4849aef052d069a54ebc86ea4819bfaebaf6b8c6
[mesa.git] / src / compiler / nir / nir_search_helpers.h
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
35 static inline bool
36 is_pos_power_of_two(UNUSED struct hash_table *ht, 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
67 static inline bool
68 is_neg_power_of_two(UNUSED struct hash_table *ht, 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 for (unsigned i = 0; i < num_components; i++) {
77 nir_alu_type type = nir_op_infos[instr->op].input_types[src];
78 switch (nir_alu_type_get_base_type(type)) {
79 case nir_type_int: {
80 int64_t val = nir_src_comp_as_int(instr->src[src].src, swizzle[i]);
81 if (val >= 0 || !util_is_power_of_two_or_zero64(-val))
82 return false;
83 break;
84 }
85 default:
86 return false;
87 }
88 }
89
90 return true;
91 }
92
93 static inline bool
94 is_zero_to_one(UNUSED struct hash_table *ht, nir_alu_instr *instr, unsigned src,
95 unsigned num_components,
96 const uint8_t *swizzle)
97 {
98 /* only constant srcs: */
99 if (!nir_src_is_const(instr->src[src].src))
100 return false;
101
102 for (unsigned i = 0; i < num_components; i++) {
103 switch (nir_op_infos[instr->op].input_types[src]) {
104 case nir_type_float: {
105 double val = nir_src_comp_as_float(instr->src[src].src, swizzle[i]);
106 if (isnan(val) || val < 0.0f || val > 1.0f)
107 return false;
108 break;
109 }
110 default:
111 return false;
112 }
113 }
114
115 return true;
116 }
117
118 /**
119 * Exclusive compare with (0, 1).
120 *
121 * This differs from \c is_zero_to_one because that function tests 0 <= src <=
122 * 1 while this function tests 0 < src < 1.
123 */
124 static inline bool
125 is_gt_0_and_lt_1(UNUSED struct hash_table *ht, nir_alu_instr *instr,
126 unsigned src, unsigned num_components,
127 const uint8_t *swizzle)
128 {
129 /* only constant srcs: */
130 if (!nir_src_is_const(instr->src[src].src))
131 return false;
132
133 for (unsigned i = 0; i < num_components; i++) {
134 switch (nir_op_infos[instr->op].input_types[src]) {
135 case nir_type_float: {
136 double val = nir_src_comp_as_float(instr->src[src].src, swizzle[i]);
137 if (isnan(val) || val <= 0.0f || val >= 1.0f)
138 return false;
139 break;
140 }
141 default:
142 return false;
143 }
144 }
145
146 return true;
147 }
148
149 static inline bool
150 is_not_const_zero(UNUSED struct hash_table *ht, nir_alu_instr *instr,
151 unsigned src, unsigned num_components,
152 const uint8_t *swizzle)
153 {
154 if (nir_src_as_const_value(instr->src[src].src) == NULL)
155 return true;
156
157 for (unsigned i = 0; i < num_components; i++) {
158 nir_alu_type type = nir_op_infos[instr->op].input_types[src];
159 switch (nir_alu_type_get_base_type(type)) {
160 case nir_type_float:
161 if (nir_src_comp_as_float(instr->src[src].src, swizzle[i]) == 0.0)
162 return false;
163 break;
164 case nir_type_bool:
165 case nir_type_int:
166 case nir_type_uint:
167 if (nir_src_comp_as_uint(instr->src[src].src, swizzle[i]) == 0)
168 return false;
169 break;
170 default:
171 return false;
172 }
173 }
174
175 return true;
176 }
177
178 static inline bool
179 is_not_const(UNUSED struct hash_table *ht, nir_alu_instr *instr, unsigned src,
180 UNUSED unsigned num_components,
181 UNUSED const uint8_t *swizzle)
182 {
183 return !nir_src_is_const(instr->src[src].src);
184 }
185
186 static inline bool
187 is_not_fmul(struct hash_table *ht, nir_alu_instr *instr, unsigned src,
188 UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
189 {
190 nir_alu_instr *src_alu =
191 nir_src_as_alu_instr(instr->src[src].src);
192
193 if (src_alu == NULL)
194 return true;
195
196 if (src_alu->op == nir_op_fneg)
197 return is_not_fmul(ht, src_alu, 0, 0, NULL);
198
199 return src_alu->op != nir_op_fmul;
200 }
201
202 static inline bool
203 is_fsign(nir_alu_instr *instr, unsigned src,
204 UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
205 {
206 nir_alu_instr *src_alu =
207 nir_src_as_alu_instr(instr->src[src].src);
208
209 if (src_alu == NULL)
210 return false;
211
212 if (src_alu->op == nir_op_fneg)
213 src_alu = nir_src_as_alu_instr(src_alu->src[0].src);
214
215 return src_alu != NULL && src_alu->op == nir_op_fsign;
216 }
217
218 static inline bool
219 is_not_const_and_not_fsign(struct hash_table *ht, nir_alu_instr *instr, unsigned src,
220 unsigned num_components, const uint8_t *swizzle)
221 {
222 return is_not_const(ht, instr, src, num_components, swizzle) &&
223 !is_fsign(instr, src, num_components, swizzle);
224 }
225
226 static inline bool
227 is_used_once(nir_alu_instr *instr)
228 {
229 bool zero_if_use = list_empty(&instr->dest.dest.ssa.if_uses);
230 bool zero_use = list_empty(&instr->dest.dest.ssa.uses);
231
232 if (zero_if_use && zero_use)
233 return false;
234
235 if (!zero_if_use && list_is_singular(&instr->dest.dest.ssa.uses))
236 return false;
237
238 if (!zero_use && list_is_singular(&instr->dest.dest.ssa.if_uses))
239 return false;
240
241 if (!list_is_singular(&instr->dest.dest.ssa.if_uses) &&
242 !list_is_singular(&instr->dest.dest.ssa.uses))
243 return false;
244
245 return true;
246 }
247
248 static inline bool
249 is_used_by_if(nir_alu_instr *instr)
250 {
251 return !list_empty(&instr->dest.dest.ssa.if_uses);
252 }
253
254 static inline bool
255 is_not_used_by_if(nir_alu_instr *instr)
256 {
257 return list_empty(&instr->dest.dest.ssa.if_uses);
258 }
259
260 static inline bool
261 is_used_by_non_fsat(nir_alu_instr *instr)
262 {
263 nir_foreach_use(src, &instr->dest.dest.ssa) {
264 const nir_instr *const user_instr = src->parent_instr;
265
266 if (user_instr->type != nir_instr_type_alu)
267 return true;
268
269 const nir_alu_instr *const user_alu = nir_instr_as_alu(user_instr);
270
271 assert(instr != user_alu);
272 if (user_alu->op != nir_op_fsat)
273 return true;
274 }
275
276 return false;
277 }
278
279 /**
280 * Returns true if a NIR ALU src represents a constant integer
281 * of either 32 or 64 bits, and the higher word (bit-size / 2)
282 * of all its components is zero.
283 */
284 static inline bool
285 is_upper_half_zero(UNUSED struct hash_table *ht,
286 nir_alu_instr *instr, unsigned src,
287 unsigned num_components, const uint8_t *swizzle)
288 {
289 if (nir_src_as_const_value(instr->src[src].src) == NULL)
290 return false;
291
292 for (unsigned i = 0; i < num_components; i++) {
293 unsigned half_bit_size = nir_src_bit_size(instr->src[src].src) / 2;
294 uint32_t high_bits = ((1 << half_bit_size) - 1) << half_bit_size;
295 if ((nir_src_comp_as_uint(instr->src[src].src,
296 swizzle[i]) & high_bits) != 0) {
297 return false;
298 }
299 }
300
301 return true;
302 }
303
304 /**
305 * Returns true if a NIR ALU src represents a constant integer
306 * of either 32 or 64 bits, and the lower word (bit-size / 2)
307 * of all its components is zero.
308 */
309 static inline bool
310 is_lower_half_zero(UNUSED struct hash_table *ht,
311 nir_alu_instr *instr, unsigned src,
312 unsigned num_components, const uint8_t *swizzle)
313 {
314 if (nir_src_as_const_value(instr->src[src].src) == NULL)
315 return false;
316
317 for (unsigned i = 0; i < num_components; i++) {
318 uint32_t low_bits =
319 (1 << (nir_src_bit_size(instr->src[src].src) / 2)) - 1;
320 if ((nir_src_comp_as_int(instr->src[src].src, swizzle[i]) & low_bits) != 0)
321 return false;
322 }
323
324 return true;
325 }
326
327 static inline bool
328 no_signed_wrap(nir_alu_instr *instr)
329 {
330 return instr->no_signed_wrap;
331 }
332
333 static inline bool
334 no_unsigned_wrap(nir_alu_instr *instr)
335 {
336 return instr->no_unsigned_wrap;
337 }
338
339 static inline bool
340 is_integral(struct hash_table *ht, nir_alu_instr *instr, unsigned src,
341 UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
342 {
343 const struct ssa_result_range r = nir_analyze_range(ht, instr, src);
344
345 return r.is_integral;
346 }
347
348 #define RELATION(r) \
349 static inline bool \
350 is_ ## r (struct hash_table *ht, nir_alu_instr *instr, unsigned src, \
351 UNUSED unsigned num_components, UNUSED const uint8_t *swizzle) \
352 { \
353 const struct ssa_result_range v = nir_analyze_range(ht, instr, src); \
354 return v.range == r; \
355 }
356
357 RELATION(lt_zero)
358 RELATION(le_zero)
359 RELATION(gt_zero)
360 RELATION(ge_zero)
361 RELATION(ne_zero)
362
363 static inline bool
364 is_not_negative(struct hash_table *ht, nir_alu_instr *instr, unsigned src,
365 UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
366 {
367 const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
368 return v.range == ge_zero || v.range == gt_zero || v.range == eq_zero;
369 }
370
371 static inline bool
372 is_not_positive(struct hash_table *ht, nir_alu_instr *instr, unsigned src,
373 UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
374 {
375 const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
376 return v.range == le_zero || v.range == lt_zero || v.range == eq_zero;
377 }
378
379 static inline bool
380 is_not_zero(struct hash_table *ht, nir_alu_instr *instr, unsigned src,
381 UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
382 {
383 const struct ssa_result_range v = nir_analyze_range(ht, instr, src);
384 return v.range == lt_zero || v.range == gt_zero || v.range == ne_zero;
385 }
386
387 #endif /* _NIR_SEARCH_ */