github.com/johnnyeven/libtools@v0.0.0-20191126065708-61829c1adf46/third_party/mlir/lib/Analysis/Dominance.cpp (about) 1 //===- Dominance.cpp - Dominator analysis for CFGs ------------------------===// 2 // 3 // Copyright 2019 The MLIR Authors. 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 // ============================================================================= 17 // 18 // Implementation of dominance related classes and instantiations of extern 19 // templates. 20 // 21 //===----------------------------------------------------------------------===// 22 23 #include "mlir/Analysis/Dominance.h" 24 #include "mlir/IR/Operation.h" 25 #include "llvm/Support/GenericDomTreeConstruction.h" 26 27 using namespace mlir; 28 using namespace mlir::detail; 29 30 template class llvm::DominatorTreeBase<Block, /*IsPostDom=*/false>; 31 template class llvm::DominatorTreeBase<Block, /*IsPostDom=*/true>; 32 template class llvm::DomTreeNodeBase<Block>; 33 34 //===----------------------------------------------------------------------===// 35 // DominanceInfoBase 36 //===----------------------------------------------------------------------===// 37 38 template <bool IsPostDom> 39 void DominanceInfoBase<IsPostDom>::recalculate(Operation *op) { 40 dominanceInfos.clear(); 41 42 /// Build the dominance for each of the operation regions. 43 op->walk([&](Operation *op) { 44 for (auto ®ion : op->getRegions()) { 45 // Don't compute dominance if the region is empty. 46 if (region.empty()) 47 continue; 48 auto opDominance = std::make_unique<base>(); 49 opDominance->recalculate(region); 50 dominanceInfos.try_emplace(®ion, std::move(opDominance)); 51 } 52 }); 53 } 54 55 /// Return true if the specified block A properly dominates block B. 56 template <bool IsPostDom> 57 bool DominanceInfoBase<IsPostDom>::properlyDominates(Block *a, Block *b) { 58 // A block dominates itself but does not properly dominate itself. 59 if (a == b) 60 return false; 61 62 // If either a or b are null, then conservatively return false. 63 if (!a || !b) 64 return false; 65 66 // If both blocks are not in the same region, 'a' properly dominates 'b' if 67 // 'b' is defined in an operation region that (recursively) ends up being 68 // dominated by 'a'. Walk up the list of containers enclosing B. 69 auto *regionA = a->getParent(), *regionB = b->getParent(); 70 if (regionA != regionB) { 71 Operation *bAncestor; 72 do { 73 bAncestor = regionB->getParentOp(); 74 // If 'bAncestor' is the top level region, then 'a' is a block that post 75 // dominates 'b'. 76 if (!bAncestor || !bAncestor->getBlock()) 77 return IsPostDom; 78 79 regionB = bAncestor->getBlock()->getParent(); 80 } while (regionA != regionB); 81 82 // Check to see if the ancestor of 'b' is the same block as 'a'. 83 b = bAncestor->getBlock(); 84 if (a == b) 85 return true; 86 } 87 88 // Otherwise, use the standard dominance functionality. 89 90 // If we don't have a dominance information for this region, assume that b is 91 // dominated by anything. 92 auto baseInfoIt = dominanceInfos.find(regionA); 93 if (baseInfoIt == dominanceInfos.end()) 94 return true; 95 return baseInfoIt->second->properlyDominates(a, b); 96 } 97 98 template class mlir::detail::DominanceInfoBase</*IsPostDom=*/true>; 99 template class mlir::detail::DominanceInfoBase</*IsPostDom=*/false>; 100 101 //===----------------------------------------------------------------------===// 102 // DominanceInfo 103 //===----------------------------------------------------------------------===// 104 105 /// Return true if operation A properly dominates operation B. 106 bool DominanceInfo::properlyDominates(Operation *a, Operation *b) { 107 auto *aBlock = a->getBlock(), *bBlock = b->getBlock(); 108 109 // If a or b are not within a block, then a does not dominate b. 110 if (!aBlock || !bBlock) 111 return false; 112 113 // If the blocks are the same, then check if b is before a in the block. 114 if (aBlock == bBlock) 115 return a->isBeforeInBlock(b); 116 117 // Traverse up b's hierarchy to check if b's block is contained in a's. 118 if (auto *bAncestor = aBlock->findAncestorInstInBlock(*b)) { 119 // Since we already know that aBlock != bBlock, here bAncestor != b. 120 // a and bAncestor are in the same block; check if 'a' dominates 121 // bAncestor. 122 return dominates(a, bAncestor); 123 } 124 125 // If the blocks are different, check if a's block dominates b's. 126 return properlyDominates(aBlock, bBlock); 127 } 128 129 /// Return true if value A properly dominates operation B. 130 bool DominanceInfo::properlyDominates(Value *a, Operation *b) { 131 if (auto *aInst = a->getDefiningOp()) 132 return properlyDominates(aInst, b); 133 134 // block arguments properly dominate all operations in their own block, so 135 // we use a dominates check here, not a properlyDominates check. 136 return dominates(cast<BlockArgument>(a)->getOwner(), b->getBlock()); 137 } 138 139 //===----------------------------------------------------------------------===// 140 // PostDominanceInfo 141 //===----------------------------------------------------------------------===// 142 143 /// Returns true if statement 'a' properly postdominates statement b. 144 bool PostDominanceInfo::properlyPostDominates(Operation *a, Operation *b) { 145 auto *aBlock = a->getBlock(), *bBlock = b->getBlock(); 146 147 // If a or b are not within a block, then a does not post dominate b. 148 if (!aBlock || !bBlock) 149 return false; 150 151 // If the blocks are the same, check if b is before a in the block. 152 if (aBlock == bBlock) 153 return b->isBeforeInBlock(a); 154 155 // Traverse up b's hierarchy to check if b's block is contained in a's. 156 if (auto *bAncestor = a->getBlock()->findAncestorInstInBlock(*b)) 157 // Since we already know that aBlock != bBlock, here bAncestor != b. 158 // a and bAncestor are in the same block; check if 'a' postdominates 159 // bAncestor. 160 return postDominates(a, bAncestor); 161 162 // If the blocks are different, check if a's block post dominates b's. 163 return properlyDominates(aBlock, bBlock); 164 }