[llvm] 1e28b7e - [CoroCleanup] Fix stale unwind predecessor when erase noop coro (#185337)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Mar 8 20:26:01 PDT 2026
Author: Weibo He
Date: 2026-03-09T11:25:57+08:00
New Revision: 1e28b7ef9c7480c33de836582611d9d32c84f6c8
URL: https://github.com/llvm/llvm-project/commit/1e28b7ef9c7480c33de836582611d9d32c84f6c8
DIFF: https://github.com/llvm/llvm-project/commit/1e28b7ef9c7480c33de836582611d9d32c84f6c8.diff
LOG: [CoroCleanup] Fix stale unwind predecessor when erase noop coro (#185337)
This patch fixes two crashing reports.
Close #185155
Close #185274
Added:
Modified:
llvm/lib/Transforms/Coroutines/CoroCleanup.cpp
llvm/test/Transforms/Coroutines/coro-cleanup-noop-elide.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Coroutines/CoroCleanup.cpp b/llvm/lib/Transforms/Coroutines/CoroCleanup.cpp
index c44eaddd7ee55..01b5a0a24ced0 100644
--- a/llvm/lib/Transforms/Coroutines/CoroCleanup.cpp
+++ b/llvm/lib/Transforms/Coroutines/CoroCleanup.cpp
@@ -225,6 +225,7 @@ void NoopCoroElider::visitCallBase(CallBase &CB) {
void NoopCoroElider::visitIntrinsicInst(IntrinsicInst &II) {
if (auto *SubFn = dyn_cast<CoroSubFnInst>(&II)) {
auto *User = SubFn->getUniqueUndroppableUser();
+ assert(User && "Broken module");
if (!tryEraseCallInvoke(cast<Instruction>(User)))
return;
SubFn->eraseFromParent();
@@ -242,6 +243,7 @@ bool NoopCoroElider::tryEraseCallInvoke(Instruction *I) {
Builder.SetInsertPoint(II);
Builder.CreateBr(II->getNormalDest());
eraseFromWorklist(II);
+ II->getUnwindDest()->removePredecessor(II->getParent());
II->eraseFromParent();
return true;
}
diff --git a/llvm/test/Transforms/Coroutines/coro-cleanup-noop-elide.ll b/llvm/test/Transforms/Coroutines/coro-cleanup-noop-elide.ll
index 6d9dd654b914a..7942834effcf6 100644
--- a/llvm/test/Transforms/Coroutines/coro-cleanup-noop-elide.ll
+++ b/llvm/test/Transforms/Coroutines/coro-cleanup-noop-elide.ll
@@ -2,11 +2,28 @@
; RUN: opt < %s -S -passes='coro-cleanup' | FileCheck %s
; Tests that resume or destroy a no-op coroutine can be erased; Finally, erase coro.noop if it has no users.
-define void @erase() personality i32 0 {
-; CHECK-LABEL: define void @erase() personality i32 0 {
+define void @erase(i1 %cond) personality i32 0 {
+; CHECK-LABEL: define void @erase(
+; CHECK-SAME: i1 [[COND:%.*]]) personality i32 0 {
; CHECK-NEXT: [[DONE:.*:]]
+; CHECK-NEXT: br i1 [[COND]], label %[[DONE1:.*]], label %[[OTHER:.*]]
+; CHECK: [[DONE_UNREACHABLE:.*]]:
+; CHECK-NEXT: unreachable
+; CHECK: [[DONE1]]:
; CHECK-NEXT: ret void
+; CHECK: [[UNWIND:.*]]:
+; CHECK-NEXT: [[PAD:%.*]] = landingpad { ptr, i32 }
+; CHECK-NEXT: catch ptr null
+; CHECK-NEXT: call void @terminate()
+; CHECK-NEXT: unreachable
+; CHECK: [[OTHER]]:
+; CHECK-NEXT: invoke void @terminate()
+; CHECK-NEXT: to label %[[DONE_UNREACHABLE]] unwind label %[[UNWIND]]
;
+entry:
+ br i1 %cond, label %coro, label %other
+
+coro:
%frame = call noundef ptr @llvm.coro.noop()
%resume = call ptr @llvm.coro.subfn.addr(ptr %frame, i8 0)
call fastcc void %resume(ptr %frame)
@@ -14,14 +31,18 @@ define void @erase() personality i32 0 {
invoke fastcc void %destroy(ptr %frame)
to label %done unwind label %unwind
-done:
+done: ; preds = %coro, %other
ret void
-unwind:
+unwind: ; preds = %coro, %other
+ %phi = phi i32 [ 0, %coro ], [ 1, %other ]
%pad = landingpad { ptr, i32 }
catch ptr null
call void @terminate()
unreachable
+
+other:
+ invoke void @terminate() to label %done unwind label %unwind
}
; Tests the load-and-call pattern despite mismatched calling conventions. Prevent instcombine from breaking code.
More information about the llvm-commits
mailing list