Skip to content

Commit c141586

Browse files
committed
[CoroutineAccessors] Open code dealloc fn.
1 parent dd23834 commit c141586

File tree

8 files changed

+115
-63
lines changed

8 files changed

+115
-63
lines changed

include/swift/Runtime/Coro.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,6 @@
2121
#include "swift/Runtime/Config.h"
2222
#include <cstddef>
2323

24-
namespace swift {
25-
SWIFT_RUNTIME_EXPORT
26-
SWIFT_CC(swift) void swift_coro_dealloc(CoroAllocator *allocator, void *ptr);
27-
} // end namespace swift
24+
namespace swift {} // end namespace swift
2825

2926
#endif

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_dealloc(CoroAllocator *, void *ptr);
3012-
FUNCTION(CoroDealloc,
3013-
Swift, swift_coro_dealloc, SwiftCC,
3014-
CoroutineAccessorsAvailability,
3015-
RETURNS(VoidTy),
3016-
ARGS(CoroAllocatorPtrTy, Int8PtrTy),
3017-
NO_ATTRS,
3018-
EFFECT(RuntimeEffect::Deallocating, RuntimeEffect::Concurrency),
3019-
UNKNOWN_MEMEFFECTS)
3020-
30213011
#undef RETURNS
30223012
#undef ARGS
30233013
#undef ATTRS

lib/IRGen/GenCall.cpp

Lines changed: 63 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5173,33 +5173,78 @@ static llvm::Constant *getCoroAllocFn(IRGenModule &IGM) {
51735173
/*optionalLinkageOverride=*/nullptr, IGM.SwiftCoroCC);
51745174
}
51755175

5176-
static llvm::Constant *getCoroDeallocWrapperFn(IRGenModule &IGM) {
5176+
static llvm::Constant *getCoroDeallocFn(IRGenModule &IGM) {
5177+
auto isSwiftCoroCCAvailable = IGM.SwiftCoroCC == llvm::CallingConv::SwiftCoro;
51775178
return IGM.getOrCreateHelperFunction(
5178-
"__swift_coro_dealloc_", IGM.VoidTy,
5179+
"_swift_coro_dealloc", IGM.VoidTy,
51795180
{IGM.CoroAllocatorPtrTy, IGM.Int8PtrTy},
5180-
[](IRGenFunction &IGF) {
5181+
[isSwiftCoroCCAvailable](IRGenFunction &IGF) {
51815182
auto parameters = IGF.collectParameters();
51825183
auto *allocator = parameters.claimNext();
51835184
auto *ptr = parameters.claimNext();
5184-
auto *nullAllocator = IGF.Builder.CreateCmp(
5185-
llvm::CmpInst::Predicate::ICMP_EQ, allocator,
5186-
llvm::ConstantPointerNull::get(
5187-
cast<llvm::PointerType>(allocator->getType())));
5188-
auto *bailBlock = IGF.createBasicBlock("bail");
5189-
auto *forwardBlock = IGF.createBasicBlock("forward");
5190-
IGF.Builder.CreateCondBr(nullAllocator, bailBlock, forwardBlock);
5191-
IGF.Builder.emitBlock(bailBlock);
5192-
// Emit the dynamic alloca.
5185+
if (isSwiftCoroCCAvailable) {
5186+
// swiftcorocc is available, so if there's no allocator pointer,
5187+
// storage was allocated on the stack which will be naturally cleaned
5188+
// up when the coroutine's frame is "freed".
5189+
auto *nullAllocator = IGF.Builder.CreateCmp(
5190+
llvm::CmpInst::Predicate::ICMP_EQ, allocator,
5191+
llvm::ConstantPointerNull::get(
5192+
cast<llvm::PointerType>(allocator->getType())));
5193+
auto *bailBlock = IGF.createBasicBlock("null_allocator");
5194+
auto *normalBlock = IGF.createBasicBlock("nonnull_allocator");
5195+
IGF.Builder.CreateCondBr(nullAllocator, bailBlock, normalBlock);
5196+
IGF.Builder.emitBlock(bailBlock);
5197+
// Nothing to do here.
5198+
IGF.Builder.CreateRetVoid();
5199+
// Start emitting the "normal" block.
5200+
IGF.Builder.emitBlock(normalBlock);
5201+
}
5202+
auto shouldDeallocateImmediatelyFlag = CoroAllocatorFlags(0);
5203+
shouldDeallocateImmediatelyFlag.setShouldDeallocateImmediately(true);
5204+
auto *flagsPtr = IGF.Builder.CreateInBoundsGEP(
5205+
IGF.IGM.CoroAllocatorTy, allocator,
5206+
{llvm::ConstantInt::get(IGF.IGM.Int32Ty, 0),
5207+
llvm::ConstantInt::get(IGF.IGM.Int32Ty, 0)});
5208+
auto *flags = IGF.Builder.CreateLoad(
5209+
Address(flagsPtr, IGF.IGM.Int32Ty, Alignment(4)), "");
5210+
auto *deallocDeferringAllocator = IGF.Builder.CreateAnd(
5211+
flags,
5212+
llvm::APInt(IGF.IGM.Int32Ty->getBitWidth(),
5213+
shouldDeallocateImmediatelyFlag.getOpaqueValue()));
5214+
auto *isDeallocDeferringAllocator = IGF.Builder.CreateICmpNE(
5215+
deallocDeferringAllocator,
5216+
llvm::ConstantInt::get(IGF.IGM.Int32Ty, 0));
5217+
auto *deferringAllocatorBlock =
5218+
IGF.createBasicBlock("deferring_allocator");
5219+
auto *normalBlock = IGF.createBasicBlock("normal");
5220+
IGF.Builder.CreateCondBr(isDeallocDeferringAllocator,
5221+
deferringAllocatorBlock, normalBlock);
5222+
IGF.Builder.emitBlock(deferringAllocatorBlock);
5223+
// Nothing to do here.
51935224
IGF.Builder.CreateRetVoid();
5194-
IGF.Builder.emitBlock(forwardBlock);
5195-
IGF.Builder.CreateCall(
5196-
IGF.IGM.getCoroDeallocFunctionPointer(), {allocator, ptr});
5225+
// Start emitting the "normal" block.
5226+
IGF.Builder.emitBlock(normalBlock);
5227+
auto *calleePtr = IGF.Builder.CreateInBoundsGEP(
5228+
IGF.IGM.CoroAllocatorTy, allocator,
5229+
{llvm::ConstantInt::get(IGF.IGM.Int32Ty, 0),
5230+
llvm::ConstantInt::get(IGF.IGM.Int32Ty, 2)});
5231+
auto *callee = IGF.Builder.CreateLoad(
5232+
Address(calleePtr, IGF.IGM.CoroDeallocateFnTy->getPointerTo(),
5233+
IGF.IGM.getPointerAlignment()),
5234+
"deallocate_fn");
5235+
auto fnPtr = FunctionPointer::createUnsigned(
5236+
FunctionPointer::Kind::Function, callee,
5237+
Signature(cast<llvm::FunctionType>(IGF.IGM.CoroDeallocateFnTy), {},
5238+
IGF.IGM.SwiftCC));
5239+
auto *call = IGF.Builder.CreateCall(fnPtr, {ptr});
5240+
call->setDoesNotThrow();
5241+
call->setCallingConv(IGF.IGM.SwiftCC);
51975242
IGF.Builder.CreateRetVoid();
51985243
},
5199-
/*setIsNoInline=*/false,
5244+
/*setIsNoInline=*/true,
52005245
/*forPrologue=*/false,
52015246
/*isPerformanceConstraint=*/false,
5202-
/*optionalLinkageOverride=*/nullptr, llvm::CallingConv::SwiftCoro);
5247+
/*optionalLinkageOverride=*/nullptr, IGM.SwiftCoroCC);
52035248
}
52045249

52055250
void irgen::emitYieldOnce2CoroutineEntry(IRGenFunction &IGF,
@@ -5208,12 +5253,8 @@ void irgen::emitYieldOnce2CoroutineEntry(IRGenFunction &IGF,
52085253
llvm::Value *allocator,
52095254
llvm::GlobalVariable *cfp) {
52105255
IGF.setCoroutineAllocator(allocator);
5211-
auto isSwiftCoroCCAvailable =
5212-
IGF.IGM.SwiftCoroCC == llvm::CallingConv::SwiftCoro;
52135256
auto allocFn = IGF.IGM.getOpaquePtr(getCoroAllocFn(IGF.IGM));
5214-
auto deallocFn = IGF.IGM.getOpaquePtr(isSwiftCoroCCAvailable
5215-
? getCoroDeallocWrapperFn(IGF.IGM)
5216-
: IGF.IGM.getCoroDeallocFn());
5257+
auto deallocFn = IGF.IGM.getOpaquePtr(getCoroDeallocFn(IGF.IGM));
52175258
emitRetconCoroutineEntry(
52185259
IGF, fnType, buffer, llvm::Intrinsic::coro_id_retcon_once_dynamic,
52195260
Size(-1) /*dynamic-to-IRGen size*/, IGF.IGM.getCoroStaticFrameAlignment(),

stdlib/public/runtime/Coro.cpp

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,3 @@
1515
#include "swift/Basic/FlagSet.h"
1616

1717
using namespace swift;
18-
19-
void swift::swift_coro_dealloc(CoroAllocator *allocator, void *ptr) {
20-
assert(allocator);
21-
// Calls to swift_coro_dealloc are emitted in resume funclets for every
22-
// live-across dynamic allocation. Whether such calls immediately deallocate
23-
// memory depends on the allocator.
24-
if (!allocator->shouldDeallocateImmediately()) {
25-
return;
26-
}
27-
allocator->deallocate(ptr);
28-
}

test/IRGen/coroutine_accessors.swift

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,34 @@
3939
// CHECK: ret ptr [[ALLOCATION]]
4040
// CHECK: }
4141

42+
// CHECK-LABEL: @_swift_coro_dealloc(
43+
// CHECK-SAME: ptr [[ALLOCATOR:%[^,]+]]
44+
// CHECK-SAME: ptr [[ADDRESS:%[^)]+]]
45+
// CHECK-SAME: )
46+
// CHECK-SAME: {
47+
// CHECK: entry:
48+
// CHECK: [[FLAGS_ADDR:%[^,]+]] = getelementptr inbounds %swift.coro_allocator
49+
// CHECK-SAME: ptr [[ALLOCATOR]]
50+
// CHECK-SAME: i32 0
51+
// CHECK-SAME: i32 0
52+
// CHECK: [[FLAGS:%[^,]+]] = load i32, ptr [[FLAGS_ADDR]], align 4
53+
// CHECK: [[DEALLOC_DEFERRING_ALLOCATOR:%[^,]+]] = and i32 [[FLAGS]], 256
54+
// CHECK: [[IS_DEALLOC_DEFERRING_ALLOCATOR:%[^,]+]] = icmp ne i32 [[DEALLOC_DEFERRING_ALLOCATOR]], 0
55+
// CHECK: br i1 [[IS_DEALLOC_DEFERRING_ALLOCATOR]]
56+
// CHECK-SAME: label %deferring_allocator
57+
// CHECK-SAME: label %normal
58+
// CHECK: deferring_allocator:
59+
// CHECK: ret void
60+
// CHECK: normal:
61+
// CHECK: [[DEALLOCATE_FN_PTR:%[^,]+]] = getelementptr inbounds %swift.coro_allocator
62+
// CHECK-SAME: ptr [[ALLOCATOR]]
63+
// CHECK-SAME: i32 0
64+
// CHECK-SAME: i32 2
65+
// CHECK: [[DEALLOCATE_FN:%[^,]+]] = load ptr, ptr [[DEALLOCATE_FN_PTR]]
66+
// CHECK: call swiftcc void [[DEALLOCATE_FN]](ptr [[ADDRESS]])
67+
// CHECK: ret void
68+
// CHECK: }
69+
4270
@frozen
4371
public struct S {
4472
public var o: any AnyObject

test/IRGen/coroutine_accessors_popless.swift

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,23 +52,38 @@
5252
// CHECK: ret ptr [[ALLOCATION]]
5353
// CHECK: }
5454

55-
// CHECK-LABEL: @__swift_coro_dealloc_(
55+
// CHECK-LABEL: @_swift_coro_dealloc(
5656
// CHECK-SAME: ptr [[ALLOCATOR:%[^,]+]]
5757
// CHECK-SAME: ptr [[ADDRESS:%[^)]+]]
5858
// CHECK-SAME: )
5959
// CHECK-SAME: {
6060
// CHECK: entry:
6161
// CHECK: [[BAIL:%[^,]+]] = icmp eq ptr [[ALLOCATOR]], null
6262
// CHECK: br i1 [[USE_POPLESS]],
63-
// CHECK-SAME: label %bail
64-
// CHECK-SAME: label %forward
65-
// CHECK: bail:
63+
// CHECK-SAME: label %null_allocator
64+
// CHECK-SAME: label %nonnull_allocator
65+
// CHECK: null_allocator:
6666
// CHECK: ret void
67-
// CHECK: forward:
68-
// CHECK: call swiftcc void @swift_coro_dealloc(
67+
// CHECK: nonnull_allocator:
68+
// CHECK: [[FLAGS_ADDR:%[^,]+]] = getelementptr inbounds %swift.coro_allocator
6969
// CHECK-SAME: ptr [[ALLOCATOR]]
70-
// CHECK-SAME: ptr [[ADDRESS]]
71-
// CHECK-SAME: )
70+
// CHECK-SAME: i32 0
71+
// CHECK-SAME: i32 0
72+
// CHECK: [[FLAGS:%[^,]+]] = load i32, ptr [[FLAGS_ADDR]], align 4
73+
// CHECK: [[DEALLOC_DEFERRING_ALLOCATOR:%[^,]+]] = and i32 [[FLAGS]], 256
74+
// CHECK: [[IS_DEALLOC_DEFERRING_ALLOCATOR:%[^,]+]] = icmp ne i32 [[DEALLOC_DEFERRING_ALLOCATOR]], 0
75+
// CHECK: br i1 [[IS_DEALLOC_DEFERRING_ALLOCATOR]]
76+
// CHECK-SAME: label %deferring_allocator
77+
// CHECK-SAME: label %normal
78+
// CHECK: deferring_allocator:
79+
// CHECK: ret void
80+
// CHECK: normal:
81+
// CHECK: [[DEALLOCATE_FN_PTR:%[^,]+]] = getelementptr inbounds %swift.coro_allocator
82+
// CHECK-SAME: ptr [[ALLOCATOR]]
83+
// CHECK-SAME: i32 0
84+
// CHECK-SAME: i32 2
85+
// CHECK: [[DEALLOCATE_FN:%[^,]+]] = load ptr, ptr [[DEALLOCATE_FN_PTR]]
86+
// CHECK: call swiftcc void [[DEALLOCATE_FN]](ptr [[ADDRESS]])
7287
// CHECK: ret void
7388
// CHECK: }
7489

test/abi/macOS/arm64/stdlib.swift

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -942,7 +942,3 @@ Added: _$ss18EnumeratedSequenceVsSlRzrlE7isEmptySbvpMV
942942
Added: _$ss18EnumeratedSequenceVsSlRzrlE8endIndexABsSlRzrlE0D0Vyx_GvpMV
943943
Added: _$ss18EnumeratedSequenceVsSlRzrlEySi6offset_7ElementQz7elementtABsSlRzrlE5IndexVyx_GcipMV
944944
Added: _$ss18EnumeratedSequenceVyxGSKsSkRzrlMc
945-
946-
// CoroutineAccessors
947-
Added: _swift_coro_alloc
948-
Added: _swift_coro_dealloc

test/abi/macOS/x86_64/stdlib.swift

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -942,7 +942,3 @@ Added: _$ss18EnumeratedSequenceVsSlRzrlE7isEmptySbvpMV
942942
Added: _$ss18EnumeratedSequenceVsSlRzrlE8endIndexABsSlRzrlE0D0Vyx_GvpMV
943943
Added: _$ss18EnumeratedSequenceVsSlRzrlEySi6offset_7ElementQz7elementtABsSlRzrlE5IndexVyx_GcipMV
944944
Added: _$ss18EnumeratedSequenceVyxGSKsSkRzrlMc
945-
946-
// CoroutineAccessors
947-
Added: _swift_coro_alloc
948-
Added: _swift_coro_dealloc

0 commit comments

Comments
 (0)