-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[mlir][Transforms] Greedy pattern rewriter: fix infinite folding loop #161145
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
[mlir][Transforms] Greedy pattern rewriter: fix infinite folding loop #161145
Conversation
@llvm/pr-subscribers-mlir-arith @llvm/pr-subscribers-mlir Author: Matthias Springer (matthias-springer) ChangesFix an infinite folding loop when the result of a folding is identical to the folded operation. Full diff: https://github.com/llvm/llvm-project/pull/161145.diff 2 Files Affected:
diff --git a/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp b/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp
index 74e4a822b4fd7..93468dd79808f 100644
--- a/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp
+++ b/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp
@@ -555,7 +555,8 @@ bool GreedyPatternRewriteDriver::processWorklist() {
replacements.push_back(constOp->getResult(0));
}
- if (materializationSucceeded) {
+ if (materializationSucceeded &&
+ !llvm::equal(replacements, op->getResults())) {
rewriter.replaceOp(op, replacements);
changed = true;
LLVM_DEBUG(logSuccessfulFolding(dumpRootOp));
diff --git a/mlir/test/Transforms/canonicalize.mlir b/mlir/test/Transforms/canonicalize.mlir
index 8e02c06a0a293..ed987e555926c 100644
--- a/mlir/test/Transforms/canonicalize.mlir
+++ b/mlir/test/Transforms/canonicalize.mlir
@@ -1248,3 +1248,12 @@ func.func @test_materialize_failure() -> i64 {
%u = index.castu %const : index to i64
return %u: i64
}
+
+// -----
+
+// Make sure that the canonicalizer does not fold infinitely.
+
+// CHECK: %[[c0:.*]] = arith.constant 0 : index
+%c0 = arith.constant 0 : index
+// CHECK: %[[add:.*]] = arith.addi %[[c0]], %[[add]] : index
+%0 = arith.addi %c0, %0 : index
|
@llvm/pr-subscribers-mlir-core Author: Matthias Springer (matthias-springer) ChangesFix an infinite folding loop when the result of a folding is identical to the folded operation. Full diff: https://github.com/llvm/llvm-project/pull/161145.diff 2 Files Affected:
diff --git a/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp b/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp
index 74e4a822b4fd7..93468dd79808f 100644
--- a/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp
+++ b/mlir/lib/Transforms/Utils/GreedyPatternRewriteDriver.cpp
@@ -555,7 +555,8 @@ bool GreedyPatternRewriteDriver::processWorklist() {
replacements.push_back(constOp->getResult(0));
}
- if (materializationSucceeded) {
+ if (materializationSucceeded &&
+ !llvm::equal(replacements, op->getResults())) {
rewriter.replaceOp(op, replacements);
changed = true;
LLVM_DEBUG(logSuccessfulFolding(dumpRootOp));
diff --git a/mlir/test/Transforms/canonicalize.mlir b/mlir/test/Transforms/canonicalize.mlir
index 8e02c06a0a293..ed987e555926c 100644
--- a/mlir/test/Transforms/canonicalize.mlir
+++ b/mlir/test/Transforms/canonicalize.mlir
@@ -1248,3 +1248,12 @@ func.func @test_materialize_failure() -> i64 {
%u = index.castu %const : index to i64
return %u: i64
}
+
+// -----
+
+// Make sure that the canonicalizer does not fold infinitely.
+
+// CHECK: %[[c0:.*]] = arith.constant 0 : index
+%c0 = arith.constant 0 : index
+// CHECK: %[[add:.*]] = arith.addi %[[c0]], %[[add]] : index
+%0 = arith.addi %c0, %0 : index
|
Note: There is still an infinite loop when canonicalizing this IR:
|
This PR does not fix the problem yet. I'm seeing an infinite loop again, not sure why the CI has a different error. The problem is here:
Without the above check, we return Fixing the folder itself it not enough, the next pattern that causes infinite looping is I'm not sure what's the right fix here. We likely have many folders/patterns that run into infinite loops in such cases. Should we fix all these? Are they even broken? I am using the |
What about in an unreachable block in a CFG? DialectConversion does not visit there, but they could happen in the greedy rewriter. |
I'm not sure how this comment relates to this PR. |
I was following up on:
|
a5e9b84
to
24471f6
Compare
Ok, then it cannot be fixed in the verifier. Then we have to fix the folder. The API of the single-result folder is: if the folder returns the op result of the same op, the op was folded in-place. This is violated here. (I updated the PR. But only in one place. There are many places like that.) Single-result folder called here: template <typename ConcreteOpT>
static LogicalResult
foldSingleResultHook(Operation *op, ArrayRef<Attribute> operands,
SmallVectorImpl<OpFoldResult> &results) {
...
// If the fold failed or was in-place, try to fold the traits of the
// operation.
if (!result ||
llvm::dyn_cast_if_present<Value>(result) == op->getResult(0)) { Also, it doesn't fix the issue yet, because now this canonicalization pattern gets into an infinite loop. Unfortunately, it's written in TableGen and there may be no way to fix this without rewriting it in C++:
|
Could we detect this in: |
The issue is that this isn't necessarily about the immediate operands:
A folder on |
Fix an infinite folding loop when the result of a folding is identical to the folded operation. (This can be the case when the folder is faulty or the input IR is invalid.)
Fixes one issue mentioned in #159675 (comment).