@@ -213,61 +213,73 @@ DominanceInfoBase<IsPostDom>::findNearestCommonDominator(Block *a,
213
213
return getDomTree (a->getParent ()).findNearestCommonDominator (a, b);
214
214
}
215
215
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
+ }
221
238
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) {
224
244
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);
245
251
}
246
252
247
253
template <bool IsPostDom>
248
254
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 " );
252
258
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 )
256
262
return !hasSSADominance (aBlock);
257
263
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.
259
266
Region *aRegion = aBlock->getParent ();
260
267
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
262
269
// 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)
265
278
return false ;
266
- bBlock = b->getBlock ();
267
- assert (bBlock->getParent () == aRegion);
279
+ assert (bBlock->getParent () == aRegion && " expected block in regionA" );
268
280
269
281
// If 'a' encloses 'b', then we consider it to (post)dominate.
270
- if (a == b && enclosingOpOk )
282
+ if (aBlock == bBlock && aIt == bIt && enclosingOk )
271
283
return true ;
272
284
}
273
285
@@ -279,9 +291,9 @@ bool DominanceInfoBase<IsPostDom>::properlyDominatesImpl(
279
291
if (!hasSSADominance (aBlock))
280
292
return true ;
281
293
if constexpr (IsPostDom) {
282
- return b-> isBeforeInBlock (a );
294
+ return isBeforeInBlock (aBlock, bIt, aIt );
283
295
} else {
284
- return a-> isBeforeInBlock (b );
296
+ return isBeforeInBlock (aBlock, aIt, bIt );
285
297
}
286
298
}
287
299
@@ -309,6 +321,18 @@ template class detail::DominanceInfoBase</*IsPostDom=*/false>;
309
321
// DominanceInfo
310
322
// ===----------------------------------------------------------------------===//
311
323
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
+
312
336
// / Return true if the `a` value properly dominates operation `b`, i.e if the
313
337
// / operation that defines `a` properlyDominates `b` and the operation that
314
338
// / defines `a` does not contain `b`.
@@ -322,3 +346,19 @@ bool DominanceInfo::properlyDominates(Value a, Operation *b) const {
322
346
// `b`, but `a` does not itself enclose `b` in one of its regions.
323
347
return properlyDominates (a.getDefiningOp (), b, /* enclosingOpOk=*/ false );
324
348
}
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