-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[BasicBlockUtils] Handle funclets when detaching EH pad blocks #157363
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
Conversation
@llvm/pr-subscribers-llvm-ir @llvm/pr-subscribers-llvm-transforms Author: Gábor Spaits (spaits) ChangesFixes #148052 . The issue reproducer: https://godbolt.org/z/njT5ET3dj The problem in the issue was that, SimplifyCFG deemed the basic block ( This makes a few basic blocks unreachable including the one containing the
This PR disables the deletion of Full diff: https://github.com/llvm/llvm-project/pull/157363.diff 4 Files Affected:
diff --git a/llvm/include/llvm/IR/BasicBlock.h b/llvm/include/llvm/IR/BasicBlock.h
index 533808e0666d5..8c831d8380bbb 100644
--- a/llvm/include/llvm/IR/BasicBlock.h
+++ b/llvm/include/llvm/IR/BasicBlock.h
@@ -705,6 +705,7 @@ class BasicBlock final : public Value, // Basic blocks are data objects also
/// Return true if this basic block is an exception handling block.
bool isEHPad() const { return getFirstNonPHIIt()->isEHPad(); }
+ bool isEHPadWithReturn() const;
/// Return true if this basic block is a landing pad.
///
diff --git a/llvm/lib/IR/BasicBlock.cpp b/llvm/lib/IR/BasicBlock.cpp
index 3642e935397cb..51b303d36e862 100644
--- a/llvm/lib/IR/BasicBlock.cpp
+++ b/llvm/lib/IR/BasicBlock.cpp
@@ -658,6 +658,10 @@ void BasicBlock::replaceSuccessorsPhiUsesWith(BasicBlock *New) {
this->replaceSuccessorsPhiUsesWith(this, New);
}
+bool BasicBlock::isEHPadWithReturn() const {
+ return isEHPad() && isa<CleanupReturnInst>(getTerminator());
+}
+
bool BasicBlock::isLandingPad() const {
return isa<LandingPadInst>(getFirstNonPHIIt());
}
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 055e8cadaab76..ae55cee02ecb6 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -8340,8 +8340,9 @@ bool SimplifyCFGOpt::simplifyOnce(BasicBlock *BB) {
// Remove basic blocks that have no predecessors (except the entry block)...
// or that just have themself as a predecessor. These are unreachable.
- if ((pred_empty(BB) && BB != &BB->getParent()->getEntryBlock()) ||
- BB->getSinglePredecessor() == BB) {
+ if (((pred_empty(BB) && BB != &BB->getParent()->getEntryBlock()) ||
+ BB->getSinglePredecessor() == BB) &&
+ (!BB->isEHPad() || BB->isEHPadWithReturn())) {
LLVM_DEBUG(dbgs() << "Removing BB: \n" << *BB);
DeleteDeadBlock(BB, DTU);
return true;
diff --git a/llvm/test/Transforms/SimplifyCFG/keep-non-linear-cleanuppad.ll b/llvm/test/Transforms/SimplifyCFG/keep-non-linear-cleanuppad.ll
new file mode 100644
index 0000000000000..e91df1b903037
--- /dev/null
+++ b/llvm/test/Transforms/SimplifyCFG/keep-non-linear-cleanuppad.ll
@@ -0,0 +1,48 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -passes=simplifycfg -S < %s | FileCheck %s
+
+define void @_RINvCs3LQYlzOoal9_5repro13repro_genericNtB2_10ReproShapeEB2_(i64 %shapes.1) personality ptr null {
+; CHECK-LABEL: define void @_RINvCs3LQYlzOoal9_5repro13repro_genericNtB2_10ReproShapeEB2_(
+; CHECK-SAME: i64 [[SHAPES_1:%.*]]) personality ptr null {
+; CHECK-NEXT: [[START:.*:]]
+; CHECK-NEXT: [[_7:%.*]] = icmp ult i64 0, [[SHAPES_1]]
+; CHECK-NEXT: call void @llvm.assume(i1 [[_7]])
+; CHECK-NEXT: ret void
+;
+start:
+ %_7 = icmp ult i64 0, %shapes.1
+ br i1 %_7, label %bb1, label %panic
+
+bb1:
+ %_11 = icmp ult i64 0, %shapes.1
+ br i1 %_11, label %bb3, label %panic1
+
+panic:
+ unreachable
+
+bb3:
+ ret void
+
+panic1:
+ invoke void @_RNvNtCshEuXqvZjEXJ_4core9panicking18panic_bounds_check(i64 0, i64 0, ptr null)
+ to label %unreachable unwind label %funclet_bb14
+
+funclet_bb14:
+ %cleanuppad = cleanuppad within none []
+ br label %bb13
+
+unreachable:
+ unreachable
+
+bb10:
+ cleanupret from %cleanuppad5 unwind to caller
+
+funclet_bb10:
+ %cleanuppad5 = cleanuppad within none []
+ br label %bb10
+
+bb13:
+ cleanupret from %cleanuppad unwind label %funclet_bb10
+}
+
+declare void @_RNvNtCshEuXqvZjEXJ_4core9panicking18panic_bounds_check(i64, i64, ptr)
|
02c5309
to
644e0d7
Compare
I have checked the failing tests in the CI and I have found something pretty interesting. It is not caused by the PR, it is rather "found" by it.
For example in
So it may happen, that the The IR never leaves any pass in that state. It doesn't seem cause any problems for now. Addressing So summarized, it would be more pragmatic, but more expensive, while the current version also works, but the IR may be in inconsistent state (not caused by this PR, it was already in that state). This state has never caused any problem and will not cause any problem after this ptach. |
✅ With the latest revision this PR passed the C/C++ code formatter. |
I have added another commit to the PR that contains the code, that makes the dead basic block deletion fully consistent for exception handling. I will check the CI. |
I think the current version works almost 100% according to the language refrenece. There is only one thing I did not "fix". That is, the language reference says that |
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.
Looks good with the recommended suggestion
Can I please ask you @dtcxzyw to run your pre commit checks for this PR? I think they would be relevant here. Thank you. |
No new crashes. |
Thank you @dtcxzyw . |
Thank you @rnk @efriedma-quic @nikic for reviewing. I will wait some time, if there is any additional comment and then merge the PR. |
hi, we're seeing crashes after this patch:
|
Hi @aeubanks . I will check it out. |
…s" (#158364) Reverts #157363 Causes crashes, see #157363 (comment)
…llvm#157363) Fixes llvm#148052 . When removing EH Pad blocks, the value defined by them becomes poison. These poison values are then used by `catchret` and `cleanupret`, which is invalid. This commit replaces those unreachable `catchret` and `cleanupret` instructions with `unreachable`.
…H pad blocks" (#158364) Reverts llvm/llvm-project#157363 Causes crashes, see llvm/llvm-project#157363 (comment)
…llvm#157363) Fixes llvm#148052 . When removing EH Pad blocks, the value defined by them becomes poison. These poison values are then used by `catchret` and `cleanupret`, which is invalid. This commit replaces those unreachable `catchret` and `cleanupret` instructions with `unreachable`.
Fixes #148052 .
The issue reproducer: https://godbolt.org/z/njT5ET3dj
The problem in the issue was that, SimplifyCFG deemed the basic block (
bb1
) unnecessary, that would invoke the excpetion (under basic blockpanic1
). I think SimplifyCFG is right to deem it unnecessary.This makes a few basic blocks unreachable including the one containing the
cleanuppad
instruction. The "result" of the cleanuppad is replaced with poison, it is used for thecleanupret
. I don't think it is valid to use a poison value forcleanupret
. See https://llvm.org/docs/LangRef.html#cleanupret-instruction :This PR disables the deletion of
cleanuppad
basic blocks, if thecleanupret
basic block is in another block.I am open to implement any idea if you have a more generic solution in mind.