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 "nir.h"
31#include "util/bitscan.h"
32#include "nir_range_analysis.h"
33#include <math.h>
34
35static inline bool
36is_pos_power_of_two(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
37                    unsigned src, unsigned num_components,
38                    const uint8_t *swizzle)
39{
40   /* only constant srcs: */
41   if (!nir_src_is_const(instr->src[src].src))
42      return false;
43
44   for (unsigned i = 0; i < num_components; i++) {
45      nir_alu_type type = nir_op_infos[instr->op].input_types[src];
46      switch (nir_alu_type_get_base_type(type)) {
47      case nir_type_int: {
48         int64_t val = nir_src_comp_as_int(instr->src[src].src, swizzle[i]);
49         if (val <= 0 || !util_is_power_of_two_or_zero64(val))
50            return false;
51         break;
52      }
53      case nir_type_uint: {
54         uint64_t val = nir_src_comp_as_uint(instr->src[src].src, swizzle[i]);
55         if (val == 0 || !util_is_power_of_two_or_zero64(val))
56            return false;
57         break;
58      }
59      default:
60         return false;
61      }
62   }
63
64   return true;
65}
66
67static inline bool
68is_neg_power_of_two(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
69                    unsigned src, unsigned num_components,
70                    const uint8_t *swizzle)
71{
72   /* only constant srcs: */
73   if (!nir_src_is_const(instr->src[src].src))
74      return false;
75
76   int64_t int_min = u_intN_min(instr->src[src].src.ssa->bit_size);
77
78   for (unsigned i = 0; i < num_components; i++) {
79      nir_alu_type type = nir_op_infos[instr->op].input_types[src];
80      switch (nir_alu_type_get_base_type(type)) {
81      case nir_type_int: {
82         int64_t val = nir_src_comp_as_int(instr->src[src].src, swizzle[i]);
83         /* "int_min" is a power-of-two, but negation can cause overflow. */
84         if (val == int_min || val >= 0 || !util_is_power_of_two_or_zero64(-val))
85            return false;
86         break;
87      }
88      default:
89         return false;
90      }
91   }
92
93   return true;
94}
95
96static inline bool
97is_bitcount2(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
98             unsigned src, unsigned num_components,
99             const uint8_t *swizzle)
100{
101   /* only constant srcs: */
102   if (!nir_src_is_const(instr->src[src].src))
103      return false;
104
105   for (unsigned i = 0; i < num_components; i++) {
106      uint64_t val = nir_src_comp_as_uint(instr->src[src].src, swizzle[i]);
107      if (util_bitcount64(val) != 2)
108         return false;
109   }
110
111   return true;
112}
113
114#define MULTIPLE(test)                                                  \
115static inline bool                                                      \
116is_unsigned_multiple_of_ ## test(UNUSED struct hash_table *ht,          \
117                                 const nir_alu_instr *instr,            \
118                                 unsigned src, unsigned num_components, \
119                                 const uint8_t *swizzle)                \
120{                                                                       \
121   /* only constant srcs: */                                            \
122   if (!nir_src_is_const(instr->src[src].src))                          \
123      return false;                                                     \
124                                                                        \
125   for (unsigned i = 0; i < num_components; i++) {                      \
126      uint64_t val = nir_src_comp_as_uint(instr->src[src].src, swizzle[i]); \
127      if (val % test != 0)                                              \
128         return false;                                                  \
129   }                                                                    \
130                                                                        \
131   return true;                                                         \
132}
133
134MULTIPLE(2)
135MULTIPLE(4)
136MULTIPLE(8)
137MULTIPLE(16)
138MULTIPLE(32)
139MULTIPLE(64)
140
141static inline bool
142is_zero_to_one(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
143               unsigned src, unsigned num_components,
144               const uint8_t *swizzle)
145{
146   /* only constant srcs: */
147   if (!nir_src_is_const(instr->src[src].src))
148      return false;
149
150   for (unsigned i = 0; i < num_components; i++) {
151      nir_alu_type type = nir_op_infos[instr->op].input_types[src];
152      switch (nir_alu_type_get_base_type(type)) {
153      case nir_type_float: {
154         double val = nir_src_comp_as_float(instr->src[src].src, swizzle[i]);
155         if (isnan(val) || val < 0.0f || val > 1.0f)
156            return false;
157         break;
158      }
159      default:
160         return false;
161      }
162   }
163
164   return true;
165}
166
167/**
168 * Exclusive compare with (0, 1).
169 *
170 * This differs from \c is_zero_to_one because that function tests 0 <= src <=
171 * 1 while this function tests 0 < src < 1.
172 */
173static inline bool
174is_gt_0_and_lt_1(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
175                 unsigned src, unsigned num_components,
176                 const uint8_t *swizzle)
177{
178   /* only constant srcs: */
179   if (!nir_src_is_const(instr->src[src].src))
180      return false;
181
182   for (unsigned i = 0; i < num_components; i++) {
183      nir_alu_type type = nir_op_infos[instr->op].input_types[src];
184      switch (nir_alu_type_get_base_type(type)) {
185      case nir_type_float: {
186         double val = nir_src_comp_as_float(instr->src[src].src, swizzle[i]);
187         if (isnan(val) || val <= 0.0f || val >= 1.0f)
188            return false;
189         break;
190      }
191      default:
192         return false;
193      }
194   }
195
196   return true;
197}
198
199static inline bool
200is_not_const_zero(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
201                  unsigned src, unsigned num_components,
202                  const uint8_t *swizzle)
203{
204   if (nir_src_as_const_value(instr->src[src].src) == NULL)
205      return true;
206
207   for (unsigned i = 0; i < num_components; i++) {
208      nir_alu_type type = nir_op_infos[instr->op].input_types[src];
209      switch (nir_alu_type_get_base_type(type)) {
210      case nir_type_float:
211         if (nir_src_comp_as_float(instr->src[src].src, swizzle[i]) == 0.0)
212            return false;
213         break;
214      case nir_type_bool:
215      case nir_type_int:
216      case nir_type_uint:
217         if (nir_src_comp_as_uint(instr->src[src].src, swizzle[i]) == 0)
218            return false;
219         break;
220      default:
221         return false;
222      }
223   }
224
225   return true;
226}
227
228/** Is value unsigned less than 0xfffc07fc? */
229static inline bool
230is_ult_0xfffc07fc(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
231                  unsigned src, unsigned num_components,
232                  const uint8_t *swizzle)
233{
234   /* only constant srcs: */
235   if (!nir_src_is_const(instr->src[src].src))
236      return false;
237
238   for (unsigned i = 0; i < num_components; i++) {
239      const unsigned val =
240         nir_src_comp_as_uint(instr->src[src].src, swizzle[i]);
241
242      if (val >= 0xfffc07fcU)
243         return false;
244   }
245
246   return true;
247}
248
249/** Is the first 5 bits of value unsigned greater than or equal 2? */
250static inline bool
251is_first_5_bits_uge_2(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
252                      unsigned src, unsigned num_components,
253                      const uint8_t *swizzle)
254{
255   /* only constant srcs: */
256   if (!nir_src_is_const(instr->src[src].src))
257      return false;
258
259   for (unsigned i = 0; i < num_components; i++) {
260      const unsigned val =
261         nir_src_comp_as_uint(instr->src[src].src, swizzle[i]);
262
263      if ((val & 0x1f) < 2)
264         return false;
265   }
266
267   return true;
268}
269
270static inline bool
271is_not_const(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
272             unsigned src, UNUSED unsigned num_components,
273             UNUSED const uint8_t *swizzle)
274{
275   return !nir_src_is_const(instr->src[src].src);
276}
277
278static inline bool
279is_not_fmul(struct hash_table *ht, const nir_alu_instr *instr, unsigned src,
280            UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
281{
282   nir_alu_instr *src_alu =
283      nir_src_as_alu_instr(instr->src[src].src);
284
285   if (src_alu == NULL)
286      return true;
287
288   if (src_alu->op == nir_op_fneg)
289      return is_not_fmul(ht, src_alu, 0, 0, NULL);
290
291   return src_alu->op != nir_op_fmul && src_alu->op != nir_op_fmulz;
292}
293
294static inline bool
295is_fmul(struct hash_table *ht, const nir_alu_instr *instr, unsigned src,
296        UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
297{
298   nir_alu_instr *src_alu =
299      nir_src_as_alu_instr(instr->src[src].src);
300
301   if (src_alu == NULL)
302      return false;
303
304   if (src_alu->op == nir_op_fneg)
305      return is_fmul(ht, src_alu, 0, 0, NULL);
306
307   return src_alu->op == nir_op_fmul || src_alu->op == nir_op_fmulz;
308}
309
310static inline bool
311is_fsign(const nir_alu_instr *instr, unsigned src,
312         UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
313{
314   nir_alu_instr *src_alu =
315      nir_src_as_alu_instr(instr->src[src].src);
316
317   if (src_alu == NULL)
318      return false;
319
320   if (src_alu->op == nir_op_fneg)
321      src_alu = nir_src_as_alu_instr(src_alu->src[0].src);
322
323   return src_alu != NULL && src_alu->op == nir_op_fsign;
324}
325
326static inline bool
327is_not_const_and_not_fsign(struct hash_table *ht, const nir_alu_instr *instr,
328                           unsigned src, unsigned num_components,
329                           const uint8_t *swizzle)
330{
331   return is_not_const(ht, instr, src, num_components, swizzle) &&
332          !is_fsign(instr, src, num_components, swizzle);
333}
334
335static inline bool
336is_used_once(const nir_alu_instr *instr)
337{
338   bool zero_if_use = list_is_empty(&instr->dest.dest.ssa.if_uses);
339   bool zero_use = list_is_empty(&instr->dest.dest.ssa.uses);
340
341   if (zero_if_use && zero_use)
342      return false;
343
344   if (!zero_if_use && list_is_singular(&instr->dest.dest.ssa.uses))
345     return false;
346
347   if (!zero_use && list_is_singular(&instr->dest.dest.ssa.if_uses))
348     return false;
349
350   if (!list_is_singular(&instr->dest.dest.ssa.if_uses) &&
351       !list_is_singular(&instr->dest.dest.ssa.uses))
352      return false;
353
354   return true;
355}
356
357static inline bool
358is_used_by_if(const nir_alu_instr *instr)
359{
360   return !list_is_empty(&instr->dest.dest.ssa.if_uses);
361}
362
363static inline bool
364is_not_used_by_if(const nir_alu_instr *instr)
365{
366   return list_is_empty(&instr->dest.dest.ssa.if_uses);
367}
368
369static inline bool
370is_used_by_non_fsat(const nir_alu_instr *instr)
371{
372   nir_foreach_use(src, &instr->dest.dest.ssa) {
373      const nir_instr *const user_instr = src->parent_instr;
374
375      if (user_instr->type != nir_instr_type_alu)
376         return true;
377
378      const nir_alu_instr *const user_alu = nir_instr_as_alu(user_instr);
379
380      assert(instr != user_alu);
381      if (user_alu->op != nir_op_fsat)
382         return true;
383   }
384
385   return false;
386}
387
388static inline bool
389is_only_used_as_float(const nir_alu_instr *instr)
390{
391   nir_foreach_use(src, &instr->dest.dest.ssa) {
392      const nir_instr *const user_instr = src->parent_instr;
393      if (user_instr->type != nir_instr_type_alu)
394         return false;
395
396      const nir_alu_instr *const user_alu = nir_instr_as_alu(user_instr);
397      assert(instr != user_alu);
398
399      unsigned index = (nir_alu_src*)container_of(src, nir_alu_src, src) - user_alu->src;
400      nir_alu_type type = nir_op_infos[user_alu->op].input_types[index];
401      if (nir_alu_type_get_base_type(type) != nir_type_float)
402         return false;
403   }
404
405   return true;
406}
407
408static inline bool
409only_lower_8_bits_used(const nir_alu_instr *instr)
410{
411   return (nir_ssa_def_bits_used(&instr->dest.dest.ssa) & ~0xffull) == 0;
412}
413
414static inline bool
415only_lower_16_bits_used(const nir_alu_instr *instr)
416{
417   return (nir_ssa_def_bits_used(&instr->dest.dest.ssa) & ~0xffffull) == 0;
418}
419
420/**
421 * Returns true if a NIR ALU src represents a constant integer
422 * of either 32 or 64 bits, and the higher word (bit-size / 2)
423 * of all its components is zero.
424 */
425static inline bool
426is_upper_half_zero(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
427                   unsigned src, unsigned num_components,
428                   const uint8_t *swizzle)
429{
430   if (nir_src_as_const_value(instr->src[src].src) == NULL)
431      return false;
432
433   for (unsigned i = 0; i < num_components; i++) {
434      unsigned half_bit_size = nir_src_bit_size(instr->src[src].src) / 2;
435      uint32_t high_bits = ((1 << half_bit_size) - 1) << half_bit_size;
436      if ((nir_src_comp_as_uint(instr->src[src].src,
437                                swizzle[i]) & high_bits) != 0) {
438         return false;
439      }
440   }
441
442   return true;
443}
444
445/**
446 * Returns true if a NIR ALU src represents a constant integer
447 * of either 32 or 64 bits, and the lower word (bit-size / 2)
448 * of all its components is zero.
449 */
450static inline bool
451is_lower_half_zero(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
452                   unsigned src, unsigned num_components,
453                   const uint8_t *swizzle)
454{
455   if (nir_src_as_const_value(instr->src[src].src) == NULL)
456      return false;
457
458   for (unsigned i = 0; i < num_components; i++) {
459      uint32_t low_bits =
460         (1 << (nir_src_bit_size(instr->src[src].src) / 2)) - 1;
461      if ((nir_src_comp_as_int(instr->src[src].src, swizzle[i]) & low_bits) != 0)
462         return false;
463   }
464
465   return true;
466}
467
468static inline bool
469no_signed_wrap(const nir_alu_instr *instr)
470{
471   return instr->no_signed_wrap;
472}
473
474static inline bool
475no_unsigned_wrap(const nir_alu_instr *instr)
476{
477   return instr->no_unsigned_wrap;
478}
479
480static inline bool
481is_integral(struct hash_table *ht, const nir_alu_instr *instr, unsigned src,
482            UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
483{
484   const struct ssa_result_range r = nir_analyze_range(ht, instr, src);
485
486   return r.is_integral;
487}
488
489/**
490 * Is the value finite?
491 */
492static inline bool
493is_finite(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
494          unsigned src, UNUSED unsigned num_components,
495          UNUSED const uint8_t *swizzle)
496{
497   const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
498
499   return v.is_finite;
500}
501
502static inline bool
503is_finite_not_zero(UNUSED struct hash_table *ht, const nir_alu_instr *instr,
504                   unsigned src, UNUSED unsigned num_components,
505                   UNUSED const uint8_t *swizzle)
506{
507   const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
508
509   return v.is_finite &&
510          (v.range == lt_zero || v.range == gt_zero || v.range == ne_zero);
511}
512
513
514#define RELATION(r)                                                     \
515static inline bool                                                      \
516is_ ## r (struct hash_table *ht, const nir_alu_instr *instr,            \
517          unsigned src, UNUSED unsigned num_components,                 \
518          UNUSED const uint8_t *swizzle)                                \
519{                                                                       \
520   const struct ssa_result_range v = nir_analyze_range(ht, instr, src);  \
521   return v.range == r;                                                 \
522}                                                                       \
523                                                                        \
524static inline bool                                                      \
525is_a_number_ ## r (struct hash_table *ht, const nir_alu_instr *instr,   \
526                   unsigned src, UNUSED unsigned num_components,        \
527                   UNUSED const uint8_t *swizzle)                       \
528{                                                                       \
529   const struct ssa_result_range v = nir_analyze_range(ht, instr, src); \
530   return v.is_a_number && v.range == r;                                \
531}
532
533RELATION(lt_zero)
534RELATION(le_zero)
535RELATION(gt_zero)
536RELATION(ge_zero)
537RELATION(ne_zero)
538
539static inline bool
540is_not_negative(struct hash_table *ht, const nir_alu_instr *instr, unsigned src,
541                UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
542{
543   const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
544   return v.range == ge_zero || v.range == gt_zero || v.range == eq_zero;
545}
546
547static inline bool
548is_a_number_not_negative(struct hash_table *ht, const nir_alu_instr *instr,
549                         unsigned src, UNUSED unsigned num_components,
550                         UNUSED const uint8_t *swizzle)
551{
552   const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
553   return v.is_a_number &&
554          (v.range == ge_zero || v.range == gt_zero || v.range == eq_zero);
555}
556
557
558static inline bool
559is_not_positive(struct hash_table *ht, const nir_alu_instr *instr, unsigned src,
560                UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
561{
562   const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
563   return v.range == le_zero || v.range == lt_zero || v.range == eq_zero;
564}
565
566static inline bool
567is_a_number_not_positive(struct hash_table *ht, const nir_alu_instr *instr,
568                         unsigned src, UNUSED unsigned num_components,
569                         UNUSED const uint8_t *swizzle)
570{
571   const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
572   return v.is_a_number &&
573          (v.range == le_zero || v.range == lt_zero || v.range == eq_zero);
574}
575
576static inline bool
577is_not_zero(struct hash_table *ht, const nir_alu_instr *instr, unsigned src,
578            UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
579{
580   const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
581   return v.range == lt_zero || v.range == gt_zero || v.range == ne_zero;
582}
583
584static inline bool
585is_a_number_not_zero(struct hash_table *ht, const nir_alu_instr *instr,
586                     unsigned src, UNUSED unsigned num_components,
587                     UNUSED const uint8_t *swizzle)
588{
589   const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
590   return v.is_a_number &&
591          (v.range == lt_zero || v.range == gt_zero || v.range == ne_zero);
592}
593
594static inline bool
595is_a_number(struct hash_table *ht, const nir_alu_instr *instr, unsigned src,
596            UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
597{
598   const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
599   return v.is_a_number;
600}
601
602#endif /* _NIR_SEARCH_ */
603