Go to the documentation of this file.
71 #include <initializer_list>
76 #define DEBUG_TYPE "coro-split"
108 Value *NewFramePtr =
nullptr;
118 : OrigF(OrigF), NewF(
nullptr), Suffix(Suffix), Shape(Shape),
126 : OrigF(OrigF), NewF(NewF), Suffix(Suffix), Shape(Shape),
131 assert(NewF &&
"need existing function for continuation");
132 assert(ActiveSuspend &&
"need active suspend point for continuation");
136 assert(NewF !=
nullptr &&
"declaration not yet set");
143 bool isSwitchDestroyFunction() {
146 case Kind::Continuation:
147 case Kind::SwitchResume:
149 case Kind::SwitchUnwind:
150 case Kind::SwitchCleanup:
156 void replaceEntryBlock();
157 Value *deriveNewFramePointer();
158 void replaceRetconOrAsyncSuspendUses();
159 void replaceCoroSuspends();
160 void replaceCoroEnds();
163 void handleFinalSuspend();
185 auto *EndAsync = dyn_cast<CoroAsyncEndInst>(End);
191 auto *MustTailCallFunc = EndAsync->getMustTailCallFunction();
192 if (!MustTailCallFunc) {
198 auto *CoroEndBlock = End->getParent();
199 auto *MustTailCallFuncBlock = CoroEndBlock->getSinglePredecessor();
200 assert(MustTailCallFuncBlock &&
"Must have a single predecessor block");
201 auto It = MustTailCallFuncBlock->getTerminator()->getIterator();
202 auto *MustTailCall = cast<CallInst>(&*std::prev(It));
203 CoroEndBlock->getInstList().splice(
204 End->getIterator(), MustTailCallFuncBlock->getInstList(), MustTailCall);
212 auto *
BB = End->getParent();
213 BB->splitBasicBlock(End);
214 BB->getTerminator()->eraseFromParent();
217 assert(InlineRes.isSuccess() &&
"Expected inlining to succeed");
245 if (!CoroEndBlockNeedsCleanup)
262 auto RetStructTy = dyn_cast<StructType>(RetTy);
264 cast<PointerType>(RetStructTy ? RetStructTy->getElementType(0) : RetTy);
271 Builder.CreateRet(ReturnValue);
277 auto *
BB = End->getParent();
278 BB->splitBasicBlock(End);
279 BB->getTerminator()->eraseFromParent();
294 "markCoroutineAsDone is only supported for Switch-Resumed ABI for now.");
295 auto *GepIndex =
Builder.CreateStructGEP(
300 Builder.CreateStore(NullPtr, GepIndex);
305 Value *FramePtr,
bool InResume,
335 auto *FromPad = cast<CleanupPadInst>(Bundle->Inputs[0]);
336 auto *CleanupRet =
Builder.CreateCleanupRet(FromPad,
nullptr);
337 End->getParent()->splitBasicBlock(End);
338 CleanupRet->getParent()->getTerminator()->eraseFromParent();
349 auto &
Context = End->getContext();
352 End->eraseFromParent();
377 auto *GepIndex =
Builder.CreateStructGEP(
384 size_t SuspendIndex = 0;
386 auto *
S = cast<CoroSuspendInst>(AnyS);
392 auto *Save =
S->getCoroSave();
399 auto *GepIndex =
Builder.CreateStructGEP(
401 Builder.CreateStore(IndexVal, GepIndex);
404 Save->eraseFromParent();
429 auto *SuspendBB =
S->getParent();
431 SuspendBB->splitBasicBlock(
S,
"resume." +
Twine(SuspendIndex));
432 auto *LandingBB = ResumeBB->splitBasicBlock(
433 S->getNextNode(), ResumeBB->getName() +
Twine(
".landing"));
434 Switch->addCase(IndexVal, ResumeBB);
436 cast<BranchInst>(SuspendBB->getTerminator())->setSuccessor(0, LandingBB);
438 S->replaceAllUsesWith(PN);
439 PN->addIncoming(
Builder.getInt8(-1), SuspendBB);
440 PN->addIncoming(
S, ResumeBB);
445 Builder.SetInsertPoint(UnreachBB);
461 void CoroCloner::handleFinalSuspend() {
463 Shape.SwitchLowering.HasFinalSuspend);
464 auto *
Switch = cast<SwitchInst>(VMap[Shape.SwitchLowering.ResumeSwitch]);
465 auto FinalCaseIt = std::prev(
Switch->case_end());
466 BasicBlock *ResumeBB = FinalCaseIt->getCaseSuccessor();
467 Switch->removeCase(FinalCaseIt);
468 if (isSwitchDestroyFunction()) {
472 auto *GepIndex =
Builder.CreateStructGEP(Shape.FrameTy, NewFramePtr,
475 auto *
Load =
Builder.CreateLoad(Shape.getSwitchResumePointerType(),
485 auto *AsyncSuspend = cast<CoroSuspendAsyncInst>(Suspend);
486 auto *StructTy = cast<StructType>(AsyncSuspend->getType());
512 M->getFunctionList().insert(InsertBefore, NewF);
521 void CoroCloner::replaceRetconOrAsyncSuspendUses() {
525 auto NewS = VMap[ActiveSuspend];
526 if (NewS->use_empty())
return;
533 for (
auto I = IsAsyncABI ? NewF->arg_begin() : std::next(NewF->arg_begin()),
540 if (!isa<StructType>(NewS->getType())) {
542 NewS->replaceAllUsesWith(
Args.front());
548 auto *EVI = dyn_cast<ExtractValueInst>(U.getUser());
549 if (!EVI || EVI->getNumIndices() != 1)
552 EVI->replaceAllUsesWith(
Args[EVI->getIndices().front()]);
553 EVI->eraseFromParent();
557 if (NewS->use_empty())
return;
561 for (
size_t I = 0,
E =
Args.size();
I !=
E; ++
I)
564 NewS->replaceAllUsesWith(Agg);
567 void CoroCloner::replaceCoroSuspends() {
568 Value *SuspendResult;
578 SuspendResult =
Builder.getInt8(isSwitchDestroyFunction() ? 1 : 0);
595 if (CS == ActiveSuspend)
continue;
597 auto *MappedCS = cast<AnyCoroSuspendInst>(VMap[CS]);
598 MappedCS->replaceAllUsesWith(SuspendResult);
599 MappedCS->eraseFromParent();
603 void CoroCloner::replaceCoroEnds() {
607 auto *NewCE = cast<AnyCoroEndInst>(VMap[CE]);
616 Value *CachedSlot =
nullptr;
617 auto getSwiftErrorSlot = [&](
Type *ValueTy) ->
Value * {
620 ->isOpaqueOrPointeeTypeMatches(ValueTy) &&
621 "multiple swifterror slots in function with different types");
626 for (
auto &
Arg :
F.args()) {
627 if (
Arg.isSwiftError()) {
630 ->isOpaqueOrPointeeTypeMatches(ValueTy) &&
631 "swifterror argument does not have expected type");
638 auto Alloca =
Builder.CreateAlloca(ValueTy);
639 Alloca->setSwiftError(
true);
646 auto MappedOp = VMap ? cast<CallInst>((*VMap)[
Op]) :
Op;
651 if (
Op->arg_empty()) {
652 auto ValueTy =
Op->getType();
653 auto Slot = getSwiftErrorSlot(ValueTy);
654 MappedResult =
Builder.CreateLoad(ValueTy, Slot);
657 auto Value = MappedOp->getArgOperand(0);
659 auto Slot = getSwiftErrorSlot(ValueTy);
664 MappedOp->replaceAllUsesWith(MappedResult);
665 MappedOp->eraseFromParent();
669 if (VMap ==
nullptr) {
681 for (
auto &
BB : *NewF)
683 if (
auto *DVI = dyn_cast<DbgVariableIntrinsic>(&
I))
684 Worklist.push_back(DVI);
696 if (IsUnreachableBlock(DVI->getParent()))
697 DVI->eraseFromParent();
698 else if (isa_and_nonnull<AllocaInst>(DVI->getVariableLocationOp(0))) {
701 for (
auto *
User : DVI->getVariableLocationOp(0)->
users())
702 if (
auto *
I = dyn_cast<Instruction>(
User))
703 if (!isa<AllocaInst>(
I) && !IsUnreachableBlock(
I->getParent()))
706 DVI->eraseFromParent();
711 void CoroCloner::replaceEntryBlock() {
717 auto *Entry = cast<BasicBlock>(VMap[Shape.AllocaSpillBlock]);
718 auto *OldEntry = &NewF->getEntryBlock();
719 Entry->setName(
"entry" + Suffix);
720 Entry->moveBefore(OldEntry);
721 Entry->getTerminator()->eraseFromParent();
726 assert(Entry->hasOneUse());
727 auto BranchToEntry = cast<BranchInst>(Entry->user_back());
728 assert(BranchToEntry->isUnconditional());
729 Builder.SetInsertPoint(BranchToEntry);
731 BranchToEntry->eraseFromParent();
740 cast<BasicBlock>(VMap[Shape.SwitchLowering.ResumeEntryBlock]);
751 isa<CoroSuspendAsyncInst>(ActiveSuspend)) ||
754 isa<CoroSuspendRetconInst>(ActiveSuspend)));
755 auto *MappedCS = cast<AnyCoroSuspendInst>(VMap[ActiveSuspend]);
756 auto Branch = cast<BranchInst>(MappedCS->getNextNode());
768 auto *Alloca = dyn_cast<AllocaInst>(&
I);
769 if (!Alloca ||
I.use_empty())
771 if (DT.isReachableFromEntry(
I.getParent()) ||
772 !isa<ConstantInt>(Alloca->getArraySize()))
774 I.moveBefore(*Entry, Entry->getFirstInsertionPt());
779 Value *CoroCloner::deriveNewFramePointer() {
785 return &*NewF->arg_begin();
792 auto *ActiveAsyncSuspend = cast<CoroSuspendAsyncInst>(ActiveSuspend);
793 auto ContextIdx = ActiveAsyncSuspend->getStorageArgumentIndex() & 0xff;
794 auto *CalleeContext = NewF->getArg(ContextIdx);
795 auto *FramePtrTy = Shape.FrameTy->getPointerTo();
796 auto *ProjectionFunc =
797 ActiveAsyncSuspend->getAsyncContextProjectionFunction();
799 cast<CoroSuspendAsyncInst>(VMap[ActiveSuspend])->getDebugLoc();
801 auto *CallerContext =
Builder.CreateCall(ProjectionFunc->getFunctionType(),
802 ProjectionFunc, CalleeContext);
803 CallerContext->setCallingConv(ProjectionFunc->getCallingConv());
804 CallerContext->setDebugLoc(DbgLoc);
807 auto *FramePtrAddr =
Builder.CreateConstInBoundsGEP1_32(
809 Shape.AsyncLowering.FrameOffset,
"async.ctx.frameptr");
813 assert(InlineRes.isSuccess());
815 return Builder.CreateBitCast(FramePtrAddr, FramePtrTy);
820 Argument *NewStorage = &*NewF->arg_begin();
821 auto FramePtrTy = Shape.FrameTy->getPointerTo();
824 if (Shape.RetconLowering.IsFrameInlineInStorage)
825 return Builder.CreateBitCast(NewStorage, FramePtrTy);
829 Builder.CreateBitCast(NewStorage, FramePtrTy->getPointerTo());
830 return Builder.CreateLoad(FramePtrTy, FramePtrPtr);
848 unsigned ParamIndex) {
855 unsigned ParamIndex) {
863 void CoroCloner::create() {
867 OrigF.getParent()->end(), ActiveSuspend);
878 VMap[&
A] = DummyArgs.back();
885 auto savedVisibility = NewF->getVisibility();
886 auto savedUnnamedAddr = NewF->getUnnamedAddr();
887 auto savedDLLStorageClass = NewF->getDLLStorageClass();
892 auto savedLinkage = NewF->getLinkage();
898 auto &
Context = NewF->getContext();
907 assert(SP != OrigF.getSubprogram() && SP->isDistinct());
909 if (
auto DL = ActiveSuspend->getDebugLoc())
910 if (SP->getFile() ==
DL->getFile())
911 SP->setScopeLine(
DL->getLine());
920 if (!SP->getDeclaration() && SP->getUnit() &&
921 SP->getUnit()->getSourceLanguage() == dwarf::DW_LANG_Swift)
925 NewF->setLinkage(savedLinkage);
926 NewF->setVisibility(savedVisibility);
927 NewF->setUnnamedAddr(savedUnnamedAddr);
928 NewF->setDLLStorageClass(savedDLLStorageClass);
931 auto OrigAttrs = NewF->getAttributes();
938 NewAttrs = NewAttrs.addFnAttributes(
942 Shape.FrameSize, Shape.FrameAlign);
945 auto *ActiveAsyncSuspend = cast<CoroSuspendAsyncInst>(ActiveSuspend);
946 if (OrigF.hasParamAttribute(Shape.AsyncLowering.ContextArgNo,
947 Attribute::SwiftAsync)) {
949 ActiveAsyncSuspend->getStorageArgumentIndex();
950 auto ContextArgIndex = ArgAttributeIndices & 0xff;
955 auto SwiftSelfIndex = ArgAttributeIndices >> 8;
961 auto FnAttrs = OrigF.getAttributes().getFnAttrs();
969 NewAttrs = Shape.RetconLowering.ResumePrototype->getAttributes();
972 Shape.getRetconCoroId()->getStorageSize(),
973 Shape.getRetconCoroId()->getStorageAlignment());
1002 NewF->setAttributes(NewAttrs);
1003 NewF->setCallingConv(Shape.getResumeFunctionCC());
1006 replaceEntryBlock();
1008 Builder.SetInsertPoint(&NewF->getEntryBlock().front());
1009 NewFramePtr = deriveNewFramePointer();
1012 Value *OldFramePtr = VMap[Shape.FramePtr];
1013 NewFramePtr->
takeName(OldFramePtr);
1017 auto *NewVFrame =
Builder.CreateBitCast(
1019 Value *OldVFrame = cast<Value>(VMap[Shape.CoroBegin]);
1020 if (OldVFrame != NewVFrame)
1027 DummyArg->deleteValue();
1030 switch (Shape.ABI) {
1035 if (Shape.SwitchLowering.HasFinalSuspend)
1036 handleFinalSuspend();
1043 assert(ActiveSuspend !=
nullptr &&
1044 "no active suspend when lowering a continuation-style coroutine");
1045 replaceRetconOrAsyncSuspendUses();
1050 replaceCoroSuspends();
1065 FKind == CoroCloner::Kind::SwitchCleanup);
1073 CoroCloner Cloner(
F, Suffix, Shape, FKind);
1075 return Cloner.getFunction();
1081 auto *FuncPtrStruct = cast<ConstantStruct>(
1083 auto *OrigRelativeFunOffset = FuncPtrStruct->getOperand(0);
1084 auto *OrigContextSize = FuncPtrStruct->getOperand(1);
1088 FuncPtrStruct->getType(), OrigRelativeFunOffset, NewContextSize);
1107 auto *SizeIntrin = Shape.
CoroSizes.back();
1108 Module *
M = SizeIntrin->getModule();
1110 auto Size =
DL.getTypeAllocSize(Shape.
FrameTy);
1145 F.getName() +
Twine(
".resumers"));
1160 auto *ResumeAddr =
Builder.CreateStructGEP(
1163 Builder.CreateStore(ResumeFn, ResumeAddr);
1165 Value *DestroyOrCleanupFn = DestroyFn;
1171 DestroyOrCleanupFn =
Builder.CreateSelect(CA, DestroyFn, CleanupFn);
1174 auto *DestroyAddr =
Builder.CreateStructGEP(
1177 Builder.CreateStore(DestroyOrCleanupFn, DestroyAddr);
1199 auto V = PN.getIncomingValueForBlock(PrevBB);
1201 auto VI = ResolvedValues.
find(V);
1202 if (
VI != ResolvedValues.
end())
1205 ResolvedValues[&PN] = V;
1221 if (isa<BitCastInst>(
I) ||
I->isDebugOrPseudoInst() ||
1222 I->isLifetimeStartOrEnd())
1223 I =
I->getNextNode();
1227 I = &*
I->eraseFromParent();
1234 auto TryResolveConstant = [&ResolvedValues](
Value *V) {
1235 auto It = ResolvedValues.
find(V);
1236 if (It != ResolvedValues.
end())
1238 return dyn_cast<ConstantInt>(V);
1242 while (
I->isTerminator() || isa<CmpInst>(
I)) {
1243 if (isa<ReturnInst>(
I)) {
1244 if (
I != InitialInst) {
1247 if (UnconditionalSucc)
1253 if (
auto *
BR = dyn_cast<BranchInst>(
I)) {
1254 if (
BR->isUnconditional()) {
1256 if (
I == InitialInst)
1257 UnconditionalSucc = Succ;
1273 I =
BB->getTerminator();
1276 }
else if (
auto *CondCmp = dyn_cast<CmpInst>(
I)) {
1279 auto *
BR = dyn_cast<BranchInst>(
1280 GetFirstValidInstruction(CondCmp->getNextNode()));
1281 if (!
BR || !
BR->isConditional() || CondCmp !=
BR->getCondition())
1287 ConstantInt *Cond0 = TryResolveConstant(CondCmp->getOperand(0));
1288 auto *Cond1 = dyn_cast<ConstantInt>(CondCmp->getOperand(1));
1289 if (!Cond0 || !Cond1)
1296 CondCmp->getPredicate(), Cond0, Cond1,
DL));
1300 CondCmp->replaceAllUsesWith(ConstResult);
1301 CondCmp->eraseFromParent();
1306 }
else if (
auto *
SI = dyn_cast<SwitchInst>(
I)) {
1313 I = GetFirstValidInstruction(
BB->getFirstNonPHIOrDbgOrLifetime());
1342 Attribute::StructRet, Attribute::ByVal, Attribute::InAlloca,
1343 Attribute::Preallocated, Attribute::InReg, Attribute::Returned,
1344 Attribute::SwiftSelf, Attribute::SwiftError};
1346 for (
auto AK : ABIAttrs)
1347 if (
Attrs.hasParamAttr(0, AK))
1359 bool changed =
false;
1364 if (
auto *Call = dyn_cast<CallInst>(&
I))
1366 Resumes.push_back(Call);
1383 auto *CoroId = CoroBegin->
getId();
1385 switch (Shape.
ABI) {
1387 auto SwitchId = cast<CoroIdInst>(CoroId);
1393 auto *VFrame =
Builder.CreateBitCast(Frame,
Builder.getInt8PtrTy());
1394 AllocInst->replaceAllUsesWith(
Builder.getFalse());
1395 AllocInst->eraseFromParent();
1396 CoroBegin->replaceAllUsesWith(VFrame);
1398 CoroBegin->replaceAllUsesWith(CoroBegin->getMem());
1410 CoroBegin->eraseFromParent();
1419 if (isa<IntrinsicInst>(
I))
1422 if (isa<CallBase>(
I))
1433 Worklist.push_back(ResDesBB);
1438 while (!Worklist.empty()) {
1443 Worklist.push_back(Pred);
1448 Set.
erase(ResDesBB);
1450 for (
auto *
BB : Set)
1459 auto *ResumeOrDestroyBB = ResumeOrDestroy->
getParent();
1461 if (SaveBB == ResumeOrDestroyBB)
1489 Prev = Pred->getTerminator();
1492 CallBase *CB = dyn_cast<CallBase>(Prev);
1499 auto *SubFn = dyn_cast<CoroSubFnInst>(
Callee);
1504 if (SubFn->getFrame() != CoroBegin)
1518 Save->eraseFromParent();
1521 if (
auto *Invoke = dyn_cast<InvokeInst>(CB)) {
1530 if (CalledValue != SubFn && CalledValue->user_empty())
1531 if (
auto *
I = dyn_cast<Instruction>(CalledValue))
1532 I->eraseFromParent();
1535 if (SubFn->user_empty())
1536 SubFn->eraseFromParent();
1548 size_t I = 0,
N =
S.size();
1552 auto SI = cast<CoroSuspendInst>(
S[
I]);
1573 CoroCloner::Kind::SwitchResume);
1575 CoroCloner::Kind::SwitchUnwind);
1577 CoroCloner::Kind::SwitchCleanup);
1589 Clones.push_back(ResumeClone);
1590 Clones.push_back(DestroyClone);
1591 Clones.push_back(CleanupClone);
1600 Value *Continuation) {
1606 auto *Val =
Builder.CreateBitOrPointerCast(Continuation, Int8PtrTy);
1607 ResumeIntrinsic->replaceAllUsesWith(Val);
1608 ResumeIntrinsic->eraseFromParent();
1618 for (
auto paramTy : FnTy->
params()) {
1620 if (paramTy != FnArgs[ArgIdx]->
getType())
1622 Builder.CreateBitOrPointerCast(FnArgs[ArgIdx], paramTy));
1624 CallArgs.push_back(FnArgs[ArgIdx]);
1651 F.removeFnAttr(Attribute::NoReturn);
1652 F.removeRetAttr(Attribute::NoAlias);
1653 F.removeRetAttr(Attribute::NonNull);
1661 auto *FramePtr =
Id->getStorage();
1662 FramePtr =
Builder.CreateBitOrPointerCast(FramePtr, Int8PtrTy);
1663 FramePtr =
Builder.CreateConstInBoundsGEP1_32(
1665 "async.ctx.frameptr");
1676 auto NextF = std::next(
F.getIterator());
1680 for (
size_t Idx = 0, End = Shape.
CoroSuspends.size(); Idx != End; ++Idx) {
1681 auto *Suspend = cast<CoroSuspendAsyncInst>(Shape.
CoroSuspends[Idx]);
1684 auto ResumeNameSuffix =
".resume.";
1685 auto ProjectionFunctionName =
1686 Suspend->getAsyncContextProjectionFunction()->getName();
1687 bool UseSwiftMangling =
false;
1688 if (ProjectionFunctionName.equals(
"__swift_async_resume_project_context")) {
1689 ResumeNameSuffix =
"TQ";
1690 UseSwiftMangling =
true;
1691 }
else if (ProjectionFunctionName.equals(
1692 "__swift_async_resume_get_context")) {
1693 ResumeNameSuffix =
"TY";
1694 UseSwiftMangling =
true;
1698 UseSwiftMangling ? ResumeNameSuffix +
Twine(Idx) +
"_"
1699 : ResumeNameSuffix +
Twine(Idx),
1701 Clones.push_back(Continuation);
1705 auto *SuspendBB = Suspend->getParent();
1706 auto *NewSuspendBB = SuspendBB->splitBasicBlock(Suspend);
1707 auto *
Branch = cast<BranchInst>(SuspendBB->getTerminator());
1712 Branch->setSuccessor(0, ReturnBB);
1717 auto *Fn = Suspend->getMustTailCallFunction();
1726 assert(InlineRes.isSuccess() &&
"Expected inlining to succeed");
1734 for (
size_t Idx = 0, End = Shape.
CoroSuspends.size(); Idx != End; ++Idx) {
1736 auto *Clone = Clones[Idx];
1738 CoroCloner(
F,
"resume." +
Twine(Idx), Shape, Clone, Suspend).create();
1750 F.removeFnAttr(Attribute::NoReturn);
1751 F.removeRetAttr(Attribute::NoAlias);
1752 F.removeRetAttr(Attribute::NonNull);
1758 RawFramePtr =
Id->getStorage();
1764 auto Size =
DL.getTypeAllocSize(Shape.
FrameTy);
1774 auto Dest =
Builder.CreateBitCast(
Id->getStorage(),
1776 Builder.CreateStore(RawFramePtr, Dest);
1792 auto NextF = std::next(
F.getIterator());
1797 auto Suspend = cast<CoroSuspendRetconInst>(Shape.
CoroSuspends[
i]);
1802 Clones.push_back(Continuation);
1806 auto SuspendBB = Suspend->getParent();
1807 auto NewSuspendBB = SuspendBB->splitBasicBlock(Suspend);
1808 auto Branch = cast<BranchInst>(SuspendBB->getTerminator());
1820 assert(ReturnPHIs.empty());
1823 ReturnPHIs.push_back(
Builder.CreatePHI(Continuation->getType(),
1828 ReturnPHIs.push_back(
Builder.CreatePHI(ResultTy,
1832 auto RetTy =
F.getReturnType();
1837 auto CastedContinuationTy =
1838 (ReturnPHIs.size() == 1 ? RetTy : RetTy->getStructElementType(0));
1839 auto *CastedContinuation =
1840 Builder.CreateBitCast(ReturnPHIs[0], CastedContinuationTy);
1843 if (ReturnPHIs.size() == 1) {
1844 RetV = CastedContinuation;
1847 RetV =
Builder.CreateInsertValue(RetV, CastedContinuation, 0);
1848 for (
size_t I = 1,
E = ReturnPHIs.size();
I !=
E; ++
I)
1849 RetV =
Builder.CreateInsertValue(RetV, ReturnPHIs[
I],
I);
1856 Branch->setSuccessor(0, ReturnBB);
1857 ReturnPHIs[0]->addIncoming(Continuation, SuspendBB);
1858 size_t NextPHIIndex = 1;
1859 for (
auto &VUse : Suspend->value_operands())
1860 ReturnPHIs[NextPHIIndex++]->addIncoming(&*VUse, SuspendBB);
1861 assert(NextPHIIndex == ReturnPHIs.size());
1867 auto Clone = Clones[
i];
1869 CoroCloner(
F,
"resume." +
Twine(
i), Shape, Clone, Suspend).create();
1879 OS <<
"While splitting coroutine ";
1880 F.printAsOperand(OS,
false,
F.getParent());
1888 bool OptimizeFrame) {
1889 PrettyStackTraceFunction prettyStackTrace(
F);
1908 switch (Shape.
ABI) {
1931 for (
auto &
BB :
F) {
1932 for (
auto &
I :
BB) {
1933 if (
auto *DDI = dyn_cast<DbgDeclareInst>(&
I)) {
1934 Worklist.push_back(DDI);
1937 if (
auto *DDI = dyn_cast<DbgAddrIntrinsic>(&
I)) {
1938 Worklist.push_back(DDI);
1943 for (
auto *DDI : Worklist)
1958 auto &
Context = End->getContext();
1960 End->eraseFromParent();
1963 if (!Clones.empty()) {
1964 switch (Shape.
ABI) {
1976 if (!Clones.empty())
2005 auto *Cast = dyn_cast<BitCastInst>(U.getUser());
2006 if (!Cast || Cast->getType() != Fn->getType())
2010 Cast->replaceAllUsesWith(Fn);
2011 Cast->eraseFromParent();
2020 while (
auto *Cast = dyn_cast<BitCastInst>(CastFn)) {
2021 if (!Cast->use_empty())
2023 CastFn = Cast->getOperand(0);
2024 Cast->eraseFromParent();
2030 bool Changed =
false;
2033 auto *Prepare = cast<CallInst>(
P.getUser());
2044 auto *PrepareFn =
M.getFunction(
Name);
2045 if (PrepareFn && !PrepareFn->use_empty())
2046 Fns.push_back(PrepareFn);
2055 Module &
M = *
C.begin()->getFunction().getParent();
2068 Coroutines.push_back(&
N);
2070 if (Coroutines.empty() && PrepareFns.empty())
2073 if (Coroutines.empty()) {
2074 for (
auto *PrepareFn : PrepareFns) {
2082 LLVM_DEBUG(
dbgs() <<
"CoroSplit: Processing coroutine '" <<
F.getName()
2098 if (!PrepareFns.empty()) {
2099 for (
auto *PrepareFn : PrepareFns) {
SmallVector< CoroSizeInst *, 2 > CoroSizes
static void postSplitCleanup(Function &F)
Instruction * getInsertPtAfterFramePtr() const
A set of analyses that are preserved following a run of a transformation pass.
This class represents an incoming formal argument to a Function.
CallInst * createMustTailCall(DebugLoc Loc, Function *MustTailCallFn, ArrayRef< Value * > Arguments, IRBuilder<> &)
Constant * ConstantFoldCompareInstOperands(unsigned Predicate, Constant *LHS, Constant *RHS, const DataLayout &DL, const TargetLibraryInfo *TLI=nullptr)
ConstantFoldCompareInstOperands - Attempt to constant fold a compare instruction (icmp/fcmp) with the...
static void addPrepareFunction(const Module &M, SmallVectorImpl< Function * > &Fns, StringRef Name)
static Function * createCloneDeclaration(Function &OrigF, coro::Shape &Shape, const Twine &Suffix, Module::iterator InsertBefore, AnyCoroSuspendInst *ActiveSuspend)
static bool shouldBeMustTail(const CallInst &CI, const Function &F)
This is an optimization pass for GlobalISel generic memory operations.
DISubprogram * getSubprogram() const
Get the subprogram for this scope.
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
static void updateCoroFrame(coro::Shape &Shape, Function *ResumeFn, Function *DestroyFn, Function *CleanupFn)
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
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.
A parsed version of the target data layout string in and methods for querying it.
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
SwitchLoweringStorage SwitchLowering
const Function * getParent() const
Return the enclosing method, or null if none.
bool isPointerTy() const
True if this is an instance of PointerType.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
FunctionListType::iterator iterator
The Function iterators.
static Function * getFunction(Constant *C)
This currently compiles esp xmm0 movsd esp eax eax esp ret We should use not the dag combiner This is because dagcombine2 needs to be able to see through the X86ISD::Wrapper which DAGCombine can t really do The code for turning x load into a single vector load is target independent and should be moved to the dag combiner The code for turning x load into a vector load can only handle a direct load from a global or a direct load from the stack It should be generalized to handle any load from P
static Constant * get(StructType *T, ArrayRef< Constant * > V)
ValueTy * getValPtr() const
static void addFramePointerAttrs(AttributeList &Attrs, LLVMContext &Context, unsigned ParamIndex, uint64_t Size, Align Alignment)
static bool hasCallsInBlockBetween(Instruction *From, Instruction *To)
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
bool isInlineAsm() const
Check if this call is an inline asm statement.
unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
@ Retcon
The "returned-continuation" lowering, where each suspend point creates a single continuation function...
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
The basic data container for the call graph of a Module of IR.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
FunctionAnalysisManager FAM
bool verifyFunction(const Function &F, raw_ostream *OS=nullptr)
Check a function for errors, useful for use when debugging a pass.
static bool hasCallsBetween(Instruction *Save, Instruction *ResumeOrDestroy)
@ Switch
The "resume-switch" lowering, where there are separate resume and destroy functions that are shared b...
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
static void scanPHIsAndUpdateValueMap(Instruction *Prev, BasicBlock *NewBlock, DenseMap< Value *, Value * > &ResolvedValues)
The instances of the Type class are immutable: once they are created, they are never changed.
bool removeUnreachableBlocks(Function &F, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Remove all blocks that can not be reached from the function's entry.
CoroAsyncResumeInst * getResumeFunction() const
AnyCoroIdInst * getId() const
AttributeList getAttributes() const
Return the parameter attributes for this call.
FunctionType * getFunctionType() const
static bool replaceCoroEndAsync(AnyCoroEndInst *End)
Replace an llvm.coro.end.async.
BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="", bool Before=false)
Split the basic block into two basic blocks at the specified instruction.
CoroAllocInst * getCoroAlloc()
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
static void handleNoSuspendCoroutine(coro::Shape &Shape)
unsigned getNumParams() const
Return the number of fixed parameters this function type requires.
const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
LLVM_NODISCARD T pop_back_val()
SwitchInst * ResumeSwitch
static void replaceCoroEnd(AnyCoroEndInst *End, const coro::Shape &Shape, Value *FramePtr, bool InResume, CallGraph *CG)
void buildCoroutineFrame(Function &F, Shape &Shape)
static IntegerType * getInt8Ty(LLVMContext &C)
static Constant * getPointerCast(Constant *C, Type *Ty)
Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant expression.
SmallPtrSet< MachineInstr *, 2 > Uses
LLVM Basic Block Representation.
void emitDealloc(IRBuilder<> &Builder, Value *Ptr, CallGraph *CG) const
Deallocate memory according to the rules of the active lowering.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
This represents the llvm.coro.align instruction.
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
PrettyStackTraceEntry - This class is used to represent a frame of the "pretty" stack trace that is d...
static void updateAsyncFuncPointerContextSize(coro::Shape &Shape)
static void addAsyncContextAttrs(AttributeList &Attrs, LLVMContext &Context, unsigned ParamIndex)
void setInfo(Constant *C)
This is the shared class of boolean and integer constants.
FunctionType * getType(LLVMContext &Context, ID id, ArrayRef< Type * > Tys=None)
Return the function type for an intrinsic.
bool IsFrameInlineInStorage
An SCC of the call graph.
GlobalVariable * AsyncFuncPointer
static void splitAsyncCoroutine(Function &F, coro::Shape &Shape, SmallVectorImpl< Function * > &Clones)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static Function * createClone(Function &F, const Twine &Suffix, coro::Shape &Shape, CoroCloner::Kind FKind)
static void addSwiftSelfAttrs(AttributeList &Attrs, LLVMContext &Context, unsigned ParamIndex)
(vector float) vec_cmpeq(*A, *B) C
ArrayRef< Type * > getRetconResultTypes() const
This represents the llvm.coro.suspend instruction.
void ReplaceInstWithInst(BasicBlock::InstListType &BIL, BasicBlock::iterator &BI, Instruction *I)
Replace the instruction specified by BI with the instruction specified by I.
static void splitRetconCoroutine(Function &F, coro::Shape &Shape, SmallVectorImpl< Function * > &Clones)
iterator_range< use_iterator > uses()
static void replaceFrameSizeAndAlignment(coro::Shape &Shape)
SmallVector< AnyCoroSuspendInst *, 4 > CoroSuspends
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...
SmallVector< AnyCoroEndInst *, 4 > CoroEnds
void replaceCoroFree(CoroIdInst *CoroId, bool Elide)
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
iterator_range< const_phi_iterator > phis() const
Returns a range that iterates over the phis in the basic block.
auto predecessors(MachineBasicBlock *BB)
This class implements an extremely fast bulk output stream that can only output to a stream.
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
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.
ArrayRef< Type * > params() const
SCC * lookupSCC(Node &N) const
Lookup a function's SCC in the graph.
static void splitSwitchCoroutine(Function &F, coro::Shape &Shape, SmallVectorImpl< Function * > &Clones)
This struct is a compact representation of a valid (non-zero power of two) alignment.
CallingConv::ID getCallingConv() const
AttrBuilder & addAlignmentAttr(MaybeAlign Align)
This turns an alignment into the form used internally in Attribute.
Node & get(Function &F)
Get a graph node for a given function, scanning it to populate the graph data as necessary.
IntegerType * getIndexType() const
AsyncLoweringStorage AsyncLowering
AttrBuilder & addAttribute(Attribute::AttrKind Val)
Add an attribute to the builder.
static bool hasCallsInBlocksBetween(BasicBlock *SaveBB, BasicBlock *ResDesBB)
This is the common base class for debug info intrinsics for variables.
SmallVector< CallInst *, 2 > SwiftErrorOps
inst_range instructions(Function *F)
static void setCoroInfo(Function &F, coro::Shape &Shape, ArrayRef< Function * > Fns)
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
ArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
static void simplifySuspendPoints(coro::Shape &Shape)
PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR)
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.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
void addSplitFunction(Function &OriginalFunction, Function &NewFunction)
Add a new function split/outlined from an existing function.
Module * getParent()
Get the module that this global value is contained inside of...
static ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
This is an important class for using LLVM in a threaded context.
static BranchInst * Create(BasicBlock *IfTrue, Instruction *InsertBefore=nullptr)
static void coerceArguments(IRBuilder<> &Builder, FunctionType *FnTy, ArrayRef< Value * > FnArgs, SmallVectorImpl< Value * > &CallArgs)
Coerce the arguments in FnArgs according to FnTy in CallArgs.
static void markCoroutineAsDone(IRBuilder<> &Builder, const coro::Shape &Shape, Value *FramePtr)
This represents the llvm.coro.suspend.async instruction.
Type * getParamType(unsigned i) const
Parameter type accessors.
SmallPriorityWorklist< LazyCallGraph::SCC *, 1 > & CWorklist
Worklist of the SCCs queued for processing.
AttrKind
This enumeration lists the attributes that can be associated with parameters, function results,...
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...
Class to represent pointers.
static void addMustTailToCoroResumes(Function &F)
static MDString * get(LLVMContext &Context, StringRef Str)
iterator find(const_arg_type_t< KeyT > Val)
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
StandardInstrumentations SI(Debug, VerifyEach)
static void replaceUnwindCoroEnd(AnyCoroEndInst *End, const coro::Shape &Shape, Value *FramePtr, bool InResume, CallGraph *CG)
Replace an unwind call to llvm.coro.end.
@ Async
The "async continuation" lowering, where each suspend point creates a single continuation function.
static coro::Shape splitCoroutine(Function &F, SmallVectorImpl< Function * > &Clones, bool OptimizeFrame)
bool OptimizeFrame
This would only be true if optimization are enabled.
bool isVoidTy() const
Return true if this is 'void'.
static ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
A Module instance is used to store all the information related to an LLVM module.
A node in the call graph.
void setOperand(unsigned i, Value *Val)
static void replaceAsyncResumeFunction(CoroSuspendAsyncInst *Suspend, Value *Continuation)
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 bool simplifyTerminatorLeadingToRet(Instruction *InitialInst)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
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.
SmallVector< MachineOperand, 4 > Cond
StringRef - Represent a constant reference to a string, i.e.
static void createResumeEntryBlock(Function &F, coro::Shape &Shape)
static void replaceSwiftErrorOps(Function &F, coro::Shape &Shape, ValueToValueMapTy *VMap)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Type * getType() const
All values are typed, get the type of this value.
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)
This represents the llvm.coro.id instruction.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
CoroBeginInst * CoroBegin
Type * getTypeAtIndex(const Value *V) const
Given an index value into the type, return the type of the element.
FunctionType * getResumeFunctionType() const
This represents the llvm.coro.alloc instruction.
StringRef getName() const
Return a constant reference to the value's name.
#define CORO_PRESPLIT_ATTR
BasicBlock * ResumeEntryBlock
RetconLoweringStorage RetconLowering
const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
static ConstantInt * getFalse(LLVMContext &Context)
amdgpu Simplify well known AMD library false FunctionCallee Callee
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 addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
adds the attribute to the list of attributes for the given arg.
SmallVector< CoroAlignInst *, 2 > CoroAligns
@ RetconOnce
The "unique returned-continuation" lowering, where each suspend point creates a single continuation f...
Support structure for SCC passes to communicate updates the call graph back to the CGSCC pass manager...
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
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...
static ConstantInt * getTrue(LLVMContext &Context)
void addSplitRefRecursiveFunctions(Function &OriginalFunction, ArrayRef< Function * > NewFunctions)
Add new ref-recursive functions split/outlined from an existing function.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
@ BR
Control flow instructions. These all have token chains.
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...
uint64_t value() const
This is a hole in the type system and should not be abused.
static ConstantTokenNone * get(LLVMContext &Context)
Return the ConstantTokenNone.
ConstantInt * getIndex(uint64_t Value) const
static FunctionType * getFunctionTypeFromAsyncSuspend(AnyCoroSuspendInst *Suspend)
AMDGPU Lower Kernel Arguments
void salvageDebugInfo(Instruction &I)
Assuming the instruction I is going to be deleted, attempt to salvage debug users of I by writing the...
PointerType * getPointerTo(unsigned AddrSpace=0) const
Return a pointer to the current type.
This class captures the data input to the InlineFunction call, and records the auxiliary results prod...
Value * emitAlloc(IRBuilder<> &Builder, Value *Size, CallGraph *CG) const
Allocate memory according to the rules of the active lowering.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
static Constant * get(ArrayType *T, ArrayRef< Constant * > V)
CoroIdInst * getSwitchCoroId() const
Value * getCalledOperand() const
static bool replaceAllPrepares(Function *PrepareFn, LazyCallGraph &CG, LazyCallGraph::SCC &C)
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.
unsigned getSwitchIndexField() const
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,...
AttrBuilder & addDereferenceableAttr(uint64_t Bytes)
This turns the number of dereferenceable bytes into the form used internally in Attribute.
@ ExternalLinkage
Externally visible function.
static Type * getVoidTy(LLVMContext &C)
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...
@ PrivateLinkage
Like Internal, but omit from symbol table.
CoroSaveInst * getCoroSave() const
This represents the llvm.coro.size instruction.
Value * getArgOperand(unsigned i) const
This class represents a freeze function that returns random concrete value if an operand is either a ...
static void maybeFreeRetconStorage(IRBuilder<> &Builder, const coro::Shape &Shape, Value *FramePtr, CallGraph *CG)
const BasicBlock * getParent() const
size_t size() const
size - Get the array size.
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...
This class represents the llvm.coro.begin instruction.
void removePredecessor(BasicBlock *Pred, bool KeepOneInputPHIs=false)
Update PHI nodes in this BasicBlock before removal of predecessor Pred.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
InlineResult InlineFunction(CallBase &CB, InlineFunctionInfo &IFI, AAResults *CalleeAAR=nullptr, bool InsertLifetime=true, Function *ForwardVarArgsTo=nullptr)
This function inlines the called function into the basic block of the caller.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
PointerType * getType() const
Global values are always pointers.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
A container for analyses that lazily runs them and caches their results.
static void replacePrepare(CallInst *Prepare, LazyCallGraph &CG, LazyCallGraph::SCC &C)
Replace a call to llvm.coro.prepare.retcon.
This class represents a function call, abstracting a target machine's calling convention.
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.
Common register allocation spilling lr str ldr sxth r3 ldr mla r4 can lr mov lr str ldr sxth r3 mla r4 and then merge mul and lr str ldr sxth r3 mla r4 It also increase the likelihood the store may become dead bb27 Successors according to LLVM BB
BlockVerifier::State From
void takeName(Value *V)
Transfer the name from V to this value.
static bool simplifySuspendPoint(CoroSuspendInst *Suspend, CoroBeginInst *CoroBegin)
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
A lazily constructed view of the call graph of a module.
bool contains(ConstPtrType Ptr) const
void reserve(size_type N)
A proxy from a FunctionAnalysisManager to an SCC.
Type * getReturnType() const
LLVM Value Representation.
iterator_range< user_iterator > users()
@ Async
"Asynchronous" unwind tables (instr precise)
void setInitializer(Constant *InitVal)
setInitializer - Sets the initializer for this global variable, removing any existing initializer if ...
Class to represent function types.
A Use represents the edge between a Value definition and its users.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.