[Mlir-commits] [mlir] [mlir][scf] Use a signed compare for the parallel loop tiling in-bound check (PR #226130)
Samarth Narang
llvmlistbot at llvm.org
Thu Sep 24 04:59:53 PDT 2026
https://github.com/snarang181 updated https://github.com/llvm/llvm-project/pull/226130
>From e26f3d1c506b0ffcdf9ce9a904d35c1d6cf9db39 Mon Sep 17 00:00:00 2001
From: Samarth Narang <sn2910 at nyu.edu>
Date: Thu, 24 Sep 2026 11:19:52 +0000
Subject: [PATCH] [mlir][scf] Use a signed compare for the parallel loop tiling
in-bound check
With no-min-max-bounds the tiled loop guards the tail iterations with
`inner_iv * inner_step + outer_iv < outer_upper_bound`, but emitted the compare
as `ult`. scf.parallel bounds are signed index values and a negative lower
bound is legal, so every negative index was treated as out of bounds and
skipped: tiling `scf.parallel (%i) = (-3) to (4) step (1)` by 3 executed 4 of
the 7 iterations. Use `slt`.
Fixes #223233
---
.../SCF/Transforms/ParallelLoopTiling.cpp | 2 +-
.../parallel-loop-tiling-inbound-check.mlir | 24 +++++++++++++++++--
2 files changed, 23 insertions(+), 3 deletions(-)
diff --git a/mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp b/mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp
index 081f5fb3dc8f2a..9638f0a3c75c57 100644
--- a/mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp
+++ b/mlir/lib/Dialect/SCF/Transforms/ParallelLoopTiling.cpp
@@ -150,7 +150,7 @@ mlir::scf::tileParallelLoop(ParallelOp op, ArrayRef<int64_t> tileSizes,
b, op.getLoc(),
arith::MulIOp::create(b, op.getLoc(), innerIV, innerStep), outerIV);
Value dimInbound = arith::CmpIOp::create(
- b, op.getLoc(), arith::CmpIPredicate::ult, index, outerUpperBound);
+ b, op.getLoc(), arith::CmpIPredicate::slt, index, outerUpperBound);
inbound = arith::AndIOp::create(b, op.getLoc(), inbound, dimInbound);
}
auto ifInbound = IfOp::create(b, op.getLoc(),
diff --git a/mlir/test/Dialect/SCF/parallel-loop-tiling-inbound-check.mlir b/mlir/test/Dialect/SCF/parallel-loop-tiling-inbound-check.mlir
index 7491550c1dc7c2..79907b03996aa8 100644
--- a/mlir/test/Dialect/SCF/parallel-loop-tiling-inbound-check.mlir
+++ b/mlir/test/Dialect/SCF/parallel-loop-tiling-inbound-check.mlir
@@ -27,11 +27,11 @@ func.func @parallel_loop(%arg0 : index, %arg1 : index, %arg2 : index,
// CHECK: %true = arith.constant true
// CHECK: [[V11:%.*]] = arith.muli [[V7]], [[ARG5]] : index
// CHECK: [[V12:%.*]] = arith.addi [[V11]], [[V3]] : index
-// CHECK: [[V13:%.*]] = arith.cmpi ult, [[V12]], [[ARG3]] : index
+// CHECK: [[V13:%.*]] = arith.cmpi slt, [[V12]], [[ARG3]] : index
// CHECK: [[V14:%.*]] = arith.andi %true, [[V13]] : i1
// CHECK: [[V15:%.*]] = arith.muli [[V8]], [[ARG6]] : index
// CHECK: [[V16:%.*]] = arith.addi [[V15]], [[V4]] : index
-// CHECK: [[V17:%.*]] = arith.cmpi ult, [[V16]], [[ARG4]] : index
+// CHECK: [[V17:%.*]] = arith.cmpi slt, [[V16]], [[ARG4]] : index
// CHECK: [[V18:%.*]] = arith.andi [[V14]], [[V17]] : i1
// CHECK: scf.if [[V18]] {
// CHECK: [[V19:%.*]] = memref.load [[ARG8]]{{\[}}[[V9]], [[V10]]] : memref<?x?xf32>
@@ -147,3 +147,23 @@ func.func @tile_nested_in_non_ploop() {
// CHECK: }
// CHECK: }
// CHECK: }
+
+// -----
+
+func.func @parallel_loop_negative_lower_bound(%arg0 : index, %arg1 : index,
+ %result: memref<?x?xf32>) {
+ %c1 = arith.constant 1 : index
+ %cm3 = arith.constant -3 : index
+ %cst = arith.constant 0.0 : f32
+ scf.parallel (%i0, %i1) = (%cm3, %cm3) to (%arg0, %arg1) step (%c1, %c1) {
+ memref.store %cst, %result[%i0, %i1] : memref<?x?xf32>
+ }
+ return
+}
+
+// The bounds are signed, so a negative index must not be treated as out of
+// bounds by an unsigned compare.
+// CHECK-LABEL: func @parallel_loop_negative_lower_bound(
+// CHECK-NOT: arith.cmpi ult
+// CHECK: arith.cmpi slt
+// CHECK-NOT: arith.cmpi ult
More information about the Mlir-commits
mailing list