• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "brw_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_variable replace1_0_0 = {
35    { nir_search_value_variable, 0 },
36    0, /* x */
37    false,
38    nir_type_invalid,
39    NULL,
40 };
41 static const nir_search_expression replace1_0 = {
42    { nir_search_value_expression, 0 },
43    false,
44    nir_op_fcos,
45    { &replace1_0_0.value },
46    NULL,
47 };
48 
49 static const nir_search_constant replace1_1 = {
50    { nir_search_value_constant, 0 },
51    nir_type_float, { 0x3fefffc115df6556 /* 0.99997 */ },
52 };
53 static const nir_search_expression replace1 = {
54    { nir_search_value_expression, 0 },
55    false,
56    nir_op_fmul,
57    { &replace1_0.value, &replace1_1.value },
58    NULL,
59 };
60 
61 static const struct transform brw_nir_apply_trig_workarounds_fcos_xforms[] = {
62    { &search1, &replace1.value, 0 },
63 };
64 
65 static const nir_search_variable search0_0 = {
66    { nir_search_value_variable, 0 },
67    0, /* x */
68    false,
69    nir_type_invalid,
70    NULL,
71 };
72 static const nir_search_expression search0 = {
73    { nir_search_value_expression, 0 },
74    false,
75    nir_op_fsin,
76    { &search0_0.value },
77    NULL,
78 };
79 
80 static const nir_search_variable replace0_0_0 = {
81    { nir_search_value_variable, 0 },
82    0, /* x */
83    false,
84    nir_type_invalid,
85    NULL,
86 };
87 static const nir_search_expression replace0_0 = {
88    { nir_search_value_expression, 0 },
89    false,
90    nir_op_fsin,
91    { &replace0_0_0.value },
92    NULL,
93 };
94 
95 static const nir_search_constant replace0_1 = {
96    { nir_search_value_constant, 0 },
97    nir_type_float, { 0x3fefffc115df6556 /* 0.99997 */ },
98 };
99 static const nir_search_expression replace0 = {
100    { nir_search_value_expression, 0 },
101    false,
102    nir_op_fmul,
103    { &replace0_0.value, &replace0_1.value },
104    NULL,
105 };
106 
107 static const struct transform brw_nir_apply_trig_workarounds_fsin_xforms[] = {
108    { &search0, &replace0.value, 0 },
109 };
110 
111 static bool
brw_nir_apply_trig_workarounds_block(nir_block * block,const bool * condition_flags,void * mem_ctx)112 brw_nir_apply_trig_workarounds_block(nir_block *block, const bool *condition_flags,
113                    void *mem_ctx)
114 {
115    bool progress = false;
116 
117    nir_foreach_instr_reverse_safe(instr, block) {
118       if (instr->type != nir_instr_type_alu)
119          continue;
120 
121       nir_alu_instr *alu = nir_instr_as_alu(instr);
122       if (!alu->dest.dest.is_ssa)
123          continue;
124 
125       switch (alu->op) {
126       case nir_op_fcos:
127          for (unsigned i = 0; i < ARRAY_SIZE(brw_nir_apply_trig_workarounds_fcos_xforms); i++) {
128             const struct transform *xform = &brw_nir_apply_trig_workarounds_fcos_xforms[i];
129             if (condition_flags[xform->condition_offset] &&
130                 nir_replace_instr(alu, xform->search, xform->replace,
131                                   mem_ctx)) {
132                progress = true;
133                break;
134             }
135          }
136          break;
137       case nir_op_fsin:
138          for (unsigned i = 0; i < ARRAY_SIZE(brw_nir_apply_trig_workarounds_fsin_xforms); i++) {
139             const struct transform *xform = &brw_nir_apply_trig_workarounds_fsin_xforms[i];
140             if (condition_flags[xform->condition_offset] &&
141                 nir_replace_instr(alu, xform->search, xform->replace,
142                                   mem_ctx)) {
143                progress = true;
144                break;
145             }
146          }
147          break;
148       default:
149          break;
150       }
151    }
152 
153    return progress;
154 }
155 
156 static bool
brw_nir_apply_trig_workarounds_impl(nir_function_impl * impl,const bool * condition_flags)157 brw_nir_apply_trig_workarounds_impl(nir_function_impl *impl, const bool *condition_flags)
158 {
159    void *mem_ctx = ralloc_parent(impl);
160    bool progress = false;
161 
162    nir_foreach_block_reverse(block, impl) {
163       progress |= brw_nir_apply_trig_workarounds_block(block, condition_flags, mem_ctx);
164    }
165 
166    if (progress)
167       nir_metadata_preserve(impl, nir_metadata_block_index |
168                                   nir_metadata_dominance);
169 
170    return progress;
171 }
172 
173 
174 bool
brw_nir_apply_trig_workarounds(nir_shader * shader)175 brw_nir_apply_trig_workarounds(nir_shader *shader)
176 {
177    bool progress = false;
178    bool condition_flags[1];
179    const nir_shader_compiler_options *options = shader->options;
180    (void) options;
181 
182    condition_flags[0] = true;
183 
184    nir_foreach_function(function, shader) {
185       if (function->impl)
186          progress |= brw_nir_apply_trig_workarounds_impl(function->impl, condition_flags);
187    }
188 
189    return progress;
190 }
191 
192