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 19namespace spvtools { 20namespace opt { 21namespace { 22 23using WrapOpKillTest = PassTest<::testing::Test>; 24 25TEST_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 74TEST_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 136TEST_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 195TEST_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 245TEST_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 308TEST_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 368TEST_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 435TEST_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 499TEST_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 551TEST_F(WrapOpKillTest, IdBoundOverflow1) { 552 const std::string text = R"( 553OpCapability GeometryStreams 554OpMemoryModel Logical GLSL450 555OpEntryPoint Fragment %main "main" 556OpExecutionMode %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 563OpBranch %9 564%9 = OpLabel 565OpLoopMerge %10 %11 None 566OpBranch %12 567%12 = OpLabel 568OpBranchConditional %true %13 %10 569%13 = OpLabel 570OpBranch %11 571%11 = OpLabel 572%14 = OpFunctionCall %void %kill_ 573OpBranch %9 574%10 = OpLabel 575OpReturn 576OpFunctionEnd 577%kill_ = OpFunction %2 Pure|Const %3 578%4194302 = OpLabel 579OpKill 580OpFunctionEnd 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 592TEST_F(WrapOpKillTest, IdBoundOverflow2) { 593 const std::string text = R"( 594OpCapability GeometryStreams 595OpMemoryModel Logical GLSL450 596OpEntryPoint Fragment %main "main" 597OpExecutionMode %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 604OpBranch %9 605%9 = OpLabel 606OpLoopMerge %10 %11 None 607OpBranch %12 608%12 = OpLabel 609OpBranchConditional %true %13 %10 610%13 = OpLabel 611OpBranch %11 612%11 = OpLabel 613%14 = OpFunctionCall %void %kill_ 614OpBranch %9 615%10 = OpLabel 616OpReturn 617OpFunctionEnd 618%kill_ = OpFunction %2 Pure|Const %3 619%4194301 = OpLabel 620OpKill 621OpFunctionEnd 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 633TEST_F(WrapOpKillTest, IdBoundOverflow3) { 634 const std::string text = R"( 635OpCapability GeometryStreams 636OpMemoryModel Logical GLSL450 637OpEntryPoint Fragment %main "main" 638OpExecutionMode %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 645OpBranch %9 646%9 = OpLabel 647OpLoopMerge %10 %11 None 648OpBranch %12 649%12 = OpLabel 650OpBranchConditional %true %13 %10 651%13 = OpLabel 652OpBranch %11 653%11 = OpLabel 654%14 = OpFunctionCall %void %kill_ 655OpBranch %9 656%10 = OpLabel 657OpReturn 658OpFunctionEnd 659%kill_ = OpFunction %2 Pure|Const %3 660%4194300 = OpLabel 661OpKill 662OpFunctionEnd 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 674TEST_F(WrapOpKillTest, IdBoundOverflow4) { 675 const std::string text = R"( 676OpCapability DerivativeControl 677OpMemoryModel Logical GLSL450 678OpEntryPoint Fragment %main "main" 679OpExecutionMode %main OriginUpperLeft 680OpDecorate %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 687OpBranch %9 688%9 = OpLabel 689OpLoopMerge %10 %11 None 690OpBranch %12 691%12 = OpLabel 692OpBranchConditional %true %13 %10 693%13 = OpLabel 694OpBranch %11 695%11 = OpLabel 696%14 = OpFunctionCall %void %kill_ 697OpBranch %9 698%10 = OpLabel 699OpReturn 700OpFunctionEnd 701%kill_ = OpFunction %2 Inline|Pure|Const %3 702%4194302 = OpLabel 703OpKill 704OpFunctionEnd 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 716TEST_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 776TEST_F(WrapOpKillTest, SkipEntryPoint) { 777 const std::string text = R"( 778OpCapability GeometryStreams 779OpMemoryModel Logical GLSL450 780OpEntryPoint Fragment %4 "main" 781OpExecutionMode %4 OriginUpperLeft 782%2 = OpTypeVoid 783%3 = OpTypeFunction %2 784%4 = OpFunction %2 Pure|Const %3 785%5 = OpLabel 786OpKill 787OpFunctionEnd 788)"; 789 790 auto result = SinglePassRunToBinary<WrapOpKill>(text, true); 791 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); 792} 793 794TEST_F(WrapOpKillTest, SkipFunctionNotInContinue) { 795 const std::string text = R"( 796OpCapability GeometryStreams 797OpMemoryModel Logical GLSL450 798OpEntryPoint Fragment %main "main" 799OpExecutionMode %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 807OpReturn 808OpFunctionEnd 809%4 = OpFunction %2 Pure|Const %3 810%5 = OpLabel 811OpKill 812OpFunctionEnd 813)"; 814 815 auto result = SinglePassRunToBinary<WrapOpKill>(text, true); 816 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); 817} 818 819TEST_F(WrapOpKillTest, SetParentBlock) { 820 const std::string text = R"( 821OpCapability Shader 822OpMemoryModel Logical GLSL450 823OpEntryPoint Fragment %main "main" 824OpExecutionMode %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 831OpBranch %loop 832%loop = OpLabel 833OpLoopMerge %merge %continue None 834OpBranchConditional %undef %merge %continue 835%continue = OpLabel 836%call = OpFunctionCall %void %kill_func 837OpBranch %loop 838%merge = OpLabel 839OpReturn 840OpFunctionEnd 841%kill_func = OpFunction %void None %void_fn 842%kill_entry = OpLabel 843OpKill 844OpFunctionEnd 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 853TEST_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 895TEST_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