spirv-opt: Add support for OpLabel to dominator analysis (#3516)

Fixes #3515.
This commit is contained in:
Vasyl Teliman 2020-07-15 14:59:35 +03:00 committed by GitHub
parent f12c40f5a6
commit 8e0215afe0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 136 additions and 3 deletions

View File

@ -55,12 +55,25 @@ bool DominatorAnalysisBase::Dominates(Instruction* a, Instruction* b) const {
return tree_.Dominates(bb_a, bb_b);
}
Instruction* current_inst = a;
while ((current_inst = current_inst->NextNode())) {
if (current_inst == b) {
const Instruction* current = a;
const Instruction* other = b;
if (tree_.IsPostDominator()) {
std::swap(current, other);
}
// We handle OpLabel instructions explicitly since they are not stored in the
// instruction list.
if (current->opcode() == SpvOpLabel) {
return true;
}
while ((current = current->NextNode())) {
if (current == other) {
return true;
}
}
return false;
}

View File

@ -895,6 +895,126 @@ TEST_F(PassClassTest, DominatorUnreachableFromEntry) {
}
}
TEST_F(PassClassTest, DominationForInstructions) {
const std::string text = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %4 "main"
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeInt 32 1
%7 = OpTypeBool
%8 = OpConstantTrue %7
%9 = OpConstant %6 37
%10 = OpConstant %6 3
%13 = OpConstant %6 5
%4 = OpFunction %2 None %3
%5 = OpLabel
%12 = OpIAdd %6 %9 %10
%15 = OpISub %6 %12 %13
OpSelectionMerge %18 None
OpBranchConditional %8 %16 %17
%16 = OpLabel
%20 = OpISub %6 %12 %13
OpBranch %18
%17 = OpLabel
%21 = OpISub %6 %12 %13
OpBranch %18
%18 = OpLabel
%22 = OpISub %6 %12 %13
OpReturn
OpFunctionEnd
)";
// clang-format on
std::unique_ptr<IRContext> context =
BuildModule(SPV_ENV_UNIVERSAL_1_0, nullptr, text,
SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
EXPECT_NE(nullptr, context->module()) << "Assembling failed for shader:\n"
<< text << std::endl;
{
const DominatorAnalysis* dominator_analysis = context->GetDominatorAnalysis(
spvtest::GetFunction(context->module(), 4));
EXPECT_TRUE(
dominator_analysis->Dominates(context->get_def_use_mgr()->GetDef(12),
context->get_def_use_mgr()->GetDef(15)));
EXPECT_FALSE(
dominator_analysis->Dominates(context->get_def_use_mgr()->GetDef(15),
context->get_def_use_mgr()->GetDef(12)));
EXPECT_TRUE(
dominator_analysis->Dominates(context->get_def_use_mgr()->GetDef(5),
context->get_def_use_mgr()->GetDef(12)));
EXPECT_FALSE(
dominator_analysis->Dominates(context->get_def_use_mgr()->GetDef(12),
context->get_def_use_mgr()->GetDef(5)));
EXPECT_TRUE(
dominator_analysis->Dominates(context->get_def_use_mgr()->GetDef(15),
context->get_def_use_mgr()->GetDef(16)));
EXPECT_TRUE(
dominator_analysis->Dominates(context->get_def_use_mgr()->GetDef(15),
context->get_def_use_mgr()->GetDef(21)));
EXPECT_TRUE(
dominator_analysis->Dominates(context->get_def_use_mgr()->GetDef(15),
context->get_def_use_mgr()->GetDef(18)));
EXPECT_TRUE(
dominator_analysis->Dominates(context->get_def_use_mgr()->GetDef(15),
context->get_def_use_mgr()->GetDef(22)));
EXPECT_FALSE(
dominator_analysis->Dominates(context->get_def_use_mgr()->GetDef(20),
context->get_def_use_mgr()->GetDef(22)));
EXPECT_FALSE(
dominator_analysis->Dominates(context->get_def_use_mgr()->GetDef(21),
context->get_def_use_mgr()->GetDef(22)));
EXPECT_TRUE(
dominator_analysis->Dominates(context->get_def_use_mgr()->GetDef(15),
context->get_def_use_mgr()->GetDef(15)));
}
{
const PostDominatorAnalysis* post_dominator_analysis =
context->GetPostDominatorAnalysis(
spvtest::GetFunction(context->module(), 4));
EXPECT_TRUE(post_dominator_analysis->Dominates(
context->get_def_use_mgr()->GetDef(15),
context->get_def_use_mgr()->GetDef(12)));
EXPECT_FALSE(post_dominator_analysis->Dominates(
context->get_def_use_mgr()->GetDef(12),
context->get_def_use_mgr()->GetDef(15)));
EXPECT_TRUE(post_dominator_analysis->Dominates(
context->get_def_use_mgr()->GetDef(12),
context->get_def_use_mgr()->GetDef(5)));
EXPECT_FALSE(post_dominator_analysis->Dominates(
context->get_def_use_mgr()->GetDef(5),
context->get_def_use_mgr()->GetDef(12)));
EXPECT_FALSE(post_dominator_analysis->Dominates(
context->get_def_use_mgr()->GetDef(16),
context->get_def_use_mgr()->GetDef(15)));
EXPECT_FALSE(post_dominator_analysis->Dominates(
context->get_def_use_mgr()->GetDef(21),
context->get_def_use_mgr()->GetDef(15)));
EXPECT_TRUE(post_dominator_analysis->Dominates(
context->get_def_use_mgr()->GetDef(18),
context->get_def_use_mgr()->GetDef(15)));
EXPECT_TRUE(post_dominator_analysis->Dominates(
context->get_def_use_mgr()->GetDef(22),
context->get_def_use_mgr()->GetDef(15)));
EXPECT_TRUE(post_dominator_analysis->Dominates(
context->get_def_use_mgr()->GetDef(22),
context->get_def_use_mgr()->GetDef(20)));
EXPECT_TRUE(post_dominator_analysis->Dominates(
context->get_def_use_mgr()->GetDef(22),
context->get_def_use_mgr()->GetDef(21)));
EXPECT_TRUE(post_dominator_analysis->Dominates(
context->get_def_use_mgr()->GetDef(15),
context->get_def_use_mgr()->GetDef(15)));
}
}
} // namespace
} // namespace opt
} // namespace spvtools