• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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