1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2016 Red Hat
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21bf215546Sopenharmony_ci * IN THE SOFTWARE.
22bf215546Sopenharmony_ci *
23bf215546Sopenharmony_ci * Authors:
24bf215546Sopenharmony_ci *    Rob Clark <robclark@freedesktop.org>
25bf215546Sopenharmony_ci */
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci#ifndef _NIR_SEARCH_HELPERS_
28bf215546Sopenharmony_ci#define _NIR_SEARCH_HELPERS_
29bf215546Sopenharmony_ci
30bf215546Sopenharmony_ci#include "nir.h"
31bf215546Sopenharmony_ci#include "util/bitscan.h"
32bf215546Sopenharmony_ci#include "nir_range_analysis.h"
33bf215546Sopenharmony_ci#include <math.h>
34bf215546Sopenharmony_ci
35bf215546Sopenharmony_cistatic inline bool
36bf215546Sopenharmony_ciis_pos_power_of_two(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
37bf215546Sopenharmony_ci                    unsigned src, unsigned num_components,
38bf215546Sopenharmony_ci                    const uint8_t *swizzle)
39bf215546Sopenharmony_ci{
40bf215546Sopenharmony_ci   /* only constant srcs: */
41bf215546Sopenharmony_ci   if (!nir_src_is_const(instr->src[src].src))
42bf215546Sopenharmony_ci      return false;
43bf215546Sopenharmony_ci
44bf215546Sopenharmony_ci   for (unsigned i = 0; i < num_components; i++) {
45bf215546Sopenharmony_ci      nir_alu_type type = nir_op_infos[instr->op].input_types[src];
46bf215546Sopenharmony_ci      switch (nir_alu_type_get_base_type(type)) {
47bf215546Sopenharmony_ci      case nir_type_int: {
48bf215546Sopenharmony_ci         int64_t val = nir_src_comp_as_int(instr->src[src].src, swizzle[i]);
49bf215546Sopenharmony_ci         if (val <= 0 || !util_is_power_of_two_or_zero64(val))
50bf215546Sopenharmony_ci            return false;
51bf215546Sopenharmony_ci         break;
52bf215546Sopenharmony_ci      }
53bf215546Sopenharmony_ci      case nir_type_uint: {
54bf215546Sopenharmony_ci         uint64_t val = nir_src_comp_as_uint(instr->src[src].src, swizzle[i]);
55bf215546Sopenharmony_ci         if (val == 0 || !util_is_power_of_two_or_zero64(val))
56bf215546Sopenharmony_ci            return false;
57bf215546Sopenharmony_ci         break;
58bf215546Sopenharmony_ci      }
59bf215546Sopenharmony_ci      default:
60bf215546Sopenharmony_ci         return false;
61bf215546Sopenharmony_ci      }
62bf215546Sopenharmony_ci   }
63bf215546Sopenharmony_ci
64bf215546Sopenharmony_ci   return true;
65bf215546Sopenharmony_ci}
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_cistatic inline bool
68bf215546Sopenharmony_ciis_neg_power_of_two(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
69bf215546Sopenharmony_ci                    unsigned src, unsigned num_components,
70bf215546Sopenharmony_ci                    const uint8_t *swizzle)
71bf215546Sopenharmony_ci{
72bf215546Sopenharmony_ci   /* only constant srcs: */
73bf215546Sopenharmony_ci   if (!nir_src_is_const(instr->src[src].src))
74bf215546Sopenharmony_ci      return false;
75bf215546Sopenharmony_ci
76bf215546Sopenharmony_ci   int64_t int_min = u_intN_min(instr->src[src].src.ssa->bit_size);
77bf215546Sopenharmony_ci
78bf215546Sopenharmony_ci   for (unsigned i = 0; i < num_components; i++) {
79bf215546Sopenharmony_ci      nir_alu_type type = nir_op_infos[instr->op].input_types[src];
80bf215546Sopenharmony_ci      switch (nir_alu_type_get_base_type(type)) {
81bf215546Sopenharmony_ci      case nir_type_int: {
82bf215546Sopenharmony_ci         int64_t val = nir_src_comp_as_int(instr->src[src].src, swizzle[i]);
83bf215546Sopenharmony_ci         /* "int_min" is a power-of-two, but negation can cause overflow. */
84bf215546Sopenharmony_ci         if (val == int_min || val >= 0 || !util_is_power_of_two_or_zero64(-val))
85bf215546Sopenharmony_ci            return false;
86bf215546Sopenharmony_ci         break;
87bf215546Sopenharmony_ci      }
88bf215546Sopenharmony_ci      default:
89bf215546Sopenharmony_ci         return false;
90bf215546Sopenharmony_ci      }
91bf215546Sopenharmony_ci   }
92bf215546Sopenharmony_ci
93bf215546Sopenharmony_ci   return true;
94bf215546Sopenharmony_ci}
95bf215546Sopenharmony_ci
96bf215546Sopenharmony_cistatic inline bool
97bf215546Sopenharmony_ciis_bitcount2(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
98bf215546Sopenharmony_ci             unsigned src, unsigned num_components,
99bf215546Sopenharmony_ci             const uint8_t *swizzle)
100bf215546Sopenharmony_ci{
101bf215546Sopenharmony_ci   /* only constant srcs: */
102bf215546Sopenharmony_ci   if (!nir_src_is_const(instr->src[src].src))
103bf215546Sopenharmony_ci      return false;
104bf215546Sopenharmony_ci
105bf215546Sopenharmony_ci   for (unsigned i = 0; i < num_components; i++) {
106bf215546Sopenharmony_ci      uint64_t val = nir_src_comp_as_uint(instr->src[src].src, swizzle[i]);
107bf215546Sopenharmony_ci      if (util_bitcount64(val) != 2)
108bf215546Sopenharmony_ci         return false;
109bf215546Sopenharmony_ci   }
110bf215546Sopenharmony_ci
111bf215546Sopenharmony_ci   return true;
112bf215546Sopenharmony_ci}
113bf215546Sopenharmony_ci
114bf215546Sopenharmony_ci#define MULTIPLE(test)                                                  \
115bf215546Sopenharmony_cistatic inline bool                                                      \
116bf215546Sopenharmony_ciis_unsigned_multiple_of_ ## test(UNUSED struct hash_table *ht,          \
117bf215546Sopenharmony_ci                                 const nir_alu_instr *instr,            \
118bf215546Sopenharmony_ci                                 unsigned src, unsigned num_components, \
119bf215546Sopenharmony_ci                                 const uint8_t *swizzle)                \
120bf215546Sopenharmony_ci{                                                                       \
121bf215546Sopenharmony_ci   /* only constant srcs: */                                            \
122bf215546Sopenharmony_ci   if (!nir_src_is_const(instr->src[src].src))                          \
123bf215546Sopenharmony_ci      return false;                                                     \
124bf215546Sopenharmony_ci                                                                        \
125bf215546Sopenharmony_ci   for (unsigned i = 0; i < num_components; i++) {                      \
126bf215546Sopenharmony_ci      uint64_t val = nir_src_comp_as_uint(instr->src[src].src, swizzle[i]); \
127bf215546Sopenharmony_ci      if (val % test != 0)                                              \
128bf215546Sopenharmony_ci         return false;                                                  \
129bf215546Sopenharmony_ci   }                                                                    \
130bf215546Sopenharmony_ci                                                                        \
131bf215546Sopenharmony_ci   return true;                                                         \
132bf215546Sopenharmony_ci}
133bf215546Sopenharmony_ci
134bf215546Sopenharmony_ciMULTIPLE(2)
135bf215546Sopenharmony_ciMULTIPLE(4)
136bf215546Sopenharmony_ciMULTIPLE(8)
137bf215546Sopenharmony_ciMULTIPLE(16)
138bf215546Sopenharmony_ciMULTIPLE(32)
139bf215546Sopenharmony_ciMULTIPLE(64)
140bf215546Sopenharmony_ci
141bf215546Sopenharmony_cistatic inline bool
142bf215546Sopenharmony_ciis_zero_to_one(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
143bf215546Sopenharmony_ci               unsigned src, unsigned num_components,
144bf215546Sopenharmony_ci               const uint8_t *swizzle)
145bf215546Sopenharmony_ci{
146bf215546Sopenharmony_ci   /* only constant srcs: */
147bf215546Sopenharmony_ci   if (!nir_src_is_const(instr->src[src].src))
148bf215546Sopenharmony_ci      return false;
149bf215546Sopenharmony_ci
150bf215546Sopenharmony_ci   for (unsigned i = 0; i < num_components; i++) {
151bf215546Sopenharmony_ci      nir_alu_type type = nir_op_infos[instr->op].input_types[src];
152bf215546Sopenharmony_ci      switch (nir_alu_type_get_base_type(type)) {
153bf215546Sopenharmony_ci      case nir_type_float: {
154bf215546Sopenharmony_ci         double val = nir_src_comp_as_float(instr->src[src].src, swizzle[i]);
155bf215546Sopenharmony_ci         if (isnan(val) || val < 0.0f || val > 1.0f)
156bf215546Sopenharmony_ci            return false;
157bf215546Sopenharmony_ci         break;
158bf215546Sopenharmony_ci      }
159bf215546Sopenharmony_ci      default:
160bf215546Sopenharmony_ci         return false;
161bf215546Sopenharmony_ci      }
162bf215546Sopenharmony_ci   }
163bf215546Sopenharmony_ci
164bf215546Sopenharmony_ci   return true;
165bf215546Sopenharmony_ci}
166bf215546Sopenharmony_ci
167bf215546Sopenharmony_ci/**
168bf215546Sopenharmony_ci * Exclusive compare with (0, 1).
169bf215546Sopenharmony_ci *
170bf215546Sopenharmony_ci * This differs from \c is_zero_to_one because that function tests 0 <= src <=
171bf215546Sopenharmony_ci * 1 while this function tests 0 < src < 1.
172bf215546Sopenharmony_ci */
173bf215546Sopenharmony_cistatic inline bool
174bf215546Sopenharmony_ciis_gt_0_and_lt_1(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
175bf215546Sopenharmony_ci                 unsigned src, unsigned num_components,
176bf215546Sopenharmony_ci                 const uint8_t *swizzle)
177bf215546Sopenharmony_ci{
178bf215546Sopenharmony_ci   /* only constant srcs: */
179bf215546Sopenharmony_ci   if (!nir_src_is_const(instr->src[src].src))
180bf215546Sopenharmony_ci      return false;
181bf215546Sopenharmony_ci
182bf215546Sopenharmony_ci   for (unsigned i = 0; i < num_components; i++) {
183bf215546Sopenharmony_ci      nir_alu_type type = nir_op_infos[instr->op].input_types[src];
184bf215546Sopenharmony_ci      switch (nir_alu_type_get_base_type(type)) {
185bf215546Sopenharmony_ci      case nir_type_float: {
186bf215546Sopenharmony_ci         double val = nir_src_comp_as_float(instr->src[src].src, swizzle[i]);
187bf215546Sopenharmony_ci         if (isnan(val) || val <= 0.0f || val >= 1.0f)
188bf215546Sopenharmony_ci            return false;
189bf215546Sopenharmony_ci         break;
190bf215546Sopenharmony_ci      }
191bf215546Sopenharmony_ci      default:
192bf215546Sopenharmony_ci         return false;
193bf215546Sopenharmony_ci      }
194bf215546Sopenharmony_ci   }
195bf215546Sopenharmony_ci
196bf215546Sopenharmony_ci   return true;
197bf215546Sopenharmony_ci}
198bf215546Sopenharmony_ci
199bf215546Sopenharmony_cistatic inline bool
200bf215546Sopenharmony_ciis_not_const_zero(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
201bf215546Sopenharmony_ci                  unsigned src, unsigned num_components,
202bf215546Sopenharmony_ci                  const uint8_t *swizzle)
203bf215546Sopenharmony_ci{
204bf215546Sopenharmony_ci   if (nir_src_as_const_value(instr->src[src].src) == NULL)
205bf215546Sopenharmony_ci      return true;
206bf215546Sopenharmony_ci
207bf215546Sopenharmony_ci   for (unsigned i = 0; i < num_components; i++) {
208bf215546Sopenharmony_ci      nir_alu_type type = nir_op_infos[instr->op].input_types[src];
209bf215546Sopenharmony_ci      switch (nir_alu_type_get_base_type(type)) {
210bf215546Sopenharmony_ci      case nir_type_float:
211bf215546Sopenharmony_ci         if (nir_src_comp_as_float(instr->src[src].src, swizzle[i]) == 0.0)
212bf215546Sopenharmony_ci            return false;
213bf215546Sopenharmony_ci         break;
214bf215546Sopenharmony_ci      case nir_type_bool:
215bf215546Sopenharmony_ci      case nir_type_int:
216bf215546Sopenharmony_ci      case nir_type_uint:
217bf215546Sopenharmony_ci         if (nir_src_comp_as_uint(instr->src[src].src, swizzle[i]) == 0)
218bf215546Sopenharmony_ci            return false;
219bf215546Sopenharmony_ci         break;
220bf215546Sopenharmony_ci      default:
221bf215546Sopenharmony_ci         return false;
222bf215546Sopenharmony_ci      }
223bf215546Sopenharmony_ci   }
224bf215546Sopenharmony_ci
225bf215546Sopenharmony_ci   return true;
226bf215546Sopenharmony_ci}
227bf215546Sopenharmony_ci
228bf215546Sopenharmony_ci/** Is value unsigned less than 0xfffc07fc? */
229bf215546Sopenharmony_cistatic inline bool
230bf215546Sopenharmony_ciis_ult_0xfffc07fc(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
231bf215546Sopenharmony_ci                  unsigned src, unsigned num_components,
232bf215546Sopenharmony_ci                  const uint8_t *swizzle)
233bf215546Sopenharmony_ci{
234bf215546Sopenharmony_ci   /* only constant srcs: */
235bf215546Sopenharmony_ci   if (!nir_src_is_const(instr->src[src].src))
236bf215546Sopenharmony_ci      return false;
237bf215546Sopenharmony_ci
238bf215546Sopenharmony_ci   for (unsigned i = 0; i < num_components; i++) {
239bf215546Sopenharmony_ci      const unsigned val =
240bf215546Sopenharmony_ci         nir_src_comp_as_uint(instr->src[src].src, swizzle[i]);
241bf215546Sopenharmony_ci
242bf215546Sopenharmony_ci      if (val >= 0xfffc07fcU)
243bf215546Sopenharmony_ci         return false;
244bf215546Sopenharmony_ci   }
245bf215546Sopenharmony_ci
246bf215546Sopenharmony_ci   return true;
247bf215546Sopenharmony_ci}
248bf215546Sopenharmony_ci
249bf215546Sopenharmony_ci/** Is the first 5 bits of value unsigned greater than or equal 2? */
250bf215546Sopenharmony_cistatic inline bool
251bf215546Sopenharmony_ciis_first_5_bits_uge_2(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
252bf215546Sopenharmony_ci                      unsigned src, unsigned num_components,
253bf215546Sopenharmony_ci                      const uint8_t *swizzle)
254bf215546Sopenharmony_ci{
255bf215546Sopenharmony_ci   /* only constant srcs: */
256bf215546Sopenharmony_ci   if (!nir_src_is_const(instr->src[src].src))
257bf215546Sopenharmony_ci      return false;
258bf215546Sopenharmony_ci
259bf215546Sopenharmony_ci   for (unsigned i = 0; i < num_components; i++) {
260bf215546Sopenharmony_ci      const unsigned val =
261bf215546Sopenharmony_ci         nir_src_comp_as_uint(instr->src[src].src, swizzle[i]);
262bf215546Sopenharmony_ci
263bf215546Sopenharmony_ci      if ((val & 0x1f) < 2)
264bf215546Sopenharmony_ci         return false;
265bf215546Sopenharmony_ci   }
266bf215546Sopenharmony_ci
267bf215546Sopenharmony_ci   return true;
268bf215546Sopenharmony_ci}
269bf215546Sopenharmony_ci
270bf215546Sopenharmony_cistatic inline bool
271bf215546Sopenharmony_ciis_not_const(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
272bf215546Sopenharmony_ci             unsigned src, UNUSED unsigned num_components,
273bf215546Sopenharmony_ci             UNUSED const uint8_t *swizzle)
274bf215546Sopenharmony_ci{
275bf215546Sopenharmony_ci   return !nir_src_is_const(instr->src[src].src);
276bf215546Sopenharmony_ci}
277bf215546Sopenharmony_ci
278bf215546Sopenharmony_cistatic inline bool
279bf215546Sopenharmony_ciis_not_fmul(struct hash_table *ht, const nir_alu_instr *instr, unsigned src,
280bf215546Sopenharmony_ci            UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
281bf215546Sopenharmony_ci{
282bf215546Sopenharmony_ci   nir_alu_instr *src_alu =
283bf215546Sopenharmony_ci      nir_src_as_alu_instr(instr->src[src].src);
284bf215546Sopenharmony_ci
285bf215546Sopenharmony_ci   if (src_alu == NULL)
286bf215546Sopenharmony_ci      return true;
287bf215546Sopenharmony_ci
288bf215546Sopenharmony_ci   if (src_alu->op == nir_op_fneg)
289bf215546Sopenharmony_ci      return is_not_fmul(ht, src_alu, 0, 0, NULL);
290bf215546Sopenharmony_ci
291bf215546Sopenharmony_ci   return src_alu->op != nir_op_fmul && src_alu->op != nir_op_fmulz;
292bf215546Sopenharmony_ci}
293bf215546Sopenharmony_ci
294bf215546Sopenharmony_cistatic inline bool
295bf215546Sopenharmony_ciis_fmul(struct hash_table *ht, const nir_alu_instr *instr, unsigned src,
296bf215546Sopenharmony_ci        UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
297bf215546Sopenharmony_ci{
298bf215546Sopenharmony_ci   nir_alu_instr *src_alu =
299bf215546Sopenharmony_ci      nir_src_as_alu_instr(instr->src[src].src);
300bf215546Sopenharmony_ci
301bf215546Sopenharmony_ci   if (src_alu == NULL)
302bf215546Sopenharmony_ci      return false;
303bf215546Sopenharmony_ci
304bf215546Sopenharmony_ci   if (src_alu->op == nir_op_fneg)
305bf215546Sopenharmony_ci      return is_fmul(ht, src_alu, 0, 0, NULL);
306bf215546Sopenharmony_ci
307bf215546Sopenharmony_ci   return src_alu->op == nir_op_fmul || src_alu->op == nir_op_fmulz;
308bf215546Sopenharmony_ci}
309bf215546Sopenharmony_ci
310bf215546Sopenharmony_cistatic inline bool
311bf215546Sopenharmony_ciis_fsign(const nir_alu_instr *instr, unsigned src,
312bf215546Sopenharmony_ci         UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
313bf215546Sopenharmony_ci{
314bf215546Sopenharmony_ci   nir_alu_instr *src_alu =
315bf215546Sopenharmony_ci      nir_src_as_alu_instr(instr->src[src].src);
316bf215546Sopenharmony_ci
317bf215546Sopenharmony_ci   if (src_alu == NULL)
318bf215546Sopenharmony_ci      return false;
319bf215546Sopenharmony_ci
320bf215546Sopenharmony_ci   if (src_alu->op == nir_op_fneg)
321bf215546Sopenharmony_ci      src_alu = nir_src_as_alu_instr(src_alu->src[0].src);
322bf215546Sopenharmony_ci
323bf215546Sopenharmony_ci   return src_alu != NULL && src_alu->op == nir_op_fsign;
324bf215546Sopenharmony_ci}
325bf215546Sopenharmony_ci
326bf215546Sopenharmony_cistatic inline bool
327bf215546Sopenharmony_ciis_not_const_and_not_fsign(struct hash_table *ht, const nir_alu_instr *instr,
328bf215546Sopenharmony_ci                           unsigned src, unsigned num_components,
329bf215546Sopenharmony_ci                           const uint8_t *swizzle)
330bf215546Sopenharmony_ci{
331bf215546Sopenharmony_ci   return is_not_const(ht, instr, src, num_components, swizzle) &&
332bf215546Sopenharmony_ci          !is_fsign(instr, src, num_components, swizzle);
333bf215546Sopenharmony_ci}
334bf215546Sopenharmony_ci
335bf215546Sopenharmony_cistatic inline bool
336bf215546Sopenharmony_ciis_used_once(const nir_alu_instr *instr)
337bf215546Sopenharmony_ci{
338bf215546Sopenharmony_ci   bool zero_if_use = list_is_empty(&instr->dest.dest.ssa.if_uses);
339bf215546Sopenharmony_ci   bool zero_use = list_is_empty(&instr->dest.dest.ssa.uses);
340bf215546Sopenharmony_ci
341bf215546Sopenharmony_ci   if (zero_if_use && zero_use)
342bf215546Sopenharmony_ci      return false;
343bf215546Sopenharmony_ci
344bf215546Sopenharmony_ci   if (!zero_if_use && list_is_singular(&instr->dest.dest.ssa.uses))
345bf215546Sopenharmony_ci     return false;
346bf215546Sopenharmony_ci
347bf215546Sopenharmony_ci   if (!zero_use && list_is_singular(&instr->dest.dest.ssa.if_uses))
348bf215546Sopenharmony_ci     return false;
349bf215546Sopenharmony_ci
350bf215546Sopenharmony_ci   if (!list_is_singular(&instr->dest.dest.ssa.if_uses) &&
351bf215546Sopenharmony_ci       !list_is_singular(&instr->dest.dest.ssa.uses))
352bf215546Sopenharmony_ci      return false;
353bf215546Sopenharmony_ci
354bf215546Sopenharmony_ci   return true;
355bf215546Sopenharmony_ci}
356bf215546Sopenharmony_ci
357bf215546Sopenharmony_cistatic inline bool
358bf215546Sopenharmony_ciis_used_by_if(const nir_alu_instr *instr)
359bf215546Sopenharmony_ci{
360bf215546Sopenharmony_ci   return !list_is_empty(&instr->dest.dest.ssa.if_uses);
361bf215546Sopenharmony_ci}
362bf215546Sopenharmony_ci
363bf215546Sopenharmony_cistatic inline bool
364bf215546Sopenharmony_ciis_not_used_by_if(const nir_alu_instr *instr)
365bf215546Sopenharmony_ci{
366bf215546Sopenharmony_ci   return list_is_empty(&instr->dest.dest.ssa.if_uses);
367bf215546Sopenharmony_ci}
368bf215546Sopenharmony_ci
369bf215546Sopenharmony_cistatic inline bool
370bf215546Sopenharmony_ciis_used_by_non_fsat(const nir_alu_instr *instr)
371bf215546Sopenharmony_ci{
372bf215546Sopenharmony_ci   nir_foreach_use(src, &instr->dest.dest.ssa) {
373bf215546Sopenharmony_ci      const nir_instr *const user_instr = src->parent_instr;
374bf215546Sopenharmony_ci
375bf215546Sopenharmony_ci      if (user_instr->type != nir_instr_type_alu)
376bf215546Sopenharmony_ci         return true;
377bf215546Sopenharmony_ci
378bf215546Sopenharmony_ci      const nir_alu_instr *const user_alu = nir_instr_as_alu(user_instr);
379bf215546Sopenharmony_ci
380bf215546Sopenharmony_ci      assert(instr != user_alu);
381bf215546Sopenharmony_ci      if (user_alu->op != nir_op_fsat)
382bf215546Sopenharmony_ci         return true;
383bf215546Sopenharmony_ci   }
384bf215546Sopenharmony_ci
385bf215546Sopenharmony_ci   return false;
386bf215546Sopenharmony_ci}
387bf215546Sopenharmony_ci
388bf215546Sopenharmony_cistatic inline bool
389bf215546Sopenharmony_ciis_only_used_as_float(const nir_alu_instr *instr)
390bf215546Sopenharmony_ci{
391bf215546Sopenharmony_ci   nir_foreach_use(src, &instr->dest.dest.ssa) {
392bf215546Sopenharmony_ci      const nir_instr *const user_instr = src->parent_instr;
393bf215546Sopenharmony_ci      if (user_instr->type != nir_instr_type_alu)
394bf215546Sopenharmony_ci         return false;
395bf215546Sopenharmony_ci
396bf215546Sopenharmony_ci      const nir_alu_instr *const user_alu = nir_instr_as_alu(user_instr);
397bf215546Sopenharmony_ci      assert(instr != user_alu);
398bf215546Sopenharmony_ci
399bf215546Sopenharmony_ci      unsigned index = (nir_alu_src*)container_of(src, nir_alu_src, src) - user_alu->src;
400bf215546Sopenharmony_ci      nir_alu_type type = nir_op_infos[user_alu->op].input_types[index];
401bf215546Sopenharmony_ci      if (nir_alu_type_get_base_type(type) != nir_type_float)
402bf215546Sopenharmony_ci         return false;
403bf215546Sopenharmony_ci   }
404bf215546Sopenharmony_ci
405bf215546Sopenharmony_ci   return true;
406bf215546Sopenharmony_ci}
407bf215546Sopenharmony_ci
408bf215546Sopenharmony_cistatic inline bool
409bf215546Sopenharmony_cionly_lower_8_bits_used(const nir_alu_instr *instr)
410bf215546Sopenharmony_ci{
411bf215546Sopenharmony_ci   return (nir_ssa_def_bits_used(&instr->dest.dest.ssa) & ~0xffull) == 0;
412bf215546Sopenharmony_ci}
413bf215546Sopenharmony_ci
414bf215546Sopenharmony_cistatic inline bool
415bf215546Sopenharmony_cionly_lower_16_bits_used(const nir_alu_instr *instr)
416bf215546Sopenharmony_ci{
417bf215546Sopenharmony_ci   return (nir_ssa_def_bits_used(&instr->dest.dest.ssa) & ~0xffffull) == 0;
418bf215546Sopenharmony_ci}
419bf215546Sopenharmony_ci
420bf215546Sopenharmony_ci/**
421bf215546Sopenharmony_ci * Returns true if a NIR ALU src represents a constant integer
422bf215546Sopenharmony_ci * of either 32 or 64 bits, and the higher word (bit-size / 2)
423bf215546Sopenharmony_ci * of all its components is zero.
424bf215546Sopenharmony_ci */
425bf215546Sopenharmony_cistatic inline bool
426bf215546Sopenharmony_ciis_upper_half_zero(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
427bf215546Sopenharmony_ci                   unsigned src, unsigned num_components,
428bf215546Sopenharmony_ci                   const uint8_t *swizzle)
429bf215546Sopenharmony_ci{
430bf215546Sopenharmony_ci   if (nir_src_as_const_value(instr->src[src].src) == NULL)
431bf215546Sopenharmony_ci      return false;
432bf215546Sopenharmony_ci
433bf215546Sopenharmony_ci   for (unsigned i = 0; i < num_components; i++) {
434bf215546Sopenharmony_ci      unsigned half_bit_size = nir_src_bit_size(instr->src[src].src) / 2;
435bf215546Sopenharmony_ci      uint32_t high_bits = ((1 << half_bit_size) - 1) << half_bit_size;
436bf215546Sopenharmony_ci      if ((nir_src_comp_as_uint(instr->src[src].src,
437bf215546Sopenharmony_ci                                swizzle[i]) & high_bits) != 0) {
438bf215546Sopenharmony_ci         return false;
439bf215546Sopenharmony_ci      }
440bf215546Sopenharmony_ci   }
441bf215546Sopenharmony_ci
442bf215546Sopenharmony_ci   return true;
443bf215546Sopenharmony_ci}
444bf215546Sopenharmony_ci
445bf215546Sopenharmony_ci/**
446bf215546Sopenharmony_ci * Returns true if a NIR ALU src represents a constant integer
447bf215546Sopenharmony_ci * of either 32 or 64 bits, and the lower word (bit-size / 2)
448bf215546Sopenharmony_ci * of all its components is zero.
449bf215546Sopenharmony_ci */
450bf215546Sopenharmony_cistatic inline bool
451bf215546Sopenharmony_ciis_lower_half_zero(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
452bf215546Sopenharmony_ci                   unsigned src, unsigned num_components,
453bf215546Sopenharmony_ci                   const uint8_t *swizzle)
454bf215546Sopenharmony_ci{
455bf215546Sopenharmony_ci   if (nir_src_as_const_value(instr->src[src].src) == NULL)
456bf215546Sopenharmony_ci      return false;
457bf215546Sopenharmony_ci
458bf215546Sopenharmony_ci   for (unsigned i = 0; i < num_components; i++) {
459bf215546Sopenharmony_ci      uint32_t low_bits =
460bf215546Sopenharmony_ci         (1 << (nir_src_bit_size(instr->src[src].src) / 2)) - 1;
461bf215546Sopenharmony_ci      if ((nir_src_comp_as_int(instr->src[src].src, swizzle[i]) & low_bits) != 0)
462bf215546Sopenharmony_ci         return false;
463bf215546Sopenharmony_ci   }
464bf215546Sopenharmony_ci
465bf215546Sopenharmony_ci   return true;
466bf215546Sopenharmony_ci}
467bf215546Sopenharmony_ci
468bf215546Sopenharmony_cistatic inline bool
469bf215546Sopenharmony_cino_signed_wrap(const nir_alu_instr *instr)
470bf215546Sopenharmony_ci{
471bf215546Sopenharmony_ci   return instr->no_signed_wrap;
472bf215546Sopenharmony_ci}
473bf215546Sopenharmony_ci
474bf215546Sopenharmony_cistatic inline bool
475bf215546Sopenharmony_cino_unsigned_wrap(const nir_alu_instr *instr)
476bf215546Sopenharmony_ci{
477bf215546Sopenharmony_ci   return instr->no_unsigned_wrap;
478bf215546Sopenharmony_ci}
479bf215546Sopenharmony_ci
480bf215546Sopenharmony_cistatic inline bool
481bf215546Sopenharmony_ciis_integral(struct hash_table *ht, const nir_alu_instr *instr, unsigned src,
482bf215546Sopenharmony_ci            UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
483bf215546Sopenharmony_ci{
484bf215546Sopenharmony_ci   const struct ssa_result_range r = nir_analyze_range(ht, instr, src);
485bf215546Sopenharmony_ci
486bf215546Sopenharmony_ci   return r.is_integral;
487bf215546Sopenharmony_ci}
488bf215546Sopenharmony_ci
489bf215546Sopenharmony_ci/**
490bf215546Sopenharmony_ci * Is the value finite?
491bf215546Sopenharmony_ci */
492bf215546Sopenharmony_cistatic inline bool
493bf215546Sopenharmony_ciis_finite(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
494bf215546Sopenharmony_ci          unsigned src, UNUSED unsigned num_components,
495bf215546Sopenharmony_ci          UNUSED const uint8_t *swizzle)
496bf215546Sopenharmony_ci{
497bf215546Sopenharmony_ci   const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
498bf215546Sopenharmony_ci
499bf215546Sopenharmony_ci   return v.is_finite;
500bf215546Sopenharmony_ci}
501bf215546Sopenharmony_ci
502bf215546Sopenharmony_cistatic inline bool
503bf215546Sopenharmony_ciis_finite_not_zero(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
504bf215546Sopenharmony_ci                   unsigned src, UNUSED unsigned num_components,
505bf215546Sopenharmony_ci                   UNUSED const uint8_t *swizzle)
506bf215546Sopenharmony_ci{
507bf215546Sopenharmony_ci   const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
508bf215546Sopenharmony_ci
509bf215546Sopenharmony_ci   return v.is_finite &&
510bf215546Sopenharmony_ci          (v.range == lt_zero || v.range == gt_zero || v.range == ne_zero);
511bf215546Sopenharmony_ci}
512bf215546Sopenharmony_ci
513bf215546Sopenharmony_ci
514bf215546Sopenharmony_ci#define RELATION(r)                                                     \
515bf215546Sopenharmony_cistatic inline bool                                                      \
516bf215546Sopenharmony_ciis_ ## r (struct hash_table *ht, const nir_alu_instr *instr,            \
517bf215546Sopenharmony_ci          unsigned src, UNUSED unsigned num_components,                 \
518bf215546Sopenharmony_ci          UNUSED const uint8_t *swizzle)                                \
519bf215546Sopenharmony_ci{                                                                       \
520bf215546Sopenharmony_ci   const struct ssa_result_range v = nir_analyze_range(ht, instr, src);  \
521bf215546Sopenharmony_ci   return v.range == r;                                                 \
522bf215546Sopenharmony_ci}                                                                       \
523bf215546Sopenharmony_ci                                                                        \
524bf215546Sopenharmony_cistatic inline bool                                                      \
525bf215546Sopenharmony_ciis_a_number_ ## r (struct hash_table *ht, const nir_alu_instr *instr,   \
526bf215546Sopenharmony_ci                   unsigned src, UNUSED unsigned num_components,        \
527bf215546Sopenharmony_ci                   UNUSED const uint8_t *swizzle)                       \
528bf215546Sopenharmony_ci{                                                                       \
529bf215546Sopenharmony_ci   const struct ssa_result_range v = nir_analyze_range(ht, instr, src); \
530bf215546Sopenharmony_ci   return v.is_a_number && v.range == r;                                \
531bf215546Sopenharmony_ci}
532bf215546Sopenharmony_ci
533bf215546Sopenharmony_ciRELATION(lt_zero)
534bf215546Sopenharmony_ciRELATION(le_zero)
535bf215546Sopenharmony_ciRELATION(gt_zero)
536bf215546Sopenharmony_ciRELATION(ge_zero)
537bf215546Sopenharmony_ciRELATION(ne_zero)
538bf215546Sopenharmony_ci
539bf215546Sopenharmony_cistatic inline bool
540bf215546Sopenharmony_ciis_not_negative(struct hash_table *ht, const nir_alu_instr *instr, unsigned src,
541bf215546Sopenharmony_ci                UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
542bf215546Sopenharmony_ci{
543bf215546Sopenharmony_ci   const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
544bf215546Sopenharmony_ci   return v.range == ge_zero || v.range == gt_zero || v.range == eq_zero;
545bf215546Sopenharmony_ci}
546bf215546Sopenharmony_ci
547bf215546Sopenharmony_cistatic inline bool
548bf215546Sopenharmony_ciis_a_number_not_negative(struct hash_table *ht, const nir_alu_instr *instr,
549bf215546Sopenharmony_ci                         unsigned src, UNUSED unsigned num_components,
550bf215546Sopenharmony_ci                         UNUSED const uint8_t *swizzle)
551bf215546Sopenharmony_ci{
552bf215546Sopenharmony_ci   const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
553bf215546Sopenharmony_ci   return v.is_a_number &&
554bf215546Sopenharmony_ci          (v.range == ge_zero || v.range == gt_zero || v.range == eq_zero);
555bf215546Sopenharmony_ci}
556bf215546Sopenharmony_ci
557bf215546Sopenharmony_ci
558bf215546Sopenharmony_cistatic inline bool
559bf215546Sopenharmony_ciis_not_positive(struct hash_table *ht, const nir_alu_instr *instr, unsigned src,
560bf215546Sopenharmony_ci                UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
561bf215546Sopenharmony_ci{
562bf215546Sopenharmony_ci   const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
563bf215546Sopenharmony_ci   return v.range == le_zero || v.range == lt_zero || v.range == eq_zero;
564bf215546Sopenharmony_ci}
565bf215546Sopenharmony_ci
566bf215546Sopenharmony_cistatic inline bool
567bf215546Sopenharmony_ciis_a_number_not_positive(struct hash_table *ht, const nir_alu_instr *instr,
568bf215546Sopenharmony_ci                         unsigned src, UNUSED unsigned num_components,
569bf215546Sopenharmony_ci                         UNUSED const uint8_t *swizzle)
570bf215546Sopenharmony_ci{
571bf215546Sopenharmony_ci   const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
572bf215546Sopenharmony_ci   return v.is_a_number &&
573bf215546Sopenharmony_ci          (v.range == le_zero || v.range == lt_zero || v.range == eq_zero);
574bf215546Sopenharmony_ci}
575bf215546Sopenharmony_ci
576bf215546Sopenharmony_cistatic inline bool
577bf215546Sopenharmony_ciis_not_zero(struct hash_table *ht, const nir_alu_instr *instr, unsigned src,
578bf215546Sopenharmony_ci            UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
579bf215546Sopenharmony_ci{
580bf215546Sopenharmony_ci   const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
581bf215546Sopenharmony_ci   return v.range == lt_zero || v.range == gt_zero || v.range == ne_zero;
582bf215546Sopenharmony_ci}
583bf215546Sopenharmony_ci
584bf215546Sopenharmony_cistatic inline bool
585bf215546Sopenharmony_ciis_a_number_not_zero(struct hash_table *ht, const nir_alu_instr *instr,
586bf215546Sopenharmony_ci                     unsigned src, UNUSED unsigned num_components,
587bf215546Sopenharmony_ci                     UNUSED const uint8_t *swizzle)
588bf215546Sopenharmony_ci{
589bf215546Sopenharmony_ci   const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
590bf215546Sopenharmony_ci   return v.is_a_number &&
591bf215546Sopenharmony_ci          (v.range == lt_zero || v.range == gt_zero || v.range == ne_zero);
592bf215546Sopenharmony_ci}
593bf215546Sopenharmony_ci
594bf215546Sopenharmony_cistatic inline bool
595bf215546Sopenharmony_ciis_a_number(struct hash_table *ht, const nir_alu_instr *instr, unsigned src,
596bf215546Sopenharmony_ci            UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
597bf215546Sopenharmony_ci{
598bf215546Sopenharmony_ci   const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
599bf215546Sopenharmony_ci   return v.is_a_number;
600bf215546Sopenharmony_ci}
601bf215546Sopenharmony_ci
602bf215546Sopenharmony_ci#endif /* _NIR_SEARCH_ */
603