73#include <initializer_list>
78#define DEBUG_TYPE "coro-split"
110 Value *NewFramePtr =
nullptr;
120 : OrigF(OrigF), NewF(
nullptr), Suffix(Suffix), Shape(Shape),
128 : OrigF(OrigF), NewF(NewF), Suffix(Suffix), Shape(Shape),
129 FKind(Shape.
ABI == coro::ABI::Async ? Kind::Async : Kind::Continuation),
130 Builder(OrigF.
getContext()), ActiveSuspend(ActiveSuspend) {
132 Shape.
ABI == coro::ABI::RetconOnce || Shape.
ABI == coro::ABI::Async);
133 assert(NewF &&
"need existing function for continuation");
134 assert(ActiveSuspend &&
"need active suspend point for continuation");
138 assert(NewF !=
nullptr &&
"declaration not yet set");
145 bool isSwitchDestroyFunction() {
148 case Kind::Continuation:
149 case Kind::SwitchResume:
151 case Kind::SwitchUnwind:
152 case Kind::SwitchCleanup:
158 void replaceEntryBlock();
159 Value *deriveNewFramePointer();
160 void replaceRetconOrAsyncSuspendUses();
161 void replaceCoroSuspends();
162 void replaceCoroEnds();
165 void handleFinalSuspend();
174 Shape.
ABI == coro::ABI::RetconOnce);
187 auto *EndAsync = dyn_cast<CoroAsyncEndInst>(
End);
193 auto *MustTailCallFunc = EndAsync->getMustTailCallFunction();
194 if (!MustTailCallFunc) {
200 auto *CoroEndBlock =
End->getParent();
201 auto *MustTailCallFuncBlock = CoroEndBlock->getSinglePredecessor();
202 assert(MustTailCallFuncBlock &&
"Must have a single predecessor block");
203 auto It = MustTailCallFuncBlock->getTerminator()->getIterator();
204 auto *MustTailCall = cast<CallInst>(&*std::prev(It));
205 CoroEndBlock->splice(
End->getIterator(), MustTailCallFuncBlock,
206 MustTailCall->getIterator());
214 auto *BB =
End->getParent();
215 BB->splitBasicBlock(
End);
216 BB->getTerminator()->eraseFromParent();
219 assert(InlineRes.isSuccess() &&
"Expected inlining to succeed");
236 case coro::ABI::Switch:
237 assert(!cast<CoroEndInst>(
End)->hasResults() &&
238 "switch coroutine should not return any values");
247 case coro::ABI::Async: {
249 if (!CoroEndBlockNeedsCleanup)
256 case coro::ABI::RetconOnce: {
258 auto *CoroEnd = cast<CoroEndInst>(
End);
261 if (!CoroEnd->hasResults()) {
267 auto *CoroResults = CoroEnd->getResults();
268 unsigned NumReturns = CoroResults->numReturns();
270 if (
auto *RetStructTy = dyn_cast<StructType>(
RetTy)) {
271 assert(RetStructTy->getNumElements() == NumReturns &&
272 "numbers of returns should match resume function singature");
275 for (
Value *RetValEl : CoroResults->return_values())
278 }
else if (NumReturns == 0) {
283 Builder.
CreateRet(*CoroResults->retval_begin());
286 CoroResults->eraseFromParent();
292 case coro::ABI::Retcon: {
293 assert(!cast<CoroEndInst>(
End)->hasResults() &&
294 "retcon coroutine should not return any values");
297 auto RetStructTy = dyn_cast<StructType>(
RetTy);
299 cast<PointerType>(RetStructTy ? RetStructTy->getElementType(0) :
RetTy);
312 auto *BB =
End->getParent();
313 BB->splitBasicBlock(
End);
314 BB->getTerminator()->eraseFromParent();
328 Shape.
ABI == coro::ABI::Switch &&
329 "markCoroutineAsDone is only supported for Switch-Resumed ABI for now.");
348 "The final suspend should only live in the last position of "
366 case coro::ABI::Switch: {
379 case coro::ABI::Async:
382 case coro::ABI::Retcon:
383 case coro::ABI::RetconOnce:
390 auto *FromPad = cast<CleanupPadInst>(Bundle->Inputs[0]);
392 End->getParent()->splitBasicBlock(
End);
393 CleanupRet->getParent()->getTerminator()->eraseFromParent();
407 End->eraseFromParent();
439 size_t SuspendIndex = 0;
441 auto *S = cast<CoroSuspendInst>(AnyS);
447 auto *Save = S->getCoroSave();
460 Save->eraseFromParent();
485 auto *SuspendBB = S->getParent();
487 SuspendBB->splitBasicBlock(S,
"resume." +
Twine(SuspendIndex));
488 auto *LandingBB = ResumeBB->splitBasicBlock(
489 S->getNextNode(), ResumeBB->getName() +
Twine(
".landing"));
490 Switch->addCase(IndexVal, ResumeBB);
492 cast<BranchInst>(SuspendBB->getTerminator())->setSuccessor(0, LandingBB);
494 PN->insertBefore(LandingBB->begin());
495 S->replaceAllUsesWith(PN);
496 PN->addIncoming(Builder.
getInt8(-1), SuspendBB);
497 PN->addIncoming(S, ResumeBB);
517void CoroCloner::handleFinalSuspend() {
518 assert(Shape.ABI == coro::ABI::Switch &&
519 Shape.SwitchLowering.HasFinalSuspend);
521 if (isSwitchDestroyFunction() && Shape.SwitchLowering.HasUnwindCoroEnd)
524 auto *
Switch = cast<SwitchInst>(VMap[Shape.SwitchLowering.ResumeSwitch]);
525 auto FinalCaseIt = std::prev(
Switch->case_end());
526 BasicBlock *ResumeBB = FinalCaseIt->getCaseSuccessor();
527 Switch->removeCase(FinalCaseIt);
528 if (isSwitchDestroyFunction()) {
533 if (NewF->isCoroOnlyDestroyWhenComplete()) {
536 Builder.CreateBr(ResumeBB);
538 auto *GepIndex = Builder.CreateStructGEP(
542 Builder.CreateLoad(Shape.getSwitchResumePointerType(), GepIndex);
543 auto *
Cond = Builder.CreateIsNull(Load);
544 Builder.CreateCondBr(
Cond, ResumeBB, NewSwitchBB);
552 auto *AsyncSuspend = cast<CoroSuspendAsyncInst>(Suspend);
553 auto *StructTy = cast<StructType>(AsyncSuspend->getType());
556 return FunctionType::get(VoidTy, StructTy->elements(),
false);
564 auto *FnTy = (Shape.
ABI != coro::ABI::Async)
572 M->getFunctionList().insert(InsertBefore, NewF);
581void CoroCloner::replaceRetconOrAsyncSuspendUses() {
582 assert(Shape.ABI == coro::ABI::Retcon || Shape.ABI == coro::ABI::RetconOnce ||
583 Shape.ABI == coro::ABI::Async);
585 auto NewS = VMap[ActiveSuspend];
586 if (NewS->use_empty())
return;
592 bool IsAsyncABI = Shape.ABI == coro::ABI::Async;
593 for (
auto I = IsAsyncABI ? NewF->arg_begin() : std::next(NewF->arg_begin()),
600 if (!isa<StructType>(NewS->getType())) {
602 NewS->replaceAllUsesWith(
Args.front());
608 auto *EVI = dyn_cast<ExtractValueInst>(
U.getUser());
609 if (!EVI || EVI->getNumIndices() != 1)
612 EVI->replaceAllUsesWith(Args[EVI->getIndices().front()]);
613 EVI->eraseFromParent();
617 if (NewS->use_empty())
return;
621 for (
size_t I = 0,
E =
Args.size();
I !=
E; ++
I)
622 Agg = Builder.CreateInsertValue(Agg, Args[
I],
I);
627void CoroCloner::replaceCoroSuspends() {
628 Value *SuspendResult;
637 case coro::ABI::Switch:
638 SuspendResult = Builder.getInt8(isSwitchDestroyFunction() ? 1 : 0);
642 case coro::ABI::Async:
648 case coro::ABI::RetconOnce:
649 case coro::ABI::Retcon:
655 if (CS == ActiveSuspend)
continue;
657 auto *MappedCS = cast<AnyCoroSuspendInst>(VMap[CS]);
658 MappedCS->replaceAllUsesWith(SuspendResult);
659 MappedCS->eraseFromParent();
663void CoroCloner::replaceCoroEnds() {
667 auto *NewCE = cast<AnyCoroEndInst>(VMap[CE]);
676 Value *CachedSlot =
nullptr;
677 auto getSwiftErrorSlot = [&](
Type *ValueTy) ->
Value * {
682 for (
auto &Arg :
F.args()) {
683 if (Arg.isSwiftError()) {
690 IRBuilder<> Builder(
F.getEntryBlock().getFirstNonPHIOrDbg());
699 auto MappedOp = VMap ? cast<CallInst>((*VMap)[
Op]) :
Op;
704 if (
Op->arg_empty()) {
705 auto ValueTy =
Op->getType();
706 auto Slot = getSwiftErrorSlot(ValueTy);
707 MappedResult = Builder.
CreateLoad(ValueTy, Slot);
710 auto Value = MappedOp->getArgOperand(0);
712 auto Slot = getSwiftErrorSlot(ValueTy);
717 MappedOp->replaceAllUsesWith(MappedResult);
718 MappedOp->eraseFromParent();
722 if (VMap ==
nullptr) {
732 if (
auto *DVI = dyn_cast<DbgVariableIntrinsic>(&
I))
737void CoroCloner::replaceSwiftErrorOps() {
741void CoroCloner::salvageDebugInfo() {
756 auto IsUnreachableBlock = [&](
BasicBlock *BB) {
761 if (IsUnreachableBlock(DVI->getParent()))
762 DVI->eraseFromParent();
763 else if (isa_and_nonnull<AllocaInst>(DVI->getVariableLocationOp(0))) {
766 for (
auto *
User : DVI->getVariableLocationOp(0)->
users())
767 if (
auto *
I = dyn_cast<Instruction>(
User))
768 if (!isa<AllocaInst>(
I) && !IsUnreachableBlock(
I->getParent()))
771 DVI->eraseFromParent();
776void CoroCloner::replaceEntryBlock() {
782 auto *Entry = cast<BasicBlock>(VMap[Shape.AllocaSpillBlock]);
783 auto *OldEntry = &NewF->getEntryBlock();
784 Entry->setName(
"entry" + Suffix);
785 Entry->moveBefore(OldEntry);
786 Entry->getTerminator()->eraseFromParent();
791 assert(Entry->hasOneUse());
792 auto BranchToEntry = cast<BranchInst>(Entry->user_back());
793 assert(BranchToEntry->isUnconditional());
794 Builder.SetInsertPoint(BranchToEntry);
795 Builder.CreateUnreachable();
796 BranchToEntry->eraseFromParent();
799 Builder.SetInsertPoint(Entry);
801 case coro::ABI::Switch: {
805 cast<BasicBlock>(VMap[Shape.SwitchLowering.ResumeEntryBlock]);
806 Builder.CreateBr(SwitchBB);
809 case coro::ABI::Async:
810 case coro::ABI::Retcon:
811 case coro::ABI::RetconOnce: {
815 assert((Shape.ABI == coro::ABI::Async &&
816 isa<CoroSuspendAsyncInst>(ActiveSuspend)) ||
817 ((Shape.ABI == coro::ABI::Retcon ||
818 Shape.ABI == coro::ABI::RetconOnce) &&
819 isa<CoroSuspendRetconInst>(ActiveSuspend)));
820 auto *MappedCS = cast<AnyCoroSuspendInst>(VMap[ActiveSuspend]);
821 auto Branch = cast<BranchInst>(MappedCS->getNextNode());
823 Builder.CreateBr(
Branch->getSuccessor(0));
833 auto *Alloca = dyn_cast<AllocaInst>(&
I);
834 if (!Alloca ||
I.use_empty())
836 if (DT.isReachableFromEntry(
I.getParent()) ||
837 !isa<ConstantInt>(Alloca->getArraySize()))
839 I.moveBefore(*Entry, Entry->getFirstInsertionPt());
844Value *CoroCloner::deriveNewFramePointer() {
849 case coro::ABI::Switch:
850 return &*NewF->arg_begin();
856 case coro::ABI::Async: {
857 auto *ActiveAsyncSuspend = cast<CoroSuspendAsyncInst>(ActiveSuspend);
858 auto ContextIdx = ActiveAsyncSuspend->getStorageArgumentIndex() & 0xff;
859 auto *CalleeContext = NewF->getArg(ContextIdx);
860 auto *ProjectionFunc =
861 ActiveAsyncSuspend->getAsyncContextProjectionFunction();
863 cast<CoroSuspendAsyncInst>(VMap[ActiveSuspend])->getDebugLoc();
865 auto *CallerContext = Builder.CreateCall(ProjectionFunc->getFunctionType(),
866 ProjectionFunc, CalleeContext);
867 CallerContext->setCallingConv(ProjectionFunc->getCallingConv());
868 CallerContext->setDebugLoc(DbgLoc);
870 auto &
Context = Builder.getContext();
871 auto *FramePtrAddr = Builder.CreateConstInBoundsGEP1_32(
873 Shape.AsyncLowering.FrameOffset,
"async.ctx.frameptr");
877 assert(InlineRes.isSuccess());
882 case coro::ABI::Retcon:
883 case coro::ABI::RetconOnce: {
884 Argument *NewStorage = &*NewF->arg_begin();
885 auto FramePtrTy = PointerType::getUnqual(Shape.FrameTy->getContext());
888 if (Shape.RetconLowering.IsFrameInlineInStorage)
892 return Builder.CreateLoad(FramePtrTy, NewStorage);
900 Align Alignment,
bool NoAlias) {
910 Attrs = Attrs.addParamAttributes(
Context, ParamIndex, ParamAttrs);
914 unsigned ParamIndex) {
917 Attrs = Attrs.addParamAttributes(
Context, ParamIndex, ParamAttrs);
921 unsigned ParamIndex) {
924 Attrs = Attrs.addParamAttributes(
Context, ParamIndex, ParamAttrs);
929void CoroCloner::create() {
933 OrigF.getParent()->end(), ActiveSuspend);
944 VMap[&
A] = DummyArgs.
back();
951 auto savedVisibility = NewF->getVisibility();
952 auto savedUnnamedAddr = NewF->getUnnamedAddr();
953 auto savedDLLStorageClass = NewF->getDLLStorageClass();
958 auto savedLinkage = NewF->getLinkage();
962 CloneFunctionChangeType::LocalChangesOnly, Returns);
964 auto &
Context = NewF->getContext();
973 assert(SP != OrigF.getSubprogram() && SP->isDistinct());
975 if (
auto DL = ActiveSuspend->getDebugLoc())
976 if (SP->getFile() ==
DL->getFile())
977 SP->setScopeLine(
DL->getLine());
987 SP->getUnit()->getSourceLanguage() == dwarf::DW_LANG_Swift) {
988 SP->replaceLinkageName(
MDString::get(Context, NewF->getName()));
989 if (
auto *Decl = SP->getDeclaration()) {
990 auto *NewDecl = DISubprogram::get(
991 Decl->getContext(), Decl->getScope(), Decl->getName(),
992 NewF->getName(), Decl->getFile(), Decl->getLine(), Decl->getType(),
993 Decl->getScopeLine(), Decl->getContainingType(),
994 Decl->getVirtualIndex(), Decl->getThisAdjustment(),
995 Decl->getFlags(), Decl->getSPFlags(), Decl->getUnit(),
996 Decl->getTemplateParams(),
nullptr, Decl->getRetainedNodes(),
997 Decl->getThrownTypes(), Decl->getAnnotations(),
998 Decl->getTargetFuncName());
999 SP->replaceDeclaration(NewDecl);
1004 NewF->setLinkage(savedLinkage);
1005 NewF->setVisibility(savedVisibility);
1006 NewF->setUnnamedAddr(savedUnnamedAddr);
1007 NewF->setDLLStorageClass(savedDLLStorageClass);
1011 if (Shape.ABI == coro::ABI::Switch &&
1012 NewF->hasMetadata(LLVMContext::MD_func_sanitize))
1013 NewF->eraseMetadata(LLVMContext::MD_func_sanitize);
1016 auto OrigAttrs = NewF->getAttributes();
1019 switch (Shape.ABI) {
1020 case coro::ABI::Switch:
1023 NewAttrs = NewAttrs.addFnAttributes(
1024 Context,
AttrBuilder(Context, OrigAttrs.getFnAttrs()));
1027 Shape.FrameAlign,
false);
1029 case coro::ABI::Async: {
1030 auto *ActiveAsyncSuspend = cast<CoroSuspendAsyncInst>(ActiveSuspend);
1031 if (OrigF.hasParamAttribute(Shape.AsyncLowering.ContextArgNo,
1032 Attribute::SwiftAsync)) {
1034 ActiveAsyncSuspend->getStorageArgumentIndex();
1035 auto ContextArgIndex = ArgAttributeIndices & 0xff;
1040 auto SwiftSelfIndex = ArgAttributeIndices >> 8;
1046 auto FnAttrs = OrigF.getAttributes().getFnAttrs();
1047 NewAttrs = NewAttrs.addFnAttributes(Context,
AttrBuilder(Context, FnAttrs));
1050 case coro::ABI::Retcon:
1051 case coro::ABI::RetconOnce:
1054 NewAttrs = Shape.RetconLowering.ResumePrototype->getAttributes();
1058 Shape.getRetconCoroId()->getStorageSize(),
1059 Shape.getRetconCoroId()->getStorageAlignment(),
1065 switch (Shape.ABI) {
1070 case coro::ABI::Switch:
1071 case coro::ABI::RetconOnce:
1080 case coro::ABI::Retcon:
1086 case coro::ABI::Async:
1090 NewF->setAttributes(NewAttrs);
1091 NewF->setCallingConv(Shape.getResumeFunctionCC());
1094 replaceEntryBlock();
1096 Builder.SetInsertPoint(&NewF->getEntryBlock().front());
1097 NewFramePtr = deriveNewFramePointer();
1100 Value *OldFramePtr = VMap[Shape.FramePtr];
1101 NewFramePtr->
takeName(OldFramePtr);
1105 auto *NewVFrame = Builder.CreateBitCast(
1106 NewFramePtr, PointerType::getUnqual(Builder.getContext()),
"vFrame");
1107 Value *OldVFrame = cast<Value>(VMap[Shape.CoroBegin]);
1108 if (OldVFrame != NewVFrame)
1115 DummyArg->deleteValue();
1118 switch (Shape.ABI) {
1119 case coro::ABI::Switch:
1123 if (Shape.SwitchLowering.HasFinalSuspend)
1124 handleFinalSuspend();
1126 case coro::ABI::Async:
1127 case coro::ABI::Retcon:
1128 case coro::ABI::RetconOnce:
1131 assert(ActiveSuspend !=
nullptr &&
1132 "no active suspend when lowering a continuation-style coroutine");
1133 replaceRetconOrAsyncSuspendUses();
1138 replaceCoroSuspends();
1151 if (Shape.ABI == coro::ABI::Switch)
1153 FKind == CoroCloner::Kind::SwitchCleanup);
1161 CoroCloner Cloner(
F, Suffix, Shape, FKind);
1163 return Cloner.getFunction();
1169 auto *FuncPtrStruct = cast<ConstantStruct>(
1171 auto *OrigRelativeFunOffset = FuncPtrStruct->getOperand(0);
1172 auto *OrigContextSize = FuncPtrStruct->getOperand(1);
1176 FuncPtrStruct->getType(), OrigRelativeFunOffset, NewContextSize);
1182 if (Shape.
ABI == coro::ABI::Async)
1195 auto *SizeIntrin = Shape.
CoroSizes.back();
1196 Module *M = SizeIntrin->getModule();
1228 auto *ArrTy = ArrayType::get(Part->
getType(), Args.size());
1232 GlobalVariable::PrivateLinkage, ConstVal,
1233 F.getName() +
Twine(
".resumers"));
1253 Value *DestroyOrCleanupFn = DestroyFn;
1259 DestroyOrCleanupFn = Builder.
CreateSelect(CA, DestroyFn, CleanupFn);
1265 Builder.
CreateStore(DestroyOrCleanupFn, DestroyAddr);
1287 auto V = PN.getIncomingValueForBlock(PrevBB);
1289 auto VI = ResolvedValues.
find(V);
1290 if (VI != ResolvedValues.
end())
1293 ResolvedValues[&PN] = V;
1302 if (isa<ReturnInst>(InitialInst))
1312 if (isa<BitCastInst>(
I) ||
I->isDebugOrPseudoInst() ||
1313 I->isLifetimeStartOrEnd())
1314 I =
I->getNextNode();
1318 I = &*
I->eraseFromParent();
1325 auto TryResolveConstant = [&ResolvedValues](
Value *V) {
1326 auto It = ResolvedValues.
find(V);
1327 if (It != ResolvedValues.
end())
1329 return dyn_cast<ConstantInt>(V);
1333 while (
I->isTerminator() || isa<CmpInst>(
I)) {
1334 if (isa<ReturnInst>(
I)) {
1339 if (
auto *BR = dyn_cast<BranchInst>(
I)) {
1340 unsigned SuccIndex = 0;
1341 if (BR->isConditional()) {
1353 SuccIndex =
Cond->isOne() ? 0 : 1;
1356 BasicBlock *Succ = BR->getSuccessor(SuccIndex);
1363 if (
auto *CondCmp = dyn_cast<CmpInst>(
I)) {
1366 auto *BR = dyn_cast<BranchInst>(
1367 GetFirstValidInstruction(CondCmp->getNextNode()));
1368 if (!BR || !BR->isConditional() || CondCmp != BR->getCondition())
1374 ConstantInt *Cond0 = TryResolveConstant(CondCmp->getOperand(0));
1375 auto *Cond1 = dyn_cast<ConstantInt>(CondCmp->getOperand(1));
1376 if (!Cond0 || !Cond1)
1383 CondCmp->getPredicate(), Cond0, Cond1,
DL));
1387 ResolvedValues[BR->getCondition()] = ConstResult;
1394 if (
auto *SI = dyn_cast<SwitchInst>(
I)) {
1418 if (!CalleeTy->getReturnType()->isVoidTy() || (CalleeTy->getNumParams() != 1))
1421 Type *CalleeParmTy = CalleeTy->getParamType(0);
1431 Attribute::StructRet, Attribute::ByVal, Attribute::InAlloca,
1432 Attribute::Preallocated, Attribute::InReg, Attribute::Returned,
1433 Attribute::SwiftSelf, Attribute::SwiftError};
1435 for (
auto AK : ABIAttrs)
1436 if (Attrs.hasParamAttr(0, AK))
1448 bool changed =
false;
1453 if (
auto *Call = dyn_cast<CallInst>(&
I))
1474 auto *CoroId = CoroBegin->
getId();
1476 switch (Shape.
ABI) {
1477 case coro::ABI::Switch: {
1478 auto SwitchId = cast<CoroIdInst>(CoroId);
1484 AllocInst->replaceAllUsesWith(Builder.
getFalse());
1485 AllocInst->eraseFromParent();
1486 CoroBegin->replaceAllUsesWith(Frame);
1488 CoroBegin->replaceAllUsesWith(CoroBegin->getMem());
1493 case coro::ABI::Async:
1494 case coro::ABI::Retcon:
1495 case coro::ABI::RetconOnce:
1500 CoroBegin->eraseFromParent();
1509 if (isa<IntrinsicInst>(
I))
1512 if (isa<CallBase>(
I))
1528 while (!Worklist.
empty()) {
1538 Set.
erase(ResDesBB);
1540 for (
auto *BB : Set)
1549 auto *ResumeOrDestroyBB = ResumeOrDestroy->
getParent();
1551 if (SaveBB == ResumeOrDestroyBB)
1579 Prev = Pred->getTerminator();
1582 CallBase *CB = dyn_cast<CallBase>(Prev);
1589 auto *SubFn = dyn_cast<CoroSubFnInst>(Callee);
1594 if (SubFn->getFrame() != CoroBegin)
1608 Save->eraseFromParent();
1611 if (
auto *Invoke = dyn_cast<InvokeInst>(CB)) {
1620 if (CalledValue != SubFn && CalledValue->user_empty())
1621 if (
auto *
I = dyn_cast<Instruction>(CalledValue))
1622 I->eraseFromParent();
1625 if (SubFn->user_empty())
1626 SubFn->eraseFromParent();
1634 if (Shape.
ABI != coro::ABI::Switch)
1638 size_t I = 0,
N = S.size();
1642 size_t ChangedFinalIndex = std::numeric_limits<size_t>::max();
1644 auto SI = cast<CoroSuspendInst>(S[
I]);
1653 if (cast<CoroSuspendInst>(S[
I])->isFinal()) {
1655 ChangedFinalIndex =
I;
1667 if (ChangedFinalIndex <
N) {
1668 assert(cast<CoroSuspendInst>(S[ChangedFinalIndex])->isFinal());
1669 std::swap(S[ChangedFinalIndex], S.back());
1680 CoroCloner::Kind::SwitchResume);
1682 CoroCloner::Kind::SwitchUnwind);
1684 CoroCloner::Kind::SwitchCleanup);
1713 Value *Continuation) {
1716 auto *Int8PtrTy = PointerType::getUnqual(
Context);
1721 ResumeIntrinsic->eraseFromParent();
1731 for (
auto *paramTy : FnTy->params()) {
1733 if (paramTy != FnArgs[ArgIdx]->
getType())
1751 auto *TailCall = Builder.
CreateCall(FnTy, MustTailCallFn, CallArgs);
1753 TailCall->setDebugLoc(Loc);
1764 F.removeFnAttr(Attribute::NoReturn);
1765 F.removeRetAttr(Attribute::NoAlias);
1766 F.removeRetAttr(Attribute::NonNull);
1769 auto *Int8PtrTy = PointerType::getUnqual(
Context);
1778 "async.ctx.frameptr");
1789 auto NextF = std::next(
F.getIterator());
1797 auto ResumeNameSuffix =
".resume.";
1798 auto ProjectionFunctionName =
1799 Suspend->getAsyncContextProjectionFunction()->getName();
1800 bool UseSwiftMangling =
false;
1801 if (ProjectionFunctionName.equals(
"__swift_async_resume_project_context")) {
1802 ResumeNameSuffix =
"TQ";
1803 UseSwiftMangling =
true;
1804 }
else if (ProjectionFunctionName.equals(
1805 "__swift_async_resume_get_context")) {
1806 ResumeNameSuffix =
"TY";
1807 UseSwiftMangling =
true;
1811 UseSwiftMangling ? ResumeNameSuffix +
Twine(
Idx) +
"_"
1818 auto *SuspendBB = Suspend->getParent();
1819 auto *NewSuspendBB = SuspendBB->splitBasicBlock(Suspend);
1820 auto *Branch = cast<BranchInst>(SuspendBB->getTerminator());
1825 Branch->setSuccessor(0, ReturnBB);
1830 auto *Fn = Suspend->getMustTailCallFunction();
1839 assert(InlineRes.isSuccess() &&
"Expected inlining to succeed");
1849 auto *Clone = Clones[
Idx];
1851 CoroCloner(
F,
"resume." +
Twine(
Idx), Shape, Clone, Suspend).create();
1857 assert(Shape.
ABI == coro::ABI::Retcon ||
1858 Shape.
ABI == coro::ABI::RetconOnce);
1863 F.removeFnAttr(Attribute::NoReturn);
1864 F.removeRetAttr(Attribute::NoAlias);
1865 F.removeRetAttr(Attribute::NonNull);
1871 RawFramePtr = Id->getStorage();
1887 Builder.
CreateStore(RawFramePtr, Id->getStorage());
1903 auto NextF = std::next(
F.getIterator());
1907 for (
size_t i = 0, e = Shape.
CoroSuspends.size(); i != e; ++i) {
1908 auto Suspend = cast<CoroSuspendRetconInst>(Shape.
CoroSuspends[i]);
1917 auto SuspendBB = Suspend->getParent();
1918 auto NewSuspendBB = SuspendBB->splitBasicBlock(Suspend);
1919 auto Branch = cast<BranchInst>(SuspendBB->getTerminator());
1943 auto RetTy =
F.getReturnType();
1948 auto CastedContinuationTy =
1949 (ReturnPHIs.
size() == 1 ?
RetTy :
RetTy->getStructElementType(0));
1950 auto *CastedContinuation =
1954 if (ReturnPHIs.
size() == 1) {
1955 RetV = CastedContinuation;
1959 for (
size_t I = 1,
E = ReturnPHIs.
size();
I !=
E; ++
I)
1967 Branch->setSuccessor(0, ReturnBB);
1968 ReturnPHIs[0]->addIncoming(Continuation, SuspendBB);
1969 size_t NextPHIIndex = 1;
1970 for (
auto &VUse : Suspend->value_operands())
1971 ReturnPHIs[NextPHIIndex++]->addIncoming(&*VUse, SuspendBB);
1976 for (
size_t i = 0, e = Shape.
CoroSuspends.size(); i != e; ++i) {
1978 auto Clone = Clones[i];
1980 CoroCloner(
F,
"resume." +
Twine(i), Shape, Clone, Suspend).create();
1988 PrettyStackTraceFunction(
Function &F) :
F(
F) {}
1990 OS <<
"While splitting coroutine ";
1991 F.printAsOperand(
OS,
false,
F.getParent());
2000 std::function<
bool(
Instruction &)> MaterializableCallback) {
2001 PrettyStackTraceFunction prettyStackTrace(
F);
2012 buildCoroutineFrame(
F, Shape, MaterializableCallback);
2020 switch (Shape.
ABI) {
2021 case coro::ABI::Switch:
2024 case coro::ABI::Async:
2027 case coro::ABI::Retcon:
2028 case coro::ABI::RetconOnce:
2064 if (Shape.
ABI != coro::ABI::Switch)
2070 End->eraseFromParent();
2074 if (!Clones.
empty()) {
2075 switch (Shape.
ABI) {
2076 case coro::ABI::Switch:
2082 case coro::ABI::Async:
2083 case coro::ABI::Retcon:
2084 case coro::ABI::RetconOnce:
2087 if (!Clones.empty())
2116 auto *Cast = dyn_cast<BitCastInst>(U.getUser());
2117 if (!Cast || Cast->getType() != Fn->getType())
2121 Cast->replaceAllUsesWith(Fn);
2122 Cast->eraseFromParent();
2131 while (
auto *Cast = dyn_cast<BitCastInst>(CastFn)) {
2132 if (!Cast->use_empty())
2134 CastFn = Cast->getOperand(0);
2135 Cast->eraseFromParent();
2141 bool Changed =
false;
2144 auto *Prepare = cast<CallInst>(
P.getUser());
2155 auto *PrepareFn = M.getFunction(
Name);
2156 if (PrepareFn && !PrepareFn->use_empty())
2161 : MaterializableCallback(coro::defaultMaterializable),
2162 OptimizeFrame(OptimizeFrame) {}
2170 Module &M = *
C.begin()->getFunction().getParent();
2182 if (
N.getFunction().isPresplitCoroutine())
2185 if (Coroutines.
empty() && PrepareFns.
empty())
2188 if (Coroutines.
empty()) {
2189 for (
auto *PrepareFn : PrepareFns) {
2197 LLVM_DEBUG(
dbgs() <<
"CoroSplit: Processing coroutine '" <<
F.getName()
2199 F.setSplittedCoroutine();
2210 <<
"Split '" <<
ore::NV(
"function",
F.getName())
2211 <<
"' (frame_size=" <<
ore::NV(
"frame_size", Shape.FrameSize)
2212 <<
", align=" <<
ore::NV(
"align", Shape.FrameAlign.value()) <<
")";
2215 if (!Shape.CoroSuspends.empty()) {
2223 if (!PrepareFns.
empty()) {
2224 for (
auto *PrepareFn : PrepareFns) {
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
AMDGPU Lower Kernel Arguments
This file contains the simple types necessary to represent the attributes associated with functions a...
BlockVerifier::State From
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
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...
Remove calls to llvm coro end in the original static function void removeCoroEnds(const coro::Shape &Shape)
static void addSwiftSelfAttrs(AttributeList &Attrs, LLVMContext &Context, unsigned ParamIndex)
static void splitSwitchCoroutine(Function &F, coro::Shape &Shape, SmallVectorImpl< Function * > &Clones, TargetTransformInfo &TTI)
static bool hasCallsBetween(Instruction *Save, Instruction *ResumeOrDestroy)
static void replaceSwiftErrorOps(Function &F, coro::Shape &Shape, ValueToValueMapTy *VMap)
static void addAsyncContextAttrs(AttributeList &Attrs, LLVMContext &Context, unsigned ParamIndex)
static void addMustTailToCoroResumes(Function &F, TargetTransformInfo &TTI)
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 addPrepareFunction(const Module &M, SmallVectorImpl< Function * > &Fns, StringRef Name)
static void 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 simplifySuspendPoints(coro::Shape &Shape)
static void addFramePointerAttrs(AttributeList &Attrs, LLVMContext &Context, unsigned ParamIndex, uint64_t Size, Align Alignment, bool NoAlias)
static bool replaceAllPrepares(Function *PrepareFn, LazyCallGraph &CG, LazyCallGraph::SCC &C)
static void replaceFallthroughCoroEnd(AnyCoroEndInst *End, const coro::Shape &Shape, Value *FramePtr, bool InResume, CallGraph *CG)
Replace a non-unwind call to llvm.coro.end.
static void replaceFrameSizeAndAlignment(coro::Shape &Shape)
static SmallVector< DbgVariableIntrinsic *, 8 > collectDbgVariableIntrinsics(Function &F)
Returns all DbgVariableIntrinsic in F.
static bool replaceCoroEndAsync(AnyCoroEndInst *End)
Replace an llvm.coro.end.async.
Replace a call to llvm coro prepare static retcon void replacePrepare(CallInst *Prepare, LazyCallGraph &CG, LazyCallGraph::SCC &C)
static void replaceUnwindCoroEnd(AnyCoroEndInst *End, const coro::Shape &Shape, Value *FramePtr, bool InResume, CallGraph *CG)
Replace an unwind call to llvm.coro.end.
static bool simplifySuspendPoint(CoroSuspendInst *Suspend, CoroBeginInst *CoroBegin)
static bool hasCallsInBlockBetween(Instruction *From, Instruction *To)
static void markCoroutineAsDone(IRBuilder<> &Builder, const coro::Shape &Shape, Value *FramePtr)
static void splitAsyncCoroutine(Function &F, coro::Shape &Shape, SmallVectorImpl< Function * > &Clones)
static void updateAsyncFuncPointerContextSize(coro::Shape &Shape)
static void replaceCoroEnd(AnyCoroEndInst *End, const coro::Shape &Shape, Value *FramePtr, bool InResume, CallGraph *CG)
static void setCoroInfo(Function &F, coro::Shape &Shape, ArrayRef< Function * > Fns)
static void handleNoSuspendCoroutine(coro::Shape &Shape)
static void updateCoroFrame(coro::Shape &Shape, Function *ResumeFn, Function *DestroyFn, Function *CleanupFn)
static void createResumeEntryBlock(Function &F, coro::Shape &Shape)
static coro::Shape splitCoroutine(Function &F, SmallVectorImpl< Function * > &Clones, TargetTransformInfo &TTI, bool OptimizeFrame, std::function< bool(Instruction &)> MaterializableCallback)
static void postSplitCleanup(Function &F)
static bool simplifyTerminatorLeadingToRet(Instruction *InitialInst)
static void splitRetconCoroutine(Function &F, coro::Shape &Shape, SmallVectorImpl< Function * > &Clones)
static void scanPHIsAndUpdateValueMap(Instruction *Prev, BasicBlock *NewBlock, DenseMap< Value *, Value * > &ResolvedValues)
Coerce the arguments in p FnArgs according to p FnTy in p static CallArgs void coerceArguments(IRBuilder<> &Builder, FunctionType *FnTy, ArrayRef< Value * > FnArgs, SmallVectorImpl< Value * > &CallArgs)
static void replaceAsyncResumeFunction(CoroSuspendAsyncInst *Suspend, Value *Continuation)
static bool shouldBeMustTail(const CallInst &CI, const Function &F)
static Function * createClone(Function &F, const Twine &Suffix, coro::Shape &Shape, CoroCloner::Kind FKind)
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
This file defines the DenseMap class.
This file contains constants used for implementing Dwarf debug support.
static Function * getFunction(Constant *C)
Rewrite Partial Register Uses
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
Select target instructions out of generic instructions
Implements a lazy call graph analysis and related passes for the new pass manager.
Module.h This file contains the declarations for the Module class.
FunctionAnalysisManager FAM
This file provides a priority worklist.
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
static SymbolRef::Type getType(const Symbol *Sym)
static const unsigned FramePtr
void setSwiftError(bool V)
Specify whether this alloca is used to represent a swifterror.
void setAlignment(Align Align)
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
CoroAllocInst * getCoroAlloc()
This class represents an incoming formal argument to a Function.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
ArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
size_t size() const
size - Get the array size.
AttrBuilder & addAlignmentAttr(MaybeAlign Align)
This turns an alignment into the form used internally in Attribute.
AttrBuilder & addAttribute(Attribute::AttrKind Val)
Add an attribute to the builder.
AttrBuilder & addDereferenceableAttr(uint64_t Bytes)
This turns the number of dereferenceable bytes into the form used internally in Attribute.
AttrKind
This enumeration lists the attributes that can be associated with parameters, function results,...
LLVM Basic Block Representation.
iterator_range< const_phi_iterator > phis() const
Returns a range that iterates over the phis in the basic block.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="", bool Before=false)
Split the basic block into two basic blocks at the specified instruction.
const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
const Instruction * getFirstNonPHIOrDbgOrLifetime(bool SkipPseudoOp=true) const
Returns a pointer to the first instruction in this block that is not a PHINode, a debug intrinsic,...
const Function * getParent() const
Return the enclosing method, or null if none.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
static BranchInst * Create(BasicBlock *IfTrue, Instruction *InsertBefore=nullptr)
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
bool isInlineAsm() const
Check if this call is an inline asm statement.
CallingConv::ID getCallingConv() const
Value * getCalledOperand() const
Value * getArgOperand(unsigned i) const
FunctionType * getFunctionType() const
AttributeList getAttributes() const
Return the parameter attributes for this call.
The basic data container for the call graph of a Module of IR.
This class represents a function call, abstracting a target machine's calling convention.
static Constant * get(ArrayType *T, ArrayRef< Constant * > V)
static Constant * getPointerCast(Constant *C, Type *Ty)
Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant expression.
This is the shared class of boolean and integer constants.
static ConstantInt * getTrue(LLVMContext &Context)
static Constant * get(Type *Ty, uint64_t V, bool IsSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
static ConstantInt * getFalse(LLVMContext &Context)
static ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
static Constant * get(StructType *T, ArrayRef< Constant * > V)
static ConstantTokenNone * get(LLVMContext &Context)
Return the ConstantTokenNone.
This represents the llvm.coro.align instruction.
This represents the llvm.coro.alloc instruction.
This class represents the llvm.coro.begin instruction.
AnyCoroIdInst * getId() const
This represents the llvm.coro.id instruction.
void setInfo(Constant *C)
This represents the llvm.coro.size instruction.
This represents the llvm.coro.suspend.async instruction.
CoroAsyncResumeInst * getResumeFunction() const
This represents the llvm.coro.suspend instruction.
CoroSaveInst * getCoroSave() const
DISubprogram * getSubprogram() const
Get the subprogram for this scope.
This class represents an Operation in the Expression.
A parsed version of the target data layout string in and methods for querying it.
This is the common base class for debug info intrinsics for variables.
iterator find(const_arg_type_t< KeyT > Val)
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
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.
Type * getReturnType() const
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
FunctionType * getFunctionType() const
Returns the FunctionType for me.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Module * getParent()
Get the module that this global value is contained inside of...
PointerType * getType() const
Global values are always pointers.
@ ExternalLinkage
Externally visible function.
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
void setInitializer(Constant *InitVal)
setInitializer - Sets the initializer for this global variable, removing any existing initializer if ...
AllocaInst * CreateAlloca(Type *Ty, unsigned AddrSpace, Value *ArraySize=nullptr, const Twine &Name="")
Value * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &Name="")
UnreachableInst * CreateUnreachable()
Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
Value * CreateStructGEP(Type *Ty, Value *Ptr, unsigned Idx, const Twine &Name="")
Value * CreateConstInBoundsGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name="")
ConstantInt * getInt8(uint8_t C)
Get a constant 8-bit value.
CleanupReturnInst * CreateCleanupRet(CleanupPadInst *CleanupPad, BasicBlock *UnwindBB=nullptr)
ReturnInst * CreateRet(Value *V)
Create a 'ret <val>' instruction.
ConstantInt * getInt64(uint64_t C)
Get a constant 64-bit value.
Value * CreateBitOrPointerCast(Value *V, Type *DestTy, const Twine &Name="")
PHINode * CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name="")
SwitchInst * CreateSwitch(Value *V, BasicBlock *Dest, unsigned NumCases=10, MDNode *BranchWeights=nullptr, MDNode *Unpredictable=nullptr)
Create a switch instruction with the specified value, default dest, and with a hint for the number of...
Value * CreateBitCast(Value *V, Type *DestTy, 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...
ReturnInst * CreateRetVoid()
Create a 'ret void' instruction.
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
ConstantInt * getFalse()
Get the constant value for i1 false.
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args=std::nullopt, const Twine &Name="", MDNode *FPMathTag=nullptr)
IntegerType * getInt8Ty()
Fetch the type representing an 8-bit integer.
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 Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
const BasicBlock * getParent() const
InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
This is an important class for using LLVM in a threaded context.
A node in the call graph.
An SCC of the call graph.
A lazily constructed view of the call graph of a module.
void addSplitFunction(Function &OriginalFunction, Function &NewFunction)
Add a new function split/outlined from an existing function.
void addSplitRefRecursiveFunctions(Function &OriginalFunction, ArrayRef< Function * > NewFunctions)
Add new ref-recursive functions split/outlined from an existing function.
Node & get(Function &F)
Get a graph node for a given function, scanning it to populate the graph data as necessary.
SCC * lookupSCC(Node &N) const
Lookup a function's SCC in the graph.
static 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.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PrettyStackTraceEntry - This class is used to represent a frame of the "pretty" stack trace that is d...
virtual void print(raw_ostream &OS) const =0
print - Emit information about this stack frame to OS.
Return a value (possibly void), from a function.
bool erase(PtrType Ptr)
erase - If the set contains the specified pointer, remove it and return true, otherwise return false.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
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 push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Type * getTypeAtIndex(const Value *V) const
Given an index value into the type, return the type of the element.
Analysis pass providing the TargetTransformInfo.
Value handle that tracks a Value across RAUW.
ValueTy * getValPtr() const
Triple - Helper class for working with autoconf configuration names.
bool isArch64Bit() const
Test whether the architecture is 64-bit.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
bool isPointerTy() const
True if this is an instance of PointerType.
unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
static Type * getVoidTy(LLVMContext &C)
static IntegerType * getInt8Ty(LLVMContext &C)
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
A Use represents the edge between a Value definition and its users.
void setOperand(unsigned i, Value *Val)
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
iterator_range< use_iterator > uses()
StringRef getName() const
Return a constant reference to the value's name.
void takeName(Value *V)
Transfer the name from V to this value.
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
@ C
The default llvm calling convention, compatible with C.
@ Switch
The "resume-switch" lowering, where there are separate resume and destroy functions that are shared b...
void salvageDebugInfo(SmallDenseMap< Argument *, AllocaInst *, 4 > &ArgToAllocaMap, DbgVariableIntrinsic *DVI, bool OptimizeFrame, bool IsEntryPoint)
Attempts to rewrite the location operand of debug intrinsics in terms of the coroutine frame pointer,...
void replaceCoroFree(CoroIdInst *CoroId, bool Elide)
CallInst * createMustTailCall(DebugLoc Loc, Function *MustTailCallFn, ArrayRef< Value * > Arguments, IRBuilder<> &)
DiagnosticInfoOptimizationBase::Argument NV
This is an optimization pass for GlobalISel generic memory operations.
void ReplaceInstWithInst(BasicBlock *BB, BasicBlock::iterator &BI, Instruction *I)
Replace the instruction specified by BI with the instruction specified by I.
bool verifyFunction(const Function &F, raw_ostream *OS=nullptr)
Check a function for errors, useful for use when debugging a pass.
void salvageDebugInfo(const MachineRegisterInfo &MRI, MachineInstr &MI)
Assuming the instruction MI is going to be deleted, attempt to salvage debug users of MI by writing t...
LazyCallGraph::SCC & updateCGAndAnalysisManagerForFunctionPass(LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR, FunctionAnalysisManager &FAM)
Helper to update the call graph after running a function pass.
LazyCallGraph::SCC & updateCGAndAnalysisManagerForCGSCCPass(LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR, FunctionAnalysisManager &FAM)
Helper to update the call graph after running a CGSCC pass.
Constant * ConstantFoldCompareInstOperands(unsigned Predicate, Constant *LHS, Constant *RHS, const DataLayout &DL, const TargetLibraryInfo *TLI=nullptr, const Instruction *I=nullptr)
Attempt to constant fold a compare instruction (icmp/fcmp) with the specified operands.
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...
bool isInstructionTriviallyDead(Instruction *I, const TargetLibraryInfo *TLI=nullptr)
Return true if the result produced by the instruction is not used, and the instruction will return.
@ Async
"Asynchronous" unwind tables (instr precise)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
unsigned changeToUnreachable(Instruction *I, bool PreserveLCSSA=false, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Insert an unreachable instruction before the specified instruction, making it and the rest of the cod...
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
DWARFExpression::Operation Op
InlineResult InlineFunction(CallBase &CB, InlineFunctionInfo &IFI, bool MergeAttributes=false, AAResults *CalleeAAR=nullptr, bool InsertLifetime=true, Function *ForwardVarArgsTo=nullptr)
This function inlines the called function into the basic block of the caller.
void CloneFunctionInto(Function *NewFunc, const Function *OldFunc, ValueToValueMapTy &VMap, CloneFunctionChangeType Changes, SmallVectorImpl< ReturnInst * > &Returns, const char *NameSuffix="", ClonedCodeInfo *CodeInfo=nullptr, ValueMapTypeRemapper *TypeMapper=nullptr, ValueMaterializer *Materializer=nullptr)
Clone OldFunc into NewFunc, transforming the old arguments into references to VMap values.
auto predecessors(const MachineBasicBlock *BB)
bool removeUnreachableBlocks(Function &F, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Remove all blocks that can not be reached from the function's entry.
bool isPotentiallyReachable(const Instruction *From, const Instruction *To, const SmallPtrSetImpl< BasicBlock * > *ExclusionSet=nullptr, const DominatorTree *DT=nullptr, const LoopInfo *LI=nullptr)
Determine whether instruction 'To' is reachable from 'From', without passing through any blocks in Ex...
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
uint64_t value() const
This is a hole in the type system and should not be abused.
Support structure for SCC passes to communicate updates the call graph back to the CGSCC pass manager...
SmallPriorityWorklist< LazyCallGraph::SCC *, 1 > & CWorklist
Worklist of the SCCs queued for processing.
const std::function< bool(Instruction &)> MaterializableCallback
PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR)
CoroSplitPass(bool OptimizeFrame=false)
GlobalVariable * AsyncFuncPointer
bool IsFrameInlineInStorage
SwitchInst * ResumeSwitch
BasicBlock * ResumeEntryBlock
AsyncLoweringStorage AsyncLowering
FunctionType * getResumeFunctionType() const
IntegerType * getIndexType() const
CoroIdInst * getSwitchCoroId() const
Instruction * getInsertPtAfterFramePtr() const
SmallVector< CoroSizeInst *, 2 > CoroSizes
SmallVector< AnyCoroSuspendInst *, 4 > CoroSuspends
Value * emitAlloc(IRBuilder<> &Builder, Value *Size, CallGraph *CG) const
Allocate memory according to the rules of the active lowering.
SmallVector< CallInst *, 2 > SwiftErrorOps
ConstantInt * getIndex(uint64_t Value) const
bool OptimizeFrame
This would only be true if optimization are enabled.
SwitchLoweringStorage SwitchLowering
CoroBeginInst * CoroBegin
ArrayRef< Type * > getRetconResultTypes() const
void emitDealloc(IRBuilder<> &Builder, Value *Ptr, CallGraph *CG) const
Deallocate memory according to the rules of the active lowering.
RetconLoweringStorage RetconLowering
SmallVector< CoroAlignInst *, 2 > CoroAligns
SmallVector< AnyCoroEndInst *, 4 > CoroEnds
unsigned getSwitchIndexField() const