Skip to content

Commit a230a52

Browse files
[mlir][IR] Add Block::isReachable helper function
Add a new helper function `isReachable` to `Block`. This function traverses all successors of a block to determine if another block is reachable from the current block. This functionality has been reimplemented in multiple places.
1 parent 013f4a4 commit a230a52

File tree

4 files changed

+29
-36
lines changed

4 files changed

+29
-36
lines changed

mlir/include/mlir/IR/Block.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,11 @@ class alignas(8) Block : public IRObjectWithUseList<BlockOperand>,
264264
succ_iterator succ_end() { return getSuccessors().end(); }
265265
SuccessorRange getSuccessors() { return SuccessorRange(this); }
266266

267+
/// Return "true" if there is a path from this block to the given block
268+
/// (according to the successors relationship). Both blocks must be in the
269+
/// same region. Paths that contain a block from `except` do not count.
270+
bool isReachable(Block *other, ArrayRef<Block *> except = {});
271+
267272
//===--------------------------------------------------------------------===//
268273
// Walkers
269274
//===--------------------------------------------------------------------===//

mlir/lib/Dialect/Bufferization/Transforms/OneShotAnalysis.cpp

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -273,25 +273,6 @@ static bool happensBefore(Operation *a, Operation *b,
273273
return false;
274274
}
275275

276-
static bool isReachable(Block *from, Block *to, ArrayRef<Block *> except) {
277-
DenseSet<Block *> visited;
278-
SmallVector<Block *> worklist;
279-
for (Block *succ : from->getSuccessors())
280-
worklist.push_back(succ);
281-
while (!worklist.empty()) {
282-
Block *next = worklist.pop_back_val();
283-
if (llvm::is_contained(except, next))
284-
continue;
285-
if (next == to)
286-
return true;
287-
if (!visited.insert(next).second)
288-
continue;
289-
for (Block *succ : next->getSuccessors())
290-
worklist.push_back(succ);
291-
}
292-
return false;
293-
}
294-
295276
/// Return `true` if op dominance can be used to rule out a read-after-write
296277
/// conflicts based on the ordering of ops. Returns `false` if op dominance
297278
/// cannot be used to due region-based loops.
@@ -427,8 +408,8 @@ static bool canUseOpDominanceDueToBlocks(OpOperand *uRead, OpOperand *uWrite,
427408
Block *writeBlock = uWrite->getOwner()->getBlock();
428409
for (Value def : definitions) {
429410
Block *defBlock = def.getParentBlock();
430-
if (isReachable(readBlock, writeBlock, {defBlock}) &&
431-
isReachable(writeBlock, readBlock, {defBlock}))
411+
if (readBlock->isReachable(writeBlock, {defBlock}) &&
412+
writeBlock->isReachable(readBlock, {defBlock}))
432413
return false;
433414
}
434415

mlir/lib/Dialect/Vector/Transforms/VectorTransferOpTransforms.cpp

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -73,20 +73,7 @@ bool TransferOptimization::isReachable(Operation *start, Operation *dest) {
7373
// Simple case where the start op dominate the destination.
7474
if (dominators.dominates(start, dest))
7575
return true;
76-
Block *startBlock = start->getBlock();
77-
Block *destBlock = dest->getBlock();
78-
SmallVector<Block *, 32> worklist(startBlock->succ_begin(),
79-
startBlock->succ_end());
80-
SmallPtrSet<Block *, 32> visited;
81-
while (!worklist.empty()) {
82-
Block *bb = worklist.pop_back_val();
83-
if (!visited.insert(bb).second)
84-
continue;
85-
if (dominators.dominates(bb, destBlock))
86-
return true;
87-
worklist.append(bb->succ_begin(), bb->succ_end());
88-
}
89-
return false;
76+
return start->getBlock()->isReachable(dest->getBlock());
9077
}
9178

9279
/// For transfer_write to overwrite fully another transfer_write must:

mlir/lib/IR/Block.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "mlir/IR/Block.h"
10+
1011
#include "mlir/IR/Builders.h"
1112
#include "mlir/IR/Operation.h"
1213
#include "llvm/ADT/BitVector.h"
14+
#include "llvm/ADT/SmallPtrSet.h"
15+
1316
using namespace mlir;
1417

1518
//===----------------------------------------------------------------------===//
@@ -331,7 +334,7 @@ unsigned PredecessorIterator::getSuccessorIndex() const {
331334
}
332335

333336
//===----------------------------------------------------------------------===//
334-
// SuccessorRange
337+
// Successors
335338
//===----------------------------------------------------------------------===//
336339

337340
SuccessorRange::SuccessorRange() : SuccessorRange(nullptr, 0) {}
@@ -349,6 +352,23 @@ SuccessorRange::SuccessorRange(Operation *term) : SuccessorRange() {
349352
base = term->getBlockOperands().data();
350353
}
351354

355+
bool Block::isReachable(Block *other, ArrayRef<Block *> except) {
356+
assert(getParent() == other->getParent() && "expected same region");
357+
SmallVector<Block *> worklist(succ_begin(), succ_end());
358+
SmallPtrSet<Block *, 16> visited;
359+
while (!worklist.empty()) {
360+
Block *next = worklist.pop_back_val();
361+
if (llvm::is_contained(except, next))
362+
continue;
363+
if (next == other)
364+
return true;
365+
if (!visited.insert(next).second)
366+
continue;
367+
worklist.append(next->succ_begin(), next->succ_end());
368+
}
369+
return false;
370+
}
371+
352372
//===----------------------------------------------------------------------===//
353373
// BlockRange
354374
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)