nir/algebraic: Commute 1-fsat(a) to fsat(1-a) for all non-fmul instructions
[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 <math.h>
33
34 static inline bool
35 is_pos_power_of_two(nir_alu_instr *instr, unsigned src, unsigned num_components,
36 const uint8_t *swizzle)
37 {
38 /* only constant srcs: */
39 if (!nir_src_is_const(instr->src[src].src))
40 return false;
41
42 for (unsigned i = 0; i < num_components; i++) {
43 switch (nir_op_infos[instr->op].input_types[src]) {
44 case nir_type_int: {
45 int64_t val = nir_src_comp_as_int(instr->src[src].src, swizzle[i]);
46 if (val <= 0 || !util_is_power_of_two_or_zero64(val))
47 return false;
48 break;
49 }
50 case nir_type_uint: {
51 uint64_t val = nir_src_comp_as_uint(instr->src[src].src, swizzle[i]);
52 if (val == 0 || !util_is_power_of_two_or_zero64(val))
53 return false;
54 break;
55 }
56 default:
57 return false;
58 }
59 }
60
61 return true;
62 }
63
64 static inline bool
65 is_neg_power_of_two(nir_alu_instr *instr, unsigned src, unsigned num_components,
66 const uint8_t *swizzle)
67 {
68 /* only constant srcs: */
69 if (!nir_src_is_const(instr->src[src].src))
70 return false;
71
72 for (unsigned i = 0; i < num_components; i++) {
73 switch (nir_op_infos[instr->op].input_types[src]) {
74 case nir_type_int: {
75 int64_t val = nir_src_comp_as_int(instr->src[src].src, swizzle[i]);
76 if (val >= 0 || !util_is_power_of_two_or_zero64(-val))
77 return false;
78 break;
79 }
80 default:
81 return false;
82 }
83 }
84
85 return true;
86 }
87
88 static inline bool
89 is_zero_to_one(nir_alu_instr *instr, unsigned src, unsigned num_components,
90 const uint8_t *swizzle)
91 {
92 /* only constant srcs: */
93 if (!nir_src_is_const(instr->src[src].src))
94 return false;
95
96 for (unsigned i = 0; i < num_components; i++) {
97 switch (nir_op_infos[instr->op].input_types[src]) {
98 case nir_type_float: {
99 double val = nir_src_comp_as_float(instr->src[src].src, swizzle[i]);
100 if (isnan(val) || val < 0.0f || val > 1.0f)
101 return false;
102 break;
103 }
104 default:
105 return false;
106 }
107 }
108
109 return true;
110 }
111
112 /**
113 * Exclusive compare with (0, 1).
114 *
115 * This differs from \c is_zero_to_one because that function tests 0 <= src <=
116 * 1 while this function tests 0 < src < 1.
117 */
118 static inline bool
119 is_gt_0_and_lt_1(nir_alu_instr *instr, unsigned src, unsigned num_components,
120 const uint8_t *swizzle)
121 {
122 /* only constant srcs: */
123 if (!nir_src_is_const(instr->src[src].src))
124 return false;
125
126 for (unsigned i = 0; i < num_components; i++) {
127 switch (nir_op_infos[instr->op].input_types[src]) {
128 case nir_type_float: {
129 double val = nir_src_comp_as_float(instr->src[src].src, swizzle[i]);
130 if (isnan(val) || val <= 0.0f || val >= 1.0f)
131 return false;
132 break;
133 }
134 default:
135 return false;
136 }
137 }
138
139 return true;
140 }
141
142 static inline bool
143 is_not_const_zero(nir_alu_instr *instr, unsigned src, unsigned num_components,
144 const uint8_t *swizzle)
145 {
146 if (nir_src_as_const_value(instr->src[src].src) == NULL)
147 return true;
148
149 for (unsigned i = 0; i < num_components; i++) {
150 switch (nir_op_infos[instr->op].input_types[src]) {
151 case nir_type_float:
152 if (nir_src_comp_as_float(instr->src[src].src, swizzle[i]) == 0.0)
153 return false;
154 break;
155 case nir_type_bool:
156 case nir_type_int:
157 case nir_type_uint:
158 if (nir_src_comp_as_uint(instr->src[src].src, swizzle[i]) == 0)
159 return false;
160 break;
161 default:
162 return false;
163 }
164 }
165
166 return true;
167 }
168
169 static inline bool
170 is_not_const(nir_alu_instr *instr, unsigned src, UNUSED unsigned num_components,
171 UNUSED const uint8_t *swizzle)
172 {
173 return !nir_src_is_const(instr->src[src].src);
174 }
175
176 static inline bool
177 is_not_fmul(nir_alu_instr *instr, unsigned src,
178 UNUSED unsigned num_components, UNUSED const uint8_t *swizzle)
179 {
180 nir_alu_instr *src_alu =
181 nir_src_as_alu_instr(instr->src[src].src);
182
183 if (src_alu == NULL)
184 return true;
185
186 if (src_alu->op == nir_op_fneg)
187 return is_not_fmul(src_alu, 0, 0, NULL);
188
189 return src_alu->op != nir_op_fmul;
190 }
191
192 static inline bool
193 is_used_once(nir_alu_instr *instr)
194 {
195 bool zero_if_use = list_empty(&instr->dest.dest.ssa.if_uses);
196 bool zero_use = list_empty(&instr->dest.dest.ssa.uses);
197
198 if (zero_if_use && zero_use)
199 return false;
200
201 if (!zero_if_use && list_is_singular(&instr->dest.dest.ssa.uses))
202 return false;
203
204 if (!zero_use && list_is_singular(&instr->dest.dest.ssa.if_uses))
205 return false;
206
207 if (!list_is_singular(&instr->dest.dest.ssa.if_uses) &&
208 !list_is_singular(&instr->dest.dest.ssa.uses))
209 return false;
210
211 return true;
212 }
213
214 static inline bool
215 is_used_by_if(nir_alu_instr *instr)
216 {
217 return !list_empty(&instr->dest.dest.ssa.if_uses);
218 }
219
220 static inline bool
221 is_not_used_by_if(nir_alu_instr *instr)
222 {
223 return list_empty(&instr->dest.dest.ssa.if_uses);
224 }
225
226 static inline bool
227 is_used_by_non_fsat(nir_alu_instr *instr)
228 {
229 nir_foreach_use(src, &instr->dest.dest.ssa) {
230 const nir_instr *const user_instr = src->parent_instr;
231
232 if (user_instr->type != nir_instr_type_alu)
233 return true;
234
235 const nir_alu_instr *const user_alu = nir_instr_as_alu(user_instr);
236
237 assert(instr != user_alu);
238 if (user_alu->op != nir_op_fsat)
239 return true;
240 }
241
242 return false;
243 }
244
245 #endif /* _NIR_SEARCH_ */