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