1 // Copyright (c) 2019 Google LLC
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/assembly_builder.h"
18 #include "test/opt/pass_fixture.h"
19 #include "test/opt/pass_utils.h"
20
21 namespace spvtools {
22 namespace opt {
23 namespace {
24
25 using CodeSinkTest = PassTest<::testing::Test>;
26
TEST_F(CodeSinkTest,MoveToNextBlock)27 TEST_F(CodeSinkTest, MoveToNextBlock) {
28 const std::string text = R"(
29 ;CHECK: OpFunction
30 ;CHECK: OpLabel
31 ;CHECK: OpLabel
32 ;CHECK: [[ac:%\w+]] = OpAccessChain
33 ;CHECK: [[ld:%\w+]] = OpLoad %uint [[ac]]
34 ;CHECK: OpCopyObject %uint [[ld]]
35 OpCapability Shader
36 OpMemoryModel Logical GLSL450
37 OpEntryPoint GLCompute %1 "main"
38 %void = OpTypeVoid
39 %uint = OpTypeInt 32 0
40 %uint_0 = OpConstant %uint 0
41 %uint_4 = OpConstant %uint 4
42 %_arr_uint_uint_4 = OpTypeArray %uint %uint_4
43 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
44 %_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4
45 %9 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform
46 %10 = OpTypeFunction %void
47 %1 = OpFunction %void None %10
48 %11 = OpLabel
49 %12 = OpAccessChain %_ptr_Uniform_uint %9 %uint_0
50 %13 = OpLoad %uint %12
51 OpBranch %14
52 %14 = OpLabel
53 %15 = OpCopyObject %uint %13
54 OpReturn
55 OpFunctionEnd
56 )";
57
58 SinglePassRunAndMatch<CodeSinkingPass>(text, true);
59 }
60
TEST_F(CodeSinkTest,MovePastSelection)61 TEST_F(CodeSinkTest, MovePastSelection) {
62 const std::string text = R"(
63 ;CHECK: OpFunction
64 ;CHECK: OpLabel
65 ;CHECK: OpSelectionMerge [[merge_bb:%\w+]]
66 ;CHECK: [[merge_bb]] = OpLabel
67 ;CHECK: [[ac:%\w+]] = OpAccessChain
68 ;CHECK: [[ld:%\w+]] = OpLoad %uint [[ac]]
69 ;CHECK: OpCopyObject %uint [[ld]]
70 OpCapability Shader
71 OpMemoryModel Logical GLSL450
72 OpEntryPoint GLCompute %1 "main"
73 %void = OpTypeVoid
74 %bool = OpTypeBool
75 %true = OpConstantTrue %bool
76 %uint = OpTypeInt 32 0
77 %uint_0 = OpConstant %uint 0
78 %uint_4 = OpConstant %uint 4
79 %_arr_uint_uint_4 = OpTypeArray %uint %uint_4
80 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
81 %_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4
82 %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform
83 %12 = OpTypeFunction %void
84 %1 = OpFunction %void None %12
85 %13 = OpLabel
86 %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0
87 %15 = OpLoad %uint %14
88 OpSelectionMerge %16 None
89 OpBranchConditional %true %17 %16
90 %17 = OpLabel
91 OpBranch %16
92 %16 = OpLabel
93 %18 = OpCopyObject %uint %15
94 OpReturn
95 OpFunctionEnd
96 )";
97
98 SinglePassRunAndMatch<CodeSinkingPass>(text, true);
99 }
100
TEST_F(CodeSinkTest,MoveIntoSelection)101 TEST_F(CodeSinkTest, MoveIntoSelection) {
102 const std::string text = R"(
103 ;CHECK: OpFunction
104 ;CHECK: OpLabel
105 ;CHECK: OpSelectionMerge [[merge_bb:%\w+]]
106 ;CHECK-NEXT: OpBranchConditional %true [[bb:%\w+]] [[merge_bb]]
107 ;CHECK: [[bb]] = OpLabel
108 ;CHECK-NEXT: [[ac:%\w+]] = OpAccessChain
109 ;CHECK-NEXT: [[ld:%\w+]] = OpLoad %uint [[ac]]
110 ;CHECK-NEXT: OpCopyObject %uint [[ld]]
111 OpCapability Shader
112 OpMemoryModel Logical GLSL450
113 OpEntryPoint GLCompute %1 "main"
114 %void = OpTypeVoid
115 %bool = OpTypeBool
116 %true = OpConstantTrue %bool
117 %uint = OpTypeInt 32 0
118 %uint_0 = OpConstant %uint 0
119 %uint_4 = OpConstant %uint 4
120 %_arr_uint_uint_4 = OpTypeArray %uint %uint_4
121 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
122 %_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4
123 %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform
124 %12 = OpTypeFunction %void
125 %1 = OpFunction %void None %12
126 %13 = OpLabel
127 %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0
128 %15 = OpLoad %uint %14
129 OpSelectionMerge %16 None
130 OpBranchConditional %true %17 %16
131 %17 = OpLabel
132 %18 = OpCopyObject %uint %15
133 OpBranch %16
134 %16 = OpLabel
135 OpReturn
136 OpFunctionEnd
137 )";
138
139 SinglePassRunAndMatch<CodeSinkingPass>(text, true);
140 }
141
TEST_F(CodeSinkTest,LeaveBeforeSelection)142 TEST_F(CodeSinkTest, LeaveBeforeSelection) {
143 const std::string text = R"(
144 OpCapability Shader
145 OpMemoryModel Logical GLSL450
146 OpEntryPoint GLCompute %1 "main"
147 %void = OpTypeVoid
148 %bool = OpTypeBool
149 %true = OpConstantTrue %bool
150 %uint = OpTypeInt 32 0
151 %uint_0 = OpConstant %uint 0
152 %uint_4 = OpConstant %uint 4
153 %_arr_uint_uint_4 = OpTypeArray %uint %uint_4
154 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
155 %_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4
156 %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform
157 %12 = OpTypeFunction %void
158 %1 = OpFunction %void None %12
159 %13 = OpLabel
160 %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0
161 %15 = OpLoad %uint %14
162 OpSelectionMerge %16 None
163 OpBranchConditional %true %17 %20
164 %20 = OpLabel
165 OpBranch %16
166 %17 = OpLabel
167 %18 = OpCopyObject %uint %15
168 OpBranch %16
169 %16 = OpLabel
170 %19 = OpCopyObject %uint %15
171 OpReturn
172 OpFunctionEnd
173 )";
174
175 auto result = SinglePassRunAndDisassemble<CodeSinkingPass>(
176 text, /* skip_nop = */ true, /* do_validation = */ true);
177 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
178 }
179
TEST_F(CodeSinkTest,LeaveAloneUseInSameBlock)180 TEST_F(CodeSinkTest, LeaveAloneUseInSameBlock) {
181 const std::string text = R"(
182 OpCapability Shader
183 OpMemoryModel Logical GLSL450
184 OpEntryPoint GLCompute %1 "main"
185 %void = OpTypeVoid
186 %bool = OpTypeBool
187 %true = OpConstantTrue %bool
188 %uint = OpTypeInt 32 0
189 %uint_0 = OpConstant %uint 0
190 %uint_4 = OpConstant %uint 4
191 %_arr_uint_uint_4 = OpTypeArray %uint %uint_4
192 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
193 %_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4
194 %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform
195 %12 = OpTypeFunction %void
196 %1 = OpFunction %void None %12
197 %13 = OpLabel
198 %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0
199 %15 = OpLoad %uint %14
200 %cond = OpIEqual %bool %15 %uint_0
201 OpSelectionMerge %16 None
202 OpBranchConditional %cond %17 %16
203 %17 = OpLabel
204 OpBranch %16
205 %16 = OpLabel
206 %19 = OpCopyObject %uint %15
207 OpReturn
208 OpFunctionEnd
209 )";
210
211 auto result = SinglePassRunAndDisassemble<CodeSinkingPass>(
212 text, /* skip_nop = */ true, /* do_validation = */ true);
213 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
214 }
215
TEST_F(CodeSinkTest,DontMoveIntoLoop)216 TEST_F(CodeSinkTest, DontMoveIntoLoop) {
217 const std::string text = R"(
218 OpCapability Shader
219 OpMemoryModel Logical GLSL450
220 OpEntryPoint GLCompute %1 "main"
221 %void = OpTypeVoid
222 %bool = OpTypeBool
223 %true = OpConstantTrue %bool
224 %uint = OpTypeInt 32 0
225 %uint_0 = OpConstant %uint 0
226 %uint_4 = OpConstant %uint 4
227 %_arr_uint_uint_4 = OpTypeArray %uint %uint_4
228 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
229 %_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4
230 %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform
231 %12 = OpTypeFunction %void
232 %1 = OpFunction %void None %12
233 %13 = OpLabel
234 %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0
235 %15 = OpLoad %uint %14
236 OpBranch %17
237 %17 = OpLabel
238 OpLoopMerge %merge %cont None
239 OpBranch %cont
240 %cont = OpLabel
241 %cond = OpIEqual %bool %15 %uint_0
242 OpBranchConditional %cond %merge %17
243 %merge = OpLabel
244 OpReturn
245 OpFunctionEnd
246 )";
247
248 auto result = SinglePassRunAndDisassemble<CodeSinkingPass>(
249 text, /* skip_nop = */ true, /* do_validation = */ true);
250 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
251 }
252
TEST_F(CodeSinkTest,DontMoveIntoLoop2)253 TEST_F(CodeSinkTest, DontMoveIntoLoop2) {
254 const std::string text = R"(
255 OpCapability Shader
256 OpMemoryModel Logical GLSL450
257 OpEntryPoint GLCompute %1 "main"
258 %void = OpTypeVoid
259 %bool = OpTypeBool
260 %true = OpConstantTrue %bool
261 %uint = OpTypeInt 32 0
262 %uint_0 = OpConstant %uint 0
263 %uint_4 = OpConstant %uint 4
264 %_arr_uint_uint_4 = OpTypeArray %uint %uint_4
265 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
266 %_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4
267 %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform
268 %12 = OpTypeFunction %void
269 %1 = OpFunction %void None %12
270 %13 = OpLabel
271 %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0
272 %15 = OpLoad %uint %14
273 OpSelectionMerge %16 None
274 OpBranchConditional %true %17 %16
275 %17 = OpLabel
276 OpLoopMerge %merge %cont None
277 OpBranch %cont
278 %cont = OpLabel
279 %cond = OpIEqual %bool %15 %uint_0
280 OpBranchConditional %cond %merge %17
281 %merge = OpLabel
282 OpBranch %16
283 %16 = OpLabel
284 OpReturn
285 OpFunctionEnd
286 )";
287
288 auto result = SinglePassRunAndDisassemble<CodeSinkingPass>(
289 text, /* skip_nop = */ true, /* do_validation = */ true);
290 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
291 }
292
TEST_F(CodeSinkTest,DontMoveSelectionUsedInBothSides)293 TEST_F(CodeSinkTest, DontMoveSelectionUsedInBothSides) {
294 const std::string text = R"(
295 OpCapability Shader
296 OpMemoryModel Logical GLSL450
297 OpEntryPoint GLCompute %1 "main"
298 %void = OpTypeVoid
299 %bool = OpTypeBool
300 %true = OpConstantTrue %bool
301 %uint = OpTypeInt 32 0
302 %uint_0 = OpConstant %uint 0
303 %uint_4 = OpConstant %uint 4
304 %_arr_uint_uint_4 = OpTypeArray %uint %uint_4
305 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
306 %_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4
307 %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform
308 %12 = OpTypeFunction %void
309 %1 = OpFunction %void None %12
310 %13 = OpLabel
311 %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0
312 %15 = OpLoad %uint %14
313 OpSelectionMerge %16 None
314 OpBranchConditional %true %17 %20
315 %20 = OpLabel
316 %19 = OpCopyObject %uint %15
317 OpBranch %16
318 %17 = OpLabel
319 %18 = OpCopyObject %uint %15
320 OpBranch %16
321 %16 = OpLabel
322 OpReturn
323 OpFunctionEnd
324 )";
325
326 auto result = SinglePassRunAndDisassemble<CodeSinkingPass>(
327 text, /* skip_nop = */ true, /* do_validation = */ true);
328 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
329 }
330
TEST_F(CodeSinkTest,DontMoveBecauseOfStore)331 TEST_F(CodeSinkTest, DontMoveBecauseOfStore) {
332 const std::string text = R"(
333 OpCapability Shader
334 OpMemoryModel Logical GLSL450
335 OpEntryPoint GLCompute %1 "main"
336 %void = OpTypeVoid
337 %bool = OpTypeBool
338 %true = OpConstantTrue %bool
339 %uint = OpTypeInt 32 0
340 %uint_0 = OpConstant %uint 0
341 %uint_4 = OpConstant %uint 4
342 %_arr_uint_uint_4 = OpTypeArray %uint %uint_4
343 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
344 %_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4
345 %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform
346 %12 = OpTypeFunction %void
347 %1 = OpFunction %void None %12
348 %13 = OpLabel
349 %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0
350 %15 = OpLoad %uint %14
351 OpStore %14 %15
352 OpSelectionMerge %16 None
353 OpBranchConditional %true %17 %20
354 %20 = OpLabel
355 OpBranch %16
356 %17 = OpLabel
357 %18 = OpCopyObject %uint %15
358 OpBranch %16
359 %16 = OpLabel
360 OpReturn
361 OpFunctionEnd
362 )";
363
364 auto result = SinglePassRunAndDisassemble<CodeSinkingPass>(
365 text, /* skip_nop = */ true, /* do_validation = */ true);
366 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
367 }
368
TEST_F(CodeSinkTest,MoveReadOnlyLoadWithSync)369 TEST_F(CodeSinkTest, MoveReadOnlyLoadWithSync) {
370 const std::string text = R"(
371 OpCapability Shader
372 OpMemoryModel Logical GLSL450
373 OpEntryPoint GLCompute %1 "main"
374 %void = OpTypeVoid
375 %bool = OpTypeBool
376 %true = OpConstantTrue %bool
377 %uint = OpTypeInt 32 0
378 %uint_0 = OpConstant %uint 0
379 %uint_4 = OpConstant %uint 4
380 %mem_semantics = OpConstant %uint 0x42 ; Uniform memory arquire
381 %_arr_uint_uint_4 = OpTypeArray %uint %uint_4
382 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
383 %_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4
384 %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform
385 %12 = OpTypeFunction %void
386 %1 = OpFunction %void None %12
387 %13 = OpLabel
388 %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0
389 %15 = OpLoad %uint %14
390 OpMemoryBarrier %uint_4 %mem_semantics
391 OpSelectionMerge %16 None
392 OpBranchConditional %true %17 %20
393 %20 = OpLabel
394 OpBranch %16
395 %17 = OpLabel
396 %18 = OpCopyObject %uint %15
397 OpBranch %16
398 %16 = OpLabel
399 OpReturn
400 OpFunctionEnd
401 )";
402
403 auto result = SinglePassRunAndDisassemble<CodeSinkingPass>(
404 text, /* skip_nop = */ true, /* do_validation = */ true);
405 EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result));
406 }
407
TEST_F(CodeSinkTest,DontMoveBecauseOfSync)408 TEST_F(CodeSinkTest, DontMoveBecauseOfSync) {
409 const std::string text = R"(
410 OpCapability Shader
411 OpMemoryModel Logical GLSL450
412 OpEntryPoint GLCompute %1 "main"
413 OpDecorate %_arr_uint_uint_4 BufferBlock
414 OpMemberDecorate %_arr_uint_uint_4 0 Offset 0
415 %void = OpTypeVoid
416 %bool = OpTypeBool
417 %true = OpConstantTrue %bool
418 %uint = OpTypeInt 32 0
419 %uint_0 = OpConstant %uint 0
420 %uint_4 = OpConstant %uint 4
421 %mem_semantics = OpConstant %uint 0x42 ; Uniform memory arquire
422 %_arr_uint_uint_4 = OpTypeStruct %uint
423 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
424 %_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4
425 %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform
426 %12 = OpTypeFunction %void
427 %1 = OpFunction %void None %12
428 %13 = OpLabel
429 %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0
430 %15 = OpLoad %uint %14
431 OpMemoryBarrier %uint_4 %mem_semantics
432 OpSelectionMerge %16 None
433 OpBranchConditional %true %17 %20
434 %20 = OpLabel
435 OpBranch %16
436 %17 = OpLabel
437 %18 = OpCopyObject %uint %15
438 OpBranch %16
439 %16 = OpLabel
440 OpReturn
441 OpFunctionEnd
442 )";
443
444 auto result = SinglePassRunAndDisassemble<CodeSinkingPass>(
445 text, /* skip_nop = */ true, /* do_validation = */ true);
446 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
447 }
448
TEST_F(CodeSinkTest,DontMoveBecauseOfAtomicWithSync)449 TEST_F(CodeSinkTest, DontMoveBecauseOfAtomicWithSync) {
450 const std::string text = R"(
451 OpCapability Shader
452 OpMemoryModel Logical GLSL450
453 OpEntryPoint GLCompute %1 "main"
454 OpDecorate %_arr_uint_uint_4 BufferBlock
455 OpMemberDecorate %_arr_uint_uint_4 0 Offset 0
456 %void = OpTypeVoid
457 %bool = OpTypeBool
458 %true = OpConstantTrue %bool
459 %uint = OpTypeInt 32 0
460 %uint_0 = OpConstant %uint 0
461 %uint_4 = OpConstant %uint 4
462 %mem_semantics = OpConstant %uint 0x42 ; Uniform memory arquire
463 %_arr_uint_uint_4 = OpTypeStruct %uint
464 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
465 %_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4
466 %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform
467 %12 = OpTypeFunction %void
468 %1 = OpFunction %void None %12
469 %13 = OpLabel
470 %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0
471 %15 = OpLoad %uint %14
472 %al = OpAtomicLoad %uint %14 %uint_4 %mem_semantics
473 OpSelectionMerge %16 None
474 OpBranchConditional %true %17 %20
475 %20 = OpLabel
476 OpBranch %16
477 %17 = OpLabel
478 %18 = OpCopyObject %uint %15
479 OpBranch %16
480 %16 = OpLabel
481 OpReturn
482 OpFunctionEnd
483 )";
484
485 auto result = SinglePassRunAndDisassemble<CodeSinkingPass>(
486 text, /* skip_nop = */ true, /* do_validation = */ true);
487 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
488 }
489
TEST_F(CodeSinkTest,MoveWithAtomicWithoutSync)490 TEST_F(CodeSinkTest, MoveWithAtomicWithoutSync) {
491 const std::string text = R"(
492 OpCapability Shader
493 OpMemoryModel Logical GLSL450
494 OpEntryPoint GLCompute %1 "main"
495 OpDecorate %_arr_uint_uint_4 BufferBlock
496 OpMemberDecorate %_arr_uint_uint_4 0 Offset 0
497 %void = OpTypeVoid
498 %bool = OpTypeBool
499 %true = OpConstantTrue %bool
500 %uint = OpTypeInt 32 0
501 %uint_0 = OpConstant %uint 0
502 %uint_4 = OpConstant %uint 4
503 %_arr_uint_uint_4 = OpTypeStruct %uint
504 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
505 %_ptr_Uniform__arr_uint_uint_4 = OpTypePointer Uniform %_arr_uint_uint_4
506 %11 = OpVariable %_ptr_Uniform__arr_uint_uint_4 Uniform
507 %12 = OpTypeFunction %void
508 %1 = OpFunction %void None %12
509 %13 = OpLabel
510 %14 = OpAccessChain %_ptr_Uniform_uint %11 %uint_0
511 %15 = OpLoad %uint %14
512 %al = OpAtomicLoad %uint %14 %uint_4 %uint_0
513 OpSelectionMerge %16 None
514 OpBranchConditional %true %17 %20
515 %20 = OpLabel
516 OpBranch %16
517 %17 = OpLabel
518 %18 = OpCopyObject %uint %15
519 OpBranch %16
520 %16 = OpLabel
521 OpReturn
522 OpFunctionEnd
523 )";
524
525 auto result = SinglePassRunAndDisassemble<CodeSinkingPass>(
526 text, /* skip_nop = */ true, /* do_validation = */ true);
527 EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result));
528 }
529
TEST_F(CodeSinkTest,DecorationOnLoad)530 TEST_F(CodeSinkTest, DecorationOnLoad) {
531 const std::string text = R"(
532 OpCapability Shader
533 OpMemoryModel Logical GLSL450
534 OpEntryPoint GLCompute %1 "main" %2
535 OpDecorate %3 RelaxedPrecision
536 %void = OpTypeVoid
537 %5 = OpTypeFunction %void
538 %float = OpTypeFloat 32
539 %_ptr_Input_float = OpTypePointer Input %float
540 %2 = OpVariable %_ptr_Input_float Input
541 %1 = OpFunction %void None %5
542 %8 = OpLabel
543 %3 = OpLoad %float %2
544 OpReturn
545 OpFunctionEnd
546 )";
547
548 // We just want to make sure the code does not crash.
549 auto result = SinglePassRunAndDisassemble<CodeSinkingPass>(
550 text, /* skip_nop = */ true, /* do_validation = */ true);
551 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
552 }
553
554 } // namespace
555 } // namespace opt
556 } // namespace spvtools
557