@@ -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
247253template <bool IsPostDom>
248254bool 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) const {
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) const {
362+ return super::properlyDominatesImpl (a, a->end (), b, b->end (),
363+ /* enclosingOk=*/ true );
364+ }
0 commit comments