Skip to content

Commit f25a3b0

Browse files
authored
spirv-opt: Invalidate analyses in DeadBranchElimPass (KhronosGroup#6764)
Invalidate kAnalysisCFG, kAnalysisDominatorAnalysis, and kAnalysisStructuredCFG analyses when DeadBranchElimPass makes changes to basic blocks. This forces FixBlockOrder() to rebuild them rather than using stale caches containing deleted basic block references. Fixes KhronosGroup#6632
1 parent eb5b997 commit f25a3b0

2 files changed

Lines changed: 95 additions & 2 deletions

File tree

source/opt/dead_branch_elim_pass.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,12 @@ Pass::Status DeadBranchElimPass::Process() {
480480
return EliminateDeadBranches(fp);
481481
};
482482
bool modified = context()->ProcessReachableCallTree(pfn);
483-
if (modified) FixBlockOrder();
483+
if (modified) {
484+
context()->InvalidateAnalyses(IRContext::kAnalysisCFG |
485+
IRContext::kAnalysisDominatorAnalysis |
486+
IRContext::kAnalysisStructuredCFG);
487+
FixBlockOrder();
488+
}
484489
return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange;
485490
}
486491

test/opt/dead_branch_elim_test.cpp

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
#include <string>
1717

1818
#include "test/opt/pass_fixture.h"
19-
#include "test/opt/pass_utils.h"
2019

2120
namespace spvtools {
2221
namespace opt {
@@ -3349,6 +3348,95 @@ OpFunctionEnd
33493348
SinglePassRunAndCheck<DeadBranchElimPass>(text, text, false);
33503349
}
33513350

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+
33523440
// TODO(greg-lunarg): Add tests to verify handling of these cases:
33533441
//
33543442
// More complex control flow

0 commit comments

Comments
 (0)