|
16 | 16 | #include <string> |
17 | 17 |
|
18 | 18 | #include "test/opt/pass_fixture.h" |
19 | | -#include "test/opt/pass_utils.h" |
20 | 19 |
|
21 | 20 | namespace spvtools { |
22 | 21 | namespace opt { |
@@ -3349,6 +3348,95 @@ OpFunctionEnd |
3349 | 3348 | SinglePassRunAndCheck<DeadBranchElimPass>(text, text, false); |
3350 | 3349 | } |
3351 | 3350 |
|
| 3351 | +TEST_F(DeadBranchElimTest, CFGAndDominatorsStaleCrash) { |
| 3352 | + const std::string text = R"( |
| 3353 | + OpCapability Addresses |
| 3354 | + OpCapability Kernel |
| 3355 | + OpCapability Int64 |
| 3356 | + OpMemoryModel Physical64 OpenCL |
| 3357 | + OpEntryPoint Kernel %1 "main_kernel" |
| 3358 | + %void = OpTypeVoid |
| 3359 | + %uint = OpTypeInt 32 0 |
| 3360 | + %ulong = OpTypeInt 64 0 |
| 3361 | +%_ptr_CrossWorkgroup_uint = OpTypePointer CrossWorkgroup %uint |
| 3362 | + %6 = OpTypeFunction %void %_ptr_CrossWorkgroup_uint %ulong |
| 3363 | + %bool = OpTypeBool |
| 3364 | + %true = OpConstantTrue %bool |
| 3365 | + %1 = OpFunction %void None %6 |
| 3366 | + %9 = OpFunctionParameter %_ptr_CrossWorkgroup_uint |
| 3367 | + %10 = OpFunctionParameter %ulong |
| 3368 | + %11 = OpLabel |
| 3369 | + OpSelectionMerge %12 None |
| 3370 | + OpBranchConditional %true %12 %13 |
| 3371 | + %12 = OpLabel |
| 3372 | + OpBranch %14 |
| 3373 | + %13 = OpLabel |
| 3374 | + OpReturn |
| 3375 | + %15 = OpLabel |
| 3376 | + OpLoopMerge %16 %17 None |
| 3377 | + OpBranch %18 |
| 3378 | + %18 = OpLabel |
| 3379 | + OpSelectionMerge %19 None |
| 3380 | + OpBranchConditional %true %20 %20 |
| 3381 | + %20 = OpLabel |
| 3382 | + OpBranch %19 |
| 3383 | + %19 = OpLabel |
| 3384 | + OpBranch %17 |
| 3385 | + %17 = OpLabel |
| 3386 | + OpBranch %15 |
| 3387 | + %16 = OpLabel |
| 3388 | + OpBranch %14 |
| 3389 | + %14 = OpLabel |
| 3390 | + OpReturn |
| 3391 | + OpFunctionEnd |
| 3392 | +)"; |
| 3393 | + |
| 3394 | + std::unique_ptr<IRContext> context = BuildModule( |
| 3395 | + SPV_ENV_UNIVERSAL_1_1, nullptr, text, SPV_TEXT_TO_BINARY_OPTION_NONE); |
| 3396 | + ASSERT_NE(nullptr, context); |
| 3397 | + |
| 3398 | + // Force dominator analysis to be cached for the function. |
| 3399 | + Function* func = &*context->module()->begin(); |
| 3400 | + context->GetDominatorAnalysis(func); |
| 3401 | + |
| 3402 | + DeadBranchElimPass pass; |
| 3403 | + auto status = pass.Run(context.get()); |
| 3404 | + |
| 3405 | + EXPECT_EQ(Pass::Status::SuccessWithChange, status); |
| 3406 | + |
| 3407 | + std::vector<uint32_t> optimized_bin; |
| 3408 | + context->module()->ToBinary(&optimized_bin, /* skip_nop = */ true); |
| 3409 | + std::string optimized_asm; |
| 3410 | + SpirvTools tools(SPV_ENV_UNIVERSAL_1_1); |
| 3411 | + EXPECT_TRUE(tools.Disassemble(optimized_bin, &optimized_asm)); |
| 3412 | + |
| 3413 | + const std::string expected = R"(OpCapability Addresses |
| 3414 | +OpCapability Kernel |
| 3415 | +OpCapability Int64 |
| 3416 | +OpMemoryModel Physical64 OpenCL |
| 3417 | +OpEntryPoint Kernel %1 "main_kernel" |
| 3418 | +%void = OpTypeVoid |
| 3419 | +%uint = OpTypeInt 32 0 |
| 3420 | +%ulong = OpTypeInt 64 0 |
| 3421 | +%_ptr_CrossWorkgroup_uint = OpTypePointer CrossWorkgroup %uint |
| 3422 | +%6 = OpTypeFunction %void %_ptr_CrossWorkgroup_uint %ulong |
| 3423 | +%bool = OpTypeBool |
| 3424 | +%true = OpConstantTrue %bool |
| 3425 | +%1 = OpFunction %void None %6 |
| 3426 | +%9 = OpFunctionParameter %_ptr_CrossWorkgroup_uint |
| 3427 | +%10 = OpFunctionParameter %ulong |
| 3428 | +%11 = OpLabel |
| 3429 | +OpBranch %12 |
| 3430 | +%12 = OpLabel |
| 3431 | +OpBranch %14 |
| 3432 | +%14 = OpLabel |
| 3433 | +OpReturn |
| 3434 | +OpFunctionEnd |
| 3435 | +)"; |
| 3436 | + |
| 3437 | + EXPECT_EQ(expected, optimized_asm); |
| 3438 | +} |
| 3439 | + |
3352 | 3440 | // TODO(greg-lunarg): Add tests to verify handling of these cases: |
3353 | 3441 | // |
3354 | 3442 | // More complex control flow |
|
0 commit comments