[llvm-branch-commits] [mlir] [mlir][IR] Add helper functions to compute insertion point (PR #114940)
Matthias Springer via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Nov 8 22:24:39 PST 2024
================
@@ -641,3 +641,76 @@ void OpBuilder::cloneRegionBefore(Region ®ion, Region &parent,
void OpBuilder::cloneRegionBefore(Region ®ion, Block *before) {
cloneRegionBefore(region, *before->getParent(), before->getIterator());
}
+
+//===----------------------------------------------------------------------===//
+// InsertPoint
+//===----------------------------------------------------------------------===//
+
+OpBuilder::InsertPoint OpBuilder::InsertPoint::after(Value value) {
+ if (auto blockArg = dyn_cast<BlockArgument>(value))
+ return InsertPoint(blockArg.getOwner(), blockArg.getOwner()->begin());
+ Operation *op = value.getDefiningOp();
+ return InsertPoint(op->getBlock(), ++op->getIterator());
+}
+
+/// Helper function that returns "true" if:
+/// - `a` is a proper ancestor of `b`
+/// - or: there is a path from `a` to `b`
+static bool isAncestorOrBefore(Block *a, Block *b) {
+ if (a->getParentOp()->isProperAncestor(b->getParentOp()))
+ return true;
+ if (a->getParent() != b->getParent())
+ return false;
+ return a->isReachable(b);
+}
+
+OpBuilder::InsertPoint
+OpBuilder::InsertPoint::findClosest(ArrayRef<Value> values) {
+ // Compute the insertion point after the first value.
+ assert(!values.empty() && "expected at least one value");
+ InsertPoint result = InsertPoint::after(values.front());
+
+ // Check all other values and update the insertion point as needed.
+ for (Value v : values.drop_front()) {
+ InsertPoint pt = InsertPoint::after(v);
+
+ if (pt.getBlock() == result.getBlock()) {
+ // Both values belong to the same block. Modify the iterator (but keep
+ // the block) if needed: take the later one of the two insertion points.
+ Block *block = pt.getBlock();
+ if (pt.getPoint() == block->end()) {
+ // `pt` points to the end of the block: take `pt`.
+ result = pt;
+ continue;
+ } else if (result.getPoint() == block->end()) {
+ // `result` points to the end of the block: nothing to do.
+ continue;
+ }
+ // Neither `pt` nor `result` point to the end of the block, so both
+ // iterators point to an operation. Set `result` to the later one of the
+ // two insertion point.
+ if (result.getPoint()->isBeforeInBlock(&*pt.getPoint()))
+ result = pt;
+ continue;
+ }
+
+ if (isAncestorOrBefore(result.getBlock(), pt.getBlock())) {
+ // `result` is an ancestor of `pt`. Therefore, `pt` is a valid insertion
+ // point for `v` and all previous values.
+ result = pt;
+ continue;
+ }
+
+ if (isAncestorOrBefore(pt.getBlock(), result.getBlock())) {
+ // `pt` is an ancestor of `result`. Therefore, `result` is a valid
+ // insertion point for `v` and all previous values.
+ continue;
+ }
+
+ // `pt` and `result` are in different subtrees: neither is an ancestor of
+ // the other. In that case, there is no suitable insertion point.
----------------
matthias-springer wrote:
Yes. Post-dominator `Block::iterator` to be precise. (Adding support for that in #115587.)
https://github.com/llvm/llvm-project/pull/114940
More information about the llvm-branch-commits
mailing list