Skip to content

Commit dd23834

Browse files
committed
[CoroutineAccessors] Open code alloc fn.
Replace the runtime function with an open-coded version.
1 parent b878155 commit dd23834

File tree

6 files changed

+72
-54
lines changed

6 files changed

+72
-54
lines changed

include/swift/Runtime/Coro.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@
2222
#include <cstddef>
2323

2424
namespace swift {
25-
SWIFT_RUNTIME_EXPORT
26-
SWIFT_CC(swift) void *swift_coro_alloc(CoroAllocator *allocator, size_t size);
27-
2825
SWIFT_RUNTIME_EXPORT
2926
SWIFT_CC(swift) void swift_coro_dealloc(CoroAllocator *allocator, void *ptr);
3027
} // end namespace swift

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3008,16 +3008,6 @@ FUNCTION(MemsetS, c, memset_s, C_CC, AlwaysAvailable,
30083008
EFFECT(RuntimeEffect::NoEffect),
30093009
UNKNOWN_MEMEFFECTS)
30103010

3011-
// void *swift_coro_alloc(CoroAllocator *, size_t size);
3012-
FUNCTION(CoroAlloc,
3013-
Swift, swift_coro_alloc, SwiftCC,
3014-
CoroutineAccessorsAvailability,
3015-
RETURNS(Int8PtrTy),
3016-
ARGS(CoroAllocatorPtrTy, SizeTy),
3017-
NO_ATTRS,
3018-
EFFECT(RuntimeEffect::Allocating, RuntimeEffect::Concurrency),
3019-
UNKNOWN_MEMEFFECTS)
3020-
30213011
// void swift_coro_dealloc(CoroAllocator *, void *ptr);
30223012
FUNCTION(CoroDealloc,
30233013
Swift, swift_coro_dealloc, SwiftCC,

lib/IRGen/GenCall.cpp

Lines changed: 46 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5118,39 +5118,59 @@ void irgen::emitYieldManyCoroutineEntry(
51185118
allocFn, deallocFn, {});
51195119
}
51205120

5121-
static llvm::Constant *getCoroAllocWrapperFn(IRGenModule &IGM) {
5121+
static llvm::Constant *getCoroAllocFn(IRGenModule &IGM) {
5122+
auto isSwiftCoroCCAvailable = IGM.SwiftCoroCC == llvm::CallingConv::SwiftCoro;
51225123
return IGM.getOrCreateHelperFunction(
5123-
"__swift_coro_alloc_", IGM.Int8PtrTy,
5124-
{IGM.CoroAllocatorPtrTy, IGM.SizeTy},
5125-
[](IRGenFunction &IGF) {
5124+
"_swift_coro_alloc", IGM.Int8PtrTy, {IGM.CoroAllocatorPtrTy, IGM.SizeTy},
5125+
[isSwiftCoroCCAvailable](IRGenFunction &IGF) {
51265126
auto parameters = IGF.collectParameters();
51275127
auto *allocator = parameters.claimNext();
51285128
auto *size = parameters.claimNext();
5129-
auto *nullAllocator = IGF.Builder.CreateCmp(
5130-
llvm::CmpInst::Predicate::ICMP_EQ, allocator,
5131-
llvm::ConstantPointerNull::get(
5132-
cast<llvm::PointerType>(allocator->getType())));
5133-
auto *poplessReturn = IGF.createBasicBlock("coro.return.popless");
5134-
auto *normalReturn = IGF.createBasicBlock("coro.return.normal");
5135-
IGF.Builder.CreateCondBr(nullAllocator, poplessReturn, normalReturn);
5136-
IGF.Builder.emitBlock(poplessReturn);
5137-
// Emit the dynamic alloca.
5138-
auto *alloca =
5139-
IGF.Builder.IRBuilderBase::CreateAlloca(IGF.IGM.Int8Ty, size);
5140-
alloca->setAlignment(llvm::Align(MaximumAlignment));
5141-
auto *retPopless = IGF.Builder.CreateIntrinsic(
5142-
IGF.IGM.VoidTy, llvm::Intrinsic::ret_popless, {});
5143-
retPopless->setTailCallKind(llvm::CallInst::TailCallKind::TCK_MustTail);
5144-
IGF.Builder.CreateRet(alloca);
5145-
IGF.Builder.emitBlock(normalReturn);
5146-
auto *call = IGF.Builder.CreateCall(
5147-
IGF.IGM.getCoroAllocFunctionPointer(), {allocator, size});
5129+
if (isSwiftCoroCCAvailable) {
5130+
// swiftcorocc is available, so if there's no allocator pointer,
5131+
// allocate storage on the stack and return a pointer to it without
5132+
// popping the stack.
5133+
auto *nullAllocator = IGF.Builder.CreateCmp(
5134+
llvm::CmpInst::Predicate::ICMP_EQ, allocator,
5135+
llvm::ConstantPointerNull::get(
5136+
cast<llvm::PointerType>(allocator->getType())));
5137+
auto *poplessReturn = IGF.createBasicBlock("popless");
5138+
auto *normalReturn = IGF.createBasicBlock("normal");
5139+
IGF.Builder.CreateCondBr(nullAllocator, poplessReturn, normalReturn);
5140+
IGF.Builder.emitBlock(poplessReturn);
5141+
// Emit the dynamic alloca.
5142+
auto *alloca =
5143+
IGF.Builder.IRBuilderBase::CreateAlloca(IGF.IGM.Int8Ty, size);
5144+
alloca->setAlignment(llvm::Align(MaximumAlignment));
5145+
auto *retPopless = IGF.Builder.CreateIntrinsic(
5146+
IGF.IGM.VoidTy, llvm::Intrinsic::ret_popless, {});
5147+
retPopless->setTailCallKind(
5148+
llvm::CallInst::TailCallKind::TCK_MustTail);
5149+
IGF.Builder.CreateRet(alloca);
5150+
// Start emitting the "normal" block.
5151+
IGF.Builder.emitBlock(normalReturn);
5152+
}
5153+
auto *calleePtr = IGF.Builder.CreateInBoundsGEP(
5154+
IGF.IGM.CoroAllocatorTy, allocator,
5155+
{llvm::ConstantInt::get(IGF.IGM.Int32Ty, 0),
5156+
llvm::ConstantInt::get(IGF.IGM.Int32Ty, 1)});
5157+
auto *callee = IGF.Builder.CreateLoad(
5158+
Address(calleePtr, IGF.IGM.CoroAllocateFnTy->getPointerTo(),
5159+
IGF.IGM.getPointerAlignment()),
5160+
"allocate_fn");
5161+
auto fnPtr = FunctionPointer::createUnsigned(
5162+
FunctionPointer::Kind::Function, callee,
5163+
Signature(cast<llvm::FunctionType>(IGF.IGM.CoroAllocateFnTy), {},
5164+
IGF.IGM.SwiftCC));
5165+
auto *call = IGF.Builder.CreateCall(fnPtr, {size});
5166+
call->setDoesNotThrow();
5167+
call->setCallingConv(IGF.IGM.SwiftCC);
51485168
IGF.Builder.CreateRet(call);
51495169
},
5150-
/*setIsNoInline=*/false,
5170+
/*setIsNoInline=*/true,
51515171
/*forPrologue=*/false,
51525172
/*isPerformanceConstraint=*/false,
5153-
/*optionalLinkageOverride=*/nullptr, llvm::CallingConv::SwiftCoro);
5173+
/*optionalLinkageOverride=*/nullptr, IGM.SwiftCoroCC);
51545174
}
51555175

51565176
static llvm::Constant *getCoroDeallocWrapperFn(IRGenModule &IGM) {
@@ -5190,9 +5210,7 @@ void irgen::emitYieldOnce2CoroutineEntry(IRGenFunction &IGF,
51905210
IGF.setCoroutineAllocator(allocator);
51915211
auto isSwiftCoroCCAvailable =
51925212
IGF.IGM.SwiftCoroCC == llvm::CallingConv::SwiftCoro;
5193-
auto allocFn = IGF.IGM.getOpaquePtr(isSwiftCoroCCAvailable
5194-
? getCoroAllocWrapperFn(IGF.IGM)
5195-
: IGF.IGM.getCoroAllocFn());
5213+
auto allocFn = IGF.IGM.getOpaquePtr(getCoroAllocFn(IGF.IGM));
51965214
auto deallocFn = IGF.IGM.getOpaquePtr(isSwiftCoroCCAvailable
51975215
? getCoroDeallocWrapperFn(IGF.IGM)
51985216
: IGF.IGM.getCoroDeallocFn());

stdlib/public/runtime/Coro.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,6 @@
1616

1717
using namespace swift;
1818

19-
void *swift::swift_coro_alloc(CoroAllocator *allocator, size_t size) {
20-
return allocator->allocate(size);
21-
}
22-
2319
void swift::swift_coro_dealloc(CoroAllocator *allocator, void *ptr) {
2420
assert(allocator);
2521
// Calls to swift_coro_dealloc are emitted in resume funclets for every

test/IRGen/coroutine_accessors.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,21 @@
2424
// CHECK-SAME: swift_task_dealloc
2525
// CHECK-SAME: }
2626

27+
// CHECK-LABEL: @_swift_coro_alloc(
28+
// CHECK-SAME: ptr [[ALLOCATOR:%[^,]+]]
29+
// CHECK-SAME: [[INT]] [[SIZE:%[^)]+]]
30+
// CHECK-SAME: )
31+
// CHECK-SAME: {
32+
// CHECK: entry:
33+
// CHECK: [[ALLOCATE_FN_PTR:%[^,]+]] = getelementptr inbounds %swift.coro_allocator
34+
// CHECK-SAME: ptr [[ALLOCATOR]]
35+
// CHECK-SAME: i32 0
36+
// CHECK-SAME: i32 1
37+
// CHECK: [[ALLOCATE_FN:%[^,]+]] = load ptr, ptr [[ALLOCATE_FN_PTR]]
38+
// CHECK: [[ALLOCATION:%[^,]+]] = call swiftcc ptr [[ALLOCATE_FN]]([[INT]] [[SIZE]])
39+
// CHECK: ret ptr [[ALLOCATION]]
40+
// CHECK: }
41+
2742
@frozen
2843
public struct S {
2944
public var o: any AnyObject

test/IRGen/coroutine_accessors_popless.swift

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,26 +28,28 @@
2828
// CHECK-SAME: free
2929
// CHECK-SAME: }
3030

31-
// CHECK-LABEL: @__swift_coro_alloc_(
31+
// CHECK-LABEL: @_swift_coro_alloc(
3232
// CHECK-SAME: ptr [[ALLOCATOR:%[^,]+]]
3333
// CHECK-SAME: i64 [[SIZE:%[^)]+]]
3434
// CHECK-SAME: )
3535
// CHECK-SAME: {
3636
// CHECK: entry:
3737
// CHECK: [[USE_POPLESS:%[^,]+]] = icmp eq ptr [[ALLOCATOR]], null
3838
// CHECK: br i1 [[USE_POPLESS]],
39-
// CHECK-SAME: label %coro.return.popless
40-
// CHECK-SAME: label %coro.return.normal
41-
// CHECK: coro.return.popless:
39+
// CHECK-SAME: label %popless
40+
// CHECK-SAME: label %normal
41+
// CHECK: popless:
4242
// CHECK: [[STACK_ALLOCATION:%[^,]+]] = alloca i8, i64 [[SIZE]]
4343
// CHECK: musttail call void @llvm.ret.popless()
4444
// CHECK: ret ptr [[STACK_ALLOCATION]]
45-
// CHECK: coro.return.normal:
46-
// CHECK: [[OTHER_ALLOCATION:%[^,]+]] = call swiftcc ptr @swift_coro_alloc(
45+
// CHECK: normal:
46+
// CHECK: [[ALLOCATE_FN_PTR:%[^,]+]] = getelementptr inbounds %swift.coro_allocator
4747
// CHECK-SAME: ptr [[ALLOCATOR]]
48-
// CHECK-SAME: i64 [[SIZE]]
49-
// CHECK-SAME: )
50-
// CHECK: ret ptr [[OTHER_ALLOCATION]]
48+
// CHECK-SAME: i32 0
49+
// CHECK-SAME: i32 1
50+
// CHECK: [[ALLOCATE_FN:%[^,]+]] = load ptr, ptr [[ALLOCATE_FN_PTR]]
51+
// CHECK: [[ALLOCATION:%[^,]+]] = call swiftcc ptr [[ALLOCATE_FN]](i64 [[SIZE]])
52+
// CHECK: ret ptr [[ALLOCATION]]
5153
// CHECK: }
5254

5355
// CHECK-LABEL: @__swift_coro_dealloc_(

0 commit comments

Comments
 (0)