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