1 //===- TestDominance.cpp - Test dominance construction and information 2 //-------===// 3 // 4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file contains test passes for constructing and resolving dominance 11 // information. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "mlir/IR/Dominance.h" 16 #include "mlir/Pass/Pass.h" 17 18 using namespace mlir; 19 20 /// Overloaded helper to call the right function based on whether we are testing 21 /// dominance or post-dominance. 22 static bool dominatesOrPostDominates(DominanceInfo &dominanceInfo, Block *a, 23 Block *b) { 24 return dominanceInfo.dominates(a, b); 25 } 26 27 static bool dominatesOrPostDominates(PostDominanceInfo &dominanceInfo, Block *a, 28 Block *b) { 29 return dominanceInfo.postDominates(a, b); 30 } 31 32 namespace { 33 34 /// Helper class to print dominance information. 35 class DominanceTest { 36 public: 37 /// Constructs a new test instance using the given operation. 38 DominanceTest(Operation *operation) : operation(operation) { 39 // Create unique ids for each block. 40 operation->walk([&](Operation *nested) { 41 if (blockIds.count(nested->getBlock()) > 0) 42 return; 43 blockIds.insert({nested->getBlock(), blockIds.size()}); 44 }); 45 } 46 47 /// Prints dominance information of all blocks. 48 template <typename DominanceT> 49 void printDominance(DominanceT &dominanceInfo, 50 bool printCommonDominatorInfo) { 51 DenseSet<Block *> parentVisited; 52 operation->walk([&](Operation *op) { 53 Block *block = op->getBlock(); 54 if (!parentVisited.insert(block).second) 55 return; 56 57 DenseSet<Block *> visited; 58 operation->walk([&](Operation *nested) { 59 Block *nestedBlock = nested->getBlock(); 60 if (!visited.insert(nestedBlock).second) 61 return; 62 if (printCommonDominatorInfo) { 63 llvm::errs() << "Nearest(" << blockIds[block] << ", " 64 << blockIds[nestedBlock] << ") = "; 65 Block *dom = 66 dominanceInfo.findNearestCommonDominator(block, nestedBlock); 67 if (dom) 68 llvm::errs() << blockIds[dom]; 69 else 70 llvm::errs() << "<no dom>"; 71 llvm::errs() << "\n"; 72 } else { 73 if (std::is_same<DominanceInfo, DominanceT>::value) 74 llvm::errs() << "dominates("; 75 else 76 llvm::errs() << "postdominates("; 77 llvm::errs() << blockIds[block] << ", " << blockIds[nestedBlock] 78 << ") = "; 79 if (dominatesOrPostDominates(dominanceInfo, block, nestedBlock)) 80 llvm::errs() << "true\n"; 81 else 82 llvm::errs() << "false\n"; 83 } 84 }); 85 }); 86 } 87 88 private: 89 Operation *operation; 90 DenseMap<Block *, size_t> blockIds; 91 }; 92 93 struct TestDominancePass 94 : public PassWrapper<TestDominancePass, OperationPass<FuncOp>> { 95 StringRef getArgument() const final { return "test-print-dominance"; } 96 StringRef getDescription() const final { 97 return "Print the dominance information for multiple regions."; 98 } 99 100 void runOnOperation() override { 101 llvm::errs() << "Testing : " << getOperation().getName() << "\n"; 102 DominanceTest dominanceTest(getOperation()); 103 104 // Print dominance information. 105 llvm::errs() << "--- DominanceInfo ---\n"; 106 dominanceTest.printDominance(getAnalysis<DominanceInfo>(), 107 /*printCommonDominatorInfo=*/true); 108 109 llvm::errs() << "--- PostDominanceInfo ---\n"; 110 dominanceTest.printDominance(getAnalysis<PostDominanceInfo>(), 111 /*printCommonDominatorInfo=*/true); 112 113 // Print dominance relationship between blocks. 114 llvm::errs() << "--- Block Dominance relationship ---\n"; 115 dominanceTest.printDominance(getAnalysis<DominanceInfo>(), 116 /*printCommonDominatorInfo=*/false); 117 118 llvm::errs() << "--- Block PostDominance relationship ---\n"; 119 dominanceTest.printDominance(getAnalysis<PostDominanceInfo>(), 120 /*printCommonDominatorInfo=*/false); 121 } 122 }; 123 124 } // namespace 125 126 namespace mlir { 127 namespace test { 128 void registerTestDominancePass() { PassRegistration<TestDominancePass>(); } 129 } // namespace test 130 } // namespace mlir 131