• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2016 Red Hat
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  *
23  * Authors:
24  *    Rob Clark <robclark@freedesktop.org>
25  */
26 
27 #ifndef _NIR_SEARCH_HELPERS_
28 #define _NIR_SEARCH_HELPERS_
29 
30 #include <math.h>
31 #include "util/bitscan.h"
32 #include "util/u_math.h"
33 #include "nir.h"
34 #include "nir_range_analysis.h"
35 
36 static inline bool
is_pos_power_of_two(UNUSED struct hash_table * ht,const nir_alu_instr * instr,unsigned src,unsigned num_components,const uint8_t * swizzle)37 is_pos_power_of_two(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
38                     unsigned src, unsigned num_components,
39                     const uint8_t *swizzle)
40 {
41    /* only constant srcs: */
42    if (!nir_src_is_const(instr->src[src].src))
43       return false;
44 
45    for (unsigned i = 0; i < num_components; i++) {
46       nir_alu_type type = nir_op_infos[instr->op].input_types[src];
47       switch (nir_alu_type_get_base_type(type)) {
48       case nir_type_int: {
49          int64_t val = nir_src_comp_as_int(instr->src[src].src, swizzle[i]);
50          if (val <= 0 || !util_is_power_of_two_or_zero64(val))
51             return false;
52          break;
53       }
54       case nir_type_uint: {
55          uint64_t val = nir_src_comp_as_uint(instr->src[src].src, swizzle[i]);
56          if (val == 0 || !util_is_power_of_two_or_zero64(val))
57             return false;
58          break;
59       }
60       default:
61          return false;
62       }
63    }
64 
65    return true;
66 }
67 
68 static inline bool
is_neg_power_of_two(UNUSED struct hash_table * ht,const nir_alu_instr * instr,unsigned src,unsigned num_components,const uint8_t * swizzle)69 is_neg_power_of_two(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
70                     unsigned src, unsigned num_components,
71                     const uint8_t *swizzle)
72 {
73    /* only constant srcs: */
74    if (!nir_src_is_const(instr->src[src].src))
75       return false;
76 
77    int64_t int_min = u_intN_min(instr->src[src].src.ssa->bit_size);
78 
79    for (unsigned i = 0; i < num_components; i++) {
80       nir_alu_type type = nir_op_infos[instr->op].input_types[src];
81       switch (nir_alu_type_get_base_type(type)) {
82       case nir_type_int: {
83          int64_t val = nir_src_comp_as_int(instr->src[src].src, swizzle[i]);
84          /* "int_min" is a power-of-two, but negation can cause overflow. */
85          if (val == int_min || val >= 0 || !util_is_power_of_two_or_zero64(-val))
86             return false;
87          break;
88       }
89       default:
90          return false;
91       }
92    }
93 
94    return true;
95 }
96 
97 static inline bool
is_bitcount2(UNUSED struct hash_table * ht,const nir_alu_instr * instr,unsigned src,unsigned num_components,const uint8_t * swizzle)98 is_bitcount2(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
99              unsigned src, unsigned num_components,
100              const uint8_t *swizzle)
101 {
102    /* only constant srcs: */
103    if (!nir_src_is_const(instr->src[src].src))
104       return false;
105 
106    for (unsigned i = 0; i < num_components; i++) {
107       uint64_t val = nir_src_comp_as_uint(instr->src[src].src, swizzle[i]);
108       if (util_bitcount64(val) != 2)
109          return false;
110    }
111 
112    return true;
113 }
114 
115 static inline bool
is_nan(UNUSED struct hash_table * ht,const nir_alu_instr * instr,unsigned src,unsigned num_components,const uint8_t * swizzle)116 is_nan(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
117        unsigned src, unsigned num_components, const uint8_t *swizzle)
118 {
119    /* only constant srcs: */
120    if (!nir_src_is_const(instr->src[src].src))
121       return false;
122 
123    for (unsigned i = 0; i < num_components; i++) {
124       if (!isnan(nir_src_comp_as_float(instr->src[src].src, swizzle[i])))
125          return false;
126    }
127 
128    return true;
129 }
130 
131 static inline bool
is_negative_zero(UNUSED struct hash_table * ht,const nir_alu_instr * instr,unsigned src,unsigned num_components,const uint8_t * swizzle)132 is_negative_zero(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
133        unsigned src, unsigned num_components, const uint8_t *swizzle)
134 {
135    /* only constant srcs: */
136    if (!nir_src_is_const(instr->src[src].src))
137       return false;
138 
139    for (unsigned i = 0; i < num_components; i++) {
140       union di tmp;
141       tmp.d = nir_src_comp_as_float(instr->src[src].src, swizzle[i]);
142       if (tmp.ui != 0x8000000000000000ull)
143          return false;
144    }
145 
146    return true;
147 }
148 
149 static inline bool
is_any_comp_nan(UNUSED struct hash_table * ht,const nir_alu_instr * instr,unsigned src,unsigned num_components,const uint8_t * swizzle)150 is_any_comp_nan(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
151                 unsigned src, unsigned num_components, const uint8_t *swizzle)
152 {
153    /* only constant srcs: */
154    if (!nir_src_is_const(instr->src[src].src))
155       return false;
156 
157    for (unsigned i = 0; i < num_components; i++) {
158       if (isnan(nir_src_comp_as_float(instr->src[src].src, swizzle[i])))
159          return true;
160    }
161 
162    return false;
163 }
164 
165 #define MULTIPLE(test)                                                         \
166    static inline bool                                                          \
167       is_unsigned_multiple_of_##test(UNUSED struct hash_table *ht,             \
168                                      const nir_alu_instr *instr,               \
169                                      unsigned src, unsigned num_components,    \
170                                      const uint8_t *swizzle)                   \
171    {                                                                           \
172       /* only constant srcs: */                                                \
173       if (!nir_src_is_const(instr->src[src].src))                              \
174          return false;                                                         \
175                                                                                \
176       for (unsigned i = 0; i < num_components; i++) {                          \
177          uint64_t val = nir_src_comp_as_uint(instr->src[src].src, swizzle[i]); \
178          if (val % test != 0)                                                  \
179             return false;                                                      \
180       }                                                                        \
181                                                                                \
182       return true;                                                             \
183    }
184 
185 MULTIPLE(2)
186 MULTIPLE(4)
187 MULTIPLE(8)
188 MULTIPLE(16)
189 MULTIPLE(32)
190 MULTIPLE(64)
191 
192 static inline bool
is_zero_to_one(UNUSED struct hash_table * ht,const nir_alu_instr * instr,unsigned src,unsigned num_components,const uint8_t * swizzle)193 is_zero_to_one(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
194                unsigned src, unsigned num_components,
195                const uint8_t *swizzle)
196 {
197    /* only constant srcs: */
198    if (!nir_src_is_const(instr->src[src].src))
199       return false;
200 
201    for (unsigned i = 0; i < num_components; i++) {
202       nir_alu_type type = nir_op_infos[instr->op].input_types[src];
203       switch (nir_alu_type_get_base_type(type)) {
204       case nir_type_float: {
205          double val = nir_src_comp_as_float(instr->src[src].src, swizzle[i]);
206          if (isnan(val) || val < 0.0f || val > 1.0f)
207             return false;
208          break;
209       }
210       default:
211          return false;
212       }
213    }
214 
215    return true;
216 }
217 
218 /**
219  * Exclusive compare with (0, 1).
220  *
221  * This differs from \c is_zero_to_one because that function tests 0 <= src <=
222  * 1 while this function tests 0 < src < 1.
223  */
224 static inline bool
is_gt_0_and_lt_1(UNUSED struct hash_table * ht,const nir_alu_instr * instr,unsigned src,unsigned num_components,const uint8_t * swizzle)225 is_gt_0_and_lt_1(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
226                  unsigned src, unsigned num_components,
227                  const uint8_t *swizzle)
228 {
229    /* only constant srcs: */
230    if (!nir_src_is_const(instr->src[src].src))
231       return false;
232 
233    for (unsigned i = 0; i < num_components; i++) {
234       nir_alu_type type = nir_op_infos[instr->op].input_types[src];
235       switch (nir_alu_type_get_base_type(type)) {
236       case nir_type_float: {
237          double val = nir_src_comp_as_float(instr->src[src].src, swizzle[i]);
238          if (isnan(val) || val <= 0.0f || val >= 1.0f)
239             return false;
240          break;
241       }
242       default:
243          return false;
244       }
245    }
246 
247    return true;
248 }
249 
250 /**
251  * x & 1 != 0
252  */
253 static inline bool
is_odd(UNUSED struct hash_table * ht,const nir_alu_instr * instr,unsigned src,unsigned num_components,const uint8_t * swizzle)254 is_odd(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
255        unsigned src, unsigned num_components,
256        const uint8_t *swizzle)
257 {
258    /* only constant srcs: */
259    if (!nir_src_is_const(instr->src[src].src))
260       return false;
261 
262    for (unsigned i = 0; i < num_components; i++) {
263       nir_alu_type type = nir_op_infos[instr->op].input_types[src];
264       switch (nir_alu_type_get_base_type(type)) {
265       case nir_type_int:
266       case nir_type_uint: {
267          if ((nir_src_comp_as_uint(instr->src[src].src, swizzle[i]) & 1) == 0)
268             return false;
269          break;
270       }
271       default:
272          return false;
273       }
274    }
275 
276    return true;
277 }
278 
279 static inline bool
is_not_const_zero(UNUSED struct hash_table * ht,const nir_alu_instr * instr,unsigned src,unsigned num_components,const uint8_t * swizzle)280 is_not_const_zero(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
281                   unsigned src, unsigned num_components,
282                   const uint8_t *swizzle)
283 {
284    if (nir_src_as_const_value(instr->src[src].src) == NULL)
285       return true;
286 
287    for (unsigned i = 0; i < num_components; i++) {
288       nir_alu_type type = nir_op_infos[instr->op].input_types[src];
289       switch (nir_alu_type_get_base_type(type)) {
290       case nir_type_float:
291          if (nir_src_comp_as_float(instr->src[src].src, swizzle[i]) == 0.0)
292             return false;
293          break;
294       case nir_type_bool:
295       case nir_type_int:
296       case nir_type_uint:
297          if (nir_src_comp_as_uint(instr->src[src].src, swizzle[i]) == 0)
298             return false;
299          break;
300       default:
301          return false;
302       }
303    }
304 
305    return true;
306 }
307 
308 /** Is value unsigned less than the limit? */
309 static inline bool
is_ult(const nir_alu_instr * instr,unsigned src,unsigned num_components,const uint8_t * swizzle,uint64_t limit)310 is_ult(const nir_alu_instr *instr, unsigned src, unsigned num_components, const uint8_t *swizzle,
311        uint64_t limit)
312 {
313    /* only constant srcs: */
314    if (!nir_src_is_const(instr->src[src].src))
315       return false;
316 
317    for (unsigned i = 0; i < num_components; i++) {
318       const uint64_t val =
319          nir_src_comp_as_uint(instr->src[src].src, swizzle[i]);
320 
321       if (val >= limit)
322          return false;
323    }
324 
325    return true;
326 }
327 
328 /** Is value unsigned less than 32? */
329 static inline bool
is_ult_32(UNUSED struct hash_table * ht,const nir_alu_instr * instr,unsigned src,unsigned num_components,const uint8_t * swizzle)330 is_ult_32(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
331           unsigned src, unsigned num_components,
332           const uint8_t *swizzle)
333 {
334    return is_ult(instr, src, num_components, swizzle, 32);
335 }
336 
337 /** Is value unsigned less than 0xfffc07fc? */
338 static inline bool
is_ult_0xfffc07fc(UNUSED struct hash_table * ht,const nir_alu_instr * instr,unsigned src,unsigned num_components,const uint8_t * swizzle)339 is_ult_0xfffc07fc(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
340                   unsigned src, unsigned num_components,
341                   const uint8_t *swizzle)
342 {
343    return is_ult(instr, src, num_components, swizzle, 0xfffc07fcU);
344 }
345 
346 /** Is the first 5 bits of value unsigned greater than or equal 2? */
347 static inline bool
is_first_5_bits_uge_2(UNUSED struct hash_table * ht,const nir_alu_instr * instr,unsigned src,unsigned num_components,const uint8_t * swizzle)348 is_first_5_bits_uge_2(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
349                       unsigned src, unsigned num_components,
350                       const uint8_t *swizzle)
351 {
352    /* only constant srcs: */
353    if (!nir_src_is_const(instr->src[src].src))
354       return false;
355 
356    for (unsigned i = 0; i < num_components; i++) {
357       const unsigned val =
358          nir_src_comp_as_uint(instr->src[src].src, swizzle[i]);
359 
360       if ((val & 0x1f) < 2)
361          return false;
362    }
363 
364    return true;
365 }
366 
367 /**
368  * Is this a constant that could be either int16_t or uint16_t after applying
369  * a scale factor?
370  */
371 static inline bool
is_16_bits_with_scale(const nir_alu_instr * instr,unsigned src,unsigned num_components,const uint8_t * swizzle,int scale)372 is_16_bits_with_scale(const nir_alu_instr *instr,
373                       unsigned src, unsigned num_components,
374                       const uint8_t *swizzle, int scale)
375 {
376    /* only constant srcs: */
377    if (!nir_src_is_const(instr->src[src].src))
378       return false;
379 
380    /* All elements must be representable as int16_t or uint16_t. */
381    bool must_be_signed = false;
382    bool must_be_unsigned = false;
383 
384    for (unsigned i = 0; i < num_components; i++) {
385       const int64_t val =
386          scale * nir_src_comp_as_int(instr->src[src].src, swizzle[i]);
387 
388       if (val > 0xffff || val < -0x8000)
389          return false;
390 
391       if (val < 0) {
392          if (must_be_unsigned)
393             return false;
394 
395          must_be_signed = true;
396       }
397 
398       if (val > 0x7fff) {
399          if (must_be_signed)
400             return false;
401 
402          must_be_unsigned = true;
403       }
404    }
405 
406    return true;
407 }
408 
409 /** Is this a constant that could be either int16_t or uint16_t? */
410 static inline bool
is_16_bits(UNUSED struct hash_table * ht,const nir_alu_instr * instr,unsigned src,unsigned num_components,const uint8_t * swizzle)411 is_16_bits(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
412            unsigned src, unsigned num_components,
413            const uint8_t *swizzle)
414 {
415    return is_16_bits_with_scale(instr, src, num_components, swizzle, 1);
416 }
417 
418 /** Like is_16_bits, but could 2 times the constant fit in 16 bits? */
419 static inline bool
is_2x_16_bits(UNUSED struct hash_table * ht,const nir_alu_instr * instr,unsigned src,unsigned num_components,const uint8_t * swizzle)420 is_2x_16_bits(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
421               unsigned src, unsigned num_components,
422               const uint8_t *swizzle)
423 {
424    return is_16_bits_with_scale(instr, src, num_components, swizzle, 2);
425 }
426 
427 /** Like is_16_bits, but could -2 times the constant fit in 16 bits? */
428 static inline bool
is_neg2x_16_bits(UNUSED struct hash_table * ht,const nir_alu_instr * instr,unsigned src,unsigned num_components,const uint8_t * swizzle)429 is_neg2x_16_bits(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
430                  unsigned src, unsigned num_components,
431                  const uint8_t *swizzle)
432 {
433    return is_16_bits_with_scale(instr, src, num_components, swizzle, -2);
434 }
435 
436 static inline bool
is_not_const(UNUSED struct hash_table * ht,const nir_alu_instr * instr,unsigned src,UNUSED unsigned num_components,UNUSED const uint8_t * swizzle)437 is_not_const(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
438              unsigned src, UNUSED unsigned num_components,
439              UNUSED const uint8_t *swizzle)
440 {
441    return !nir_src_is_const(instr->src[src].src);
442 }
443 
444 static inline bool
is_not_fmul(struct hash_table * ht,const nir_alu_instr * instr,unsigned src,UNUSED unsigned num_components,UNUSED const uint8_t * swizzle)445 is_not_fmul(struct hash_table *ht, const nir_alu_instr *instr, unsigned src,
446             UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
447 {
448    nir_alu_instr *src_alu =
449       nir_src_as_alu_instr(instr->src[src].src);
450 
451    if (src_alu == NULL)
452       return true;
453 
454    if (src_alu->op == nir_op_fneg)
455       return is_not_fmul(ht, src_alu, 0, 0, NULL);
456 
457    return src_alu->op != nir_op_fmul && src_alu->op != nir_op_fmulz;
458 }
459 
460 static inline bool
is_fmul(struct hash_table * ht,const nir_alu_instr * instr,unsigned src,UNUSED unsigned num_components,UNUSED const uint8_t * swizzle)461 is_fmul(struct hash_table *ht, const nir_alu_instr *instr, unsigned src,
462         UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
463 {
464    nir_alu_instr *src_alu =
465       nir_src_as_alu_instr(instr->src[src].src);
466 
467    if (src_alu == NULL)
468       return false;
469 
470    if (src_alu->op == nir_op_fneg)
471       return is_fmul(ht, src_alu, 0, 0, NULL);
472 
473    return src_alu->op == nir_op_fmul || src_alu->op == nir_op_fmulz;
474 }
475 
476 static inline bool
is_fsign(const nir_alu_instr * instr,unsigned src,UNUSED unsigned num_components,UNUSED const uint8_t * swizzle)477 is_fsign(const nir_alu_instr *instr, unsigned src,
478          UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
479 {
480    nir_alu_instr *src_alu =
481       nir_src_as_alu_instr(instr->src[src].src);
482 
483    if (src_alu == NULL)
484       return false;
485 
486    if (src_alu->op == nir_op_fneg)
487       src_alu = nir_src_as_alu_instr(src_alu->src[0].src);
488 
489    return src_alu != NULL && src_alu->op == nir_op_fsign;
490 }
491 
492 static inline bool
is_not_const_and_not_fsign(struct hash_table * ht,const nir_alu_instr * instr,unsigned src,unsigned num_components,const uint8_t * swizzle)493 is_not_const_and_not_fsign(struct hash_table *ht, const nir_alu_instr *instr,
494                            unsigned src, unsigned num_components,
495                            const uint8_t *swizzle)
496 {
497    return is_not_const(ht, instr, src, num_components, swizzle) &&
498           !is_fsign(instr, src, num_components, swizzle);
499 }
500 
501 static inline bool
is_used_once(const nir_alu_instr * instr)502 is_used_once(const nir_alu_instr *instr)
503 {
504    return list_is_singular(&instr->def.uses);
505 }
506 
507 static inline bool
is_used_by_if(const nir_alu_instr * instr)508 is_used_by_if(const nir_alu_instr *instr)
509 {
510    return nir_def_used_by_if(&instr->def);
511 }
512 
513 static inline bool
is_not_used_by_if(const nir_alu_instr * instr)514 is_not_used_by_if(const nir_alu_instr *instr)
515 {
516    return !is_used_by_if(instr);
517 }
518 
519 static inline bool
is_only_used_by_if(const nir_alu_instr * instr)520 is_only_used_by_if(const nir_alu_instr *instr)
521 {
522    return nir_def_only_used_by_if(&instr->def);
523 }
524 
525 static inline bool
is_used_by_non_fsat(const nir_alu_instr * instr)526 is_used_by_non_fsat(const nir_alu_instr *instr)
527 {
528    nir_foreach_use(src, &instr->def) {
529       const nir_instr *const user_instr = nir_src_parent_instr(src);
530 
531       if (user_instr->type != nir_instr_type_alu)
532          return true;
533 
534       const nir_alu_instr *const user_alu = nir_instr_as_alu(user_instr);
535 
536       assert(instr != user_alu);
537       if (user_alu->op != nir_op_fsat)
538          return true;
539    }
540 
541    return false;
542 }
543 
544 static inline bool
is_only_used_as_float_impl(const nir_alu_instr * instr,unsigned depth)545 is_only_used_as_float_impl(const nir_alu_instr *instr, unsigned depth)
546 {
547    nir_foreach_use(src, &instr->def) {
548       const nir_instr *const user_instr = nir_src_parent_instr(src);
549 
550       if (user_instr->type != nir_instr_type_alu) {
551          if (user_instr->type == nir_instr_type_intrinsic) {
552             switch (nir_instr_as_intrinsic(user_instr)->intrinsic) {
553             case nir_intrinsic_ddx:
554             case nir_intrinsic_ddy:
555             case nir_intrinsic_ddx_fine:
556             case nir_intrinsic_ddy_fine:
557             case nir_intrinsic_ddx_coarse:
558             case nir_intrinsic_ddy_coarse:
559                continue;
560             default:
561                break;
562             }
563          }
564          return false;
565       }
566 
567       const nir_alu_instr *const user_alu = nir_instr_as_alu(user_instr);
568       assert(instr != user_alu);
569 
570       unsigned index = (nir_alu_src *)container_of(src, nir_alu_src, src) - user_alu->src;
571 
572       /* bcsel acts like a move: if the bcsel is only used by float
573        * instructions, then the original value is (transitively) only used by
574        * float too.
575        *
576        * The unbounded recursion would terminate because use chains are acyclic
577        * in SSA. However, we limit the search depth regardless to avoid stack
578        * overflows in patholgical shaders and to reduce the worst-case time.
579        */
580       if (user_alu->op == nir_op_bcsel && index != 0 && depth < 8) {
581          if (is_only_used_as_float_impl(user_alu, depth + 1))
582             continue;
583       }
584 
585       nir_alu_type type = nir_op_infos[user_alu->op].input_types[index];
586       if (nir_alu_type_get_base_type(type) != nir_type_float)
587          return false;
588    }
589 
590    return true;
591 }
592 
593 static inline bool
is_only_used_as_float(const nir_alu_instr * instr)594 is_only_used_as_float(const nir_alu_instr *instr)
595 {
596    return is_only_used_as_float_impl(instr, 0);
597 }
598 
599 static inline bool
is_only_used_by_fadd(const nir_alu_instr * instr)600 is_only_used_by_fadd(const nir_alu_instr *instr)
601 {
602    nir_foreach_use(src, &instr->def) {
603       const nir_instr *const user_instr = nir_src_parent_instr(src);
604       if (user_instr->type != nir_instr_type_alu)
605          return false;
606 
607       const nir_alu_instr *const user_alu = nir_instr_as_alu(user_instr);
608       assert(instr != user_alu);
609 
610       if (user_alu->op == nir_op_fneg || user_alu->op == nir_op_fabs) {
611          if (!is_only_used_by_fadd(user_alu))
612             return false;
613       } else if (user_alu->op != nir_op_fadd) {
614          return false;
615       }
616    }
617 
618    return true;
619 }
620 
621 static inline bool
is_only_used_by_alu_op(const nir_alu_instr * instr,nir_op op)622 is_only_used_by_alu_op(const nir_alu_instr *instr, nir_op op)
623 {
624    nir_foreach_use(src, &instr->def) {
625       const nir_instr *const user_instr = nir_src_parent_instr(src);
626       if (user_instr->type != nir_instr_type_alu)
627          return false;
628 
629       const nir_alu_instr *const user_alu = nir_instr_as_alu(user_instr);
630       assert(instr != user_alu);
631 
632       if (user_alu->op != op)
633          return false;
634    }
635 
636    return true;
637 }
638 
639 static inline bool
is_only_used_by_iadd(const nir_alu_instr * instr)640 is_only_used_by_iadd(const nir_alu_instr *instr)
641 {
642    return is_only_used_by_alu_op(instr, nir_op_iadd);
643 }
644 
645 static inline bool
is_only_used_by_iand(const nir_alu_instr * instr)646 is_only_used_by_iand(const nir_alu_instr *instr)
647 {
648    return is_only_used_by_alu_op(instr, nir_op_iand);
649 }
650 
651 static inline bool
is_only_used_by_ior(const nir_alu_instr * instr)652 is_only_used_by_ior(const nir_alu_instr *instr)
653 {
654    return is_only_used_by_alu_op(instr, nir_op_ior);
655 }
656 
657 static inline bool
only_lower_8_bits_used(const nir_alu_instr * instr)658 only_lower_8_bits_used(const nir_alu_instr *instr)
659 {
660    return (nir_def_bits_used(&instr->def) & ~0xffull) == 0;
661 }
662 
663 static inline bool
only_lower_16_bits_used(const nir_alu_instr * instr)664 only_lower_16_bits_used(const nir_alu_instr *instr)
665 {
666    return (nir_def_bits_used(&instr->def) & ~0xffffull) == 0;
667 }
668 
669 /**
670  * Returns true if a NIR ALU src represents a constant integer
671  * of either 32 or 64 bits, and the higher word (bit-size / 2)
672  * of all its components is zero.
673  */
674 static inline bool
is_upper_half_zero(UNUSED struct hash_table * ht,const nir_alu_instr * instr,unsigned src,unsigned num_components,const uint8_t * swizzle)675 is_upper_half_zero(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
676                    unsigned src, unsigned num_components,
677                    const uint8_t *swizzle)
678 {
679    if (nir_src_as_const_value(instr->src[src].src) == NULL)
680       return false;
681 
682    for (unsigned i = 0; i < num_components; i++) {
683       unsigned half_bit_size = nir_src_bit_size(instr->src[src].src) / 2;
684       uint64_t high_bits = u_bit_consecutive64(half_bit_size, half_bit_size);
685       if ((nir_src_comp_as_uint(instr->src[src].src,
686                                 swizzle[i]) &
687            high_bits) != 0) {
688          return false;
689       }
690    }
691 
692    return true;
693 }
694 
695 /**
696  * Returns true if a NIR ALU src represents a constant integer
697  * of either 32 or 64 bits, and the lower word (bit-size / 2)
698  * of all its components is zero.
699  */
700 static inline bool
is_lower_half_zero(UNUSED struct hash_table * ht,const nir_alu_instr * instr,unsigned src,unsigned num_components,const uint8_t * swizzle)701 is_lower_half_zero(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
702                    unsigned src, unsigned num_components,
703                    const uint8_t *swizzle)
704 {
705    if (nir_src_as_const_value(instr->src[src].src) == NULL)
706       return false;
707 
708    for (unsigned i = 0; i < num_components; i++) {
709       uint64_t low_bits = u_bit_consecutive64(0, nir_src_bit_size(instr->src[src].src) / 2);
710       if ((nir_src_comp_as_uint(instr->src[src].src, swizzle[i]) & low_bits) != 0)
711          return false;
712    }
713 
714    return true;
715 }
716 
717 static inline bool
is_upper_half_negative_one(UNUSED struct hash_table * ht,const nir_alu_instr * instr,unsigned src,unsigned num_components,const uint8_t * swizzle)718 is_upper_half_negative_one(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
719                            unsigned src, unsigned num_components,
720                            const uint8_t *swizzle)
721 {
722    if (nir_src_as_const_value(instr->src[src].src) == NULL)
723       return false;
724 
725    for (unsigned i = 0; i < num_components; i++) {
726       unsigned half_bit_size = nir_src_bit_size(instr->src[src].src) / 2;
727       uint64_t high_bits = u_bit_consecutive64(half_bit_size, half_bit_size);
728       if ((nir_src_comp_as_uint(instr->src[src].src,
729                                 swizzle[i]) &
730            high_bits) != high_bits) {
731          return false;
732       }
733    }
734 
735    return true;
736 }
737 
738 static inline bool
is_lower_half_negative_one(UNUSED struct hash_table * ht,const nir_alu_instr * instr,unsigned src,unsigned num_components,const uint8_t * swizzle)739 is_lower_half_negative_one(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
740                            unsigned src, unsigned num_components,
741                            const uint8_t *swizzle)
742 {
743    if (nir_src_as_const_value(instr->src[src].src) == NULL)
744       return false;
745 
746    for (unsigned i = 0; i < num_components; i++) {
747       uint64_t low_bits = u_bit_consecutive64(0, nir_src_bit_size(instr->src[src].src) / 2);
748       if ((nir_src_comp_as_uint(instr->src[src].src, swizzle[i]) & low_bits) != low_bits)
749          return false;
750    }
751 
752    return true;
753 }
754 
755 /**
756  * Returns whether an operand is a constant bit-mask, meaning that it
757  * only has consecutive 1 bits starting from the LSB.
758  * Numbers whose MSB is 1 are excluded because they are not useful
759  * for the optimizations where this function is used.
760  */
761 static inline bool
is_const_bitmask(UNUSED struct hash_table * ht,const nir_alu_instr * instr,unsigned src,unsigned num_components,const uint8_t * swizzle)762 is_const_bitmask(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
763                  unsigned src, unsigned num_components,
764                  const uint8_t *swizzle)
765 {
766    if (nir_src_as_const_value(instr->src[src].src) == NULL)
767       return false;
768 
769    for (unsigned i = 0; i < num_components; i++) {
770       const unsigned bit_size = instr->src[src].src.ssa->bit_size;
771       const uint64_t c = nir_src_comp_as_uint(instr->src[src].src, swizzle[i]);
772       const unsigned num_bits = util_bitcount64(c);
773       if (c != BITFIELD64_MASK(num_bits) || num_bits == bit_size)
774          return false;
775    }
776 
777    return true;
778 }
779 
780 /**
781  * Returns whether the 5 LSBs of an operand are non-zero.
782  */
783 static inline bool
is_5lsb_not_zero(UNUSED struct hash_table * ht,const nir_alu_instr * instr,unsigned src,unsigned num_components,const uint8_t * swizzle)784 is_5lsb_not_zero(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
785                  unsigned src, unsigned num_components,
786                  const uint8_t *swizzle)
787 {
788    if (nir_src_as_const_value(instr->src[src].src) == NULL)
789       return false;
790 
791    for (unsigned i = 0; i < num_components; i++) {
792       const uint64_t c = nir_src_comp_as_uint(instr->src[src].src, swizzle[i]);
793       if ((c & 0x1f) == 0)
794          return false;
795    }
796 
797    return true;
798 }
799 
800 static inline bool
no_signed_wrap(const nir_alu_instr * instr)801 no_signed_wrap(const nir_alu_instr *instr)
802 {
803    return instr->no_signed_wrap;
804 }
805 
806 static inline bool
no_unsigned_wrap(const nir_alu_instr * instr)807 no_unsigned_wrap(const nir_alu_instr *instr)
808 {
809    return instr->no_unsigned_wrap;
810 }
811 
812 static inline bool
is_integral(struct hash_table * ht,const nir_alu_instr * instr,unsigned src,UNUSED unsigned num_components,UNUSED const uint8_t * swizzle)813 is_integral(struct hash_table *ht, const nir_alu_instr *instr, unsigned src,
814             UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
815 {
816    const struct ssa_result_range r = nir_analyze_range(ht, instr, src);
817 
818    return r.is_integral;
819 }
820 
821 /**
822  * Is the value finite?
823  */
824 static inline bool
is_finite(UNUSED struct hash_table * ht,const nir_alu_instr * instr,unsigned src,UNUSED unsigned num_components,UNUSED const uint8_t * swizzle)825 is_finite(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
826           unsigned src, UNUSED unsigned num_components,
827           UNUSED const uint8_t *swizzle)
828 {
829    const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
830 
831    return v.is_finite;
832 }
833 
834 static inline bool
is_finite_not_zero(UNUSED struct hash_table * ht,const nir_alu_instr * instr,unsigned src,UNUSED unsigned num_components,UNUSED const uint8_t * swizzle)835 is_finite_not_zero(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
836                    unsigned src, UNUSED unsigned num_components,
837                    UNUSED const uint8_t *swizzle)
838 {
839    const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
840 
841    return v.is_finite &&
842           (v.range == lt_zero || v.range == gt_zero || v.range == ne_zero);
843 }
844 
845 #define RELATION(r)                                                        \
846    static inline bool                                                      \
847       is_##r(struct hash_table *ht, const nir_alu_instr *instr,            \
848              unsigned src, UNUSED unsigned num_components,                 \
849              UNUSED const uint8_t *swizzle)                                \
850    {                                                                       \
851       const struct ssa_result_range v = nir_analyze_range(ht, instr, src); \
852       return v.range == r;                                                 \
853    }                                                                       \
854                                                                            \
855    static inline bool                                                      \
856       is_a_number_##r(struct hash_table *ht, const nir_alu_instr *instr,   \
857                       unsigned src, UNUSED unsigned num_components,        \
858                       UNUSED const uint8_t *swizzle)                       \
859    {                                                                       \
860       const struct ssa_result_range v = nir_analyze_range(ht, instr, src); \
861       return v.is_a_number && v.range == r;                                \
862    }
863 
864 RELATION(lt_zero)
RELATION(le_zero)865 RELATION(le_zero)
866 RELATION(gt_zero)
867 RELATION(ge_zero)
868 RELATION(ne_zero)
869 
870 static inline bool
871 is_not_negative(struct hash_table *ht, const nir_alu_instr *instr, unsigned src,
872                 UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
873 {
874    const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
875    return v.range == ge_zero || v.range == gt_zero || v.range == eq_zero;
876 }
877 
878 static inline bool
is_a_number_not_negative(struct hash_table * ht,const nir_alu_instr * instr,unsigned src,UNUSED unsigned num_components,UNUSED const uint8_t * swizzle)879 is_a_number_not_negative(struct hash_table *ht, const nir_alu_instr *instr,
880                          unsigned src, UNUSED unsigned num_components,
881                          UNUSED const uint8_t *swizzle)
882 {
883    const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
884    return v.is_a_number &&
885           (v.range == ge_zero || v.range == gt_zero || v.range == eq_zero);
886 }
887 
888 static inline bool
is_not_positive(struct hash_table * ht,const nir_alu_instr * instr,unsigned src,UNUSED unsigned num_components,UNUSED const uint8_t * swizzle)889 is_not_positive(struct hash_table *ht, const nir_alu_instr *instr, unsigned src,
890                 UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
891 {
892    const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
893    return v.range == le_zero || v.range == lt_zero || v.range == eq_zero;
894 }
895 
896 static inline bool
is_a_number_not_positive(struct hash_table * ht,const nir_alu_instr * instr,unsigned src,UNUSED unsigned num_components,UNUSED const uint8_t * swizzle)897 is_a_number_not_positive(struct hash_table *ht, const nir_alu_instr *instr,
898                          unsigned src, UNUSED unsigned num_components,
899                          UNUSED const uint8_t *swizzle)
900 {
901    const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
902    return v.is_a_number &&
903           (v.range == le_zero || v.range == lt_zero || v.range == eq_zero);
904 }
905 
906 static inline bool
is_not_zero(struct hash_table * ht,const nir_alu_instr * instr,unsigned src,UNUSED unsigned num_components,UNUSED const uint8_t * swizzle)907 is_not_zero(struct hash_table *ht, const nir_alu_instr *instr, unsigned src,
908             UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
909 {
910    const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
911    return v.range == lt_zero || v.range == gt_zero || v.range == ne_zero;
912 }
913 
914 static inline bool
is_a_number_not_zero(struct hash_table * ht,const nir_alu_instr * instr,unsigned src,UNUSED unsigned num_components,UNUSED const uint8_t * swizzle)915 is_a_number_not_zero(struct hash_table *ht, const nir_alu_instr *instr,
916                      unsigned src, UNUSED unsigned num_components,
917                      UNUSED const uint8_t *swizzle)
918 {
919    const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
920    return v.is_a_number &&
921           (v.range == lt_zero || v.range == gt_zero || v.range == ne_zero);
922 }
923 
924 static inline bool
is_a_number(struct hash_table * ht,const nir_alu_instr * instr,unsigned src,UNUSED unsigned num_components,UNUSED const uint8_t * swizzle)925 is_a_number(struct hash_table *ht, const nir_alu_instr *instr, unsigned src,
926             UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
927 {
928    const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
929    return v.is_a_number;
930 }
931 
932 #endif /* _NIR_SEARCH_ */
933