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