• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 Collabora, Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  */
23 
24 #include "agx_test.h"
25 
26 #include <gtest/gtest.h>
27 
28 #define CASE(copies, expected) do { \
29    agx_builder *A = agx_test_builder(mem_ctx); \
30    agx_builder *B = agx_test_builder(mem_ctx); \
31    \
32    agx_emit_parallel_copies(A, copies, ARRAY_SIZE(copies)); \
33    \
34    { \
35       agx_builder *b = B; \
36       expected; \
37    } \
38    \
39    ASSERT_SHADER_EQUAL(A->shader, B->shader); \
40 } while(0)
41 
42 static inline void
xor_swap(agx_builder * b,agx_index x,agx_index y)43 xor_swap(agx_builder *b, agx_index x, agx_index y)
44 {
45    agx_xor_to(b, x, x, y);
46    agx_xor_to(b, y, x, y);
47    agx_xor_to(b, x, x, y);
48 }
49 
50 class LowerParallelCopy : public testing::Test {
51 protected:
LowerParallelCopy()52    LowerParallelCopy() {
53       mem_ctx = ralloc_context(NULL);
54    }
55 
~LowerParallelCopy()56    ~LowerParallelCopy() {
57       ralloc_free(mem_ctx);
58    }
59 
60    void *mem_ctx;
61 };
62 
TEST_F(LowerParallelCopy,UnrelatedCopies)63 TEST_F(LowerParallelCopy, UnrelatedCopies) {
64    struct agx_copy test_1[] = {
65         { .dest = 0, .src = 2, .size = AGX_SIZE_32 },
66         { .dest = 4, .src = 6, .size = AGX_SIZE_32 },
67    };
68 
69    CASE(test_1, {
70         agx_mov_to(b, agx_register(0, AGX_SIZE_32), agx_register(2, AGX_SIZE_32));
71         agx_mov_to(b, agx_register(4, AGX_SIZE_32), agx_register(6, AGX_SIZE_32));
72    });
73 
74    struct agx_copy test_2[] = {
75         { .dest = 0, .src = 1, .size = AGX_SIZE_16 },
76         { .dest = 4, .src = 5, .size = AGX_SIZE_16 },
77    };
78 
79    CASE(test_2, {
80         agx_mov_to(b, agx_register(0, AGX_SIZE_16), agx_register(1, AGX_SIZE_16));
81         agx_mov_to(b, agx_register(4, AGX_SIZE_16), agx_register(5, AGX_SIZE_16));
82    });
83 }
84 
TEST_F(LowerParallelCopy,RelatedSource)85 TEST_F(LowerParallelCopy, RelatedSource)
86 {
87    struct agx_copy test_1[] = {
88         { .dest = 0, .src = 2, .size = AGX_SIZE_32 },
89         { .dest = 4, .src = 2, .size = AGX_SIZE_32 },
90    };
91 
92    CASE(test_1, {
93         agx_mov_to(b, agx_register(0, AGX_SIZE_32), agx_register(2, AGX_SIZE_32));
94         agx_mov_to(b, agx_register(4, AGX_SIZE_32), agx_register(2, AGX_SIZE_32));
95    });
96 
97    struct agx_copy test_2[] = {
98         { .dest = 0, .src = 1, .size = AGX_SIZE_16 },
99         { .dest = 4, .src = 1, .size = AGX_SIZE_16 },
100    };
101 
102    CASE(test_2, {
103         agx_mov_to(b, agx_register(0, AGX_SIZE_16), agx_register(1, AGX_SIZE_16));
104         agx_mov_to(b, agx_register(4, AGX_SIZE_16), agx_register(1, AGX_SIZE_16));
105    });
106 }
107 
TEST_F(LowerParallelCopy,DependentCopies)108 TEST_F(LowerParallelCopy, DependentCopies)
109 {
110    struct agx_copy test_1[] = {
111         { .dest = 0, .src = 2, .size = AGX_SIZE_32 },
112         { .dest = 4, .src = 0, .size = AGX_SIZE_32 },
113    };
114 
115    CASE(test_1, {
116         agx_mov_to(b, agx_register(4, AGX_SIZE_32), agx_register(0, AGX_SIZE_32));
117         agx_mov_to(b, agx_register(0, AGX_SIZE_32), agx_register(2, AGX_SIZE_32));
118    });
119 
120    struct agx_copy test_2[] = {
121         { .dest = 0, .src = 1, .size = AGX_SIZE_16 },
122         { .dest = 4, .src = 0, .size = AGX_SIZE_16 },
123    };
124 
125    CASE(test_2, {
126         agx_mov_to(b, agx_register(4, AGX_SIZE_16), agx_register(0, AGX_SIZE_16));
127         agx_mov_to(b, agx_register(0, AGX_SIZE_16), agx_register(1, AGX_SIZE_16));
128    });
129 }
130 
TEST_F(LowerParallelCopy,ManyDependentCopies)131 TEST_F(LowerParallelCopy, ManyDependentCopies)
132 {
133    struct agx_copy test_1[] = {
134         { .dest = 0, .src = 2, .size = AGX_SIZE_32 },
135         { .dest = 4, .src = 0, .size = AGX_SIZE_32 },
136         { .dest = 8, .src = 6, .size = AGX_SIZE_32 },
137         { .dest = 6, .src = 4, .size = AGX_SIZE_32 },
138    };
139 
140    CASE(test_1, {
141         agx_mov_to(b, agx_register(8, AGX_SIZE_32), agx_register(6, AGX_SIZE_32));
142         agx_mov_to(b, agx_register(6, AGX_SIZE_32), agx_register(4, AGX_SIZE_32));
143         agx_mov_to(b, agx_register(4, AGX_SIZE_32), agx_register(0, AGX_SIZE_32));
144         agx_mov_to(b, agx_register(0, AGX_SIZE_32), agx_register(2, AGX_SIZE_32));
145    });
146 
147    struct agx_copy test_2[] = {
148         { .dest = 0, .src = 1, .size = AGX_SIZE_16 },
149         { .dest = 2, .src = 0, .size = AGX_SIZE_16 },
150         { .dest = 4, .src = 3, .size = AGX_SIZE_16 },
151         { .dest = 3, .src = 2, .size = AGX_SIZE_16 },
152    };
153 
154    CASE(test_2, {
155         agx_mov_to(b, agx_register(4, AGX_SIZE_16), agx_register(3, AGX_SIZE_16));
156         agx_mov_to(b, agx_register(3, AGX_SIZE_16), agx_register(2, AGX_SIZE_16));
157         agx_mov_to(b, agx_register(2, AGX_SIZE_16), agx_register(0, AGX_SIZE_16));
158         agx_mov_to(b, agx_register(0, AGX_SIZE_16), agx_register(1, AGX_SIZE_16));
159    });
160 }
161 
TEST_F(LowerParallelCopy,Swap)162 TEST_F(LowerParallelCopy, Swap) {
163    struct agx_copy test_1[] = {
164         { .dest = 0, .src = 2, .size = AGX_SIZE_32 },
165         { .dest = 2, .src = 0, .size = AGX_SIZE_32 },
166    };
167 
168    CASE(test_1, {
169         xor_swap(b, agx_register(0, AGX_SIZE_32), agx_register(2, AGX_SIZE_32));
170    });
171 
172    struct agx_copy test_2[] = {
173         { .dest = 0, .src = 1, .size = AGX_SIZE_16 },
174         { .dest = 1, .src = 0, .size = AGX_SIZE_16 },
175    };
176 
177    CASE(test_2, {
178         xor_swap(b, agx_register(0, AGX_SIZE_16), agx_register(1, AGX_SIZE_16));
179    });
180 }
181 
TEST_F(LowerParallelCopy,Cycle3)182 TEST_F(LowerParallelCopy, Cycle3) {
183    struct agx_copy test[] = {
184         { .dest = 0, .src = 1, .size = AGX_SIZE_16 },
185         { .dest = 1, .src = 2, .size = AGX_SIZE_16 },
186         { .dest = 2, .src = 0, .size = AGX_SIZE_16 },
187    };
188 
189    /* XXX: requires 6 instructions. if we had a temp free, could do it in 4 */
190    CASE(test, {
191         xor_swap(b, agx_register(0, AGX_SIZE_16), agx_register(1, AGX_SIZE_16));
192         xor_swap(b, agx_register(1, AGX_SIZE_16), agx_register(2, AGX_SIZE_16));
193    });
194 }
195 
196 /* Test case from Hack et al */
TEST_F(LowerParallelCopy,TwoSwaps)197 TEST_F(LowerParallelCopy, TwoSwaps) {
198    struct agx_copy test[] = {
199         { .dest = 4, .src = 2, .size = AGX_SIZE_32 },
200         { .dest = 6, .src = 4, .size = AGX_SIZE_32 },
201         { .dest = 2, .src = 6, .size = AGX_SIZE_32 },
202         { .dest = 8, .src = 8, .size = AGX_SIZE_32 },
203    };
204 
205    CASE(test, {
206         xor_swap(b, agx_register(4, AGX_SIZE_32), agx_register(2, AGX_SIZE_32));
207         xor_swap(b, agx_register(6, AGX_SIZE_32), agx_register(2, AGX_SIZE_32));
208    });
209 }
210 
211 #if 0
212 TEST_F(LowerParallelCopy, LooksLikeASwap) {
213    struct agx_copy test[] = {
214         { .dest = 0, .src = 2, .size = AGX_SIZE_32 },
215         { .dest = 2, .src = 0, .size = AGX_SIZE_32 },
216         { .dest = 4, .src = 2, .size = AGX_SIZE_32 },
217    };
218 
219    CASE(test, {
220          agx_mov_to(b, agx_register(4, AGX_SIZE_32), agx_register(2, AGX_SIZE_32));
221          agx_mov_to(b, agx_register(2, AGX_SIZE_32), agx_register(0, AGX_SIZE_32));
222          agx_mov_to(b, agx_register(0, AGX_SIZE_32), agx_register(4, AGX_SIZE_32));
223    });
224 }
225 #endif
226