[Mlir-commits] [mlir] 294c9c8 - [mlir][SCF] Skip dynamic peeling for non-index loops (#217909)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Sun Aug 23 02:31:01 PDT 2026


Author: purnima shrivastava
Date: 2026-08-23T09:30:55Z
New Revision: 294c9c8b3fb92da313cd1544ae267a50aff8689f

URL: https://github.com/llvm/llvm-project/commit/294c9c8b3fb92da313cd1544ae267a50aff8689f
DIFF: https://github.com/llvm/llvm-project/commit/294c9c8b3fb92da313cd1544ae267a50aff8689f.diff

LOG: [mlir][SCF] Skip dynamic peeling for non-index loops (#217909)

`scf-for-loop-peeling` constructs an `affine.apply` on its dynamic path
to compute the split bound. However, `affine.apply` requires `index`
operands, while `scf.for` also permits signless integer induction
variables and bounds.

Skip the dynamic peeling path when the loop induction variable is not
`index`. The existing constant-bounds path remains unchanged, so
constant integer loops can still be peeled.

Add a regression test for a loop with dynamic `i32` bounds, verifying
that the pass leaves it unchanged rather than producing invalid IR.

Fixes #216631.

Co-authored-by: Purnima Shrivastava <purnimashrivastava05 at .com>

Added: 
    

Modified: 
    mlir/lib/Dialect/SCF/Transforms/LoopSpecialization.cpp
    mlir/test/Dialect/SCF/for-loop-peeling.mlir

Removed: 
    


################################################################################
diff  --git a/mlir/lib/Dialect/SCF/Transforms/LoopSpecialization.cpp b/mlir/lib/Dialect/SCF/Transforms/LoopSpecialization.cpp
index a39e5520a144b..ba5375bb42d94 100644
--- a/mlir/lib/Dialect/SCF/Transforms/LoopSpecialization.cpp
+++ b/mlir/lib/Dialect/SCF/Transforms/LoopSpecialization.cpp
@@ -136,6 +136,13 @@ static LogicalResult peelForLoop(RewriterBase &b, ForOp forOp,
   // Fast path: lb, ub and step are constants.
   if (lbInt && ubInt && stepInt && (*ubInt - *lbInt) % *stepInt == 0)
     return failure();
+
+  // Only the dynamic path computes the peeling bound with affine.apply, which
+  // accepts only index operands.
+  if ((!lbInt || !ubInt || !stepInt) &&
+      !forOp.getInductionVar().getType().isIndex())
+    return failure();
+
   // Slow path: Examine the ops that define lb, ub and step.
   AffineExpr sym0, sym1, sym2;
   bindSymbols(b.getContext(), sym0, sym1, sym2);

diff  --git a/mlir/test/Dialect/SCF/for-loop-peeling.mlir b/mlir/test/Dialect/SCF/for-loop-peeling.mlir
index 4337f3b8d4d6f..d1026f5090cb0 100644
--- a/mlir/test/Dialect/SCF/for-loop-peeling.mlir
+++ b/mlir/test/Dialect/SCF/for-loop-peeling.mlir
@@ -377,3 +377,25 @@ func.func @zero_step(%arg0: memref<i64>) {
   }
   return
 }
+
+// -----
+
+// CHECK-LABEL:   func.func @non_index_loop_bounds(
+// CHECK-SAME:                                         %[[INIT:.*]]: i32,
+// CHECK-SAME:                                         %[[N:.*]]: i32) -> i32 {
+// CHECK:           %[[C0:.*]] = arith.constant 0 : i32
+// CHECK:           %[[C2:.*]] = arith.constant 2 : i32
+// CHECK:           %[[RESULT:.*]] = scf.for %[[IV:.*]] = %[[C0]] to %[[N]] step %[[C2]] iter_args(%[[ACC:.*]] = %[[INIT]]) -> (i32) : i32 {
+// CHECK:             %[[ADD:.*]] = arith.addi %[[ACC]], %[[IV]] : i32
+// CHECK:             scf.yield %[[ADD]] : i32
+// CHECK:           }
+// CHECK:           return %[[RESULT]] : i32
+func.func @non_index_loop_bounds(%init: i32, %n: i32) -> i32 {
+  %c0 = arith.constant 0 : i32
+  %c2 = arith.constant 2 : i32
+  %r = scf.for %i = %c0 to %n step %c2 iter_args(%a = %init) -> (i32) : i32 {
+    %t = arith.addi %a, %i : i32
+    scf.yield %t : i32
+  }
+  return %r : i32
+}


        


More information about the Mlir-commits mailing list