-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
[LICM] allow MemoryAccess creation failure #116813
Conversation
@llvm/pr-subscribers-llvm-analysis @llvm/pr-subscribers-llvm-transforms Author: DianQK (DianQK) ChangesFixes #116809. Full diff: https://github.com/llvm/llvm-project/pull/116813.diff 2 Files Affected:
diff --git a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp
index aa3cbc5e4bddc2..d807c66bd96195 100644
--- a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp
+++ b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp
@@ -1678,7 +1678,7 @@ deleteDeadClonedBlocks(Loop &L, ArrayRef<BasicBlock *> ExitBlocks,
if (BasicBlock *ClonedBB = cast_or_null<BasicBlock>(VMap->lookup(BB)))
if (!DT.isReachableFromEntry(ClonedBB)) {
for (BasicBlock *SuccBB : successors(ClonedBB))
- SuccBB->removePredecessor(ClonedBB);
+ SuccBB->removePredecessor(ClonedBB, /*KeepOneInputPHIs*/ true);
DeadBlocks.push_back(ClonedBB);
}
@@ -1716,7 +1716,7 @@ static void deleteDeadBlocksFromLoop(Loop &L,
auto *BB = DeathCandidates.pop_back_val();
if (!DeadBlockSet.count(BB) && !DT.isReachableFromEntry(BB)) {
for (BasicBlock *SuccBB : successors(BB)) {
- SuccBB->removePredecessor(BB);
+ SuccBB->removePredecessor(BB, /*KeepOneInputPHIs*/ true);
DeathCandidates.push_back(SuccBB);
}
DeadBlockSet.insert(BB);
diff --git a/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-pred-removed.ll b/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-pred-removed.ll
new file mode 100644
index 00000000000000..3545492f1e5e23
--- /dev/null
+++ b/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch-pred-removed.ll
@@ -0,0 +1,24 @@
+; RUN: opt -passes='loop-mssa(simple-loop-unswitch<nontrivial>),print<memoryssa>' -verify-memoryssa -disable-output -S < %s 2>&1 | FileCheck %s
+; RUN: opt -passes='loop-mssa(simple-loop-unswitch<nontrivial>,licm)' -verify-memoryssa -disable-output -S
+
+; Check that SimpleLoopUnswitch preserves the MemoryDef of `call i32 @bar()` by preserving the PHI node.
+; Also, check that executing LICM after SimpleLoopUnswitch does not result in a crash.
+
+; CHECK: %unswitched.select = phi ptr [ @bar, %bb2 ]
+; CHECK-NEXT: MemoryDef
+; CHECK-NEXT: call i32 %unswitched.select()
+
+define i32 @foo(i1 %arg, ptr %arg1) {
+bb:
+ br label %bb2
+
+bb2: ; preds = %bb2, %bb
+ %i = select i1 %arg, ptr %arg1, ptr @bar
+ %i3 = call i32 %i()
+ br i1 %arg, label %bb2, label %bb4
+
+bb4: ; preds = %bb2
+ ret i32 %i3
+}
+
+declare i32 @bar() nounwind willreturn memory(none)
|
Does it fix #116228? |
@@ -1678,7 +1678,7 @@ deleteDeadClonedBlocks(Loop &L, ArrayRef<BasicBlock *> ExitBlocks, | |||
if (BasicBlock *ClonedBB = cast_or_null<BasicBlock>(VMap->lookup(BB))) | |||
if (!DT.isReachableFromEntry(ClonedBB)) { | |||
for (BasicBlock *SuccBB : successors(ClonedBB)) | |||
SuccBB->removePredecessor(ClonedBB); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have a test case for now yet, but I think we also need to keep one phi here.
; Also, check that executing LICM after SimpleLoopUnswitch does not result in a crash. | ||
|
||
; CHECK: %unswitched.select = phi ptr [ @bar, %bb2 ] | ||
; CHECK-NEXT: MemoryDef |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I cannot use /llvm/utils/update_test_checks.py
because I want to check MemoryDef
here.
@@ -0,0 +1,24 @@ | |||
; RUN: opt -passes='loop-mssa(simple-loop-unswitch<nontrivial>),print<memoryssa>' -verify-memoryssa -disable-output -S < %s 2>&1 | FileCheck %s | |||
; RUN: opt -passes='loop-mssa(simple-loop-unswitch<nontrivial>,licm)' -verify-memoryssa -disable-output -S |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If possible, I like /llvm/utils/update_test_checks.py
, but verifying that it does not crash is sufficient.
@@ -1716,7 +1716,7 @@ static void deleteDeadBlocksFromLoop(Loop &L, | |||
auto *BB = DeathCandidates.pop_back_val(); | |||
if (!DeadBlockSet.count(BB) && !DT.isReachableFromEntry(BB)) { | |||
for (BasicBlock *SuccBB : successors(BB)) { | |||
SuccBB->removePredecessor(BB); | |||
SuccBB->removePredecessor(BB, /*KeepOneInputPHIs*/ true); | |||
DeathCandidates.push_back(SuccBB); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: why can't MemorySSA be updated here? Is it because MemorySSAUpdater
does not yet support this?
Edit: I think this is a different issue. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add more detail to the PR description to explain why you think this is the right fix? This is not how such assertion failures are usually addressed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand correctly, you're basically trying to fix this problem by preventing simplifications that may make a call memory(none)
from occurring. This is definitely not a battle you can win :) SimpleLoopUnswitch is not the only pass that can do such simplifications. LoopInstSimplify is usually the easier way to produce such cases.
The more robust way to fix this is, when creating a new memory access that is essentially a clone of an existing one, to pass CreationMustSucceed=false to createDefinedAccess() and then handle no access being created.
The relevant code here (
llvm-project/llvm/lib/Transforms/Scalar/LICM.cpp
Line 1468 in 0611a66
MemoryAccess *NewMemAcc = MSSAU.createMemoryAccessInBB( |
That was my initial thought. But, as I kept digging into the root cause of the failure, I noticed the MemorySSA being outdated. Then, I found that many calls to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
/cherry-pick 18b02bb |
/pull-request #117082 |
Fixes llvm#116809. After running some passes (SimpleLoopUnswitch, LoopInstSimplify, etc.), MemorySSA might be outdated, and the instruction `I` may have become a non-memory touching instruction. LICM has already handled this, but it does not pass `CreationMustSucceed=false` to `createDefinedAccess`. (cherry picked from commit 18b02bb)
Fixes llvm#116809. After running some passes (SimpleLoopUnswitch, LoopInstSimplify, etc.), MemorySSA might be outdated, and the instruction `I` may have become a non-memory touching instruction. LICM has already handled this, but it does not pass `CreationMustSucceed=false` to `createDefinedAccess`. (cherry picked from commit 18b02bb)
Fixes llvm#116809. After running some passes (SimpleLoopUnswitch, LoopInstSimplify, etc.), MemorySSA might be outdated, and the instruction `I` may have become a non-memory touching instruction. LICM has already handled this, but it does not pass `CreationMustSucceed=false` to `createDefinedAccess`. (cherry picked from commit 18b02bb)
Fixes #116809.
After running some passes (SimpleLoopUnswitch, LoopInstSimplify, etc.), MemorySSA might be outdated, and the instruction
I
may have become a non-memory touching instruction.LICM has already handled this, but it does not pass
CreationMustSucceed=false
tocreateDefinedAccess
.