73#include <initializer_list>
78#define DEBUG_TYPE "coro-split"
99 if (
auto Invoke = dyn_cast<InvokeInst>(CB)) {
102 Invoke->getUnwindDest(), {Awaiter, FramePtr});
105 std::copy(Invoke->bundle_op_info_begin(), Invoke->bundle_op_info_end(),
106 WrapperInvoke->bundle_op_info_begin());
107 WrapperInvoke->setAttributes(NewAttributes);
108 WrapperInvoke->setDebugLoc(Invoke->getDebugLoc());
109 NewCall = WrapperInvoke;
110 }
else if (
auto Call = dyn_cast<CallInst>(CB)) {
114 WrapperCall->setDebugLoc(Call->getDebugLoc());
115 NewCall = WrapperCall;
121 Intrinsic::coro_await_suspend_handle) {
124 if (
auto *Invoke = dyn_cast<InvokeInst>(CB)) {
126 Builder.
SetInsertPoint(Invoke->getNormalDest()->getFirstInsertionPt());
136 auto *ResumeCall = Builder.
CreateCall(ResumeTy, ResumeAddr, {NewCall});
143 NewCall = ResumeCall;
159 assert(Shape.
ABI == coro::ABI::Retcon || Shape.
ABI == coro::ABI::RetconOnce);
172 auto *EndAsync = dyn_cast<CoroAsyncEndInst>(
End);
178 auto *MustTailCallFunc = EndAsync->getMustTailCallFunction();
179 if (!MustTailCallFunc) {
185 auto *CoroEndBlock =
End->getParent();
186 auto *MustTailCallFuncBlock = CoroEndBlock->getSinglePredecessor();
187 assert(MustTailCallFuncBlock &&
"Must have a single predecessor block");
188 auto It = MustTailCallFuncBlock->getTerminator()->getIterator();
189 auto *MustTailCall = cast<CallInst>(&*std::prev(It));
190 CoroEndBlock->splice(
End->getIterator(), MustTailCallFuncBlock,
191 MustTailCall->getIterator());
199 auto *BB =
End->getParent();
200 BB->splitBasicBlock(
End);
201 BB->getTerminator()->eraseFromParent();
204 assert(InlineRes.isSuccess() &&
"Expected inlining to succeed");
221 case coro::ABI::Switch:
222 assert(!cast<CoroEndInst>(
End)->hasResults() &&
223 "switch coroutine should not return any values");
232 case coro::ABI::Async: {
234 if (!CoroEndBlockNeedsCleanup)
241 case coro::ABI::RetconOnce: {
243 auto *CoroEnd = cast<CoroEndInst>(
End);
246 if (!CoroEnd->hasResults()) {
252 auto *CoroResults = CoroEnd->getResults();
253 unsigned NumReturns = CoroResults->numReturns();
255 if (
auto *RetStructTy = dyn_cast<StructType>(
RetTy)) {
256 assert(RetStructTy->getNumElements() == NumReturns &&
257 "numbers of returns should match resume function singature");
260 for (
Value *RetValEl : CoroResults->return_values())
263 }
else if (NumReturns == 0) {
268 Builder.
CreateRet(*CoroResults->retval_begin());
272 CoroResults->eraseFromParent();
278 case coro::ABI::Retcon: {
279 assert(!cast<CoroEndInst>(
End)->hasResults() &&
280 "retcon coroutine should not return any values");
283 auto RetStructTy = dyn_cast<StructType>(
RetTy);
285 cast<PointerType>(RetStructTy ? RetStructTy->getElementType(0) :
RetTy);
298 auto *BB =
End->getParent();
299 BB->splitBasicBlock(
End);
300 BB->getTerminator()->eraseFromParent();
314 Shape.
ABI == coro::ABI::Switch &&
315 "markCoroutineAsDone is only supported for Switch-Resumed ABI for now.");
334 "The final suspend should only live in the last position of "
352 case coro::ABI::Switch: {
365 case coro::ABI::Async:
368 case coro::ABI::Retcon:
369 case coro::ABI::RetconOnce:
376 auto *FromPad = cast<CleanupPadInst>(Bundle->Inputs[0]);
378 End->getParent()->splitBasicBlock(
End);
379 CleanupRet->getParent()->getTerminator()->eraseFromParent();
390 auto &Context =
End->getContext();
393 End->eraseFromParent();
413 auto FinalCaseIt = std::prev(
Switch->case_end());
414 BasicBlock *ResumeBB = FinalCaseIt->getCaseSuccessor();
415 Switch->removeCase(FinalCaseIt);
440 auto *AsyncSuspend = cast<CoroSuspendAsyncInst>(Suspend);
441 auto *StructTy = cast<StructType>(AsyncSuspend->getType());
442 auto &Context = Suspend->
getParent()->getParent()->getContext();
460 M->getFunctionList().insert(InsertBefore, NewF);
473 auto NewS = VMap[ActiveSuspend];
474 if (NewS->use_empty())
482 for (
auto I = IsAsyncABI ? NewF->arg_begin() : std::next(NewF->arg_begin()),
489 if (!isa<StructType>(NewS->getType())) {
491 NewS->replaceAllUsesWith(Args.front());
497 auto *EVI = dyn_cast<ExtractValueInst>(U.getUser());
498 if (!EVI || EVI->getNumIndices() != 1)
501 EVI->replaceAllUsesWith(Args[EVI->getIndices().front()]);
502 EVI->eraseFromParent();
506 if (NewS->use_empty())
512 Aggr = Builder.CreateInsertValue(Aggr, Arg,
Idx);
518 Value *SuspendResult;
528 SuspendResult = Builder.getInt8(isSwitchDestroyFunction() ? 1 : 0);
545 if (CS == ActiveSuspend)
548 auto *MappedCS = cast<AnyCoroSuspendInst>(VMap[CS]);
549 MappedCS->replaceAllUsesWith(SuspendResult);
550 MappedCS->eraseFromParent();
558 auto *NewCE = cast<AnyCoroEndInst>(VMap[CE]);
567 Value *CachedSlot =
nullptr;
568 auto getSwiftErrorSlot = [&](
Type *ValueTy) ->
Value * {
573 for (
auto &Arg :
F.args()) {
574 if (Arg.isSwiftError()) {
581 IRBuilder<> Builder(
F.getEntryBlock().getFirstNonPHIOrDbg());
590 auto MappedOp = VMap ? cast<CallInst>((*VMap)[
Op]) :
Op;
595 if (
Op->arg_empty()) {
596 auto ValueTy =
Op->getType();
597 auto Slot = getSwiftErrorSlot(ValueTy);
598 MappedResult = Builder.
CreateLoad(ValueTy, Slot);
601 auto Value = MappedOp->getArgOperand(0);
603 auto Slot = getSwiftErrorSlot(ValueTy);
608 MappedOp->replaceAllUsesWith(MappedResult);
609 MappedOp->eraseFromParent();
613 if (VMap ==
nullptr) {
619static std::pair<SmallVector<DbgVariableIntrinsic *, 8>,
627 if (
auto *DVI = dyn_cast<DbgVariableIntrinsic>(&
I))
630 return {Intrinsics, DbgVariableRecords};
652 auto IsUnreachableBlock = [&](
BasicBlock *BB) {
656 auto RemoveOne = [&](
auto *DVI) {
657 if (IsUnreachableBlock(DVI->getParent()))
658 DVI->eraseFromParent();
659 else if (isa_and_nonnull<AllocaInst>(DVI->getVariableLocationOp(0))) {
662 for (
auto *
User : DVI->getVariableLocationOp(0)->
users())
663 if (
auto *
I = dyn_cast<Instruction>(
User))
664 if (!isa<AllocaInst>(
I) && !IsUnreachableBlock(
I->getParent()))
667 DVI->eraseFromParent();
671 for_each(DbgVariableRecords, RemoveOne);
681 auto *OldEntry = &NewF->getEntryBlock();
682 Entry->setName(
"entry" + Suffix);
683 Entry->moveBefore(OldEntry);
684 Entry->getTerminator()->eraseFromParent();
689 assert(Entry->hasOneUse());
690 auto BranchToEntry = cast<BranchInst>(Entry->user_back());
691 assert(BranchToEntry->isUnconditional());
692 Builder.SetInsertPoint(BranchToEntry);
693 Builder.CreateUnreachable();
694 BranchToEntry->eraseFromParent();
697 Builder.SetInsertPoint(Entry);
704 Builder.CreateBr(SwitchBB);
714 isa<CoroSuspendAsyncInst>(ActiveSuspend)) ||
717 isa<CoroSuspendRetconInst>(ActiveSuspend)));
718 auto *MappedCS = cast<AnyCoroSuspendInst>(VMap[ActiveSuspend]);
719 auto Branch = cast<BranchInst>(MappedCS->getNextNode());
720 assert(Branch->isUnconditional());
721 Builder.CreateBr(Branch->getSuccessor(0));
731 auto *Alloca = dyn_cast<AllocaInst>(&
I);
732 if (!Alloca ||
I.use_empty())
735 !isa<ConstantInt>(Alloca->getArraySize()))
737 I.moveBefore(*Entry, Entry->getFirstInsertionPt());
748 return &*NewF->arg_begin();
755 auto *ActiveAsyncSuspend = cast<CoroSuspendAsyncInst>(ActiveSuspend);
756 auto ContextIdx = ActiveAsyncSuspend->getStorageArgumentIndex() & 0xff;
757 auto *CalleeContext = NewF->getArg(ContextIdx);
758 auto *ProjectionFunc =
759 ActiveAsyncSuspend->getAsyncContextProjectionFunction();
761 cast<CoroSuspendAsyncInst>(VMap[ActiveSuspend])->getDebugLoc();
763 auto *CallerContext = Builder.CreateCall(ProjectionFunc->getFunctionType(),
764 ProjectionFunc, CalleeContext);
765 CallerContext->setCallingConv(ProjectionFunc->getCallingConv());
766 CallerContext->setDebugLoc(DbgLoc);
768 auto &Context = Builder.getContext();
769 auto *FramePtrAddr = Builder.CreateConstInBoundsGEP1_32(
775 assert(InlineRes.isSuccess());
782 Argument *NewStorage = &*NewF->arg_begin();
790 return Builder.CreateLoad(FramePtrTy, NewStorage);
810 if (
auto *Branch = dyn_cast_or_null<BranchInst>(
Successor);
811 Branch && Branch->isUnconditional())
812 Successor = Branch->getSuccessor(0)->getFirstNonPHIOrDbg();
818 if (!
DL ||
DL.getLine() == 0)
821 if (SPToUpdate.
getFile() ==
DL->getFile()) {
822 SPToUpdate.setScopeLine(
DL.getLine());
831 if (SPToUpdate.
getFile() ==
DL->getFile())
832 SPToUpdate.setScopeLine(
DL->getLine());
837 Align Alignment,
bool NoAlias) {
847 Attrs = Attrs.addParamAttributes(Context, ParamIndex, ParamAttrs);
851 unsigned ParamIndex) {
854 Attrs = Attrs.addParamAttributes(Context, ParamIndex, ParamAttrs);
858 unsigned ParamIndex) {
861 Attrs = Attrs.addParamAttributes(Context, ParamIndex, ParamAttrs);
877 VMap[&
A] = DummyArgs.
back();
884 auto savedVisibility = NewF->getVisibility();
885 auto savedUnnamedAddr = NewF->getUnnamedAddr();
886 auto savedDLLStorageClass = NewF->getDLLStorageClass();
891 auto savedLinkage = NewF->getLinkage();
897 auto &Context = NewF->getContext();
900 assert(SP != OrigF.getSubprogram() && SP->isDistinct());
912 SP->getUnit()->getSourceLanguage() == dwarf::DW_LANG_Swift) {
913 SP->replaceLinkageName(
MDString::get(Context, NewF->getName()));
914 if (
auto *Decl = SP->getDeclaration()) {
916 Decl->getContext(), Decl->getScope(), Decl->getName(),
917 NewF->getName(), Decl->getFile(), Decl->getLine(), Decl->getType(),
918 Decl->getScopeLine(), Decl->getContainingType(),
919 Decl->getVirtualIndex(), Decl->getThisAdjustment(),
920 Decl->getFlags(), Decl->getSPFlags(), Decl->getUnit(),
921 Decl->getTemplateParams(),
nullptr, Decl->getRetainedNodes(),
922 Decl->getThrownTypes(), Decl->getAnnotations(),
923 Decl->getTargetFuncName());
924 SP->replaceDeclaration(NewDecl);
929 NewF->setLinkage(savedLinkage);
930 NewF->setVisibility(savedVisibility);
931 NewF->setUnnamedAddr(savedUnnamedAddr);
932 NewF->setDLLStorageClass(savedDLLStorageClass);
937 NewF->hasMetadata(LLVMContext::MD_func_sanitize))
938 NewF->eraseMetadata(LLVMContext::MD_func_sanitize);
941 auto OrigAttrs = NewF->getAttributes();
948 NewAttrs = NewAttrs.addFnAttributes(
949 Context,
AttrBuilder(Context, OrigAttrs.getFnAttrs()));
955 auto *ActiveAsyncSuspend = cast<CoroSuspendAsyncInst>(ActiveSuspend);
957 Attribute::SwiftAsync)) {
959 ActiveAsyncSuspend->getStorageArgumentIndex();
960 auto ContextArgIndex = ArgAttributeIndices & 0xff;
965 auto SwiftSelfIndex = ArgAttributeIndices >> 8;
971 auto FnAttrs = OrigF.getAttributes().getFnAttrs();
972 NewAttrs = NewAttrs.addFnAttributes(Context,
AttrBuilder(Context, FnAttrs));
1015 NewF->setAttributes(NewAttrs);
1019 replaceEntryBlock();
1023 ResumeCall = cast<CallInst>(VMap[ResumeCall]);
1035 Builder.CreateRetVoid();
1039 Builder.SetInsertPoint(&NewF->getEntryBlock().front());
1040 NewFramePtr = deriveNewFramePointer();
1044 NewFramePtr->
takeName(OldFramePtr);
1048 auto *NewVFrame = Builder.CreateBitCast(
1051 if (OldVFrame != NewVFrame)
1058 DummyArg->deleteValue();
1067 handleFinalSuspend();
1074 assert(ActiveSuspend !=
nullptr &&
1075 "no active suspend when lowering a continuation-style coroutine");
1076 replaceRetconOrAsyncSuspendUses();
1081 replaceCoroSuspends();
1110 auto *FuncPtrStruct = cast<ConstantStruct>(
1112 auto *OrigRelativeFunOffset = FuncPtrStruct->getOperand(0);
1113 auto *OrigContextSize = FuncPtrStruct->getOperand(1);
1114 auto *NewContextSize = ConstantInt::get(OrigContextSize->getType(),
1117 FuncPtrStruct->getType(), OrigRelativeFunOffset, NewContextSize);
1124 auto *SizeIntrin = Shape.
CoroSizes.back();
1125 Module *M = SizeIntrin->getModule();
1127 return DL.getTypeAllocSize(Shape.
FrameTy);
1144 auto *SizeIntrin = Shape.
CoroSizes.back();
1145 auto *SizeConstant =
1170 switch (Shape.
ABI) {
1179 AllocInst->replaceAllUsesWith(Builder.
getFalse());
1180 AllocInst->eraseFromParent();
1181 CoroBegin->replaceAllUsesWith(Frame);
1183 CoroBegin->replaceAllUsesWith(CoroBegin->getMem());
1195 CoroBegin->eraseFromParent();
1205 if (isa<IntrinsicInst>(
I))
1208 if (isa<CallBase>(
I))
1224 while (!Worklist.
empty()) {
1228 if (!Set.contains(Pred))
1234 Set.erase(ResDesBB);
1236 for (
auto *BB : Set)
1245 auto *ResumeOrDestroyBB = ResumeOrDestroy->
getParent();
1247 if (SaveBB == ResumeOrDestroyBB)
1272 auto *Pred = Suspend->
getParent()->getSinglePredecessor();
1275 Prev = Pred->getTerminator();
1278 CallBase *CB = dyn_cast<CallBase>(Prev);
1285 auto *SubFn = dyn_cast<CoroSubFnInst>(Callee);
1290 if (SubFn->getFrame() != CoroBegin)
1304 Save->eraseFromParent();
1307 if (
auto *Invoke = dyn_cast<InvokeInst>(CB)) {
1316 if (CalledValue != SubFn && CalledValue->user_empty())
1317 if (
auto *
I = dyn_cast<Instruction>(CalledValue))
1318 I->eraseFromParent();
1321 if (SubFn->user_empty())
1322 SubFn->eraseFromParent();
1334 size_t I = 0,
N = S.size();
1338 size_t ChangedFinalIndex = std::numeric_limits<size_t>::max();
1340 auto SI = cast<CoroSuspendInst>(S[
I]);
1349 if (cast<CoroSuspendInst>(S[
I])->isFinal()) {
1351 ChangedFinalIndex =
I;
1363 if (ChangedFinalIndex <
N) {
1364 assert(cast<CoroSuspendInst>(S[ChangedFinalIndex])->isFinal());
1365 std::swap(S[ChangedFinalIndex], S.back());
1371struct SwitchCoroutineSplitter {
1380 createResumeEntryBlock(
F, Shape);
1382 F,
".resume", Shape, coro::CloneKind::SwitchResume,
TTI);
1384 F,
".destroy", Shape, coro::CloneKind::SwitchUnwind,
TTI);
1386 F,
".cleanup", Shape, coro::CloneKind::SwitchCleanup,
TTI);
1393 updateCoroFrame(Shape, ResumeClone, DestroyClone, CleanupClone);
1403 setCoroInfo(
F, Shape, Clones);
1416 auto *OrigFnTy =
F.getFunctionType();
1417 auto OldParams = OrigFnTy->params();
1420 NewParams.
reserve(OldParams.size() + 1);
1421 NewParams.
append(OldParams.begin(), OldParams.end());
1424 auto *NewFnTy = FunctionType::get(OrigFnTy->getReturnType(), NewParams,
1425 OrigFnTy->isVarArg());
1430 unsigned int Idx = 0;
1431 for (
const auto &
I :
F.args()) {
1436 auto FrameIdx = NoAllocF->
arg_size() - 1;
1439 CloneFunctionChangeType::LocalChangesOnly, Returns);
1442 auto *NewCoroBegin =
1443 cast_if_present<CoroBeginInst>(VMap[Shape.
CoroBegin]);
1444 auto *NewCoroId = cast<CoroIdInst>(NewCoroBegin->getId());
1447 NewCoroBegin->replaceAllUsesWith(NoAllocF->
getArg(FrameIdx));
1448 NewCoroBegin->eraseFromParent();
1452 M->getFunctionList().insert(
M->end(), NoAllocF);
1467 setCoroInfo(
F, Shape, Clones);
1495 auto *FrameTy = Shape.
FrameTy;
1496 auto *GepIndex = Builder.CreateStructGEP(
1503 size_t SuspendIndex = 0;
1505 auto *S = cast<CoroSuspendInst>(AnyS);
1511 auto *Save = S->getCoroSave();
1512 Builder.SetInsertPoint(Save);
1518 auto *GepIndex = Builder.CreateStructGEP(
1520 Builder.CreateStore(IndexVal, GepIndex);
1524 Save->eraseFromParent();
1549 auto *SuspendBB = S->getParent();
1551 SuspendBB->splitBasicBlock(S,
"resume." +
Twine(SuspendIndex));
1552 auto *LandingBB = ResumeBB->splitBasicBlock(
1553 S->getNextNode(), ResumeBB->getName() +
Twine(
".landing"));
1554 Switch->addCase(IndexVal, ResumeBB);
1556 cast<BranchInst>(SuspendBB->getTerminator())->setSuccessor(0, LandingBB);
1558 PN->insertBefore(LandingBB->begin());
1559 S->replaceAllUsesWith(PN);
1560 PN->addIncoming(Builder.getInt8(-1), SuspendBB);
1561 PN->addIncoming(S, ResumeBB);
1566 Builder.SetInsertPoint(UnreachBB);
1567 Builder.CreateUnreachable();
1577 auto *ResumeAddr = Builder.CreateStructGEP(
1580 Builder.CreateStore(ResumeFn, ResumeAddr);
1582 Value *DestroyOrCleanupFn = DestroyFn;
1588 DestroyOrCleanupFn = Builder.CreateSelect(CA, DestroyFn, CleanupFn);
1591 auto *DestroyAddr = Builder.CreateStructGEP(
1594 Builder.CreateStore(DestroyOrCleanupFn, DestroyAddr);
1618 auto *ArrTy = ArrayType::get(Part->
getType(),
Args.size());
1622 GlobalVariable::PrivateLinkage, ConstVal,
1623 F.getName() +
Twine(
".resumers"));
1637 auto &Context = Suspend->
getParent()->getParent()->getContext();
1643 ResumeIntrinsic->eraseFromParent();
1653 for (
auto *paramTy : FnTy->params()) {
1655 if (paramTy != FnArgs[ArgIdx]->
getType())
1674 auto *TailCall = Builder.
CreateCall(FnTy, MustTailCallFn, CallArgs);
1679 TailCall->setDebugLoc(Loc);
1691 F.removeFnAttr(Attribute::NoReturn);
1692 F.removeRetAttr(Attribute::NoAlias);
1693 F.removeRetAttr(Attribute::NonNull);
1695 auto &Context =
F.getContext();
1705 "async.ctx.frameptr");
1716 auto NextF = std::next(
F.getIterator());
1721 auto *Suspend = cast<CoroSuspendAsyncInst>(CS);
1724 auto ResumeNameSuffix =
".resume.";
1725 auto ProjectionFunctionName =
1726 Suspend->getAsyncContextProjectionFunction()->getName();
1727 bool UseSwiftMangling =
false;
1728 if (ProjectionFunctionName ==
"__swift_async_resume_project_context") {
1729 ResumeNameSuffix =
"TQ";
1730 UseSwiftMangling =
true;
1731 }
else if (ProjectionFunctionName ==
"__swift_async_resume_get_context") {
1732 ResumeNameSuffix =
"TY";
1733 UseSwiftMangling =
true;
1737 UseSwiftMangling ? ResumeNameSuffix +
Twine(
Idx) +
"_"
1744 auto *SuspendBB = Suspend->getParent();
1745 auto *NewSuspendBB = SuspendBB->splitBasicBlock(Suspend);
1746 auto *Branch = cast<BranchInst>(SuspendBB->getTerminator());
1751 Branch->setSuccessor(0, ReturnBB);
1756 auto *Fn = Suspend->getMustTailCallFunction();
1773 auto *Clone = Clones[
Idx];
1788 F.removeFnAttr(Attribute::NoReturn);
1789 F.removeRetAttr(Attribute::NoAlias);
1790 F.removeRetAttr(Attribute::NonNull);
1796 RawFramePtr = Id->getStorage();
1812 Builder.
CreateStore(RawFramePtr, Id->getStorage());
1825 PHINode *ContinuationPhi =
nullptr;
1829 auto NextF = std::next(
F.getIterator());
1834 auto Suspend = cast<CoroSuspendRetconInst>(CS);
1843 auto SuspendBB = Suspend->getParent();
1844 auto NewSuspendBB = SuspendBB->splitBasicBlock(Suspend);
1845 auto Branch = cast<BranchInst>(SuspendBB->getTerminator());
1869 auto RetTy =
F.getReturnType();
1874 auto CastedContinuationTy =
1876 auto *CastedContinuation =
1877 Builder.
CreateBitCast(ContinuationPhi, CastedContinuationTy);
1879 Value *RetV = CastedContinuation;
1880 if (!ReturnPHIs.
empty()) {
1885 for (
auto Phi : ReturnPHIs)
1893 Branch->setSuccessor(0, ReturnBB);
1896 for (
auto [Phi, VUse] :
1898 Phi->addIncoming(VUse, SuspendBB);
1904 auto Clone = Clones[
Idx];
1918 OS <<
"While splitting coroutine ";
1919 F.printAsOperand(
OS,
false,
F.getParent());
1933 auto &Context =
End->getContext();
1935 End->eraseFromParent();
1941 for (
auto *U :
F.users()) {
1942 if (
auto *CB = dyn_cast<CallBase>(U)) {
1943 auto *Caller = CB->getFunction();
1944 if (Caller && Caller->isPresplitCoroutine() &&
1945 CB->hasFnAttr(llvm::Attribute::CoroElideSafe))
1955 SwitchCoroutineSplitter::split(
F,
Shape, Clones,
TTI);
1960 bool OptimizeFrame) {
1961 PrettyStackTraceFunction prettyStackTrace(
F);
1963 auto &Shape =
ABI.Shape;
1971 ABI.buildCoroutineFrame(OptimizeFrame);
1974 bool isNoSuspendCoroutine = Shape.
CoroSuspends.empty();
1976 bool shouldCreateNoAllocVariant =
1982 if (isNoSuspendCoroutine) {
1985 ABI.splitCoroutine(
F, Shape, Clones,
TTI);
1997 for (
auto *DDI : DbgInsts)
2004 if (shouldCreateNoAllocVariant)
2005 SwitchCoroutineSplitter::createNoAllocVariant(
F, Shape, Clones);
2014 auto *CurrentSCC = &
C;
2015 if (!Clones.
empty()) {
2016 switch (Shape.
ABI) {
2028 if (!Clones.empty())
2060 auto *Cast = dyn_cast<BitCastInst>(U.getUser());
2061 if (!Cast || Cast->getType() != Fn->getType())
2065 Cast->replaceAllUsesWith(Fn);
2066 Cast->eraseFromParent();
2075 while (
auto *Cast = dyn_cast<BitCastInst>(CastFn)) {
2076 if (!Cast->use_empty())
2078 CastFn = Cast->getOperand(0);
2079 Cast->eraseFromParent();
2085 bool Changed =
false;
2088 auto *Prepare = cast<CallInst>(
P.getUser());
2099 auto *PrepareFn = M.getFunction(
Name);
2100 if (PrepareFn && !PrepareFn->use_empty())
2104static std::unique_ptr<coro::BaseABI>
2110 if (CustomABI >= GenCustomABIs.
size())
2112 return GenCustomABIs[CustomABI](
F, S);
2117 return std::make_unique<coro::SwitchABI>(
F, S, IsMatCallback);
2119 return std::make_unique<coro::AsyncABI>(
F, S, IsMatCallback);
2121 return std::make_unique<coro::AnyRetconABI>(
F, S, IsMatCallback);
2123 return std::make_unique<coro::AnyRetconABI>(
F, S, IsMatCallback);
2129 : CreateAndInitABI([](
Function &
F, coro::Shape &S) {
2130 std::unique_ptr<coro::BaseABI> ABI =
2135 OptimizeFrame(OptimizeFrame) {}
2139 : CreateAndInitABI([=](
Function &
F, coro::Shape &S) {
2140 std::unique_ptr<coro::BaseABI> ABI =
2145 OptimizeFrame(OptimizeFrame) {}
2151 : CreateAndInitABI([=](
Function &
F, coro::Shape &S) {
2152 std::unique_ptr<coro::BaseABI> ABI =
2157 OptimizeFrame(OptimizeFrame) {}
2164 : CreateAndInitABI([=](
Function &
F, coro::Shape &S) {
2165 std::unique_ptr<coro::BaseABI> ABI =
2170 OptimizeFrame(OptimizeFrame) {}
2178 Module &M = *
C.begin()->getFunction().getParent();
2190 if (
N.getFunction().isPresplitCoroutine())
2193 if (Coroutines.
empty() && PrepareFns.
empty())
2196 auto *CurrentSCC = &
C;
2200 LLVM_DEBUG(
dbgs() <<
"CoroSplit: Processing coroutine '" <<
F.getName()
2212 F.setSplittedCoroutine();
2220 *
N, Shape, Clones, *CurrentSCC, CG, AM, UR,
FAM);
2225 <<
"Split '" <<
ore::NV(
"function",
F.getName())
2238 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...
BlockVerifier::State From
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)
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 bool hasCallsInBlockBetween(Instruction *From, Instruction *To)
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.
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....
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.
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
void replaceSwiftErrorOps()
Value * deriveNewFramePointer()
Derive the value of the new frame pointer.
void replaceCoroSuspends()
void handleFinalSuspend()
static Function * createClone(Function &OrigF, const Twine &Suffix, coro::Shape &Shape, Function *NewF, AnyCoroSuspendInst *ActiveSuspend, TargetTransformInfo &TTI)
Create a clone for a continuation lowering.
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
static Function * createClone(Function &OrigF, const Twine &Suffix, coro::Shape &Shape, CloneKind FKind, TargetTransformInfo &TTI)
Create a clone for a switch lowering.
void create() override
Clone the body of the original function into a resume function of some sort.
const ParentTy * getParent() const
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
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.
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...
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.
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.
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)
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.
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