Skip to content

Commit 9979c63

Browse files
[mlir][IR][NFC] DominanceInfo: Share same impl for block/op dominance
The `properlyDominates` implementations for blocks and ops are very similar. This commit replaces them with a single implementation that operates on block iterators. That implementation can be used to implement both `properlyDominates` variants. Note: A subsequent commit will add a new public `properlyDominates` overload that accepts block iterators. That functionality can then be used to find a valid insertion point at which a range of values is defined (by utilizing post dominance). Depends on #115433.
1 parent 26e5b4f commit 9979c63

File tree

2 files changed

+92
-60
lines changed

2 files changed

+92
-60
lines changed

mlir/include/mlir/IR/Dominance.h

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -113,12 +113,12 @@ class DominanceInfoBase {
113113
llvm::PointerIntPair<DomTree *, 1, bool>
114114
getDominanceInfo(Region *region, bool needsDomTree) const;
115115

116-
/// Return "true" if the specified block A properly (post)dominates block B.
117-
bool properlyDominatesImpl(Block *a, Block *b) const;
118-
119-
/// Return "true" if the specified op A properly (post)dominates op B.
120-
bool properlyDominatesImpl(Operation *a, Operation *b,
121-
bool enclosingOpOk = true) const;
116+
/// Return "true" if block iterator A properly (post)dominates block iterator
117+
/// B. If `enclosingOk` is set, A is considered to (post)dominate B if A
118+
/// encloses B.
119+
bool properlyDominatesImpl(Block *aBlock, Block::iterator aIt, Block *bBlock,
120+
Block::iterator bIt,
121+
bool enclosingOk = true) const;
122122

123123
/// A mapping of regions to their base dominator tree and a cached
124124
/// "hasSSADominance" bit. This map does not contain dominator trees for
@@ -151,9 +151,7 @@ class DominanceInfo : public detail::DominanceInfoBase</*IsPostDom=*/false> {
151151
/// The `enclosingOpOk` flag says whether we should return true if the B op
152152
/// is enclosed by a region on A.
153153
bool properlyDominates(Operation *a, Operation *b,
154-
bool enclosingOpOk = true) const {
155-
return super::properlyDominatesImpl(a, b, enclosingOpOk);
156-
}
154+
bool enclosingOpOk = true) const;
157155

158156
/// Return true if operation A dominates operation B, i.e. if A and B are the
159157
/// same operation or A properly dominates B.
@@ -188,9 +186,7 @@ class DominanceInfo : public detail::DominanceInfoBase</*IsPostDom=*/false> {
188186
/// Graph regions have only a single block. To be consistent with "proper
189187
/// dominance" of ops, the single block is considered to properly dominate
190188
/// itself in a graph region.
191-
bool properlyDominates(Block *a, Block *b) const {
192-
return super::properlyDominatesImpl(a, b);
193-
}
189+
bool properlyDominates(Block *a, Block *b) const;
194190
};
195191

196192
/// A class for computing basic postdominance information.
@@ -200,19 +196,15 @@ class PostDominanceInfo : public detail::DominanceInfoBase</*IsPostDom=*/true> {
200196

201197
/// Return true if operation A properly postdominates operation B.
202198
bool properlyPostDominates(Operation *a, Operation *b,
203-
bool enclosingOpOk = true) {
204-
return super::properlyDominatesImpl(a, b, enclosingOpOk);
205-
}
199+
bool enclosingOpOk = true);
206200

207201
/// Return true if operation A postdominates operation B.
208202
bool postDominates(Operation *a, Operation *b) {
209203
return a == b || properlyPostDominates(a, b);
210204
}
211205

212206
/// Return true if the specified block A properly postdominates block B.
213-
bool properlyPostDominates(Block *a, Block *b) {
214-
return super::properlyDominatesImpl(a, b);
215-
}
207+
bool properlyPostDominates(Block *a, Block *b);
216208

217209
/// Return true if the specified block A postdominates block B.
218210
bool postDominates(Block *a, Block *b) {

mlir/lib/IR/Dominance.cpp

Lines changed: 82 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -213,61 +213,73 @@ DominanceInfoBase<IsPostDom>::findNearestCommonDominator(Block *a,
213213
return getDomTree(a->getParent()).findNearestCommonDominator(a, b);
214214
}
215215

216-
/// Return true if the specified block A properly dominates block B.
217-
template <bool IsPostDom>
218-
bool DominanceInfoBase<IsPostDom>::properlyDominatesImpl(Block *a,
219-
Block *b) const {
220-
assert(a && b && "null blocks not allowed");
216+
/// Returns the given block iterator if it lies within the region region.
217+
/// Otherwise, otherwise finds the ancestor of the given block iterator that
218+
/// lies within the given region. Returns and "empty" iterator if the latter
219+
/// fails.
220+
///
221+
/// Note: This is a variant of Region::findAncestorOpInRegion that operates on
222+
/// block iterators instead of ops.
223+
static std::pair<Block *, Block::iterator>
224+
findAncestorIteratorInRegion(Region *r, Block *b, Block::iterator it) {
225+
// Case 1: The iterator lies within the region region.
226+
if (b->getParent() == r)
227+
return std::make_pair(b, it);
228+
229+
// Otherwise: Find ancestor iterator. Bail if we run out of parent ops.
230+
Operation *parentOp = b->getParentOp();
231+
if (!parentOp)
232+
return std::make_pair(static_cast<Block *>(nullptr), Block::iterator());
233+
Operation *op = r->findAncestorOpInRegion(*parentOp);
234+
if (!op)
235+
return std::make_pair(static_cast<Block *>(nullptr), Block::iterator());
236+
return std::make_pair(op->getBlock(), op->getIterator());
237+
}
221238

222-
// A block dominates, but does not properly dominate, itself unless this
223-
// is a graph region.
239+
/// Given two iterators into the same block, return "true" if `a` is before `b.
240+
/// Note: This is a variant of Operation::isBeforeInBlock that operates on
241+
/// block iterators instead of ops.
242+
static bool isBeforeInBlock(Block *block, Block::iterator a,
243+
Block::iterator b) {
224244
if (a == b)
225-
return !hasSSADominance(a);
226-
227-
// If both blocks are not in the same region, `a` properly dominates `b` if
228-
// `b` is defined in an operation region that (recursively) ends up being
229-
// dominated by `a`. Walk up the list of containers enclosing B.
230-
Region *regionA = a->getParent();
231-
if (regionA != b->getParent()) {
232-
b = regionA ? regionA->findAncestorBlockInRegion(*b) : nullptr;
233-
// If we could not find a valid block b then it is a not a dominator.
234-
if (!b)
235-
return false;
236-
237-
// Check to see if the ancestor of `b` is the same block as `a`. A properly
238-
// dominates B if it contains an op that contains the B block.
239-
if (a == b)
240-
return true;
241-
}
242-
243-
// Otherwise, they are two different blocks in the same region, use DomTree.
244-
return getDomTree(regionA).properlyDominates(a, b);
245+
return false;
246+
if (a == block->end())
247+
return false;
248+
if (b == block->end())
249+
return true;
250+
return a->isBeforeInBlock(&*b);
245251
}
246252

247253
template <bool IsPostDom>
248254
bool DominanceInfoBase<IsPostDom>::properlyDominatesImpl(
249-
Operation *a, Operation *b, bool enclosingOpOk) const {
250-
Block *aBlock = a->getBlock(), *bBlock = b->getBlock();
251-
assert(aBlock && bBlock && "operations must be in a block");
255+
Block *aBlock, Block::iterator aIt, Block *bBlock, Block::iterator bIt,
256+
bool enclosingOk) const {
257+
assert(aBlock && bBlock && "expected non-null blocks");
252258

253-
// An operation (pos)dominates, but does not properly (pos)dominate, itself
254-
// unless this is a graph region.
255-
if (a == b)
259+
// A block iterator (post)dominates, but does not properly (post)dominate,
260+
// itself unless this is a graph region.
261+
if (aBlock == bBlock && aIt == bIt)
256262
return !hasSSADominance(aBlock);
257263

258-
// If these ops are in different regions, then normalize one into the other.
264+
// If the iterators are in different regions, then normalize one into the
265+
// other.
259266
Region *aRegion = aBlock->getParent();
260267
if (aRegion != bBlock->getParent()) {
261-
// Scoot up b's region tree until we find an operation in A's region that
268+
// Scoot up b's region tree until we find a location in A's region that
262269
// encloses it. If this fails, then we know there is no (post)dom relation.
263-
b = aRegion ? aRegion->findAncestorOpInRegion(*b) : nullptr;
264-
if (!b)
270+
if (!aRegion) {
271+
bBlock = nullptr;
272+
bIt = Block::iterator();
273+
} else {
274+
std::tie(bBlock, bIt) =
275+
findAncestorIteratorInRegion(aRegion, bBlock, bIt);
276+
}
277+
if (!bBlock)
265278
return false;
266-
bBlock = b->getBlock();
267-
assert(bBlock->getParent() == aRegion);
279+
assert(bBlock->getParent() == aRegion && "expected block in regionA");
268280

269281
// If 'a' encloses 'b', then we consider it to (post)dominate.
270-
if (a == b && enclosingOpOk)
282+
if (aBlock == bBlock && aIt == bIt && enclosingOk)
271283
return true;
272284
}
273285

@@ -279,9 +291,9 @@ bool DominanceInfoBase<IsPostDom>::properlyDominatesImpl(
279291
if (!hasSSADominance(aBlock))
280292
return true;
281293
if constexpr (IsPostDom) {
282-
return b->isBeforeInBlock(a);
294+
return isBeforeInBlock(aBlock, bIt, aIt);
283295
} else {
284-
return a->isBeforeInBlock(b);
296+
return isBeforeInBlock(aBlock, aIt, bIt);
285297
}
286298
}
287299

@@ -309,6 +321,18 @@ template class detail::DominanceInfoBase</*IsPostDom=*/false>;
309321
// DominanceInfo
310322
//===----------------------------------------------------------------------===//
311323

324+
bool DominanceInfo::properlyDominates(Operation *a, Operation *b,
325+
bool enclosingOpOk) const {
326+
return super::properlyDominatesImpl(a->getBlock(), a->getIterator(),
327+
b->getBlock(), b->getIterator(),
328+
enclosingOpOk);
329+
}
330+
331+
bool DominanceInfo::properlyDominates(Block *a, Block *b) const {
332+
return super::properlyDominatesImpl(a, a->begin(), b, b->begin(),
333+
/*enclosingOk=*/true);
334+
}
335+
312336
/// Return true if the `a` value properly dominates operation `b`, i.e if the
313337
/// operation that defines `a` properlyDominates `b` and the operation that
314338
/// defines `a` does not contain `b`.
@@ -322,3 +346,19 @@ bool DominanceInfo::properlyDominates(Value a, Operation *b) const {
322346
// `b`, but `a` does not itself enclose `b` in one of its regions.
323347
return properlyDominates(a.getDefiningOp(), b, /*enclosingOpOk=*/false);
324348
}
349+
350+
//===----------------------------------------------------------------------===//
351+
// PostDominanceInfo
352+
//===----------------------------------------------------------------------===//
353+
354+
bool PostDominanceInfo::properlyPostDominates(Operation *a, Operation *b,
355+
bool enclosingOpOk) {
356+
return super::properlyDominatesImpl(a->getBlock(), a->getIterator(),
357+
b->getBlock(), b->getIterator(),
358+
enclosingOpOk);
359+
}
360+
361+
bool PostDominanceInfo::properlyPostDominates(Block *a, Block *b) {
362+
return super::properlyDominatesImpl(a, a->end(), b, b->end(),
363+
/*enclosingOk=*/true);
364+
}

0 commit comments

Comments
 (0)