mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-12 22:30:12 +00:00
[coroutines] PR33271: Remove stray coro.save intrinsics during CoroSplit
Summary: Optimization passes may remove llvm.coro.suspend intrinsic while leaving matching llvm.coro.save intrinsic orphaned. Make sure we clean up orphaned coro.saves. The bug manifested with a crash similar to this: ``` llvm_unreachable("Unknown type!"); llvm::MVT::getVT (Ty=0x489518, HandleUnknown=false) llvm::EVT::getEVT llvm::TargetLoweringBase::getValueType llvm::ComputeValueVTs llvm::SelectionDAGBuilder::visitTargetIntrinsic ``` Reviewers: GorNishanov Subscribers: EricWF, llvm-commits Differential Revision: https://reviews.llvm.org/D33817 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@304518 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
79a680d764
commit
1b0c4ab66c
@ -218,6 +218,8 @@ void coro::Shape::buildFrom(Function &F) {
|
||||
size_t FinalSuspendIndex = 0;
|
||||
clear(*this);
|
||||
SmallVector<CoroFrameInst *, 8> CoroFrames;
|
||||
SmallVector<CoroSaveInst *, 2> UnusedCoroSaves;
|
||||
|
||||
for (Instruction &I : instructions(F)) {
|
||||
if (auto II = dyn_cast<IntrinsicInst>(&I)) {
|
||||
switch (II->getIntrinsicID()) {
|
||||
@ -229,6 +231,12 @@ void coro::Shape::buildFrom(Function &F) {
|
||||
case Intrinsic::coro_frame:
|
||||
CoroFrames.push_back(cast<CoroFrameInst>(II));
|
||||
break;
|
||||
case Intrinsic::coro_save:
|
||||
// After optimizations, coro_suspends using this coro_save might have
|
||||
// been removed, remember orphaned coro_saves to remove them later.
|
||||
if (II->use_empty())
|
||||
UnusedCoroSaves.push_back(cast<CoroSaveInst>(II));
|
||||
break;
|
||||
case Intrinsic::coro_suspend:
|
||||
CoroSuspends.push_back(cast<CoroSuspendInst>(II));
|
||||
if (CoroSuspends.back()->isFinal()) {
|
||||
@ -311,4 +319,8 @@ void coro::Shape::buildFrom(Function &F) {
|
||||
if (HasFinalSuspend &&
|
||||
FinalSuspendIndex != CoroSuspends.size() - 1)
|
||||
std::swap(CoroSuspends[FinalSuspendIndex], CoroSuspends.back());
|
||||
|
||||
// Remove orphaned coro.saves.
|
||||
for (CoroSaveInst *CoroSave : UnusedCoroSaves)
|
||||
CoroSave->eraseFromParent();
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
; Tests that coro-split can handle the case when a code after coro.suspend uses
|
||||
; a value produces between coro.save and coro.suspend (%Result.i19)
|
||||
; and checks whether stray coro.saves are properly removed
|
||||
; RUN: opt < %s -coro-split -S | FileCheck %s
|
||||
|
||||
%"struct.std::coroutine_handle" = type { i8* }
|
||||
@ -24,9 +25,10 @@ entry:
|
||||
i8 1, label %exit
|
||||
]
|
||||
await.ready:
|
||||
%StrayCoroSave = call token @llvm.coro.save(i8* null)
|
||||
%val = load i32, i32* %Result.i19
|
||||
call void @print(i32 %val)
|
||||
br label %exit
|
||||
br label %exit
|
||||
exit:
|
||||
call i1 @llvm.coro.end(i8* null, i1 false)
|
||||
ret void
|
||||
@ -35,6 +37,7 @@ exit:
|
||||
; CHECK-LABEL: @a.resume(
|
||||
; CHECK: getelementptr inbounds %a.Frame
|
||||
; CHECK-NEXT: getelementptr inbounds %"struct.lean_future<int>::Awaiter"
|
||||
; CHECK-NOT: call token @llvm.coro.save(i8* null)
|
||||
; CHECK-NEXT: %val = load i32, i32* %Result
|
||||
; CHECK-NEXT: call void @print(i32 %val)
|
||||
; CHECK-NEXT: ret void
|
||||
|
Loading…
x
Reference in New Issue
Block a user