Skip to content

Commit e52b2dd

Browse files
Merge pull request #11671 from nate-chandler/general-coro/20251009/1
stable/21.x: [Coro] RetconOnceDynamic: Distinguish frame allocs and pass frame pointers.
2 parents 1f484c9 + a1c6568 commit e52b2dd

File tree

10 files changed

+262
-61
lines changed

10 files changed

+262
-61
lines changed

llvm/include/llvm/IR/Intrinsics.td

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1771,7 +1771,7 @@ def int_coro_id_retcon_once : Intrinsic<[llvm_token_ty],
17711771
[]>;
17721772
def int_coro_id_retcon_once_dynamic : Intrinsic<[llvm_token_ty],
17731773
[llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty,
1774-
llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty],
1774+
llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty],
17751775
[]>;
17761776
def int_coro_alloc : Intrinsic<[llvm_i1_ty], [llvm_token_ty], []>;
17771777
def int_coro_id_async : Intrinsic<[llvm_token_ty],
@@ -1818,8 +1818,11 @@ def int_coro_prepare_retcon : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty],
18181818
[IntrNoMem]>;
18191819
def int_coro_alloca_alloc : Intrinsic<[llvm_token_ty],
18201820
[llvm_anyint_ty, llvm_i32_ty], []>;
1821+
def int_coro_alloca_alloc_frame : Intrinsic<[llvm_token_ty],
1822+
[llvm_anyint_ty, llvm_i32_ty], []>;
18211823
def int_coro_alloca_get : Intrinsic<[llvm_ptr_ty], [llvm_token_ty], []>;
18221824
def int_coro_alloca_free : Intrinsic<[], [llvm_token_ty], []>;
1825+
def int_coro_alloca_free_frame : Intrinsic<[], [llvm_token_ty], []>;
18231826

18241827
// Coroutine Manipulation Intrinsics.
18251828

llvm/include/llvm/Transforms/Coroutines/CoroInstr.h

Lines changed: 73 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,9 @@ class LLVM_LIBRARY_VISIBILITY CoroIdRetconOnceDynamicInst
327327
StorageArg,
328328
PrototypeArg,
329329
AllocArg,
330-
DeallocArg
330+
DeallocArg,
331+
AllocFrameArg,
332+
DeallocFrameArg,
331333
};
332334

333335
public:
@@ -371,6 +373,16 @@ class LLVM_LIBRARY_VISIBILITY CoroIdRetconOnceDynamicInst
371373
return cast<Function>(getArgOperand(DeallocArg)->stripPointerCasts());
372374
}
373375

376+
/// Return the function to use for allocating memory.
377+
Function *getAllocFrameFunction() const {
378+
return cast<Function>(getArgOperand(AllocFrameArg)->stripPointerCasts());
379+
}
380+
381+
/// Return the function to use for deallocating memory.
382+
Function *getDeallocFrameFunction() const {
383+
return cast<Function>(getArgOperand(DeallocFrameArg)->stripPointerCasts());
384+
}
385+
374386
Value *getAllocator() const { return getArgOperand(AllocatorArg); }
375387

376388
// Methods to support type inquiry through isa, cast, and dyn_cast:
@@ -822,8 +834,7 @@ class CoroAsyncEndInst : public AnyCoroEndInst {
822834
}
823835
};
824836

825-
/// This represents the llvm.coro.alloca.alloc instruction.
826-
class CoroAllocaAllocInst : public IntrinsicInst {
837+
class AnyCoroAllocaAllocInst : public IntrinsicInst {
827838
enum { SizeArg, AlignArg };
828839

829840
public:
@@ -832,6 +843,21 @@ class CoroAllocaAllocInst : public IntrinsicInst {
832843
return cast<ConstantInt>(getArgOperand(AlignArg))->getAlignValue();
833844
}
834845

846+
// Methods to support type inquiry through isa, cast, and dyn_cast:
847+
static bool classof(const IntrinsicInst *I) {
848+
auto ID = I->getIntrinsicID();
849+
return ID == Intrinsic::coro_alloca_alloc ||
850+
ID == Intrinsic::coro_alloca_alloc_frame;
851+
}
852+
853+
static bool classof(const Value *V) {
854+
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
855+
}
856+
};
857+
858+
/// This represents the llvm.coro.alloca.alloc instruction.
859+
class CoroAllocaAllocInst : public AnyCoroAllocaAllocInst {
860+
public:
835861
// Methods to support type inquiry through isa, cast, and dyn_cast:
836862
static bool classof(const IntrinsicInst *I) {
837863
return I->getIntrinsicID() == Intrinsic::coro_alloca_alloc;
@@ -841,13 +867,25 @@ class CoroAllocaAllocInst : public IntrinsicInst {
841867
}
842868
};
843869

870+
/// This represents the llvm.coro.alloca.alloc.frame instruction.
871+
class CoroAllocaAllocFrameInst : public AnyCoroAllocaAllocInst {
872+
public:
873+
// Methods to support type inquiry through isa, cast, and dyn_cast:
874+
static bool classof(const IntrinsicInst *I) {
875+
return I->getIntrinsicID() == Intrinsic::coro_alloca_alloc_frame;
876+
}
877+
static bool classof(const Value *V) {
878+
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
879+
}
880+
};
881+
844882
/// This represents the llvm.coro.alloca.get instruction.
845883
class CoroAllocaGetInst : public IntrinsicInst {
846884
enum { AllocArg };
847885

848886
public:
849-
CoroAllocaAllocInst *getAlloc() const {
850-
return cast<CoroAllocaAllocInst>(getArgOperand(AllocArg));
887+
AnyCoroAllocaAllocInst *getAlloc() const {
888+
return cast<AnyCoroAllocaAllocInst>(getArgOperand(AllocArg));
851889
}
852890

853891
// Methods to support type inquiry through isa, cast, and dyn_cast:
@@ -859,15 +897,29 @@ class CoroAllocaGetInst : public IntrinsicInst {
859897
}
860898
};
861899

862-
/// This represents the llvm.coro.alloca.free instruction.
863-
class CoroAllocaFreeInst : public IntrinsicInst {
900+
class AnyCoroAllocaFreeInst : public IntrinsicInst {
864901
enum { AllocArg };
865902

866903
public:
867-
CoroAllocaAllocInst *getAlloc() const {
868-
return cast<CoroAllocaAllocInst>(getArgOperand(AllocArg));
904+
AnyCoroAllocaAllocInst *getAlloc() const {
905+
return cast<AnyCoroAllocaAllocInst>(getArgOperand(AllocArg));
869906
}
870907

908+
// Methods to support type inquiry through isa, cast, and dyn_cast:
909+
static bool classof(const IntrinsicInst *I) {
910+
auto ID = I->getIntrinsicID();
911+
return ID == Intrinsic::coro_alloca_free ||
912+
ID == Intrinsic::coro_alloca_free_frame;
913+
}
914+
915+
static bool classof(const Value *V) {
916+
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
917+
}
918+
};
919+
920+
/// This represents the llvm.coro.alloca.free instruction.
921+
class CoroAllocaFreeInst : public IntrinsicInst {
922+
public:
871923
// Methods to support type inquiry through isa, cast, and dyn_cast:
872924
static bool classof(const IntrinsicInst *I) {
873925
return I->getIntrinsicID() == Intrinsic::coro_alloca_free;
@@ -877,6 +929,18 @@ class CoroAllocaFreeInst : public IntrinsicInst {
877929
}
878930
};
879931

932+
/// This represents the llvm.coro.alloca.free instruction.
933+
class CoroAllocaFreeFrameInst : public IntrinsicInst {
934+
public:
935+
// Methods to support type inquiry through isa, cast, and dyn_cast:
936+
static bool classof(const IntrinsicInst *I) {
937+
return I->getIntrinsicID() == Intrinsic::coro_alloca_free_frame;
938+
}
939+
static bool classof(const Value *V) {
940+
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
941+
}
942+
};
943+
880944
} // End namespace llvm.
881945

882946
#endif // LLVM_TRANSFORMS_COROUTINES_COROINSTR_H

llvm/include/llvm/Transforms/Coroutines/CoroShape.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,9 @@ struct Shape {
135135
struct RetconLoweringStorage {
136136
Function *ResumePrototype;
137137
Function *Alloc;
138+
Function *AllocFrame;
138139
Function *Dealloc;
140+
Function *DeallocFrame;
139141
Value *Allocator;
140142
BasicBlock *ReturnBlock;
141143
bool IsFrameInlineInStorage;
@@ -278,13 +280,13 @@ struct Shape {
278280
///
279281
/// \param CG - if non-null, will be updated for the new call
280282
LLVM_ABI Value *emitAlloc(IRBuilder<> &Builder, Value *Size,
281-
CallGraph *CG) const;
283+
AnyCoroAllocaAllocInst *AI, CallGraph *CG) const;
282284

283285
/// Deallocate memory according to the rules of the active lowering.
284286
///
285287
/// \param CG - if non-null, will be updated for the new call
286288
LLVM_ABI void emitDealloc(IRBuilder<> &Builder, Value *Ptr,
287-
CallGraph *CG) const;
289+
AnyCoroAllocaAllocInst *AI, CallGraph *CG) const;
288290

289291
Shape() = delete;
290292
explicit Shape(Function &F) {

llvm/include/llvm/Transforms/Coroutines/SpillUtils.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ void collectSpillsFromArgs(SpillInfo &Spills, Function &F,
3535
void collectSpillsAndAllocasFromInsts(
3636
SpillInfo &Spills, SmallVector<AllocaInfo, 8> &Allocas,
3737
SmallVector<Instruction *, 4> &DeadInstructions,
38-
SmallVector<CoroAllocaAllocInst *, 4> &LocalAllocas, Function &F,
38+
SmallVector<AnyCoroAllocaAllocInst *, 4> &LocalAllocas, Function &F,
3939
const SuspendCrossingInfo &Checker, const DominatorTree &DT,
4040
const coro::Shape &Shape);
4141
void collectSpillsFromDbgInfo(SpillInfo &Spills, Function &F,

llvm/lib/Transforms/Coroutines/CoroFrame.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1598,12 +1598,12 @@ static bool willLeaveFunctionImmediatelyAfter(BasicBlock *BB,
15981598
return true;
15991599
}
16001600

1601-
static bool localAllocaNeedsStackSave(CoroAllocaAllocInst *AI) {
1601+
static bool localAllocaNeedsStackSave(AnyCoroAllocaAllocInst *AI) {
16021602
// Look for a free that isn't sufficiently obviously followed by
16031603
// either a suspend or a termination, i.e. something that will leave
16041604
// the coro resumption frame.
16051605
for (auto *U : AI->users()) {
1606-
auto FI = dyn_cast<CoroAllocaFreeInst>(U);
1606+
auto FI = dyn_cast<AnyCoroAllocaFreeInst>(U);
16071607
if (!FI) continue;
16081608

16091609
if (!willLeaveFunctionImmediatelyAfter(FI->getParent()))
@@ -1616,8 +1616,8 @@ static bool localAllocaNeedsStackSave(CoroAllocaAllocInst *AI) {
16161616

16171617
/// Turn each of the given local allocas into a normal (dynamic) alloca
16181618
/// instruction.
1619-
static void lowerLocalAllocas(ArrayRef<CoroAllocaAllocInst*> LocalAllocas,
1620-
SmallVectorImpl<Instruction*> &DeadInsts) {
1619+
static void lowerLocalAllocas(ArrayRef<AnyCoroAllocaAllocInst *> LocalAllocas,
1620+
SmallVectorImpl<Instruction *> &DeadInsts) {
16211621
for (auto *AI : LocalAllocas) {
16221622
IRBuilder<> Builder(AI);
16231623

@@ -1640,7 +1640,7 @@ static void lowerLocalAllocas(ArrayRef<CoroAllocaAllocInst*> LocalAllocas,
16401640
// alloca.alloc is required to obey a stack discipline, although we
16411641
// don't enforce that structurally.
16421642
} else {
1643-
auto FI = cast<CoroAllocaFreeInst>(U);
1643+
auto FI = cast<AnyCoroAllocaFreeInst>(U);
16441644
if (StackSave) {
16451645
Builder.SetInsertPoint(FI);
16461646
Builder.CreateStackRestore(StackSave);
@@ -2146,7 +2146,7 @@ void coro::BaseABI::buildCoroutineFrame(bool OptimizeFrame) {
21462146
// Collect the spills for arguments and other not-materializable values.
21472147
coro::collectSpillsFromArgs(Spills, F, Checker);
21482148
SmallVector<Instruction *, 4> DeadInstructions;
2149-
SmallVector<CoroAllocaAllocInst *, 4> LocalAllocas;
2149+
SmallVector<AnyCoroAllocaAllocInst *, 4> LocalAllocas;
21502150
coro::collectSpillsAndAllocasFromInsts(Spills, Allocas, DeadInstructions,
21512151
LocalAllocas, F, Checker, DT, Shape);
21522152
coro::collectSpillsFromDbgInfo(Spills, F, Checker);

llvm/lib/Transforms/Coroutines/CoroSplit.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ static void maybeFreeRetconStorage(IRBuilder<> &Builder,
163163
if (Shape.RetconLowering.IsFrameInlineInStorage)
164164
return;
165165

166-
Shape.emitDealloc(Builder, FramePtr, CG);
166+
Shape.emitDealloc(Builder, FramePtr, nullptr, CG);
167167
}
168168

169169
/// Replace an llvm.coro.end.async.
@@ -1903,7 +1903,8 @@ void coro::AnyRetconABI::splitCoroutine(Function &F, coro::Shape &Shape,
19031903
// Allocate. We don't need to update the call graph node because we're
19041904
// going to recompute it from scratch after splitting.
19051905
// FIXME: pass the required alignment
1906-
RawFramePtr = Shape.emitAlloc(Builder, Builder.getInt64(Size), nullptr);
1906+
RawFramePtr =
1907+
Shape.emitAlloc(Builder, Builder.getInt64(Size), nullptr, nullptr);
19071908
RawFramePtr =
19081909
Builder.CreateBitCast(RawFramePtr, Shape.CoroBegin->getType());
19091910

llvm/lib/Transforms/Coroutines/Coroutines.cpp

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,9 @@ void coro::Shape::analyze(Function &F,
325325
auto Prototype = ContinuationId->getPrototype();
326326
RetconLowering.ResumePrototype = Prototype;
327327
RetconLowering.Alloc = ContinuationId->getAllocFunction();
328+
RetconLowering.AllocFrame = ContinuationId->getAllocFrameFunction();
328329
RetconLowering.Dealloc = ContinuationId->getDeallocFunction();
330+
RetconLowering.DeallocFrame = ContinuationId->getDeallocFrameFunction();
329331
RetconLowering.Storage = ContinuationId->getStorage();
330332
RetconLowering.Allocator = ContinuationId->getAllocator();
331333
RetconLowering.ReturnBlock = nullptr;
@@ -523,7 +525,7 @@ static void addCallToCallGraph(CallGraph *CG, CallInst *Call, Function *Callee){
523525
}
524526

525527
Value *coro::Shape::emitAlloc(IRBuilder<> &Builder, Value *Size,
526-
CallGraph *CG) const {
528+
AnyCoroAllocaAllocInst *AI, CallGraph *CG) const {
527529
switch (ABI) {
528530
case coro::ABI::Switch:
529531
llvm_unreachable("can't allocate memory in coro switch-lowering");
@@ -532,12 +534,21 @@ Value *coro::Shape::emitAlloc(IRBuilder<> &Builder, Value *Size,
532534
case coro::ABI::RetconOnce:
533535
case coro::ABI::RetconOnceDynamic: {
534536
unsigned sizeParamIndex = 0;
537+
Function *Alloc = nullptr;
538+
if (isa_and_nonnull<CoroAllocaAllocFrameInst>(AI)) {
539+
assert(ABI == coro::ABI::RetconOnceDynamic);
540+
Alloc = RetconLowering.AllocFrame;
541+
} else {
542+
Alloc = RetconLowering.Alloc;
543+
}
535544
SmallVector<Value *, 2> Args;
536545
if (ABI == coro::ABI::RetconOnceDynamic) {
537-
sizeParamIndex = 1;
546+
Args.push_back(RetconLowering.Storage);
538547
Args.push_back(RetconLowering.Allocator);
548+
sizeParamIndex = 2;
549+
} else {
550+
Alloc = RetconLowering.Alloc;
539551
}
540-
auto Alloc = RetconLowering.Alloc;
541552
Size = Builder.CreateIntCast(
542553
Size, Alloc->getFunctionType()->getParamType(sizeParamIndex),
543554
/*is signed*/ false);
@@ -548,6 +559,9 @@ Value *coro::Shape::emitAlloc(IRBuilder<> &Builder, Value *Size,
548559
Args.push_back(TypeId);
549560
}
550561
auto *Call = Builder.CreateCall(Alloc, Args);
562+
if (ABI == coro::ABI::RetconOnceDynamic) {
563+
Call->addParamAttr(1, Attribute::SwiftCoro);
564+
}
551565
propagateCallAttrsFromCallee(Call, Alloc);
552566
addCallToCallGraph(CG, Call, Alloc);
553567
return Call;
@@ -559,25 +573,37 @@ Value *coro::Shape::emitAlloc(IRBuilder<> &Builder, Value *Size,
559573
}
560574

561575
void coro::Shape::emitDealloc(IRBuilder<> &Builder, Value *Ptr,
562-
CallGraph *CG) const {
576+
AnyCoroAllocaAllocInst *AI, CallGraph *CG) const {
563577
switch (ABI) {
564578
case coro::ABI::Switch:
565579
llvm_unreachable("can't allocate memory in coro switch-lowering");
566580

567581
case coro::ABI::Retcon:
568582
case coro::ABI::RetconOnce:
569583
case coro::ABI::RetconOnceDynamic: {
570-
auto Dealloc = RetconLowering.Dealloc;
584+
Function *Dealloc = nullptr;
585+
if (isa_and_nonnull<CoroAllocaAllocFrameInst>(AI)) {
586+
assert(ABI == coro::ABI::RetconOnceDynamic);
587+
Dealloc = RetconLowering.DeallocFrame;
588+
} else {
589+
Dealloc = RetconLowering.Dealloc;
590+
}
591+
unsigned allocationParamIndex = 0;
571592
SmallVector<Value *, 2> Args;
572-
unsigned sizeParamIndex = 0;
573593
if (ABI == coro::ABI::RetconOnceDynamic) {
574-
sizeParamIndex = 1;
594+
allocationParamIndex = 2;
595+
Args.push_back(RetconLowering.Storage);
575596
Args.push_back(RetconLowering.Allocator);
597+
} else {
598+
Dealloc = RetconLowering.Dealloc;
576599
}
577600
Ptr = Builder.CreateBitCast(
578-
Ptr, Dealloc->getFunctionType()->getParamType(sizeParamIndex));
601+
Ptr, Dealloc->getFunctionType()->getParamType(allocationParamIndex));
579602
Args.push_back(Ptr);
580603
auto *Call = Builder.CreateCall(Dealloc, Args);
604+
if (ABI == coro::ABI::RetconOnceDynamic) {
605+
Call->addParamAttr(1, Attribute::SwiftCoro);
606+
}
581607
propagateCallAttrsFromCallee(Call, Dealloc);
582608
addCallToCallGraph(CG, Call, Dealloc);
583609
return;

0 commit comments

Comments
 (0)