[Mlir-commits] [mlir] [mlir] Harden affine loop folding (PR #208736)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Fri Jul 10 07:34:42 PDT 2026
https://github.com/mygitljf created https://github.com/llvm/llvm-project/pull/208736
I made affine loop folding fail closed when conversion is looking at temporary IR whose value ownership cannot be proven, and I made the loop interface default treat unknown parentage conservatively. This keeps normal stable-IR folding behavior intact while avoiding unsafe conversion-time folding.
Fixes #207352
>From 0582d9740cb10dc99afe852978e42d04138cabbe Mon Sep 17 00:00:00 2001
From: mygitljf <2410316423 at qq.com>
Date: Fri, 10 Jul 2026 22:33:17 +0000
Subject: [PATCH] [mlir] Harden affine loop folding
---
mlir/include/mlir/Interfaces/LoopLikeInterface.td | 4 +++-
mlir/lib/Dialect/Affine/IR/AffineOps.cpp | 5 ++---
mlir/test/Transforms/test-convert-func-op.mlir | 15 +++++++++++++++
3 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/mlir/include/mlir/Interfaces/LoopLikeInterface.td b/mlir/include/mlir/Interfaces/LoopLikeInterface.td
index 5fb897339ffde..d64287b6c1f0b 100644
--- a/mlir/include/mlir/Interfaces/LoopLikeInterface.td
+++ b/mlir/include/mlir/Interfaces/LoopLikeInterface.td
@@ -62,7 +62,9 @@ def LoopLikeOpInterface : OpInterface<"LoopLikeOpInterface"> {
/*args=*/(ins "::mlir::Value ":$value),
/*methodBody=*/"",
/*defaultImplementation=*/[{
- return !$_op->isAncestor(value.getParentRegion()->getParentOp());
+ ::mlir::Region *region = value.getParentRegion();
+ ::mlir::Operation *parentOp = region ? region->getParentOp() : nullptr;
+ return parentOp && !$_op->isAncestor(parentOp);
}]
>,
InterfaceMethod<[{
diff --git a/mlir/lib/Dialect/Affine/IR/AffineOps.cpp b/mlir/lib/Dialect/Affine/IR/AffineOps.cpp
index f095500495f18..9caa5841b0e4d 100644
--- a/mlir/lib/Dialect/Affine/IR/AffineOps.cpp
+++ b/mlir/lib/Dialect/Affine/IR/AffineOps.cpp
@@ -2595,9 +2595,8 @@ static SmallVector<OpFoldResult> AffineForEmptyLoopFolder(AffineForOp forOp) {
if (val == forOp.getInductionVar())
return {};
if (iterArgIt == iterArgs.end()) {
- // `val` is defined outside of the loop.
- assert(forOp.isDefinedOutsideOfLoop(val) &&
- "must be defined outside of the loop");
+ if (!forOp.isDefinedOutsideOfLoop(val))
+ return {};
hasValDefinedOutsideLoop = true;
replacements.push_back(val);
} else {
diff --git a/mlir/test/Transforms/test-convert-func-op.mlir b/mlir/test/Transforms/test-convert-func-op.mlir
index 180f16a32991b..8587677e7bc30 100644
--- a/mlir/test/Transforms/test-convert-func-op.mlir
+++ b/mlir/test/Transforms/test-convert-func-op.mlir
@@ -38,3 +38,18 @@ func.func @byref(%arg0: !test.smpla {llvm.byref = !test.smpla}) -> !test.smpla {
// CHECK-SAME: (%[[ARG0:.*]]: !llvm.ptr {llvm.byref = !llvm.struct<(i8, i8)>}) -> !llvm.struct<(i8, i8)>
// CHECK: %[[LD:.*]] = llvm.load %[[ARG0]] : !llvm.ptr -> !llvm.struct<(i8, i8)>
// CHECK: llvm.return %[[LD]] : !llvm.struct<(i8, i8)>
+
+// -----
+
+// CHECK-LABEL: llvm.func @affine_for_iter_args
+func.func @affine_for_iter_args(%arg0: memref<10xf32>) {
+ %0 = affine.for %arg1 = 0 to 10 iter_args(%arg2 = %arg0) -> (memref<10xf32>) {
+ affine.yield %arg0 : memref<10xf32>
+ }
+ return
+}
+
+// CHECK: builtin.unrealized_conversion_cast
+// CHECK: affine.for
+// CHECK: affine.yield
+// CHECK: llvm.return
More information about the Mlir-commits
mailing list