77#include <initializer_list>
82#define DEBUG_TYPE "coro-split"
94 Builder.SetInsertPoint(CB);
105 Builder.CreateInvoke(
Wrapper, Invoke->getNormalDest(),
106 Invoke->getUnwindDest(), {Awaiter, FramePtr});
108 WrapperInvoke->setCallingConv(Invoke->getCallingConv());
109 std::copy(Invoke->bundle_op_info_begin(), Invoke->bundle_op_info_end(),
110 WrapperInvoke->bundle_op_info_begin());
111 WrapperInvoke->setAttributes(NewAttributes);
112 WrapperInvoke->setDebugLoc(Invoke->getDebugLoc());
113 NewCall = WrapperInvoke;
117 WrapperCall->setAttributes(NewAttributes);
118 WrapperCall->setDebugLoc(
Call->getDebugLoc());
119 NewCall = WrapperCall;
125 Intrinsic::coro_await_suspend_handle) {
130 Builder.SetInsertPoint(Invoke->getNormalDest()->getFirstInsertionPt());
135 &*Builder.GetInsertPoint());
140 auto *ResumeCall = Builder.CreateCall(ResumeTy, ResumeAddr, {NewCall});
146 NewCall = ResumeCall;
175 return Builder.CreateInBoundsPtrAdd(
FramePtr,
Offset,
"destroy.addr");
191 DestroyAddr,
"destroy");
195 EntryBuilder.
CreateICmpEQ(DestroyFn, CleanupFn,
"is.elided");
207 Builder.CreateSelect(IsElided,
Null,
FramePtr,
"coro.free");
215 CF->eraseFromParent();
227 Builder.CreateRetVoid();
231 auto *MustTailCallFunc = EndAsync->getMustTailCallFunction();
232 if (!MustTailCallFunc) {
233 Builder.CreateRetVoid();
238 auto *CoroEndBlock =
End->getParent();
239 auto *MustTailCallFuncBlock = CoroEndBlock->getSinglePredecessor();
240 assert(MustTailCallFuncBlock &&
"Must have a single predecessor block");
241 auto It = MustTailCallFuncBlock->getTerminator()->getIterator();
243 CoroEndBlock->splice(
End->getIterator(), MustTailCallFuncBlock,
244 MustTailCall->getIterator());
247 Builder.SetInsertPoint(
End);
248 Builder.CreateRetVoid();
252 auto *BB =
End->getParent();
253 BB->splitBasicBlock(
End);
254 BB->getTerminator()->eraseFromParent();
257 assert(InlineRes.isSuccess() &&
"Expected inlining to succeed");
276 "switch coroutine should not return any values");
281 Builder.CreateRetVoid();
287 if (!CoroEndBlockNeedsCleanup)
299 if (!CoroEnd->hasResults()) {
300 assert(RetTy->isVoidTy());
301 Builder.CreateRetVoid();
305 auto *CoroResults = CoroEnd->getResults();
306 unsigned NumReturns = CoroResults->numReturns();
309 assert(RetStructTy->getNumElements() == NumReturns &&
310 "numbers of returns should match resume function singature");
313 for (
Value *RetValEl : CoroResults->return_values())
314 ReturnValue = Builder.CreateInsertValue(ReturnValue, RetValEl, Idx++);
315 Builder.CreateRet(ReturnValue);
316 }
else if (NumReturns == 0) {
317 assert(RetTy->isVoidTy());
318 Builder.CreateRetVoid();
321 Builder.CreateRet(*CoroResults->retval_begin());
323 CoroResults->replaceAllUsesWith(
325 CoroResults->eraseFromParent();
333 "retcon coroutine should not return any values");
345 Builder.CreateRet(ReturnValue);
351 auto *BB =
End->getParent();
352 BB->splitBasicBlock(
End);
353 BB->getTerminator()->eraseFromParent();
359 return Builder.CreatePtrAddWithUnsignedOffset(
376 "markCoroutineAsDone is only supported for Switch-Resumed ABI for now.");
379 Builder.CreateStore(NullPtr,
FramePtr);
392 "The final suspend should only live in the last position of "
396 Builder.CreateStore(IndexVal, FinalIndex);
432 auto *CleanupRet = Builder.CreateCleanupRet(FromPad,
nullptr);
433 End->getParent()->splitBasicBlock(
End);
434 CleanupRet->getParent()->getTerminator()->eraseFromParent();
444 End->eraseFromParent();
458 Shape.SwitchLowering.HasFinalSuspend);
464 auto FinalCaseIt = std::prev(
Switch->case_end());
465 BasicBlock *ResumeBB = FinalCaseIt->getCaseSuccessor();
476 if (
NewF->isCoroOnlyDestroyWhenComplete()) {
485 auto *Br =
Builder.CreateCondBr(
Cond, ResumeBB, NewSwitchBB);
499 auto &Context = Suspend->
getParent()->getParent()->getContext();
517 M->getFunctionList().insert(InsertBefore, NewF);
531 if (NewS->use_empty())
539 for (
auto I = IsAsyncABI ?
NewF->arg_begin() : std::next(
NewF->arg_begin()),
548 NewS->replaceAllUsesWith(Args.front());
555 if (!EVI || EVI->getNumIndices() != 1)
558 EVI->replaceAllUsesWith(Args[EVI->getIndices().front()]);
559 EVI->eraseFromParent();
563 if (NewS->use_empty())
569 Aggr =
Builder.CreateInsertValue(Aggr, Arg, Idx);
571 NewS->replaceAllUsesWith(Aggr);
575 Value *SuspendResult;
606 MappedCS->replaceAllUsesWith(SuspendResult);
607 MappedCS->eraseFromParent();
621 auto &Ctx =
OrigF.getContext();
622 for (
auto *
II :
Shape.CoroIsInRampInsts) {
625 NewII->eraseFromParent();
633 Value *CachedSlot =
nullptr;
634 auto getSwiftErrorSlot = [&](
Type *ValueTy) ->
Value * {
639 for (
auto &Arg :
F.args()) {
640 if (Arg.isSwiftError()) {
647 IRBuilder<> Builder(
F.getEntryBlock().getFirstNonPHIOrPseudoProbe());
648 auto Alloca = Builder.CreateAlloca(ValueTy);
649 Alloca->setSwiftError(
true);
661 if (
Op->arg_empty()) {
662 auto ValueTy =
Op->getType();
663 auto Slot = getSwiftErrorSlot(ValueTy);
664 MappedResult = Builder.CreateLoad(ValueTy, Slot);
667 auto Value = MappedOp->getArgOperand(0);
669 auto Slot = getSwiftErrorSlot(ValueTy);
670 Builder.CreateStore(
Value, Slot);
675 MappedOp->eraseFromParent();
679 if (VMap ==
nullptr) {
692 return DbgVariableRecords;
704 bool UseEntryValue =
OrigF.getParent()->getTargetTriple().isArch64Bit();
711 auto IsUnreachableBlock = [&](
BasicBlock *BB) {
716 if (IsUnreachableBlock(DVI->getParent()))
717 DVI->eraseFromParent();
721 for (
auto *
User : DVI->getVariableLocationOp(0)->
users())
726 DVI->eraseFromParent();
729 for_each(DbgVariableRecords, RemoveOne);
739 auto *OldEntry = &
NewF->getEntryBlock();
740 Entry->setName(
"entry" +
Suffix);
741 Entry->moveBefore(OldEntry);
742 Entry->getTerminator()->eraseFromParent();
747 assert(Entry->hasOneUse());
749 Builder.SetInsertPoint(BranchToEntry);
751 BranchToEntry->eraseFromParent();
762 SwitchBB->moveAfter(Entry);
778 Builder.CreateBr(Branch->getSuccessor(0));
789 if (!Alloca ||
I.use_empty())
794 I.moveBefore(*Entry, Entry->getFirstInsertionPt());
808 for (
unsigned Repeat = 0; Repeat < 2; Repeat++) {
812 Successor = Branch->getSuccessor()->getFirstNonPHIOrPseudoProbe();
818 if (
DL &&
DL.getLine() != 0)
831 return &*
NewF->arg_begin();
839 auto ContextIdx = ActiveAsyncSuspend->getStorageArgumentIndex() & 0xff;
840 auto *CalleeContext =
NewF->getArg(ContextIdx);
841 auto *ProjectionFunc =
842 ActiveAsyncSuspend->getAsyncContextProjectionFunction();
844 DebugLoc DbgLoc = NewSuspend->getDebugLoc();
848 if (DbgLoc && DbgLoc.
getLine() == 0)
852 auto *CallerContext =
Builder.CreateCall(ProjectionFunc->getFunctionType(),
853 ProjectionFunc, CalleeContext);
854 CallerContext->setCallingConv(ProjectionFunc->getCallingConv());
855 CallerContext->setDebugLoc(DbgLoc);
857 auto *FramePtrAddr =
Builder.CreatePtrAddWithUnsignedOffset(
858 CallerContext,
Shape.AsyncLowering.FrameOffset,
"async.ctx.frameptr",
863 assert(InlineRes.isSuccess());
874 if (
Shape.RetconLowering.IsFrameInlineInStorage)
878 return Builder.CreateLoad(FramePtrTy, NewStorage);
899 SPToUpdate.setScopeLine(
DL.getLine());
904 Align Alignment,
bool NoAlias) {
905 AttrBuilder ParamAttrs(Context);
906 ParamAttrs.addAttribute(Attribute::NonNull);
907 ParamAttrs.addAttribute(Attribute::NoUndef);
910 ParamAttrs.addAttribute(Attribute::NoAlias);
912 ParamAttrs.addAlignmentAttr(Alignment);
913 ParamAttrs.addDereferenceableAttr(
Size);
914 Attrs = Attrs.addParamAttributes(Context, ParamIndex, ParamAttrs);
918 unsigned ParamIndex) {
919 AttrBuilder ParamAttrs(Context);
920 ParamAttrs.addAttribute(Attribute::SwiftAsync);
921 Attrs = Attrs.addParamAttributes(Context, ParamIndex, ParamAttrs);
925 unsigned ParamIndex) {
926 AttrBuilder ParamAttrs(Context);
927 ParamAttrs.addAttribute(Attribute::SwiftSelf);
928 Attrs = Attrs.addParamAttributes(Context, ParamIndex, ParamAttrs);
951 auto savedVisibility =
NewF->getVisibility();
952 auto savedUnnamedAddr =
NewF->getUnnamedAddr();
953 auto savedDLLStorageClass =
NewF->getDLLStorageClass();
958 auto savedLinkage =
NewF->getLinkage();
964 auto &Context =
NewF->getContext();
967 assert(SP !=
OrigF.getSubprogram() && SP->isDistinct());
973 SP->replaceLinkageName(NewLinkageName);
975 TempDISubprogram NewDecl = Decl->clone();
976 NewDecl->replaceLinkageName(NewLinkageName);
981 NewF->setLinkage(savedLinkage);
982 NewF->setVisibility(savedVisibility);
983 NewF->setUnnamedAddr(savedUnnamedAddr);
984 NewF->setDLLStorageClass(savedDLLStorageClass);
989 NewF->hasMetadata(LLVMContext::MD_func_sanitize))
990 NewF->eraseMetadata(LLVMContext::MD_func_sanitize);
993 auto OrigAttrs =
NewF->getAttributes();
1000 NewAttrs = NewAttrs.addFnAttributes(
1001 Context, AttrBuilder(Context, OrigAttrs.getFnAttrs()));
1004 Shape.FrameAlign,
false);
1008 if (
OrigF.hasParamAttribute(
Shape.AsyncLowering.ContextArgNo,
1009 Attribute::SwiftAsync)) {
1011 ActiveAsyncSuspend->getStorageArgumentIndex();
1012 auto ContextArgIndex = ArgAttributeIndices & 0xff;
1017 auto SwiftSelfIndex = ArgAttributeIndices >> 8;
1023 auto FnAttrs =
OrigF.getAttributes().getFnAttrs();
1024 NewAttrs = NewAttrs.addFnAttributes(Context, AttrBuilder(Context, FnAttrs));
1031 NewAttrs =
Shape.RetconLowering.ResumePrototype->getAttributes();
1035 Shape.getRetconCoroId()->getStorageSize(),
1036 Shape.getRetconCoroId()->getStorageAlignment(),
1042 switch (
Shape.ABI) {
1067 NewF->setAttributes(NewAttrs);
1068 NewF->setCallingConv(
Shape.getResumeFunctionCC());
1076 if (
TTI.supportsTailCallFor(ResumeCall)) {
1091 Builder.SetInsertPoint(&
NewF->getEntryBlock().front());
1100 auto *NewVFrame =
Builder.CreateBitCast(
1103 if (OldVFrame != NewVFrame)
1110 DummyArg->deleteValue();
1113 switch (
Shape.ABI) {
1118 if (
Shape.SwitchLowering.HasFinalSuspend)
1127 "no active suspend when lowering a continuation-style coroutine");
1158 Shape.ResumeEntryCount.has_value()) {
1159 NewF->setEntryCount(
Shape.ResumeEntryCount.value());
1172 auto *OrigRelativeFunOffset = FuncPtrStruct->getOperand(0);
1173 auto *OrigContextSize = FuncPtrStruct->getOperand(1);
1174 auto *NewContextSize = ConstantInt::get(OrigContextSize->getType(),
1177 FuncPtrStruct->getType(), OrigRelativeFunOffset, NewContextSize);
1196 auto *SizeIntrin = Shape.
CoroSizes.back();
1197 auto *SizeConstant = ConstantInt::get(SizeIntrin->getType(),
1222 switch (Shape.
ABI) {
1231 auto *Frame = Builder.CreateAlloca(
1232 FrameTy,
nullptr, AllocInst->getFunction()->getName() +
".Frame");
1234 AllocInst->replaceAllUsesWith(Builder.getFalse());
1235 AllocInst->eraseFromParent();
1236 CoroBegin->replaceAllUsesWith(Frame);
1238 CoroBegin->replaceAllUsesWith(CoroBegin->getMem());
1279 while (!Worklist.
empty()) {
1283 if (!Set.contains(
Pred))
1289 Set.erase(ResDesBB);
1291 for (
auto *BB : Set)
1300 auto *ResumeOrDestroyBB = ResumeOrDestroy->
getParent();
1304 if (SaveBB == ResumeOrDestroyBB)
1313 {ResumeOrDestroyBB->getFirstNonPHIIt(), ResumeOrDestroyIt}))
1332 Prev =
Pred->getTerminator();
1347 if (SubFn->getFrame() != CoroBegin)
1361 Save->eraseFromParent();
1373 if (CalledValue != SubFn && CalledValue->user_empty())
1375 I->eraseFromParent();
1378 if (SubFn->user_empty())
1379 SubFn->eraseFromParent();
1391 size_t I = 0,
N = S.size();
1395 size_t ChangedFinalIndex = std::numeric_limits<size_t>::max();
1408 ChangedFinalIndex =
I;
1420 if (ChangedFinalIndex <
N) {
1422 std::swap(S[ChangedFinalIndex], S.back());
1428struct SwitchCoroutineSplitter {
1430 SmallVectorImpl<Function *> &Clones,
1431 TargetTransformInfo &
TTI) {
1437 createResumeEntryBlock(
F, Shape);
1439 F,
".resume", Shape, coro::CloneKind::SwitchResume,
TTI);
1441 F,
".destroy", Shape, coro::CloneKind::SwitchUnwind,
TTI);
1443 F,
".cleanup", Shape, coro::CloneKind::SwitchCleanup,
TTI);
1453 updateCoroFrame(Shape, ResumeClone, DestroyClone, CleanupClone);
1463 setCoroInfo(
F, Shape, Clones);
1474 SmallVectorImpl<Function *> &Clones) {
1476 auto *OrigFnTy =
F.getFunctionType();
1477 auto OldParams = OrigFnTy->params();
1480 NewParams.
reserve(OldParams.size() + 1);
1481 NewParams.
append(OldParams.begin(), OldParams.end());
1484 auto *NewFnTy = FunctionType::get(OrigFnTy->getReturnType(), NewParams,
1485 OrigFnTy->isVarArg());
1487 NewFnTy,
F.getLinkage(),
F.getAddressSpace(),
F.getName() +
".noalloc");
1490 unsigned int Idx = 0;
1491 for (
const auto &
I :
F.args()) {
1492 VMap[&
I] = NoAllocF->
getArg(Idx++);
1496 auto FrameIdx = NoAllocF->
arg_size() - 1;
1499 CloneFunctionChangeType::LocalChangesOnly, Returns);
1502 auto *NewCoroBegin =
1506 NewCoroBegin->replaceAllUsesWith(NoAllocF->
getArg(FrameIdx));
1507 NewCoroBegin->eraseFromParent();
1511 M->getFunctionList().insert(
M->end(), NoAllocF);
1526 setCoroInfo(
F, Shape, Clones);
1537 static void createResumeEntryBlock(
Function &
F, coro::Shape &Shape) {
1540 DIBuilder DBuilder(*
F.getParent(),
false);
1541 DISubprogram *DIS =
F.getSubprogram();
1545 bool AddDebugLabels = DIS && DIS->getUnit() &&
1546 (DIS->getUnit()->getEmissionKind() ==
1547 DICompileUnit::DebugEmissionKind::FullDebug);
1566 Builder.CreateSwitch(Index, UnreachBB, Shape.
CoroSuspends.size());
1570 size_t SuspendIndex = 0;
1571 SmallVector<uint64_t, 8> SwitchWeights64;
1577 ConstantInt *IndexVal = Shape.
getIndex(SuspendIndex);
1582 auto *Save = S->getCoroSave();
1583 Builder.SetInsertPoint(Save);
1590 Builder.CreateStore(IndexVal, GepIndex);
1594 Save->eraseFromParent();
1620 auto *SuspendBB = S->getParent();
1622 SuspendBB->splitBasicBlock(S,
"resume." + Twine(SuspendIndex));
1623 auto *LandingBB = ResumeBB->splitBasicBlock(
1624 S->getNextNode(), ResumeBB->getName() + Twine(
".landing"));
1625 Switch->addCase(IndexVal, ResumeBB);
1631 Weight = It->second;
1637 PN->insertBefore(LandingBB->begin());
1638 S->replaceAllUsesWith(PN);
1639 PN->addIncoming(Builder.getInt8(-1), SuspendBB);
1640 PN->addIncoming(S, ResumeBB);
1642 if (AddDebugLabels) {
1643 if (
DebugLoc SuspendLoc = S->getDebugLoc()) {
1644 std::string LabelName =
1645 (
"__coro_resume_" + Twine(SuspendIndex)).str();
1651 DILocation *DILoc = SuspendLoc;
1652 while (DILocation *InlinedAt = DILoc->getInlinedAt())
1655 DILabel *ResumeLabel =
1656 DBuilder.createLabel(DIS, LabelName, DILoc->getFile(),
1657 SuspendLoc.getLine(), SuspendLoc.getCol(),
1661 DBuilder.insertLabel(ResumeLabel, DILoc, ResumeBB->begin());
1671 Switch->setMetadata(LLVMContext::MD_prof,
1672 MDB.createBranchWeights(SwitchWeights32));
1675 Builder.SetInsertPoint(UnreachBB);
1676 Builder.CreateUnreachable();
1677 DBuilder.finalize();
1683 static void updateCoroFrame(coro::Shape &Shape,
Function *ResumeFn,
1689 Builder.CreateStore(ResumeFn, ResumeAddr);
1691 Value *DestroyOrCleanupFn = DestroyFn;
1697 DestroyOrCleanupFn = Builder.CreateSelect(CA, DestroyFn, CleanupFn);
1705 Value *DestroyAddr = Builder.CreatePtrAddWithUnsignedOffset(
1708 Builder.CreateStore(DestroyOrCleanupFn, DestroyAddr);
1724 static void setCoroInfo(
Function &
F, coro::Shape &Shape,
1728 SmallVector<Constant *, 4>
Args(Fns);
1732 auto *ArrTy = ArrayType::get(Part->
getType(),
Args.size());
1735 auto *GV =
new GlobalVariable(*M, ConstVal->getType(),
true,
1736 GlobalVariable::PrivateLinkage, ConstVal,
1737 F.getName() + Twine(
".resumers"));
1740 LLVMContext &
C =
F.getContext();
1751 auto &Context = Suspend->
getParent()->getParent()->getContext();
1755 auto *Val = Builder.CreateBitOrPointerCast(
Continuation, Int8PtrTy);
1756 ResumeIntrinsic->replaceAllUsesWith(Val);
1757 ResumeIntrinsic->eraseFromParent();
1767 for (
auto *paramTy : FnTy->params()) {
1769 if (paramTy != FnArgs[ArgIdx]->
getType())
1771 Builder.CreateBitOrPointerCast(FnArgs[ArgIdx], paramTy));
1788 auto *TailCall = Builder.CreateCall(FnTy, MustTailCallFn, CallArgs);
1790 if (
TTI.supportsTailCallFor(TailCall)) {
1793 TailCall->setDebugLoc(
Loc);
1805 F.removeFnAttr(Attribute::NoReturn);
1806 F.removeRetAttr(Attribute::NoAlias);
1807 F.removeRetAttr(Attribute::NonNull);
1809 auto &Context =
F.getContext();
1812 auto *Id =
Shape.getAsyncCoroId();
1817 FramePtr = Builder.CreatePtrAddWithUnsignedOffset(
1818 FramePtr,
Shape.AsyncLowering.FrameOffset,
"async.ctx.frameptr",
1830 auto NextF = std::next(
F.getIterator());
1838 auto ResumeNameSuffix =
".resume.";
1839 auto ProjectionFunctionName =
1840 Suspend->getAsyncContextProjectionFunction()->getName();
1841 bool UseSwiftMangling =
false;
1842 if (ProjectionFunctionName ==
"__swift_async_resume_project_context") {
1843 ResumeNameSuffix =
"TQ";
1844 UseSwiftMangling =
true;
1845 }
else if (ProjectionFunctionName ==
"__swift_async_resume_get_context") {
1846 ResumeNameSuffix =
"TY";
1847 UseSwiftMangling =
true;
1851 UseSwiftMangling ? ResumeNameSuffix +
Twine(Idx) +
"_"
1852 : ResumeNameSuffix +
Twine(Idx),
1858 auto *SuspendBB = Suspend->getParent();
1859 auto *NewSuspendBB = SuspendBB->splitBasicBlock(Suspend);
1865 Branch->setSuccessor(0, ReturnBB);
1870 auto *Fn = Suspend->getMustTailCallFunction();
1876 Builder.CreateRetVoid();
1888 auto *Clone = Clones[Idx];
1903 F.removeFnAttr(Attribute::NoReturn);
1904 F.removeRetAttr(Attribute::NoAlias);
1905 F.removeRetAttr(Attribute::NonNull);
1908 auto *Id =
Shape.getRetconCoroId();
1910 if (
Shape.RetconLowering.IsFrameInlineInStorage) {
1911 RawFramePtr = Id->getStorage();
1915 auto FrameSize = Builder.getInt64(
Shape.FrameSize);
1920 RawFramePtr =
Shape.emitAlloc(Builder, FrameSize,
nullptr);
1922 Builder.CreateBitCast(RawFramePtr,
Shape.CoroBegin->getType());
1925 Builder.CreateStore(RawFramePtr, Id->getStorage());
1932 Shape.CoroBegin->replaceAllUsesWith(RawFramePtr);
1938 PHINode *ContinuationPhi =
nullptr;
1942 auto NextF = std::next(
F.getIterator());
1951 F,
Shape,
".resume." +
Twine(Idx), NextF,
nullptr);
1956 auto SuspendBB = Suspend->getParent();
1957 auto NewSuspendBB = SuspendBB->splitBasicBlock(Suspend);
1965 Shape.RetconLowering.ReturnBlock = ReturnBB;
1977 for (
auto *ResultTy :
Shape.getRetconResultTypes())
1979 Builder.CreatePHI(ResultTy,
Shape.CoroSuspends.size()));
1982 auto RetTy =
F.getReturnType();
1987 auto CastedContinuationTy =
1988 (ReturnPHIs.
empty() ? RetTy : RetTy->getStructElementType(0));
1989 auto *CastedContinuation =
1990 Builder.CreateBitCast(ContinuationPhi, CastedContinuationTy);
1992 Value *RetV = CastedContinuation;
1993 if (!ReturnPHIs.
empty()) {
1996 RetV = Builder.CreateInsertValue(RetV, CastedContinuation, ValueIdx++);
1998 for (
auto Phi : ReturnPHIs)
1999 RetV = Builder.CreateInsertValue(RetV, Phi, ValueIdx++);
2002 Builder.CreateRet(RetV);
2006 Branch->setSuccessor(0, ReturnBB);
2009 for (
auto [Phi, VUse] :
2011 Phi->addIncoming(VUse, SuspendBB);
2018 auto Clone = Clones[Idx];
2032 OS <<
"While splitting coroutine ";
2033 F.printAsOperand(OS,
false,
F.getParent());
2047 End->eraseFromParent();
2053 auto &Ctx =
II->getContext();
2055 II->eraseFromParent();
2060 for (
auto *U :
F.users()) {
2062 auto *Caller = CB->getFunction();
2063 if (Caller && Caller->isPresplitCoroutine() &&
2064 CB->hasFnAttr(llvm::Attribute::CoroElideSafe))
2074 SwitchCoroutineSplitter::split(
F,
Shape, Clones,
TTI);
2079 bool OptimizeFrame) {
2080 PrettyStackTraceFunction prettyStackTrace(
F);
2082 auto &Shape = ABI.
Shape;
2090 ABI.buildCoroutineFrame(OptimizeFrame);
2093 bool isNoSuspendCoroutine = Shape.
CoroSuspends.empty();
2095 bool shouldCreateNoAllocVariant =
2100 shouldCreateNoAllocVariant;
2104 if (isNoSuspendCoroutine) {
2107 ABI.splitCoroutine(
F, Shape, Clones,
TTI);
2125 if (shouldCreateNoAllocVariant)
2126 SwitchCoroutineSplitter::createNoAllocVariant(
F, Shape, Clones);
2135 auto *CurrentSCC = &
C;
2136 if (!Clones.
empty()) {
2137 switch (Shape.
ABI) {
2143 assert(Clones.
size() >= 3 &&
"expected switch coroutine clones");
2161 if (!Clones.
empty())
2194 if (!Cast || Cast->getType() != Fn->getType())
2198 Cast->replaceAllUsesWith(Fn);
2199 Cast->eraseFromParent();
2209 if (!Cast->use_empty())
2211 CastFn = Cast->getOperand(0);
2212 Cast->eraseFromParent();
2232 auto *PrepareFn = M.getFunction(Name);
2233 if (PrepareFn && !PrepareFn->use_empty())
2237static std::unique_ptr<coro::BaseABI>
2243 if (CustomABI >= GenCustomABIs.
size())
2245 return GenCustomABIs[CustomABI](
F, S);
2250 return std::make_unique<coro::SwitchABI>(
F, S, IsMatCallback);
2252 return std::make_unique<coro::AsyncABI>(
F, S, IsMatCallback);
2254 return std::make_unique<coro::AnyRetconABI>(
F, S, IsMatCallback);
2256 return std::make_unique<coro::AnyRetconABI>(
F, S, IsMatCallback);
2263 std::unique_ptr<coro::BaseABI> ABI =
2268 OptimizeFrame(OptimizeFrame) {}
2273 std::unique_ptr<coro::BaseABI> ABI =
2278 OptimizeFrame(OptimizeFrame) {}
2285 std::unique_ptr<coro::BaseABI> ABI =
2290 OptimizeFrame(OptimizeFrame) {}
2298 std::unique_ptr<coro::BaseABI> ABI =
2303 OptimizeFrame(OptimizeFrame) {}
2311 Module &M = *
C.begin()->getFunction().getParent();
2323 if (
N.getFunction().isPresplitCoroutine())
2326 if (Coroutines.
empty() && PrepareFns.
empty())
2329 auto *CurrentSCC = &
C;
2333 LLVM_DEBUG(
dbgs() <<
"CoroSplit: Processing coroutine '" <<
F.getName()
2345 F.setSplittedCoroutine();
2351 uint64_t Freq = BFI.getBlockFreq(BB).getFrequency();
2356 std::optional<uint64_t>
Count = BFI.getBlockProfileCount(BB);
2357 if (
Count.has_value()) {
2375 *
N, Shape, Clones, *CurrentSCC, CG, AM, UR,
FAM);
2380 <<
"Split '" <<
ore::NV(
"function",
F.getName())
2397 for (
auto *PrepareFn : PrepareFns) {
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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 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 replaceFallthroughCoroEnd(AnyCoroEndInst *End, const coro::Shape &Shape, Value *FramePtr, bool InRamp, CallGraph *CG)
Replace a non-unwind call to llvm.coro.end.
static void replaceSwiftErrorOps(Function &F, coro::Shape &Shape, ValueToValueMapTy *VMap)
static void replaceCoroEnd(AnyCoroEndInst *End, const coro::Shape &Shape, Value *FramePtr, bool InRamp, CallGraph *CG)
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)
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 removeCoroIsInRampFromRampFunction(const coro::Shape &Shape)
static void replaceSwitchResumeCoroFree(const coro::Shape &Shape, Function &Resume, Function &Cleanup)
Make resume-clone coro.free conditional on whether the frame is elided.
static void addPrepareFunction(const Module &M, SmallVectorImpl< Function * > &Fns, StringRef Name)
static Value * createSwitchDestroyPtr(const coro::Shape &Shape, IRBuilder<> &Builder, Value *FramePtr)
Create a pointer to the switch destroy function field in the coroutine frame.
static SmallVector< DbgVariableRecord * > collectDbgVariableRecords(Function &F)
Returns all debug records in F.
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 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)
static bool simplifySuspendPoint(CoroSuspendInst *Suspend, CoroBeginInst *CoroBegin)
static Value * createSwitchIndexPtr(const coro::Shape &Shape, IRBuilder<> &Builder, Value *FramePtr)
Create a pointer to the switch index field in the coroutine frame.
static void removeCoroEndsFromRampFunction(const coro::Shape &Shape)
Remove calls to llvm.coro.end in the original function.
static void markCoroutineAsDone(IRBuilder<> &Builder, const coro::Shape &Shape, Value *FramePtr)
static void updateAsyncFuncPointerContextSize(coro::Shape &Shape)
static void coerceArguments(IRBuilder<> &Builder, FunctionType *FnTy, ArrayRef< Value * > FnArgs, SmallVectorImpl< Value * > &CallArgs)
Coerce the arguments in FnArgs according to FnTy in CallArgs.
static void replaceUnwindCoroEnd(AnyCoroEndInst *End, const coro::Shape &Shape, Value *FramePtr, bool InRamp, CallGraph *CG)
Replace an unwind call to llvm.coro.end.
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 void replacePrepare(CallInst *Prepare, LazyCallGraph &CG, LazyCallGraph::SCC &C)
Replace a call to llvm.coro.prepare.retcon.
static DebugLoc getFirstNonZeroLocAfterSuspend(Instruction *ActiveSuspend)
Returns the location of the first instruction after ActiveSuspend with a non-zero line,...
static void replaceAsyncResumeFunction(CoroSuspendAsyncInst *Suspend, Value *Continuation)
This file defines the DenseMap class.
This file contains constants used for implementing Dwarf debug support.
ManagedStatic< HTTPClientCleanup > Cleanup
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.
Machine Check Debug Module
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
This file provides a priority worklist.
This file contains the declarations for profiling metadata utility functions.
SmallVector< MachineOperand, 4 > Cond
Remove Loads Into Fake Uses
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
static SymbolRef::Type getType(const Symbol *Sym)
static const unsigned FramePtr
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
CoroAllocInst * getCoroAlloc()
This class represents an incoming formal argument to a Function.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
LLVM Basic Block Representation.
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
const Function * getParent() const
Return the enclosing method, or null if none.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
InstListType::iterator iterator
Instruction iterators...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Analysis pass which computes BlockFrequencyInfo.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
Value * getCalledOperand() const
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 LLVM_ABI Constant * get(ArrayType *T, ArrayRef< Constant * > V)
static LLVM_ABI 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 LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
static LLVM_ABI ConstantInt * getFalse(LLVMContext &Context)
static LLVM_ABI ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
static LLVM_ABI Constant * get(StructType *T, ArrayRef< Constant * > V)
static LLVM_ABI ConstantTokenNone * get(LLVMContext &Context)
Return the ConstantTokenNone.
This represents the llvm.coro.align 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.
bool hasCustomABI() const
This represents the llvm.coro.free 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
Subprogram description. Uses SubclassData1.
Record of a variable value-assignment, aka a non instruction representation of the dbg....
LLVM_ABI unsigned getLine() const
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
LLVM_ABI 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 LLVM_ABI 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)
const BasicBlock & getEntryBlock() const
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.
Argument * getArg(unsigned i) const
static GEPNoWrapFlags inBounds()
void setLinkage(LinkageTypes LT)
unsigned getAddressSpace() const
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.
LLVM_ABI void setInitializer(Constant *InitVal)
setInitializer - Sets the initializer for this global variable, removing any existing initializer if ...
Value * CreatePointerCast(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
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.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
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.
LLVM_ABI void addSplitFunction(Function &OriginalFunction, Function &NewFunction)
Add a new function split/outlined from an existing function.
LLVM_ABI 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 std::enable_if_t< std::is_base_of< MDNode, T >::value, T * > replaceWithUniqued(std::unique_ptr< T, TempMDNodeDeleter > N)
Replace a temporary node with a uniqued one.
static LLVM_ABI 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(LLVMContext &C)
This constructs an opaque pointer to an object in the default address space (address space zero).
static LLVM_ABI 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.
Represent a constant reference to a string, i.e.
A wrapper class to simplify modification of SwitchInst cases along with their prof branch_weights met...
LLVM_ABI SwitchInst::CaseIt removeCase(SwitchInst::CaseIt I)
Delegate the call to the underlying SwitchInst::removeCase() and remove correspondent branch weight.
Analysis pass providing the TargetTransformInfo.
Value handle that tracks a Value across RAUW.
ValueTy * getValPtr() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
static UncondBrInst * Create(BasicBlock *Target, InsertPosition InsertBefore=nullptr)
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.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVMContext & getContext() const
All values hold a context through their type.
iterator_range< user_iterator > users()
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
iterator_range< use_iterator > uses()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
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()
AnyCoroSuspendInst * ActiveSuspend
The active suspend instruction; meaningful only for continuation and async ABIs.
Value * deriveNewFramePointer()
Derive the value of the new frame pointer.
void replaceCoroSuspends()
void handleFinalSuspend()
TargetTransformInfo & TTI
static Function * createClone(Function &OrigF, const Twine &Suffix, coro::Shape &Shape, Function *NewF, AnyCoroSuspendInst *ActiveSuspend, TargetTransformInfo &TTI)
Create a clone for a continuation lowering.
void replaceCoroIsInRamp()
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
self_iterator getIterator()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
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.
@ 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<> &)
LLVM_ABI bool isTriviallyMaterializable(Instruction &I)
@ SwitchCleanup
The shared cleanup function for a switch lowering.
@ SwitchResume
The shared resume function for a switch lowering.
@ Continuation
An individual continuation function.
void elideCoroFree(Value *FramePtr)
void salvageDebugInfo(SmallDenseMap< Argument *, AllocaInst *, 4 > &ArgToAllocaMap, DbgVariableRecord &DVR, bool UseEntryValue)
Attempts to rewrite the location operand of debug records in terms of the coroutine frame pointer,...
DiagnosticInfoOptimizationBase::Argument NV
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
auto cast_if_present(const Y &Val)
cast_if_present<X> - Functionally identical to cast, except that a null value is accepted.
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,...
LLVM_ABI void setExplicitlyUnknownBranchWeightsIfProfiled(Instruction &I, StringRef PassName, const Function *F=nullptr)
Like setExplicitlyUnknownBranchWeights(...), but only sets unknown branch weights in the new instruct...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI bool verifyFunction(const Function &F, raw_ostream *OS=nullptr)
Check a function for errors, useful for use when debugging a pass.
@ Load
The value being inserted comes from a load (InsertElement only).
LLVM_ABI 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.
LLVM_ABI 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...
LLVM_ABI void applyProfMetadataIfEnabled(Value *V, llvm::function_ref< void(Instruction *)> setMetadataCallback)
bool isa_and_nonnull(const Y &Val)
LLVM_ABI InlineResult InlineFunction(CallBase &CB, InlineFunctionInfo &IFI, bool MergeAttributes=false, AAResults *CalleeAAR=nullptr, bool InsertLifetime=true, bool TrackInlineHistory=false, Function *ForwardVarArgsTo=nullptr, OptimizationRemarkEmitter *ORE=nullptr)
This function inlines the called function into the basic block of the caller.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
AnalysisManager< LazyCallGraph::SCC, LazyCallGraph & > CGSCCAnalysisManager
The CGSCC analysis manager.
LLVM_ABI bool removeUnreachableBlocks(Function &F, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr, bool FoldInstsToUnreachable=true)
Remove all blocks that can not be reached from the function's entry.
auto dyn_cast_or_null(const Y &Val)
LLVM_ABI SmallVector< uint32_t > fitWeights(ArrayRef< uint64_t > Weights)
Push the weights right to fit in uint32_t.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
iterator_range< SplittingIterator > split(StringRef Str, StringRef Separator)
Split the specified string over a separator and return a range-compatible iterable over its partition...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI 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...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
LLVM_ABI bool isPotentiallyReachable(const Instruction *From, const Instruction *To, const SmallPtrSetImpl< BasicBlock * > *ExclusionSet=nullptr, const DominatorTree *DT=nullptr, const LoopInfo *LI=nullptr, const CycleInfo *CI=nullptr)
Determine whether instruction 'To' is reachable from 'From', without passing through any blocks in Ex...
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy
LLVM_ABI 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.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto predecessors(const MachineBasicBlock *BB)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
@ End
Run the machine verifier once, at the end of the pipeline.
static auto filterDbgVars(iterator_range< simple_ilist< DbgRecord >::iterator > R)
Filter the DbgRecord range to DbgVariableRecord types only and downcast.
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.
constexpr 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.
LLVM_ABI PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR)
LLVM_ABI CoroSplitPass(bool OptimizeFrame=false)
BaseABITy CreateAndInitABI
CallInst * makeSubFnCall(Value *Arg, int Index, Instruction *InsertPt)
GlobalVariable * AsyncFuncPointer
bool IsFrameInlineInStorage
bool HasCoroElideNoAllocVariant
SwitchInst * ResumeSwitch
BasicBlock * ResumeEntryBlock
SmallVector< CallInst *, 2 > SymmetricTransfers
SmallVector< CoroAwaitSuspendInst *, 4 > CoroAwaitSuspends
AsyncLoweringStorage AsyncLowering
FunctionType * getResumeFunctionType() const
IntegerType * getIndexType() const
PointerType * getSwitchResumePointerType() const
CoroIdInst * getSwitchCoroId() const
SmallVector< CoroSizeInst *, 2 > CoroSizes
SmallVector< AnyCoroSuspendInst *, 4 > CoroSuspends
std::optional< uint64_t > ResumeEntryCount
ConstantInt * getIndex(uint64_t Value) const
SwitchLoweringStorage SwitchLowering
CoroBeginInst * CoroBegin
SmallDenseMap< AnyCoroSuspendInst *, uint64_t, 4 > SuspendFreqs
BasicBlock::iterator getInsertPtAfterFramePtr() const
SmallVector< CoroIsInRampInst *, 2 > CoroIsInRampInsts
LLVM_ABI 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
SmallVector< AnyCoroEndInst *, 4 > CoroEnds
SmallVector< CallInst *, 2 > SwiftErrorOps