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 <[email protected]>
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(const nir_alu_instr * instr)545 is_only_used_as_float(const nir_alu_instr *instr)
546 {
547 nir_foreach_use(src, &instr->def) {
548 const nir_instr *const user_instr = nir_src_parent_instr(src);
549 if (user_instr->type != nir_instr_type_alu)
550 return false;
551
552 const nir_alu_instr *const user_alu = nir_instr_as_alu(user_instr);
553 assert(instr != user_alu);
554
555 unsigned index = (nir_alu_src *)container_of(src, nir_alu_src, src) - user_alu->src;
556 nir_alu_type type = nir_op_infos[user_alu->op].input_types[index];
557 if (nir_alu_type_get_base_type(type) != nir_type_float)
558 return false;
559 }
560
561 return true;
562 }
563
564 static inline bool
is_only_used_by_fadd(const nir_alu_instr * instr)565 is_only_used_by_fadd(const nir_alu_instr *instr)
566 {
567 nir_foreach_use(src, &instr->def) {
568 const nir_instr *const user_instr = nir_src_parent_instr(src);
569 if (user_instr->type != nir_instr_type_alu)
570 return false;
571
572 const nir_alu_instr *const user_alu = nir_instr_as_alu(user_instr);
573 assert(instr != user_alu);
574
575 if (user_alu->op == nir_op_fneg || user_alu->op == nir_op_fabs) {
576 if (!is_only_used_by_fadd(user_alu))
577 return false;
578 } else if (user_alu->op != nir_op_fadd) {
579 return false;
580 }
581 }
582
583 return true;
584 }
585
586 static inline bool
is_only_used_by_iadd(const nir_alu_instr * instr)587 is_only_used_by_iadd(const nir_alu_instr *instr)
588 {
589 nir_foreach_use(src, &instr->def) {
590 const nir_instr *const user_instr = nir_src_parent_instr(src);
591 if (user_instr->type != nir_instr_type_alu)
592 return false;
593
594 const nir_alu_instr *const user_alu = nir_instr_as_alu(user_instr);
595 assert(instr != user_alu);
596
597 if (user_alu->op != nir_op_iadd)
598 return false;
599 }
600
601 return true;
602 }
603
604 static inline bool
only_lower_8_bits_used(const nir_alu_instr * instr)605 only_lower_8_bits_used(const nir_alu_instr *instr)
606 {
607 return (nir_def_bits_used(&instr->def) & ~0xffull) == 0;
608 }
609
610 static inline bool
only_lower_16_bits_used(const nir_alu_instr * instr)611 only_lower_16_bits_used(const nir_alu_instr *instr)
612 {
613 return (nir_def_bits_used(&instr->def) & ~0xffffull) == 0;
614 }
615
616 /**
617 * Returns true if a NIR ALU src represents a constant integer
618 * of either 32 or 64 bits, and the higher word (bit-size / 2)
619 * of all its components is zero.
620 */
621 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)622 is_upper_half_zero(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
623 unsigned src, unsigned num_components,
624 const uint8_t *swizzle)
625 {
626 if (nir_src_as_const_value(instr->src[src].src) == NULL)
627 return false;
628
629 for (unsigned i = 0; i < num_components; i++) {
630 unsigned half_bit_size = nir_src_bit_size(instr->src[src].src) / 2;
631 uint64_t high_bits = u_bit_consecutive64(half_bit_size, half_bit_size);
632 if ((nir_src_comp_as_uint(instr->src[src].src,
633 swizzle[i]) &
634 high_bits) != 0) {
635 return false;
636 }
637 }
638
639 return true;
640 }
641
642 /**
643 * Returns true if a NIR ALU src represents a constant integer
644 * of either 32 or 64 bits, and the lower word (bit-size / 2)
645 * of all its components is zero.
646 */
647 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)648 is_lower_half_zero(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
649 unsigned src, unsigned num_components,
650 const uint8_t *swizzle)
651 {
652 if (nir_src_as_const_value(instr->src[src].src) == NULL)
653 return false;
654
655 for (unsigned i = 0; i < num_components; i++) {
656 uint64_t low_bits = u_bit_consecutive64(0, nir_src_bit_size(instr->src[src].src) / 2);
657 if ((nir_src_comp_as_uint(instr->src[src].src, swizzle[i]) & low_bits) != 0)
658 return false;
659 }
660
661 return true;
662 }
663
664 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)665 is_upper_half_negative_one(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
666 unsigned src, unsigned num_components,
667 const uint8_t *swizzle)
668 {
669 if (nir_src_as_const_value(instr->src[src].src) == NULL)
670 return false;
671
672 for (unsigned i = 0; i < num_components; i++) {
673 unsigned half_bit_size = nir_src_bit_size(instr->src[src].src) / 2;
674 uint64_t high_bits = u_bit_consecutive64(half_bit_size, half_bit_size);
675 if ((nir_src_comp_as_uint(instr->src[src].src,
676 swizzle[i]) &
677 high_bits) != high_bits) {
678 return false;
679 }
680 }
681
682 return true;
683 }
684
685 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)686 is_lower_half_negative_one(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
687 unsigned src, unsigned num_components,
688 const uint8_t *swizzle)
689 {
690 if (nir_src_as_const_value(instr->src[src].src) == NULL)
691 return false;
692
693 for (unsigned i = 0; i < num_components; i++) {
694 uint64_t low_bits = u_bit_consecutive64(0, nir_src_bit_size(instr->src[src].src) / 2);
695 if ((nir_src_comp_as_uint(instr->src[src].src, swizzle[i]) & low_bits) != low_bits)
696 return false;
697 }
698
699 return true;
700 }
701
702 static inline bool
no_signed_wrap(const nir_alu_instr * instr)703 no_signed_wrap(const nir_alu_instr *instr)
704 {
705 return instr->no_signed_wrap;
706 }
707
708 static inline bool
no_unsigned_wrap(const nir_alu_instr * instr)709 no_unsigned_wrap(const nir_alu_instr *instr)
710 {
711 return instr->no_unsigned_wrap;
712 }
713
714 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)715 is_integral(struct hash_table *ht, const nir_alu_instr *instr, unsigned src,
716 UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
717 {
718 const struct ssa_result_range r = nir_analyze_range(ht, instr, src);
719
720 return r.is_integral;
721 }
722
723 /**
724 * Is the value finite?
725 */
726 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)727 is_finite(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
728 unsigned src, UNUSED unsigned num_components,
729 UNUSED const uint8_t *swizzle)
730 {
731 const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
732
733 return v.is_finite;
734 }
735
736 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)737 is_finite_not_zero(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
738 unsigned src, UNUSED unsigned num_components,
739 UNUSED const uint8_t *swizzle)
740 {
741 const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
742
743 return v.is_finite &&
744 (v.range == lt_zero || v.range == gt_zero || v.range == ne_zero);
745 }
746
747 #define RELATION(r) \
748 static inline bool \
749 is_##r(struct hash_table *ht, const nir_alu_instr *instr, \
750 unsigned src, UNUSED unsigned num_components, \
751 UNUSED const uint8_t *swizzle) \
752 { \
753 const struct ssa_result_range v = nir_analyze_range(ht, instr, src); \
754 return v.range == r; \
755 } \
756 \
757 static inline bool \
758 is_a_number_##r(struct hash_table *ht, const nir_alu_instr *instr, \
759 unsigned src, UNUSED unsigned num_components, \
760 UNUSED const uint8_t *swizzle) \
761 { \
762 const struct ssa_result_range v = nir_analyze_range(ht, instr, src); \
763 return v.is_a_number && v.range == r; \
764 }
765
766 RELATION(lt_zero)
RELATION(le_zero)767 RELATION(le_zero)
768 RELATION(gt_zero)
769 RELATION(ge_zero)
770 RELATION(ne_zero)
771
772 static inline bool
773 is_not_negative(struct hash_table *ht, const nir_alu_instr *instr, unsigned src,
774 UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
775 {
776 const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
777 return v.range == ge_zero || v.range == gt_zero || v.range == eq_zero;
778 }
779
780 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)781 is_a_number_not_negative(struct hash_table *ht, const nir_alu_instr *instr,
782 unsigned src, UNUSED unsigned num_components,
783 UNUSED const uint8_t *swizzle)
784 {
785 const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
786 return v.is_a_number &&
787 (v.range == ge_zero || v.range == gt_zero || v.range == eq_zero);
788 }
789
790 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)791 is_not_positive(struct hash_table *ht, const nir_alu_instr *instr, unsigned src,
792 UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
793 {
794 const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
795 return v.range == le_zero || v.range == lt_zero || v.range == eq_zero;
796 }
797
798 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)799 is_a_number_not_positive(struct hash_table *ht, const nir_alu_instr *instr,
800 unsigned src, UNUSED unsigned num_components,
801 UNUSED const uint8_t *swizzle)
802 {
803 const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
804 return v.is_a_number &&
805 (v.range == le_zero || v.range == lt_zero || v.range == eq_zero);
806 }
807
808 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)809 is_not_zero(struct hash_table *ht, const nir_alu_instr *instr, unsigned src,
810 UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
811 {
812 const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
813 return v.range == lt_zero || v.range == gt_zero || v.range == ne_zero;
814 }
815
816 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)817 is_a_number_not_zero(struct hash_table *ht, const nir_alu_instr *instr,
818 unsigned src, UNUSED unsigned num_components,
819 UNUSED const uint8_t *swizzle)
820 {
821 const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
822 return v.is_a_number &&
823 (v.range == lt_zero || v.range == gt_zero || v.range == ne_zero);
824 }
825
826 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)827 is_a_number(struct hash_table *ht, const nir_alu_instr *instr, unsigned src,
828 UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
829 {
830 const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
831 return v.is_a_number;
832 }
833
834 #endif /* _NIR_SEARCH_ */
835