• 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 #define CASE(copies, expected)                                                 \
13    do {                                                                        \
14       agx_builder *A = agx_test_builder(mem_ctx);                              \
15       agx_builder *B = agx_test_builder(mem_ctx);                              \
16                                                                                \
17       agx_emit_parallel_copies(A, copies, ARRAY_SIZE(copies));                 \
18                                                                                \
19       {                                                                        \
20          agx_builder *b = B;                                                   \
21          expected;                                                             \
22       }                                                                        \
23                                                                                \
24       ASSERT_SHADER_EQUAL(A->shader, B->shader);                               \
25    } while (0)
26 
27 class LowerParallelCopy : public testing::Test {
28  protected:
LowerParallelCopy()29    LowerParallelCopy()
30    {
31       mem_ctx = ralloc_context(NULL);
32    }
33 
~LowerParallelCopy()34    ~LowerParallelCopy()
35    {
36       ralloc_free(mem_ctx);
37    }
38 
39    void *mem_ctx;
40 };
41 
TEST_F(LowerParallelCopy,UnrelatedCopies)42 TEST_F(LowerParallelCopy, UnrelatedCopies)
43 {
44    struct agx_copy test_1[] = {
45       {.dest = 0, .src = agx_register(2, AGX_SIZE_32)},
46       {.dest = 4, .src = agx_register(6, AGX_SIZE_32)},
47    };
48 
49    CASE(test_1, {
50       agx_mov_to(b, agx_register(0, AGX_SIZE_32), agx_register(2, AGX_SIZE_32));
51       agx_mov_to(b, agx_register(4, AGX_SIZE_32), agx_register(6, AGX_SIZE_32));
52    });
53 
54    struct agx_copy test_2[] = {
55       {.dest = 0, .src = agx_register(1, AGX_SIZE_16)},
56       {.dest = 4, .src = agx_register(5, AGX_SIZE_16)},
57    };
58 
59    CASE(test_2, {
60       agx_mov_to(b, agx_register(0, AGX_SIZE_16), agx_register(1, AGX_SIZE_16));
61       agx_mov_to(b, agx_register(4, AGX_SIZE_16), agx_register(5, AGX_SIZE_16));
62    });
63 }
64 
TEST_F(LowerParallelCopy,RelatedSource)65 TEST_F(LowerParallelCopy, RelatedSource)
66 {
67    struct agx_copy test_1[] = {
68       {.dest = 0, .src = agx_register(2, AGX_SIZE_32)},
69       {.dest = 4, .src = agx_register(2, AGX_SIZE_32)},
70    };
71 
72    CASE(test_1, {
73       agx_mov_to(b, agx_register(0, AGX_SIZE_32), agx_register(2, AGX_SIZE_32));
74       agx_mov_to(b, agx_register(4, AGX_SIZE_32), agx_register(2, AGX_SIZE_32));
75    });
76 
77    struct agx_copy test_2[] = {
78       {.dest = 0, .src = agx_register(1, AGX_SIZE_16)},
79       {.dest = 4, .src = agx_register(1, AGX_SIZE_16)},
80    };
81 
82    CASE(test_2, {
83       agx_mov_to(b, agx_register(0, AGX_SIZE_16), agx_register(1, AGX_SIZE_16));
84       agx_mov_to(b, agx_register(4, AGX_SIZE_16), agx_register(1, AGX_SIZE_16));
85    });
86 }
87 
TEST_F(LowerParallelCopy,DependentCopies)88 TEST_F(LowerParallelCopy, DependentCopies)
89 {
90    struct agx_copy test_1[] = {
91       {.dest = 0, .src = agx_register(2, AGX_SIZE_32)},
92       {.dest = 4, .src = agx_register(0, AGX_SIZE_32)},
93    };
94 
95    CASE(test_1, {
96       agx_mov_to(b, agx_register(4, AGX_SIZE_32), agx_register(0, AGX_SIZE_32));
97       agx_mov_to(b, agx_register(0, AGX_SIZE_32), agx_register(2, AGX_SIZE_32));
98    });
99 
100    struct agx_copy test_2[] = {
101       {.dest = 0, .src = agx_register(1, AGX_SIZE_16)},
102       {.dest = 4, .src = agx_register(0, AGX_SIZE_16)},
103    };
104 
105    CASE(test_2, {
106       agx_mov_to(b, agx_register(4, AGX_SIZE_16), agx_register(0, AGX_SIZE_16));
107       agx_mov_to(b, agx_register(0, AGX_SIZE_16), agx_register(1, AGX_SIZE_16));
108    });
109 }
110 
TEST_F(LowerParallelCopy,ManyDependentCopies)111 TEST_F(LowerParallelCopy, ManyDependentCopies)
112 {
113    struct agx_copy test_1[] = {
114       {.dest = 0, .src = agx_register(2, AGX_SIZE_32)},
115       {.dest = 4, .src = agx_register(0, AGX_SIZE_32)},
116       {.dest = 8, .src = agx_register(6, AGX_SIZE_32)},
117       {.dest = 6, .src = agx_register(4, AGX_SIZE_32)},
118    };
119 
120    CASE(test_1, {
121       agx_mov_to(b, agx_register(8, AGX_SIZE_32), agx_register(6, AGX_SIZE_32));
122       agx_mov_to(b, agx_register(6, AGX_SIZE_32), agx_register(4, AGX_SIZE_32));
123       agx_mov_to(b, agx_register(4, AGX_SIZE_32), agx_register(0, AGX_SIZE_32));
124       agx_mov_to(b, agx_register(0, AGX_SIZE_32), agx_register(2, AGX_SIZE_32));
125    });
126 
127    struct agx_copy test_2[] = {
128       {.dest = 0, .src = agx_register(1, AGX_SIZE_16)},
129       {.dest = 2, .src = agx_register(0, AGX_SIZE_16)},
130       {.dest = 4, .src = agx_register(3, AGX_SIZE_16)},
131       {.dest = 3, .src = agx_register(2, AGX_SIZE_16)},
132    };
133 
134    CASE(test_2, {
135       agx_mov_to(b, agx_register(4, AGX_SIZE_16), agx_register(3, AGX_SIZE_16));
136       agx_mov_to(b, agx_register(3, AGX_SIZE_16), agx_register(2, AGX_SIZE_16));
137       agx_mov_to(b, agx_register(2, AGX_SIZE_16), agx_register(0, AGX_SIZE_16));
138       agx_mov_to(b, agx_register(0, AGX_SIZE_16), agx_register(1, AGX_SIZE_16));
139    });
140 }
141 
TEST_F(LowerParallelCopy,Swap)142 TEST_F(LowerParallelCopy, Swap)
143 {
144    struct agx_copy test_1[] = {
145       {.dest = 0, .src = agx_register(2, AGX_SIZE_32)},
146       {.dest = 2, .src = agx_register(0, AGX_SIZE_32)},
147    };
148 
149    CASE(test_1, {
150       agx_swap(b, agx_register(0, AGX_SIZE_32), agx_register(2, AGX_SIZE_32));
151    });
152 
153    struct agx_copy test_2[] = {
154       {.dest = 0, .src = agx_register(1, AGX_SIZE_16)},
155       {.dest = 1, .src = agx_register(0, AGX_SIZE_16)},
156    };
157 
158    CASE(test_2, {
159       agx_swap(b, agx_register(0, AGX_SIZE_16), agx_register(1, AGX_SIZE_16));
160    });
161 }
162 
TEST_F(LowerParallelCopy,Cycle3)163 TEST_F(LowerParallelCopy, Cycle3)
164 {
165    struct agx_copy test[] = {
166       {.dest = 0, .src = agx_register(1, AGX_SIZE_16)},
167       {.dest = 1, .src = agx_register(2, AGX_SIZE_16)},
168       {.dest = 2, .src = agx_register(0, AGX_SIZE_16)},
169    };
170 
171    CASE(test, {
172       agx_swap(b, agx_register(0, AGX_SIZE_16), agx_register(1, AGX_SIZE_16));
173       agx_swap(b, agx_register(1, AGX_SIZE_16), agx_register(2, AGX_SIZE_16));
174    });
175 }
176 
TEST_F(LowerParallelCopy,Immediate64)177 TEST_F(LowerParallelCopy, Immediate64)
178 {
179    agx_index imm = agx_immediate(10);
180    imm.size = AGX_SIZE_64;
181 
182    struct agx_copy test_1[] = {
183       {.dest = 4, .src = imm},
184    };
185 
186    CASE(test_1, {
187       agx_mov_imm_to(b, agx_register(4, AGX_SIZE_32), 10);
188       agx_mov_imm_to(b, agx_register(6, AGX_SIZE_32), 0);
189    });
190 }
191 
192 /* Test case from Hack et al */
TEST_F(LowerParallelCopy,TwoSwaps)193 TEST_F(LowerParallelCopy, TwoSwaps)
194 {
195    struct agx_copy test[] = {
196       {.dest = 4, .src = agx_register(2, AGX_SIZE_32)},
197       {.dest = 6, .src = agx_register(4, AGX_SIZE_32)},
198       {.dest = 2, .src = agx_register(6, AGX_SIZE_32)},
199       {.dest = 8, .src = agx_register(8, AGX_SIZE_32)},
200    };
201 
202    CASE(test, {
203       agx_swap(b, agx_register(4, AGX_SIZE_32), agx_register(2, AGX_SIZE_32));
204       agx_swap(b, agx_register(6, AGX_SIZE_32), agx_register(2, AGX_SIZE_32));
205    });
206 }
207 
TEST_F(LowerParallelCopy,VectorizeAlignedHalfRegs)208 TEST_F(LowerParallelCopy, VectorizeAlignedHalfRegs)
209 {
210    struct agx_copy test[] = {
211       {.dest = 0, .src = agx_register(10, AGX_SIZE_16)},
212       {.dest = 1, .src = agx_register(11, AGX_SIZE_16)},
213       {.dest = 2, .src = agx_uniform(8, AGX_SIZE_16)},
214       {.dest = 3, .src = agx_uniform(9, AGX_SIZE_16)},
215    };
216 
217    CASE(test, {
218       agx_mov_to(b, agx_register(0, AGX_SIZE_32),
219                  agx_register(10, AGX_SIZE_32));
220       agx_mov_to(b, agx_register(2, AGX_SIZE_32), agx_uniform(8, AGX_SIZE_32));
221    });
222 }
223 
TEST_F(LowerParallelCopy,StackCopies)224 TEST_F(LowerParallelCopy, StackCopies)
225 {
226    struct agx_copy test[] = {
227       {.dest = 21, .dest_mem = true, .src = agx_register(20, AGX_SIZE_16)},
228       {.dest = 22, .dest_mem = true, .src = agx_register(22, AGX_SIZE_32)},
229       {.dest = 0, .src = agx_memory_register(10, AGX_SIZE_16)},
230       {.dest = 1, .src = agx_memory_register(11, AGX_SIZE_16)},
231       {.dest = 0, .dest_mem = true, .src = agx_memory_register(12, AGX_SIZE_16)},
232       {.dest = 1, .dest_mem = true, .src = agx_memory_register(13, AGX_SIZE_16)},
233       {.dest = 2,
234        .dest_mem = true,
235        .src = agx_memory_register(804, AGX_SIZE_32)},
236       {.dest = 804,
237        .dest_mem = true,
238        .src = agx_memory_register(2, AGX_SIZE_32)},
239       {.dest = 807,
240        .dest_mem = true,
241        .src = agx_memory_register(808, AGX_SIZE_16)},
242       {.dest = 808,
243        .dest_mem = true,
244        .src = agx_memory_register(807, AGX_SIZE_16)},
245    };
246 
247    CASE(test, {
248       /* Vectorized fill */
249       agx_mov_to(b, agx_register(0, AGX_SIZE_32),
250                  agx_memory_register(10, AGX_SIZE_32));
251 
252       /* Regular spills */
253       agx_mov_to(b, agx_memory_register(21, AGX_SIZE_16),
254                  agx_register(20, AGX_SIZE_16));
255       agx_mov_to(b, agx_memory_register(22, AGX_SIZE_32),
256                  agx_register(22, AGX_SIZE_32));
257 
258       /* Vectorized stack->stack copy */
259       agx_mov_to(b, agx_register(2, AGX_SIZE_32),
260                  agx_memory_register(12, AGX_SIZE_32));
261 
262       agx_mov_to(b, agx_memory_register(0, AGX_SIZE_32),
263                  agx_register(2, AGX_SIZE_32));
264 
265       /* Stack swap: 32-bit */
266       agx_index temp1 = agx_register(4, AGX_SIZE_32);
267       agx_index temp2 = agx_register(6, AGX_SIZE_32);
268       agx_index spilled_gpr_vec2 = agx_register(0, AGX_SIZE_32);
269       spilled_gpr_vec2.channels_m1++;
270 
271       agx_mov_to(b, temp1, agx_memory_register(2, AGX_SIZE_32));
272       agx_mov_to(b, temp2, agx_memory_register(804, AGX_SIZE_32));
273       agx_mov_to(b, agx_memory_register(804, AGX_SIZE_32), temp1);
274       agx_mov_to(b, agx_memory_register(2, AGX_SIZE_32), temp2);
275 
276       /* Stack swap: 16-bit */
277       spilled_gpr_vec2.size = AGX_SIZE_16;
278       temp1.size = AGX_SIZE_16;
279       temp2.size = AGX_SIZE_16;
280 
281       agx_mov_to(b, temp1, agx_memory_register(807, AGX_SIZE_16));
282       agx_mov_to(b, temp2, agx_memory_register(808, AGX_SIZE_16));
283       agx_mov_to(b, agx_memory_register(808, AGX_SIZE_16), temp1);
284       agx_mov_to(b, agx_memory_register(807, AGX_SIZE_16), temp2);
285    });
286 }
287 
288 #if 0
289 TEST_F(LowerParallelCopy, LooksLikeASwap) {
290    struct agx_copy test[] = {
291         { .dest = 0, .src = agx_register(2, AGX_SIZE_32) },
292         { .dest = 2, .src = agx_register(0, AGX_SIZE_32) },
293         { .dest = 4, .src = agx_register(2, AGX_SIZE_32) },
294    };
295 
296    CASE(test, {
297          agx_mov_to(b, agx_register(4, AGX_SIZE_32), agx_register(2, AGX_SIZE_32));
298          agx_mov_to(b, agx_register(2, AGX_SIZE_32), agx_register(0, AGX_SIZE_32));
299          agx_mov_to(b, agx_register(0, AGX_SIZE_32), agx_register(4, AGX_SIZE_32));
300    });
301 }
302 #endif
303