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