[Mlir-commits] [mlir] [mlir][affine] Preserve used sibling loop results during fusion (PR #216564)
Oleksandr Alex Zinenko
llvmlistbot at llvm.org
Tue Sep 22 02:15:39 PDT 2026
================
@@ -124,6 +126,168 @@ static bool canRemoveSrcNodeAfterFusion(
return true;
}
+static void replaceInits(RewriterBase &rewriter, AffineForOp forOp,
+ ArrayRef<unsigned> initIndices, ValueRange newInits) {
+ assert(initIndices.size() == newInits.size() &&
+ "expected one replacement value per init operand index");
+
+ SmallVector<Value> inits(forOp.getInits());
+ assert(llvm::all_of(initIndices,
+ [&](unsigned index) { return index < inits.size(); }) &&
+ "expected replacement indices to fit in affine.for init operands");
+
+ for (auto [initIndex, newInit] : llvm::zip(initIndices, newInits))
+ inits[initIndex] = newInit;
+ rewriter.modifyOpInPlace(forOp,
+ [&]() { forOp.getInitsMutable().assign(inits); });
+}
+
+static AffineForOp
+getAffineForOpWithResults(ValueRange values,
+ SmallVectorImpl<unsigned> &indices) {
+ assert(!values.empty() && "expected values to forward");
+ auto firstResult = dyn_cast<OpResult>(values.front());
+ if (!firstResult)
+ return nullptr;
+
+ auto forOp = dyn_cast<AffineForOp>(firstResult.getOwner());
+ if (!forOp)
+ return nullptr;
+ assert(forOp.getNumResults() == forOp.getInits().size() &&
+ "expected one init operand per affine.for result");
+
+ indices.clear();
+ for (Value value : values) {
+ auto result = dyn_cast<OpResult>(value);
+ if (!result || result.getOwner() != forOp) {
+ indices.clear();
+ return nullptr;
+ }
+ indices.push_back(result.getResultNumber());
+ }
+ return forOp;
+}
+
+static LogicalResult getBackwardSliceForValues(ValueRange values,
+ AffineForOp parentForOp,
+ SetVector<Operation *> &slice) {
+ BackwardSliceOptions options;
+ options.inclusive = true;
+ options.omitBlockArguments = true;
+ options.filter = [&](Operation *op) {
+ return parentForOp->isProperAncestor(op);
+ };
+
+ for (Value value : values)
+ if (Operation *definingOp = value.getDefiningOp()) {
+ if (failed(getBackwardSlice(definingOp, &slice, options)))
+ return failure();
+ }
+ return success();
+}
+
+static void replaceInitUsesInPromotedSlice(RewriterBase &rewriter,
+ const SetVector<Operation *> &slice,
+ ValueRange oldValues,
+ ValueRange newValues) {
+ assert(oldValues.size() == newValues.size() &&
+ "expected one replacement value per old value");
+
+ for (auto [oldValue, newValue] : llvm::zip(oldValues, newValues)) {
+ rewriter.replaceUsesWithIf(oldValue, newValue, [&](OpOperand &use) {
+ return slice.contains(use.getOwner());
+ });
+ }
+}
+
+static Operation *getAncestorInBlock(Operation *op, Block *block) {
+ while (op && op->getBlock() != block)
+ op = op->getParentOp();
+ return op;
+}
+
+// Check that all result users remain dominated after sibling fusion moves
+// `definingOp` before `insertPoint`.
+static bool resultUsersRemainDominated(Operation *opWithUsers,
+ Operation *definingOp,
+ Operation *insertPoint) {
+ Block *block = insertPoint->getBlock();
+ bool definingOpWillMove = definingOp != insertPoint;
+ for (Value result : opWithUsers->getResults()) {
+ if (result.use_empty())
+ continue;
+ for (OpOperand &use : result.getUses()) {
+ Operation *userAncestor = getAncestorInBlock(use.getOwner(), block);
+ if (!userAncestor)
+ return false;
+ if (definingOpWillMove && userAncestor->isBeforeInBlock(insertPoint))
+ return false;
+ if (!definingOpWillMove && !definingOp->isBeforeInBlock(userAncestor))
+ return false;
+ }
+ }
+ return true;
+}
+
+// Carry values from the cloned sibling loop through the destination loop nest.
+// Each newly added iter_arg is used as the corresponding init of the loop that
+// currently defines the forwarded values.
+static FailureOr<SmallVector<Value>>
+forwardValuesThroughAffineForNest(ValueRange values, ValueRange inits,
+ AffineForOp &outerForOp) {
+ IRRewriter rewriter(outerForOp->getContext());
+ SmallVector<Value> forwardedValues(values.begin(), values.end());
----------------
ftynse wrote:
Nit: `llvm::to_vector`.
https://github.com/llvm/llvm-project/pull/216564
More information about the Mlir-commits
mailing list