• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 Collabora, Ltd.
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include "agx_builder.h"
7 #include "agx_compiler.h"
8 #include "agx_test.h"
9 
10 #include <gtest/gtest.h>
11 
12 static void
agx_optimize_and_dce(agx_context * ctx)13 agx_optimize_and_dce(agx_context *ctx)
14 {
15    agx_optimizer(ctx);
16    agx_dce(ctx, true);
17 }
18 
19 #define CASE(instr, expected, size, returns)                                   \
20    INSTRUCTION_CASE(                                                           \
21       {                                                                        \
22          UNUSED agx_index out = agx_temp(b->shader, AGX_SIZE_##size);          \
23          instr;                                                                \
24          if (returns)                                                          \
25             agx_unit_test(b, out);                                             \
26       },                                                                       \
27       {                                                                        \
28          UNUSED agx_index out = agx_temp(b->shader, AGX_SIZE_##size);          \
29          expected;                                                             \
30          if (returns)                                                          \
31             agx_unit_test(b, out);                                             \
32       },                                                                       \
33       agx_optimize_and_dce)
34 
35 #define NEGCASE(instr, size) CASE(instr, instr, size, true)
36 
37 #define CASE16(instr, expected) CASE(instr, expected, 16, true)
38 #define CASE32(instr, expected) CASE(instr, expected, 32, true)
39 
40 #define CASE_NO_RETURN(instr, expected)                                        \
41    CASE(instr, expected, 32 /* irrelevant */, false)
42 
43 #define NEGCASE16(instr) NEGCASE(instr, 16)
44 #define NEGCASE32(instr) NEGCASE(instr, 32)
45 
46 static inline agx_index
agx_fmov(agx_builder * b,agx_index s0)47 agx_fmov(agx_builder *b, agx_index s0)
48 {
49    agx_index tmp = agx_temp(b->shader, s0.size);
50    agx_fmov_to(b, tmp, s0);
51    return tmp;
52 }
53 
54 class Optimizer : public testing::Test {
55  protected:
Optimizer()56    Optimizer()
57    {
58       mem_ctx = ralloc_context(NULL);
59 
60       wx = agx_register(0, AGX_SIZE_32);
61       wy = agx_register(2, AGX_SIZE_32);
62       wz = agx_register(4, AGX_SIZE_32);
63 
64       hx = agx_register(0, AGX_SIZE_16);
65       hy = agx_register(1, AGX_SIZE_16);
66       hz = agx_register(2, AGX_SIZE_16);
67    }
68 
~Optimizer()69    ~Optimizer()
70    {
71       ralloc_free(mem_ctx);
72    }
73 
74    void *mem_ctx;
75 
76    agx_index wx, wy, wz, hx, hy, hz;
77 };
78 
TEST_F(Optimizer,FloatCopyprop)79 TEST_F(Optimizer, FloatCopyprop)
80 {
81    CASE32(agx_fadd_to(b, out, agx_abs(agx_fmov(b, wx)), wy),
82           agx_fadd_to(b, out, agx_abs(wx), wy));
83 
84    CASE32(agx_fadd_to(b, out, agx_neg(agx_fmov(b, wx)), wy),
85           agx_fadd_to(b, out, agx_neg(wx), wy));
86 }
87 
TEST_F(Optimizer,FloatConversion)88 TEST_F(Optimizer, FloatConversion)
89 {
90    CASE32(
91       {
92          agx_index cvt = agx_temp(b->shader, AGX_SIZE_32);
93          agx_fmov_to(b, cvt, hx);
94          agx_fadd_to(b, out, cvt, wy);
95       },
96       { agx_fadd_to(b, out, hx, wy); });
97 
98    CASE16(
99       {
100          agx_index sum = agx_temp(b->shader, AGX_SIZE_32);
101          agx_fadd_to(b, sum, wx, wy);
102          agx_fmov_to(b, out, sum);
103       },
104       { agx_fadd_to(b, out, wx, wy); });
105 }
106 
TEST_F(Optimizer,FusedFABSNEG)107 TEST_F(Optimizer, FusedFABSNEG)
108 {
109    CASE32(agx_fadd_to(b, out, agx_fmov(b, agx_abs(wx)), wy),
110           agx_fadd_to(b, out, agx_abs(wx), wy));
111 
112    CASE32(agx_fmul_to(b, out, wx, agx_fmov(b, agx_neg(agx_abs(wx)))),
113           agx_fmul_to(b, out, wx, agx_neg(agx_abs(wx))));
114 }
115 
TEST_F(Optimizer,FusedFabsAbsorb)116 TEST_F(Optimizer, FusedFabsAbsorb)
117 {
118    CASE32(agx_fadd_to(b, out, agx_abs(agx_fmov(b, agx_abs(wx))), wy),
119           agx_fadd_to(b, out, agx_abs(wx), wy));
120 }
121 
TEST_F(Optimizer,FusedFnegCancel)122 TEST_F(Optimizer, FusedFnegCancel)
123 {
124    CASE32(agx_fmul_to(b, out, wx, agx_neg(agx_fmov(b, agx_neg(wx)))),
125           agx_fmul_to(b, out, wx, wx));
126 
127    CASE32(agx_fmul_to(b, out, wx, agx_neg(agx_fmov(b, agx_neg(agx_abs(wx))))),
128           agx_fmul_to(b, out, wx, agx_abs(wx)));
129 }
130 
TEST_F(Optimizer,FusedNot)131 TEST_F(Optimizer, FusedNot)
132 {
133    CASE32(agx_not_to(b, out, agx_and(b, wx, wx)), agx_nand_to(b, out, wx, wx));
134 
135    CASE32(agx_not_to(b, out, agx_or(b, wx, wx)), agx_nor_to(b, out, wx, wx));
136 
137    CASE32(agx_not_to(b, out, agx_xor(b, wx, wx)), agx_xnor_to(b, out, wx, wx));
138 
139    CASE32(agx_xor_to(b, out, agx_not(b, wx), agx_not(b, wx)),
140           agx_xor_to(b, out, wx, wx));
141 
142    CASE32(agx_xor_to(b, out, agx_not(b, wx), wx), agx_xnor_to(b, out, wx, wx));
143 
144    CASE32(agx_xor_to(b, out, wx, agx_not(b, wx)), agx_xnor_to(b, out, wx, wx));
145 
146    CASE32(agx_nand_to(b, out, agx_not(b, wx), agx_not(b, wx)),
147           agx_or_to(b, out, wx, wx));
148 
149    CASE32(agx_andn1_to(b, out, agx_not(b, wx), wx), agx_and_to(b, out, wx, wx));
150 
151    CASE32(agx_andn1_to(b, out, wx, agx_not(b, wx)), agx_nor_to(b, out, wx, wx));
152 
153    CASE32(agx_andn2_to(b, out, agx_not(b, wx), wx), agx_nor_to(b, out, wx, wx));
154 
155    CASE32(agx_andn2_to(b, out, wx, agx_not(b, wx)), agx_and_to(b, out, wx, wx));
156 
157    CASE32(agx_xor_to(b, out, agx_not(b, wx), agx_uniform(8, AGX_SIZE_32)),
158           agx_xnor_to(b, out, wx, agx_uniform(8, AGX_SIZE_32)));
159 
160    CASE32(agx_or_to(b, out, agx_immediate(123), agx_not(b, wx)),
161           agx_orn2_to(b, out, agx_immediate(123), wx));
162 
163    CASE32(agx_xor_to(b, out, wx, agx_not(b, wy)), agx_xnor_to(b, out, wx, wy));
164 
165    CASE32(agx_xor_to(b, out, wy, agx_not(b, wx)), agx_xnor_to(b, out, wy, wx));
166 
167    CASE32(agx_and_to(b, out, agx_not(b, wx), wy), agx_andn1_to(b, out, wx, wy));
168 
169    CASE32(agx_or_to(b, out, wx, agx_not(b, wy)), agx_orn2_to(b, out, wx, wy));
170 }
171 
TEST_F(Optimizer,FmulFsatF2F16)172 TEST_F(Optimizer, FmulFsatF2F16)
173 {
174    CASE16(
175       {
176          agx_index tmp = agx_temp(b->shader, AGX_SIZE_32);
177          agx_fmov_to(b, tmp, agx_fmul(b, wx, wy))->saturate = true;
178          agx_fmov_to(b, out, tmp);
179       },
180       { agx_fmul_to(b, out, wx, wy)->saturate = true; });
181 }
182 
TEST_F(Optimizer,Copyprop)183 TEST_F(Optimizer, Copyprop)
184 {
185    CASE32(agx_fmul_to(b, out, wx, agx_mov(b, wy)), agx_fmul_to(b, out, wx, wy));
186    CASE32(agx_fmul_to(b, out, agx_mov(b, wx), agx_mov(b, wy)),
187           agx_fmul_to(b, out, wx, wy));
188 }
189 
TEST_F(Optimizer,InlineHazards)190 TEST_F(Optimizer, InlineHazards)
191 {
192    NEGCASE32({
193       agx_instr *I = agx_collect_to(b, out, 4);
194       I->src[0] = agx_mov_imm(b, AGX_SIZE_32, 0);
195       I->src[1] = wy;
196       I->src[2] = wz;
197       I->src[3] = wz;
198    });
199 }
200 
TEST_F(Optimizer,CopypropRespectsAbsNeg)201 TEST_F(Optimizer, CopypropRespectsAbsNeg)
202 {
203    CASE32(agx_fadd_to(b, out, agx_abs(agx_mov(b, wx)), wy),
204           agx_fadd_to(b, out, agx_abs(wx), wy));
205 
206    CASE32(agx_fadd_to(b, out, agx_neg(agx_mov(b, wx)), wy),
207           agx_fadd_to(b, out, agx_neg(wx), wy));
208 
209    CASE32(agx_fadd_to(b, out, agx_neg(agx_abs(agx_mov(b, wx))), wy),
210           agx_fadd_to(b, out, agx_neg(agx_abs(wx)), wy));
211 }
212 
TEST_F(Optimizer,IntCopyprop)213 TEST_F(Optimizer, IntCopyprop)
214 {
215    CASE32(agx_xor_to(b, out, agx_mov(b, wx), wy), agx_xor_to(b, out, wx, wy));
216 }
217 
TEST_F(Optimizer,CopypropSplitMovedUniform64)218 TEST_F(Optimizer, CopypropSplitMovedUniform64)
219 {
220    CASE32(
221       {
222          /* emit_load_preamble puts in the move, so we do too */
223          agx_index mov = agx_mov(b, agx_uniform(40, AGX_SIZE_64));
224          agx_instr *spl = agx_split(b, 2, mov);
225          spl->dest[0] = agx_temp(b->shader, AGX_SIZE_32);
226          spl->dest[1] = agx_temp(b->shader, AGX_SIZE_32);
227          agx_xor_to(b, out, spl->dest[0], spl->dest[1]);
228       },
229       {
230          agx_xor_to(b, out, agx_uniform(40, AGX_SIZE_32),
231                     agx_uniform(42, AGX_SIZE_32));
232       });
233 }
234 
TEST_F(Optimizer,IntCopypropDoesntConvert)235 TEST_F(Optimizer, IntCopypropDoesntConvert)
236 {
237    NEGCASE32({
238       agx_index cvt = agx_temp(b->shader, AGX_SIZE_32);
239       agx_mov_to(b, cvt, hx);
240       agx_xor_to(b, out, cvt, wy);
241    });
242 }
243 
TEST_F(Optimizer,SkipPreloads)244 TEST_F(Optimizer, SkipPreloads)
245 {
246    NEGCASE32({
247       agx_index preload = agx_preload(b, agx_register(0, AGX_SIZE_32));
248       agx_xor_to(b, out, preload, wy);
249    });
250 }
251 
TEST_F(Optimizer,NoConversionsOn16BitALU)252 TEST_F(Optimizer, NoConversionsOn16BitALU)
253 {
254    NEGCASE16({
255       agx_index cvt = agx_temp(b->shader, AGX_SIZE_16);
256       agx_fmov_to(b, cvt, wx);
257       agx_fadd_to(b, out, cvt, hy);
258    });
259 
260    NEGCASE32(agx_fmov_to(b, out, agx_fadd(b, hx, hy)));
261 }
262 
TEST_F(Optimizer,BallotCondition)263 TEST_F(Optimizer, BallotCondition)
264 {
265    CASE32(agx_ballot_to(b, out, agx_icmp(b, wx, wy, AGX_ICOND_UEQ, true)),
266           agx_icmp_ballot_to(b, out, wx, wy, AGX_ICOND_UEQ, true));
267 
268    CASE32(agx_ballot_to(b, out, agx_fcmp(b, wx, wy, AGX_FCOND_GE, false)),
269           agx_fcmp_ballot_to(b, out, wx, wy, AGX_FCOND_GE, false));
270 
271    CASE32(agx_quad_ballot_to(b, out, agx_icmp(b, wx, wy, AGX_ICOND_UEQ, true)),
272           agx_icmp_quad_ballot_to(b, out, wx, wy, AGX_ICOND_UEQ, true));
273 
274    CASE32(agx_quad_ballot_to(b, out, agx_fcmp(b, wx, wy, AGX_FCOND_GT, false)),
275           agx_fcmp_quad_ballot_to(b, out, wx, wy, AGX_FCOND_GT, false));
276 }
277 
TEST_F(Optimizer,BallotMultipleUses)278 TEST_F(Optimizer, BallotMultipleUses)
279 {
280    CASE32(
281       {
282          agx_index cmp = agx_fcmp(b, wx, wy, AGX_FCOND_GT, false);
283          agx_index ballot = agx_quad_ballot(b, cmp);
284          agx_fadd_to(b, out, cmp, ballot);
285       },
286       {
287          agx_index cmp = agx_fcmp(b, wx, wy, AGX_FCOND_GT, false);
288          agx_index ballot =
289             agx_fcmp_quad_ballot(b, wx, wy, AGX_FCOND_GT, false);
290          agx_fadd_to(b, out, cmp, ballot);
291       });
292 }
293 
TEST_F(Optimizer,IfCondition)294 TEST_F(Optimizer, IfCondition)
295 {
296    CASE_NO_RETURN(agx_if_icmp(b, agx_icmp(b, wx, wy, AGX_ICOND_UEQ, true),
297                               agx_zero(), 1, AGX_ICOND_UEQ, true, NULL),
298                   agx_if_icmp(b, wx, wy, 1, AGX_ICOND_UEQ, true, NULL));
299 
300    CASE_NO_RETURN(agx_if_icmp(b, agx_fcmp(b, wx, wy, AGX_FCOND_EQ, true),
301                               agx_zero(), 1, AGX_ICOND_UEQ, true, NULL),
302                   agx_if_fcmp(b, wx, wy, 1, AGX_FCOND_EQ, true, NULL));
303 
304    CASE_NO_RETURN(agx_if_icmp(b, agx_fcmp(b, hx, hy, AGX_FCOND_LT, false),
305                               agx_zero(), 1, AGX_ICOND_UEQ, true, NULL),
306                   agx_if_fcmp(b, hx, hy, 1, AGX_FCOND_LT, false, NULL));
307 }
308 
TEST_F(Optimizer,SelectCondition)309 TEST_F(Optimizer, SelectCondition)
310 {
311    CASE32(agx_icmpsel_to(b, out, agx_icmp(b, wx, wy, AGX_ICOND_UEQ, false),
312                          agx_zero(), wz, wx, AGX_ICOND_UEQ),
313           agx_icmpsel_to(b, out, wx, wy, wx, wz, AGX_ICOND_UEQ));
314 
315    CASE32(agx_icmpsel_to(b, out, agx_icmp(b, wx, wy, AGX_ICOND_UEQ, true),
316                          agx_zero(), wz, wx, AGX_ICOND_UEQ),
317           agx_icmpsel_to(b, out, wx, wy, wz, wx, AGX_ICOND_UEQ));
318 
319    CASE32(agx_icmpsel_to(b, out, agx_fcmp(b, wx, wy, AGX_FCOND_EQ, false),
320                          agx_zero(), wz, wx, AGX_ICOND_UEQ),
321           agx_fcmpsel_to(b, out, wx, wy, wx, wz, AGX_FCOND_EQ));
322 
323    CASE32(agx_icmpsel_to(b, out, agx_fcmp(b, wx, wy, AGX_FCOND_LT, true),
324                          agx_zero(), wz, wx, AGX_ICOND_UEQ),
325           agx_fcmpsel_to(b, out, wx, wy, wz, wx, AGX_FCOND_LT));
326 }
327