[llvm-branch-commits] [mlir] [mlir][IR] Add helper functions to compute insertion point (PR #114940)

Mehdi Amini via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Nov 8 05:00:39 PST 2024


================
@@ -641,3 +641,76 @@ void OpBuilder::cloneRegionBefore(Region &region, Region &parent,
 void OpBuilder::cloneRegionBefore(Region &region, 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.
----------------
joker-eph wrote:

Wouldn't the right insertion point be the post-dominator block?

https://github.com/llvm/llvm-project/pull/114940


More information about the llvm-branch-commits mailing list