From 8e0215afe0e77940f4ab0c2a9919785bff5d4a4e Mon Sep 17 00:00:00 2001 From: Vasyl Teliman Date: Wed, 15 Jul 2020 14:59:35 +0300 Subject: [PATCH] spirv-opt: Add support for OpLabel to dominator analysis (#3516) Fixes #3515. --- source/opt/dominator_analysis.cpp | 19 +++- test/opt/dominator_tree/generated.cpp | 120 ++++++++++++++++++++++++++ 2 files changed, 136 insertions(+), 3 deletions(-) diff --git a/source/opt/dominator_analysis.cpp b/source/opt/dominator_analysis.cpp index aef43e69f..b692d26a2 100644 --- a/source/opt/dominator_analysis.cpp +++ b/source/opt/dominator_analysis.cpp @@ -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; } diff --git a/test/opt/dominator_tree/generated.cpp b/test/opt/dominator_tree/generated.cpp index 43b723e93..534f770b5 100644 --- a/test/opt/dominator_tree/generated.cpp +++ b/test/opt/dominator_tree/generated.cpp @@ -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 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