diff --git a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp index 8ac0b4f9636aa4..aadd7fe3dd5652 100644 --- a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp @@ -1201,6 +1201,22 @@ static bool simplifyTerminatorLeadingToRet(Instruction *InitialInst) { assert(InitialInst->getModule()); const DataLayout &DL = InitialInst->getModule()->getDataLayout(); + auto GetFirstValidInstruction = [](Instruction *I) { + while (I) { + // BitCastInst wouldn't generate actual code so that we could skip it. + if (isa(I) || I->isDebugOrPseudoInst() || + I->isLifetimeStartOrEnd()) + I = I->getNextNode(); + else if (isInstructionTriviallyDead(I)) + // Duing we are in the middle of the transformation, we need to erase + // the dead instruction manually. + I = &*I->eraseFromParent(); + else + break; + } + return I; + }; + auto TryResolveConstant = [&ResolvedValues](Value *V) { auto It = ResolvedValues.find(V); if (It != ResolvedValues.end()) @@ -1209,8 +1225,7 @@ static bool simplifyTerminatorLeadingToRet(Instruction *InitialInst) { }; Instruction *I = InitialInst; - while (I->isTerminator() || - (isa(I) && I->getNextNode()->isTerminator())) { + while (I->isTerminator() || isa(I)) { if (isa(I)) { if (I != InitialInst) { // If InitialInst is an unconditional branch, @@ -1227,7 +1242,7 @@ static bool simplifyTerminatorLeadingToRet(Instruction *InitialInst) { if (I == InitialInst) UnconditionalSucc = Succ; scanPHIsAndUpdateValueMap(I, Succ, ResolvedValues); - I = Succ->getFirstNonPHIOrDbgOrLifetime(); + I = GetFirstValidInstruction(Succ->getFirstNonPHIOrDbgOrLifetime()); continue; } @@ -1247,7 +1262,8 @@ static bool simplifyTerminatorLeadingToRet(Instruction *InitialInst) { } else if (auto *CondCmp = dyn_cast(I)) { // If the case number of suspended switch instruction is reduced to // 1, then it is simplified to CmpInst in llvm::ConstantFoldTerminator. - auto *BR = dyn_cast(I->getNextNode()); + auto *BR = dyn_cast( + GetFirstValidInstruction(CondCmp->getNextNode())); if (!BR || !BR->isConditional() || CondCmp != BR->getCondition()) return false; @@ -1280,9 +1296,10 @@ static bool simplifyTerminatorLeadingToRet(Instruction *InitialInst) { BasicBlock *BB = SI->findCaseValue(Cond)->getCaseSuccessor(); scanPHIsAndUpdateValueMap(I, BB, ResolvedValues); - I = BB->getFirstNonPHIOrDbgOrLifetime(); + I = GetFirstValidInstruction(BB->getFirstNonPHIOrDbgOrLifetime()); continue; } + return false; } return false; diff --git a/llvm/test/Transforms/Coroutines/coro-split-musttail5.ll b/llvm/test/Transforms/Coroutines/coro-split-musttail5.ll index 84a52e47f939d5..9f29f1d8b8938b 100644 --- a/llvm/test/Transforms/Coroutines/coro-split-musttail5.ll +++ b/llvm/test/Transforms/Coroutines/coro-split-musttail5.ll @@ -36,10 +36,10 @@ exit: ret void } -; FIXME: The fakeresume1 here should be marked as musttail. ; Verify that in the resume part resume call is marked with musttail. ; CHECK-LABEL: @g.resume( -; CHECK-NOT: musttail call fastcc void @fakeresume1(i64* align 8 null) +; CHECK: musttail call fastcc void @fakeresume1(i64* align 8 null) +; CHECK-NEXT: ret void declare token @llvm.coro.id(i32, i8* readnone, i8* nocapture readonly, i8*) #1 declare i1 @llvm.coro.alloc(token) #2 diff --git a/llvm/test/Transforms/Coroutines/coro-split-musttail6.ll b/llvm/test/Transforms/Coroutines/coro-split-musttail6.ll index f139b8fb58843a..a86de71278a593 100644 --- a/llvm/test/Transforms/Coroutines/coro-split-musttail6.ll +++ b/llvm/test/Transforms/Coroutines/coro-split-musttail6.ll @@ -40,10 +40,10 @@ exit: ret void } -; FIXME: The fakeresume1 here should be marked as musttail. ; Verify that in the resume part resume call is marked with musttail. ; CHECK-LABEL: @g.resume( -; CHECK-NOT: musttail call fastcc void @fakeresume1(i64* align 8 null) +; CHECK: musttail call fastcc void @fakeresume1(i64* align 8 null) +; CHECK-NEXT: ret void ; It has a cleanup bb. define void @f() #0 { @@ -92,7 +92,8 @@ exit: ; FIXME: The fakeresume1 here should be marked as musttail. ; Verify that in the resume part resume call is marked with musttail. ; CHECK-LABEL: @f.resume( -; CHECK-NOT: musttail call fastcc void @fakeresume1(i64* align 8 null) +; CHECK: musttail call fastcc void @fakeresume1(i64* align 8 null) +; CHECK-NEXT: ret void declare token @llvm.coro.id(i32, i8* readnone, i8* nocapture readonly, i8*) #1 declare i1 @llvm.coro.alloc(token) #2 diff --git a/llvm/test/Transforms/Coroutines/coro-split-musttail7.ll b/llvm/test/Transforms/Coroutines/coro-split-musttail7.ll index ce1f7203a0c7e6..4d176cbb2c66ad 100644 --- a/llvm/test/Transforms/Coroutines/coro-split-musttail7.ll +++ b/llvm/test/Transforms/Coroutines/coro-split-musttail7.ll @@ -41,10 +41,10 @@ exit: ret void } -; FIXME: The fakeresume1 here should be marked as musttail. ; Verify that in the resume part resume call is marked with musttail. ; CHECK-LABEL: @g.resume( -; CHECK-NOT: musttail call fastcc void @fakeresume1(i64* align 8 null) +; CHECK: musttail call fastcc void @fakeresume1(i64* align 8 null) +; CHECK-NEXT: ret void ; It has a cleanup bb. define void @f() #0 { @@ -94,7 +94,8 @@ exit: ; FIXME: The fakeresume1 here should be marked as musttail. ; Verify that in the resume part resume call is marked with musttail. ; CHECK-LABEL: @f.resume( -; CHECK-NOT: musttail call fastcc void @fakeresume1(i64* align 8 null) +; CHECK: musttail call fastcc void @fakeresume1(i64* align 8 null) +; CHECK-NEXT: ret void declare token @llvm.coro.id(i32, i8* readnone, i8* nocapture readonly, i8*) #1 declare i1 @llvm.coro.alloc(token) #2