Skip to content

Commit 570f7b4

Browse files
committed
[Coro] Popless return on null allocator.
When the coroutine is using the swiftcorocc convention, branch on the nullness of the allocator argument. If it's null, use a popless return. Otherwise, use a regular return.
1 parent 6c453dd commit 570f7b4

File tree

3 files changed

+36
-1
lines changed

3 files changed

+36
-1
lines changed

llvm/include/llvm/IR/Intrinsics.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1754,6 +1754,10 @@ def int_coro_await_suspend_handle : Intrinsic<[],
17541754
[llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty],
17551755
[Throws]>;
17561756

1757+
// FIXME: enforce musttail
1758+
// XXX: attrs; not throws, wb DefaultAttrsIntrinsic
1759+
def int_coro_return : Intrinsic<[llvm_any_ty], [LLVMMatchType<0>], []>;
1760+
17571761
// Coroutine Lowering Intrinsics. Used internally by coroutine passes.
17581762

17591763
def int_coro_subfn_addr : DefaultAttrsIntrinsic<

llvm/lib/Transforms/Coroutines/CoroCleanup.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ bool Lowerer::lower(Function &F) {
7272
case Intrinsic::coro_id_async:
7373
II->replaceAllUsesWith(ConstantTokenNone::get(Context));
7474
break;
75+
case Intrinsic::coro_return:
76+
// FIXME: Remove this case with backend support.
77+
II->replaceAllUsesWith(II->getArgOperand(0));
78+
break;
7579
case Intrinsic::coro_subfn_addr:
7680
lowerSubFn(Builder, cast<CoroSubFnInst>(II));
7781
break;

llvm/lib/Transforms/Coroutines/CoroSplit.cpp

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)