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