Don't merge unreachable blocks (#2375)

Fixes #2374

* Block merging no longer merges unreachable blocks into their
successors
 * added a test
This commit is contained in:
alan-baker 2019-02-12 09:24:01 -05:00 committed by GitHub
parent 40a7940e05
commit 354205b3dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 48 additions and 0 deletions

View File

@ -86,6 +86,11 @@ bool CanMergeWithSuccessor(IRContext* context, BasicBlock* block) {
return false;
}
// Don't bother trying to merge unreachable blocks.
if (auto dominators = context->GetDominatorAnalysis(block->GetParent())) {
if (!dominators->IsReachable(block)) return false;
}
Instruction* merge_inst = block->GetMergeInst();
const bool pred_is_header = IsHeader(block);
if (pred_is_header && lab_id != merge_inst->GetSingleWordInOperand(0u)) {

View File

@ -483,6 +483,8 @@ TEST_F(BlockMergeTest, RemoveStructuredDeclaration) {
; CHECK-NOT: OpLoopMerge
; CHECK: OpReturn
; CHECK: [[continue:%\w+]] = OpLabel
; CHECK-NEXT: OpBranch [[block:%\w+]]
; CHECK: [[block]] = OpLabel
; CHECK-NEXT: OpBranch [[header]]
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
@ -880,6 +882,47 @@ OpFunctionEnd
prefix + suffix_after, true, true);
}
TEST_F(BlockMergeTest, UnreachableLoop) {
const std::string spirv = R"(OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main"
OpExecutionMode %main OriginUpperLeft
OpSource ESSL 310
OpName %main "main"
%void = OpTypeVoid
%4 = OpTypeFunction %void
%int = OpTypeInt 32 1
%_ptr_Function_int = OpTypePointer Function %int
%bool = OpTypeBool
%false = OpConstantFalse %bool
%main = OpFunction %void None %4
%9 = OpLabel
OpBranch %10
%11 = OpLabel
OpLoopMerge %12 %13 None
OpBranchConditional %false %13 %14
%13 = OpLabel
OpSelectionMerge %15 None
OpBranchConditional %false %16 %17
%16 = OpLabel
OpBranch %15
%17 = OpLabel
OpBranch %15
%15 = OpLabel
OpBranch %11
%14 = OpLabel
OpReturn
%12 = OpLabel
OpBranch %10
%10 = OpLabel
OpReturn
OpFunctionEnd
)";
SinglePassRunAndCheck<BlockMergePass>(spirv, spirv, true, true);
}
// TODO(greg-lunarg): Add tests to verify handling of these cases:
//
// More complex control flow