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