74#include <initializer_list>
79#define DEBUG_TYPE "coro-split"
92 F, CloneFunctionChangeType::LocalChangesOnly, DIFinder);
95 DIFinder, SPClonedWithinModule);
118 if (
auto Invoke = dyn_cast<InvokeInst>(CB)) {
121 Invoke->getUnwindDest(), {Awaiter, FramePtr});
124 std::copy(Invoke->bundle_op_info_begin(), Invoke->bundle_op_info_end(),
125 WrapperInvoke->bundle_op_info_begin());
126 WrapperInvoke->setAttributes(NewAttributes);
127 WrapperInvoke->setDebugLoc(Invoke->getDebugLoc());
128 NewCall = WrapperInvoke;
129 }
else if (
auto Call = dyn_cast<CallInst>(CB)) {
133 WrapperCall->setDebugLoc(Call->getDebugLoc());
134 NewCall = WrapperCall;
140 Intrinsic::coro_await_suspend_handle) {
143 if (
auto *Invoke = dyn_cast<InvokeInst>(CB)) {
145 Builder.
SetInsertPoint(Invoke->getNormalDest()->getFirstInsertionPt());
155 auto *ResumeCall = Builder.
CreateCall(ResumeTy, ResumeAddr, {NewCall});
162 NewCall = ResumeCall;
178 assert(Shape.
ABI == coro::ABI::Retcon || Shape.
ABI == coro::ABI::RetconOnce);
191 auto *EndAsync = dyn_cast<CoroAsyncEndInst>(
End);
197 auto *MustTailCallFunc = EndAsync->getMustTailCallFunction();
198 if (!MustTailCallFunc) {
204 auto *CoroEndBlock =
End->getParent();
205 auto *MustTailCallFuncBlock = CoroEndBlock->getSinglePredecessor();
206 assert(MustTailCallFuncBlock &&
"Must have a single predecessor block");
207 auto It = MustTailCallFuncBlock->getTerminator()->getIterator();
208 auto *MustTailCall = cast<CallInst>(&*std::prev(It));
209 CoroEndBlock->splice(
End->getIterator(), MustTailCallFuncBlock,
210 MustTailCall->getIterator());
218 auto *BB =
End->getParent();
219 BB->splitBasicBlock(
End);
220 BB->getTerminator()->eraseFromParent();
223 assert(InlineRes.isSuccess() &&
"Expected inlining to succeed");
240 case coro::ABI::Switch:
241 assert(!cast<CoroEndInst>(
End)->hasResults() &&
242 "switch coroutine should not return any values");
251 case coro::ABI::Async: {
253 if (!CoroEndBlockNeedsCleanup)
260 case coro::ABI::RetconOnce: {
262 auto *CoroEnd = cast<CoroEndInst>(
End);
265 if (!CoroEnd->hasResults()) {
271 auto *CoroResults = CoroEnd->getResults();
272 unsigned NumReturns = CoroResults->numReturns();
274 if (
auto *RetStructTy = dyn_cast<StructType>(
RetTy)) {
275 assert(RetStructTy->getNumElements() == NumReturns &&
276 "numbers of returns should match resume function singature");
279 for (
Value *RetValEl : CoroResults->return_values())
282 }
else if (NumReturns == 0) {
287 Builder.
CreateRet(*CoroResults->retval_begin());
291 CoroResults->eraseFromParent();
297 case coro::ABI::Retcon: {
298 assert(!cast<CoroEndInst>(
End)->hasResults() &&
299 "retcon coroutine should not return any values");
302 auto RetStructTy = dyn_cast<StructType>(
RetTy);
304 cast<PointerType>(RetStructTy ? RetStructTy->getElementType(0) :
RetTy);
317 auto *BB =
End->getParent();
318 BB->splitBasicBlock(
End);
319 BB->getTerminator()->eraseFromParent();
333 Shape.
ABI == coro::ABI::Switch &&
334 "markCoroutineAsDone is only supported for Switch-Resumed ABI for now.");
353 "The final suspend should only live in the last position of "
371 case coro::ABI::Switch: {
384 case coro::ABI::Async:
387 case coro::ABI::Retcon:
388 case coro::ABI::RetconOnce:
395 auto *FromPad = cast<CleanupPadInst>(Bundle->Inputs[0]);
397 End->getParent()->splitBasicBlock(
End);
398 CleanupRet->getParent()->getTerminator()->eraseFromParent();
409 auto &Context =
End->getContext();
412 End->eraseFromParent();
432 auto FinalCaseIt = std::prev(
Switch->case_end());
433 BasicBlock *ResumeBB = FinalCaseIt->getCaseSuccessor();
434 Switch->removeCase(FinalCaseIt);
459 auto *AsyncSuspend = cast<CoroSuspendAsyncInst>(Suspend);
460 auto *StructTy = cast<StructType>(AsyncSuspend->getType());
461 auto &Context = Suspend->
getParent()->getParent()->getContext();
479 M->getFunctionList().insert(InsertBefore, NewF);
492 auto NewS = VMap[ActiveSuspend];
493 if (NewS->use_empty())
501 for (
auto I = IsAsyncABI ? NewF->arg_begin() : std::next(NewF->arg_begin()),
508 if (!isa<StructType>(NewS->getType())) {
510 NewS->replaceAllUsesWith(Args.front());
516 auto *EVI = dyn_cast<ExtractValueInst>(U.getUser());
517 if (!EVI || EVI->getNumIndices() != 1)
520 EVI->replaceAllUsesWith(Args[EVI->getIndices().front()]);
521 EVI->eraseFromParent();
525 if (NewS->use_empty())
531 Aggr = Builder.CreateInsertValue(Aggr, Arg,
Idx);
537 Value *SuspendResult;
547 SuspendResult = Builder.getInt8(isSwitchDestroyFunction() ? 1 : 0);
564 if (CS == ActiveSuspend)
567 auto *MappedCS = cast<AnyCoroSuspendInst>(VMap[CS]);
568 MappedCS->replaceAllUsesWith(SuspendResult);
569 MappedCS->eraseFromParent();
577 auto *NewCE = cast<AnyCoroEndInst>(VMap[CE]);
586 Value *CachedSlot =
nullptr;
587 auto getSwiftErrorSlot = [&](
Type *ValueTy) ->
Value * {
592 for (
auto &Arg :
F.args()) {
593 if (Arg.isSwiftError()) {
601 F.getEntryBlock().getFirstNonPHIOrDbg());
610 auto MappedOp = VMap ? cast<CallInst>((*VMap)[
Op]) :
Op;
615 if (
Op->arg_empty()) {
616 auto ValueTy =
Op->getType();
617 auto Slot = getSwiftErrorSlot(ValueTy);
618 MappedResult = Builder.
CreateLoad(ValueTy, Slot);
621 auto Value = MappedOp->getArgOperand(0);
623 auto Slot = getSwiftErrorSlot(ValueTy);
628 MappedOp->replaceAllUsesWith(MappedResult);
629 MappedOp->eraseFromParent();
633 if (VMap ==
nullptr) {
639static std::pair<SmallVector<DbgVariableIntrinsic *, 8>,
647 if (
auto *DVI = dyn_cast<DbgVariableIntrinsic>(&
I))
650 return {Intrinsics, DbgVariableRecords};
672 auto IsUnreachableBlock = [&](
BasicBlock *BB) {
676 auto RemoveOne = [&](
auto *DVI) {
677 if (IsUnreachableBlock(DVI->getParent()))
678 DVI->eraseFromParent();
679 else if (isa_and_nonnull<AllocaInst>(DVI->getVariableLocationOp(0))) {
682 for (
auto *
User : DVI->getVariableLocationOp(0)->
users())
683 if (
auto *
I = dyn_cast<Instruction>(
User))
684 if (!isa<AllocaInst>(
I) && !IsUnreachableBlock(
I->getParent()))
687 DVI->eraseFromParent();
691 for_each(DbgVariableRecords, RemoveOne);
701 auto *OldEntry = &NewF->getEntryBlock();
702 Entry->setName(
"entry" + Suffix);
703 Entry->moveBefore(OldEntry);
704 Entry->getTerminator()->eraseFromParent();
709 assert(Entry->hasOneUse());
710 auto BranchToEntry = cast<BranchInst>(Entry->user_back());
711 assert(BranchToEntry->isUnconditional());
712 Builder.SetInsertPoint(BranchToEntry);
713 Builder.CreateUnreachable();
714 BranchToEntry->eraseFromParent();
717 Builder.SetInsertPoint(Entry);
724 Builder.CreateBr(SwitchBB);
734 isa<CoroSuspendAsyncInst>(ActiveSuspend)) ||
737 isa<CoroSuspendRetconInst>(ActiveSuspend)));
738 auto *MappedCS = cast<AnyCoroSuspendInst>(VMap[ActiveSuspend]);
739 auto Branch = cast<BranchInst>(MappedCS->getNextNode());
740 assert(Branch->isUnconditional());
741 Builder.CreateBr(Branch->getSuccessor(0));
751 auto *Alloca = dyn_cast<AllocaInst>(&
I);
752 if (!Alloca ||
I.use_empty())
755 !isa<ConstantInt>(Alloca->getArraySize()))
757 I.moveBefore(*Entry, Entry->getFirstInsertionPt());
768 return &*NewF->arg_begin();
775 auto *ActiveAsyncSuspend = cast<CoroSuspendAsyncInst>(ActiveSuspend);
776 auto ContextIdx = ActiveAsyncSuspend->getStorageArgumentIndex() & 0xff;
777 auto *CalleeContext = NewF->getArg(ContextIdx);
778 auto *ProjectionFunc =
779 ActiveAsyncSuspend->getAsyncContextProjectionFunction();
781 cast<CoroSuspendAsyncInst>(VMap[ActiveSuspend])->getDebugLoc();
783 auto *CallerContext = Builder.CreateCall(ProjectionFunc->getFunctionType(),
784 ProjectionFunc, CalleeContext);
785 CallerContext->setCallingConv(ProjectionFunc->getCallingConv());
786 CallerContext->setDebugLoc(DbgLoc);
788 auto &Context = Builder.getContext();
789 auto *FramePtrAddr = Builder.CreateConstInBoundsGEP1_32(
795 assert(InlineRes.isSuccess());
802 Argument *NewStorage = &*NewF->arg_begin();
810 return Builder.CreateLoad(FramePtrTy, NewStorage);
830 if (SPToUpdate.
getFile() ==
DL->getFile())
831 SPToUpdate.setScopeLine(
DL->getLine());
839 if (
auto *Branch = dyn_cast_or_null<BranchInst>(
Successor);
840 Branch && Branch->isUnconditional())
841 Successor = Branch->getSuccessor(0)->getFirstNonPHIOrDbg();
849 if (!
DL ||
DL.getLine() == 0)
852 if (SPToUpdate.
getFile() ==
DL->getFile()) {
853 SPToUpdate.setScopeLine(
DL.getLine());
862 if (SPToUpdate.
getFile() ==
DL->getFile())
863 SPToUpdate.setScopeLine(
DL->getLine());
868 Align Alignment,
bool NoAlias) {
878 Attrs = Attrs.addParamAttributes(Context, ParamIndex, ParamAttrs);
882 unsigned ParamIndex) {
885 Attrs = Attrs.addParamAttributes(Context, ParamIndex, ParamAttrs);
889 unsigned ParamIndex) {
892 Attrs = Attrs.addParamAttributes(Context, ParamIndex, ParamAttrs);
908 VMap[&
A] = DummyArgs.
back();
915 auto savedVisibility = NewF->getVisibility();
916 auto savedUnnamedAddr = NewF->getUnnamedAddr();
917 auto savedDLLStorageClass = NewF->getDLLStorageClass();
922 auto savedLinkage = NewF->getLinkage();
929 nullptr,
nullptr, &CommonDebugInfo);
931 auto &Context = NewF->getContext();
934 assert(SP != OrigF.getSubprogram() && SP->isDistinct());
946 SP->getUnit()->getSourceLanguage() == dwarf::DW_LANG_Swift) {
947 SP->replaceLinkageName(
MDString::get(Context, NewF->getName()));
948 if (
auto *Decl = SP->getDeclaration()) {
950 Decl->getContext(), Decl->getScope(), Decl->getName(),
951 NewF->getName(), Decl->getFile(), Decl->getLine(), Decl->getType(),
952 Decl->getScopeLine(), Decl->getContainingType(),
953 Decl->getVirtualIndex(), Decl->getThisAdjustment(),
954 Decl->getFlags(), Decl->getSPFlags(), Decl->getUnit(),
955 Decl->getTemplateParams(),
nullptr, Decl->getRetainedNodes(),
956 Decl->getThrownTypes(), Decl->getAnnotations(),
957 Decl->getTargetFuncName());
958 SP->replaceDeclaration(NewDecl);
963 NewF->setLinkage(savedLinkage);
964 NewF->setVisibility(savedVisibility);
965 NewF->setUnnamedAddr(savedUnnamedAddr);
966 NewF->setDLLStorageClass(savedDLLStorageClass);
971 NewF->hasMetadata(LLVMContext::MD_func_sanitize))
972 NewF->eraseMetadata(LLVMContext::MD_func_sanitize);
975 auto OrigAttrs = NewF->getAttributes();
982 NewAttrs = NewAttrs.addFnAttributes(
983 Context,
AttrBuilder(Context, OrigAttrs.getFnAttrs()));
989 auto *ActiveAsyncSuspend = cast<CoroSuspendAsyncInst>(ActiveSuspend);
991 Attribute::SwiftAsync)) {
993 ActiveAsyncSuspend->getStorageArgumentIndex();
994 auto ContextArgIndex = ArgAttributeIndices & 0xff;
999 auto SwiftSelfIndex = ArgAttributeIndices >> 8;
1005 auto FnAttrs = OrigF.getAttributes().getFnAttrs();
1006 NewAttrs = NewAttrs.addFnAttributes(Context,
AttrBuilder(Context, FnAttrs));
1049 NewF->setAttributes(NewAttrs);
1053 replaceEntryBlock();
1057 ResumeCall = cast<CallInst>(VMap[ResumeCall]);
1069 Builder.CreateRetVoid();
1073 Builder.SetInsertPoint(&NewF->getEntryBlock().front());
1074 NewFramePtr = deriveNewFramePointer();
1078 NewFramePtr->
takeName(OldFramePtr);
1082 auto *NewVFrame = Builder.CreateBitCast(
1085 if (OldVFrame != NewVFrame)
1092 DummyArg->deleteValue();
1101 handleFinalSuspend();
1108 assert(ActiveSuspend !=
nullptr &&
1109 "no active suspend when lowering a continuation-style coroutine");
1110 replaceRetconOrAsyncSuspendUses();
1115 replaceCoroSuspends();
1144 auto *FuncPtrStruct = cast<ConstantStruct>(
1146 auto *OrigRelativeFunOffset = FuncPtrStruct->getOperand(0);
1147 auto *OrigContextSize = FuncPtrStruct->getOperand(1);
1148 auto *NewContextSize = ConstantInt::get(OrigContextSize->getType(),
1151 FuncPtrStruct->getType(), OrigRelativeFunOffset, NewContextSize);
1158 auto *SizeIntrin = Shape.
CoroSizes.back();
1159 Module *M = SizeIntrin->getModule();
1161 return DL.getTypeAllocSize(Shape.
FrameTy);
1178 auto *SizeIntrin = Shape.
CoroSizes.back();
1179 auto *SizeConstant =
1204 switch (Shape.
ABI) {
1213 AllocInst->replaceAllUsesWith(Builder.
getFalse());
1214 AllocInst->eraseFromParent();
1215 CoroBegin->replaceAllUsesWith(Frame);
1217 CoroBegin->replaceAllUsesWith(CoroBegin->getMem());
1229 CoroBegin->eraseFromParent();
1239 if (isa<IntrinsicInst>(
I))
1242 if (isa<CallBase>(
I))
1258 while (!Worklist.
empty()) {
1262 if (!Set.contains(Pred))
1268 Set.erase(ResDesBB);
1270 for (
auto *BB : Set)
1279 auto *ResumeOrDestroyBB = ResumeOrDestroy->
getParent();
1283 if (SaveBB == ResumeOrDestroyBB)
1292 {ResumeOrDestroyBB->getFirstNonPHIIt(), ResumeOrDestroyIt}))
1308 auto *Pred = Suspend->
getParent()->getSinglePredecessor();
1311 Prev = Pred->getTerminator();
1314 CallBase *CB = dyn_cast<CallBase>(Prev);
1321 auto *SubFn = dyn_cast<CoroSubFnInst>(Callee);
1326 if (SubFn->getFrame() != CoroBegin)
1340 Save->eraseFromParent();
1343 if (
auto *Invoke = dyn_cast<InvokeInst>(CB)) {
1352 if (CalledValue != SubFn && CalledValue->user_empty())
1353 if (
auto *
I = dyn_cast<Instruction>(CalledValue))
1354 I->eraseFromParent();
1357 if (SubFn->user_empty())
1358 SubFn->eraseFromParent();
1370 size_t I = 0,
N = S.size();
1374 size_t ChangedFinalIndex = std::numeric_limits<size_t>::max();
1376 auto SI = cast<CoroSuspendInst>(S[
I]);
1385 if (cast<CoroSuspendInst>(S[
I])->isFinal()) {
1387 ChangedFinalIndex =
I;
1399 if (ChangedFinalIndex <
N) {
1400 assert(cast<CoroSuspendInst>(S[ChangedFinalIndex])->isFinal());
1401 std::swap(S[ChangedFinalIndex], S.back());
1407struct SwitchCoroutineSplitter {
1418 createResumeEntryBlock(
F, Shape);
1420 F,
".resume", Shape, coro::CloneKind::SwitchResume,
TTI,
1423 F,
".destroy", Shape, coro::CloneKind::SwitchUnwind,
TTI,
1426 F,
".cleanup", Shape, coro::CloneKind::SwitchCleanup,
TTI,
1434 updateCoroFrame(Shape, ResumeClone, DestroyClone, CleanupClone);
1444 setCoroInfo(
F, Shape, Clones);
1457 auto *OrigFnTy =
F.getFunctionType();
1458 auto OldParams = OrigFnTy->params();
1461 NewParams.
reserve(OldParams.size() + 1);
1462 NewParams.
append(OldParams.begin(), OldParams.end());
1465 auto *NewFnTy = FunctionType::get(OrigFnTy->getReturnType(), NewParams,
1466 OrigFnTy->isVarArg());
1471 unsigned int Idx = 0;
1472 for (
const auto &
I :
F.args()) {
1477 auto FrameIdx = NoAllocF->
arg_size() - 1;
1480 CloneFunctionChangeType::LocalChangesOnly, Returns);
1483 auto *NewCoroBegin =
1484 cast_if_present<CoroBeginInst>(VMap[Shape.
CoroBegin]);
1485 auto *NewCoroId = cast<CoroIdInst>(NewCoroBegin->getId());
1488 NewCoroBegin->replaceAllUsesWith(NoAllocF->
getArg(FrameIdx));
1489 NewCoroBegin->eraseFromParent();
1493 M->getFunctionList().insert(
M->end(), NoAllocF);
1508 setCoroInfo(
F, Shape, Clones);
1536 auto *FrameTy = Shape.
FrameTy;
1537 auto *GepIndex = Builder.CreateStructGEP(
1544 size_t SuspendIndex = 0;
1546 auto *S = cast<CoroSuspendInst>(AnyS);
1552 auto *Save = S->getCoroSave();
1553 Builder.SetInsertPoint(Save);
1559 auto *GepIndex = Builder.CreateStructGEP(
1561 Builder.CreateStore(IndexVal, GepIndex);
1565 Save->eraseFromParent();
1590 auto *SuspendBB = S->getParent();
1592 SuspendBB->splitBasicBlock(S,
"resume." +
Twine(SuspendIndex));
1593 auto *LandingBB = ResumeBB->splitBasicBlock(
1594 S->getNextNode(), ResumeBB->getName() +
Twine(
".landing"));
1595 Switch->addCase(IndexVal, ResumeBB);
1597 cast<BranchInst>(SuspendBB->getTerminator())->setSuccessor(0, LandingBB);
1599 PN->insertBefore(LandingBB->begin());
1600 S->replaceAllUsesWith(PN);
1601 PN->addIncoming(Builder.getInt8(-1), SuspendBB);
1602 PN->addIncoming(S, ResumeBB);
1607 Builder.SetInsertPoint(UnreachBB);
1608 Builder.CreateUnreachable();
1618 auto *ResumeAddr = Builder.CreateStructGEP(
1621 Builder.CreateStore(ResumeFn, ResumeAddr);
1623 Value *DestroyOrCleanupFn = DestroyFn;
1629 DestroyOrCleanupFn = Builder.CreateSelect(CA, DestroyFn, CleanupFn);
1632 auto *DestroyAddr = Builder.CreateStructGEP(
1635 Builder.CreateStore(DestroyOrCleanupFn, DestroyAddr);
1659 auto *ArrTy = ArrayType::get(Part->
getType(),
Args.size());
1663 GlobalVariable::PrivateLinkage, ConstVal,
1664 F.getName() +
Twine(
".resumers"));
1678 auto &Context = Suspend->
getParent()->getParent()->getContext();
1684 ResumeIntrinsic->eraseFromParent();
1694 for (
auto *paramTy : FnTy->params()) {
1696 if (paramTy != FnArgs[ArgIdx]->
getType())
1715 auto *TailCall = Builder.
CreateCall(FnTy, MustTailCallFn, CallArgs);
1720 TailCall->setDebugLoc(Loc);
1732 F.removeFnAttr(Attribute::NoReturn);
1733 F.removeRetAttr(Attribute::NoAlias);
1734 F.removeRetAttr(Attribute::NonNull);
1736 auto &Context =
F.getContext();
1746 "async.ctx.frameptr");
1757 auto NextF = std::next(
F.getIterator());
1762 auto *Suspend = cast<CoroSuspendAsyncInst>(CS);
1765 auto ResumeNameSuffix =
".resume.";
1766 auto ProjectionFunctionName =
1767 Suspend->getAsyncContextProjectionFunction()->getName();
1768 bool UseSwiftMangling =
false;
1769 if (ProjectionFunctionName ==
"__swift_async_resume_project_context") {
1770 ResumeNameSuffix =
"TQ";
1771 UseSwiftMangling =
true;
1772 }
else if (ProjectionFunctionName ==
"__swift_async_resume_get_context") {
1773 ResumeNameSuffix =
"TY";
1774 UseSwiftMangling =
true;
1778 UseSwiftMangling ? ResumeNameSuffix +
Twine(
Idx) +
"_"
1785 auto *SuspendBB = Suspend->getParent();
1786 auto *NewSuspendBB = SuspendBB->splitBasicBlock(Suspend);
1787 auto *Branch = cast<BranchInst>(SuspendBB->getTerminator());
1792 Branch->setSuccessor(0, ReturnBB);
1797 auto *Fn = Suspend->getMustTailCallFunction();
1817 auto *Clone = Clones[
Idx];
1820 Suspend,
TTI, CommonDebugInfo);
1832 F.removeFnAttr(Attribute::NoReturn);
1833 F.removeRetAttr(Attribute::NoAlias);
1834 F.removeRetAttr(Attribute::NonNull);
1840 RawFramePtr = Id->getStorage();
1856 Builder.
CreateStore(RawFramePtr, Id->getStorage());
1869 PHINode *ContinuationPhi =
nullptr;
1873 auto NextF = std::next(
F.getIterator());
1878 auto Suspend = cast<CoroSuspendRetconInst>(CS);
1887 auto SuspendBB = Suspend->getParent();
1888 auto NewSuspendBB = SuspendBB->splitBasicBlock(Suspend);
1889 auto Branch = cast<BranchInst>(SuspendBB->getTerminator());
1913 auto RetTy =
F.getReturnType();
1918 auto CastedContinuationTy =
1920 auto *CastedContinuation =
1921 Builder.
CreateBitCast(ContinuationPhi, CastedContinuationTy);
1923 Value *RetV = CastedContinuation;
1924 if (!ReturnPHIs.
empty()) {
1929 for (
auto Phi : ReturnPHIs)
1937 Branch->setSuccessor(0, ReturnBB);
1940 for (
auto [Phi, VUse] :
1942 Phi->addIncoming(VUse, SuspendBB);
1951 auto Clone = Clones[
Idx];
1954 Suspend,
TTI, CommonDebugInfo);
1965 OS <<
"While splitting coroutine ";
1966 F.printAsOperand(
OS,
false,
F.getParent());
1980 auto &Context =
End->getContext();
1982 End->eraseFromParent();
1988 for (
auto *U :
F.users()) {
1989 if (
auto *CB = dyn_cast<CallBase>(U)) {
1990 auto *Caller = CB->getFunction();
1991 if (Caller && Caller->isPresplitCoroutine() &&
1992 CB->hasFnAttr(llvm::Attribute::CoroElideSafe))
2002 SwitchCoroutineSplitter::split(
F,
Shape, Clones,
TTI);
2007 bool OptimizeFrame) {
2008 PrettyStackTraceFunction prettyStackTrace(
F);
2010 auto &Shape =
ABI.Shape;
2018 ABI.buildCoroutineFrame(OptimizeFrame);
2021 bool isNoSuspendCoroutine = Shape.
CoroSuspends.empty();
2023 bool shouldCreateNoAllocVariant =
2029 if (isNoSuspendCoroutine) {
2032 ABI.splitCoroutine(
F, Shape, Clones,
TTI);
2044 for (
auto *DDI : DbgInsts)
2051 if (shouldCreateNoAllocVariant)
2052 SwitchCoroutineSplitter::createNoAllocVariant(
F, Shape, Clones);
2061 auto *CurrentSCC = &
C;
2062 if (!Clones.
empty()) {
2063 switch (Shape.
ABI) {
2075 if (!Clones.empty())
2107 auto *Cast = dyn_cast<BitCastInst>(U.getUser());
2108 if (!Cast || Cast->getType() != Fn->getType())
2112 Cast->replaceAllUsesWith(Fn);
2113 Cast->eraseFromParent();
2122 while (
auto *Cast = dyn_cast<BitCastInst>(CastFn)) {
2123 if (!Cast->use_empty())
2125 CastFn = Cast->getOperand(0);
2126 Cast->eraseFromParent();
2132 bool Changed =
false;
2135 auto *Prepare = cast<CallInst>(
P.getUser());
2146 auto *PrepareFn = M.getFunction(
Name);
2147 if (PrepareFn && !PrepareFn->use_empty())
2151static std::unique_ptr<coro::BaseABI>
2157 if (CustomABI >= GenCustomABIs.
size())
2159 return GenCustomABIs[CustomABI](
F, S);
2164 return std::make_unique<coro::SwitchABI>(
F, S, IsMatCallback);
2166 return std::make_unique<coro::AsyncABI>(
F, S, IsMatCallback);
2168 return std::make_unique<coro::AnyRetconABI>(
F, S, IsMatCallback);
2170 return std::make_unique<coro::AnyRetconABI>(
F, S, IsMatCallback);
2176 : CreateAndInitABI([](
Function &
F, coro::Shape &S) {
2177 std::unique_ptr<coro::BaseABI> ABI =
2182 OptimizeFrame(OptimizeFrame) {}
2186 : CreateAndInitABI([=](
Function &
F, coro::Shape &S) {
2187 std::unique_ptr<coro::BaseABI> ABI =
2192 OptimizeFrame(OptimizeFrame) {}
2198 : CreateAndInitABI([=](
Function &
F, coro::Shape &S) {
2199 std::unique_ptr<coro::BaseABI> ABI =
2204 OptimizeFrame(OptimizeFrame) {}
2211 : CreateAndInitABI([=](
Function &
F, coro::Shape &S) {
2212 std::unique_ptr<coro::BaseABI> ABI =
2217 OptimizeFrame(OptimizeFrame) {}
2225 Module &M = *
C.begin()->getFunction().getParent();
2237 if (
N.getFunction().isPresplitCoroutine())
2240 if (Coroutines.
empty() && PrepareFns.
empty())
2243 auto *CurrentSCC = &
C;
2247 LLVM_DEBUG(
dbgs() <<
"CoroSplit: Processing coroutine '" <<
F.getName()
2259 F.setSplittedCoroutine();
2267 *
N, Shape, Clones, *CurrentSCC, CG, AM, UR,
FAM);
2272 <<
"Split '" <<
ore::NV(
"function",
F.getName())
2285 for (
auto *PrepareFn : PrepareFns) {
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
AMDGPU Lower Kernel Arguments
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
Expand Atomic instructions
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
This file provides interfaces used to manipulate a call graph, regardless if it is a "old style" Call...
This file provides interfaces used to build and manipulate a call graph, which is a very useful tool ...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static void addSwiftSelfAttrs(AttributeList &Attrs, LLVMContext &Context, unsigned ParamIndex)
static bool hasCallsBetween(Instruction *Save, Instruction *ResumeOrDestroy)
static std::pair< SmallVector< DbgVariableIntrinsic *, 8 >, SmallVector< DbgVariableRecord * > > collectDbgVariableIntrinsics(Function &F)
Returns all DbgVariableIntrinsic in F.
static LazyCallGraph::SCC & updateCallGraphAfterCoroutineSplit(LazyCallGraph::Node &N, const coro::Shape &Shape, const SmallVectorImpl< Function * > &Clones, LazyCallGraph::SCC &C, LazyCallGraph &CG, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR, FunctionAnalysisManager &FAM)
static void replaceSwiftErrorOps(Function &F, coro::Shape &Shape, ValueToValueMapTy *VMap)
static void addAsyncContextAttrs(AttributeList &Attrs, LLVMContext &Context, unsigned ParamIndex)
static void maybeFreeRetconStorage(IRBuilder<> &Builder, const coro::Shape &Shape, Value *FramePtr, CallGraph *CG)
static bool hasCallsInBlocksBetween(BasicBlock *SaveBB, BasicBlock *ResDesBB)
static Function * createCloneDeclaration(Function &OrigF, coro::Shape &Shape, const Twine &Suffix, Module::iterator InsertBefore, AnyCoroSuspendInst *ActiveSuspend)
Remove calls to llvm coro end in the original static function void removeCoroEndsFromRampFunction(const coro::Shape &Shape)
static FunctionType * getFunctionTypeFromAsyncSuspend(AnyCoroSuspendInst *Suspend)
static void updateScopeLine(Instruction *ActiveSuspend, DISubprogram &SPToUpdate)
Adjust the scope line of the funclet to the first line number after the suspend point.
static void addPrepareFunction(const Module &M, SmallVectorImpl< Function * > &Fns, StringRef Name)
static void simplifySuspendPoints(coro::Shape &Shape)
static void addFramePointerAttrs(AttributeList &Attrs, LLVMContext &Context, unsigned ParamIndex, uint64_t Size, Align Alignment, bool NoAlias)
static bool hasSafeElideCaller(Function &F)
static bool replaceAllPrepares(Function *PrepareFn, LazyCallGraph &CG, LazyCallGraph::SCC &C)
static void replaceFallthroughCoroEnd(AnyCoroEndInst *End, const coro::Shape &Shape, Value *FramePtr, bool InResume, CallGraph *CG)
Replace a non-unwind call to llvm.coro.end.
static void replaceFrameSizeAndAlignment(coro::Shape &Shape)
static std::unique_ptr< coro::BaseABI > CreateNewABI(Function &F, coro::Shape &S, std::function< bool(Instruction &)> IsMatCallback, const SmallVector< CoroSplitPass::BaseABITy > GenCustomABIs)
static bool replaceCoroEndAsync(AnyCoroEndInst *End)
Replace an llvm.coro.end.async.
static void doSplitCoroutine(Function &F, SmallVectorImpl< Function * > &Clones, coro::BaseABI &ABI, TargetTransformInfo &TTI, bool OptimizeFrame)
static bool hasCallsInBlockBetween(iterator_range< BasicBlock::iterator > R)
Replace a call to llvm coro prepare static retcon void replacePrepare(CallInst *Prepare, LazyCallGraph &CG, LazyCallGraph::SCC &C)
static void replaceUnwindCoroEnd(AnyCoroEndInst *End, const coro::Shape &Shape, Value *FramePtr, bool InResume, CallGraph *CG)
Replace an unwind call to llvm.coro.end.
static bool simplifySuspendPoint(CoroSuspendInst *Suspend, CoroBeginInst *CoroBegin)
static void markCoroutineAsDone(IRBuilder<> &Builder, const coro::Shape &Shape, Value *FramePtr)
static void updateAsyncFuncPointerContextSize(coro::Shape &Shape)
static void replaceCoroEnd(AnyCoroEndInst *End, const coro::Shape &Shape, Value *FramePtr, bool InResume, CallGraph *CG)
static void lowerAwaitSuspend(IRBuilder<> &Builder, CoroAwaitSuspendInst *CB, coro::Shape &Shape)
static void lowerAwaitSuspends(Function &F, coro::Shape &Shape)
static void handleNoSuspendCoroutine(coro::Shape &Shape)
static void postSplitCleanup(Function &F)
static TypeSize getFrameSizeForShape(coro::Shape &Shape)
Coerce the arguments in p FnArgs according to p FnTy in p static CallArgs void coerceArguments(IRBuilder<> &Builder, FunctionType *FnTy, ArrayRef< Value * > FnArgs, SmallVectorImpl< Value * > &CallArgs)
static void replaceAsyncResumeFunction(CoroSuspendAsyncInst *Suspend, Value *Continuation)
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
This file defines the DenseMap class.
This file contains constants used for implementing Dwarf debug support.
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
Module.h This file contains the declarations for the Module class.
Implements a lazy call graph analysis and related passes for the new pass manager.
FunctionAnalysisManager FAM
This file provides a priority worklist.
const SmallVectorImpl< MachineOperand > & Cond
Remove Loads Into Fake Uses
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
static SymbolRef::Type getType(const Symbol *Sym)
static const unsigned FramePtr
void setSwiftError(bool V)
Specify whether this alloca is used to represent a swifterror.
void setAlignment(Align Align)
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
CoroAllocInst * getCoroAlloc()
Align getStorageAlignment() const
uint64_t getStorageSize() const
This class represents an incoming formal argument to a Function.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
ArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
size_t size() const
size - Get the array size.
AttrBuilder & addAlignmentAttr(MaybeAlign Align)
This turns an alignment into the form used internally in Attribute.
AttrBuilder & addAttribute(Attribute::AttrKind Val)
Add an attribute to the builder.
AttrBuilder & addDereferenceableAttr(uint64_t Bytes)
This turns the number of dereferenceable bytes into the form used internally in Attribute.
AttributeList removeParamAttributes(LLVMContext &C, unsigned ArgNo, const AttributeMask &AttrsToRemove) const
Remove the specified attribute at the specified arg index from this attribute list.
LLVM Basic Block Representation.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="", bool Before=false)
Split the basic block into two basic blocks at the specified instruction.
const Function * getParent() const
Return the enclosing method, or null if none.
InstListType::iterator iterator
Instruction iterators...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
static BranchInst * Create(BasicBlock *IfTrue, InsertPosition InsertBefore=nullptr)
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
void setCallingConv(CallingConv::ID CC)
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
Value * getCalledOperand() const
void setAttributes(AttributeList A)
Set the attributes for this call.
Value * getArgOperand(unsigned i) const
AttributeList getAttributes() const
Return the attributes for this call.
The basic data container for the call graph of a Module of IR.
This class represents a function call, abstracting a target machine's calling convention.
static Constant * get(ArrayType *T, ArrayRef< Constant * > V)
static Constant * getPointerCast(Constant *C, Type *Ty)
Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant expression.
This is the shared class of boolean and integer constants.
static ConstantInt * getTrue(LLVMContext &Context)
static ConstantInt * getFalse(LLVMContext &Context)
static ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
static Constant * get(StructType *T, ArrayRef< Constant * > V)
static ConstantTokenNone * get(LLVMContext &Context)
Return the ConstantTokenNone.
This represents the llvm.coro.align instruction.
This represents the llvm.coro.alloc instruction.
This represents the llvm.coro.await.suspend.{void,bool,handle} instructions.
Value * getAwaiter() const
Function * getWrapperFunction() const
This class represents the llvm.coro.begin or llvm.coro.begin.custom.abi instructions.
AnyCoroIdInst * getId() const
bool hasCustomABI() const
This represents the llvm.coro.id instruction.
void setInfo(Constant *C)
This represents the llvm.coro.size instruction.
This represents the llvm.coro.suspend.async instruction.
CoroAsyncResumeInst * getResumeFunction() const
This represents the llvm.coro.suspend instruction.
CoroSaveInst * getCoroSave() const
DISubprogram * getSubprogram() const
Get the subprogram for this scope.
This class represents an Operation in the Expression.
A parsed version of the target data layout string in and methods for querying it.
This is the common base class for debug info intrinsics for variables.
Record of a variable value-assignment, aka a non instruction representation of the dbg....
Utility to find all debug info in a module.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
bool isReachableFromEntry(const Use &U) const
Provide an overload for a Use.
This class represents a freeze function that returns random concrete value if an operand is either a ...
A proxy from a FunctionAnalysisManager to an SCC.
Class to represent function types.
Type * getReturnType() const
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
AttributeList getAttributes() const
Return the attribute list for this Function.
void setAttributes(AttributeList Attrs)
Set the attribute list for this Function.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
bool isCoroOnlyDestroyWhenComplete() const
Argument * getArg(unsigned i) const
void setLinkage(LinkageTypes LT)
Module * getParent()
Get the module that this global value is contained inside of...
PointerType * getType() const
Global values are always pointers.
@ InternalLinkage
Rename collisions when linking (static functions).
@ ExternalLinkage
Externally visible function.
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
void setInitializer(Constant *InitVal)
setInitializer - Sets the initializer for this global variable, removing any existing initializer if ...
AllocaInst * CreateAlloca(Type *Ty, unsigned AddrSpace, Value *ArraySize=nullptr, const Twine &Name="")
Value * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &Name="")
InvokeInst * CreateInvoke(FunctionType *Ty, Value *Callee, BasicBlock *NormalDest, BasicBlock *UnwindDest, ArrayRef< Value * > Args, ArrayRef< OperandBundleDef > OpBundles, const Twine &Name="")
Create an invoke instruction.
BasicBlock::iterator GetInsertPoint() const
Value * CreateStructGEP(Type *Ty, Value *Ptr, unsigned Idx, const Twine &Name="")
Value * CreateConstInBoundsGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name="")
CleanupReturnInst * CreateCleanupRet(CleanupPadInst *CleanupPad, BasicBlock *UnwindBB=nullptr)
ReturnInst * CreateRet(Value *V)
Create a 'ret <val>' instruction.
ConstantInt * getInt64(uint64_t C)
Get a constant 64-bit value.
Value * CreateBitOrPointerCast(Value *V, Type *DestTy, const Twine &Name="")
PHINode * CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name="")
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
BranchInst * CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False, MDNode *BranchWeights=nullptr, MDNode *Unpredictable=nullptr)
Create a conditional 'br Cond, TrueDest, FalseDest' instruction.
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
LLVMContext & getContext() const
ReturnInst * CreateRetVoid()
Create a 'ret void' instruction.
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
ConstantInt * getFalse()
Get the constant value for i1 false.
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
BranchInst * CreateBr(BasicBlock *Dest)
Create an unconditional 'br label X' instruction.
Value * CreateIsNull(Value *Arg, const Twine &Name="")
Return a boolean value testing if Arg == 0.
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
This class captures the data input to the InlineFunction call, and records the auxiliary results prod...
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
const Instruction * getNextNonDebugInstruction(bool SkipPseudoOp=false) const
Return a pointer to the next non-debug instruction in the same basic block as 'this',...
This is an important class for using LLVM in a threaded context.
A node in the call graph.
An SCC of the call graph.
A lazily constructed view of the call graph of a module.
void addSplitFunction(Function &OriginalFunction, Function &NewFunction)
Add a new function split/outlined from an existing function.
void addSplitRefRecursiveFunctions(Function &OriginalFunction, ArrayRef< Function * > NewFunctions)
Add new ref-recursive functions split/outlined from an existing function.
Node & get(Function &F)
Get a graph node for a given function, scanning it to populate the graph data as necessary.
SCC * lookupSCC(Node &N) const
Lookup a function's SCC in the graph.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
static MDString * get(LLVMContext &Context, StringRef Str)
A Module instance is used to store all the information related to an LLVM module.
FunctionListType::iterator iterator
The Function iterators.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PrettyStackTraceEntry - This class is used to represent a frame of the "pretty" stack trace that is d...
Return a value (possibly void), from a function.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Type * getTypeAtIndex(const Value *V) const
Given an index value into the type, return the type of the element.
Analysis pass providing the TargetTransformInfo.
The TimeTraceScope is a helper class to call the begin and end functions of the time trace profiler.
Value handle that tracks a Value across RAUW.
ValueTy * getValPtr() const
Triple - Helper class for working with autoconf configuration names.
bool isArch64Bit() const
Test whether the architecture is 64-bit.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
static Type * getVoidTy(LLVMContext &C)
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
static IntegerType * getInt8Ty(LLVMContext &C)
A Use represents the edge between a Value definition and its users.
void setOperand(unsigned i, Value *Val)
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
LLVMContext & getContext() const
All values hold a context through their type.
iterator_range< use_iterator > uses()
StringRef getName() const
Return a constant reference to the value's name.
void takeName(Value *V)
Transfer the name from V to this value.
void splitCoroutine(Function &F, coro::Shape &Shape, SmallVectorImpl< Function * > &Clones, TargetTransformInfo &TTI) override
void splitCoroutine(Function &F, coro::Shape &Shape, SmallVectorImpl< Function * > &Clones, TargetTransformInfo &TTI) override
static Function * createClone(Function &OrigF, const Twine &Suffix, coro::Shape &Shape, Function *NewF, AnyCoroSuspendInst *ActiveSuspend, TargetTransformInfo &TTI, const MetadataSetTy &CommonDebugInfo)
Create a clone for a continuation lowering.
void replaceSwiftErrorOps()
Value * deriveNewFramePointer()
Derive the value of the new frame pointer.
void replaceCoroSuspends()
void handleFinalSuspend()
bool isSwitchDestroyFunction()
void replaceRetconOrAsyncSuspendUses()
Replace uses of the active llvm.coro.suspend.retcon/async call with the arguments to the continuation...
virtual void create()
Clone the body of the original function into a resume function of some sort.
void splitCoroutine(Function &F, coro::Shape &Shape, SmallVectorImpl< Function * > &Clones, TargetTransformInfo &TTI) override
void create() override
Clone the body of the original function into a resume function of some sort.
static Function * createClone(Function &OrigF, const Twine &Suffix, coro::Shape &Shape, CloneKind FKind, TargetTransformInfo &TTI, const MetadataSetTy &CommonDebugInfo)
Create a clone for a switch lowering.
const ParentTy * getParent() const
self_iterator getIterator()
A range adaptor for a pair of iterators.
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ C
The default llvm calling convention, compatible with C.
void salvageDebugInfo(SmallDenseMap< Argument *, AllocaInst *, 4 > &ArgToAllocaMap, DbgVariableIntrinsic &DVI, bool IsEntryPoint)
Attempts to rewrite the location operand of debug intrinsics in terms of the coroutine frame pointer,...
@ Async
The "async continuation" lowering, where each suspend point creates a single continuation function.
@ RetconOnce
The "unique returned-continuation" lowering, where each suspend point creates a single continuation f...
@ Retcon
The "returned-continuation" lowering, where each suspend point creates a single continuation function...
@ Switch
The "resume-switch" lowering, where there are separate resume and destroy functions that are shared b...
void suppressCoroAllocs(CoroIdInst *CoroId)
Replaces all @llvm.coro.alloc intrinsics calls associated with a given call @llvm....
void normalizeCoroutine(Function &F, coro::Shape &Shape, TargetTransformInfo &TTI)
CallInst * createMustTailCall(DebugLoc Loc, Function *MustTailCallFn, TargetTransformInfo &TTI, ArrayRef< Value * > Arguments, IRBuilder<> &)
void replaceCoroFree(CoroIdInst *CoroId, bool Elide)
bool isTriviallyMaterializable(Instruction &I)
@ SwitchCleanup
The shared cleanup function for a switch lowering.
@ Continuation
An individual continuation function.
DiagnosticInfoOptimizationBase::Argument NV
This is an optimization pass for GlobalISel generic memory operations.
void CloneFunctionAttributesInto(Function *NewFunc, const Function *OldFunc, ValueToValueMapTy &VMap, bool ModuleLevelChanges, ValueMapTypeRemapper *TypeMapper=nullptr, ValueMaterializer *Materializer=nullptr)
Clone OldFunc's attributes into NewFunc, transforming values based on the mappings in VMap.
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
detail::zippy< detail::zip_first, T, U, Args... > zip_equal(T &&t, U &&u, Args &&...args)
zip iterator that assumes that all iteratees have the same length.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
bool verifyFunction(const Function &F, raw_ostream *OS=nullptr)
Check a function for errors, useful for use when debugging a pass.
LazyCallGraph::SCC & updateCGAndAnalysisManagerForFunctionPass(LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR, FunctionAnalysisManager &FAM)
Helper to update the call graph after running a function pass.
LazyCallGraph::SCC & updateCGAndAnalysisManagerForCGSCCPass(LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR, FunctionAnalysisManager &FAM)
Helper to update the call graph after running a CGSCC pass.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
BasicBlock::iterator skipDebugIntrinsics(BasicBlock::iterator It)
Advance It while it points to a debug instruction and return the result.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
MetadataSetTy FindDebugInfoToIdentityMap(CloneFunctionChangeType Changes, DebugInfoFinder &DIFinder, DISubprogram *SPClonedWithinModule)
Based on Changes and DIFinder return debug info that needs to be identity mapped during Metadata clon...
unsigned changeToUnreachable(Instruction *I, bool PreserveLCSSA=false, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Insert an unreachable instruction before the specified instruction, making it and the rest of the cod...
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
void CloneFunctionMetadataInto(Function &NewFunc, const Function &OldFunc, ValueToValueMapTy &VMap, RemapFlags RemapFlag, ValueMapTypeRemapper *TypeMapper=nullptr, ValueMaterializer *Materializer=nullptr, const MetadataSetTy *IdentityMD=nullptr)
Clone OldFunc's metadata into NewFunc.
DWARFExpression::Operation Op
InlineResult InlineFunction(CallBase &CB, InlineFunctionInfo &IFI, bool MergeAttributes=false, AAResults *CalleeAAR=nullptr, bool InsertLifetime=true, Function *ForwardVarArgsTo=nullptr)
This function inlines the called function into the basic block of the caller.
void CloneFunctionInto(Function *NewFunc, const Function *OldFunc, ValueToValueMapTy &VMap, CloneFunctionChangeType Changes, SmallVectorImpl< ReturnInst * > &Returns, const char *NameSuffix="", ClonedCodeInfo *CodeInfo=nullptr, ValueMapTypeRemapper *TypeMapper=nullptr, ValueMaterializer *Materializer=nullptr)
Clone OldFunc into NewFunc, transforming the old arguments into references to VMap values.
auto predecessors(const MachineBasicBlock *BB)
DISubprogram * CollectDebugInfoForCloning(const Function &F, CloneFunctionChangeType Changes, DebugInfoFinder &DIFinder)
Collect debug information such as types, compile units, and other subprograms that are reachable from...
static auto filterDbgVars(iterator_range< simple_ilist< DbgRecord >::iterator > R)
Filter the DbgRecord range to DbgVariableRecord types only and downcast.
bool removeUnreachableBlocks(Function &F, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Remove all blocks that can not be reached from the function's entry.
void CloneFunctionBodyInto(Function &NewFunc, const Function &OldFunc, ValueToValueMapTy &VMap, RemapFlags RemapFlag, SmallVectorImpl< ReturnInst * > &Returns, const char *NameSuffix="", ClonedCodeInfo *CodeInfo=nullptr, ValueMapTypeRemapper *TypeMapper=nullptr, ValueMaterializer *Materializer=nullptr, const MetadataSetTy *IdentityMD=nullptr)
Clone OldFunc's body into NewFunc.
bool isPotentiallyReachable(const Instruction *From, const Instruction *To, const SmallPtrSetImpl< BasicBlock * > *ExclusionSet=nullptr, const DominatorTree *DT=nullptr, const LoopInfo *LI=nullptr)
Determine whether instruction 'To' is reachable from 'From', without passing through any blocks in Ex...
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
uint64_t value() const
This is a hole in the type system and should not be abused.
Support structure for SCC passes to communicate updates the call graph back to the CGSCC pass manager...
SmallPriorityWorklist< LazyCallGraph::SCC *, 1 > & CWorklist
Worklist of the SCCs queued for processing.
PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR)
CoroSplitPass(bool OptimizeFrame=false)
BaseABITy CreateAndInitABI
CallInst * makeSubFnCall(Value *Arg, int Index, Instruction *InsertPt)
GlobalVariable * AsyncFuncPointer
bool IsFrameInlineInStorage
Function * ResumePrototype
SwitchInst * ResumeSwitch
BasicBlock * ResumeEntryBlock
SmallVector< CallInst *, 2 > SymmetricTransfers
SmallVector< CoroAwaitSuspendInst *, 4 > CoroAwaitSuspends
AsyncLoweringStorage AsyncLowering
FunctionType * getResumeFunctionType() const
IntegerType * getIndexType() const
AnyCoroIdRetconInst * getRetconCoroId() const
PointerType * getSwitchResumePointerType() const
CoroIdInst * getSwitchCoroId() const
SmallVector< CoroSizeInst *, 2 > CoroSizes
CallingConv::ID getResumeFunctionCC() const
SmallVector< AnyCoroSuspendInst *, 4 > CoroSuspends
Value * emitAlloc(IRBuilder<> &Builder, Value *Size, CallGraph *CG) const
Allocate memory according to the rules of the active lowering.
ConstantInt * getIndex(uint64_t Value) const
SwitchLoweringStorage SwitchLowering
CoroBeginInst * CoroBegin
BasicBlock::iterator getInsertPtAfterFramePtr() const
ArrayRef< Type * > getRetconResultTypes() const
void emitDealloc(IRBuilder<> &Builder, Value *Ptr, CallGraph *CG) const
Deallocate memory according to the rules of the active lowering.
RetconLoweringStorage RetconLowering
SmallVector< CoroAlignInst *, 2 > CoroAligns
CoroIdAsyncInst * getAsyncCoroId() const
SmallVector< AnyCoroEndInst *, 4 > CoroEnds
SmallVector< CallInst *, 2 > SwiftErrorOps
BasicBlock * AllocaSpillBlock
unsigned getSwitchIndexField() const