Struct CFG analysus and single block loop (#3293)

Loop headers must be marked as in the continue if the loop header is
also the continue target.

Fixes #3264
This commit is contained in:
Steven Perron 2020-04-13 10:08:31 -04:00 committed by GitHub
parent 000040e707
commit e70d25f6fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 77 additions and 1 deletions

View File

@ -85,9 +85,14 @@ void StructuredCFGAnalysis::AddBlocksInFunction(Function* func) {
if (merge_inst->opcode() == SpvOpLoopMerge) {
new_state.cinfo.containing_loop = block->id();
new_state.cinfo.containing_switch = 0;
new_state.cinfo.in_continue = false;
new_state.continue_node =
merge_inst->GetSingleWordInOperand(kContinueNodeIndex);
if (block->id() == new_state.continue_node) {
new_state.cinfo.in_continue = true;
bb_to_construct_[block->id()].in_continue = true;
} else {
new_state.cinfo.in_continue = false;
}
} else {
new_state.cinfo.containing_loop = state.back().cinfo.containing_loop;
new_state.cinfo.in_continue = state.back().cinfo.in_continue;

View File

@ -1369,6 +1369,35 @@ TEST_F(StructCFGAnalysisTest, FuncCallInContinueIndirect) {
auto c = analysis.FindFuncsCalledFromContinue();
EXPECT_THAT(c, UnorderedElementsAre(14u, 16u, 21u));
}
TEST_F(StructCFGAnalysisTest, SingleBlockLoop) {
const std::string text = R"(
OpCapability Shader
OpCapability Linkage
OpMemoryModel Logical GLSL450
%void = OpTypeVoid
%bool = OpTypeBool
%undef = OpUndef %bool
%void_fn = OpTypeFunction %void
%main = OpFunction %void None %void_fn
%2 = OpLabel
OpBranch %3
%3 = OpLabel
OpLoopMerge %4 %3 None
OpBranchConditional %undef %3 %4
%4 = OpLabel
OpReturn
OpFunctionEnd
)";
std::unique_ptr<IRContext> context =
BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
StructuredCFGAnalysis analysis(context.get());
EXPECT_TRUE(analysis.IsInContinueConstruct(3));
}
} // namespace
} // namespace opt
} // namespace spvtools

View File

@ -547,6 +547,48 @@ OpFunctionEnd
EXPECT_EQ(Pass::Status::SuccessWithChange, std::get<1>(result));
}
TEST_F(WrapOpKillTest, KillInSingleBlockLoop) {
const std::string text = R"(
; CHECK: OpFunction %void
; CHECK: OpFunction %void
; CHECK-NOT: OpKill
; CHECK: OpFunctionCall %void [[new_kill:%\w+]]
; CHECK-NOT: OpKill
; CHECK: [[new_kill]] = OpFunction
; CHECK-NEXT: OpLabel
; CHECK-NEXT: OpKill
; CHECK-NEXT: OpFunctionEnd
OpCapability Shader
OpCapability Linkage
OpMemoryModel Logical GLSL450
%void = OpTypeVoid
%bool = OpTypeBool
%undef = OpUndef %bool
%void_fn = OpTypeFunction %void
%main = OpFunction %void None %void_fn
%main_entry = OpLabel
OpBranch %loop
%loop = OpLabel
%call = OpFunctionCall %void %sub
OpLoopMerge %exit %loop None
OpBranchConditional %undef %loop %exit
%exit = OpLabel
OpReturn
OpFunctionEnd
%sub = OpFunction %void None %void_fn
%sub_entry = OpLabel
OpSelectionMerge %ret None
OpBranchConditional %undef %kill %ret
%kill = OpLabel
OpKill
%ret = OpLabel
OpReturn
OpFunctionEnd
)";
SinglePassRunAndMatch<WrapOpKill>(text, true);
}
} // namespace
} // namespace opt
} // namespace spvtools