1 #include "ir3_nir.h"
2
3 #include "nir.h"
4 #include "nir_builder.h"
5 #include "nir_search.h"
6 #include "nir_search_helpers.h"
7
8 /* What follows is NIR algebraic transform code for the following 2
9 * transforms:
10 * ('fsin', 'x@32') => ('fsin', ('fsub', ('fmul', 6.2831853, ('ffract', ('fadd', ('fmul', 0.15915494, 'x'), 0.5))), 3.14159265))
11 * ('fcos', 'x@32') => ('fcos', ('fsub', ('fmul', 6.2831853, ('ffract', ('fadd', ('fmul', 0.15915494, 'x'), 0.5))), 3.14159265))
12 */
13
14
15 static const nir_search_variable search0_0 = {
16 { nir_search_value_variable, 32 },
17 0, /* x */
18 false,
19 nir_type_invalid,
20 NULL,
21 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
22 };
23 static const nir_search_expression search0 = {
24 { nir_search_value_expression, 32 },
25 false, false,
26 -1, 0,
27 nir_op_fsin,
28 { &search0_0.value },
29 NULL,
30 };
31
32 static const nir_search_constant replace0_0_0_0 = {
33 { nir_search_value_constant, 32 },
34 nir_type_float, { 0x401921fb53c8d4f1 /* 6.2831853 */ },
35 };
36
37 static const nir_search_constant replace0_0_0_1_0_0_0 = {
38 { nir_search_value_constant, 32 },
39 nir_type_float, { 0x3fc45f306725feed /* 0.15915494 */ },
40 };
41
42 /* replace0_0_0_1_0_0_1 -> search0_0 in the cache */
43 static const nir_search_expression replace0_0_0_1_0_0 = {
44 { nir_search_value_expression, 32 },
45 false, false,
46 2, 1,
47 nir_op_fmul,
48 { &replace0_0_0_1_0_0_0.value, &search0_0.value },
49 NULL,
50 };
51
52 static const nir_search_constant replace0_0_0_1_0_1 = {
53 { nir_search_value_constant, 32 },
54 nir_type_float, { 0x3fe0000000000000 /* 0.5 */ },
55 };
56 static const nir_search_expression replace0_0_0_1_0 = {
57 { nir_search_value_expression, 32 },
58 false, false,
59 1, 2,
60 nir_op_fadd,
61 { &replace0_0_0_1_0_0.value, &replace0_0_0_1_0_1.value },
62 NULL,
63 };
64 static const nir_search_expression replace0_0_0_1 = {
65 { nir_search_value_expression, 32 },
66 false, false,
67 -1, 2,
68 nir_op_ffract,
69 { &replace0_0_0_1_0.value },
70 NULL,
71 };
72 static const nir_search_expression replace0_0_0 = {
73 { nir_search_value_expression, 32 },
74 false, false,
75 0, 3,
76 nir_op_fmul,
77 { &replace0_0_0_0.value, &replace0_0_0_1.value },
78 NULL,
79 };
80
81 static const nir_search_constant replace0_0_1 = {
82 { nir_search_value_constant, 32 },
83 nir_type_float, { 0x400921fb53c8d4f1 /* 3.14159265 */ },
84 };
85 static const nir_search_expression replace0_0 = {
86 { nir_search_value_expression, 32 },
87 false, false,
88 -1, 3,
89 nir_op_fsub,
90 { &replace0_0_0.value, &replace0_0_1.value },
91 NULL,
92 };
93 static const nir_search_expression replace0 = {
94 { nir_search_value_expression, 32 },
95 false, false,
96 -1, 3,
97 nir_op_fsin,
98 { &replace0_0.value },
99 NULL,
100 };
101
102 /* search1_0 -> search0_0 in the cache */
103 static const nir_search_expression search1 = {
104 { nir_search_value_expression, 32 },
105 false, false,
106 -1, 0,
107 nir_op_fcos,
108 { &search0_0.value },
109 NULL,
110 };
111
112 /* replace1_0_0_0 -> replace0_0_0_0 in the cache */
113
114 /* replace1_0_0_1_0_0_0 -> replace0_0_0_1_0_0_0 in the cache */
115
116 /* replace1_0_0_1_0_0_1 -> search0_0 in the cache */
117 /* replace1_0_0_1_0_0 -> replace0_0_0_1_0_0 in the cache */
118
119 /* replace1_0_0_1_0_1 -> replace0_0_0_1_0_1 in the cache */
120 /* replace1_0_0_1_0 -> replace0_0_0_1_0 in the cache */
121 /* replace1_0_0_1 -> replace0_0_0_1 in the cache */
122 /* replace1_0_0 -> replace0_0_0 in the cache */
123
124 /* replace1_0_1 -> replace0_0_1 in the cache */
125 /* replace1_0 -> replace0_0 in the cache */
126 static const nir_search_expression replace1 = {
127 { nir_search_value_expression, 32 },
128 false, false,
129 -1, 3,
130 nir_op_fcos,
131 { &replace0_0.value },
132 NULL,
133 };
134
135
136 static const struct transform ir3_nir_apply_trig_workarounds_state2_xforms[] = {
137 { &search0, &replace0.value, 0 },
138 };
139 static const struct transform ir3_nir_apply_trig_workarounds_state3_xforms[] = {
140 { &search1, &replace1.value, 0 },
141 };
142
143 static const struct per_op_table ir3_nir_apply_trig_workarounds_table[nir_num_search_ops] = {
144 [nir_op_fsin] = {
145 .filter = (uint16_t []) {
146 0,
147 0,
148 0,
149 0,
150 },
151
152 .num_filtered_states = 1,
153 .table = (uint16_t []) {
154
155 2,
156 },
157 },
158 [nir_op_fcos] = {
159 .filter = (uint16_t []) {
160 0,
161 0,
162 0,
163 0,
164 },
165
166 .num_filtered_states = 1,
167 .table = (uint16_t []) {
168
169 3,
170 },
171 },
172 };
173
174 const struct transform *ir3_nir_apply_trig_workarounds_transforms[] = {
175 NULL,
176 NULL,
177 ir3_nir_apply_trig_workarounds_state2_xforms,
178 ir3_nir_apply_trig_workarounds_state3_xforms,
179 };
180
181 const uint16_t ir3_nir_apply_trig_workarounds_transform_counts[] = {
182 0,
183 0,
184 (uint16_t)ARRAY_SIZE(ir3_nir_apply_trig_workarounds_state2_xforms),
185 (uint16_t)ARRAY_SIZE(ir3_nir_apply_trig_workarounds_state3_xforms),
186 };
187
188 bool
ir3_nir_apply_trig_workarounds(nir_shader * shader)189 ir3_nir_apply_trig_workarounds(nir_shader *shader)
190 {
191 bool progress = false;
192 bool condition_flags[1];
193 const nir_shader_compiler_options *options = shader->options;
194 const shader_info *info = &shader->info;
195 (void) options;
196 (void) info;
197
198 condition_flags[0] = true;
199
200 nir_foreach_function(function, shader) {
201 if (function->impl) {
202 progress |= nir_algebraic_impl(function->impl, condition_flags,
203 ir3_nir_apply_trig_workarounds_transforms,
204 ir3_nir_apply_trig_workarounds_transform_counts,
205 ir3_nir_apply_trig_workarounds_table);
206 }
207 }
208
209 return progress;
210 }
211
212