1 //===- Dominance.cpp - Dominator analysis for CFGs ------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Implementation of dominance related classes and instantiations of extern 10 // templates. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "mlir/IR/Dominance.h" 15 #include "mlir/IR/Operation.h" 16 #include "mlir/IR/RegionKindInterface.h" 17 #include "llvm/ADT/DenseMap.h" 18 #include "llvm/Support/GenericDomTreeConstruction.h" 19 20 using namespace mlir; 21 using namespace mlir::detail; 22 23 template class llvm::DominatorTreeBase<Block, /*IsPostDom=*/false>; 24 template class llvm::DominatorTreeBase<Block, /*IsPostDom=*/true>; 25 template class llvm::DomTreeNodeBase<Block>; 26 27 /// Return true if the region with the given index inside the operation 28 /// has SSA dominance. 29 static bool hasSSADominance(Operation *op, unsigned index) { 30 auto kindInterface = dyn_cast<RegionKindInterface>(op); 31 return op->isRegistered() && 32 (!kindInterface || kindInterface.hasSSADominance(index)); 33 } 34 35 //===----------------------------------------------------------------------===// 36 // DominanceInfoBase 37 //===----------------------------------------------------------------------===// 38 39 template <bool IsPostDom> 40 void DominanceInfoBase<IsPostDom>::recalculate(Operation *op) { 41 dominanceInfos.clear(); 42 43 // Build the dominance for each of the operation regions. 44 op->walk([&](Operation *op) { 45 auto kindInterface = dyn_cast<RegionKindInterface>(op); 46 unsigned numRegions = op->getNumRegions(); 47 for (unsigned i = 0; i < numRegions; i++) { 48 Region ®ion = op->getRegion(i); 49 // Don't compute dominance if the region is empty. 50 if (region.empty()) 51 continue; 52 53 // Dominance changes based on the region type. Avoid the helper 54 // function here so we don't do the region cast repeatedly. 55 bool hasSSADominance = 56 op->isRegistered() && 57 (!kindInterface || kindInterface.hasSSADominance(i)); 58 // If a region has SSADominance, then compute detailed dominance 59 // info. Otherwise, all values in the region are live anywhere 60 // in the region, which is represented as an empty entry in the 61 // dominanceInfos map. 62 if (hasSSADominance) { 63 auto opDominance = std::make_unique<base>(); 64 opDominance->recalculate(region); 65 dominanceInfos.try_emplace(®ion, std::move(opDominance)); 66 } 67 } 68 }); 69 } 70 71 /// Walks up the list of containers of the given block and calls the 72 /// user-defined traversal function for every pair of a region and block that 73 /// could be found during traversal. If the user-defined function returns true 74 /// for a given pair, traverseAncestors will return the current block. Nullptr 75 /// otherwise. 76 template <typename FuncT> 77 Block *traverseAncestors(Block *block, const FuncT &func) { 78 // Invoke the user-defined traversal function in the beginning for the current 79 // block. 80 if (func(block)) 81 return block; 82 83 Region *region = block->getParent(); 84 while (region) { 85 Operation *ancestor = region->getParentOp(); 86 // If we have reached to top... return. 87 if (!ancestor || !(block = ancestor->getBlock())) 88 break; 89 90 // Update the nested region using the new ancestor block. 91 region = block->getParent(); 92 93 // Invoke the user-defined traversal function and check whether we can 94 // already return. 95 if (func(block)) 96 return block; 97 } 98 return nullptr; 99 } 100 101 /// Tries to update the given block references to live in the same region by 102 /// exploring the relationship of both blocks with respect to their regions. 103 static bool tryGetBlocksInSameRegion(Block *&a, Block *&b) { 104 // If both block do not live in the same region, we will have to check their 105 // parent operations. 106 if (a->getParent() == b->getParent()) 107 return true; 108 109 // Iterate over all ancestors of a and insert them into the map. This allows 110 // for efficient lookups to find a commonly shared region. 111 llvm::SmallDenseMap<Region *, Block *, 4> ancestors; 112 traverseAncestors(a, [&](Block *block) { 113 ancestors[block->getParent()] = block; 114 return false; 115 }); 116 117 // Try to find a common ancestor starting with regionB. 118 b = traverseAncestors( 119 b, [&](Block *block) { return ancestors.count(block->getParent()) > 0; }); 120 121 // If there is no match, we will not be able to find a common dominator since 122 // both regions do not share a common parent region. 123 if (!b) 124 return false; 125 126 // We have found a common parent region. Update block a to refer to this 127 // region. 128 auto it = ancestors.find(b->getParent()); 129 assert(it != ancestors.end()); 130 a = it->second; 131 return true; 132 } 133 134 template <bool IsPostDom> 135 Block * 136 DominanceInfoBase<IsPostDom>::findNearestCommonDominator(Block *a, 137 Block *b) const { 138 // If either a or b are null, then conservatively return nullptr. 139 if (!a || !b) 140 return nullptr; 141 142 // Try to find blocks that are in the same region. 143 if (!tryGetBlocksInSameRegion(a, b)) 144 return nullptr; 145 146 // Get and verify dominance information of the common parent region. 147 Region *parentRegion = a->getParent(); 148 auto infoAIt = dominanceInfos.find(parentRegion); 149 if (infoAIt == dominanceInfos.end()) 150 return nullptr; 151 152 // Since the blocks live in the same region, we can rely on already 153 // existing dominance functionality. 154 return infoAIt->second->findNearestCommonDominator(a, b); 155 } 156 157 template <bool IsPostDom> 158 DominanceInfoNode *DominanceInfoBase<IsPostDom>::getNode(Block *a) { 159 Region *region = a->getParent(); 160 assert(dominanceInfos.count(region) != 0); 161 return dominanceInfos[region]->getNode(a); 162 } 163 164 /// Return true if the specified block A properly dominates block B. 165 template <bool IsPostDom> 166 bool DominanceInfoBase<IsPostDom>::properlyDominates(Block *a, Block *b) const { 167 // A block dominates itself but does not properly dominate itself. 168 if (a == b) 169 return false; 170 171 // If either a or b are null, then conservatively return false. 172 if (!a || !b) 173 return false; 174 175 // If both blocks are not in the same region, 'a' properly dominates 'b' if 176 // 'b' is defined in an operation region that (recursively) ends up being 177 // dominated by 'a'. Walk up the list of containers enclosing B. 178 Region *regionA = a->getParent(); 179 if (regionA != b->getParent()) { 180 b = traverseAncestors( 181 b, [&](Block *block) { return block->getParent() == regionA; }); 182 183 // If we could not find a valid block b then it is a not a dominator. 184 if (!b) 185 return false; 186 187 // Check to see if the ancestor of 'b' is the same block as 'a'. 188 if (a == b) 189 return true; 190 } 191 192 // Otherwise, use the standard dominance functionality. 193 194 // If we don't have a dominance information for this region, assume that b is 195 // dominated by anything. 196 auto baseInfoIt = dominanceInfos.find(regionA); 197 if (baseInfoIt == dominanceInfos.end()) 198 return true; 199 return baseInfoIt->second->properlyDominates(a, b); 200 } 201 202 /// Return true if the specified block is reachable from the entry block of its 203 /// region. 204 template <bool IsPostDom> 205 bool DominanceInfoBase<IsPostDom>::isReachableFromEntry(Block *a) const { 206 Region *regionA = a->getParent(); 207 auto baseInfoIt = dominanceInfos.find(regionA); 208 if (baseInfoIt == dominanceInfos.end()) 209 return true; 210 return baseInfoIt->second->isReachableFromEntry(a); 211 } 212 213 template class detail::DominanceInfoBase</*IsPostDom=*/true>; 214 template class detail::DominanceInfoBase</*IsPostDom=*/false>; 215 216 //===----------------------------------------------------------------------===// 217 // DominanceInfo 218 //===----------------------------------------------------------------------===// 219 220 /// Return true if operation A properly dominates operation B. 221 bool DominanceInfo::properlyDominates(Operation *a, Operation *b) const { 222 Block *aBlock = a->getBlock(), *bBlock = b->getBlock(); 223 Region *aRegion = a->getParentRegion(); 224 unsigned aRegionNum = aRegion->getRegionNumber(); 225 Operation *ancestor = aRegion->getParentOp(); 226 227 // If a or b are not within a block, then a does not dominate b. 228 if (!aBlock || !bBlock) 229 return false; 230 231 if (aBlock == bBlock) { 232 // Dominance changes based on the region type. In a region with SSA 233 // dominance, uses inside the same block must follow defs. In other 234 // regions kinds, uses and defs can come in any order inside a block. 235 if (hasSSADominance(ancestor, aRegionNum)) { 236 // If the blocks are the same, then check if b is before a in the block. 237 return a->isBeforeInBlock(b); 238 } 239 return true; 240 } 241 242 // Traverse up b's hierarchy to check if b's block is contained in a's. 243 if (auto *bAncestor = aBlock->findAncestorOpInBlock(*b)) { 244 // Since we already know that aBlock != bBlock, here bAncestor != b. 245 // a and bAncestor are in the same block; check if 'a' dominates 246 // bAncestor. 247 return dominates(a, bAncestor); 248 } 249 250 // If the blocks are different, check if a's block dominates b's. 251 return properlyDominates(aBlock, bBlock); 252 } 253 254 /// Return true if value A properly dominates operation B. 255 bool DominanceInfo::properlyDominates(Value a, Operation *b) const { 256 if (auto *aOp = a.getDefiningOp()) { 257 // Dominance changes based on the region type. 258 auto *aRegion = aOp->getParentRegion(); 259 unsigned aRegionNum = aRegion->getRegionNumber(); 260 Operation *ancestor = aRegion->getParentOp(); 261 // Dominance changes based on the region type. In a region with SSA 262 // dominance, values defined by an operation cannot be used by the 263 // operation. In other regions kinds they can be used the operation. 264 if (hasSSADominance(ancestor, aRegionNum)) { 265 // The values defined by an operation do *not* dominate any nested 266 // operations. 267 if (aOp->getParentRegion() != b->getParentRegion() && aOp->isAncestor(b)) 268 return false; 269 } 270 return properlyDominates(aOp, b); 271 } 272 273 // block arguments properly dominate all operations in their own block, so 274 // we use a dominates check here, not a properlyDominates check. 275 return dominates(a.cast<BlockArgument>().getOwner(), b->getBlock()); 276 } 277 278 void DominanceInfo::updateDFSNumbers() { 279 for (auto &iter : dominanceInfos) 280 iter.second->updateDFSNumbers(); 281 } 282 283 //===----------------------------------------------------------------------===// 284 // PostDominanceInfo 285 //===----------------------------------------------------------------------===// 286 287 /// Returns true if statement 'a' properly postdominates statement b. 288 bool PostDominanceInfo::properlyPostDominates(Operation *a, Operation *b) { 289 auto *aBlock = a->getBlock(), *bBlock = b->getBlock(); 290 auto *aRegion = a->getParentRegion(); 291 unsigned aRegionNum = aRegion->getRegionNumber(); 292 Operation *ancestor = aRegion->getParentOp(); 293 294 // If a or b are not within a block, then a does not post dominate b. 295 if (!aBlock || !bBlock) 296 return false; 297 298 // If the blocks are the same, check if b is before a in the block. 299 if (aBlock == bBlock) { 300 // Dominance changes based on the region type. 301 if (hasSSADominance(ancestor, aRegionNum)) { 302 // If the blocks are the same, then check if b is before a in the block. 303 return b->isBeforeInBlock(a); 304 } 305 return true; 306 } 307 308 // Traverse up b's hierarchy to check if b's block is contained in a's. 309 if (auto *bAncestor = a->getBlock()->findAncestorOpInBlock(*b)) 310 // Since we already know that aBlock != bBlock, here bAncestor != b. 311 // a and bAncestor are in the same block; check if 'a' postdominates 312 // bAncestor. 313 return postDominates(a, bAncestor); 314 315 // If the blocks are different, check if a's block post dominates b's. 316 return properlyDominates(aBlock, bBlock); 317 } 318