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