78#include <initializer_list>
83#define DEBUG_TYPE "coro-split"
95 Builder.SetInsertPoint(CB);
101 AttributeList NewAttributes =
106 Builder.CreateInvoke(
Wrapper, Invoke->getNormalDest(),
107 Invoke->getUnwindDest(), {Awaiter, FramePtr});
109 WrapperInvoke->setCallingConv(Invoke->getCallingConv());
110 std::copy(Invoke->bundle_op_info_begin(), Invoke->bundle_op_info_end(),
111 WrapperInvoke->bundle_op_info_begin());
112 WrapperInvoke->setAttributes(NewAttributes);
113 WrapperInvoke->setDebugLoc(Invoke->getDebugLoc());
114 NewCall = WrapperInvoke;
118 WrapperCall->setAttributes(NewAttributes);
119 WrapperCall->setDebugLoc(
Call->getDebugLoc());
120 NewCall = WrapperCall;
126 Intrinsic::coro_await_suspend_handle) {
131 Builder.SetInsertPoint(Invoke->getNormalDest()->getFirstInsertionPt());
136 &*Builder.GetInsertPoint());
141 auto *ResumeCall = Builder.CreateCall(ResumeTy, ResumeAddr, {NewCall});
147 NewCall = ResumeCall;
176 return Builder.CreateInBoundsPtrAdd(
FramePtr,
Offset,
"destroy.addr");
192 DestroyAddr,
"destroy");
196 EntryBuilder.
CreateICmpEQ(DestroyFn, CleanupFn,
"is.elided");
208 Builder.CreateSelect(IsElided,
Null,
FramePtr,
"coro.free");
210 CF->eraseFromParent();
222 Builder.CreateRetVoid();
226 auto *MustTailCallFunc = EndAsync->getMustTailCallFunction();
227 if (!MustTailCallFunc) {
228 Builder.CreateRetVoid();
234 auto *MustTailCallFuncBlock = CoroEndBlock->getSinglePredecessor();
235 assert(MustTailCallFuncBlock &&
"Must have a single predecessor block");
236 auto It = MustTailCallFuncBlock->getTerminator()->getIterator();
238 CoroEndBlock->splice(End->
getIterator(), MustTailCallFuncBlock,
239 MustTailCall->getIterator());
242 Builder.SetInsertPoint(End);
243 Builder.CreateRetVoid();
248 BB->splitBasicBlock(End);
249 BB->getTerminator()->eraseFromParent();
252 assert(InlineRes.isSuccess() &&
"Expected inlining to succeed");
271 "switch coroutine should not return any values");
276 Builder.CreateRetVoid();
282 if (!CoroEndBlockNeedsCleanup)
294 if (!CoroEnd->hasResults()) {
295 assert(RetTy->isVoidTy());
296 Builder.CreateRetVoid();
300 auto *CoroResults = CoroEnd->getResults();
301 unsigned NumReturns = CoroResults->numReturns();
304 assert(RetStructTy->getNumElements() == NumReturns &&
305 "numbers of returns should match resume function singature");
308 for (
Value *RetValEl : CoroResults->return_values())
309 ReturnValue = Builder.CreateInsertValue(ReturnValue, RetValEl, Idx++);
310 Builder.CreateRet(ReturnValue);
311 }
else if (NumReturns == 0) {
312 assert(RetTy->isVoidTy());
313 Builder.CreateRetVoid();
316 Builder.CreateRet(*CoroResults->retval_begin());
318 CoroResults->replaceAllUsesWith(
320 CoroResults->eraseFromParent();
328 "retcon coroutine should not return any values");
340 Builder.CreateRet(ReturnValue);
347 BB->splitBasicBlock(End);
348 BB->getTerminator()->eraseFromParent();
356 return Builder.CreateInBoundsPtrAdd(
FramePtr,
Offset,
"index.addr");
371 "markCoroutineAsDone is only supported for Switch-Resumed ABI for now.");
374 Builder.CreateStore(NullPtr,
FramePtr);
387 "The final suspend should only live in the last position of "
391 Builder.CreateStore(IndexVal, FinalIndex);
427 auto *CleanupRet = Builder.CreateCleanupRet(FromPad,
nullptr);
429 CleanupRet->getParent()->getTerminator()->eraseFromParent();
453 Shape.SwitchLowering.HasFinalSuspend);
459 auto FinalCaseIt = std::prev(
Switch->case_end());
460 BasicBlock *ResumeBB = FinalCaseIt->getCaseSuccessor();
471 if (
NewF->isCoroOnlyDestroyWhenComplete()) {
480 auto *Br =
Builder.CreateCondBr(
Cond, ResumeBB, NewSwitchBB);
494 auto &Context = Suspend->
getParent()->getParent()->getContext();
512 M->getFunctionList().insert(InsertBefore, NewF);
526 if (NewS->use_empty())
534 for (
auto I = IsAsyncABI ?
NewF->arg_begin() : std::next(
NewF->arg_begin()),
543 NewS->replaceAllUsesWith(Args.front());
550 if (!EVI || EVI->getNumIndices() != 1)
553 EVI->replaceAllUsesWith(Args[EVI->getIndices().front()]);
554 EVI->eraseFromParent();
558 if (NewS->use_empty())
564 Aggr =
Builder.CreateInsertValue(Aggr, Arg, Idx);
566 NewS->replaceAllUsesWith(Aggr);
570 Value *SuspendResult;
601 MappedCS->replaceAllUsesWith(SuspendResult);
602 MappedCS->eraseFromParent();
616 auto &Ctx =
OrigF.getContext();
617 for (
auto *
II :
Shape.CoroIsInRampInsts) {
620 NewII->eraseFromParent();
628 Value *CachedSlot =
nullptr;
629 auto getSwiftErrorSlot = [&](
Type *ValueTy) ->
Value * {
634 for (
auto &Arg :
F.args()) {
635 if (Arg.isSwiftError()) {
643 F.getEntryBlock().getFirstNonPHIOrDbg());
644 auto Alloca = Builder.CreateAlloca(ValueTy);
645 Alloca->setSwiftError(
true);
657 if (
Op->arg_empty()) {
658 auto ValueTy =
Op->getType();
659 auto Slot = getSwiftErrorSlot(ValueTy);
660 MappedResult = Builder.CreateLoad(ValueTy, Slot);
663 auto Value = MappedOp->getArgOperand(0);
665 auto Slot = getSwiftErrorSlot(ValueTy);
666 Builder.CreateStore(
Value, Slot);
671 MappedOp->eraseFromParent();
675 if (VMap ==
nullptr) {
688 return DbgVariableRecords;
700 bool UseEntryValue =
OrigF.getParent()->getTargetTriple().isArch64Bit();
707 auto IsUnreachableBlock = [&](
BasicBlock *BB) {
712 if (IsUnreachableBlock(DVI->getParent()))
713 DVI->eraseFromParent();
717 for (
auto *
User : DVI->getVariableLocationOp(0)->
users())
722 DVI->eraseFromParent();
725 for_each(DbgVariableRecords, RemoveOne);
735 auto *OldEntry = &
NewF->getEntryBlock();
736 Entry->setName(
"entry" +
Suffix);
737 Entry->moveBefore(OldEntry);
738 Entry->getTerminator()->eraseFromParent();
743 assert(Entry->hasOneUse());
745 Builder.SetInsertPoint(BranchToEntry);
747 BranchToEntry->eraseFromParent();
758 SwitchBB->moveAfter(Entry);
774 Builder.CreateBr(Branch->getSuccessor(0));
785 if (!Alloca ||
I.use_empty())
790 I.moveBefore(*Entry, Entry->getFirstInsertionPt());
801 return &*
NewF->arg_begin();
809 auto ContextIdx = ActiveAsyncSuspend->getStorageArgumentIndex() & 0xff;
810 auto *CalleeContext =
NewF->getArg(ContextIdx);
811 auto *ProjectionFunc =
812 ActiveAsyncSuspend->getAsyncContextProjectionFunction();
816 auto *CallerContext =
Builder.CreateCall(ProjectionFunc->getFunctionType(),
817 ProjectionFunc, CalleeContext);
818 CallerContext->setCallingConv(ProjectionFunc->getCallingConv());
819 CallerContext->setDebugLoc(DbgLoc);
821 auto &Context =
Builder.getContext();
822 auto *FramePtrAddr =
Builder.CreateInBoundsPtrAdd(
825 Shape.AsyncLowering.FrameOffset),
826 "async.ctx.frameptr");
830 assert(InlineRes.isSuccess());
841 if (
Shape.RetconLowering.IsFrameInlineInStorage)
845 return Builder.CreateLoad(FramePtrTy, NewStorage);
865 if (SPToUpdate.
getFile() ==
DL->getFile())
866 SPToUpdate.setScopeLine(
DL->getLine());
874 for (
unsigned Repeat = 0; Repeat < 2; Repeat++) {
878 Successor = Branch->getSuccessor()->getFirstNonPHIOrDbg();
887 if (!
DL ||
DL.getLine() == 0)
890 if (SPToUpdate.
getFile() ==
DL->getFile()) {
891 SPToUpdate.setScopeLine(
DL.getLine());
900 if (SPToUpdate.
getFile() ==
DL->getFile())
901 SPToUpdate.setScopeLine(
DL->getLine());
906 Align Alignment,
bool NoAlias) {
907 AttrBuilder ParamAttrs(Context);
908 ParamAttrs.addAttribute(Attribute::NonNull);
909 ParamAttrs.addAttribute(Attribute::NoUndef);
912 ParamAttrs.addAttribute(Attribute::NoAlias);
914 ParamAttrs.addAlignmentAttr(Alignment);
915 ParamAttrs.addDereferenceableAttr(
Size);
916 Attrs = Attrs.addParamAttributes(Context, ParamIndex, ParamAttrs);
920 unsigned ParamIndex) {
921 AttrBuilder ParamAttrs(Context);
922 ParamAttrs.addAttribute(Attribute::SwiftAsync);
923 Attrs = Attrs.addParamAttributes(Context, ParamIndex, ParamAttrs);
927 unsigned ParamIndex) {
928 AttrBuilder ParamAttrs(Context);
929 ParamAttrs.addAttribute(Attribute::SwiftSelf);
930 Attrs = Attrs.addParamAttributes(Context, ParamIndex, ParamAttrs);
953 auto savedVisibility =
NewF->getVisibility();
954 auto savedUnnamedAddr =
NewF->getUnnamedAddr();
955 auto savedDLLStorageClass =
NewF->getDLLStorageClass();
960 auto savedLinkage =
NewF->getLinkage();
966 auto &Context =
NewF->getContext();
969 assert(SP !=
OrigF.getSubprogram() && SP->isDistinct());
975 SP->replaceLinkageName(NewLinkageName);
977 TempDISubprogram NewDecl = Decl->clone();
978 NewDecl->replaceLinkageName(NewLinkageName);
983 NewF->setLinkage(savedLinkage);
984 NewF->setVisibility(savedVisibility);
985 NewF->setUnnamedAddr(savedUnnamedAddr);
986 NewF->setDLLStorageClass(savedDLLStorageClass);
991 NewF->hasMetadata(LLVMContext::MD_func_sanitize))
992 NewF->eraseMetadata(LLVMContext::MD_func_sanitize);
995 auto OrigAttrs =
NewF->getAttributes();
996 auto NewAttrs = AttributeList();
1002 NewAttrs = NewAttrs.addFnAttributes(
1003 Context, AttrBuilder(Context, OrigAttrs.getFnAttrs()));
1006 Shape.FrameAlign,
false);
1010 if (
OrigF.hasParamAttribute(
Shape.AsyncLowering.ContextArgNo,
1011 Attribute::SwiftAsync)) {
1013 ActiveAsyncSuspend->getStorageArgumentIndex();
1014 auto ContextArgIndex = ArgAttributeIndices & 0xff;
1019 auto SwiftSelfIndex = ArgAttributeIndices >> 8;
1025 auto FnAttrs =
OrigF.getAttributes().getFnAttrs();
1026 NewAttrs = NewAttrs.addFnAttributes(Context, AttrBuilder(Context, FnAttrs));
1033 NewAttrs =
Shape.RetconLowering.ResumePrototype->getAttributes();
1037 Shape.getRetconCoroId()->getStorageSize(),
1038 Shape.getRetconCoroId()->getStorageAlignment(),
1044 switch (
Shape.ABI) {
1069 NewF->setAttributes(NewAttrs);
1070 NewF->setCallingConv(
Shape.getResumeFunctionCC());
1078 if (
TTI.supportsTailCallFor(ResumeCall)) {
1093 Builder.SetInsertPoint(&
NewF->getEntryBlock().front());
1102 auto *NewVFrame =
Builder.CreateBitCast(
1105 if (OldVFrame != NewVFrame)
1112 DummyArg->deleteValue();
1115 switch (
Shape.ABI) {
1120 if (
Shape.SwitchLowering.HasFinalSuspend)
1129 "no active suspend when lowering a continuation-style coroutine");
1160 Shape.ResumeEntryCount.has_value()) {
1161 NewF->setEntryCount(
Shape.ResumeEntryCount.value());
1174 auto *OrigRelativeFunOffset = FuncPtrStruct->getOperand(0);
1175 auto *OrigContextSize = FuncPtrStruct->getOperand(1);
1176 auto *NewContextSize = ConstantInt::get(OrigContextSize->getType(),
1179 FuncPtrStruct->getType(), OrigRelativeFunOffset, NewContextSize);
1198 auto *SizeIntrin = Shape.
CoroSizes.back();
1199 auto *SizeConstant = ConstantInt::get(SizeIntrin->getType(),
1203 CS->replaceAllUsesWith(SizeConstant);
1204 CS->eraseFromParent();
1224 switch (Shape.
ABI) {
1233 auto *Frame = Builder.CreateAlloca(
1234 FrameTy,
nullptr, AllocInst->getFunction()->getName() +
".Frame");
1236 AllocInst->replaceAllUsesWith(Builder.getFalse());
1237 AllocInst->eraseFromParent();
1238 CoroBegin->replaceAllUsesWith(Frame);
1240 CoroBegin->replaceAllUsesWith(CoroBegin->getMem());
1281 while (!Worklist.
empty()) {
1285 if (!Set.contains(Pred))
1291 Set.erase(ResDesBB);
1293 for (
auto *BB : Set)
1302 auto *ResumeOrDestroyBB = ResumeOrDestroy->
getParent();
1306 if (SaveBB == ResumeOrDestroyBB)
1315 {ResumeOrDestroyBB->getFirstNonPHIIt(), ResumeOrDestroyIt}))
1331 auto *Pred = Suspend->
getParent()->getSinglePredecessor();
1334 Prev = Pred->getTerminator();
1349 if (SubFn->getFrame() != CoroBegin)
1363 Save->eraseFromParent();
1375 if (CalledValue != SubFn && CalledValue->user_empty())
1377 I->eraseFromParent();
1380 if (SubFn->user_empty())
1381 SubFn->eraseFromParent();
1393 size_t I = 0,
N = S.size();
1397 size_t ChangedFinalIndex = std::numeric_limits<size_t>::max();
1410 ChangedFinalIndex =
I;
1422 if (ChangedFinalIndex <
N) {
1424 std::swap(S[ChangedFinalIndex], S.back());
1430struct SwitchCoroutineSplitter {
1431 static void split(Function &
F, coro::Shape &Shape,
1432 SmallVectorImpl<Function *> &Clones,
1433 TargetTransformInfo &
TTI) {
1439 createResumeEntryBlock(
F, Shape);
1441 F,
".resume", Shape, coro::CloneKind::SwitchResume,
TTI);
1443 F,
".destroy", Shape, coro::CloneKind::SwitchUnwind,
TTI);
1445 F,
".cleanup", Shape, coro::CloneKind::SwitchCleanup,
TTI);
1455 updateCoroFrame(Shape, ResumeClone, DestroyClone, CleanupClone);
1465 setCoroInfo(
F, Shape, Clones);
1475 static Function *createNoAllocVariant(Function &
F, coro::Shape &Shape,
1476 SmallVectorImpl<Function *> &Clones) {
1478 auto *OrigFnTy =
F.getFunctionType();
1479 auto OldParams = OrigFnTy->params();
1482 NewParams.
reserve(OldParams.size() + 1);
1483 NewParams.
append(OldParams.begin(), OldParams.end());
1486 auto *NewFnTy = FunctionType::get(OrigFnTy->getReturnType(), NewParams,
1487 OrigFnTy->isVarArg());
1489 NewFnTy,
F.getLinkage(),
F.getAddressSpace(),
F.getName() +
".noalloc");
1492 unsigned int Idx = 0;
1493 for (
const auto &
I :
F.args()) {
1494 VMap[&
I] = NoAllocF->
getArg(Idx++);
1498 auto FrameIdx = NoAllocF->
arg_size() - 1;
1501 CloneFunctionChangeType::LocalChangesOnly, Returns);
1504 auto *NewCoroBegin =
1508 NewCoroBegin->replaceAllUsesWith(NoAllocF->
getArg(FrameIdx));
1509 NewCoroBegin->eraseFromParent();
1513 M->getFunctionList().insert(
M->end(), NoAllocF);
1528 setCoroInfo(
F, Shape, Clones);
1539 static void createResumeEntryBlock(Function &
F, coro::Shape &Shape) {
1542 DIBuilder DBuilder(*
F.getParent(),
false);
1543 DISubprogram *DIS =
F.getSubprogram();
1547 bool AddDebugLabels = DIS && DIS->getUnit() &&
1548 (DIS->getUnit()->getEmissionKind() ==
1549 DICompileUnit::DebugEmissionKind::FullDebug);
1568 Builder.CreateSwitch(Index, UnreachBB, Shape.
CoroSuspends.size());
1572 size_t SuspendIndex = 0;
1573 SmallVector<uint64_t, 8> SwitchWeights64;
1579 ConstantInt *IndexVal = Shape.
getIndex(SuspendIndex);
1584 auto *Save = S->getCoroSave();
1585 Builder.SetInsertPoint(Save);
1592 Builder.CreateStore(IndexVal, GepIndex);
1596 Save->eraseFromParent();
1622 auto *SuspendBB = S->getParent();
1624 SuspendBB->splitBasicBlock(S,
"resume." + Twine(SuspendIndex));
1625 auto *LandingBB = ResumeBB->splitBasicBlock(
1626 S->getNextNode(), ResumeBB->getName() + Twine(
".landing"));
1627 Switch->addCase(IndexVal, ResumeBB);
1630 uint64_t Weight = 1;
1633 Weight = It->second;
1639 PN->insertBefore(LandingBB->begin());
1640 S->replaceAllUsesWith(PN);
1641 PN->addIncoming(Builder.getInt8(-1), SuspendBB);
1642 PN->addIncoming(S, ResumeBB);
1644 if (AddDebugLabels) {
1645 if (
DebugLoc SuspendLoc = S->getDebugLoc()) {
1646 std::string LabelName =
1647 (
"__coro_resume_" + Twine(SuspendIndex)).str();
1653 DILocation *DILoc = SuspendLoc;
1654 while (DILocation *InlinedAt = DILoc->getInlinedAt())
1657 DILabel *ResumeLabel =
1658 DBuilder.createLabel(DIS, LabelName, DILoc->getFile(),
1659 SuspendLoc.getLine(), SuspendLoc.getCol(),
1663 DBuilder.insertLabel(ResumeLabel, DILoc, ResumeBB->begin());
1673 Switch->setMetadata(LLVMContext::MD_prof,
1674 MDB.createBranchWeights(SwitchWeights32));
1677 Builder.SetInsertPoint(UnreachBB);
1678 Builder.CreateUnreachable();
1679 DBuilder.finalize();
1685 static void updateCoroFrame(coro::Shape &Shape, Function *ResumeFn,
1686 Function *DestroyFn, Function *CleanupFn) {
1692 Builder.CreateStore(ResumeFn, ResumeAddr);
1694 Value *DestroyOrCleanupFn = DestroyFn;
1700 DestroyOrCleanupFn = Builder.CreateSelect(CA, DestroyFn, CleanupFn);
1708 Value *DestroyAddr = Builder.CreateInBoundsPtrAdd(
1710 ConstantInt::get(Type::getInt64Ty(
C),
1713 Builder.CreateStore(DestroyOrCleanupFn, DestroyAddr);
1729 static void setCoroInfo(Function &
F, coro::Shape &Shape,
1733 SmallVector<Constant *, 4>
Args(Fns);
1737 auto *ArrTy = ArrayType::get(Part->
getType(),
Args.size());
1740 auto *GV =
new GlobalVariable(*M, ConstVal->getType(),
true,
1741 GlobalVariable::PrivateLinkage, ConstVal,
1742 F.getName() + Twine(
".resumers"));
1745 LLVMContext &
C =
F.getContext();
1756 auto &Context = Suspend->
getParent()->getParent()->getContext();
1760 auto *Val = Builder.CreateBitOrPointerCast(
Continuation, Int8PtrTy);
1761 ResumeIntrinsic->replaceAllUsesWith(Val);
1762 ResumeIntrinsic->eraseFromParent();
1772 for (
auto *paramTy : FnTy->params()) {
1774 if (paramTy != FnArgs[ArgIdx]->
getType())
1776 Builder.CreateBitOrPointerCast(FnArgs[ArgIdx], paramTy));
1793 auto *TailCall = Builder.CreateCall(FnTy, MustTailCallFn, CallArgs);
1795 if (
TTI.supportsTailCallFor(TailCall)) {
1798 TailCall->setDebugLoc(
Loc);
1810 F.removeFnAttr(Attribute::NoReturn);
1811 F.removeRetAttr(Attribute::NoAlias);
1812 F.removeRetAttr(Attribute::NonNull);
1814 auto &Context =
F.getContext();
1817 auto *Id =
Shape.getAsyncCoroId();
1822 FramePtr = Builder.CreateInBoundsPtrAdd(
1825 Shape.AsyncLowering.FrameOffset),
1826 "async.ctx.frameptr");
1837 auto NextF = std::next(
F.getIterator());
1845 auto ResumeNameSuffix =
".resume.";
1846 auto ProjectionFunctionName =
1847 Suspend->getAsyncContextProjectionFunction()->getName();
1848 bool UseSwiftMangling =
false;
1849 if (ProjectionFunctionName ==
"__swift_async_resume_project_context") {
1850 ResumeNameSuffix =
"TQ";
1851 UseSwiftMangling =
true;
1852 }
else if (ProjectionFunctionName ==
"__swift_async_resume_get_context") {
1853 ResumeNameSuffix =
"TY";
1854 UseSwiftMangling =
true;
1858 UseSwiftMangling ? ResumeNameSuffix +
Twine(Idx) +
"_"
1859 : ResumeNameSuffix +
Twine(Idx),
1865 auto *SuspendBB = Suspend->getParent();
1866 auto *NewSuspendBB = SuspendBB->splitBasicBlock(Suspend);
1872 Branch->setSuccessor(0, ReturnBB);
1877 auto *Fn = Suspend->getMustTailCallFunction();
1883 Builder.CreateRetVoid();
1895 auto *Clone = Clones[Idx];
1910 F.removeFnAttr(Attribute::NoReturn);
1911 F.removeRetAttr(Attribute::NoAlias);
1912 F.removeRetAttr(Attribute::NonNull);
1915 auto *Id =
Shape.getRetconCoroId();
1917 if (
Shape.RetconLowering.IsFrameInlineInStorage) {
1918 RawFramePtr = Id->getStorage();
1922 auto FrameSize = Builder.getInt64(
Shape.FrameSize);
1927 RawFramePtr =
Shape.emitAlloc(Builder, FrameSize,
nullptr);
1929 Builder.CreateBitCast(RawFramePtr,
Shape.CoroBegin->getType());
1932 Builder.CreateStore(RawFramePtr, Id->getStorage());
1939 Shape.CoroBegin->replaceAllUsesWith(RawFramePtr);
1945 PHINode *ContinuationPhi =
nullptr;
1949 auto NextF = std::next(
F.getIterator());
1958 F,
Shape,
".resume." +
Twine(Idx), NextF,
nullptr);
1963 auto SuspendBB = Suspend->getParent();
1964 auto NewSuspendBB = SuspendBB->splitBasicBlock(Suspend);
1972 Shape.RetconLowering.ReturnBlock = ReturnBB;
1984 for (
auto *ResultTy :
Shape.getRetconResultTypes())
1986 Builder.CreatePHI(ResultTy,
Shape.CoroSuspends.size()));
1989 auto RetTy =
F.getReturnType();
1994 auto CastedContinuationTy =
1995 (ReturnPHIs.
empty() ? RetTy : RetTy->getStructElementType(0));
1996 auto *CastedContinuation =
1997 Builder.CreateBitCast(ContinuationPhi, CastedContinuationTy);
1999 Value *RetV = CastedContinuation;
2000 if (!ReturnPHIs.
empty()) {
2003 RetV = Builder.CreateInsertValue(RetV, CastedContinuation, ValueIdx++);
2005 for (
auto Phi : ReturnPHIs)
2006 RetV = Builder.CreateInsertValue(RetV, Phi, ValueIdx++);
2009 Builder.CreateRet(RetV);
2013 Branch->setSuccessor(0, ReturnBB);
2016 for (
auto [Phi, VUse] :
2018 Phi->addIncoming(VUse, SuspendBB);
2025 auto Clone = Clones[Idx];
2039 OS <<
"While splitting coroutine ";
2040 F.printAsOperand(OS,
false,
F.getParent());
2060 auto &Ctx =
II->getContext();
2062 II->eraseFromParent();
2067 for (
auto *U :
F.users()) {
2069 auto *Caller = CB->getFunction();
2070 if (Caller && Caller->isPresplitCoroutine() &&
2071 CB->hasFnAttr(llvm::Attribute::CoroElideSafe))
2081 SwitchCoroutineSplitter::split(
F,
Shape, Clones,
TTI);
2086 bool OptimizeFrame) {
2087 PrettyStackTraceFunction prettyStackTrace(
F);
2089 auto &Shape = ABI.
Shape;
2097 ABI.buildCoroutineFrame(OptimizeFrame);
2100 bool isNoSuspendCoroutine = Shape.
CoroSuspends.empty();
2102 bool shouldCreateNoAllocVariant =
2107 shouldCreateNoAllocVariant;
2111 if (isNoSuspendCoroutine) {
2114 ABI.splitCoroutine(
F, Shape, Clones,
TTI);
2132 if (shouldCreateNoAllocVariant)
2133 SwitchCoroutineSplitter::createNoAllocVariant(
F, Shape, Clones);
2142 auto *CurrentSCC = &
C;
2143 if (!Clones.
empty()) {
2144 switch (Shape.
ABI) {
2150 assert(Clones.
size() >= 3 &&
"expected switch coroutine clones");
2168 if (!Clones.
empty())
2201 if (!Cast || Cast->getType() != Fn->getType())
2205 Cast->replaceAllUsesWith(Fn);
2206 Cast->eraseFromParent();
2216 if (!Cast->use_empty())
2218 CastFn = Cast->getOperand(0);
2219 Cast->eraseFromParent();
2239 auto *PrepareFn = M.getFunction(Name);
2240 if (PrepareFn && !PrepareFn->use_empty())
2244static std::unique_ptr<coro::BaseABI>
2250 if (CustomABI >= GenCustomABIs.
size())
2252 return GenCustomABIs[CustomABI](
F, S);
2257 return std::make_unique<coro::SwitchABI>(
F, S, IsMatCallback);
2259 return std::make_unique<coro::AsyncABI>(
F, S, IsMatCallback);
2261 return std::make_unique<coro::AnyRetconABI>(
F, S, IsMatCallback);
2263 return std::make_unique<coro::AnyRetconABI>(
F, S, IsMatCallback);
2270 std::unique_ptr<coro::BaseABI> ABI =
2275 OptimizeFrame(OptimizeFrame) {}
2280 std::unique_ptr<coro::BaseABI> ABI =
2285 OptimizeFrame(OptimizeFrame) {}
2292 std::unique_ptr<coro::BaseABI> ABI =
2297 OptimizeFrame(OptimizeFrame) {}
2305 std::unique_ptr<coro::BaseABI> ABI =
2310 OptimizeFrame(OptimizeFrame) {}
2318 Module &M = *
C.begin()->getFunction().getParent();
2330 if (
N.getFunction().isPresplitCoroutine())
2333 if (Coroutines.
empty() && PrepareFns.
empty())
2336 auto *CurrentSCC = &
C;
2340 LLVM_DEBUG(
dbgs() <<
"CoroSplit: Processing coroutine '" <<
F.getName()
2352 F.setSplittedCoroutine();
2358 uint64_t Freq = BFI.getBlockFreq(BB).getFrequency();
2363 std::optional<uint64_t>
Count =
2364 BFI.getBlockProfileCount(BB,
true);
2365 if (
Count.has_value()) {
2383 *
N, Shape, Clones, *CurrentSCC, CG, AM, UR,
FAM);
2388 <<
"Split '" <<
ore::NV(
"function",
F.getName())
2405 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< 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 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.
const SmallVectorImpl< MachineOperand > & 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...
std::optional< OperandBundleUse > getOperandBundle(StringRef Name) const
Return an operand bundle by name, if present.
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....
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
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(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
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.
@ C
The default llvm calling convention, compatible with C.
@ 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.
auto dyn_cast_or_null(const Y &Val)
LLVM_ABI BasicBlock::iterator skipDebugIntrinsics(BasicBlock::iterator It)
Advance It while it points to a debug instruction and return the result.
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.
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.
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
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.
static auto filterDbgVars(iterator_range< simple_ilist< DbgRecord >::iterator > R)
Filter the DbgRecord range to DbgVariableRecord types only and downcast.
LLVM_ABI bool removeUnreachableBlocks(Function &F, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Remove all blocks that can not be reached from the function's entry.
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