Skip to content

Commit dbcd038

Browse files
committed
[CoroutineAccessors] Add wrapper for dealloc.
Make the fast path faster by avoiding a dyld stub.
1 parent f30d8a6 commit dbcd038

File tree

3 files changed

+53
-3
lines changed

3 files changed

+53
-3
lines changed

lib/IRGen/GenCall.cpp

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5153,6 +5153,35 @@ static llvm::Constant *getCoroAllocWrapperFn(IRGenModule &IGM) {
51535153
/*optionalLinkageOverride=*/nullptr, llvm::CallingConv::SwiftCoro);
51545154
}
51555155

5156+
static llvm::Constant *getCoroDeallocWrapperFn(IRGenModule &IGM) {
5157+
return IGM.getOrCreateHelperFunction(
5158+
"__swift_coro_dealloc_", IGM.VoidTy,
5159+
{IGM.CoroAllocatorPtrTy, IGM.Int8PtrTy},
5160+
[](IRGenFunction &IGF) {
5161+
auto parameters = IGF.collectParameters();
5162+
auto *allocator = parameters.claimNext();
5163+
auto *ptr = parameters.claimNext();
5164+
auto *nullAllocator = IGF.Builder.CreateCmp(
5165+
llvm::CmpInst::Predicate::ICMP_EQ, allocator,
5166+
llvm::ConstantPointerNull::get(
5167+
cast<llvm::PointerType>(allocator->getType())));
5168+
auto *bailBlock = IGF.createBasicBlock("bail");
5169+
auto *forwardBlock = IGF.createBasicBlock("forward");
5170+
IGF.Builder.CreateCondBr(nullAllocator, bailBlock, forwardBlock);
5171+
IGF.Builder.emitBlock(bailBlock);
5172+
// Emit the dynamic alloca.
5173+
IGF.Builder.CreateRetVoid();
5174+
IGF.Builder.emitBlock(forwardBlock);
5175+
IGF.Builder.CreateCall(
5176+
IGF.IGM.getCoroDeallocFunctionPointer(), {allocator, ptr});
5177+
IGF.Builder.CreateRetVoid();
5178+
},
5179+
/*setIsNoInline=*/false,
5180+
/*forPrologue=*/false,
5181+
/*isPerformanceConstraint=*/false,
5182+
/*optionalLinkageOverride=*/nullptr, llvm::CallingConv::SwiftCoro);
5183+
}
5184+
51565185
void irgen::emitYieldOnce2CoroutineEntry(IRGenFunction &IGF,
51575186
CanSILFunctionType fnType,
51585187
llvm::Value *buffer,
@@ -5164,7 +5193,9 @@ void irgen::emitYieldOnce2CoroutineEntry(IRGenFunction &IGF,
51645193
auto allocFn = IGF.IGM.getOpaquePtr(isSwiftCoroCCAvailable
51655194
? getCoroAllocWrapperFn(IGF.IGM)
51665195
: IGF.IGM.getCoroAllocFn());
5167-
auto deallocFn = IGF.IGM.getOpaquePtr(IGF.IGM.getCoroDeallocFn());
5196+
auto deallocFn = IGF.IGM.getOpaquePtr(isSwiftCoroCCAvailable
5197+
? getCoroDeallocWrapperFn(IGF.IGM)
5198+
: IGF.IGM.getCoroDeallocFn());
51685199
emitRetconCoroutineEntry(
51695200
IGF, fnType, buffer, llvm::Intrinsic::coro_id_retcon_once_dynamic,
51705201
Size(-1) /*dynamic-to-IRGen size*/, IGF.IGM.getCoroStaticFrameAlignment(),

stdlib/public/runtime/Coro.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ void *swift::swift_coro_alloc(CoroAllocator *allocator, size_t size) {
2121
}
2222

2323
void swift::swift_coro_dealloc(CoroAllocator *allocator, void *ptr) {
24-
if (!allocator)
25-
return;
24+
assert(allocator);
2625
// Calls to swift_coro_dealloc are emitted in resume funclets for every
2726
// live-across dynamic allocation. Whether such calls immediately deallocate
2827
// memory depends on the allocator.

test/IRGen/coroutine_accessors_popless.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,26 @@
5050
// CHECK: ret ptr [[OTHER_ALLOCATION]]
5151
// CHECK: }
5252

53+
// CHECK-LABEL: @__swift_coro_dealloc_(
54+
// CHECK-SAME: ptr [[ALLOCATOR:%[^,]+]]
55+
// CHECK-SAME: ptr [[ADDRESS:%[^)]+]]
56+
// CHECK-SAME: )
57+
// CHECK-SAME: {
58+
// CHECK: entry:
59+
// CHECK: [[BAIL:%[^,]+]] = icmp eq ptr [[ALLOCATOR]], null
60+
// CHECK: br i1 [[USE_POPLESS]],
61+
// CHECK-SAME: label %bail
62+
// CHECK-SAME: label %forward
63+
// CHECK: bail:
64+
// CHECK: ret void
65+
// CHECK: forward:
66+
// CHECK: call swiftcc void @swift_coro_dealloc(
67+
// CHECK-SAME: ptr [[ALLOCATOR]]
68+
// CHECK-SAME: ptr [[ADDRESS]]
69+
// CHECK-SAME: )
70+
// CHECK: ret void
71+
// CHECK: }
72+
5373
public var _i: Int = 0
5474

5575
public var i: Int {

0 commit comments

Comments
 (0)