• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 The Tint Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "src/transform/simplify_pointers.h"
16 
17 #include "src/transform/test_helper.h"
18 #include "src/transform/unshadow.h"
19 
20 namespace tint {
21 namespace transform {
22 namespace {
23 
24 using SimplifyPointersTest = TransformTest;
25 
TEST_F(SimplifyPointersTest,Error_MissingSimplifyPointers)26 TEST_F(SimplifyPointersTest, Error_MissingSimplifyPointers) {
27   auto* src = "";
28 
29   auto* expect =
30       "error: tint::transform::SimplifyPointers depends on "
31       "tint::transform::Unshadow but the dependency was not run";
32 
33   auto got = Run<SimplifyPointers>(src);
34 
35   EXPECT_EQ(expect, str(got));
36 }
37 
TEST_F(SimplifyPointersTest,EmptyModule)38 TEST_F(SimplifyPointersTest, EmptyModule) {
39   auto* src = "";
40   auto* expect = "";
41 
42   auto got = Run<Unshadow, SimplifyPointers>(src);
43 
44   EXPECT_EQ(expect, str(got));
45 }
46 
TEST_F(SimplifyPointersTest,FoldPointer)47 TEST_F(SimplifyPointersTest, FoldPointer) {
48   auto* src = R"(
49 fn f() {
50   var v : i32;
51   let p : ptr<function, i32> = &v;
52   let x : i32 = *p;
53 }
54 )";
55 
56   auto* expect = R"(
57 fn f() {
58   var v : i32;
59   let x : i32 = v;
60 }
61 )";
62 
63   auto got = Run<Unshadow, SimplifyPointers>(src);
64 
65   EXPECT_EQ(expect, str(got));
66 }
67 
TEST_F(SimplifyPointersTest,AddressOfDeref)68 TEST_F(SimplifyPointersTest, AddressOfDeref) {
69   auto* src = R"(
70 fn f() {
71   var v : i32;
72   let p : ptr<function, i32> = &(v);
73   let x : ptr<function, i32> = &(*(p));
74   let y : ptr<function, i32> = &(*(&(*(p))));
75   let z : ptr<function, i32> = &(*(&(*(&(*(&(*(p))))))));
76   var a = *x;
77   var b = *y;
78   var c = *z;
79 }
80 )";
81 
82   auto* expect = R"(
83 fn f() {
84   var v : i32;
85   var a = v;
86   var b = v;
87   var c = v;
88 }
89 )";
90 
91   auto got = Run<Unshadow, SimplifyPointers>(src);
92 
93   EXPECT_EQ(expect, str(got));
94 }
95 
TEST_F(SimplifyPointersTest,DerefAddressOf)96 TEST_F(SimplifyPointersTest, DerefAddressOf) {
97   auto* src = R"(
98 fn f() {
99   var v : i32;
100   let x : i32 = *(&(v));
101   let y : i32 = *(&(*(&(v))));
102   let z : i32 = *(&(*(&(*(&(*(&(v))))))));
103 }
104 )";
105 
106   auto* expect = R"(
107 fn f() {
108   var v : i32;
109   let x : i32 = v;
110   let y : i32 = v;
111   let z : i32 = v;
112 }
113 )";
114 
115   auto got = Run<Unshadow, SimplifyPointers>(src);
116 
117   EXPECT_EQ(expect, str(got));
118 }
119 
TEST_F(SimplifyPointersTest,ComplexChain)120 TEST_F(SimplifyPointersTest, ComplexChain) {
121   auto* src = R"(
122 fn f() {
123   var a : array<mat4x4<f32>, 4>;
124   let ap : ptr<function, array<mat4x4<f32>, 4>> = &a;
125   let mp : ptr<function, mat4x4<f32>> = &(*ap)[3];
126   let vp : ptr<function, vec4<f32>> = &(*mp)[2];
127   let v : vec4<f32> = *vp;
128 }
129 )";
130 
131   auto* expect = R"(
132 fn f() {
133   var a : array<mat4x4<f32>, 4>;
134   let v : vec4<f32> = a[3][2];
135 }
136 )";
137 
138   auto got = Run<Unshadow, SimplifyPointers>(src);
139 
140   EXPECT_EQ(expect, str(got));
141 }
142 
TEST_F(SimplifyPointersTest,SavedVars)143 TEST_F(SimplifyPointersTest, SavedVars) {
144   auto* src = R"(
145 struct S {
146   i : i32;
147 };
148 
149 fn arr() {
150   var a : array<S, 2>;
151   var i : i32 = 0;
152   var j : i32 = 0;
153   let p : ptr<function, i32> = &a[i + j].i;
154   i = 2;
155   *p = 4;
156 }
157 
158 fn matrix() {
159   var m : mat3x3<f32>;
160   var i : i32 = 0;
161   var j : i32 = 0;
162   let p : ptr<function, vec3<f32>> = &m[i + j];
163   i = 2;
164   *p = vec3<f32>(4.0, 5.0, 6.0);
165 }
166 )";
167 
168   auto* expect = R"(
169 struct S {
170   i : i32;
171 };
172 
173 fn arr() {
174   var a : array<S, 2>;
175   var i : i32 = 0;
176   var j : i32 = 0;
177   let p_save = (i + j);
178   i = 2;
179   a[p_save].i = 4;
180 }
181 
182 fn matrix() {
183   var m : mat3x3<f32>;
184   var i : i32 = 0;
185   var j : i32 = 0;
186   let p_save_1 = (i + j);
187   i = 2;
188   m[p_save_1] = vec3<f32>(4.0, 5.0, 6.0);
189 }
190 )";
191 
192   auto got = Run<Unshadow, SimplifyPointers>(src);
193 
194   EXPECT_EQ(expect, str(got));
195 }
196 
TEST_F(SimplifyPointersTest,DontSaveLiterals)197 TEST_F(SimplifyPointersTest, DontSaveLiterals) {
198   auto* src = R"(
199 fn f() {
200   var arr : array<i32, 2>;
201   let p1 : ptr<function, i32> = &arr[1];
202   *p1 = 4;
203 }
204 )";
205 
206   auto* expect = R"(
207 fn f() {
208   var arr : array<i32, 2>;
209   arr[1] = 4;
210 }
211 )";
212 
213   auto got = Run<Unshadow, SimplifyPointers>(src);
214 
215   EXPECT_EQ(expect, str(got));
216 }
217 
TEST_F(SimplifyPointersTest,SavedVarsChain)218 TEST_F(SimplifyPointersTest, SavedVarsChain) {
219   auto* src = R"(
220 fn f() {
221   var arr : array<array<i32, 2>, 2>;
222   let i : i32 = 0;
223   let j : i32 = 1;
224   let p : ptr<function, array<i32, 2>> = &arr[i];
225   let q : ptr<function, i32> = &(*p)[j];
226   *q = 12;
227 }
228 )";
229 
230   auto* expect = R"(
231 fn f() {
232   var arr : array<array<i32, 2>, 2>;
233   let i : i32 = 0;
234   let j : i32 = 1;
235   let p_save = i;
236   let q_save = j;
237   arr[p_save][q_save] = 12;
238 }
239 )";
240 
241   auto got = Run<Unshadow, SimplifyPointers>(src);
242 
243   EXPECT_EQ(expect, str(got));
244 }
245 
TEST_F(SimplifyPointersTest,ForLoopInit)246 TEST_F(SimplifyPointersTest, ForLoopInit) {
247   auto* src = R"(
248 fn foo() -> i32 {
249   return 1;
250 }
251 
252 [[stage(fragment)]]
253 fn main() {
254   var arr = array<f32, 4>();
255   for (let a = &arr[foo()]; ;) {
256     let x = *a;
257   }
258 }
259 )";
260 
261   auto* expect = R"(
262 fn foo() -> i32 {
263   return 1;
264 }
265 
266 [[stage(fragment)]]
267 fn main() {
268   var arr = array<f32, 4>();
269   let a_save = foo();
270   for(; ; ) {
271     let x = arr[a_save];
272   }
273 }
274 )";
275 
276   auto got = Run<Unshadow, SimplifyPointers>(src);
277 
278   EXPECT_EQ(expect, str(got));
279 }
280 
TEST_F(SimplifyPointersTest,MultiSavedVarsInSinglePtrLetExpr)281 TEST_F(SimplifyPointersTest, MultiSavedVarsInSinglePtrLetExpr) {
282   auto* src = R"(
283 fn x() -> i32 {
284   return 1;
285 }
286 
287 fn y() -> i32 {
288   return 1;
289 }
290 
291 fn z() -> i32 {
292   return 1;
293 }
294 
295 struct Inner {
296   a : array<i32, 2>;
297 };
298 
299 struct Outer {
300   a : array<Inner, 2>;
301 };
302 
303 fn f() {
304   var arr : array<Outer, 2>;
305   let p : ptr<function, i32> = &arr[x()].a[y()].a[z()];
306   *p = 1;
307   *p = 2;
308 }
309 )";
310 
311   auto* expect = R"(
312 fn x() -> i32 {
313   return 1;
314 }
315 
316 fn y() -> i32 {
317   return 1;
318 }
319 
320 fn z() -> i32 {
321   return 1;
322 }
323 
324 struct Inner {
325   a : array<i32, 2>;
326 };
327 
328 struct Outer {
329   a : array<Inner, 2>;
330 };
331 
332 fn f() {
333   var arr : array<Outer, 2>;
334   let p_save = x();
335   let p_save_1 = y();
336   let p_save_2 = z();
337   arr[p_save].a[p_save_1].a[p_save_2] = 1;
338   arr[p_save].a[p_save_1].a[p_save_2] = 2;
339 }
340 )";
341 
342   auto got = Run<Unshadow, SimplifyPointers>(src);
343 
344   EXPECT_EQ(expect, str(got));
345 }
346 
TEST_F(SimplifyPointersTest,ShadowPointer)347 TEST_F(SimplifyPointersTest, ShadowPointer) {
348   auto* src = R"(
349 var<private> a : array<i32, 2>;
350 
351 [[stage(compute), workgroup_size(1)]]
352 fn main() {
353   let x = &a;
354   var a : i32 = (*x)[0];
355   {
356     var a : i32 = (*x)[1];
357   }
358 }
359 )";
360 
361   auto* expect = R"(
362 var<private> a : array<i32, 2>;
363 
364 [[stage(compute), workgroup_size(1)]]
365 fn main() {
366   var a_1 : i32 = a[0];
367   {
368     var a_2 : i32 = a[1];
369   }
370 }
371 )";
372 
373   auto got = Run<Unshadow, SimplifyPointers>(src);
374 
375   EXPECT_EQ(expect, str(got));
376 }
377 
378 }  // namespace
379 }  // namespace transform
380 }  // namespace tint
381