[Mlir-commits] [mlir] [mlir][scf] Fix front peeling skipped due to float rounding in trip count (PR #231100)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Mon Oct 12 02:03:08 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir

Author: Prashanth (StarOne01)

<details>
<summary>Changes</summary>

fixes #<!-- -->231062 which affects loops with constant bounds where the `step` and `upperbound - lowerbound` are very close and close enogh to exceeds step by less than about half a float32 ulp at that magnitude.

eg: 

`ub - lb`: 20000001, `step`: 20000000
`ub - lb`: 1099511693312, `step`:  1099511627776

removing the float conversation and hence the ceil operation and comparing `*ubInt - *lbInt <= *stepInt` with repro as a test.


---
Full diff: https://github.com/llvm/llvm-project/pull/231100.diff


2 Files Affected:

- (modified) mlir/lib/Dialect/SCF/Transforms/LoopSpecialization.cpp (+1-1) 
- (modified) mlir/test/Dialect/SCF/for-loop-peeling-front.mlir (+33) 


``````````diff
diff --git a/mlir/lib/Dialect/SCF/Transforms/LoopSpecialization.cpp b/mlir/lib/Dialect/SCF/Transforms/LoopSpecialization.cpp
index 685c57319a216..d0719643603c9 100644
--- a/mlir/lib/Dialect/SCF/Transforms/LoopSpecialization.cpp
+++ b/mlir/lib/Dialect/SCF/Transforms/LoopSpecialization.cpp
@@ -239,7 +239,7 @@ LogicalResult mlir::scf::peelForLoopFirstIteration(RewriterBase &b, ForOp forOp,
   auto stepInt = getConstantIntValue(forOp.getStep());
 
   // Peeling is not needed if there is one or less iteration.
-  if (lbInt && ubInt && stepInt && ceil(float(*ubInt - *lbInt) / *stepInt) <= 1)
+  if (lbInt && ubInt && stepInt && *ubInt - *lbInt <= *stepInt)
     return failure();
 
   // The peeling bound (%lb + %step) is computed with affine.apply, which
diff --git a/mlir/test/Dialect/SCF/for-loop-peeling-front.mlir b/mlir/test/Dialect/SCF/for-loop-peeling-front.mlir
index ec91e4def6484..0eba57e5af771 100644
--- a/mlir/test/Dialect/SCF/for-loop-peeling-front.mlir
+++ b/mlir/test/Dialect/SCF/for-loop-peeling-front.mlir
@@ -242,3 +242,36 @@ func.func @non_index_loop_bounds(%init: i32, %lb: i32, %n: i32) -> i32 {
   }
   return %r : i32
 }
+
+// -----
+
+// Tests loops with constant bounds where the step and (upper bound - lower bound) are
+// very close, so `ceil(float(ub - lb) / step)` used to round to 1, and the front peeling
+// was skipped. See https://github.com/llvm/llvm-project/issues/231062
+
+// CHECK-LABEL:   func.func @peel_front_step_near_ub(
+// CHECK-SAME:                                         %[[MEMREF:[^:]*]]: memref<2xindex>) {
+// CHECK-DAG:       %[[C0:.*]] = arith.constant 0 : index
+// CHECK-DAG:       %[[C16777216:.*]] = arith.constant 16777216 : index
+// CHECK-DAG:       %[[C16777217:.*]] = arith.constant 16777217 : index
+// CHECK:           scf.for %[[IV0:.*]] = %[[C0]] to %[[C16777216]] step %[[C16777216]] {
+// CHECK:             %[[SLOT0:.*]] = arith.divui %[[IV0]], %[[C16777216]] : index
+// CHECK:             memref.store %[[IV0]], %[[MEMREF]][%[[SLOT0]]] : memref<2xindex>
+// CHECK:           }
+// CHECK:           scf.for %[[IV1:.*]] = %[[C16777216]] to %[[C16777217]] step %[[C16777216]] {
+// CHECK:             %[[SLOT1:.*]] = arith.divui %[[IV1]], %[[C16777216]] : index
+// CHECK:             memref.store %[[IV1]], %[[MEMREF]][%[[SLOT1]]] : memref<2xindex>
+// CHECK:           }
+// CHECK:           return
+
+func.func @peel_front_step_near_ub(%out: memref<2xindex>) {
+  %c0 = arith.constant 0 : index
+  %step = arith.constant 16777216 : index
+  %ub = arith.constant 16777217 : index
+
+  scf.for %i = %c0 to %ub step %step {
+    %slot = arith.divui %i, %step : index
+    memref.store %i, %out[%slot] : memref<2xindex>
+  }
+  return
+}
\ No newline at end of file

``````````

</details>


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


More information about the Mlir-commits mailing list