[Mlir-commits] [mlir] 1b0e2e1 - [mlir][SCF] Skip dynamic front-peeling for non-index loops (#218238)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Wed Aug 26 01:39:01 PDT 2026


Author: Federico Bruzzone
Date: 2026-08-26T10:38:56+02:00
New Revision: 1b0e2e1dd8dbc6d500eeebab7083f4b5b5184353

URL: https://github.com/llvm/llvm-project/commit/1b0e2e1dd8dbc6d500eeebab7083f4b5b5184353
DIFF: https://github.com/llvm/llvm-project/commit/1b0e2e1dd8dbc6d500eeebab7083f4b5b5184353.diff

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

`peelForLoopFirstIteration` computes the new lower bound with an
`affine.apply` whose operands are the loop's lower bound and step.
`affine.apply` requires operands of type `index`, while `scf.for` also
permits signless integer IV and bounds, so the operation can be
constructed with operands that it does not accept.

This is the same underlying issue as #216631 / #217909, in the sibling
"peel front" path.

Skip the front-peeling path when the loop induction variable is not
`index`, mirroring the guard added in #217909. The existing
constant-bounds path is unaffected.

---------

Signed-off-by: Federico Bruzzone <federico.bruzzone.i at gmail.com>

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/mlir/lib/Dialect/SCF/Transforms/LoopSpecialization.cpp b/mlir/lib/Dialect/SCF/Transforms/LoopSpecialization.cpp
index ba5375bb42d94..bcc7ed3d3abfd 100644
--- a/mlir/lib/Dialect/SCF/Transforms/LoopSpecialization.cpp
+++ b/mlir/lib/Dialect/SCF/Transforms/LoopSpecialization.cpp
@@ -236,6 +236,13 @@ LogicalResult mlir::scf::peelForLoopFirstIteration(RewriterBase &b, ForOp forOp,
   if (lbInt && ubInt && stepInt && ceil(float(*ubInt - *lbInt) / *stepInt) <= 1)
     return failure();
 
+  // The peeling bound (%lb + %step) is computed with affine.apply, which
+  // accepts only index operands. %ub does not feed into this bound, so only
+  // %lb and %step need to be constant to guarantee the affine.apply (see below)
+  // folds away before its (non-index) operand types matter.
+  if ((!lbInt || !stepInt) && !forOp.getInductionVar().getType().isIndex())
+    return failure();
+
   AffineExpr lbSymbol, stepSymbol;
   bindSymbols(b.getContext(), lbSymbol, stepSymbol);
 

diff  --git a/mlir/test/Dialect/SCF/for-loop-peeling-front.mlir b/mlir/test/Dialect/SCF/for-loop-peeling-front.mlir
index 1737c6b6f6c5f..afd570c8b6f8c 100644
--- a/mlir/test/Dialect/SCF/for-loop-peeling-front.mlir
+++ b/mlir/test/Dialect/SCF/for-loop-peeling-front.mlir
@@ -218,3 +218,24 @@ func.func @no_peeling_front() -> i32 {
   }
   return %r : i32
 }
+
+// -----
+
+// CHECK-LABEL:   func.func @non_index_loop_bounds(
+// CHECK-SAME:                                         %[[INIT:[^:]*]]: i32,
+// CHECK-SAME:                                         %[[LB:[^:]*]]: i32,
+// CHECK-SAME:                                         %[[N:[^:]*]]: i32) -> i32 {
+// CHECK:           %[[C2:.*]] = arith.constant 2 : i32
+// CHECK:           %[[RESULT:.*]] = scf.for %[[IV:.*]] = %[[LB]] 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, %lb: i32, %n: i32) -> i32 {
+  %c2 = arith.constant 2 : i32
+  %r = scf.for %i = %lb 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