mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-12-28 10:41:04 +00:00
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:
parent
000040e707
commit
e70d25f6fa
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user