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/remove_phonies.h"
16
17 #include <memory>
18 #include <utility>
19 #include <vector>
20
21 #include "src/transform/test_helper.h"
22
23 namespace tint {
24 namespace transform {
25 namespace {
26
27 using RemovePhoniesTest = TransformTest;
28
TEST_F(RemovePhoniesTest,EmptyModule)29 TEST_F(RemovePhoniesTest, EmptyModule) {
30 auto* src = "";
31 auto* expect = "";
32
33 auto got = Run<RemovePhonies>(src);
34
35 EXPECT_EQ(expect, str(got));
36 }
37
TEST_F(RemovePhoniesTest,NoSideEffects)38 TEST_F(RemovePhoniesTest, NoSideEffects) {
39 auto* src = R"(
40 [[group(0), binding(0)]] var t : texture_2d<f32>;
41
42 fn f() {
43 var v : i32;
44 _ = &v;
45 _ = 1;
46 _ = 1 + 2;
47 _ = t;
48 _ = u32(3.0);
49 _ = f32(i32(4u));
50 _ = vec2<f32>(5.0);
51 _ = vec3<i32>(6, 7, 8);
52 _ = mat2x2<f32>(9.0, 10.0, 11.0, 12.0);
53 }
54 )";
55
56 auto* expect = R"(
57 [[group(0), binding(0)]] var t : texture_2d<f32>;
58
59 fn f() {
60 var v : i32;
61 }
62 )";
63
64 auto got = Run<RemovePhonies>(src);
65
66 EXPECT_EQ(expect, str(got));
67 }
68
TEST_F(RemovePhoniesTest,SingleSideEffects)69 TEST_F(RemovePhoniesTest, SingleSideEffects) {
70 auto* src = R"(
71 fn neg(a : i32) -> i32 {
72 return -(a);
73 }
74
75 fn add(a : i32, b : i32) -> i32 {
76 return (a + b);
77 }
78
79 fn f() {
80 _ = neg(1);
81 _ = add(2, 3);
82 _ = add(neg(4), neg(5));
83 _ = u32(neg(6));
84 _ = f32(add(7, 8));
85 _ = vec2<f32>(f32(neg(9)));
86 _ = vec3<i32>(1, neg(10), 3);
87 _ = mat2x2<f32>(1.0, f32(add(11, 12)), 3.0, 4.0);
88 }
89 )";
90
91 auto* expect = R"(
92 fn neg(a : i32) -> i32 {
93 return -(a);
94 }
95
96 fn add(a : i32, b : i32) -> i32 {
97 return (a + b);
98 }
99
100 fn f() {
101 neg(1);
102 add(2, 3);
103 add(neg(4), neg(5));
104 neg(6);
105 add(7, 8);
106 neg(9);
107 neg(10);
108 add(11, 12);
109 }
110 )";
111
112 auto got = Run<RemovePhonies>(src);
113
114 EXPECT_EQ(expect, str(got));
115 }
116
TEST_F(RemovePhoniesTest,MultipleSideEffects)117 TEST_F(RemovePhoniesTest, MultipleSideEffects) {
118 auto* src = R"(
119 fn neg(a : i32) -> i32 {
120 return -(a);
121 }
122
123 fn add(a : i32, b : i32) -> i32 {
124 return (a + b);
125 }
126
127 fn xor(a : u32, b : u32) -> u32 {
128 return (a ^ b);
129 }
130
131 fn f() {
132 _ = (1 + add(2 + add(3, 4), 5)) * add(6, 7) * neg(8);
133 _ = add(9, neg(10)) + neg(11);
134 _ = xor(12u, 13u) + xor(14u, 15u);
135 _ = neg(16) / neg(17) + add(18, 19);
136 }
137 )";
138
139 auto* expect = R"(
140 fn neg(a : i32) -> i32 {
141 return -(a);
142 }
143
144 fn add(a : i32, b : i32) -> i32 {
145 return (a + b);
146 }
147
148 fn xor(a : u32, b : u32) -> u32 {
149 return (a ^ b);
150 }
151
152 fn phony_sink(p0 : i32, p1 : i32, p2 : i32) {
153 }
154
155 fn phony_sink_1(p0 : i32, p1 : i32) {
156 }
157
158 fn phony_sink_2(p0 : u32, p1 : u32) {
159 }
160
161 fn f() {
162 phony_sink(add((2 + add(3, 4)), 5), add(6, 7), neg(8));
163 phony_sink_1(add(9, neg(10)), neg(11));
164 phony_sink_2(xor(12u, 13u), xor(14u, 15u));
165 phony_sink(neg(16), neg(17), add(18, 19));
166 }
167 )";
168
169 auto got = Run<RemovePhonies>(src);
170
171 EXPECT_EQ(expect, str(got));
172 }
173
TEST_F(RemovePhoniesTest,ForLoop)174 TEST_F(RemovePhoniesTest, ForLoop) {
175 auto* src = R"(
176 [[block]]
177 struct S {
178 arr : array<i32>;
179 };
180
181 [[group(0), binding(0)]] var<storage, read_write> s : S;
182
183 fn x() -> i32 {
184 return 0;
185 }
186
187 fn y() -> i32 {
188 return 0;
189 }
190
191 fn z() -> i32 {
192 return 0;
193 }
194
195 fn f() {
196 for (_ = &s.arr; ;_ = &s.arr) {
197 break;
198 }
199 for (_ = x(); ;_ = y() + z()) {
200 break;
201 }
202 }
203 )";
204
205 auto* expect = R"(
206 [[block]]
207 struct S {
208 arr : array<i32>;
209 };
210
211 [[group(0), binding(0)]] var<storage, read_write> s : S;
212
213 fn x() -> i32 {
214 return 0;
215 }
216
217 fn y() -> i32 {
218 return 0;
219 }
220
221 fn z() -> i32 {
222 return 0;
223 }
224
225 fn phony_sink(p0 : i32, p1 : i32) {
226 }
227
228 fn f() {
229 for(; ; ) {
230 break;
231 }
232 for(x(); ; phony_sink(y(), z())) {
233 break;
234 }
235 }
236 )";
237
238 auto got = Run<RemovePhonies>(src);
239
240 EXPECT_EQ(expect, str(got));
241 }
242
243 } // namespace
244 } // namespace transform
245 } // namespace tint
246