[Mlir-commits] [mlir] 4575c05 - [mlir][scf] fix loop specialization crash when an scf.for result is used (#236046)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Sun Nov 1 00:58:00 PDT 2026
Author: Prashanth T
Date: 2026-11-01T15:57:55+08:00
New Revision: 4575c053e0519b968ad6117b5df4d248326725a7
URL: https://github.com/llvm/llvm-project/commit/4575c053e0519b968ad6117b5df4d248326725a7
DIFF: https://github.com/llvm/llvm-project/commit/4575c053e0519b968ad6117b5df4d248326725a7.diff
LOG: [mlir][scf] fix loop specialization crash when an scf.for result is used (#236046)
the replacement `scf.if` now has the original loop result types, if the
condition is satisfied (i.e bound equal to constant) the then branch
replaces the upper bound of the cloned loop with the constant, else the
original operation with bound is cloned as such.
the yield op is created inside both the branches if there is any
resullt, the original op's result users are redirected to the `scf.if`
results and the original loop is erased.
fixes #235552
assisted by: claude
Added:
Modified:
mlir/lib/Dialect/SCF/Transforms/LoopSpecialization.cpp
mlir/test/Dialect/SCF/for-loop-specialization.mlir
Removed:
################################################################################
diff --git a/mlir/lib/Dialect/SCF/Transforms/LoopSpecialization.cpp b/mlir/lib/Dialect/SCF/Transforms/LoopSpecialization.cpp
index e232692ecc4e5a..6ca907415fbb57 100644
--- a/mlir/lib/Dialect/SCF/Transforms/LoopSpecialization.cpp
+++ b/mlir/lib/Dialect/SCF/Transforms/LoopSpecialization.cpp
@@ -103,9 +103,19 @@ static void specializeForLoopForUnrolling(ForOp op) {
Value cond = arith::CmpIOp::create(b, op.getLoc(), arith::CmpIPredicate::eq,
bound, constant);
map.map(bound, constant);
- auto ifOp = scf::IfOp::create(b, op.getLoc(), cond, /*withElseRegion=*/true);
- ifOp.getThenBodyBuilder().clone(*op.getOperation(), map);
- ifOp.getElseBodyBuilder().clone(*op.getOperation());
+ auto ifOp = scf::IfOp::create(b, op.getLoc(), op->getResultTypes(), cond,
+ /*withElseRegion=*/true);
+
+ OpBuilder thenB = ifOp.getThenBodyBuilder();
+ Operation *thenLoop = thenB.clone(*op.getOperation(), map);
+ OpBuilder elseB = ifOp.getElseBodyBuilder();
+ Operation *elseLoop = elseB.clone(*op.getOperation());
+
+ if (op->getNumResults() > 0) {
+ scf::YieldOp::create(thenB, op.getLoc(), thenLoop->getResults());
+ scf::YieldOp::create(elseB, op.getLoc(), elseLoop->getResults());
+ op->replaceAllUsesWith(ifOp.getResults());
+ }
op.erase();
}
diff --git a/mlir/test/Dialect/SCF/for-loop-specialization.mlir b/mlir/test/Dialect/SCF/for-loop-specialization.mlir
index 59e522f621963f..6485c9cf89cb2c 100644
--- a/mlir/test/Dialect/SCF/for-loop-specialization.mlir
+++ b/mlir/test/Dialect/SCF/for-loop-specialization.mlir
@@ -63,3 +63,37 @@ func.func @for_constant_operand(%n: index) {
// CHECK: scf.for {{%.*}} = {{%.*}} to [[MIN]] step {{%.*}} {
// CHECK: }
// CHECK: }
+
+// -----
+
+// see https://github.com/llvm/llvm-project/issues/235552
+// CHECK-LABEL: func @specialize_with_iter_args
+// CHECK-SAME: (%[[N:.*]]: index) -> index {
+func.func @specialize_with_iter_args(%n: index) -> index {
+ %c0 = arith.constant 0 : index
+ %c1 = arith.constant 1 : index
+ %ub = affine.min affine_map<(d0) -> (d0, 4)>(%n)
+ %result = scf.for %iv = %c0 to %ub step %c1
+ iter_args(%acc = %c0) -> (index) {
+ scf.yield %acc : index
+ }
+ return %result : index
+}
+
+// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : index
+// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : index
+// CHECK: %[[UB:.*]] = affine.min #{{.*}}(%[[N]])
+// CHECK: %[[C4:.*]] = arith.constant 4 : index
+// CHECK: %[[COND:.*]] = arith.cmpi eq, %[[UB]], %[[C4]] : index
+// CHECK: %[[RES:.*]] = scf.if %[[COND]] -> (index) {
+// CHECK: %[[THEN:.*]] = scf.for %{{.*}} = %[[C0]] to %[[C4]] step %[[C1]] iter_args(%[[ACC1:.*]] = %[[C0]]) -> (index) {
+// CHECK: scf.yield %[[ACC1]] : index
+// CHECK: }
+// CHECK: scf.yield %[[THEN]] : index
+// CHECK: } else {
+// CHECK: %[[ELSE:.*]] = scf.for %{{.*}} = %[[C0]] to %[[UB]] step %[[C1]] iter_args(%[[ACC2:.*]] = %[[C0]]) -> (index) {
+// CHECK: scf.yield %[[ACC2]] : index
+// CHECK: }
+// CHECK: scf.yield %[[ELSE]] : index
+// CHECK: }
+// CHECK: return %[[RES]] : index
More information about the Mlir-commits
mailing list