• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "ir3_nir.h"
2 
3 #include "nir.h"
4 #include "nir_search.h"
5 #include "nir_search_helpers.h"
6 
7 #ifndef NIR_OPT_ALGEBRAIC_STRUCT_DEFS
8 #define NIR_OPT_ALGEBRAIC_STRUCT_DEFS
9 
10 struct transform {
11    const nir_search_expression *search;
12    const nir_search_value *replace;
13    unsigned condition_offset;
14 };
15 
16 #endif
17 
18 
19 static const nir_search_variable search1_0 = {
20    { nir_search_value_variable, 0 },
21    0, /* x */
22    false,
23    nir_type_invalid,
24    NULL,
25 };
26 static const nir_search_expression search1 = {
27    { nir_search_value_expression, 0 },
28    false,
29    nir_op_fcos,
30    { &search1_0.value },
31    NULL,
32 };
33 
34 static const nir_search_constant replace1_0_0_0 = {
35    { nir_search_value_constant, 0 },
36    nir_type_float, { 0x401921fb3fa6defc /* 6.283185 */ },
37 };
38 
39 static const nir_search_constant replace1_0_0_1_0_0_0 = {
40    { nir_search_value_constant, 0 },
41    nir_type_float, { 0x3fc45f30e7ff583a /* 0.159155 */ },
42 };
43 
44 static const nir_search_variable replace1_0_0_1_0_0_1 = {
45    { nir_search_value_variable, 0 },
46    0, /* x */
47    false,
48    nir_type_invalid,
49    NULL,
50 };
51 static const nir_search_expression replace1_0_0_1_0_0 = {
52    { nir_search_value_expression, 0 },
53    false,
54    nir_op_fmul,
55    { &replace1_0_0_1_0_0_0.value, &replace1_0_0_1_0_0_1.value },
56    NULL,
57 };
58 
59 static const nir_search_constant replace1_0_0_1_0_1 = {
60    { nir_search_value_constant, 0 },
61    nir_type_float, { 0x3fe0000000000000 /* 0.5 */ },
62 };
63 static const nir_search_expression replace1_0_0_1_0 = {
64    { nir_search_value_expression, 0 },
65    false,
66    nir_op_fadd,
67    { &replace1_0_0_1_0_0.value, &replace1_0_0_1_0_1.value },
68    NULL,
69 };
70 static const nir_search_expression replace1_0_0_1 = {
71    { nir_search_value_expression, 0 },
72    false,
73    nir_op_ffract,
74    { &replace1_0_0_1_0.value },
75    NULL,
76 };
77 static const nir_search_expression replace1_0_0 = {
78    { nir_search_value_expression, 0 },
79    false,
80    nir_op_fmul,
81    { &replace1_0_0_0.value, &replace1_0_0_1.value },
82    NULL,
83 };
84 
85 static const nir_search_constant replace1_0_1 = {
86    { nir_search_value_constant, 0 },
87    nir_type_float, { 0x400921fb82c2bd7f /* 3.141593 */ },
88 };
89 static const nir_search_expression replace1_0 = {
90    { nir_search_value_expression, 0 },
91    false,
92    nir_op_fsub,
93    { &replace1_0_0.value, &replace1_0_1.value },
94    NULL,
95 };
96 static const nir_search_expression replace1 = {
97    { nir_search_value_expression, 0 },
98    false,
99    nir_op_fcos,
100    { &replace1_0.value },
101    NULL,
102 };
103 
104 static const struct transform ir3_nir_apply_trig_workarounds_fcos_xforms[] = {
105    { &search1, &replace1.value, 0 },
106 };
107 
108 static const nir_search_variable search0_0 = {
109    { nir_search_value_variable, 0 },
110    0, /* x */
111    false,
112    nir_type_invalid,
113    NULL,
114 };
115 static const nir_search_expression search0 = {
116    { nir_search_value_expression, 0 },
117    false,
118    nir_op_fsin,
119    { &search0_0.value },
120    NULL,
121 };
122 
123 static const nir_search_constant replace0_0_0_0 = {
124    { nir_search_value_constant, 0 },
125    nir_type_float, { 0x401921fb3fa6defc /* 6.283185 */ },
126 };
127 
128 static const nir_search_constant replace0_0_0_1_0_0_0 = {
129    { nir_search_value_constant, 0 },
130    nir_type_float, { 0x3fc45f30e7ff583a /* 0.159155 */ },
131 };
132 
133 static const nir_search_variable replace0_0_0_1_0_0_1 = {
134    { nir_search_value_variable, 0 },
135    0, /* x */
136    false,
137    nir_type_invalid,
138    NULL,
139 };
140 static const nir_search_expression replace0_0_0_1_0_0 = {
141    { nir_search_value_expression, 0 },
142    false,
143    nir_op_fmul,
144    { &replace0_0_0_1_0_0_0.value, &replace0_0_0_1_0_0_1.value },
145    NULL,
146 };
147 
148 static const nir_search_constant replace0_0_0_1_0_1 = {
149    { nir_search_value_constant, 0 },
150    nir_type_float, { 0x3fe0000000000000 /* 0.5 */ },
151 };
152 static const nir_search_expression replace0_0_0_1_0 = {
153    { nir_search_value_expression, 0 },
154    false,
155    nir_op_fadd,
156    { &replace0_0_0_1_0_0.value, &replace0_0_0_1_0_1.value },
157    NULL,
158 };
159 static const nir_search_expression replace0_0_0_1 = {
160    { nir_search_value_expression, 0 },
161    false,
162    nir_op_ffract,
163    { &replace0_0_0_1_0.value },
164    NULL,
165 };
166 static const nir_search_expression replace0_0_0 = {
167    { nir_search_value_expression, 0 },
168    false,
169    nir_op_fmul,
170    { &replace0_0_0_0.value, &replace0_0_0_1.value },
171    NULL,
172 };
173 
174 static const nir_search_constant replace0_0_1 = {
175    { nir_search_value_constant, 0 },
176    nir_type_float, { 0x400921fb82c2bd7f /* 3.141593 */ },
177 };
178 static const nir_search_expression replace0_0 = {
179    { nir_search_value_expression, 0 },
180    false,
181    nir_op_fsub,
182    { &replace0_0_0.value, &replace0_0_1.value },
183    NULL,
184 };
185 static const nir_search_expression replace0 = {
186    { nir_search_value_expression, 0 },
187    false,
188    nir_op_fsin,
189    { &replace0_0.value },
190    NULL,
191 };
192 
193 static const struct transform ir3_nir_apply_trig_workarounds_fsin_xforms[] = {
194    { &search0, &replace0.value, 0 },
195 };
196 
197 static bool
ir3_nir_apply_trig_workarounds_block(nir_block * block,const bool * condition_flags,void * mem_ctx)198 ir3_nir_apply_trig_workarounds_block(nir_block *block, const bool *condition_flags,
199                    void *mem_ctx)
200 {
201    bool progress = false;
202 
203    nir_foreach_instr_reverse_safe(instr, block) {
204       if (instr->type != nir_instr_type_alu)
205          continue;
206 
207       nir_alu_instr *alu = nir_instr_as_alu(instr);
208       if (!alu->dest.dest.is_ssa)
209          continue;
210 
211       switch (alu->op) {
212       case nir_op_fcos:
213          for (unsigned i = 0; i < ARRAY_SIZE(ir3_nir_apply_trig_workarounds_fcos_xforms); i++) {
214             const struct transform *xform = &ir3_nir_apply_trig_workarounds_fcos_xforms[i];
215             if (condition_flags[xform->condition_offset] &&
216                 nir_replace_instr(alu, xform->search, xform->replace,
217                                   mem_ctx)) {
218                progress = true;
219                break;
220             }
221          }
222          break;
223       case nir_op_fsin:
224          for (unsigned i = 0; i < ARRAY_SIZE(ir3_nir_apply_trig_workarounds_fsin_xforms); i++) {
225             const struct transform *xform = &ir3_nir_apply_trig_workarounds_fsin_xforms[i];
226             if (condition_flags[xform->condition_offset] &&
227                 nir_replace_instr(alu, xform->search, xform->replace,
228                                   mem_ctx)) {
229                progress = true;
230                break;
231             }
232          }
233          break;
234       default:
235          break;
236       }
237    }
238 
239    return progress;
240 }
241 
242 static bool
ir3_nir_apply_trig_workarounds_impl(nir_function_impl * impl,const bool * condition_flags)243 ir3_nir_apply_trig_workarounds_impl(nir_function_impl *impl, const bool *condition_flags)
244 {
245    void *mem_ctx = ralloc_parent(impl);
246    bool progress = false;
247 
248    nir_foreach_block_reverse(block, impl) {
249       progress |= ir3_nir_apply_trig_workarounds_block(block, condition_flags, mem_ctx);
250    }
251 
252    if (progress)
253       nir_metadata_preserve(impl, nir_metadata_block_index |
254                                   nir_metadata_dominance);
255 
256    return progress;
257 }
258 
259 
260 bool
ir3_nir_apply_trig_workarounds(nir_shader * shader)261 ir3_nir_apply_trig_workarounds(nir_shader *shader)
262 {
263    bool progress = false;
264    bool condition_flags[1];
265    const nir_shader_compiler_options *options = shader->options;
266    (void) options;
267 
268    condition_flags[0] = true;
269 
270    nir_foreach_function(function, shader) {
271       if (function->impl)
272          progress |= ir3_nir_apply_trig_workarounds_impl(function->impl, condition_flags);
273    }
274 
275    return progress;
276 }
277 
278