[Mlir-commits] [mlir] [mlir] Add a utility method to move operation dependencies. (PR #129975)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Thu Mar 6 12:57:11 PST 2025


================
@@ -1054,3 +1057,65 @@ LogicalResult mlir::simplifyRegions(RewriterBase &rewriter,
   return success(eliminatedBlocks || eliminatedOpsOrArgs ||
                  mergedIdenticalBlocks || droppedRedundantArguments);
 }
+
+//===---------------------------------------------------------------------===//
+// Move operation dependencies
+//===---------------------------------------------------------------------===//
+
+LogicalResult mlir::moveOperationDependencies(RewriterBase &rewriter,
+                                              Operation *op,
+                                              Operation *insertionPoint,
+                                              DominanceInfo &dominance) {
+  // Currently unsupported case where the op and insertion point are
+  // in different basic blocks.
+  if (op->getBlock() != insertionPoint->getBlock()) {
+    return rewriter.notifyMatchFailure(
+        op, "unsupported caes where operation and insertion point are not in "
+            "the sme basic block");
+  }
+
+  // Find the backward slice of operation for each `Value` the operation
+  // depends on. Prune the slice to only include operations not already
+  // dominated by the `insertionPoint`
+  BackwardSliceOptions options;
+  options.inclusive = true;
+  options.filter = [&](Operation *sliceBoundaryOp) {
+    return !dominance.properlyDominates(sliceBoundaryOp, insertionPoint);
+  };
+  llvm::SetVector<Operation *> slice;
+
+  // Get the defined slice for operands.
+  for (Value operand : op->getOperands()) {
+    getBackwardSlice(operand, &slice, options);
+  }
+  auto regions = op->getRegions();
+  if (!regions.empty()) {
----------------
MaheshRavishankar wrote:

Good suggestion on this, but let me clarify something 
```
func.func @move_region_dependencies() -> f32 {  
  %0 = "before"() : () -> (f32)  
  %1 = "moved_op"() ({  
    "yield"(%0) : (f32) -> ()  
  }) : () -> (f32)  
  %2 = "foo"() ({  
    "yield"(%1) : (f32) -> ()  
  }) : () -> (f32)  
  return %2 : f32  
}  
```
Here the operations shouldnt be moved. `"foo"` is directly dependent on `%0 = "before"`. So moving all dependencies before would be illegal and so the method does nothing (it returns a failure). But your suggestion does work for an example like this
```
func.func @move_region_dependencies() -> f32 {  
  %0 = "before"() : () -> (f32)  
  %1 = "moved_op_1"() : () -> (f32)
  %2 = "moved_op"() ({  
    "yield"(%1) : (f32) -> ()  
  }) : () -> (f32)  
  %3 = "foo"() ({  
    "yield"(%2) : (f32) -> ()  
  }) : () -> (f32)  
  return %3 : f32  
}  
```
Here `"foo"` does not directly depend on `%0 = "before"` and you can move all its dependencies. I added this as a test.

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


More information about the Mlir-commits mailing list