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