1fd4e5da5Sopenharmony_ci// Copyright (c) 2017 Google Inc. 2fd4e5da5Sopenharmony_ci// 3fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License"); 4fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License. 5fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at 6fd4e5da5Sopenharmony_ci// 7fd4e5da5Sopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0 8fd4e5da5Sopenharmony_ci// 9fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software 10fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS, 11fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and 13fd4e5da5Sopenharmony_ci// limitations under the License. 14fd4e5da5Sopenharmony_ci 15fd4e5da5Sopenharmony_ci#include <array> 16fd4e5da5Sopenharmony_ci#include <memory> 17fd4e5da5Sopenharmony_ci#include <string> 18fd4e5da5Sopenharmony_ci#include <vector> 19fd4e5da5Sopenharmony_ci 20fd4e5da5Sopenharmony_ci#include "gmock/gmock.h" 21fd4e5da5Sopenharmony_ci#include "source/opt/dominator_analysis.h" 22fd4e5da5Sopenharmony_ci#include "source/opt/iterator.h" 23fd4e5da5Sopenharmony_ci#include "source/opt/pass.h" 24fd4e5da5Sopenharmony_ci#include "test/opt/assembly_builder.h" 25fd4e5da5Sopenharmony_ci#include "test/opt/function_utils.h" 26fd4e5da5Sopenharmony_ci#include "test/opt/pass_fixture.h" 27fd4e5da5Sopenharmony_ci#include "test/opt/pass_utils.h" 28fd4e5da5Sopenharmony_ci 29fd4e5da5Sopenharmony_cinamespace spvtools { 30fd4e5da5Sopenharmony_cinamespace opt { 31fd4e5da5Sopenharmony_cinamespace { 32fd4e5da5Sopenharmony_ci 33fd4e5da5Sopenharmony_ciusing ::testing::UnorderedElementsAre; 34fd4e5da5Sopenharmony_ciusing PassClassTest = PassTest<::testing::Test>; 35fd4e5da5Sopenharmony_ci 36fd4e5da5Sopenharmony_ci// Check that x dominates y, and 37fd4e5da5Sopenharmony_ci// if x != y then 38fd4e5da5Sopenharmony_ci// x strictly dominates y and 39fd4e5da5Sopenharmony_ci// y does not dominate x and 40fd4e5da5Sopenharmony_ci// y does not strictly dominate x 41fd4e5da5Sopenharmony_ci// if x == x then 42fd4e5da5Sopenharmony_ci// x does not strictly dominate itself 43fd4e5da5Sopenharmony_civoid check_dominance(const DominatorAnalysisBase& dom_tree, const Function* fn, 44fd4e5da5Sopenharmony_ci uint32_t x, uint32_t y) { 45fd4e5da5Sopenharmony_ci SCOPED_TRACE("Check dominance properties for Basic Block " + 46fd4e5da5Sopenharmony_ci std::to_string(x) + " and " + std::to_string(y)); 47fd4e5da5Sopenharmony_ci EXPECT_TRUE(dom_tree.Dominates(spvtest::GetBasicBlock(fn, x), 48fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, y))); 49fd4e5da5Sopenharmony_ci EXPECT_TRUE(dom_tree.Dominates(x, y)); 50fd4e5da5Sopenharmony_ci if (x == y) { 51fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.StrictlyDominates(x, x)); 52fd4e5da5Sopenharmony_ci } else { 53fd4e5da5Sopenharmony_ci EXPECT_TRUE(dom_tree.StrictlyDominates(x, y)); 54fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.Dominates(y, x)); 55fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.StrictlyDominates(y, x)); 56fd4e5da5Sopenharmony_ci } 57fd4e5da5Sopenharmony_ci} 58fd4e5da5Sopenharmony_ci 59fd4e5da5Sopenharmony_ci// Check that x does not dominates y and vice versa 60fd4e5da5Sopenharmony_civoid check_no_dominance(const DominatorAnalysisBase& dom_tree, 61fd4e5da5Sopenharmony_ci const Function* fn, uint32_t x, uint32_t y) { 62fd4e5da5Sopenharmony_ci SCOPED_TRACE("Check no domination for Basic Block " + std::to_string(x) + 63fd4e5da5Sopenharmony_ci " and " + std::to_string(y)); 64fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.Dominates(spvtest::GetBasicBlock(fn, x), 65fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, y))); 66fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.Dominates(x, y)); 67fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.StrictlyDominates(spvtest::GetBasicBlock(fn, x), 68fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, y))); 69fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.StrictlyDominates(x, y)); 70fd4e5da5Sopenharmony_ci 71fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.Dominates(spvtest::GetBasicBlock(fn, y), 72fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, x))); 73fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.Dominates(y, x)); 74fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.StrictlyDominates(spvtest::GetBasicBlock(fn, y), 75fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, x))); 76fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.StrictlyDominates(y, x)); 77fd4e5da5Sopenharmony_ci} 78fd4e5da5Sopenharmony_ci 79fd4e5da5Sopenharmony_ciTEST_F(PassClassTest, DominatorSimpleCFG) { 80fd4e5da5Sopenharmony_ci const std::string text = R"( 81fd4e5da5Sopenharmony_ci OpCapability Addresses 82fd4e5da5Sopenharmony_ci OpCapability Kernel 83fd4e5da5Sopenharmony_ci OpMemoryModel Physical64 OpenCL 84fd4e5da5Sopenharmony_ci OpEntryPoint Kernel %1 "main" 85fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 86fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 87fd4e5da5Sopenharmony_ci %4 = OpTypeBool 88fd4e5da5Sopenharmony_ci %5 = OpTypeInt 32 0 89fd4e5da5Sopenharmony_ci %6 = OpConstant %5 0 90fd4e5da5Sopenharmony_ci %7 = OpConstantFalse %4 91fd4e5da5Sopenharmony_ci %8 = OpConstantTrue %4 92fd4e5da5Sopenharmony_ci %9 = OpConstant %5 1 93fd4e5da5Sopenharmony_ci %1 = OpFunction %2 None %3 94fd4e5da5Sopenharmony_ci %10 = OpLabel 95fd4e5da5Sopenharmony_ci OpBranch %11 96fd4e5da5Sopenharmony_ci %11 = OpLabel 97fd4e5da5Sopenharmony_ci OpSwitch %6 %12 1 %13 98fd4e5da5Sopenharmony_ci %12 = OpLabel 99fd4e5da5Sopenharmony_ci OpBranch %14 100fd4e5da5Sopenharmony_ci %13 = OpLabel 101fd4e5da5Sopenharmony_ci OpBranch %14 102fd4e5da5Sopenharmony_ci %14 = OpLabel 103fd4e5da5Sopenharmony_ci OpBranchConditional %8 %11 %15 104fd4e5da5Sopenharmony_ci %15 = OpLabel 105fd4e5da5Sopenharmony_ci OpReturn 106fd4e5da5Sopenharmony_ci OpFunctionEnd 107fd4e5da5Sopenharmony_ci)"; 108fd4e5da5Sopenharmony_ci // clang-format on 109fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 110fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_0, nullptr, text, 111fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 112fd4e5da5Sopenharmony_ci Module* module = context->module(); 113fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" 114fd4e5da5Sopenharmony_ci << text << std::endl; 115fd4e5da5Sopenharmony_ci const Function* fn = spvtest::GetFunction(module, 1); 116fd4e5da5Sopenharmony_ci const BasicBlock* entry = spvtest::GetBasicBlock(fn, 10); 117fd4e5da5Sopenharmony_ci EXPECT_EQ(entry, fn->entry().get()) 118fd4e5da5Sopenharmony_ci << "The entry node is not the expected one"; 119fd4e5da5Sopenharmony_ci 120fd4e5da5Sopenharmony_ci // Test normal dominator tree 121fd4e5da5Sopenharmony_ci { 122fd4e5da5Sopenharmony_ci DominatorAnalysis dom_tree; 123fd4e5da5Sopenharmony_ci const CFG& cfg = *context->cfg(); 124fd4e5da5Sopenharmony_ci dom_tree.InitializeTree(cfg, fn); 125fd4e5da5Sopenharmony_ci 126fd4e5da5Sopenharmony_ci // Inspect the actual tree 127fd4e5da5Sopenharmony_ci DominatorTree& tree = dom_tree.GetDomTree(); 128fd4e5da5Sopenharmony_ci EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_entry_block()); 129fd4e5da5Sopenharmony_ci EXPECT_TRUE( 130fd4e5da5Sopenharmony_ci dom_tree.Dominates(cfg.pseudo_entry_block()->id(), entry->id())); 131fd4e5da5Sopenharmony_ci 132fd4e5da5Sopenharmony_ci // (strict) dominance checks 133fd4e5da5Sopenharmony_ci for (uint32_t id : {10, 11, 12, 13, 14, 15}) 134fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, id, id); 135fd4e5da5Sopenharmony_ci 136fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 10, 11); 137fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 10, 12); 138fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 10, 13); 139fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 10, 14); 140fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 10, 15); 141fd4e5da5Sopenharmony_ci 142fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 11, 12); 143fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 11, 13); 144fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 11, 14); 145fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 11, 15); 146fd4e5da5Sopenharmony_ci 147fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 14, 15); 148fd4e5da5Sopenharmony_ci 149fd4e5da5Sopenharmony_ci check_no_dominance(dom_tree, fn, 12, 13); 150fd4e5da5Sopenharmony_ci check_no_dominance(dom_tree, fn, 12, 14); 151fd4e5da5Sopenharmony_ci check_no_dominance(dom_tree, fn, 13, 14); 152fd4e5da5Sopenharmony_ci 153fd4e5da5Sopenharmony_ci // check with some invalid inputs 154fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.Dominates(nullptr, entry)); 155fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.Dominates(entry, nullptr)); 156fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.Dominates(static_cast<BasicBlock*>(nullptr), 157fd4e5da5Sopenharmony_ci static_cast<BasicBlock*>(nullptr))); 158fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.Dominates(10, 1)); 159fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.Dominates(1, 10)); 160fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.Dominates(1, 1)); 161fd4e5da5Sopenharmony_ci 162fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.StrictlyDominates(nullptr, entry)); 163fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.StrictlyDominates(entry, nullptr)); 164fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.StrictlyDominates(nullptr, nullptr)); 165fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.StrictlyDominates(10, 1)); 166fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.StrictlyDominates(1, 10)); 167fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.StrictlyDominates(1, 1)); 168fd4e5da5Sopenharmony_ci 169fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_entry_block()), nullptr); 170fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(entry), cfg.pseudo_entry_block()); 171fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(nullptr), nullptr); 172fd4e5da5Sopenharmony_ci 173fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 11)), 174fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 10)); 175fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 12)), 176fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 11)); 177fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 13)), 178fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 11)); 179fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 14)), 180fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 11)); 181fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 15)), 182fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 14)); 183fd4e5da5Sopenharmony_ci } 184fd4e5da5Sopenharmony_ci 185fd4e5da5Sopenharmony_ci // Test post dominator tree 186fd4e5da5Sopenharmony_ci { 187fd4e5da5Sopenharmony_ci PostDominatorAnalysis dom_tree; 188fd4e5da5Sopenharmony_ci const CFG& cfg = *context->cfg(); 189fd4e5da5Sopenharmony_ci dom_tree.InitializeTree(cfg, fn); 190fd4e5da5Sopenharmony_ci 191fd4e5da5Sopenharmony_ci // Inspect the actual tree 192fd4e5da5Sopenharmony_ci DominatorTree& tree = dom_tree.GetDomTree(); 193fd4e5da5Sopenharmony_ci EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_exit_block()); 194fd4e5da5Sopenharmony_ci EXPECT_TRUE(dom_tree.Dominates(cfg.pseudo_exit_block()->id(), 15)); 195fd4e5da5Sopenharmony_ci 196fd4e5da5Sopenharmony_ci // (strict) dominance checks 197fd4e5da5Sopenharmony_ci for (uint32_t id : {10, 11, 12, 13, 14, 15}) 198fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, id, id); 199fd4e5da5Sopenharmony_ci 200fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 14, 10); 201fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 14, 11); 202fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 14, 12); 203fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 14, 13); 204fd4e5da5Sopenharmony_ci 205fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 15, 10); 206fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 15, 11); 207fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 15, 12); 208fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 15, 13); 209fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 15, 14); 210fd4e5da5Sopenharmony_ci 211fd4e5da5Sopenharmony_ci check_no_dominance(dom_tree, fn, 13, 12); 212fd4e5da5Sopenharmony_ci check_no_dominance(dom_tree, fn, 12, 11); 213fd4e5da5Sopenharmony_ci check_no_dominance(dom_tree, fn, 13, 11); 214fd4e5da5Sopenharmony_ci 215fd4e5da5Sopenharmony_ci // check with some invalid inputs 216fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.Dominates(nullptr, entry)); 217fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.Dominates(entry, nullptr)); 218fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.Dominates(static_cast<BasicBlock*>(nullptr), 219fd4e5da5Sopenharmony_ci static_cast<BasicBlock*>(nullptr))); 220fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.Dominates(10, 1)); 221fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.Dominates(1, 10)); 222fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.Dominates(1, 1)); 223fd4e5da5Sopenharmony_ci 224fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.StrictlyDominates(nullptr, entry)); 225fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.StrictlyDominates(entry, nullptr)); 226fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.StrictlyDominates(nullptr, nullptr)); 227fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.StrictlyDominates(10, 1)); 228fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.StrictlyDominates(1, 10)); 229fd4e5da5Sopenharmony_ci EXPECT_FALSE(dom_tree.StrictlyDominates(1, 1)); 230fd4e5da5Sopenharmony_ci 231fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(nullptr), nullptr); 232fd4e5da5Sopenharmony_ci 233fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 11)), 234fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 14)); 235fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 12)), 236fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 14)); 237fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 13)), 238fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 14)); 239fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 14)), 240fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 15)); 241fd4e5da5Sopenharmony_ci 242fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 15)), 243fd4e5da5Sopenharmony_ci cfg.pseudo_exit_block()); 244fd4e5da5Sopenharmony_ci 245fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_exit_block()), nullptr); 246fd4e5da5Sopenharmony_ci } 247fd4e5da5Sopenharmony_ci} 248fd4e5da5Sopenharmony_ci 249fd4e5da5Sopenharmony_ciTEST_F(PassClassTest, DominatorIrreducibleCFG) { 250fd4e5da5Sopenharmony_ci const std::string text = R"( 251fd4e5da5Sopenharmony_ci OpCapability Addresses 252fd4e5da5Sopenharmony_ci OpCapability Kernel 253fd4e5da5Sopenharmony_ci OpMemoryModel Physical64 OpenCL 254fd4e5da5Sopenharmony_ci OpEntryPoint Kernel %1 "main" 255fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 256fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 257fd4e5da5Sopenharmony_ci %4 = OpTypeBool 258fd4e5da5Sopenharmony_ci %5 = OpTypeInt 32 0 259fd4e5da5Sopenharmony_ci %6 = OpConstantFalse %4 260fd4e5da5Sopenharmony_ci %7 = OpConstantTrue %4 261fd4e5da5Sopenharmony_ci %1 = OpFunction %2 None %3 262fd4e5da5Sopenharmony_ci %8 = OpLabel 263fd4e5da5Sopenharmony_ci OpBranch %9 264fd4e5da5Sopenharmony_ci %9 = OpLabel 265fd4e5da5Sopenharmony_ci OpBranchConditional %7 %10 %11 266fd4e5da5Sopenharmony_ci %10 = OpLabel 267fd4e5da5Sopenharmony_ci OpBranch %11 268fd4e5da5Sopenharmony_ci %11 = OpLabel 269fd4e5da5Sopenharmony_ci OpBranchConditional %7 %10 %12 270fd4e5da5Sopenharmony_ci %12 = OpLabel 271fd4e5da5Sopenharmony_ci OpReturn 272fd4e5da5Sopenharmony_ci OpFunctionEnd 273fd4e5da5Sopenharmony_ci)"; 274fd4e5da5Sopenharmony_ci // clang-format on 275fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 276fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_0, nullptr, text, 277fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 278fd4e5da5Sopenharmony_ci Module* module = context->module(); 279fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" 280fd4e5da5Sopenharmony_ci << text << std::endl; 281fd4e5da5Sopenharmony_ci const Function* fn = spvtest::GetFunction(module, 1); 282fd4e5da5Sopenharmony_ci 283fd4e5da5Sopenharmony_ci const BasicBlock* entry = spvtest::GetBasicBlock(fn, 8); 284fd4e5da5Sopenharmony_ci EXPECT_EQ(entry, fn->entry().get()) 285fd4e5da5Sopenharmony_ci << "The entry node is not the expected one"; 286fd4e5da5Sopenharmony_ci 287fd4e5da5Sopenharmony_ci // Check normal dominator tree 288fd4e5da5Sopenharmony_ci { 289fd4e5da5Sopenharmony_ci DominatorAnalysis dom_tree; 290fd4e5da5Sopenharmony_ci const CFG& cfg = *context->cfg(); 291fd4e5da5Sopenharmony_ci dom_tree.InitializeTree(cfg, fn); 292fd4e5da5Sopenharmony_ci 293fd4e5da5Sopenharmony_ci // Inspect the actual tree 294fd4e5da5Sopenharmony_ci DominatorTree& tree = dom_tree.GetDomTree(); 295fd4e5da5Sopenharmony_ci EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_entry_block()); 296fd4e5da5Sopenharmony_ci EXPECT_TRUE( 297fd4e5da5Sopenharmony_ci dom_tree.Dominates(cfg.pseudo_entry_block()->id(), entry->id())); 298fd4e5da5Sopenharmony_ci 299fd4e5da5Sopenharmony_ci // (strict) dominance checks 300fd4e5da5Sopenharmony_ci for (uint32_t id : {8, 9, 10, 11, 12}) 301fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, id, id); 302fd4e5da5Sopenharmony_ci 303fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 8, 9); 304fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 8, 10); 305fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 8, 11); 306fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 8, 12); 307fd4e5da5Sopenharmony_ci 308fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 9, 10); 309fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 9, 11); 310fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 9, 12); 311fd4e5da5Sopenharmony_ci 312fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 11, 12); 313fd4e5da5Sopenharmony_ci 314fd4e5da5Sopenharmony_ci check_no_dominance(dom_tree, fn, 10, 11); 315fd4e5da5Sopenharmony_ci 316fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_entry_block()), nullptr); 317fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(entry), cfg.pseudo_entry_block()); 318fd4e5da5Sopenharmony_ci 319fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 9)), 320fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 8)); 321fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 10)), 322fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 9)); 323fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 11)), 324fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 9)); 325fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 12)), 326fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 11)); 327fd4e5da5Sopenharmony_ci } 328fd4e5da5Sopenharmony_ci 329fd4e5da5Sopenharmony_ci // Check post dominator tree 330fd4e5da5Sopenharmony_ci { 331fd4e5da5Sopenharmony_ci PostDominatorAnalysis dom_tree; 332fd4e5da5Sopenharmony_ci const CFG& cfg = *context->cfg(); 333fd4e5da5Sopenharmony_ci dom_tree.InitializeTree(cfg, fn); 334fd4e5da5Sopenharmony_ci 335fd4e5da5Sopenharmony_ci // Inspect the actual tree 336fd4e5da5Sopenharmony_ci DominatorTree& tree = dom_tree.GetDomTree(); 337fd4e5da5Sopenharmony_ci EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_exit_block()); 338fd4e5da5Sopenharmony_ci EXPECT_TRUE(dom_tree.Dominates(cfg.pseudo_exit_block()->id(), 12)); 339fd4e5da5Sopenharmony_ci 340fd4e5da5Sopenharmony_ci // (strict) dominance checks 341fd4e5da5Sopenharmony_ci for (uint32_t id : {8, 9, 10, 11, 12}) 342fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, id, id); 343fd4e5da5Sopenharmony_ci 344fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 12, 8); 345fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 12, 10); 346fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 12, 11); 347fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 12, 12); 348fd4e5da5Sopenharmony_ci 349fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 11, 8); 350fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 11, 9); 351fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 11, 10); 352fd4e5da5Sopenharmony_ci 353fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 9, 8); 354fd4e5da5Sopenharmony_ci 355fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(entry), 356fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 9)); 357fd4e5da5Sopenharmony_ci 358fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 9)), 359fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 11)); 360fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 10)), 361fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 11)); 362fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 11)), 363fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 12)); 364fd4e5da5Sopenharmony_ci 365fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 12)), 366fd4e5da5Sopenharmony_ci cfg.pseudo_exit_block()); 367fd4e5da5Sopenharmony_ci 368fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_exit_block()), nullptr); 369fd4e5da5Sopenharmony_ci } 370fd4e5da5Sopenharmony_ci} 371fd4e5da5Sopenharmony_ci 372fd4e5da5Sopenharmony_ciTEST_F(PassClassTest, DominatorLoopToSelf) { 373fd4e5da5Sopenharmony_ci const std::string text = R"( 374fd4e5da5Sopenharmony_ci OpCapability Addresses 375fd4e5da5Sopenharmony_ci OpCapability Kernel 376fd4e5da5Sopenharmony_ci OpMemoryModel Physical64 OpenCL 377fd4e5da5Sopenharmony_ci OpEntryPoint Kernel %1 "main" 378fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 379fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 380fd4e5da5Sopenharmony_ci %4 = OpTypeBool 381fd4e5da5Sopenharmony_ci %5 = OpTypeInt 32 0 382fd4e5da5Sopenharmony_ci %6 = OpConstant %5 0 383fd4e5da5Sopenharmony_ci %7 = OpConstantFalse %4 384fd4e5da5Sopenharmony_ci %8 = OpConstantTrue %4 385fd4e5da5Sopenharmony_ci %9 = OpConstant %5 1 386fd4e5da5Sopenharmony_ci %1 = OpFunction %2 None %3 387fd4e5da5Sopenharmony_ci %10 = OpLabel 388fd4e5da5Sopenharmony_ci OpBranch %11 389fd4e5da5Sopenharmony_ci %11 = OpLabel 390fd4e5da5Sopenharmony_ci OpSwitch %6 %12 1 %11 391fd4e5da5Sopenharmony_ci %12 = OpLabel 392fd4e5da5Sopenharmony_ci OpReturn 393fd4e5da5Sopenharmony_ci OpFunctionEnd 394fd4e5da5Sopenharmony_ci)"; 395fd4e5da5Sopenharmony_ci // clang-format on 396fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 397fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_0, nullptr, text, 398fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 399fd4e5da5Sopenharmony_ci Module* module = context->module(); 400fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" 401fd4e5da5Sopenharmony_ci << text << std::endl; 402fd4e5da5Sopenharmony_ci const Function* fn = spvtest::GetFunction(module, 1); 403fd4e5da5Sopenharmony_ci 404fd4e5da5Sopenharmony_ci const BasicBlock* entry = spvtest::GetBasicBlock(fn, 10); 405fd4e5da5Sopenharmony_ci EXPECT_EQ(entry, fn->entry().get()) 406fd4e5da5Sopenharmony_ci << "The entry node is not the expected one"; 407fd4e5da5Sopenharmony_ci 408fd4e5da5Sopenharmony_ci // Check normal dominator tree 409fd4e5da5Sopenharmony_ci { 410fd4e5da5Sopenharmony_ci DominatorAnalysis dom_tree; 411fd4e5da5Sopenharmony_ci const CFG& cfg = *context->cfg(); 412fd4e5da5Sopenharmony_ci dom_tree.InitializeTree(cfg, fn); 413fd4e5da5Sopenharmony_ci 414fd4e5da5Sopenharmony_ci // Inspect the actual tree 415fd4e5da5Sopenharmony_ci DominatorTree& tree = dom_tree.GetDomTree(); 416fd4e5da5Sopenharmony_ci EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_entry_block()); 417fd4e5da5Sopenharmony_ci EXPECT_TRUE( 418fd4e5da5Sopenharmony_ci dom_tree.Dominates(cfg.pseudo_entry_block()->id(), entry->id())); 419fd4e5da5Sopenharmony_ci 420fd4e5da5Sopenharmony_ci // (strict) dominance checks 421fd4e5da5Sopenharmony_ci for (uint32_t id : {10, 11, 12}) check_dominance(dom_tree, fn, id, id); 422fd4e5da5Sopenharmony_ci 423fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 10, 11); 424fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 10, 12); 425fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 11, 12); 426fd4e5da5Sopenharmony_ci 427fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_entry_block()), nullptr); 428fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(entry), cfg.pseudo_entry_block()); 429fd4e5da5Sopenharmony_ci 430fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 11)), 431fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 10)); 432fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 12)), 433fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 11)); 434fd4e5da5Sopenharmony_ci 435fd4e5da5Sopenharmony_ci std::array<uint32_t, 3> node_order = {{10, 11, 12}}; 436fd4e5da5Sopenharmony_ci { 437fd4e5da5Sopenharmony_ci // Test dominator tree iteration order. 438fd4e5da5Sopenharmony_ci DominatorTree::iterator node_it = dom_tree.GetDomTree().begin(); 439fd4e5da5Sopenharmony_ci DominatorTree::iterator node_end = dom_tree.GetDomTree().end(); 440fd4e5da5Sopenharmony_ci for (uint32_t id : node_order) { 441fd4e5da5Sopenharmony_ci EXPECT_NE(node_it, node_end); 442fd4e5da5Sopenharmony_ci EXPECT_EQ(node_it->id(), id); 443fd4e5da5Sopenharmony_ci node_it++; 444fd4e5da5Sopenharmony_ci } 445fd4e5da5Sopenharmony_ci EXPECT_EQ(node_it, node_end); 446fd4e5da5Sopenharmony_ci } 447fd4e5da5Sopenharmony_ci { 448fd4e5da5Sopenharmony_ci // Same as above, but with const iterators. 449fd4e5da5Sopenharmony_ci DominatorTree::const_iterator node_it = dom_tree.GetDomTree().cbegin(); 450fd4e5da5Sopenharmony_ci DominatorTree::const_iterator node_end = dom_tree.GetDomTree().cend(); 451fd4e5da5Sopenharmony_ci for (uint32_t id : node_order) { 452fd4e5da5Sopenharmony_ci EXPECT_NE(node_it, node_end); 453fd4e5da5Sopenharmony_ci EXPECT_EQ(node_it->id(), id); 454fd4e5da5Sopenharmony_ci node_it++; 455fd4e5da5Sopenharmony_ci } 456fd4e5da5Sopenharmony_ci EXPECT_EQ(node_it, node_end); 457fd4e5da5Sopenharmony_ci } 458fd4e5da5Sopenharmony_ci { 459fd4e5da5Sopenharmony_ci // Test dominator tree iteration order. 460fd4e5da5Sopenharmony_ci DominatorTree::post_iterator node_it = dom_tree.GetDomTree().post_begin(); 461fd4e5da5Sopenharmony_ci DominatorTree::post_iterator node_end = dom_tree.GetDomTree().post_end(); 462fd4e5da5Sopenharmony_ci for (uint32_t id : make_range(node_order.rbegin(), node_order.rend())) { 463fd4e5da5Sopenharmony_ci EXPECT_NE(node_it, node_end); 464fd4e5da5Sopenharmony_ci EXPECT_EQ(node_it->id(), id); 465fd4e5da5Sopenharmony_ci node_it++; 466fd4e5da5Sopenharmony_ci } 467fd4e5da5Sopenharmony_ci EXPECT_EQ(node_it, node_end); 468fd4e5da5Sopenharmony_ci } 469fd4e5da5Sopenharmony_ci { 470fd4e5da5Sopenharmony_ci // Same as above, but with const iterators. 471fd4e5da5Sopenharmony_ci DominatorTree::const_post_iterator node_it = 472fd4e5da5Sopenharmony_ci dom_tree.GetDomTree().post_cbegin(); 473fd4e5da5Sopenharmony_ci DominatorTree::const_post_iterator node_end = 474fd4e5da5Sopenharmony_ci dom_tree.GetDomTree().post_cend(); 475fd4e5da5Sopenharmony_ci for (uint32_t id : make_range(node_order.rbegin(), node_order.rend())) { 476fd4e5da5Sopenharmony_ci EXPECT_NE(node_it, node_end); 477fd4e5da5Sopenharmony_ci EXPECT_EQ(node_it->id(), id); 478fd4e5da5Sopenharmony_ci node_it++; 479fd4e5da5Sopenharmony_ci } 480fd4e5da5Sopenharmony_ci EXPECT_EQ(node_it, node_end); 481fd4e5da5Sopenharmony_ci } 482fd4e5da5Sopenharmony_ci } 483fd4e5da5Sopenharmony_ci 484fd4e5da5Sopenharmony_ci // Check post dominator tree 485fd4e5da5Sopenharmony_ci { 486fd4e5da5Sopenharmony_ci PostDominatorAnalysis dom_tree; 487fd4e5da5Sopenharmony_ci const CFG& cfg = *context->cfg(); 488fd4e5da5Sopenharmony_ci dom_tree.InitializeTree(cfg, fn); 489fd4e5da5Sopenharmony_ci 490fd4e5da5Sopenharmony_ci // Inspect the actual tree 491fd4e5da5Sopenharmony_ci DominatorTree& tree = dom_tree.GetDomTree(); 492fd4e5da5Sopenharmony_ci EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_exit_block()); 493fd4e5da5Sopenharmony_ci EXPECT_TRUE(dom_tree.Dominates(cfg.pseudo_exit_block()->id(), 12)); 494fd4e5da5Sopenharmony_ci 495fd4e5da5Sopenharmony_ci // (strict) dominance checks 496fd4e5da5Sopenharmony_ci for (uint32_t id : {10, 11, 12}) check_dominance(dom_tree, fn, id, id); 497fd4e5da5Sopenharmony_ci 498fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 12, 10); 499fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 12, 11); 500fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 12, 12); 501fd4e5da5Sopenharmony_ci 502fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(entry), 503fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 11)); 504fd4e5da5Sopenharmony_ci 505fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 11)), 506fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 12)); 507fd4e5da5Sopenharmony_ci 508fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_exit_block()), nullptr); 509fd4e5da5Sopenharmony_ci 510fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 12)), 511fd4e5da5Sopenharmony_ci cfg.pseudo_exit_block()); 512fd4e5da5Sopenharmony_ci 513fd4e5da5Sopenharmony_ci std::array<uint32_t, 3> node_order = {{12, 11, 10}}; 514fd4e5da5Sopenharmony_ci { 515fd4e5da5Sopenharmony_ci // Test dominator tree iteration order. 516fd4e5da5Sopenharmony_ci DominatorTree::iterator node_it = tree.begin(); 517fd4e5da5Sopenharmony_ci DominatorTree::iterator node_end = tree.end(); 518fd4e5da5Sopenharmony_ci for (uint32_t id : node_order) { 519fd4e5da5Sopenharmony_ci EXPECT_NE(node_it, node_end); 520fd4e5da5Sopenharmony_ci EXPECT_EQ(node_it->id(), id); 521fd4e5da5Sopenharmony_ci node_it++; 522fd4e5da5Sopenharmony_ci } 523fd4e5da5Sopenharmony_ci EXPECT_EQ(node_it, node_end); 524fd4e5da5Sopenharmony_ci } 525fd4e5da5Sopenharmony_ci { 526fd4e5da5Sopenharmony_ci // Same as above, but with const iterators. 527fd4e5da5Sopenharmony_ci DominatorTree::const_iterator node_it = tree.cbegin(); 528fd4e5da5Sopenharmony_ci DominatorTree::const_iterator node_end = tree.cend(); 529fd4e5da5Sopenharmony_ci for (uint32_t id : node_order) { 530fd4e5da5Sopenharmony_ci EXPECT_NE(node_it, node_end); 531fd4e5da5Sopenharmony_ci EXPECT_EQ(node_it->id(), id); 532fd4e5da5Sopenharmony_ci node_it++; 533fd4e5da5Sopenharmony_ci } 534fd4e5da5Sopenharmony_ci EXPECT_EQ(node_it, node_end); 535fd4e5da5Sopenharmony_ci } 536fd4e5da5Sopenharmony_ci { 537fd4e5da5Sopenharmony_ci // Test dominator tree iteration order. 538fd4e5da5Sopenharmony_ci DominatorTree::post_iterator node_it = dom_tree.GetDomTree().post_begin(); 539fd4e5da5Sopenharmony_ci DominatorTree::post_iterator node_end = dom_tree.GetDomTree().post_end(); 540fd4e5da5Sopenharmony_ci for (uint32_t id : make_range(node_order.rbegin(), node_order.rend())) { 541fd4e5da5Sopenharmony_ci EXPECT_NE(node_it, node_end); 542fd4e5da5Sopenharmony_ci EXPECT_EQ(node_it->id(), id); 543fd4e5da5Sopenharmony_ci node_it++; 544fd4e5da5Sopenharmony_ci } 545fd4e5da5Sopenharmony_ci EXPECT_EQ(node_it, node_end); 546fd4e5da5Sopenharmony_ci } 547fd4e5da5Sopenharmony_ci { 548fd4e5da5Sopenharmony_ci // Same as above, but with const iterators. 549fd4e5da5Sopenharmony_ci DominatorTree::const_post_iterator node_it = 550fd4e5da5Sopenharmony_ci dom_tree.GetDomTree().post_cbegin(); 551fd4e5da5Sopenharmony_ci DominatorTree::const_post_iterator node_end = 552fd4e5da5Sopenharmony_ci dom_tree.GetDomTree().post_cend(); 553fd4e5da5Sopenharmony_ci for (uint32_t id : make_range(node_order.rbegin(), node_order.rend())) { 554fd4e5da5Sopenharmony_ci EXPECT_NE(node_it, node_end); 555fd4e5da5Sopenharmony_ci EXPECT_EQ(node_it->id(), id); 556fd4e5da5Sopenharmony_ci node_it++; 557fd4e5da5Sopenharmony_ci } 558fd4e5da5Sopenharmony_ci EXPECT_EQ(node_it, node_end); 559fd4e5da5Sopenharmony_ci } 560fd4e5da5Sopenharmony_ci } 561fd4e5da5Sopenharmony_ci} 562fd4e5da5Sopenharmony_ci 563fd4e5da5Sopenharmony_ciTEST_F(PassClassTest, DominatorUnreachableInLoop) { 564fd4e5da5Sopenharmony_ci const std::string text = R"( 565fd4e5da5Sopenharmony_ci OpCapability Addresses 566fd4e5da5Sopenharmony_ci OpCapability Kernel 567fd4e5da5Sopenharmony_ci OpMemoryModel Physical64 OpenCL 568fd4e5da5Sopenharmony_ci OpEntryPoint Kernel %1 "main" 569fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 570fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 571fd4e5da5Sopenharmony_ci %4 = OpTypeBool 572fd4e5da5Sopenharmony_ci %5 = OpTypeInt 32 0 573fd4e5da5Sopenharmony_ci %6 = OpConstant %5 0 574fd4e5da5Sopenharmony_ci %7 = OpConstantFalse %4 575fd4e5da5Sopenharmony_ci %8 = OpConstantTrue %4 576fd4e5da5Sopenharmony_ci %9 = OpConstant %5 1 577fd4e5da5Sopenharmony_ci %1 = OpFunction %2 None %3 578fd4e5da5Sopenharmony_ci %10 = OpLabel 579fd4e5da5Sopenharmony_ci OpBranch %11 580fd4e5da5Sopenharmony_ci %11 = OpLabel 581fd4e5da5Sopenharmony_ci OpSwitch %6 %12 1 %13 582fd4e5da5Sopenharmony_ci %12 = OpLabel 583fd4e5da5Sopenharmony_ci OpBranch %14 584fd4e5da5Sopenharmony_ci %13 = OpLabel 585fd4e5da5Sopenharmony_ci OpUnreachable 586fd4e5da5Sopenharmony_ci %14 = OpLabel 587fd4e5da5Sopenharmony_ci OpBranchConditional %8 %11 %15 588fd4e5da5Sopenharmony_ci %15 = OpLabel 589fd4e5da5Sopenharmony_ci OpReturn 590fd4e5da5Sopenharmony_ci OpFunctionEnd 591fd4e5da5Sopenharmony_ci)"; 592fd4e5da5Sopenharmony_ci // clang-format on 593fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 594fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_0, nullptr, text, 595fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 596fd4e5da5Sopenharmony_ci Module* module = context->module(); 597fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" 598fd4e5da5Sopenharmony_ci << text << std::endl; 599fd4e5da5Sopenharmony_ci const Function* fn = spvtest::GetFunction(module, 1); 600fd4e5da5Sopenharmony_ci 601fd4e5da5Sopenharmony_ci const BasicBlock* entry = spvtest::GetBasicBlock(fn, 10); 602fd4e5da5Sopenharmony_ci EXPECT_EQ(entry, fn->entry().get()) 603fd4e5da5Sopenharmony_ci << "The entry node is not the expected one"; 604fd4e5da5Sopenharmony_ci 605fd4e5da5Sopenharmony_ci // Check normal dominator tree 606fd4e5da5Sopenharmony_ci { 607fd4e5da5Sopenharmony_ci DominatorAnalysis dom_tree; 608fd4e5da5Sopenharmony_ci const CFG& cfg = *context->cfg(); 609fd4e5da5Sopenharmony_ci dom_tree.InitializeTree(cfg, fn); 610fd4e5da5Sopenharmony_ci 611fd4e5da5Sopenharmony_ci // Inspect the actual tree 612fd4e5da5Sopenharmony_ci DominatorTree& tree = dom_tree.GetDomTree(); 613fd4e5da5Sopenharmony_ci EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_entry_block()); 614fd4e5da5Sopenharmony_ci EXPECT_TRUE( 615fd4e5da5Sopenharmony_ci dom_tree.Dominates(cfg.pseudo_entry_block()->id(), entry->id())); 616fd4e5da5Sopenharmony_ci 617fd4e5da5Sopenharmony_ci // (strict) dominance checks 618fd4e5da5Sopenharmony_ci for (uint32_t id : {10, 11, 12, 13, 14, 15}) 619fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, id, id); 620fd4e5da5Sopenharmony_ci 621fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 10, 11); 622fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 10, 13); 623fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 10, 12); 624fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 10, 14); 625fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 10, 15); 626fd4e5da5Sopenharmony_ci 627fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 11, 12); 628fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 11, 13); 629fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 11, 14); 630fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 11, 15); 631fd4e5da5Sopenharmony_ci 632fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 12, 14); 633fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 12, 15); 634fd4e5da5Sopenharmony_ci 635fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 14, 15); 636fd4e5da5Sopenharmony_ci 637fd4e5da5Sopenharmony_ci check_no_dominance(dom_tree, fn, 13, 12); 638fd4e5da5Sopenharmony_ci check_no_dominance(dom_tree, fn, 13, 14); 639fd4e5da5Sopenharmony_ci check_no_dominance(dom_tree, fn, 13, 15); 640fd4e5da5Sopenharmony_ci 641fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_entry_block()), nullptr); 642fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(entry), cfg.pseudo_entry_block()); 643fd4e5da5Sopenharmony_ci 644fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 11)), 645fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 10)); 646fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 12)), 647fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 11)); 648fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 13)), 649fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 11)); 650fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 14)), 651fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 12)); 652fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 15)), 653fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 14)); 654fd4e5da5Sopenharmony_ci } 655fd4e5da5Sopenharmony_ci 656fd4e5da5Sopenharmony_ci // Check post dominator tree. 657fd4e5da5Sopenharmony_ci { 658fd4e5da5Sopenharmony_ci PostDominatorAnalysis dom_tree; 659fd4e5da5Sopenharmony_ci const CFG& cfg = *context->cfg(); 660fd4e5da5Sopenharmony_ci dom_tree.InitializeTree(cfg, fn); 661fd4e5da5Sopenharmony_ci 662fd4e5da5Sopenharmony_ci // (strict) dominance checks. 663fd4e5da5Sopenharmony_ci for (uint32_t id : {10, 11, 12, 13, 14, 15}) 664fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, id, id); 665fd4e5da5Sopenharmony_ci 666fd4e5da5Sopenharmony_ci check_no_dominance(dom_tree, fn, 15, 10); 667fd4e5da5Sopenharmony_ci check_no_dominance(dom_tree, fn, 15, 11); 668fd4e5da5Sopenharmony_ci check_no_dominance(dom_tree, fn, 15, 12); 669fd4e5da5Sopenharmony_ci check_no_dominance(dom_tree, fn, 15, 13); 670fd4e5da5Sopenharmony_ci check_no_dominance(dom_tree, fn, 15, 14); 671fd4e5da5Sopenharmony_ci 672fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 14, 12); 673fd4e5da5Sopenharmony_ci 674fd4e5da5Sopenharmony_ci check_no_dominance(dom_tree, fn, 13, 10); 675fd4e5da5Sopenharmony_ci check_no_dominance(dom_tree, fn, 13, 11); 676fd4e5da5Sopenharmony_ci check_no_dominance(dom_tree, fn, 13, 12); 677fd4e5da5Sopenharmony_ci check_no_dominance(dom_tree, fn, 13, 14); 678fd4e5da5Sopenharmony_ci check_no_dominance(dom_tree, fn, 13, 15); 679fd4e5da5Sopenharmony_ci 680fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 10)), 681fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 11)); 682fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 12)), 683fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 14)); 684fd4e5da5Sopenharmony_ci 685fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_exit_block()), nullptr); 686fd4e5da5Sopenharmony_ci 687fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 15)), 688fd4e5da5Sopenharmony_ci cfg.pseudo_exit_block()); 689fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 13)), 690fd4e5da5Sopenharmony_ci cfg.pseudo_exit_block()); 691fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 14)), 692fd4e5da5Sopenharmony_ci cfg.pseudo_exit_block()); 693fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 11)), 694fd4e5da5Sopenharmony_ci cfg.pseudo_exit_block()); 695fd4e5da5Sopenharmony_ci } 696fd4e5da5Sopenharmony_ci} 697fd4e5da5Sopenharmony_ci 698fd4e5da5Sopenharmony_ciTEST_F(PassClassTest, DominatorInfinitLoop) { 699fd4e5da5Sopenharmony_ci const std::string text = R"( 700fd4e5da5Sopenharmony_ci OpCapability Addresses 701fd4e5da5Sopenharmony_ci OpCapability Kernel 702fd4e5da5Sopenharmony_ci OpMemoryModel Physical64 OpenCL 703fd4e5da5Sopenharmony_ci OpEntryPoint Kernel %1 "main" 704fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 705fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 706fd4e5da5Sopenharmony_ci %4 = OpTypeBool 707fd4e5da5Sopenharmony_ci %5 = OpTypeInt 32 0 708fd4e5da5Sopenharmony_ci %6 = OpConstant %5 0 709fd4e5da5Sopenharmony_ci %7 = OpConstantFalse %4 710fd4e5da5Sopenharmony_ci %8 = OpConstantTrue %4 711fd4e5da5Sopenharmony_ci %9 = OpConstant %5 1 712fd4e5da5Sopenharmony_ci %1 = OpFunction %2 None %3 713fd4e5da5Sopenharmony_ci %10 = OpLabel 714fd4e5da5Sopenharmony_ci OpBranch %11 715fd4e5da5Sopenharmony_ci %11 = OpLabel 716fd4e5da5Sopenharmony_ci OpSwitch %6 %12 1 %13 717fd4e5da5Sopenharmony_ci %12 = OpLabel 718fd4e5da5Sopenharmony_ci OpReturn 719fd4e5da5Sopenharmony_ci %13 = OpLabel 720fd4e5da5Sopenharmony_ci OpBranch %13 721fd4e5da5Sopenharmony_ci OpFunctionEnd 722fd4e5da5Sopenharmony_ci)"; 723fd4e5da5Sopenharmony_ci // clang-format on 724fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 725fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_0, nullptr, text, 726fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 727fd4e5da5Sopenharmony_ci Module* module = context->module(); 728fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" 729fd4e5da5Sopenharmony_ci << text << std::endl; 730fd4e5da5Sopenharmony_ci const Function* fn = spvtest::GetFunction(module, 1); 731fd4e5da5Sopenharmony_ci 732fd4e5da5Sopenharmony_ci const BasicBlock* entry = spvtest::GetBasicBlock(fn, 10); 733fd4e5da5Sopenharmony_ci EXPECT_EQ(entry, fn->entry().get()) 734fd4e5da5Sopenharmony_ci << "The entry node is not the expected one"; 735fd4e5da5Sopenharmony_ci // Check normal dominator tree 736fd4e5da5Sopenharmony_ci { 737fd4e5da5Sopenharmony_ci DominatorAnalysis dom_tree; 738fd4e5da5Sopenharmony_ci const CFG& cfg = *context->cfg(); 739fd4e5da5Sopenharmony_ci dom_tree.InitializeTree(cfg, fn); 740fd4e5da5Sopenharmony_ci 741fd4e5da5Sopenharmony_ci // Inspect the actual tree 742fd4e5da5Sopenharmony_ci DominatorTree& tree = dom_tree.GetDomTree(); 743fd4e5da5Sopenharmony_ci EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_entry_block()); 744fd4e5da5Sopenharmony_ci EXPECT_TRUE( 745fd4e5da5Sopenharmony_ci dom_tree.Dominates(cfg.pseudo_entry_block()->id(), entry->id())); 746fd4e5da5Sopenharmony_ci 747fd4e5da5Sopenharmony_ci // (strict) dominance checks 748fd4e5da5Sopenharmony_ci for (uint32_t id : {10, 11, 12, 13}) check_dominance(dom_tree, fn, id, id); 749fd4e5da5Sopenharmony_ci 750fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 10, 11); 751fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 10, 12); 752fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 10, 13); 753fd4e5da5Sopenharmony_ci 754fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 11, 12); 755fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 11, 13); 756fd4e5da5Sopenharmony_ci 757fd4e5da5Sopenharmony_ci check_no_dominance(dom_tree, fn, 13, 12); 758fd4e5da5Sopenharmony_ci 759fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_entry_block()), nullptr); 760fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(entry), cfg.pseudo_entry_block()); 761fd4e5da5Sopenharmony_ci 762fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 11)), 763fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 10)); 764fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 12)), 765fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 11)); 766fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 13)), 767fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 11)); 768fd4e5da5Sopenharmony_ci } 769fd4e5da5Sopenharmony_ci 770fd4e5da5Sopenharmony_ci // Check post dominator tree 771fd4e5da5Sopenharmony_ci { 772fd4e5da5Sopenharmony_ci PostDominatorAnalysis dom_tree; 773fd4e5da5Sopenharmony_ci const CFG& cfg = *context->cfg(); 774fd4e5da5Sopenharmony_ci dom_tree.InitializeTree(cfg, fn); 775fd4e5da5Sopenharmony_ci 776fd4e5da5Sopenharmony_ci // Inspect the actual tree 777fd4e5da5Sopenharmony_ci DominatorTree& tree = dom_tree.GetDomTree(); 778fd4e5da5Sopenharmony_ci EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_exit_block()); 779fd4e5da5Sopenharmony_ci EXPECT_TRUE(dom_tree.Dominates(cfg.pseudo_exit_block()->id(), 12)); 780fd4e5da5Sopenharmony_ci 781fd4e5da5Sopenharmony_ci // (strict) dominance checks 782fd4e5da5Sopenharmony_ci for (uint32_t id : {10, 11, 12}) check_dominance(dom_tree, fn, id, id); 783fd4e5da5Sopenharmony_ci 784fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 12, 11); 785fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 12, 10); 786fd4e5da5Sopenharmony_ci 787fd4e5da5Sopenharmony_ci // 13 should be completely out of tree as it's unreachable from exit nodes 788fd4e5da5Sopenharmony_ci check_no_dominance(dom_tree, fn, 12, 13); 789fd4e5da5Sopenharmony_ci check_no_dominance(dom_tree, fn, 11, 13); 790fd4e5da5Sopenharmony_ci check_no_dominance(dom_tree, fn, 10, 13); 791fd4e5da5Sopenharmony_ci 792fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_exit_block()), nullptr); 793fd4e5da5Sopenharmony_ci 794fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 12)), 795fd4e5da5Sopenharmony_ci cfg.pseudo_exit_block()); 796fd4e5da5Sopenharmony_ci 797fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 10)), 798fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 11)); 799fd4e5da5Sopenharmony_ci 800fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 11)), 801fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 12)); 802fd4e5da5Sopenharmony_ci } 803fd4e5da5Sopenharmony_ci} 804fd4e5da5Sopenharmony_ci 805fd4e5da5Sopenharmony_ciTEST_F(PassClassTest, DominatorUnreachableFromEntry) { 806fd4e5da5Sopenharmony_ci const std::string text = R"( 807fd4e5da5Sopenharmony_ci OpCapability Addresses 808fd4e5da5Sopenharmony_ci OpCapability Addresses 809fd4e5da5Sopenharmony_ci OpCapability Kernel 810fd4e5da5Sopenharmony_ci OpMemoryModel Physical64 OpenCL 811fd4e5da5Sopenharmony_ci OpEntryPoint Kernel %1 "main" 812fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 813fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 814fd4e5da5Sopenharmony_ci %4 = OpTypeBool 815fd4e5da5Sopenharmony_ci %5 = OpTypeInt 32 0 816fd4e5da5Sopenharmony_ci %6 = OpConstantFalse %4 817fd4e5da5Sopenharmony_ci %7 = OpConstantTrue %4 818fd4e5da5Sopenharmony_ci %1 = OpFunction %2 None %3 819fd4e5da5Sopenharmony_ci %8 = OpLabel 820fd4e5da5Sopenharmony_ci OpBranch %9 821fd4e5da5Sopenharmony_ci %9 = OpLabel 822fd4e5da5Sopenharmony_ci OpReturn 823fd4e5da5Sopenharmony_ci %10 = OpLabel 824fd4e5da5Sopenharmony_ci OpBranch %9 825fd4e5da5Sopenharmony_ci OpFunctionEnd 826fd4e5da5Sopenharmony_ci)"; 827fd4e5da5Sopenharmony_ci // clang-format on 828fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 829fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_0, nullptr, text, 830fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 831fd4e5da5Sopenharmony_ci Module* module = context->module(); 832fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" 833fd4e5da5Sopenharmony_ci << text << std::endl; 834fd4e5da5Sopenharmony_ci const Function* fn = spvtest::GetFunction(module, 1); 835fd4e5da5Sopenharmony_ci 836fd4e5da5Sopenharmony_ci const BasicBlock* entry = spvtest::GetBasicBlock(fn, 8); 837fd4e5da5Sopenharmony_ci EXPECT_EQ(entry, fn->entry().get()) 838fd4e5da5Sopenharmony_ci << "The entry node is not the expected one"; 839fd4e5da5Sopenharmony_ci 840fd4e5da5Sopenharmony_ci // Check dominator tree 841fd4e5da5Sopenharmony_ci { 842fd4e5da5Sopenharmony_ci DominatorAnalysis dom_tree; 843fd4e5da5Sopenharmony_ci const CFG& cfg = *context->cfg(); 844fd4e5da5Sopenharmony_ci dom_tree.InitializeTree(cfg, fn); 845fd4e5da5Sopenharmony_ci 846fd4e5da5Sopenharmony_ci // Inspect the actual tree 847fd4e5da5Sopenharmony_ci DominatorTree& tree = dom_tree.GetDomTree(); 848fd4e5da5Sopenharmony_ci EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_entry_block()); 849fd4e5da5Sopenharmony_ci EXPECT_TRUE( 850fd4e5da5Sopenharmony_ci dom_tree.Dominates(cfg.pseudo_entry_block()->id(), entry->id())); 851fd4e5da5Sopenharmony_ci 852fd4e5da5Sopenharmony_ci // (strict) dominance checks 853fd4e5da5Sopenharmony_ci for (uint32_t id : {8, 9}) check_dominance(dom_tree, fn, id, id); 854fd4e5da5Sopenharmony_ci 855fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 8, 9); 856fd4e5da5Sopenharmony_ci 857fd4e5da5Sopenharmony_ci check_no_dominance(dom_tree, fn, 10, 8); 858fd4e5da5Sopenharmony_ci check_no_dominance(dom_tree, fn, 10, 9); 859fd4e5da5Sopenharmony_ci 860fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_entry_block()), nullptr); 861fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(entry), cfg.pseudo_entry_block()); 862fd4e5da5Sopenharmony_ci 863fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 9)), 864fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 8)); 865fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 10)), 866fd4e5da5Sopenharmony_ci nullptr); 867fd4e5da5Sopenharmony_ci } 868fd4e5da5Sopenharmony_ci 869fd4e5da5Sopenharmony_ci // Check post dominator tree 870fd4e5da5Sopenharmony_ci { 871fd4e5da5Sopenharmony_ci PostDominatorAnalysis dom_tree; 872fd4e5da5Sopenharmony_ci const CFG& cfg = *context->cfg(); 873fd4e5da5Sopenharmony_ci dom_tree.InitializeTree(cfg, fn); 874fd4e5da5Sopenharmony_ci 875fd4e5da5Sopenharmony_ci // Inspect the actual tree 876fd4e5da5Sopenharmony_ci DominatorTree& tree = dom_tree.GetDomTree(); 877fd4e5da5Sopenharmony_ci EXPECT_EQ(tree.GetRoot()->bb_, cfg.pseudo_exit_block()); 878fd4e5da5Sopenharmony_ci EXPECT_TRUE(dom_tree.Dominates(cfg.pseudo_exit_block()->id(), 9)); 879fd4e5da5Sopenharmony_ci 880fd4e5da5Sopenharmony_ci // (strict) dominance checks 881fd4e5da5Sopenharmony_ci for (uint32_t id : {8, 9, 10}) check_dominance(dom_tree, fn, id, id); 882fd4e5da5Sopenharmony_ci 883fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 9, 8); 884fd4e5da5Sopenharmony_ci check_dominance(dom_tree, fn, 9, 10); 885fd4e5da5Sopenharmony_ci 886fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(entry), 887fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 9)); 888fd4e5da5Sopenharmony_ci 889fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(cfg.pseudo_exit_block()), nullptr); 890fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 9)), 891fd4e5da5Sopenharmony_ci cfg.pseudo_exit_block()); 892fd4e5da5Sopenharmony_ci EXPECT_EQ(dom_tree.ImmediateDominator(spvtest::GetBasicBlock(fn, 10)), 893fd4e5da5Sopenharmony_ci spvtest::GetBasicBlock(fn, 9)); 894fd4e5da5Sopenharmony_ci } 895fd4e5da5Sopenharmony_ci} 896fd4e5da5Sopenharmony_ci 897fd4e5da5Sopenharmony_ciTEST_F(PassClassTest, DominationForInstructions) { 898fd4e5da5Sopenharmony_ci const std::string text = R"( 899fd4e5da5Sopenharmony_ci OpCapability Shader 900fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 901fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 902fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 903fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 904fd4e5da5Sopenharmony_ci OpSource ESSL 310 905fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 906fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 907fd4e5da5Sopenharmony_ci %6 = OpTypeInt 32 1 908fd4e5da5Sopenharmony_ci %7 = OpTypeBool 909fd4e5da5Sopenharmony_ci %8 = OpConstantTrue %7 910fd4e5da5Sopenharmony_ci %9 = OpConstant %6 37 911fd4e5da5Sopenharmony_ci %10 = OpConstant %6 3 912fd4e5da5Sopenharmony_ci %13 = OpConstant %6 5 913fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 914fd4e5da5Sopenharmony_ci %5 = OpLabel 915fd4e5da5Sopenharmony_ci %12 = OpIAdd %6 %9 %10 916fd4e5da5Sopenharmony_ci %15 = OpISub %6 %12 %13 917fd4e5da5Sopenharmony_ci OpSelectionMerge %18 None 918fd4e5da5Sopenharmony_ci OpBranchConditional %8 %16 %17 919fd4e5da5Sopenharmony_ci %16 = OpLabel 920fd4e5da5Sopenharmony_ci %20 = OpISub %6 %12 %13 921fd4e5da5Sopenharmony_ci OpBranch %18 922fd4e5da5Sopenharmony_ci %17 = OpLabel 923fd4e5da5Sopenharmony_ci %21 = OpISub %6 %12 %13 924fd4e5da5Sopenharmony_ci OpBranch %18 925fd4e5da5Sopenharmony_ci %18 = OpLabel 926fd4e5da5Sopenharmony_ci %22 = OpISub %6 %12 %13 927fd4e5da5Sopenharmony_ci OpReturn 928fd4e5da5Sopenharmony_ci OpFunctionEnd 929fd4e5da5Sopenharmony_ci )"; 930fd4e5da5Sopenharmony_ci 931fd4e5da5Sopenharmony_ci // clang-format on 932fd4e5da5Sopenharmony_ci std::unique_ptr<IRContext> context = 933fd4e5da5Sopenharmony_ci BuildModule(SPV_ENV_UNIVERSAL_1_0, nullptr, text, 934fd4e5da5Sopenharmony_ci SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 935fd4e5da5Sopenharmony_ci EXPECT_NE(nullptr, context->module()) << "Assembling failed for shader:\n" 936fd4e5da5Sopenharmony_ci << text << std::endl; 937fd4e5da5Sopenharmony_ci 938fd4e5da5Sopenharmony_ci { 939fd4e5da5Sopenharmony_ci const DominatorAnalysis* dominator_analysis = context->GetDominatorAnalysis( 940fd4e5da5Sopenharmony_ci spvtest::GetFunction(context->module(), 4)); 941fd4e5da5Sopenharmony_ci 942fd4e5da5Sopenharmony_ci EXPECT_TRUE( 943fd4e5da5Sopenharmony_ci dominator_analysis->Dominates(context->get_def_use_mgr()->GetDef(12), 944fd4e5da5Sopenharmony_ci context->get_def_use_mgr()->GetDef(15))); 945fd4e5da5Sopenharmony_ci EXPECT_FALSE( 946fd4e5da5Sopenharmony_ci dominator_analysis->Dominates(context->get_def_use_mgr()->GetDef(15), 947fd4e5da5Sopenharmony_ci context->get_def_use_mgr()->GetDef(12))); 948fd4e5da5Sopenharmony_ci EXPECT_TRUE( 949fd4e5da5Sopenharmony_ci dominator_analysis->Dominates(context->get_def_use_mgr()->GetDef(5), 950fd4e5da5Sopenharmony_ci context->get_def_use_mgr()->GetDef(12))); 951fd4e5da5Sopenharmony_ci EXPECT_FALSE( 952fd4e5da5Sopenharmony_ci dominator_analysis->Dominates(context->get_def_use_mgr()->GetDef(12), 953fd4e5da5Sopenharmony_ci context->get_def_use_mgr()->GetDef(5))); 954fd4e5da5Sopenharmony_ci EXPECT_TRUE( 955fd4e5da5Sopenharmony_ci dominator_analysis->Dominates(context->get_def_use_mgr()->GetDef(15), 956fd4e5da5Sopenharmony_ci context->get_def_use_mgr()->GetDef(16))); 957fd4e5da5Sopenharmony_ci EXPECT_TRUE( 958fd4e5da5Sopenharmony_ci dominator_analysis->Dominates(context->get_def_use_mgr()->GetDef(15), 959fd4e5da5Sopenharmony_ci context->get_def_use_mgr()->GetDef(21))); 960fd4e5da5Sopenharmony_ci EXPECT_TRUE( 961fd4e5da5Sopenharmony_ci dominator_analysis->Dominates(context->get_def_use_mgr()->GetDef(15), 962fd4e5da5Sopenharmony_ci context->get_def_use_mgr()->GetDef(18))); 963fd4e5da5Sopenharmony_ci EXPECT_TRUE( 964fd4e5da5Sopenharmony_ci dominator_analysis->Dominates(context->get_def_use_mgr()->GetDef(15), 965fd4e5da5Sopenharmony_ci context->get_def_use_mgr()->GetDef(22))); 966fd4e5da5Sopenharmony_ci EXPECT_FALSE( 967fd4e5da5Sopenharmony_ci dominator_analysis->Dominates(context->get_def_use_mgr()->GetDef(20), 968fd4e5da5Sopenharmony_ci context->get_def_use_mgr()->GetDef(22))); 969fd4e5da5Sopenharmony_ci EXPECT_FALSE( 970fd4e5da5Sopenharmony_ci dominator_analysis->Dominates(context->get_def_use_mgr()->GetDef(21), 971fd4e5da5Sopenharmony_ci context->get_def_use_mgr()->GetDef(22))); 972fd4e5da5Sopenharmony_ci EXPECT_TRUE( 973fd4e5da5Sopenharmony_ci dominator_analysis->Dominates(context->get_def_use_mgr()->GetDef(15), 974fd4e5da5Sopenharmony_ci context->get_def_use_mgr()->GetDef(15))); 975fd4e5da5Sopenharmony_ci } 976fd4e5da5Sopenharmony_ci { 977fd4e5da5Sopenharmony_ci const PostDominatorAnalysis* post_dominator_analysis = 978fd4e5da5Sopenharmony_ci context->GetPostDominatorAnalysis( 979fd4e5da5Sopenharmony_ci spvtest::GetFunction(context->module(), 4)); 980fd4e5da5Sopenharmony_ci 981fd4e5da5Sopenharmony_ci EXPECT_TRUE(post_dominator_analysis->Dominates( 982fd4e5da5Sopenharmony_ci context->get_def_use_mgr()->GetDef(15), 983fd4e5da5Sopenharmony_ci context->get_def_use_mgr()->GetDef(12))); 984fd4e5da5Sopenharmony_ci EXPECT_FALSE(post_dominator_analysis->Dominates( 985fd4e5da5Sopenharmony_ci context->get_def_use_mgr()->GetDef(12), 986fd4e5da5Sopenharmony_ci context->get_def_use_mgr()->GetDef(15))); 987fd4e5da5Sopenharmony_ci EXPECT_TRUE(post_dominator_analysis->Dominates( 988fd4e5da5Sopenharmony_ci context->get_def_use_mgr()->GetDef(12), 989fd4e5da5Sopenharmony_ci context->get_def_use_mgr()->GetDef(5))); 990fd4e5da5Sopenharmony_ci EXPECT_FALSE(post_dominator_analysis->Dominates( 991fd4e5da5Sopenharmony_ci context->get_def_use_mgr()->GetDef(5), 992fd4e5da5Sopenharmony_ci context->get_def_use_mgr()->GetDef(12))); 993fd4e5da5Sopenharmony_ci EXPECT_FALSE(post_dominator_analysis->Dominates( 994fd4e5da5Sopenharmony_ci context->get_def_use_mgr()->GetDef(16), 995fd4e5da5Sopenharmony_ci context->get_def_use_mgr()->GetDef(15))); 996fd4e5da5Sopenharmony_ci EXPECT_FALSE(post_dominator_analysis->Dominates( 997fd4e5da5Sopenharmony_ci context->get_def_use_mgr()->GetDef(21), 998fd4e5da5Sopenharmony_ci context->get_def_use_mgr()->GetDef(15))); 999fd4e5da5Sopenharmony_ci EXPECT_TRUE(post_dominator_analysis->Dominates( 1000fd4e5da5Sopenharmony_ci context->get_def_use_mgr()->GetDef(18), 1001fd4e5da5Sopenharmony_ci context->get_def_use_mgr()->GetDef(15))); 1002fd4e5da5Sopenharmony_ci EXPECT_TRUE(post_dominator_analysis->Dominates( 1003fd4e5da5Sopenharmony_ci context->get_def_use_mgr()->GetDef(22), 1004fd4e5da5Sopenharmony_ci context->get_def_use_mgr()->GetDef(15))); 1005fd4e5da5Sopenharmony_ci EXPECT_TRUE(post_dominator_analysis->Dominates( 1006fd4e5da5Sopenharmony_ci context->get_def_use_mgr()->GetDef(22), 1007fd4e5da5Sopenharmony_ci context->get_def_use_mgr()->GetDef(20))); 1008fd4e5da5Sopenharmony_ci EXPECT_TRUE(post_dominator_analysis->Dominates( 1009fd4e5da5Sopenharmony_ci context->get_def_use_mgr()->GetDef(22), 1010fd4e5da5Sopenharmony_ci context->get_def_use_mgr()->GetDef(21))); 1011fd4e5da5Sopenharmony_ci EXPECT_TRUE(post_dominator_analysis->Dominates( 1012fd4e5da5Sopenharmony_ci context->get_def_use_mgr()->GetDef(15), 1013fd4e5da5Sopenharmony_ci context->get_def_use_mgr()->GetDef(15))); 1014fd4e5da5Sopenharmony_ci } 1015fd4e5da5Sopenharmony_ci} 1016fd4e5da5Sopenharmony_ci 1017fd4e5da5Sopenharmony_ci} // namespace 1018fd4e5da5Sopenharmony_ci} // namespace opt 1019fd4e5da5Sopenharmony_ci} // namespace spvtools 1020