72#include <initializer_list>
77#define DEBUG_TYPE "coro-split"
109 Value *NewFramePtr =
nullptr;
119 : OrigF(OrigF), NewF(
nullptr), Suffix(Suffix), Shape(Shape),
127 : OrigF(OrigF), NewF(NewF), Suffix(Suffix), Shape(Shape),
128 FKind(Shape.
ABI == coro::ABI::Async ? Kind::Async : Kind::Continuation),
131 Shape.
ABI == coro::ABI::RetconOnce || Shape.
ABI == coro::ABI::Async);
132 assert(NewF &&
"need existing function for continuation");
133 assert(ActiveSuspend &&
"need active suspend point for continuation");
137 assert(NewF !=
nullptr &&
"declaration not yet set");
144 bool isSwitchDestroyFunction() {
147 case Kind::Continuation:
148 case Kind::SwitchResume:
150 case Kind::SwitchUnwind:
151 case Kind::SwitchCleanup:
157 void replaceEntryBlock();
158 Value *deriveNewFramePointer();
159 void replaceRetconOrAsyncSuspendUses();
160 void replaceCoroSuspends();
161 void replaceCoroEnds();
164 void handleFinalSuspend();
173 Shape.
ABI == coro::ABI::RetconOnce);
186 auto *EndAsync = dyn_cast<CoroAsyncEndInst>(End);
192 auto *MustTailCallFunc = EndAsync->getMustTailCallFunction();
193 if (!MustTailCallFunc) {
199 auto *CoroEndBlock = End->getParent();
200 auto *MustTailCallFuncBlock = CoroEndBlock->getSinglePredecessor();
201 assert(MustTailCallFuncBlock &&
"Must have a single predecessor block");
202 auto It = MustTailCallFuncBlock->getTerminator()->getIterator();
203 auto *MustTailCall = cast<CallInst>(&*std::prev(It));
204 CoroEndBlock->splice(End->getIterator(), MustTailCallFuncBlock,
205 MustTailCall->getIterator());
213 auto *BB = End->getParent();
214 BB->splitBasicBlock(End);
215 BB->getTerminator()->eraseFromParent();
218 assert(InlineRes.isSuccess() &&
"Expected inlining to succeed");
235 case coro::ABI::Switch:
244 case coro::ABI::Async: {
246 if (!CoroEndBlockNeedsCleanup)
253 case coro::ABI::RetconOnce:
260 case coro::ABI::Retcon: {
263 auto RetStructTy = dyn_cast<StructType>(
RetTy);
265 cast<PointerType>(RetStructTy ? RetStructTy->getElementType(0) :
RetTy);
272 Builder.CreateRet(ReturnValue);
278 auto *BB = End->getParent();
279 BB->splitBasicBlock(End);
280 BB->getTerminator()->eraseFromParent();
294 Shape.
ABI == coro::ABI::Switch &&
295 "markCoroutineAsDone is only supported for Switch-Resumed ABI for now.");
296 auto *GepIndex =
Builder.CreateStructGEP(
301 Builder.CreateStore(NullPtr, GepIndex);
312 case coro::ABI::Switch: {
325 case coro::ABI::Async:
328 case coro::ABI::Retcon:
329 case coro::ABI::RetconOnce:
336 auto *FromPad = cast<CleanupPadInst>(Bundle->Inputs[0]);
337 auto *CleanupRet =
Builder.CreateCleanupRet(FromPad,
nullptr);
338 End->getParent()->splitBasicBlock(End);
339 CleanupRet->getParent()->getTerminator()->eraseFromParent();
350 auto &
Context = End->getContext();
353 End->eraseFromParent();
378 auto *GepIndex =
Builder.CreateStructGEP(
385 size_t SuspendIndex = 0;
387 auto *S = cast<CoroSuspendInst>(AnyS);
393 auto *Save = S->getCoroSave();
410 auto *GepIndex =
Builder.CreateStructGEP(
412 Builder.CreateStore(IndexVal, GepIndex);
416 Save->eraseFromParent();
441 auto *SuspendBB = S->getParent();
443 SuspendBB->splitBasicBlock(S,
"resume." +
Twine(SuspendIndex));
444 auto *LandingBB = ResumeBB->splitBasicBlock(
445 S->getNextNode(), ResumeBB->getName() +
Twine(
".landing"));
446 Switch->addCase(IndexVal, ResumeBB);
448 cast<BranchInst>(SuspendBB->getTerminator())->setSuccessor(0, LandingBB);
450 S->replaceAllUsesWith(PN);
451 PN->addIncoming(
Builder.getInt8(-1), SuspendBB);
452 PN->addIncoming(S, ResumeBB);
457 Builder.SetInsertPoint(UnreachBB);
472void CoroCloner::handleFinalSuspend() {
473 assert(Shape.ABI == coro::ABI::Switch &&
474 Shape.SwitchLowering.HasFinalSuspend);
476 if (isSwitchDestroyFunction() && Shape.SwitchLowering.HasUnwindCoroEnd)
479 auto *
Switch = cast<SwitchInst>(VMap[Shape.SwitchLowering.ResumeSwitch]);
480 auto FinalCaseIt = std::prev(
Switch->case_end());
481 BasicBlock *ResumeBB = FinalCaseIt->getCaseSuccessor();
482 Switch->removeCase(FinalCaseIt);
483 if (isSwitchDestroyFunction()) {
487 auto *GepIndex =
Builder.CreateStructGEP(Shape.FrameTy, NewFramePtr,
490 auto *
Load =
Builder.CreateLoad(Shape.getSwitchResumePointerType(),
500 auto *AsyncSuspend = cast<CoroSuspendAsyncInst>(Suspend);
501 auto *StructTy = cast<StructType>(AsyncSuspend->getType());
504 return FunctionType::get(VoidTy, StructTy->elements(),
false);
512 auto *FnTy = (Shape.
ABI != coro::ABI::Async)
520 M->getFunctionList().insert(InsertBefore, NewF);
529void CoroCloner::replaceRetconOrAsyncSuspendUses() {
530 assert(Shape.ABI == coro::ABI::Retcon || Shape.ABI == coro::ABI::RetconOnce ||
531 Shape.ABI == coro::ABI::Async);
533 auto NewS = VMap[ActiveSuspend];
534 if (NewS->use_empty())
return;
540 bool IsAsyncABI = Shape.ABI == coro::ABI::Async;
541 for (
auto I = IsAsyncABI ? NewF->arg_begin() : std::next(NewF->arg_begin()),
548 if (!isa<StructType>(NewS->getType())) {
550 NewS->replaceAllUsesWith(
Args.front());
556 auto *EVI = dyn_cast<ExtractValueInst>(U.getUser());
557 if (!EVI || EVI->getNumIndices() != 1)
560 EVI->replaceAllUsesWith(Args[EVI->getIndices().front()]);
561 EVI->eraseFromParent();
565 if (NewS->use_empty())
return;
569 for (
size_t I = 0,
E =
Args.size();
I !=
E; ++
I)
570 Agg =
Builder.CreateInsertValue(Agg, Args[
I],
I);
572 NewS->replaceAllUsesWith(Agg);
575void CoroCloner::replaceCoroSuspends() {
576 Value *SuspendResult;
585 case coro::ABI::Switch:
586 SuspendResult =
Builder.getInt8(isSwitchDestroyFunction() ? 1 : 0);
590 case coro::ABI::Async:
596 case coro::ABI::RetconOnce:
597 case coro::ABI::Retcon:
603 if (CS == ActiveSuspend)
continue;
605 auto *MappedCS = cast<AnyCoroSuspendInst>(VMap[CS]);
606 MappedCS->replaceAllUsesWith(SuspendResult);
607 MappedCS->eraseFromParent();
611void CoroCloner::replaceCoroEnds() {
615 auto *NewCE = cast<AnyCoroEndInst>(VMap[CE]);
624 Value *CachedSlot =
nullptr;
625 auto getSwiftErrorSlot = [&](
Type *ValueTy) ->
Value * {
628 ->isOpaqueOrPointeeTypeMatches(ValueTy) &&
629 "multiple swifterror slots in function with different types");
634 for (
auto &
Arg :
F.args()) {
635 if (
Arg.isSwiftError()) {
638 ->isOpaqueOrPointeeTypeMatches(ValueTy) &&
639 "swifterror argument does not have expected type");
646 auto Alloca =
Builder.CreateAlloca(ValueTy);
647 Alloca->setSwiftError(
true);
654 auto MappedOp = VMap ? cast<CallInst>((*VMap)[Op]) : Op;
659 if (Op->arg_empty()) {
660 auto ValueTy = Op->getType();
661 auto Slot = getSwiftErrorSlot(ValueTy);
662 MappedResult =
Builder.CreateLoad(ValueTy, Slot);
664 assert(Op->arg_size() == 1);
665 auto Value = MappedOp->getArgOperand(0);
667 auto Slot = getSwiftErrorSlot(ValueTy);
672 MappedOp->replaceAllUsesWith(MappedResult);
673 MappedOp->eraseFromParent();
677 if (VMap ==
nullptr) {
682void CoroCloner::replaceSwiftErrorOps() {
686void CoroCloner::salvageDebugInfo() {
689 for (
auto &BB : *NewF)
691 if (
auto *DVI = dyn_cast<DbgVariableIntrinsic>(&
I))
699 auto IsUnreachableBlock = [&](
BasicBlock *BB) {
704 if (IsUnreachableBlock(DVI->getParent()))
705 DVI->eraseFromParent();
706 else if (isa_and_nonnull<AllocaInst>(DVI->getVariableLocationOp(0))) {
709 for (
auto *
User : DVI->getVariableLocationOp(0)->
users())
710 if (
auto *
I = dyn_cast<Instruction>(
User))
711 if (!isa<AllocaInst>(
I) && !IsUnreachableBlock(
I->getParent()))
714 DVI->eraseFromParent();
719void CoroCloner::replaceEntryBlock() {
725 auto *Entry = cast<BasicBlock>(VMap[Shape.AllocaSpillBlock]);
726 auto *OldEntry = &NewF->getEntryBlock();
727 Entry->setName(
"entry" + Suffix);
728 Entry->moveBefore(OldEntry);
729 Entry->getTerminator()->eraseFromParent();
734 assert(Entry->hasOneUse());
735 auto BranchToEntry = cast<BranchInst>(Entry->user_back());
736 assert(BranchToEntry->isUnconditional());
737 Builder.SetInsertPoint(BranchToEntry);
739 BranchToEntry->eraseFromParent();
744 case coro::ABI::Switch: {
748 cast<BasicBlock>(VMap[Shape.SwitchLowering.ResumeEntryBlock]);
752 case coro::ABI::Async:
753 case coro::ABI::Retcon:
754 case coro::ABI::RetconOnce: {
758 assert((Shape.ABI == coro::ABI::Async &&
759 isa<CoroSuspendAsyncInst>(ActiveSuspend)) ||
760 ((Shape.ABI == coro::ABI::Retcon ||
761 Shape.ABI == coro::ABI::RetconOnce) &&
762 isa<CoroSuspendRetconInst>(ActiveSuspend)));
763 auto *MappedCS = cast<AnyCoroSuspendInst>(VMap[ActiveSuspend]);
764 auto Branch = cast<BranchInst>(MappedCS->getNextNode());
776 auto *Alloca = dyn_cast<AllocaInst>(&
I);
777 if (!Alloca ||
I.use_empty())
779 if (DT.isReachableFromEntry(
I.getParent()) ||
780 !isa<ConstantInt>(Alloca->getArraySize()))
782 I.moveBefore(*Entry, Entry->getFirstInsertionPt());
787Value *CoroCloner::deriveNewFramePointer() {
792 case coro::ABI::Switch:
793 return &*NewF->arg_begin();
799 case coro::ABI::Async: {
800 auto *ActiveAsyncSuspend = cast<CoroSuspendAsyncInst>(ActiveSuspend);
801 auto ContextIdx = ActiveAsyncSuspend->getStorageArgumentIndex() & 0xff;
802 auto *CalleeContext = NewF->getArg(ContextIdx);
803 auto *FramePtrTy = Shape.FrameTy->getPointerTo();
804 auto *ProjectionFunc =
805 ActiveAsyncSuspend->getAsyncContextProjectionFunction();
807 cast<CoroSuspendAsyncInst>(VMap[ActiveSuspend])->getDebugLoc();
809 auto *CallerContext =
Builder.CreateCall(ProjectionFunc->getFunctionType(),
810 ProjectionFunc, CalleeContext);
811 CallerContext->setCallingConv(ProjectionFunc->getCallingConv());
812 CallerContext->setDebugLoc(DbgLoc);
815 auto *FramePtrAddr =
Builder.CreateConstInBoundsGEP1_32(
817 Shape.AsyncLowering.FrameOffset,
"async.ctx.frameptr");
821 assert(InlineRes.isSuccess());
823 return Builder.CreateBitCast(FramePtrAddr, FramePtrTy);
826 case coro::ABI::Retcon:
827 case coro::ABI::RetconOnce: {
828 Argument *NewStorage = &*NewF->arg_begin();
829 auto FramePtrTy = Shape.FrameTy->getPointerTo();
832 if (Shape.RetconLowering.IsFrameInlineInStorage)
833 return Builder.CreateBitCast(NewStorage, FramePtrTy);
837 Builder.CreateBitCast(NewStorage, FramePtrTy->getPointerTo());
838 return Builder.CreateLoad(FramePtrTy, FramePtrPtr);
846 Align Alignment,
bool NoAlias) {
856 Attrs = Attrs.addParamAttributes(
Context, ParamIndex, ParamAttrs);
860 unsigned ParamIndex) {
863 Attrs = Attrs.addParamAttributes(
Context, ParamIndex, ParamAttrs);
867 unsigned ParamIndex) {
870 Attrs = Attrs.addParamAttributes(
Context, ParamIndex, ParamAttrs);
875void CoroCloner::create() {
879 OrigF.getParent()->end(), ActiveSuspend);
890 VMap[&
A] = DummyArgs.
back();
897 auto savedVisibility = NewF->getVisibility();
898 auto savedUnnamedAddr = NewF->getUnnamedAddr();
899 auto savedDLLStorageClass = NewF->getDLLStorageClass();
904 auto savedLinkage = NewF->getLinkage();
908 CloneFunctionChangeType::LocalChangesOnly, Returns);
910 auto &
Context = NewF->getContext();
919 assert(SP != OrigF.getSubprogram() && SP->isDistinct());
921 if (
auto DL = ActiveSuspend->getDebugLoc())
922 if (SP->getFile() ==
DL->getFile())
923 SP->setScopeLine(
DL->getLine());
932 if (!SP->getDeclaration() && SP->getUnit() &&
933 SP->getUnit()->getSourceLanguage() == dwarf::DW_LANG_Swift)
934 SP->replaceLinkageName(
MDString::get(Context, NewF->getName()));
937 NewF->setLinkage(savedLinkage);
938 NewF->setVisibility(savedVisibility);
939 NewF->setUnnamedAddr(savedUnnamedAddr);
940 NewF->setDLLStorageClass(savedDLLStorageClass);
944 if (Shape.ABI == coro::ABI::Switch &&
945 NewF->hasMetadata(LLVMContext::MD_func_sanitize))
946 NewF->eraseMetadata(LLVMContext::MD_func_sanitize);
949 auto OrigAttrs = NewF->getAttributes();
953 case coro::ABI::Switch:
956 NewAttrs = NewAttrs.addFnAttributes(
957 Context,
AttrBuilder(Context, OrigAttrs.getFnAttrs()));
960 Shape.FrameAlign,
false);
962 case coro::ABI::Async: {
963 auto *ActiveAsyncSuspend = cast<CoroSuspendAsyncInst>(ActiveSuspend);
964 if (OrigF.hasParamAttribute(Shape.AsyncLowering.ContextArgNo,
965 Attribute::SwiftAsync)) {
967 ActiveAsyncSuspend->getStorageArgumentIndex();
968 auto ContextArgIndex = ArgAttributeIndices & 0xff;
973 auto SwiftSelfIndex = ArgAttributeIndices >> 8;
979 auto FnAttrs = OrigF.getAttributes().getFnAttrs();
980 NewAttrs = NewAttrs.addFnAttributes(Context,
AttrBuilder(Context, FnAttrs));
983 case coro::ABI::Retcon:
984 case coro::ABI::RetconOnce:
987 NewAttrs = Shape.RetconLowering.ResumePrototype->getAttributes();
991 Shape.getRetconCoroId()->getStorageSize(),
992 Shape.getRetconCoroId()->getStorageAlignment(),
1003 case coro::ABI::Switch:
1004 case coro::ABI::RetconOnce:
1013 case coro::ABI::Retcon:
1019 case coro::ABI::Async:
1023 NewF->setAttributes(NewAttrs);
1024 NewF->setCallingConv(Shape.getResumeFunctionCC());
1027 replaceEntryBlock();
1029 Builder.SetInsertPoint(&NewF->getEntryBlock().front());
1030 NewFramePtr = deriveNewFramePointer();
1033 Value *OldFramePtr = VMap[Shape.FramePtr];
1034 NewFramePtr->
takeName(OldFramePtr);
1038 auto *NewVFrame =
Builder.CreateBitCast(
1040 Value *OldVFrame = cast<Value>(VMap[Shape.CoroBegin]);
1041 if (OldVFrame != NewVFrame)
1048 DummyArg->deleteValue();
1051 switch (Shape.ABI) {
1052 case coro::ABI::Switch:
1056 if (Shape.SwitchLowering.HasFinalSuspend)
1057 handleFinalSuspend();
1059 case coro::ABI::Async:
1060 case coro::ABI::Retcon:
1061 case coro::ABI::RetconOnce:
1064 assert(ActiveSuspend !=
nullptr &&
1065 "no active suspend when lowering a continuation-style coroutine");
1066 replaceRetconOrAsyncSuspendUses();
1071 replaceCoroSuspends();
1084 if (Shape.ABI == coro::ABI::Switch)
1086 FKind == CoroCloner::Kind::SwitchCleanup);
1094 CoroCloner Cloner(
F, Suffix, Shape, FKind);
1096 return Cloner.getFunction();
1102 auto *FuncPtrStruct = cast<ConstantStruct>(
1104 auto *OrigRelativeFunOffset = FuncPtrStruct->getOperand(0);
1105 auto *OrigContextSize = FuncPtrStruct->getOperand(1);
1109 FuncPtrStruct->getType(), OrigRelativeFunOffset, NewContextSize);
1115 if (Shape.
ABI == coro::ABI::Async)
1128 auto *SizeIntrin = Shape.
CoroSizes.back();
1129 Module *M = SizeIntrin->getModule();
1161 auto *ArrTy = ArrayType::get(Part->
getType(), Args.size());
1165 GlobalVariable::PrivateLinkage, ConstVal,
1166 F.getName() +
Twine(
".resumers"));
1181 auto *ResumeAddr =
Builder.CreateStructGEP(
1184 Builder.CreateStore(ResumeFn, ResumeAddr);
1186 Value *DestroyOrCleanupFn = DestroyFn;
1192 DestroyOrCleanupFn =
Builder.CreateSelect(CA, DestroyFn, CleanupFn);
1195 auto *DestroyAddr =
Builder.CreateStructGEP(
1198 Builder.CreateStore(DestroyOrCleanupFn, DestroyAddr);
1220 auto V = PN.getIncomingValueForBlock(PrevBB);
1222 auto VI = ResolvedValues.
find(V);
1223 if (
VI != ResolvedValues.
end())
1226 ResolvedValues[&PN] = V;
1242 if (isa<BitCastInst>(
I) ||
I->isDebugOrPseudoInst() ||
1243 I->isLifetimeStartOrEnd())
1244 I =
I->getNextNode();
1248 I = &*
I->eraseFromParent();
1255 auto TryResolveConstant = [&ResolvedValues](
Value *V) {
1256 auto It = ResolvedValues.
find(V);
1257 if (It != ResolvedValues.
end())
1259 return dyn_cast<ConstantInt>(V);
1263 while (
I->isTerminator() || isa<CmpInst>(
I)) {
1264 if (isa<ReturnInst>(
I)) {
1265 if (
I != InitialInst) {
1268 if (UnconditionalSucc)
1274 if (
auto *BR = dyn_cast<BranchInst>(
I)) {
1275 if (BR->isUnconditional()) {
1277 if (
I == InitialInst)
1278 UnconditionalSucc = Succ;
1297 }
else if (
auto *CondCmp = dyn_cast<CmpInst>(
I)) {
1300 auto *BR = dyn_cast<BranchInst>(
1301 GetFirstValidInstruction(CondCmp->getNextNode()));
1302 if (!BR || !BR->isConditional() || CondCmp != BR->getCondition())
1308 ConstantInt *Cond0 = TryResolveConstant(CondCmp->getOperand(0));
1309 auto *Cond1 = dyn_cast<ConstantInt>(CondCmp->getOperand(1));
1310 if (!Cond0 || !Cond1)
1317 CondCmp->getPredicate(), Cond0, Cond1,
DL));
1321 CondCmp->replaceAllUsesWith(ConstResult);
1322 CondCmp->eraseFromParent();
1327 }
else if (
auto *
SI = dyn_cast<SwitchInst>(
I)) {
1350 if (!CalleeTy->getReturnType()->isVoidTy() || (CalleeTy->getNumParams() != 1))
1353 Type *CalleeParmTy = CalleeTy->getParamType(0);
1363 Attribute::StructRet, Attribute::ByVal, Attribute::InAlloca,
1364 Attribute::Preallocated, Attribute::InReg, Attribute::Returned,
1365 Attribute::SwiftSelf, Attribute::SwiftError};
1367 for (
auto AK : ABIAttrs)
1368 if (Attrs.hasParamAttr(0, AK))
1380 bool changed =
false;
1385 if (
auto *Call = dyn_cast<CallInst>(&
I))
1406 auto *CoroId = CoroBegin->
getId();
1408 switch (Shape.
ABI) {
1409 case coro::ABI::Switch: {
1410 auto SwitchId = cast<CoroIdInst>(CoroId);
1416 auto *VFrame =
Builder.CreateBitCast(Frame,
Builder.getInt8PtrTy());
1417 AllocInst->replaceAllUsesWith(
Builder.getFalse());
1418 AllocInst->eraseFromParent();
1419 CoroBegin->replaceAllUsesWith(VFrame);
1421 CoroBegin->replaceAllUsesWith(CoroBegin->getMem());
1426 case coro::ABI::Async:
1427 case coro::ABI::Retcon:
1428 case coro::ABI::RetconOnce:
1433 CoroBegin->eraseFromParent();
1442 if (isa<IntrinsicInst>(
I))
1445 if (isa<CallBase>(
I))
1461 while (!Worklist.
empty()) {
1471 Set.
erase(ResDesBB);
1473 for (
auto *BB : Set)
1482 auto *ResumeOrDestroyBB = ResumeOrDestroy->
getParent();
1484 if (SaveBB == ResumeOrDestroyBB)
1512 Prev = Pred->getTerminator();
1515 CallBase *CB = dyn_cast<CallBase>(Prev);
1522 auto *SubFn = dyn_cast<CoroSubFnInst>(
Callee);
1527 if (SubFn->getFrame() != CoroBegin)
1541 Save->eraseFromParent();
1544 if (
auto *Invoke = dyn_cast<InvokeInst>(CB)) {
1553 if (CalledValue != SubFn && CalledValue->user_empty())
1554 if (
auto *
I = dyn_cast<Instruction>(CalledValue))
1555 I->eraseFromParent();
1558 if (SubFn->user_empty())
1559 SubFn->eraseFromParent();
1567 if (Shape.
ABI != coro::ABI::Switch)
1571 size_t I = 0,
N = S.size();
1575 size_t ChangedFinalIndex = std::numeric_limits<size_t>::max();
1577 auto SI = cast<CoroSuspendInst>(S[
I]);
1586 if (cast<CoroSuspendInst>(S[
I])->isFinal()) {
1588 ChangedFinalIndex =
I;
1600 if (ChangedFinalIndex <
N) {
1601 assert(cast<CoroSuspendInst>(S[ChangedFinalIndex])->isFinal());
1602 std::swap(S[ChangedFinalIndex], S.back());
1613 CoroCloner::Kind::SwitchResume);
1615 CoroCloner::Kind::SwitchUnwind);
1617 CoroCloner::Kind::SwitchCleanup);
1646 Value *Continuation) {
1652 auto *Val =
Builder.CreateBitOrPointerCast(Continuation, Int8PtrTy);
1653 ResumeIntrinsic->replaceAllUsesWith(Val);
1654 ResumeIntrinsic->eraseFromParent();
1664 for (
auto *paramTy : FnTy->params()) {
1666 if (paramTy != FnArgs[ArgIdx]->
getType())
1668 Builder.CreateBitOrPointerCast(FnArgs[ArgIdx], paramTy));
1684 auto *TailCall =
Builder.CreateCall(FnTy, MustTailCallFn, CallArgs);
1686 TailCall->setDebugLoc(Loc);
1697 F.removeFnAttr(Attribute::NoReturn);
1698 F.removeRetAttr(Attribute::NoAlias);
1699 F.removeRetAttr(Attribute::NonNull);
1711 "async.ctx.frameptr");
1722 auto NextF = std::next(
F.getIterator());
1730 auto ResumeNameSuffix =
".resume.";
1731 auto ProjectionFunctionName =
1732 Suspend->getAsyncContextProjectionFunction()->getName();
1733 bool UseSwiftMangling =
false;
1734 if (ProjectionFunctionName.equals(
"__swift_async_resume_project_context")) {
1735 ResumeNameSuffix =
"TQ";
1736 UseSwiftMangling =
true;
1737 }
else if (ProjectionFunctionName.equals(
1738 "__swift_async_resume_get_context")) {
1739 ResumeNameSuffix =
"TY";
1740 UseSwiftMangling =
true;
1744 UseSwiftMangling ? ResumeNameSuffix +
Twine(
Idx) +
"_"
1751 auto *SuspendBB = Suspend->getParent();
1752 auto *NewSuspendBB = SuspendBB->splitBasicBlock(Suspend);
1753 auto *Branch = cast<BranchInst>(SuspendBB->getTerminator());
1758 Branch->setSuccessor(0, ReturnBB);
1763 auto *Fn = Suspend->getMustTailCallFunction();
1772 assert(InlineRes.isSuccess() &&
"Expected inlining to succeed");
1782 auto *Clone = Clones[
Idx];
1784 CoroCloner(
F,
"resume." +
Twine(
Idx), Shape, Clone, Suspend).create();
1790 assert(Shape.
ABI == coro::ABI::Retcon ||
1791 Shape.
ABI == coro::ABI::RetconOnce);
1796 F.removeFnAttr(Attribute::NoReturn);
1797 F.removeRetAttr(Attribute::NoAlias);
1798 F.removeRetAttr(Attribute::NonNull);
1804 RawFramePtr = Id->getStorage();
1820 auto Dest =
Builder.CreateBitCast(Id->getStorage(),
1822 Builder.CreateStore(RawFramePtr, Dest);
1838 auto NextF = std::next(
F.getIterator());
1842 for (
size_t i = 0, e = Shape.
CoroSuspends.size(); i != e; ++i) {
1843 auto Suspend = cast<CoroSuspendRetconInst>(Shape.
CoroSuspends[i]);
1852 auto SuspendBB = Suspend->getParent();
1853 auto NewSuspendBB = SuspendBB->splitBasicBlock(Suspend);
1854 auto Branch = cast<BranchInst>(SuspendBB->getTerminator());
1878 auto RetTy =
F.getReturnType();
1883 auto CastedContinuationTy =
1884 (ReturnPHIs.
size() == 1 ?
RetTy :
RetTy->getStructElementType(0));
1885 auto *CastedContinuation =
1886 Builder.CreateBitCast(ReturnPHIs[0], CastedContinuationTy);
1889 if (ReturnPHIs.
size() == 1) {
1890 RetV = CastedContinuation;
1893 RetV =
Builder.CreateInsertValue(RetV, CastedContinuation, 0);
1894 for (
size_t I = 1,
E = ReturnPHIs.
size();
I !=
E; ++
I)
1895 RetV =
Builder.CreateInsertValue(RetV, ReturnPHIs[
I],
I);
1902 Branch->setSuccessor(0, ReturnBB);
1903 ReturnPHIs[0]->addIncoming(Continuation, SuspendBB);
1904 size_t NextPHIIndex = 1;
1905 for (
auto &VUse : Suspend->value_operands())
1906 ReturnPHIs[NextPHIIndex++]->addIncoming(&*VUse, SuspendBB);
1911 for (
size_t i = 0, e = Shape.
CoroSuspends.size(); i != e; ++i) {
1913 auto Clone = Clones[i];
1915 CoroCloner(
F,
"resume." +
Twine(i), Shape, Clone, Suspend).create();
1923 PrettyStackTraceFunction(
Function &F) :
F(
F) {}
1925 OS <<
"While splitting coroutine ";
1926 F.printAsOperand(OS,
false,
F.getParent());
1935 bool OptimizeFrame) {
1936 PrettyStackTraceFunction prettyStackTrace(
F);
1947 buildCoroutineFrame(
F, Shape);
1955 switch (Shape.
ABI) {
1956 case coro::ABI::Switch:
1959 case coro::ABI::Async:
1962 case coro::ABI::Retcon:
1963 case coro::ABI::RetconOnce:
1978 for (
auto &BB :
F) {
1979 for (
auto &
I : BB) {
1980 if (
auto *DDI = dyn_cast<DbgDeclareInst>(&
I)) {
1984 if (
auto *DDI = dyn_cast<DbgAddrIntrinsic>(&
I)) {
1990 for (
auto *DDI : Worklist)
2011 if (Shape.
ABI != coro::ABI::Switch)
2015 auto &
Context = End->getContext();
2017 End->eraseFromParent();
2021 if (!Clones.
empty()) {
2022 switch (Shape.
ABI) {
2023 case coro::ABI::Switch:
2029 case coro::ABI::Async:
2030 case coro::ABI::Retcon:
2031 case coro::ABI::RetconOnce:
2034 if (!Clones.empty())
2063 auto *Cast = dyn_cast<BitCastInst>(U.getUser());
2064 if (!Cast || Cast->getType() != Fn->getType())
2068 Cast->replaceAllUsesWith(Fn);
2069 Cast->eraseFromParent();
2078 while (
auto *Cast = dyn_cast<BitCastInst>(CastFn)) {
2079 if (!Cast->use_empty())
2081 CastFn = Cast->getOperand(0);
2082 Cast->eraseFromParent();
2088 bool Changed =
false;
2091 auto *Prepare = cast<CallInst>(
P.getUser());
2102 auto *PrepareFn = M.getFunction(
Name);
2103 if (PrepareFn && !PrepareFn->use_empty())
2113 Module &M = *
C.begin()->getFunction().getParent();
2125 if (
N.getFunction().isPresplitCoroutine())
2128 if (Coroutines.
empty() && PrepareFns.
empty())
2131 if (Coroutines.
empty()) {
2132 for (
auto *PrepareFn : PrepareFns) {
2140 LLVM_DEBUG(
dbgs() <<
"CoroSplit: Processing coroutine '" <<
F.getName()
2142 F.setSplittedCoroutine();
2157 if (!PrepareFns.
empty()) {
2158 for (
auto *PrepareFn : PrepareFns) {
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
amdgpu Simplify well known AMD library false FunctionCallee Callee
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
AMDGPU Lower Kernel Arguments
SmallPtrSet< MachineInstr *, 2 > Uses
This file contains the simple types necessary to represent the attributes associated with functions a...
SmallVector< MachineOperand, 4 > Cond
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 coro::Shape splitCoroutine(Function &F, SmallVectorImpl< Function * > &Clones, TargetTransformInfo &TTI, bool OptimizeFrame)
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 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)
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
Implements a lazy call graph analysis and related passes for the new pass manager.
static M68kRelType getType(unsigned Kind, MCSymbolRefExpr::VariantKind &Modifier, bool &IsPCRel)
Module.h This file contains the declarations for the Module class.
print must be executed print the must be executed context for all instructions
FunctionAnalysisManager FAM
This file provides a priority worklist.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
static const unsigned FramePtr
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...
void removePredecessor(BasicBlock *Pred, bool KeepOneInputPHIs=false)
Update PHI nodes in this BasicBlock before removal of predecessor Pred.
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.
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 ...
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
SymbolTableList< Instruction >::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.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
FunctionListType::iterator iterator
The Function iterators.
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...
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
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.
PointerType * getPointerTo(unsigned AddrSpace=0) const
Return a pointer to the current type.
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 PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
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< llvm::Value *, llvm::AllocaInst *, 4 > &DbgPtrAllocaCache, DbgVariableIntrinsic *DVI, bool OptimizeFrame)
Recover a dbg.declare prepared by the frontend and emit an alloca holding a pointer to the coroutine ...
void replaceCoroFree(CoroIdInst *CoroId, bool Elide)
CallInst * createMustTailCall(DebugLoc Loc, Function *MustTailCallFn, ArrayRef< Value * > Arguments, IRBuilder<> &)
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 ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions=false, const TargetLibraryInfo *TLI=nullptr, DomTreeUpdater *DTU=nullptr)
If a terminator instruction is predicated on a constant value, convert it into an unconditional branc...
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.
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.
PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR)
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