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 "test/opt/assembly_builder.h"
16 #include "test/opt/pass_fixture.h"
17 #include "test/opt/pass_utils.h"
18
19 namespace spvtools {
20 namespace opt {
21 namespace {
22
23 using WrapOpKillTest = PassTest<::testing::Test>;
24
TEST_F(WrapOpKillTest,SingleOpKill)25 TEST_F(WrapOpKillTest, SingleOpKill) {
26 const std::string text = R"(
27 ; CHECK: OpEntryPoint Fragment [[main:%\w+]]
28 ; CHECK: [[main]] = OpFunction
29 ; CHECK: OpFunctionCall %void [[orig_kill:%\w+]]
30 ; CHECK: [[orig_kill]] = OpFunction
31 ; CHECK-NEXT: OpLabel
32 ; CHECK-NEXT: OpFunctionCall %void [[new_kill:%\w+]]
33 ; CHECK-NEXT: OpReturn
34 ; CHECK: [[new_kill]] = OpFunction
35 ; CHECK-NEXT: OpLabel
36 ; CHECK-NEXT: OpKill
37 ; CHECK-NEXT: OpFunctionEnd
38 OpCapability Shader
39 %1 = OpExtInstImport "GLSL.std.450"
40 OpMemoryModel Logical GLSL450
41 OpEntryPoint Fragment %main "main"
42 OpExecutionMode %main OriginUpperLeft
43 OpSource GLSL 330
44 OpName %main "main"
45 %void = OpTypeVoid
46 %5 = OpTypeFunction %void
47 %bool = OpTypeBool
48 %true = OpConstantTrue %bool
49 %main = OpFunction %void None %5
50 %8 = OpLabel
51 OpBranch %9
52 %9 = OpLabel
53 OpLoopMerge %10 %11 None
54 OpBranch %12
55 %12 = OpLabel
56 OpBranchConditional %true %13 %10
57 %13 = OpLabel
58 OpBranch %11
59 %11 = OpLabel
60 %14 = OpFunctionCall %void %kill_
61 OpBranch %9
62 %10 = OpLabel
63 OpReturn
64 OpFunctionEnd
65 %kill_ = OpFunction %void None %5
66 %15 = OpLabel
67 OpKill
68 OpFunctionEnd
69 )";
70
71 SinglePassRunAndMatch<WrapOpKill>(text, true);
72 }
73
TEST_F(WrapOpKillTest,MultipleOpKillInSameFunc)74 TEST_F(WrapOpKillTest, MultipleOpKillInSameFunc) {
75 const std::string text = R"(
76 ; CHECK: OpEntryPoint Fragment [[main:%\w+]]
77 ; CHECK: [[main]] = OpFunction
78 ; CHECK: OpFunctionCall %void [[orig_kill:%\w+]]
79 ; CHECK: [[orig_kill]] = OpFunction
80 ; CHECK-NEXT: OpLabel
81 ; CHECK-NEXT: OpSelectionMerge
82 ; CHECK-NEXT: OpBranchConditional
83 ; CHECK-NEXT: OpLabel
84 ; CHECK-NEXT: OpFunctionCall %void [[new_kill:%\w+]]
85 ; CHECK-NEXT: OpReturn
86 ; CHECK-NEXT: OpLabel
87 ; CHECK-NEXT: OpFunctionCall %void [[new_kill]]
88 ; CHECK-NEXT: OpReturn
89 ; CHECK: [[new_kill]] = OpFunction
90 ; CHECK-NEXT: OpLabel
91 ; CHECK-NEXT: OpKill
92 ; CHECK-NEXT: OpFunctionEnd
93 OpCapability Shader
94 %1 = OpExtInstImport "GLSL.std.450"
95 OpMemoryModel Logical GLSL450
96 OpEntryPoint Fragment %main "main"
97 OpExecutionMode %main OriginUpperLeft
98 OpSource GLSL 330
99 OpName %main "main"
100 %void = OpTypeVoid
101 %5 = OpTypeFunction %void
102 %bool = OpTypeBool
103 %true = OpConstantTrue %bool
104 %main = OpFunction %void None %5
105 %8 = OpLabel
106 OpBranch %9
107 %9 = OpLabel
108 OpLoopMerge %10 %11 None
109 OpBranch %12
110 %12 = OpLabel
111 OpBranchConditional %true %13 %10
112 %13 = OpLabel
113 OpBranch %11
114 %11 = OpLabel
115 %14 = OpFunctionCall %void %kill_
116 OpBranch %9
117 %10 = OpLabel
118 OpReturn
119 OpFunctionEnd
120 %kill_ = OpFunction %void None %5
121 %15 = OpLabel
122 OpSelectionMerge %16 None
123 OpBranchConditional %true %17 %18
124 %17 = OpLabel
125 OpKill
126 %18 = OpLabel
127 OpKill
128 %16 = OpLabel
129 OpReturn
130 OpFunctionEnd
131 )";
132
133 SinglePassRunAndMatch<WrapOpKill>(text, true);
134 }
135
TEST_F(WrapOpKillTest,MultipleOpKillInDifferentFunc)136 TEST_F(WrapOpKillTest, MultipleOpKillInDifferentFunc) {
137 const std::string text = R"(
138 ; CHECK: OpEntryPoint Fragment [[main:%\w+]]
139 ; CHECK: [[main]] = OpFunction
140 ; CHECK: OpFunctionCall %void [[orig_kill1:%\w+]]
141 ; CHECK-NEXT: OpFunctionCall %void [[orig_kill2:%\w+]]
142 ; CHECK: [[orig_kill1]] = OpFunction
143 ; CHECK-NEXT: OpLabel
144 ; CHECK-NEXT: OpFunctionCall %void [[new_kill:%\w+]]
145 ; CHECK-NEXT: OpReturn
146 ; CHECK: [[orig_kill2]] = OpFunction
147 ; CHECK-NEXT: OpLabel
148 ; CHECK-NEXT: OpFunctionCall %void [[new_kill]]
149 ; CHECK-NEXT: OpReturn
150 ; CHECK: [[new_kill]] = OpFunction
151 ; CHECK-NEXT: OpLabel
152 ; CHECK-NEXT: OpKill
153 ; CHECK-NEXT: OpFunctionEnd
154 OpCapability Shader
155 %1 = OpExtInstImport "GLSL.std.450"
156 OpMemoryModel Logical GLSL450
157 OpEntryPoint Fragment %main "main"
158 OpExecutionMode %main OriginUpperLeft
159 OpSource GLSL 330
160 OpName %main "main"
161 %void = OpTypeVoid
162 %4 = OpTypeFunction %void
163 %bool = OpTypeBool
164 %true = OpConstantTrue %bool
165 %main = OpFunction %void None %4
166 %7 = OpLabel
167 OpBranch %8
168 %8 = OpLabel
169 OpLoopMerge %9 %10 None
170 OpBranch %11
171 %11 = OpLabel
172 OpBranchConditional %true %12 %9
173 %12 = OpLabel
174 OpBranch %10
175 %10 = OpLabel
176 %13 = OpFunctionCall %void %14
177 %15 = OpFunctionCall %void %16
178 OpBranch %8
179 %9 = OpLabel
180 OpReturn
181 OpFunctionEnd
182 %14 = OpFunction %void None %4
183 %17 = OpLabel
184 OpKill
185 OpFunctionEnd
186 %16 = OpFunction %void None %4
187 %18 = OpLabel
188 OpKill
189 OpFunctionEnd
190 )";
191
192 SinglePassRunAndMatch<WrapOpKill>(text, true);
193 }
194
TEST_F(WrapOpKillTest,SingleOpTerminateInvocation)195 TEST_F(WrapOpKillTest, SingleOpTerminateInvocation) {
196 const std::string text = R"(
197 ; CHECK: OpEntryPoint Fragment [[main:%\w+]]
198 ; CHECK: [[main]] = OpFunction
199 ; CHECK: OpFunctionCall %void [[orig_kill:%\w+]]
200 ; CHECK: [[orig_kill]] = OpFunction
201 ; CHECK-NEXT: OpLabel
202 ; CHECK-NEXT: OpFunctionCall %void [[new_kill:%\w+]]
203 ; CHECK-NEXT: OpReturn
204 ; CHECK: [[new_kill]] = OpFunction
205 ; CHECK-NEXT: OpLabel
206 ; CHECK-NEXT: OpTerminateInvocation
207 ; CHECK-NEXT: OpFunctionEnd
208 OpCapability Shader
209 OpExtension "SPV_KHR_terminate_invocation"
210 %1 = OpExtInstImport "GLSL.std.450"
211 OpMemoryModel Logical GLSL450
212 OpEntryPoint Fragment %main "main"
213 OpExecutionMode %main OriginUpperLeft
214 OpSource GLSL 330
215 OpName %main "main"
216 %void = OpTypeVoid
217 %5 = OpTypeFunction %void
218 %bool = OpTypeBool
219 %true = OpConstantTrue %bool
220 %main = OpFunction %void None %5
221 %8 = OpLabel
222 OpBranch %9
223 %9 = OpLabel
224 OpLoopMerge %10 %11 None
225 OpBranch %12
226 %12 = OpLabel
227 OpBranchConditional %true %13 %10
228 %13 = OpLabel
229 OpBranch %11
230 %11 = OpLabel
231 %14 = OpFunctionCall %void %kill_
232 OpBranch %9
233 %10 = OpLabel
234 OpReturn
235 OpFunctionEnd
236 %kill_ = OpFunction %void None %5
237 %15 = OpLabel
238 OpTerminateInvocation
239 OpFunctionEnd
240 )";
241
242 SinglePassRunAndMatch<WrapOpKill>(text, true);
243 }
244
TEST_F(WrapOpKillTest,MultipleTerminateInvocationInSameFunc)245 TEST_F(WrapOpKillTest, MultipleTerminateInvocationInSameFunc) {
246 const std::string text = R"(
247 ; CHECK: OpEntryPoint Fragment [[main:%\w+]]
248 ; CHECK: [[main]] = OpFunction
249 ; CHECK: OpFunctionCall %void [[orig_kill:%\w+]]
250 ; CHECK: [[orig_kill]] = OpFunction
251 ; CHECK-NEXT: OpLabel
252 ; CHECK-NEXT: OpSelectionMerge
253 ; CHECK-NEXT: OpBranchConditional
254 ; CHECK-NEXT: OpLabel
255 ; CHECK-NEXT: OpFunctionCall %void [[new_kill:%\w+]]
256 ; CHECK-NEXT: OpReturn
257 ; CHECK-NEXT: OpLabel
258 ; CHECK-NEXT: OpFunctionCall %void [[new_kill]]
259 ; CHECK-NEXT: OpReturn
260 ; CHECK: [[new_kill]] = OpFunction
261 ; CHECK-NEXT: OpLabel
262 ; CHECK-NEXT: OpTerminateInvocation
263 ; CHECK-NEXT: OpFunctionEnd
264 OpCapability Shader
265 OpExtension "SPV_KHR_terminate_invocation"
266 %1 = OpExtInstImport "GLSL.std.450"
267 OpMemoryModel Logical GLSL450
268 OpEntryPoint Fragment %main "main"
269 OpExecutionMode %main OriginUpperLeft
270 OpSource GLSL 330
271 OpName %main "main"
272 %void = OpTypeVoid
273 %5 = OpTypeFunction %void
274 %bool = OpTypeBool
275 %true = OpConstantTrue %bool
276 %main = OpFunction %void None %5
277 %8 = OpLabel
278 OpBranch %9
279 %9 = OpLabel
280 OpLoopMerge %10 %11 None
281 OpBranch %12
282 %12 = OpLabel
283 OpBranchConditional %true %13 %10
284 %13 = OpLabel
285 OpBranch %11
286 %11 = OpLabel
287 %14 = OpFunctionCall %void %kill_
288 OpBranch %9
289 %10 = OpLabel
290 OpReturn
291 OpFunctionEnd
292 %kill_ = OpFunction %void None %5
293 %15 = OpLabel
294 OpSelectionMerge %16 None
295 OpBranchConditional %true %17 %18
296 %17 = OpLabel
297 OpTerminateInvocation
298 %18 = OpLabel
299 OpTerminateInvocation
300 %16 = OpLabel
301 OpReturn
302 OpFunctionEnd
303 )";
304
305 SinglePassRunAndMatch<WrapOpKill>(text, true);
306 }
307
TEST_F(WrapOpKillTest,MultipleOpTerminateInvocationDifferentFunc)308 TEST_F(WrapOpKillTest, MultipleOpTerminateInvocationDifferentFunc) {
309 const std::string text = R"(
310 ; CHECK: OpEntryPoint Fragment [[main:%\w+]]
311 ; CHECK: [[main]] = OpFunction
312 ; CHECK: OpFunctionCall %void [[orig_kill1:%\w+]]
313 ; CHECK-NEXT: OpFunctionCall %void [[orig_kill2:%\w+]]
314 ; CHECK: [[orig_kill1]] = OpFunction
315 ; CHECK-NEXT: OpLabel
316 ; CHECK-NEXT: OpFunctionCall %void [[new_kill:%\w+]]
317 ; CHECK-NEXT: OpReturn
318 ; CHECK: [[orig_kill2]] = OpFunction
319 ; CHECK-NEXT: OpLabel
320 ; CHECK-NEXT: OpFunctionCall %void [[new_kill]]
321 ; CHECK-NEXT: OpReturn
322 ; CHECK: [[new_kill]] = OpFunction
323 ; CHECK-NEXT: OpLabel
324 ; CHECK-NEXT: OpTerminateInvocation
325 ; CHECK-NEXT: OpFunctionEnd
326 OpCapability Shader
327 OpExtension "SPV_KHR_terminate_invocation"
328 %1 = OpExtInstImport "GLSL.std.450"
329 OpMemoryModel Logical GLSL450
330 OpEntryPoint Fragment %main "main"
331 OpExecutionMode %main OriginUpperLeft
332 OpSource GLSL 330
333 OpName %main "main"
334 %void = OpTypeVoid
335 %4 = OpTypeFunction %void
336 %bool = OpTypeBool
337 %true = OpConstantTrue %bool
338 %main = OpFunction %void None %4
339 %7 = OpLabel
340 OpBranch %8
341 %8 = OpLabel
342 OpLoopMerge %9 %10 None
343 OpBranch %11
344 %11 = OpLabel
345 OpBranchConditional %true %12 %9
346 %12 = OpLabel
347 OpBranch %10
348 %10 = OpLabel
349 %13 = OpFunctionCall %void %14
350 %15 = OpFunctionCall %void %16
351 OpBranch %8
352 %9 = OpLabel
353 OpReturn
354 OpFunctionEnd
355 %14 = OpFunction %void None %4
356 %17 = OpLabel
357 OpTerminateInvocation
358 OpFunctionEnd
359 %16 = OpFunction %void None %4
360 %18 = OpLabel
361 OpTerminateInvocation
362 OpFunctionEnd
363 )";
364
365 SinglePassRunAndMatch<WrapOpKill>(text, true);
366 }
367
TEST_F(WrapOpKillTest,KillAndTerminateInvocationSameFunc)368 TEST_F(WrapOpKillTest, KillAndTerminateInvocationSameFunc) {
369 const std::string text = R"(
370 ; CHECK: OpEntryPoint Fragment [[main:%\w+]]
371 ; CHECK: [[main]] = OpFunction
372 ; CHECK: OpFunctionCall %void [[orig_kill:%\w+]]
373 ; CHECK: [[orig_kill]] = OpFunction
374 ; CHECK-NEXT: OpLabel
375 ; CHECK-NEXT: OpSelectionMerge
376 ; CHECK-NEXT: OpBranchConditional
377 ; CHECK-NEXT: OpLabel
378 ; CHECK-NEXT: OpFunctionCall %void [[new_kill:%\w+]]
379 ; CHECK-NEXT: OpReturn
380 ; CHECK-NEXT: OpLabel
381 ; CHECK-NEXT: OpFunctionCall %void [[new_terminate:%\w+]]
382 ; CHECK-NEXT: OpReturn
383 ; CHECK: [[new_kill]] = OpFunction
384 ; CHECK-NEXT: OpLabel
385 ; CHECK-NEXT: OpKill
386 ; CHECK-NEXT: OpFunctionEnd
387 ; CHECK-NEXT: [[new_terminate]] = OpFunction
388 ; CHECK-NEXT: OpLabel
389 ; CHECK-NEXT: OpTerminateInvocation
390 ; CHECK-NEXT: OpFunctionEnd
391 OpCapability Shader
392 OpExtension "SPV_KHR_terminate_invocation"
393 %1 = OpExtInstImport "GLSL.std.450"
394 OpMemoryModel Logical GLSL450
395 OpEntryPoint Fragment %main "main"
396 OpExecutionMode %main OriginUpperLeft
397 OpSource GLSL 330
398 OpName %main "main"
399 %void = OpTypeVoid
400 %5 = OpTypeFunction %void
401 %bool = OpTypeBool
402 %true = OpConstantTrue %bool
403 %main = OpFunction %void None %5
404 %8 = OpLabel
405 OpBranch %9
406 %9 = OpLabel
407 OpLoopMerge %10 %11 None
408 OpBranch %12
409 %12 = OpLabel
410 OpBranchConditional %true %13 %10
411 %13 = OpLabel
412 OpBranch %11
413 %11 = OpLabel
414 %14 = OpFunctionCall %void %kill_
415 OpBranch %9
416 %10 = OpLabel
417 OpReturn
418 OpFunctionEnd
419 %kill_ = OpFunction %void None %5
420 %15 = OpLabel
421 OpSelectionMerge %16 None
422 OpBranchConditional %true %17 %18
423 %17 = OpLabel
424 OpKill
425 %18 = OpLabel
426 OpTerminateInvocation
427 %16 = OpLabel
428 OpReturn
429 OpFunctionEnd
430 )";
431
432 SinglePassRunAndMatch<WrapOpKill>(text, true);
433 }
434
TEST_F(WrapOpKillTest,KillAndTerminateInvocationDifferentFunc)435 TEST_F(WrapOpKillTest, KillAndTerminateInvocationDifferentFunc) {
436 const std::string text = R"(
437 ; CHECK: OpEntryPoint Fragment [[main:%\w+]]
438 ; CHECK: [[main]] = OpFunction
439 ; CHECK: OpFunctionCall %void [[orig_kill1:%\w+]]
440 ; CHECK-NEXT: OpFunctionCall %void [[orig_kill2:%\w+]]
441 ; CHECK: [[orig_kill1]] = OpFunction
442 ; CHECK-NEXT: OpLabel
443 ; CHECK-NEXT: OpFunctionCall %void [[new_terminate:%\w+]]
444 ; CHECK-NEXT: OpReturn
445 ; CHECK: [[orig_kill2]] = OpFunction
446 ; CHECK-NEXT: OpLabel
447 ; CHECK-NEXT: OpFunctionCall %void [[new_kill:%\w+]]
448 ; CHECK-NEXT: OpReturn
449 ; CHECK: [[new_kill]] = OpFunction
450 ; CHECK-NEXT: OpLabel
451 ; CHECK-NEXT: OpKill
452 ; CHECK-NEXT: OpFunctionEnd
453 ; CHECK-NEXT: [[new_terminate]] = OpFunction
454 ; CHECK-NEXT: OpLabel
455 ; CHECK-NEXT: OpTerminateInvocation
456 ; CHECK-NEXT: OpFunctionEnd
457 OpCapability Shader
458 OpExtension "SPV_KHR_terminate_invocation"
459 %1 = OpExtInstImport "GLSL.std.450"
460 OpMemoryModel Logical GLSL450
461 OpEntryPoint Fragment %main "main"
462 OpExecutionMode %main OriginUpperLeft
463 OpSource GLSL 330
464 OpName %main "main"
465 %void = OpTypeVoid
466 %4 = OpTypeFunction %void
467 %bool = OpTypeBool
468 %true = OpConstantTrue %bool
469 %main = OpFunction %void None %4
470 %7 = OpLabel
471 OpBranch %8
472 %8 = OpLabel
473 OpLoopMerge %9 %10 None
474 OpBranch %11
475 %11 = OpLabel
476 OpBranchConditional %true %12 %9
477 %12 = OpLabel
478 OpBranch %10
479 %10 = OpLabel
480 %13 = OpFunctionCall %void %14
481 %15 = OpFunctionCall %void %16
482 OpBranch %8
483 %9 = OpLabel
484 OpReturn
485 OpFunctionEnd
486 %14 = OpFunction %void None %4
487 %17 = OpLabel
488 OpTerminateInvocation
489 OpFunctionEnd
490 %16 = OpFunction %void None %4
491 %18 = OpLabel
492 OpKill
493 OpFunctionEnd
494 )";
495
496 SinglePassRunAndMatch<WrapOpKill>(text, true);
497 }
498
TEST_F(WrapOpKillTest,FuncWithReturnValue)499 TEST_F(WrapOpKillTest, FuncWithReturnValue) {
500 const std::string text = R"(
501 ; CHECK: OpEntryPoint Fragment [[main:%\w+]]
502 ; CHECK: [[main]] = OpFunction
503 ; CHECK: OpFunctionCall %int [[orig_kill:%\w+]]
504 ; CHECK: [[orig_kill]] = OpFunction
505 ; CHECK-NEXT: OpLabel
506 ; CHECK-NEXT: OpFunctionCall %void [[new_kill:%\w+]]
507 ; CHECK-NEXT: [[undef:%\w+]] = OpUndef %int
508 ; CHECK-NEXT: OpReturnValue [[undef]]
509 ; CHECK: [[new_kill]] = OpFunction
510 ; CHECK-NEXT: OpLabel
511 ; CHECK-NEXT: OpKill
512 ; CHECK-NEXT: OpFunctionEnd
513 OpCapability Shader
514 %1 = OpExtInstImport "GLSL.std.450"
515 OpMemoryModel Logical GLSL450
516 OpEntryPoint Fragment %main "main"
517 OpExecutionMode %main OriginUpperLeft
518 OpSource GLSL 330
519 OpName %main "main"
520 %void = OpTypeVoid
521 %5 = OpTypeFunction %void
522 %int = OpTypeInt 32 1
523 %func_type = OpTypeFunction %int
524 %bool = OpTypeBool
525 %true = OpConstantTrue %bool
526 %main = OpFunction %void None %5
527 %8 = OpLabel
528 OpBranch %9
529 %9 = OpLabel
530 OpLoopMerge %10 %11 None
531 OpBranch %12
532 %12 = OpLabel
533 OpBranchConditional %true %13 %10
534 %13 = OpLabel
535 OpBranch %11
536 %11 = OpLabel
537 %14 = OpFunctionCall %int %kill_
538 OpBranch %9
539 %10 = OpLabel
540 OpReturn
541 OpFunctionEnd
542 %kill_ = OpFunction %int None %func_type
543 %15 = OpLabel
544 OpKill
545 OpFunctionEnd
546 )";
547
548 SinglePassRunAndMatch<WrapOpKill>(text, true);
549 }
550
TEST_F(WrapOpKillTest,IdBoundOverflow1)551 TEST_F(WrapOpKillTest, IdBoundOverflow1) {
552 const std::string text = R"(
553 OpCapability GeometryStreams
554 OpMemoryModel Logical GLSL450
555 OpEntryPoint Fragment %main "main"
556 OpExecutionMode %main OriginUpperLeft
557 %2 = OpTypeVoid
558 %3 = OpTypeFunction %2
559 %bool = OpTypeBool
560 %true = OpConstantTrue %bool
561 %main = OpFunction %2 None %3
562 %8 = OpLabel
563 OpBranch %9
564 %9 = OpLabel
565 OpLoopMerge %10 %11 None
566 OpBranch %12
567 %12 = OpLabel
568 OpBranchConditional %true %13 %10
569 %13 = OpLabel
570 OpBranch %11
571 %11 = OpLabel
572 %14 = OpFunctionCall %void %kill_
573 OpBranch %9
574 %10 = OpLabel
575 OpReturn
576 OpFunctionEnd
577 %kill_ = OpFunction %2 Pure|Const %3
578 %4194302 = OpLabel
579 OpKill
580 OpFunctionEnd
581 )";
582
583 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
584
585 std::vector<Message> messages = {
586 {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
587 SetMessageConsumer(GetTestMessageConsumer(messages));
588 auto result = SinglePassRunToBinary<WrapOpKill>(text, true);
589 EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
590 }
591
TEST_F(WrapOpKillTest,IdBoundOverflow2)592 TEST_F(WrapOpKillTest, IdBoundOverflow2) {
593 const std::string text = R"(
594 OpCapability GeometryStreams
595 OpMemoryModel Logical GLSL450
596 OpEntryPoint Fragment %main "main"
597 OpExecutionMode %main OriginUpperLeft
598 %2 = OpTypeVoid
599 %3 = OpTypeFunction %2
600 %bool = OpTypeBool
601 %true = OpConstantTrue %bool
602 %main = OpFunction %2 None %3
603 %8 = OpLabel
604 OpBranch %9
605 %9 = OpLabel
606 OpLoopMerge %10 %11 None
607 OpBranch %12
608 %12 = OpLabel
609 OpBranchConditional %true %13 %10
610 %13 = OpLabel
611 OpBranch %11
612 %11 = OpLabel
613 %14 = OpFunctionCall %void %kill_
614 OpBranch %9
615 %10 = OpLabel
616 OpReturn
617 OpFunctionEnd
618 %kill_ = OpFunction %2 Pure|Const %3
619 %4194301 = OpLabel
620 OpKill
621 OpFunctionEnd
622 )";
623
624 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
625
626 std::vector<Message> messages = {
627 {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
628 SetMessageConsumer(GetTestMessageConsumer(messages));
629 auto result = SinglePassRunToBinary<WrapOpKill>(text, true);
630 EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
631 }
632
TEST_F(WrapOpKillTest,IdBoundOverflow3)633 TEST_F(WrapOpKillTest, IdBoundOverflow3) {
634 const std::string text = R"(
635 OpCapability GeometryStreams
636 OpMemoryModel Logical GLSL450
637 OpEntryPoint Fragment %main "main"
638 OpExecutionMode %main OriginUpperLeft
639 %2 = OpTypeVoid
640 %3 = OpTypeFunction %2
641 %bool = OpTypeBool
642 %true = OpConstantTrue %bool
643 %main = OpFunction %2 None %3
644 %8 = OpLabel
645 OpBranch %9
646 %9 = OpLabel
647 OpLoopMerge %10 %11 None
648 OpBranch %12
649 %12 = OpLabel
650 OpBranchConditional %true %13 %10
651 %13 = OpLabel
652 OpBranch %11
653 %11 = OpLabel
654 %14 = OpFunctionCall %void %kill_
655 OpBranch %9
656 %10 = OpLabel
657 OpReturn
658 OpFunctionEnd
659 %kill_ = OpFunction %2 Pure|Const %3
660 %4194300 = OpLabel
661 OpKill
662 OpFunctionEnd
663 )";
664
665 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
666
667 std::vector<Message> messages = {
668 {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
669 SetMessageConsumer(GetTestMessageConsumer(messages));
670 auto result = SinglePassRunToBinary<WrapOpKill>(text, true);
671 EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
672 }
673
TEST_F(WrapOpKillTest,IdBoundOverflow4)674 TEST_F(WrapOpKillTest, IdBoundOverflow4) {
675 const std::string text = R"(
676 OpCapability DerivativeControl
677 OpMemoryModel Logical GLSL450
678 OpEntryPoint Fragment %main "main"
679 OpExecutionMode %main OriginUpperLeft
680 OpDecorate %2 Location 539091968
681 %2 = OpTypeVoid
682 %3 = OpTypeFunction %2
683 %bool = OpTypeBool
684 %true = OpConstantTrue %bool
685 %main = OpFunction %2 None %3
686 %8 = OpLabel
687 OpBranch %9
688 %9 = OpLabel
689 OpLoopMerge %10 %11 None
690 OpBranch %12
691 %12 = OpLabel
692 OpBranchConditional %true %13 %10
693 %13 = OpLabel
694 OpBranch %11
695 %11 = OpLabel
696 %14 = OpFunctionCall %void %kill_
697 OpBranch %9
698 %10 = OpLabel
699 OpReturn
700 OpFunctionEnd
701 %kill_ = OpFunction %2 Inline|Pure|Const %3
702 %4194302 = OpLabel
703 OpKill
704 OpFunctionEnd
705 )";
706
707 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
708
709 std::vector<Message> messages = {
710 {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
711 SetMessageConsumer(GetTestMessageConsumer(messages));
712 auto result = SinglePassRunToBinary<WrapOpKill>(text, true);
713 EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
714 }
715
TEST_F(WrapOpKillTest,IdBoundOverflow5)716 TEST_F(WrapOpKillTest, IdBoundOverflow5) {
717 const std::string text = R"(
718 OpCapability Shader
719 OpMemoryModel Logical GLSL450
720 OpEntryPoint Fragment %1 "main"
721 OpExecutionMode %1 OriginUpperLeft
722 OpDecorate %void Location 539091968
723 %void = OpTypeVoid
724 %3 = OpTypeFunction %void
725 %float = OpTypeFloat 32
726 %_struct_5 = OpTypeStruct %float %float
727 %_struct_6 = OpTypeStruct %_struct_5
728 %_ptr_Function__struct_6 = OpTypePointer Function %_struct_6
729 %_ptr_Output_float = OpTypePointer Output %float
730 %9 = OpTypeFunction %_struct_5 %_ptr_Function__struct_6
731 %bool = OpTypeBool
732 %true = OpConstantTrue %bool
733 %1 = OpFunction %void None %3
734 %12 = OpLabel
735 %13 = OpVariable %_ptr_Function__struct_6 Function
736 OpBranch %14
737 %14 = OpLabel
738 OpLoopMerge %15 %16 None
739 OpBranch %17
740 %17 = OpLabel
741 OpBranchConditional %true %18 %15
742 %18 = OpLabel
743 OpBranch %16
744 %16 = OpLabel
745 %19 = OpFunctionCall %void %20
746 %21 = OpFunctionCall %_struct_5 %22 %13
747 OpBranch %14
748 %15 = OpLabel
749 OpReturn
750 OpFunctionEnd
751 %20 = OpFunction %void Inline|Pure|Const %3
752 %23 = OpLabel
753 %24 = OpVariable %_ptr_Function__struct_6 Function
754 %25 = OpFunctionCall %_struct_5 %26 %24
755 OpKill
756 OpFunctionEnd
757 %26 = OpFunction %_struct_5 None %9
758 %27 = OpLabel
759 OpUnreachable
760 OpFunctionEnd
761 %22 = OpFunction %_struct_5 Inline %9
762 %4194295 = OpLabel
763 OpKill
764 OpFunctionEnd
765 )";
766
767 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
768
769 std::vector<Message> messages = {
770 {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
771 SetMessageConsumer(GetTestMessageConsumer(messages));
772 auto result = SinglePassRunToBinary<WrapOpKill>(text, true);
773 EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
774 }
775
TEST_F(WrapOpKillTest,SkipEntryPoint)776 TEST_F(WrapOpKillTest, SkipEntryPoint) {
777 const std::string text = R"(
778 OpCapability GeometryStreams
779 OpMemoryModel Logical GLSL450
780 OpEntryPoint Fragment %4 "main"
781 OpExecutionMode %4 OriginUpperLeft
782 %2 = OpTypeVoid
783 %3 = OpTypeFunction %2
784 %4 = OpFunction %2 Pure|Const %3
785 %5 = OpLabel
786 OpKill
787 OpFunctionEnd
788 )";
789
790 auto result = SinglePassRunToBinary<WrapOpKill>(text, true);
791 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
792 }
793
TEST_F(WrapOpKillTest,SkipFunctionNotInContinue)794 TEST_F(WrapOpKillTest, SkipFunctionNotInContinue) {
795 const std::string text = R"(
796 OpCapability GeometryStreams
797 OpMemoryModel Logical GLSL450
798 OpEntryPoint Fragment %main "main"
799 OpExecutionMode %main OriginUpperLeft
800 %2 = OpTypeVoid
801 %3 = OpTypeFunction %2
802 %bool = OpTypeBool
803 %true = OpConstantTrue %bool
804 %main = OpFunction %2 None %3
805 %6 = OpLabel
806 %7 = OpFunctionCall %void %4
807 OpReturn
808 OpFunctionEnd
809 %4 = OpFunction %2 Pure|Const %3
810 %5 = OpLabel
811 OpKill
812 OpFunctionEnd
813 )";
814
815 auto result = SinglePassRunToBinary<WrapOpKill>(text, true);
816 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
817 }
818
TEST_F(WrapOpKillTest,SetParentBlock)819 TEST_F(WrapOpKillTest, SetParentBlock) {
820 const std::string text = R"(
821 OpCapability Shader
822 OpMemoryModel Logical GLSL450
823 OpEntryPoint Fragment %main "main"
824 OpExecutionMode %main OriginUpperLeft
825 %void = OpTypeVoid
826 %bool = OpTypeBool
827 %undef = OpUndef %bool
828 %void_fn = OpTypeFunction %void
829 %main = OpFunction %void None %void_fn
830 %entry = OpLabel
831 OpBranch %loop
832 %loop = OpLabel
833 OpLoopMerge %merge %continue None
834 OpBranchConditional %undef %merge %continue
835 %continue = OpLabel
836 %call = OpFunctionCall %void %kill_func
837 OpBranch %loop
838 %merge = OpLabel
839 OpReturn
840 OpFunctionEnd
841 %kill_func = OpFunction %void None %void_fn
842 %kill_entry = OpLabel
843 OpKill
844 OpFunctionEnd
845 )";
846
847 auto result = SinglePassRunToBinary<WrapOpKill>(text, true);
848 EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result));
849 result = SinglePassRunToBinary<WrapOpKill>(text, true);
850 EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result));
851 }
852
TEST_F(WrapOpKillTest,KillInSingleBlockLoop)853 TEST_F(WrapOpKillTest, KillInSingleBlockLoop) {
854 const std::string text = R"(
855 ; CHECK: OpFunction %void
856 ; CHECK: OpFunction %void
857 ; CHECK-NOT: OpKill
858 ; CHECK: OpFunctionCall %void [[new_kill:%\w+]]
859 ; CHECK-NOT: OpKill
860 ; CHECK: [[new_kill]] = OpFunction
861 ; CHECK-NEXT: OpLabel
862 ; CHECK-NEXT: OpKill
863 ; CHECK-NEXT: OpFunctionEnd
864 OpCapability Shader
865 OpCapability Linkage
866 OpMemoryModel Logical GLSL450
867 %void = OpTypeVoid
868 %bool = OpTypeBool
869 %undef = OpUndef %bool
870 %void_fn = OpTypeFunction %void
871 %main = OpFunction %void None %void_fn
872 %main_entry = OpLabel
873 OpBranch %loop
874 %loop = OpLabel
875 %call = OpFunctionCall %void %sub
876 OpLoopMerge %exit %loop None
877 OpBranchConditional %undef %loop %exit
878 %exit = OpLabel
879 OpReturn
880 OpFunctionEnd
881 %sub = OpFunction %void None %void_fn
882 %sub_entry = OpLabel
883 OpSelectionMerge %ret None
884 OpBranchConditional %undef %kill %ret
885 %kill = OpLabel
886 OpKill
887 %ret = OpLabel
888 OpReturn
889 OpFunctionEnd
890 )";
891
892 SinglePassRunAndMatch<WrapOpKill>(text, true);
893 }
894
TEST_F(WrapOpKillTest,DebugInfoSimple)895 TEST_F(WrapOpKillTest, DebugInfoSimple) {
896 const std::string text = R"(
897 ; CHECK: OpEntryPoint Fragment [[main:%\w+]]
898 ; CHECK: [[main]] = OpFunction
899 ; CHECK: OpFunctionCall %void [[orig_kill:%\w+]]
900 ; CHECK: [[orig_kill]] = OpFunction
901 ; CHECK-NEXT: OpLabel
902 ; CHECK-NEXT: {{%\d+}} = OpExtInst %void [[ext:%\d+]] DebugScope
903 ; CHECK-NEXT: OpLine [[file:%\d+]] 100 200
904 ; CHECK-NEXT: OpFunctionCall %void [[new_kill:%\w+]]
905 ; CHECK: {{%\d+}} = OpExtInst %void [[ext]] DebugNoScope
906 ; CHECK-NEXT: OpReturn
907 ; CHECK: [[new_kill]] = OpFunction
908 ; CHECK-NEXT: OpLabel
909 ; CHECK-NEXT: OpKill
910 ; CHECK-NEXT: OpFunctionEnd
911 OpCapability Shader
912 %1 = OpExtInstImport "OpenCL.DebugInfo.100"
913 OpMemoryModel Logical GLSL450
914 OpEntryPoint Fragment %main "main"
915 OpExecutionMode %main OriginUpperLeft
916 %2 = OpString "File name"
917 OpSource GLSL 330
918 OpName %main "main"
919 %void = OpTypeVoid
920 %5 = OpTypeFunction %void
921 %bool = OpTypeBool
922 %true = OpConstantTrue %bool
923 %3 = OpExtInst %void %1 DebugSource %2
924 %4 = OpExtInst %void %1 DebugCompilationUnit 0 0 %3 GLSL
925 %main = OpFunction %void None %5
926 %8 = OpLabel
927 OpBranch %9
928 %9 = OpLabel
929 OpLoopMerge %10 %11 None
930 OpBranch %12
931 %12 = OpLabel
932 OpBranchConditional %true %13 %10
933 %13 = OpLabel
934 OpBranch %11
935 %11 = OpLabel
936 %14 = OpFunctionCall %void %kill_
937 OpBranch %9
938 %10 = OpLabel
939 OpReturn
940 OpFunctionEnd
941 %kill_ = OpFunction %void None %5
942 %15 = OpLabel
943 %16 = OpExtInst %void %1 DebugScope %4
944 OpLine %2 100 200
945 OpKill
946 OpFunctionEnd
947 )";
948
949 SinglePassRunAndMatch<WrapOpKill>(text, true);
950 }
951
952 } // namespace
953 } // namespace opt
954 } // namespace spvtools
955