mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-10-18 11:10:05 +00:00
spirv-reduce: Allow merging unreachable blocks (#4303)
This change allows the reducer to merge together blocks even when they are unreachable, but keeps the restriction of reachability in place for the optimizer. Fixes #4302.
This commit is contained in:
parent
4fcdc58946
commit
b8587c984a
@ -43,6 +43,9 @@ bool TransformationMergeBlocks::IsApplicable(
|
||||
}
|
||||
auto first_block = ir_context->cfg()->block(predecessors.at(0));
|
||||
|
||||
if (!ir_context->IsReachable(*first_block)) {
|
||||
return false;
|
||||
}
|
||||
return opt::blockmergeutil::CanMergeWithSuccessor(ir_context, first_block);
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,7 @@ class TransformationMergeBlocks : public Transformation {
|
||||
TransformationMergeBlocks(uint32_t block_id);
|
||||
|
||||
// - |message_.block_id| must be the id of a block, b
|
||||
// - b must be statically reachable in the control flow graph of its function
|
||||
// - b must have a single predecessor, a
|
||||
// - b must be the sole successor of a
|
||||
// - Replacing a with the merge of a and b (and removing b) must lead to a
|
||||
|
@ -28,7 +28,9 @@ namespace opt {
|
||||
bool BlockMergePass::MergeBlocks(Function* func) {
|
||||
bool modified = false;
|
||||
for (auto bi = func->begin(); bi != func->end();) {
|
||||
if (blockmergeutil::CanMergeWithSuccessor(context(), &*bi)) {
|
||||
// Don't bother trying to merge unreachable blocks.
|
||||
if (context()->IsReachable(*bi) &&
|
||||
blockmergeutil::CanMergeWithSuccessor(context(), &*bi)) {
|
||||
blockmergeutil::MergeWithSuccessor(context(), func, bi);
|
||||
// Reprocess block.
|
||||
modified = true;
|
||||
|
@ -103,9 +103,6 @@ bool CanMergeWithSuccessor(IRContext* context, BasicBlock* block) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't bother trying to merge unreachable blocks.
|
||||
if (!context->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)) {
|
||||
|
@ -647,6 +647,64 @@ TEST(MergeBlocksReductionPassTest, LoopReturnReverse) {
|
||||
MergeBlocksReductionPassTest_LoopReturn_Helper(true);
|
||||
}
|
||||
|
||||
TEST(MergeBlocksReductionPassTest, MergeUnreachable) {
|
||||
std::string shader = R"(
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %4 "main"
|
||||
OpExecutionMode %4 OriginUpperLeft
|
||||
OpSource ESSL 320
|
||||
OpName %4 "main"
|
||||
%2 = OpTypeVoid
|
||||
%3 = OpTypeFunction %2
|
||||
%11 = OpTypeBool
|
||||
%12 = OpConstantFalse %11
|
||||
%4 = OpFunction %2 None %3
|
||||
%5 = OpLabel
|
||||
OpReturn
|
||||
%9 = OpLabel
|
||||
OpBranch %100
|
||||
%100 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
||||
const auto consumer = nullptr;
|
||||
const auto context =
|
||||
BuildModule(env, consumer, shader, kReduceAssembleOption);
|
||||
const auto ops =
|
||||
MergeBlocksReductionOpportunityFinder().GetAvailableOpportunities(
|
||||
context.get(), 0);
|
||||
ASSERT_EQ(1, ops.size());
|
||||
|
||||
ASSERT_TRUE(ops[0]->PreconditionHolds());
|
||||
ops[0]->TryToApply();
|
||||
|
||||
std::string after = R"(
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %4 "main"
|
||||
OpExecutionMode %4 OriginUpperLeft
|
||||
OpSource ESSL 320
|
||||
OpName %4 "main"
|
||||
%2 = OpTypeVoid
|
||||
%3 = OpTypeFunction %2
|
||||
%11 = OpTypeBool
|
||||
%12 = OpConstantFalse %11
|
||||
%4 = OpFunction %2 None %3
|
||||
%5 = OpLabel
|
||||
OpReturn
|
||||
%9 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CheckEqual(env, after, context.get());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace reduce
|
||||
} // namespace spvtools
|
||||
|
Loading…
Reference in New Issue
Block a user