1 // Copyright (c) 2017 Google Inc.
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 <string>
16
17 #include "test/opt/pass_fixture.h"
18 #include "test/opt/pass_utils.h"
19
20 namespace spvtools {
21 namespace opt {
22 namespace {
23
24 using CFGCleanupTest = PassTest<::testing::Test>;
25
TEST_F(CFGCleanupTest,RemoveUnreachableBlocks)26 TEST_F(CFGCleanupTest, RemoveUnreachableBlocks) {
27 const std::string declarations = R"(OpCapability Shader
28 %1 = OpExtInstImport "GLSL.std.450"
29 OpMemoryModel Logical GLSL450
30 OpEntryPoint Fragment %main "main" %inf %outf4
31 OpExecutionMode %main OriginUpperLeft
32 OpSource GLSL 450
33 OpName %main "main"
34 OpName %inf "inf"
35 OpName %outf4 "outf4"
36 OpDecorate %inf Location 0
37 OpDecorate %outf4 Location 0
38 %void = OpTypeVoid
39 %6 = OpTypeFunction %void
40 %float = OpTypeFloat 32
41 %_ptr_Input_float = OpTypePointer Input %float
42 %inf = OpVariable %_ptr_Input_float Input
43 %float_2 = OpConstant %float 2
44 %bool = OpTypeBool
45 %v4float = OpTypeVector %float 4
46 %_ptr_Output_v4float = OpTypePointer Output %v4float
47 %outf4 = OpVariable %_ptr_Output_v4float Output
48 %float_n0_5 = OpConstant %float -0.5
49 )";
50
51 const std::string body_before = R"(%main = OpFunction %void None %6
52 %14 = OpLabel
53 OpBranch %18
54 %19 = OpLabel
55 %20 = OpLoad %float %inf
56 %21 = OpCompositeConstruct %v4float %20 %20 %20 %20
57 OpStore %outf4 %21
58 OpBranch %17
59 %18 = OpLabel
60 %22 = OpLoad %float %inf
61 %23 = OpFAdd %float %22 %float_n0_5
62 %24 = OpCompositeConstruct %v4float %23 %23 %23 %23
63 OpStore %outf4 %24
64 OpBranch %17
65 %17 = OpLabel
66 OpReturn
67 OpFunctionEnd
68 )";
69
70 const std::string body_after = R"(%main = OpFunction %void None %6
71 %14 = OpLabel
72 OpBranch %15
73 %15 = OpLabel
74 %20 = OpLoad %float %inf
75 %21 = OpFAdd %float %20 %float_n0_5
76 %22 = OpCompositeConstruct %v4float %21 %21 %21 %21
77 OpStore %outf4 %22
78 OpBranch %19
79 %19 = OpLabel
80 OpReturn
81 OpFunctionEnd
82 )";
83
84 SinglePassRunAndCheck<CFGCleanupPass>(declarations + body_before,
85 declarations + body_after, true, true);
86 }
87
TEST_F(CFGCleanupTest,RemoveDecorations)88 TEST_F(CFGCleanupTest, RemoveDecorations) {
89 const std::string before = R"(
90 OpCapability Shader
91 %1 = OpExtInstImport "GLSL.std.450"
92 OpMemoryModel Logical GLSL450
93 OpEntryPoint Fragment %main "main"
94 OpExecutionMode %main OriginUpperLeft
95 OpName %main "main"
96 OpName %x "x"
97 OpName %dead "dead"
98 OpDecorate %x RelaxedPrecision
99 OpDecorate %dead RelaxedPrecision
100 %void = OpTypeVoid
101 %6 = OpTypeFunction %void
102 %float = OpTypeFloat 32
103 %_ptr_Function_float = OpTypePointer Function %float
104 %float_2 = OpConstant %float 2
105 %float_4 = OpConstant %float 4
106
107 %main = OpFunction %void None %6
108 %14 = OpLabel
109 %x = OpVariable %_ptr_Function_float Function
110 OpBranch %18
111 %19 = OpLabel
112 %dead = OpVariable %_ptr_Function_float Function
113 OpStore %dead %float_2
114 OpBranch %17
115 %18 = OpLabel
116 OpStore %x %float_4
117 OpBranch %17
118 %17 = OpLabel
119 OpReturn
120 OpFunctionEnd
121 )";
122
123 const std::string after = R"(OpCapability Shader
124 %1 = OpExtInstImport "GLSL.std.450"
125 OpMemoryModel Logical GLSL450
126 OpEntryPoint Fragment %main "main"
127 OpExecutionMode %main OriginUpperLeft
128 OpName %main "main"
129 OpName %x "x"
130 OpDecorate %x RelaxedPrecision
131 %void = OpTypeVoid
132 %6 = OpTypeFunction %void
133 %float = OpTypeFloat 32
134 %_ptr_Function_float = OpTypePointer Function %float
135 %float_2 = OpConstant %float 2
136 %float_4 = OpConstant %float 4
137 %main = OpFunction %void None %6
138 %11 = OpLabel
139 %x = OpVariable %_ptr_Function_float Function
140 OpBranch %12
141 %12 = OpLabel
142 OpStore %x %float_4
143 OpBranch %14
144 %14 = OpLabel
145 OpReturn
146 OpFunctionEnd
147 )";
148
149 SinglePassRunAndCheck<CFGCleanupPass>(before, after, true, true);
150 }
151
TEST_F(CFGCleanupTest,UpdatePhis)152 TEST_F(CFGCleanupTest, UpdatePhis) {
153 const std::string before = R"(
154 OpCapability Shader
155 %1 = OpExtInstImport "GLSL.std.450"
156 OpMemoryModel Logical GLSL450
157 OpEntryPoint Fragment %main "main" %y %outparm
158 OpExecutionMode %main OriginUpperLeft
159 OpName %main "main"
160 OpName %y "y"
161 OpName %outparm "outparm"
162 OpDecorate %y Flat
163 OpDecorate %y Location 0
164 OpDecorate %outparm Location 0
165 %void = OpTypeVoid
166 %3 = OpTypeFunction %void
167 %int = OpTypeInt 32 1
168 %_ptr_Function_int = OpTypePointer Function %int
169 %_ptr_Input_int = OpTypePointer Input %int
170 %y = OpVariable %_ptr_Input_int Input
171 %int_10 = OpConstant %int 10
172 %bool = OpTypeBool
173 %int_42 = OpConstant %int 42
174 %int_23 = OpConstant %int 23
175 %int_5 = OpConstant %int 5
176 %_ptr_Output_int = OpTypePointer Output %int
177 %outparm = OpVariable %_ptr_Output_int Output
178 %main = OpFunction %void None %3
179 %5 = OpLabel
180 %11 = OpLoad %int %y
181 OpBranch %21
182 %16 = OpLabel
183 %20 = OpIAdd %int %11 %int_42
184 OpBranch %17
185 %21 = OpLabel
186 %24 = OpISub %int %11 %int_23
187 OpBranch %17
188 %17 = OpLabel
189 %31 = OpPhi %int %20 %16 %24 %21
190 %27 = OpIAdd %int %31 %int_5
191 OpStore %outparm %27
192 OpReturn
193 OpFunctionEnd
194 )";
195
196 const std::string after = R"(OpCapability Shader
197 %1 = OpExtInstImport "GLSL.std.450"
198 OpMemoryModel Logical GLSL450
199 OpEntryPoint Fragment %main "main" %y %outparm
200 OpExecutionMode %main OriginUpperLeft
201 OpName %main "main"
202 OpName %y "y"
203 OpName %outparm "outparm"
204 OpDecorate %y Flat
205 OpDecorate %y Location 0
206 OpDecorate %outparm Location 0
207 %void = OpTypeVoid
208 %6 = OpTypeFunction %void
209 %int = OpTypeInt 32 1
210 %_ptr_Function_int = OpTypePointer Function %int
211 %_ptr_Input_int = OpTypePointer Input %int
212 %y = OpVariable %_ptr_Input_int Input
213 %int_10 = OpConstant %int 10
214 %bool = OpTypeBool
215 %int_42 = OpConstant %int 42
216 %int_23 = OpConstant %int 23
217 %int_5 = OpConstant %int 5
218 %_ptr_Output_int = OpTypePointer Output %int
219 %outparm = OpVariable %_ptr_Output_int Output
220 %main = OpFunction %void None %6
221 %16 = OpLabel
222 %17 = OpLoad %int %y
223 OpBranch %18
224 %18 = OpLabel
225 %22 = OpISub %int %17 %int_23
226 OpBranch %21
227 %21 = OpLabel
228 %23 = OpPhi %int %22 %18
229 %24 = OpIAdd %int %23 %int_5
230 OpStore %outparm %24
231 OpReturn
232 OpFunctionEnd
233 )";
234
235 SinglePassRunAndCheck<CFGCleanupPass>(before, after, true, true);
236 }
237
TEST_F(CFGCleanupTest,RemoveNamedLabels)238 TEST_F(CFGCleanupTest, RemoveNamedLabels) {
239 const std::string before = R"(
240 OpCapability Shader
241 %1 = OpExtInstImport "GLSL.std.450"
242 OpMemoryModel Logical GLSL450
243 OpEntryPoint Vertex %main "main"
244 OpSource GLSL 430
245 OpName %main "main"
246 OpName %dead "dead"
247 %void = OpTypeVoid
248 %5 = OpTypeFunction %void
249 %main = OpFunction %void None %5
250 %6 = OpLabel
251 OpReturn
252 %dead = OpLabel
253 OpReturn
254 OpFunctionEnd)";
255
256 const std::string after = R"(OpCapability Shader
257 %1 = OpExtInstImport "GLSL.std.450"
258 OpMemoryModel Logical GLSL450
259 OpEntryPoint Vertex %main "main"
260 OpSource GLSL 430
261 OpName %main "main"
262 %void = OpTypeVoid
263 %5 = OpTypeFunction %void
264 %main = OpFunction %void None %5
265 %6 = OpLabel
266 OpReturn
267 OpFunctionEnd
268 )";
269
270 SinglePassRunAndCheck<CFGCleanupPass>(before, after, true, true);
271 }
272
TEST_F(CFGCleanupTest,RemovePhiArgsFromFarBlocks)273 TEST_F(CFGCleanupTest, RemovePhiArgsFromFarBlocks) {
274 const std::string before = R"(
275 OpCapability Shader
276 %1 = OpExtInstImport "GLSL.std.450"
277 OpMemoryModel Logical GLSL450
278 OpEntryPoint Fragment %main "main" %y %outparm
279 OpExecutionMode %main OriginUpperLeft
280 OpName %main "main"
281 OpName %y "y"
282 OpName %outparm "outparm"
283 OpDecorate %y Flat
284 OpDecorate %y Location 0
285 OpDecorate %outparm Location 0
286 %void = OpTypeVoid
287 %3 = OpTypeFunction %void
288 %int = OpTypeInt 32 1
289 %_ptr_Function_int = OpTypePointer Function %int
290 %_ptr_Input_int = OpTypePointer Input %int
291 %y = OpVariable %_ptr_Input_int Input
292 %int_42 = OpConstant %int 42
293 %_ptr_Output_int = OpTypePointer Output %int
294 %outparm = OpVariable %_ptr_Output_int Output
295 %int_14 = OpConstant %int 14
296 %int_15 = OpConstant %int 15
297 %int_5 = OpConstant %int 5
298 %main = OpFunction %void None %3
299 %5 = OpLabel
300 OpBranch %40
301 %41 = OpLabel
302 %11 = OpLoad %int %y
303 OpBranch %40
304 %40 = OpLabel
305 %12 = OpLoad %int %y
306 OpSelectionMerge %16 None
307 OpSwitch %12 %16 10 %13 13 %14 18 %15
308 %13 = OpLabel
309 OpBranch %16
310 %14 = OpLabel
311 OpStore %outparm %int_14
312 OpBranch %16
313 %15 = OpLabel
314 OpStore %outparm %int_15
315 OpBranch %16
316 %16 = OpLabel
317 %30 = OpPhi %int %11 %40 %int_42 %13 %11 %14 %11 %15
318 %28 = OpIAdd %int %30 %int_5
319 OpStore %outparm %28
320 OpReturn
321 OpFunctionEnd)";
322
323 const std::string after = R"(OpCapability Shader
324 %1 = OpExtInstImport "GLSL.std.450"
325 OpMemoryModel Logical GLSL450
326 OpEntryPoint Fragment %main "main" %y %outparm
327 OpExecutionMode %main OriginUpperLeft
328 OpName %main "main"
329 OpName %y "y"
330 OpName %outparm "outparm"
331 OpDecorate %y Flat
332 OpDecorate %y Location 0
333 OpDecorate %outparm Location 0
334 %void = OpTypeVoid
335 %6 = OpTypeFunction %void
336 %int = OpTypeInt 32 1
337 %_ptr_Function_int = OpTypePointer Function %int
338 %_ptr_Input_int = OpTypePointer Input %int
339 %y = OpVariable %_ptr_Input_int Input
340 %int_42 = OpConstant %int 42
341 %_ptr_Output_int = OpTypePointer Output %int
342 %outparm = OpVariable %_ptr_Output_int Output
343 %int_14 = OpConstant %int 14
344 %int_15 = OpConstant %int 15
345 %int_5 = OpConstant %int 5
346 %26 = OpUndef %int
347 %main = OpFunction %void None %6
348 %15 = OpLabel
349 OpBranch %16
350 %16 = OpLabel
351 %19 = OpLoad %int %y
352 OpSelectionMerge %20 None
353 OpSwitch %19 %20 10 %21 13 %22 18 %23
354 %21 = OpLabel
355 OpBranch %20
356 %22 = OpLabel
357 OpStore %outparm %int_14
358 OpBranch %20
359 %23 = OpLabel
360 OpStore %outparm %int_15
361 OpBranch %20
362 %20 = OpLabel
363 %24 = OpPhi %int %26 %16 %int_42 %21 %26 %22 %26 %23
364 %25 = OpIAdd %int %24 %int_5
365 OpStore %outparm %25
366 OpReturn
367 OpFunctionEnd
368 )";
369
370 SinglePassRunAndCheck<CFGCleanupPass>(before, after, true, true);
371 }
372
TEST_F(CFGCleanupTest,RemovePhiConstantArgs)373 TEST_F(CFGCleanupTest, RemovePhiConstantArgs) {
374 const std::string before = R"(
375 OpCapability Shader
376 %1 = OpExtInstImport "GLSL.std.450"
377 OpMemoryModel Logical GLSL450
378 OpEntryPoint Fragment %main "main" %y %outparm
379 OpExecutionMode %main OriginUpperLeft
380 OpName %main "main"
381 OpName %y "y"
382 OpName %outparm "outparm"
383 OpDecorate %y Flat
384 OpDecorate %y Location 0
385 OpDecorate %outparm Location 0
386 %void = OpTypeVoid
387 %3 = OpTypeFunction %void
388 %int = OpTypeInt 32 1
389 %_ptr_Input_int = OpTypePointer Input %int
390 %y = OpVariable %_ptr_Input_int Input
391 %int_10 = OpConstant %int 10
392 %bool = OpTypeBool
393 %_ptr_Function_int = OpTypePointer Function %int
394 %int_23 = OpConstant %int 23
395 %int_5 = OpConstant %int 5
396 %_ptr_Output_int = OpTypePointer Output %int
397 %outparm = OpVariable %_ptr_Output_int Output
398 %24 = OpUndef %int
399 %main = OpFunction %void None %3
400 %5 = OpLabel
401 OpBranch %14
402 %40 = OpLabel
403 %9 = OpLoad %int %y
404 %12 = OpSGreaterThan %bool %9 %int_10
405 OpSelectionMerge %14 None
406 OpBranchConditional %12 %13 %14
407 %13 = OpLabel
408 OpBranch %14
409 %14 = OpLabel
410 %25 = OpPhi %int %24 %5 %int_23 %13
411 %20 = OpIAdd %int %25 %int_5
412 OpStore %outparm %20
413 OpReturn
414 OpFunctionEnd)";
415
416 const std::string after = R"(OpCapability Shader
417 %1 = OpExtInstImport "GLSL.std.450"
418 OpMemoryModel Logical GLSL450
419 OpEntryPoint Fragment %main "main" %y %outparm
420 OpExecutionMode %main OriginUpperLeft
421 OpName %main "main"
422 OpName %y "y"
423 OpName %outparm "outparm"
424 OpDecorate %y Flat
425 OpDecorate %y Location 0
426 OpDecorate %outparm Location 0
427 %void = OpTypeVoid
428 %6 = OpTypeFunction %void
429 %int = OpTypeInt 32 1
430 %_ptr_Input_int = OpTypePointer Input %int
431 %y = OpVariable %_ptr_Input_int Input
432 %int_10 = OpConstant %int 10
433 %bool = OpTypeBool
434 %_ptr_Function_int = OpTypePointer Function %int
435 %int_23 = OpConstant %int 23
436 %int_5 = OpConstant %int 5
437 %_ptr_Output_int = OpTypePointer Output %int
438 %outparm = OpVariable %_ptr_Output_int Output
439 %15 = OpUndef %int
440 %main = OpFunction %void None %6
441 %16 = OpLabel
442 OpBranch %17
443 %17 = OpLabel
444 %22 = OpPhi %int %15 %16
445 %23 = OpIAdd %int %22 %int_5
446 OpStore %outparm %23
447 OpReturn
448 OpFunctionEnd
449 )";
450
451 SinglePassRunAndCheck<CFGCleanupPass>(before, after, true, true);
452 }
453
454 } // namespace
455 } // namespace opt
456 } // namespace spvtools
457