• 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,FuncWithReturnValue)196 TEST_F(WrapOpKillTest, FuncWithReturnValue) {
197   const std::string text = R"(
198 ; CHECK: OpEntryPoint Fragment [[main:%\w+]]
199 ; CHECK: [[main]] = OpFunction
200 ; CHECK: OpFunctionCall %int [[orig_kill:%\w+]]
201 ; CHECK: [[orig_kill]] = OpFunction
202 ; CHECK-NEXT: OpLabel
203 ; CHECK-NEXT: OpFunctionCall %void [[new_kill:%\w+]]
204 ; CHECK-NEXT: [[undef:%\w+]] = OpUndef %int
205 ; CHECK-NEXT: OpReturnValue [[undef]]
206 ; CHECK: [[new_kill]] = OpFunction
207 ; CHECK-NEXT: OpLabel
208 ; CHECK-NEXT: OpKill
209 ; CHECK-NEXT: OpFunctionEnd
210                OpCapability Shader
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         %int = OpTypeInt 32 1
220   %func_type = OpTypeFunction %int
221        %bool = OpTypeBool
222        %true = OpConstantTrue %bool
223        %main = OpFunction %void None %5
224           %8 = OpLabel
225                OpBranch %9
226           %9 = OpLabel
227                OpLoopMerge %10 %11 None
228                OpBranch %12
229          %12 = OpLabel
230                OpBranchConditional %true %13 %10
231          %13 = OpLabel
232                OpBranch %11
233          %11 = OpLabel
234          %14 = OpFunctionCall %int %kill_
235                OpBranch %9
236          %10 = OpLabel
237                OpReturn
238                OpFunctionEnd
239       %kill_ = OpFunction %int None %func_type
240          %15 = OpLabel
241                OpKill
242                OpFunctionEnd
243   )";
244 
245   SinglePassRunAndMatch<WrapOpKill>(text, true);
246 }
247 
TEST_F(WrapOpKillTest,IdBoundOverflow1)248 TEST_F(WrapOpKillTest, IdBoundOverflow1) {
249   const std::string text = R"(
250 OpCapability GeometryStreams
251 OpMemoryModel Logical GLSL450
252 OpEntryPoint Fragment %main "main"
253 OpExecutionMode %main OriginUpperLeft
254 %2 = OpTypeVoid
255 %3 = OpTypeFunction %2
256 %bool = OpTypeBool
257 %true = OpConstantTrue %bool
258 %main = OpFunction %2 None %3
259 %8 = OpLabel
260 OpBranch %9
261 %9 = OpLabel
262 OpLoopMerge %10 %11 None
263 OpBranch %12
264 %12 = OpLabel
265 OpBranchConditional %true %13 %10
266 %13 = OpLabel
267 OpBranch %11
268 %11 = OpLabel
269 %14 = OpFunctionCall %void %kill_
270 OpBranch %9
271 %10 = OpLabel
272 OpReturn
273 OpFunctionEnd
274 %kill_ = OpFunction %2 Pure|Const %3
275 %4194302 = OpLabel
276 OpKill
277 OpFunctionEnd
278 )";
279 
280   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
281 
282   std::vector<Message> messages = {
283       {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
284   SetMessageConsumer(GetTestMessageConsumer(messages));
285   auto result = SinglePassRunToBinary<WrapOpKill>(text, true);
286   EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
287 }
288 
TEST_F(WrapOpKillTest,IdBoundOverflow2)289 TEST_F(WrapOpKillTest, IdBoundOverflow2) {
290   const std::string text = R"(
291 OpCapability GeometryStreams
292 OpMemoryModel Logical GLSL450
293 OpEntryPoint Fragment %main "main"
294 OpExecutionMode %main OriginUpperLeft
295 %2 = OpTypeVoid
296 %3 = OpTypeFunction %2
297 %bool = OpTypeBool
298 %true = OpConstantTrue %bool
299 %main = OpFunction %2 None %3
300 %8 = OpLabel
301 OpBranch %9
302 %9 = OpLabel
303 OpLoopMerge %10 %11 None
304 OpBranch %12
305 %12 = OpLabel
306 OpBranchConditional %true %13 %10
307 %13 = OpLabel
308 OpBranch %11
309 %11 = OpLabel
310 %14 = OpFunctionCall %void %kill_
311 OpBranch %9
312 %10 = OpLabel
313 OpReturn
314 OpFunctionEnd
315 %kill_ = OpFunction %2 Pure|Const %3
316 %4194301 = OpLabel
317 OpKill
318 OpFunctionEnd
319 )";
320 
321   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
322 
323   std::vector<Message> messages = {
324       {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
325   SetMessageConsumer(GetTestMessageConsumer(messages));
326   auto result = SinglePassRunToBinary<WrapOpKill>(text, true);
327   EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
328 }
329 
TEST_F(WrapOpKillTest,IdBoundOverflow3)330 TEST_F(WrapOpKillTest, IdBoundOverflow3) {
331   const std::string text = R"(
332 OpCapability GeometryStreams
333 OpMemoryModel Logical GLSL450
334 OpEntryPoint Fragment %main "main"
335 OpExecutionMode %main OriginUpperLeft
336 %2 = OpTypeVoid
337 %3 = OpTypeFunction %2
338 %bool = OpTypeBool
339 %true = OpConstantTrue %bool
340 %main = OpFunction %2 None %3
341 %8 = OpLabel
342 OpBranch %9
343 %9 = OpLabel
344 OpLoopMerge %10 %11 None
345 OpBranch %12
346 %12 = OpLabel
347 OpBranchConditional %true %13 %10
348 %13 = OpLabel
349 OpBranch %11
350 %11 = OpLabel
351 %14 = OpFunctionCall %void %kill_
352 OpBranch %9
353 %10 = OpLabel
354 OpReturn
355 OpFunctionEnd
356 %kill_ = OpFunction %2 Pure|Const %3
357 %4194300 = OpLabel
358 OpKill
359 OpFunctionEnd
360 )";
361 
362   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
363 
364   std::vector<Message> messages = {
365       {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
366   SetMessageConsumer(GetTestMessageConsumer(messages));
367   auto result = SinglePassRunToBinary<WrapOpKill>(text, true);
368   EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
369 }
370 
TEST_F(WrapOpKillTest,IdBoundOverflow4)371 TEST_F(WrapOpKillTest, IdBoundOverflow4) {
372   const std::string text = R"(
373 OpCapability DerivativeControl
374 OpMemoryModel Logical GLSL450
375 OpEntryPoint Fragment %main "main"
376 OpExecutionMode %main OriginUpperLeft
377 OpDecorate %2 Location 539091968
378 %2 = OpTypeVoid
379 %3 = OpTypeFunction %2
380 %bool = OpTypeBool
381 %true = OpConstantTrue %bool
382 %main = OpFunction %2 None %3
383 %8 = OpLabel
384 OpBranch %9
385 %9 = OpLabel
386 OpLoopMerge %10 %11 None
387 OpBranch %12
388 %12 = OpLabel
389 OpBranchConditional %true %13 %10
390 %13 = OpLabel
391 OpBranch %11
392 %11 = OpLabel
393 %14 = OpFunctionCall %void %kill_
394 OpBranch %9
395 %10 = OpLabel
396 OpReturn
397 OpFunctionEnd
398 %kill_ = OpFunction %2 Inline|Pure|Const %3
399 %4194302 = OpLabel
400 OpKill
401 OpFunctionEnd
402 )";
403 
404   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
405 
406   std::vector<Message> messages = {
407       {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
408   SetMessageConsumer(GetTestMessageConsumer(messages));
409   auto result = SinglePassRunToBinary<WrapOpKill>(text, true);
410   EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
411 }
412 
TEST_F(WrapOpKillTest,IdBoundOverflow5)413 TEST_F(WrapOpKillTest, IdBoundOverflow5) {
414   const std::string text = R"(
415                OpCapability Shader
416                OpMemoryModel Logical GLSL450
417                OpEntryPoint Fragment %1 "main"
418                OpExecutionMode %1 OriginUpperLeft
419                OpDecorate %void Location 539091968
420        %void = OpTypeVoid
421           %3 = OpTypeFunction %void
422       %float = OpTypeFloat 32
423   %_struct_5 = OpTypeStruct %float %float
424   %_struct_6 = OpTypeStruct %_struct_5
425 %_ptr_Function__struct_6 = OpTypePointer Function %_struct_6
426 %_ptr_Output_float = OpTypePointer Output %float
427           %9 = OpTypeFunction %_struct_5 %_ptr_Function__struct_6
428        %bool = OpTypeBool
429        %true = OpConstantTrue %bool
430           %1 = OpFunction %void None %3
431          %12 = OpLabel
432          %13 = OpVariable %_ptr_Function__struct_6 Function
433                OpBranch %14
434          %14 = OpLabel
435                OpLoopMerge %15 %16 None
436                OpBranch %17
437          %17 = OpLabel
438                OpBranchConditional %true %18 %15
439          %18 = OpLabel
440                OpBranch %16
441          %16 = OpLabel
442          %19 = OpFunctionCall %void %20
443          %21 = OpFunctionCall %_struct_5 %22 %13
444                OpBranch %14
445          %15 = OpLabel
446                OpReturn
447                OpFunctionEnd
448          %20 = OpFunction %void Inline|Pure|Const %3
449          %23 = OpLabel
450          %24 = OpVariable %_ptr_Function__struct_6 Function
451          %25 = OpFunctionCall %_struct_5 %26 %24
452                OpKill
453                OpFunctionEnd
454          %26 = OpFunction %_struct_5 None %9
455          %27 = OpLabel
456                OpUnreachable
457                OpFunctionEnd
458          %22 = OpFunction %_struct_5 Inline %9
459     %4194295 = OpLabel
460                OpKill
461                OpFunctionEnd
462 )";
463 
464   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
465 
466   std::vector<Message> messages = {
467       {SPV_MSG_ERROR, "", 0, 0, "ID overflow. Try running compact-ids."}};
468   SetMessageConsumer(GetTestMessageConsumer(messages));
469   auto result = SinglePassRunToBinary<WrapOpKill>(text, true);
470   EXPECT_EQ(Pass::Status::Failure, std::get<1>(result));
471 }
472 
TEST_F(WrapOpKillTest,SkipEntryPoint)473 TEST_F(WrapOpKillTest, SkipEntryPoint) {
474   const std::string text = R"(
475 OpCapability GeometryStreams
476 OpMemoryModel Logical GLSL450
477 OpEntryPoint Fragment %4 "main"
478 OpExecutionMode %4 OriginUpperLeft
479 %2 = OpTypeVoid
480 %3 = OpTypeFunction %2
481 %4 = OpFunction %2 Pure|Const %3
482 %5 = OpLabel
483 OpKill
484 OpFunctionEnd
485 )";
486 
487   auto result = SinglePassRunToBinary<WrapOpKill>(text, true);
488   EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
489 }
490 
TEST_F(WrapOpKillTest,SkipFunctionNotInContinue)491 TEST_F(WrapOpKillTest, SkipFunctionNotInContinue) {
492   const std::string text = R"(
493 OpCapability GeometryStreams
494 OpMemoryModel Logical GLSL450
495 OpEntryPoint Fragment %main "main"
496 OpExecutionMode %main OriginUpperLeft
497 %2 = OpTypeVoid
498 %3 = OpTypeFunction %2
499 %bool = OpTypeBool
500 %true = OpConstantTrue %bool
501 %main = OpFunction %2 None %3
502 %6 = OpLabel
503 %7 = OpFunctionCall %void %4
504 OpReturn
505 OpFunctionEnd
506 %4 = OpFunction %2 Pure|Const %3
507 %5 = OpLabel
508 OpKill
509 OpFunctionEnd
510 )";
511 
512   auto result = SinglePassRunToBinary<WrapOpKill>(text, true);
513   EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
514 }
515 
TEST_F(WrapOpKillTest,SetParentBlock)516 TEST_F(WrapOpKillTest, SetParentBlock) {
517   const std::string text = R"(
518 OpCapability Shader
519 OpMemoryModel Logical GLSL450
520 OpEntryPoint Fragment %main "main"
521 OpExecutionMode %main OriginUpperLeft
522 %void = OpTypeVoid
523 %bool = OpTypeBool
524 %undef = OpUndef %bool
525 %void_fn = OpTypeFunction %void
526 %main = OpFunction %void None %void_fn
527 %entry = OpLabel
528 OpBranch %loop
529 %loop = OpLabel
530 OpLoopMerge %merge %continue None
531 OpBranchConditional %undef %merge %continue
532 %continue = OpLabel
533 %call = OpFunctionCall %void %kill_func
534 OpBranch %loop
535 %merge = OpLabel
536 OpReturn
537 OpFunctionEnd
538 %kill_func = OpFunction %void None %void_fn
539 %kill_entry = OpLabel
540 OpKill
541 OpFunctionEnd
542 )";
543 
544   auto result = SinglePassRunToBinary<WrapOpKill>(text, true);
545   EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result));
546   result = SinglePassRunToBinary<WrapOpKill>(text, true);
547   EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result));
548 }
549 
550 }  // namespace
551 }  // namespace opt
552 }  // namespace spvtools
553