@@ -1967,7 +1967,34 @@ static void splitRetconCoroutine(Function &F, coro::Shape &Shape,
19671967 RetV = Builder.CreateInsertValue (RetV, ReturnPHIs[I], I);
19681968 }
19691969
1970- Builder.CreateRet (RetV);
1970+ if (Shape.ABI == coro::ABI::RetconOnceDynamic &&
1971+ F.getCallingConv () == CallingConv::SwiftCoro) {
1972+ // %retval = ...
1973+ // %null_allocator = icmp %1, null
1974+ // br i1 %null_allocator, label %popless, label %normal
1975+ // popless:
1976+ // ret %retval
1977+ // normal:
1978+ // %popless_retval = musttail call i64 @llvm.coro.return(%retval)
1979+ // ret %popless_retval
1980+ auto *NullAllocator = Builder.CreateCmp (
1981+ CmpInst::Predicate::ICMP_EQ, Shape.RetconLowering .Allocator ,
1982+ ConstantPointerNull::get (
1983+ cast<PointerType>(Shape.RetconLowering .Allocator ->getType ())));
1984+ auto *PoplessReturnBB = BasicBlock::Create (
1985+ F.getContext (), " coro.return.popless" , &F, NewSuspendBB);
1986+ auto *NormalReturnBB = BasicBlock::Create (
1987+ F.getContext (), " coro.return.normal" , &F, NewSuspendBB);
1988+ Builder.CreateCondBr (NullAllocator, PoplessReturnBB, NormalReturnBB);
1989+ IRBuilder<> PoplessBuilder (PoplessReturnBB);
1990+ auto *WrapRetV = PoplessBuilder.CreateIntrinsic (
1991+ RetV->getType (), Intrinsic::coro_return, {RetV});
1992+ PoplessBuilder.CreateRet (WrapRetV);
1993+ IRBuilder<> NormalBuilder (NormalReturnBB);
1994+ NormalBuilder.CreateRet (RetV);
1995+ } else {
1996+ Builder.CreateRet (RetV);
1997+ }
19711998 }
19721999
19732000 // Branch to the return block.
0 commit comments