[Mlir-commits] [mlir] [MLIR][SCF] Handle commuted indices in parallel loop fusion (PR #219665)

purnima shrivastava llvmlistbot at llvm.org
Sat Aug 29 03:16:20 PDT 2026


https://github.com/purnima-nlp created https://github.com/llvm/llvm-project/pull/219665

`scf-parallel-loop-fusion` compares index-producing operations with
operands in their original order. Consequently, equivalent accesses such
as `%iv + 1` and `1 + %iv` are not recognized as accessing the same
location, preventing otherwise legal loop fusion.

Handle commuted `arith.addi` expressions in `valsAreEquivalent` while
requiring matching result types and operation attributes.

Add a regression test verifying that parallel loops using commuted index
expressions are fused.

Fixes #218614.

>From a2600d408cfbc328131bf2317426e2de1e50eed1 Mon Sep 17 00:00:00 2001
From: Purnima Shrivastava <purnimashrivastava05 at .com>
Date: Sat, 29 Aug 2026 15:21:28 +0530
Subject: [PATCH] [MLIR][SCF] Handle commuted indices in parallel loop fusion

---
 .../SCF/Transforms/ParallelLoopFusion.cpp     | 12 ++++++++
 .../Dialect/SCF/parallel-loop-fusion.mlir     | 30 +++++++++++++++++++
 2 files changed, 42 insertions(+)

diff --git a/mlir/lib/Dialect/SCF/Transforms/ParallelLoopFusion.cpp b/mlir/lib/Dialect/SCF/Transforms/ParallelLoopFusion.cpp
index 397920565c5ba..265fa6c8a39d0 100644
--- a/mlir/lib/Dialect/SCF/Transforms/ParallelLoopFusion.cpp
+++ b/mlir/lib/Dialect/SCF/Transforms/ParallelLoopFusion.cpp
@@ -145,6 +145,18 @@ static bool valsAreEquivalent(Value val1, Value val2,
     return false;
   if (!isMemoryEffectFree(val1DefOp) || !isMemoryEffectFree(val2DefOp))
     return false;
+
+  // Handle commuted integer additions.
+  if (auto addOp1 = dyn_cast<arith::AddIOp>(val1DefOp)) {
+    if (auto addOp2 = dyn_cast<arith::AddIOp>(val2DefOp);
+        addOp2 &&
+        val1DefOp->getAttrDictionary() == val2DefOp->getAttrDictionary() &&
+        val1.getType() == val2.getType() &&
+        valsAreEquivalent(addOp1.getLhs(), addOp2.getRhs(), loopsIVsMap) &&
+        valsAreEquivalent(addOp1.getRhs(), addOp2.getLhs(), loopsIVsMap))
+      return true;
+  }
+
   return OperationEquivalence::isEquivalentTo(
       val1DefOp, val2DefOp,
       [&](Value v1, Value v2) {
diff --git a/mlir/test/Dialect/SCF/parallel-loop-fusion.mlir b/mlir/test/Dialect/SCF/parallel-loop-fusion.mlir
index 9472e9ebb9d22..48c7276318d0d 100644
--- a/mlir/test/Dialect/SCF/parallel-loop-fusion.mlir
+++ b/mlir/test/Dialect/SCF/parallel-loop-fusion.mlir
@@ -1761,3 +1761,33 @@ func.func @do_not_fuse_distinct_dynamic_bounds(%A: memref<16xf32>,
 // CHECK-LABEL: func @do_not_fuse_distinct_dynamic_bounds
 // CHECK:        scf.parallel
 // CHECK:        scf.parallel
+
+// -----
+
+func.func @fuse_commuted_indices(%arg0: memref<32xf32>,
+                                 %arg1: memref<32xf32>) {
+  %c0 = arith.constant 0 : index
+  %c1 = arith.constant 1 : index
+  %c16 = arith.constant 16 : index
+  %cst = arith.constant 3.000000e+00 : f32
+
+  scf.parallel (%i) = (%c0) to (%c16) step (%c1) {
+    %index = arith.addi %i, %c1 : index
+    memref.store %cst, %arg0[%index] : memref<32xf32>
+    scf.reduce
+  }
+
+  scf.parallel (%i) = (%c0) to (%c16) step (%c1) {
+    %index = arith.addi %c1, %i : index
+    %value = memref.load %arg0[%index] : memref<32xf32>
+    memref.store %value, %arg1[%index] : memref<32xf32>
+    scf.reduce
+  }
+
+  return
+}
+
+// CHECK-LABEL: func.func @fuse_commuted_indices
+// CHECK:       scf.parallel
+// CHECK-NOT:   scf.parallel
+// CHECK:       return
\ No newline at end of file



More information about the Mlir-commits mailing list