1 #include "brw_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(is_not_const)') => ('fmul', ('fsin', 'x'), 0.99997)
11 * ('fcos', 'x(is_not_const)') => ('fmul', ('fcos', 'x'), 0.99997)
12 */
13
14
15 static const nir_search_variable search0_0 = {
16 { nir_search_value_variable, -1 },
17 0, /* x */
18 false,
19 nir_type_invalid,
20 (is_not_const),
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, -1 },
25 false, false,
26 -1, 0,
27 nir_op_fsin,
28 { &search0_0.value },
29 NULL,
30 };
31
32 static const nir_search_variable replace0_0_0 = {
33 { nir_search_value_variable, -1 },
34 0, /* x */
35 false,
36 nir_type_invalid,
37 NULL,
38 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
39 };
40 static const nir_search_expression replace0_0 = {
41 { nir_search_value_expression, -1 },
42 false, false,
43 -1, 0,
44 nir_op_fsin,
45 { &replace0_0_0.value },
46 NULL,
47 };
48
49 static const nir_search_constant replace0_1 = {
50 { nir_search_value_constant, -1 },
51 nir_type_float, { 0x3fefffc115df6556 /* 0.99997 */ },
52 };
53 static const nir_search_expression replace0 = {
54 { nir_search_value_expression, -1 },
55 false, false,
56 0, 1,
57 nir_op_fmul,
58 { &replace0_0.value, &replace0_1.value },
59 NULL,
60 };
61
62 /* search1_0 -> search0_0 in the cache */
63 static const nir_search_expression search1 = {
64 { nir_search_value_expression, -1 },
65 false, false,
66 -1, 0,
67 nir_op_fcos,
68 { &search0_0.value },
69 NULL,
70 };
71
72 /* replace1_0_0 -> replace0_0_0 in the cache */
73 static const nir_search_expression replace1_0 = {
74 { nir_search_value_expression, -1 },
75 false, false,
76 -1, 0,
77 nir_op_fcos,
78 { &replace0_0_0.value },
79 NULL,
80 };
81
82 /* replace1_1 -> replace0_1 in the cache */
83 static const nir_search_expression replace1 = {
84 { nir_search_value_expression, -1 },
85 false, false,
86 0, 1,
87 nir_op_fmul,
88 { &replace1_0.value, &replace0_1.value },
89 NULL,
90 };
91
92
93 static const struct transform brw_nir_apply_trig_workarounds_state2_xforms[] = {
94 { &search0, &replace0.value, 0 },
95 };
96 static const struct transform brw_nir_apply_trig_workarounds_state3_xforms[] = {
97 { &search1, &replace1.value, 0 },
98 };
99
100 static const struct per_op_table brw_nir_apply_trig_workarounds_table[nir_num_search_ops] = {
101 [nir_op_fsin] = {
102 .filter = (uint16_t []) {
103 0,
104 0,
105 0,
106 0,
107 },
108
109 .num_filtered_states = 1,
110 .table = (uint16_t []) {
111
112 2,
113 },
114 },
115 [nir_op_fcos] = {
116 .filter = (uint16_t []) {
117 0,
118 0,
119 0,
120 0,
121 },
122
123 .num_filtered_states = 1,
124 .table = (uint16_t []) {
125
126 3,
127 },
128 },
129 };
130
131 const struct transform *brw_nir_apply_trig_workarounds_transforms[] = {
132 NULL,
133 NULL,
134 brw_nir_apply_trig_workarounds_state2_xforms,
135 brw_nir_apply_trig_workarounds_state3_xforms,
136 };
137
138 const uint16_t brw_nir_apply_trig_workarounds_transform_counts[] = {
139 0,
140 0,
141 (uint16_t)ARRAY_SIZE(brw_nir_apply_trig_workarounds_state2_xforms),
142 (uint16_t)ARRAY_SIZE(brw_nir_apply_trig_workarounds_state3_xforms),
143 };
144
145 bool
brw_nir_apply_trig_workarounds(nir_shader * shader)146 brw_nir_apply_trig_workarounds(nir_shader *shader)
147 {
148 bool progress = false;
149 bool condition_flags[1];
150 const nir_shader_compiler_options *options = shader->options;
151 const shader_info *info = &shader->info;
152 (void) options;
153 (void) info;
154
155 condition_flags[0] = true;
156
157 nir_foreach_function(function, shader) {
158 if (function->impl) {
159 progress |= nir_algebraic_impl(function->impl, condition_flags,
160 brw_nir_apply_trig_workarounds_transforms,
161 brw_nir_apply_trig_workarounds_transform_counts,
162 brw_nir_apply_trig_workarounds_table);
163 }
164 }
165
166 return progress;
167 }
168
169