46#define DEBUG_TYPE "coro-frame"
49class FrameTypeBuilder;
61 : Spills(Spills), Allocas(Allocas) {}
65 for (
const auto &
P : Spills)
67 for (
const auto &
A : Allocas)
73 auto Itr = FieldIndexMap.find(V);
74 assert(Itr != FieldIndexMap.end() &&
75 "Value does not have a frame field index");
80 assert((LayoutIndexUpdateStarted || FieldIndexMap.count(V) == 0) &&
81 "Cannot set the index for the same field twice.");
82 FieldIndexMap[V] = Index;
86 auto Iter = FieldAlignMap.find(V);
87 assert(Iter != FieldAlignMap.end());
92 assert(FieldAlignMap.count(V) == 0);
93 FieldAlignMap.insert({V, AL});
97 auto Iter = FieldDynamicAlignMap.find(V);
98 assert(Iter != FieldDynamicAlignMap.end());
103 assert(FieldDynamicAlignMap.count(V) == 0);
104 FieldDynamicAlignMap.insert({V,
Align});
108 auto Iter = FieldOffsetMap.find(V);
109 assert(Iter != FieldOffsetMap.end());
114 assert(FieldOffsetMap.count(V) == 0);
115 FieldOffsetMap.insert({V,
Offset});
119 void updateLayoutIndex(FrameTypeBuilder &
B);
124 bool LayoutIndexUpdateStarted =
false;
141 dbgs() <<
"------------- " << Title <<
" --------------\n";
142 for (
const auto &E : Spills) {
145 for (
auto *
I : E.second)
151 dbgs() <<
"------------- Allocas --------------\n";
152 for (
const auto &
A : Allocas) {
159using FieldIDType = size_t;
164class FrameTypeBuilder {
170 FieldIDType LayoutFieldIndex;
180 bool IsFinished =
false;
182 std::optional<Align> MaxFrameAlignment;
189 std::optional<Align> MaxFrameAlignment)
190 :
DL(
DL), Context(Context), MaxFrameAlignment(MaxFrameAlignment) {}
194 [[nodiscard]] FieldIDType addFieldForAlloca(
AllocaInst *AI,
195 bool IsHeader =
false) {
200 if (
auto *CI = dyn_cast<ConstantInt>(AI->
getArraySize()))
201 Ty = ArrayType::get(Ty, CI->getValue().getZExtValue());
206 return addField(Ty, AI->
getAlign(), IsHeader);
236 void addFieldForAllocas(
const Function &
F, FrameDataInfo &FrameData,
240 [[nodiscard]] FieldIDType addField(
Type *Ty,
MaybeAlign MaybeFieldAlignment,
241 bool IsHeader =
false,
242 bool IsSpillOfValue =
false) {
243 assert(!IsFinished &&
"adding fields to a finished builder");
244 assert(Ty &&
"must provide a type for a field");
251 if (FieldSize == 0) {
259 Align ABIAlign =
DL.getABITypeAlign(Ty);
260 Align TyAlignment = ABIAlign;
261 if (IsSpillOfValue && MaxFrameAlignment && *MaxFrameAlignment < ABIAlign)
262 TyAlignment = *MaxFrameAlignment;
263 Align FieldAlignment = MaybeFieldAlignment.value_or(TyAlignment);
269 if (MaxFrameAlignment && (FieldAlignment > *MaxFrameAlignment)) {
272 FieldAlignment = *MaxFrameAlignment;
273 FieldSize = FieldSize + DynamicAlignBuffer;
280 StructSize =
Offset + FieldSize;
287 Fields.
push_back({FieldSize,
Offset, Ty, 0, FieldAlignment, TyAlignment,
288 DynamicAlignBuffer});
289 return Fields.
size() - 1;
296 assert(IsFinished &&
"not yet finished!");
300 Align getStructAlign()
const {
301 assert(IsFinished &&
"not yet finished!");
305 FieldIDType getLayoutFieldIndex(FieldIDType Id)
const {
306 assert(IsFinished &&
"not yet finished!");
307 return Fields[
Id].LayoutFieldIndex;
310 Field getLayoutField(FieldIDType Id)
const {
311 assert(IsFinished &&
"not yet finished!");
317void FrameDataInfo::updateLayoutIndex(FrameTypeBuilder &
B) {
318 auto Updater = [&](
Value *
I) {
319 auto Field =
B.getLayoutField(getFieldIndex(
I));
320 setFieldIndex(
I,
Field.LayoutFieldIndex);
323 Field.DynamicAlignBuffer
326 setDynamicAlign(
I, dynamicAlign);
329 LayoutIndexUpdateStarted =
true;
330 for (
auto &S : Spills)
332 for (
const auto &
A : Allocas)
334 LayoutIndexUpdateStarted =
false;
337void FrameTypeBuilder::addFieldForAllocas(
const Function &
F,
338 FrameDataInfo &FrameData,
340 bool OptimizeFrame) {
346 for (
auto AllocaList : NonOverlapedAllocas) {
347 auto *LargestAI = *AllocaList.begin();
348 FieldIDType
Id = addFieldForAlloca(LargestAI);
349 for (
auto *Alloca : AllocaList)
354 if (!OptimizeFrame) {
357 NonOverlapedAllocas.emplace_back(AllocaSetType(1, Alloca));
377 if (
auto *ConstSWI = dyn_cast<SwitchInst>(U)) {
378 auto *SWI =
const_cast<SwitchInst *
>(ConstSWI);
379 DefaultSuspendDest[SWI] = SWI->getDefaultDest();
380 SWI->setDefaultDest(SWI->getSuccessor(1));
385 auto ExtractAllocas = [&]() {
386 AllocaSetType Allocas;
389 Allocas.push_back(
A.Alloca);
393 StackLifetime::LivenessType::May);
394 StackLifetimeAnalyzer.run();
396 return StackLifetimeAnalyzer.getLiveRange(AI1).overlaps(
397 StackLifetimeAnalyzer.getLiveRange(AI2));
400 std::optional<TypeSize> RetSize =
A.Alloca->getAllocationSize(
DL);
401 assert(RetSize &&
"Variable Length Arrays (VLA) are not supported.\n");
402 assert(!RetSize->isScalable() &&
"Scalable vectors are not yet supported");
403 return RetSize->getFixedValue();
409 sort(
FrameData.Allocas, [&](
const auto &Iter1,
const auto &Iter2) {
410 return GetAllocaSize(Iter1) > GetAllocaSize(Iter2);
418 for (
auto &AllocaSet : NonOverlapedAllocas) {
419 assert(!AllocaSet.empty() &&
"Processing Alloca Set is not empty.\n");
420 bool NoInterference =
none_of(AllocaSet, [&](
auto Iter) {
421 return DoAllocasInterfere(Alloca, Iter);
429 bool Alignable = [&]() ->
bool {
430 auto *LargestAlloca = *AllocaSet.begin();
431 return LargestAlloca->getAlign().value() % Alloca->
getAlign().
value() ==
434 bool CouldMerge = NoInterference && Alignable;
437 AllocaSet.push_back(Alloca);
442 NonOverlapedAllocas.emplace_back(AllocaSetType(1, Alloca));
447 for (
auto SwitchAndDefaultDest : DefaultSuspendDest) {
449 BasicBlock *DestBB = SwitchAndDefaultDest.second;
454 : NonOverlapedAllocas) {
455 if (AllocaSet.size() > 1) {
456 dbgs() <<
"In Function:" << F.getName() <<
"\n";
457 dbgs() <<
"Find Union Set "
459 dbgs() <<
"\tAllocas are \n";
460 for (auto Alloca : AllocaSet)
461 dbgs() <<
"\t\t" << *Alloca <<
"\n";
467 assert(!IsFinished &&
"already finished!");
473 for (
auto &
Field : Fields) {
480 StructSize = SizeAndAlign.first;
481 StructAlign = SizeAndAlign.second;
484 return *
static_cast<Field *
>(
const_cast<void*
>(LayoutField.Id));
490 for (
auto &LayoutField : LayoutFields) {
491 auto &
F = getField(LayoutField);
492 if (!
isAligned(
F.TyAlignment, LayoutField.Offset))
500 FieldTypes.
reserve(LayoutFields.size() * 3 / 2);
502 for (
auto &LayoutField : LayoutFields) {
503 auto &
F = getField(LayoutField);
505 auto Offset = LayoutField.Offset;
511 if (
Offset != LastOffset) {
518 F.LayoutFieldIndex = FieldTypes.
size();
521 if (
F.DynamicAlignBuffer) {
532 auto Layout =
DL.getStructLayout(Ty);
533 for (
auto &
F : Fields) {
535 assert(Layout->getElementOffset(
F.LayoutFieldIndex) ==
F.Offset);
546 for (
auto *V : FrameData.getAllDefs()) {
550 auto CacheIt = [&DIVarCache, V](
const auto &Container) {
554 if (
I != Container.end())
555 DIVarCache.
insert({V, (*I)->getVariable()});
569 OS <<
"__int_" << cast<IntegerType>(Ty)->getBitWidth();
571 return MDName->getString();
579 return "__floating_type_";
583 return "PointerType";
586 if (!cast<StructType>(Ty)->hasName())
587 return "__LiteralStructType_";
592 for (
auto &Iter : Buffer)
593 if (Iter ==
'.' || Iter ==
':')
596 return MDName->getString();
599 return "UnknownType";
611 DIType *RetType =
nullptr;
614 auto BitWidth = cast<IntegerType>(Ty)->getBitWidth();
616 llvm::DINode::FlagArtificial);
620 llvm::DINode::FlagArtificial);
637 llvm::DINode::FlagArtificial,
nullptr, llvm::DINodeArray());
639 auto *StructTy = cast<StructType>(Ty);
641 for (
unsigned I = 0;
I < StructTy->getNumElements();
I++) {
643 Scope, LineNum, DITypeCache);
646 Scope, DITy->
getName(), Scope->getFile(), LineNum,
649 llvm::DINode::FlagArtificial, DITy));
659 Name, 8, dwarf::DW_ATE_unsigned_char, llvm::DINode::FlagArtificial);
662 RetType = CharSizeType;
673 DITypeCache.
insert({Ty, RetType});
690 FrameDataInfo &FrameData) {
695 if (!DIS || !DIS->getUnit() ||
698 DIS->getUnit()->getEmissionKind() != DICompileUnit::DebugEmissionKind::FullDebug)
702 "We could only build debug infomation for C++ coroutine now.\n");
707 "Coroutine with switch ABI should own Promise alloca");
710 unsigned LineNum = DIS->getLine();
713 DIS->getUnit(),
Twine(
F.getName() +
".coro_frame_ty").
str(),
716 llvm::DINodeArray());
729 NameCache.
insert({ResumeIndex,
"__resume_fn"});
730 NameCache.
insert({DestroyIndex,
"__destroy_fn"});
731 NameCache.
insert({IndexIndex,
"__coro_index"});
752 dwarf::DW_ATE_unsigned_char)});
754 for (
auto *V : FrameData.getAllDefs()) {
755 auto It = DIVarCache.
find(V);
756 if (It == DIVarCache.
end())
759 auto Index = FrameData.getFieldIndex(V);
761 NameCache.
insert({Index, It->second->getName()});
762 TyCache.
insert({Index, It->second->getType()});
768 OffsetCache.
insert({ResumeIndex, {8, 0}});
769 OffsetCache.
insert({DestroyIndex, {8, 8}});
774 for (
auto *V : FrameData.getAllDefs()) {
775 auto Index = FrameData.getFieldIndex(V);
778 {Index, {FrameData.getAlign(V).
value(), FrameData.getOffset(V)}});
786 unsigned UnknownTypeNum = 0;
787 for (
unsigned Index = 0; Index < FrameTy->
getNumElements(); Index++) {
798 assert(Ty->
isSized() &&
"We can't handle type which is not sized.\n");
800 AlignInBits = OffsetCache[Index].first * 8;
801 OffsetInBits = OffsetCache[Index].second * 8;
803 if (
auto It = NameCache.
find(Index); It != NameCache.
end()) {
804 Name = It->second.str();
805 DITy = TyCache[Index];
807 DITy =
solveDIType(DBuilder, Ty, Layout, FrameDITy, LineNum, DITypeCache);
808 assert(DITy &&
"SolveDIType shouldn't return nullptr.\n");
810 Name +=
"_" + std::to_string(UnknownTypeNum);
815 FrameDITy,
Name, DFile, LineNum, SizeInBits, AlignInBits, OffsetInBits,
816 llvm::DINode::FlagArtificial, DITy));
823 FrameDITy,
true, DINode::FlagArtificial);
832 auto RetainedNodes = DIS->getRetainedNodes();
834 RetainedNodes.end());
841 DILocation::get(DIS->
getContext(), LineNum, 1, DIS);
842 assert(FrameDIVar->isValidLocationForIntrinsic(DILoc));
848 DbgVariableRecord::LocationType::Declare);
850 It->getParent()->insertDbgRecordBefore(NewDVR, It);
852 DBuilder.insertDeclare(Shape.
FramePtr, FrameDIVar,
867 FrameDataInfo &FrameData,
868 bool OptimizeFrame) {
873 std::optional<Align> MaxFrameAlignment;
874 if (Shape.
ABI == coro::ABI::Async)
876 FrameTypeBuilder
B(
C,
DL, MaxFrameAlignment);
879 std::optional<FieldIDType> SwitchIndexFieldId;
881 if (Shape.
ABI == coro::ABI::Switch) {
882 auto *FnPtrTy = PointerType::getUnqual(
C);
886 (void)
B.addField(FnPtrTy, std::nullopt,
true);
887 (void)
B.addField(FnPtrTy, std::nullopt,
true);
893 FrameData.setFieldIndex(
894 PromiseAlloca,
B.addFieldForAlloca(PromiseAlloca,
true));
901 SwitchIndexFieldId =
B.addField(IndexType, std::nullopt);
903 assert(PromiseAlloca ==
nullptr &&
"lowering doesn't support promises");
908 B.addFieldForAllocas(
F, FrameData, Shape, OptimizeFrame);
913 if (Shape.
ABI == coro::ABI::Switch && PromiseAlloca)
916 FrameData.Allocas.emplace_back(
919 for (
auto &S : FrameData.Spills) {
920 Type *FieldType = S.first->getType();
923 if (
const Argument *
A = dyn_cast<Argument>(S.first))
924 if (
A->hasByValAttr())
925 FieldType =
A->getParamByValType();
926 FieldIDType Id =
B.addField(FieldType, std::nullopt,
false ,
928 FrameData.setFieldIndex(S.first, Id);
933 Name.append(
".Frame");
934 return B.finish(
Name);
937 FrameData.updateLayoutIndex(
B);
942 case coro::ABI::Switch: {
944 auto IndexField =
B.getLayoutField(*SwitchIndexFieldId);
956 case coro::ABI::Retcon:
957 case coro::ABI::RetconOnce: {
960 = (
B.getStructSize() <= Id->getStorageSize() &&
961 B.getStructAlign() <= Id->getStorageAlignment());
964 case coro::ABI::Async: {
974 "The alignment requirment of frame variables cannot be higher than "
975 "the alignment of the async function context");
1017 auto GetFramePointer = [&](
Value *Orig) ->
Value * {
1018 FieldIDType Index = FrameData.getFieldIndex(Orig);
1024 if (
auto *AI = dyn_cast<AllocaInst>(Orig)) {
1025 if (
auto *CI = dyn_cast<ConstantInt>(AI->
getArraySize())) {
1026 auto Count = CI->getValue().getZExtValue();
1035 auto GEP = cast<GetElementPtrInst>(
1037 if (
auto *AI = dyn_cast<AllocaInst>(Orig)) {
1038 if (FrameData.getDynamicAlign(Orig) != 0) {
1041 auto *IntPtrTy = M->getDataLayout().getIntPtrType(AI->
getType());
1045 PtrValue = Builder.
CreateAdd(PtrValue, AlignMask);
1056 if (
GEP->getType() != Orig->getType())
1058 Orig->getName() +
Twine(
".cast"));
1063 for (
auto const &E : FrameData.Spills) {
1064 Value *Def = E.first;
1065 auto SpillAlignment =
Align(FrameData.getAlign(Def));
1070 Type *ByValTy =
nullptr;
1071 if (
auto *Arg = dyn_cast<Argument>(Def)) {
1074 Arg->getParent()->removeParamAttr(Arg->getArgNo(), Attribute::Captures);
1076 if (Arg->hasByValAttr())
1077 ByValTy = Arg->getParamByValType();
1080 auto Index = FrameData.getFieldIndex(Def);
1083 FrameTy,
FramePtr, 0, Index, Def->getName() +
Twine(
".spill.addr"));
1094 Value *CurrentReload =
nullptr;
1095 for (
auto *U : E.second) {
1099 if (CurrentBlock != U->getParent()) {
1100 CurrentBlock = U->getParent();
1104 auto *
GEP = GetFramePointer(E.first);
1105 GEP->setName(E.first->getName() +
Twine(
".reload.addr"));
1107 CurrentReload =
GEP;
1111 SpillAlignment, E.first->getName() +
Twine(
".reload"));
1118 if (
F->getSubprogram()) {
1120 while (DIs.
empty() && DVRs.
empty() && isa<LoadInst>(CurDef)) {
1121 auto *LdInst = cast<LoadInst>(CurDef);
1123 if (LdInst->getPointerOperandType() != LdInst->getType())
1125 CurDef = LdInst->getPointerOperand();
1126 if (!isa<AllocaInst, LoadInst>(CurDef))
1133 auto SalvageOne = [&](
auto *DDI) {
1134 bool AllowUnresolved =
false;
1141 DDI->getExpression(), DDI->getDebugLoc(),
1142 DbgVariableRecord::LocationType::Declare);
1147 .insertDeclare(CurrentReload, DDI->getVariable(),
1148 DDI->getExpression(), DDI->getDebugLoc(),
1162 if (
auto *PN = dyn_cast<PHINode>(U)) {
1163 assert(PN->getNumIncomingValues() == 1 &&
1164 "unexpected number of incoming "
1165 "values in the PHINode");
1166 PN->replaceAllUsesWith(CurrentReload);
1167 PN->eraseFromParent();
1173 U->replaceUsesOfWith(Def, CurrentReload);
1177 DVR.replaceVariableLocationOp(Def, CurrentReload,
true);
1189 if (Shape.
ABI == coro::ABI::Retcon || Shape.
ABI == coro::ABI::RetconOnce ||
1190 Shape.
ABI == coro::ABI::Async) {
1193 for (
const auto &
P : FrameData.Allocas) {
1195 auto *
G = GetFramePointer(Alloca);
1199 G->takeName(Alloca);
1214 for (
const auto &
A : FrameData.Allocas) {
1216 UsersToUpdate.
clear();
1218 auto *
I = cast<Instruction>(U);
1222 if (UsersToUpdate.
empty())
1224 auto *
G = GetFramePointer(Alloca);
1230 for (
auto *DVI : DIs)
1231 DVI->replaceUsesOfWith(Alloca,
G);
1232 for (
auto *DVR : DbgVariableRecords)
1233 DVR->replaceVariableLocationOp(Alloca,
G);
1239 if (
I->isLifetimeStartOrEnd()) {
1240 I->eraseFromParent();
1244 I->replaceUsesOfWith(Alloca,
G);
1248 for (
const auto &
A : FrameData.Allocas) {
1250 if (
A.MayWriteBeforeCoroBegin) {
1254 "Coroutines cannot handle copying of array allocas yet");
1256 auto *
G = GetFramePointer(Alloca);
1263 for (
const auto &Alias :
A.Aliases) {
1264 auto *
FramePtr = GetFramePointer(Alloca);
1265 auto &
Value = *Alias.second;
1282 auto *Inst = dyn_cast<Instruction>(U.getUser());
1283 if (!Inst || DT.dominates(Shape.CoroBegin, Inst))
1286 if (auto *CI = dyn_cast<CallInst>(Inst)) {
1291 if (CI->onlyReadsMemory() ||
1292 CI->onlyReadsMemory(CI->getArgOperandNo(&U)))
1297 return isa<StoreInst>(Inst) ||
1300 isa<GetElementPtrInst>(Inst) ||
1305 isa<BitCastInst>(Inst);
1307 if (HasAccessingPromiseBeforeCB) {
1309 auto *
G = GetFramePointer(PA);
1321 PHINode *UntilPHI =
nullptr) {
1322 auto *PN = cast<PHINode>(&SuccBB->
front());
1324 int Index = PN->getBasicBlockIndex(InsertedBB);
1325 Value *V = PN->getIncomingValue(Index);
1327 V->getType(), 1, V->getName() +
Twine(
".") + SuccBB->
getName());
1330 PN->setIncomingValue(Index, InputV);
1331 PN = dyn_cast<PHINode>(PN->getNextNode());
1332 }
while (PN != UntilPHI);
1372 auto *NewCleanupPadBB =
1375 CleanupPadBB->
getParent(), CleanupPadBB);
1378 auto *SetDispatchValuePN =
1381 CleanupPad->
insertAfter(SetDispatchValuePN->getIterator());
1382 auto *SwitchOnDispatch = Builder.
CreateSwitch(SetDispatchValuePN, UnreachBB,
1385 int SwitchIndex = 0;
1391 Twine(
".from.") + Pred->getName(),
1392 CleanupPadBB->
getParent(), CleanupPadBB);
1394 CaseBB->setName(CleanupPadBB->
getName() +
Twine(
".from.") +
1404 auto *SwitchConstant = ConstantInt::get(SwitchType, SwitchIndex);
1405 SetDispatchValuePN->addIncoming(SwitchConstant, Pred);
1406 SwitchOnDispatch->addCase(SwitchConstant, CaseBB);
1413 for (
auto &BB :
F) {
1414 for (
auto &Phi : BB.phis()) {
1415 if (Phi.getNumIncomingValues() == 1) {
1421 while (!Worklist.
empty()) {
1423 auto *OriginalValue = Phi->getIncomingValue(0);
1424 Phi->replaceAllUsesWith(OriginalValue);
1453 if (
auto *CleanupPad =
1458 dyn_cast<CatchSwitchInst>(Pred->getTerminator())) {
1461 assert(CS->getUnwindDest() == &BB);
1490 IncomingBB->setName(BB.
getName() +
Twine(
".from.") + Pred->getName());
1508 if (
auto *PN = dyn_cast<PHINode>(&BB.front()))
1509 if (PN->getNumIncomingValues() > 1)
1519 auto *BB =
I->getParent();
1520 if (&BB->front() ==
I) {
1521 if (BB->getSinglePredecessor()) {
1526 return BB->splitBasicBlock(
I,
Name);
1539 unsigned depth = 3) {
1542 if (depth == 0)
return false;
1562 for (
auto *U : AI->
users()) {
1563 auto FI = dyn_cast<CoroAllocaFreeInst>(U);
1578 for (
auto *AI : LocalAllocas) {
1583 Value *StackSave =
nullptr;
1591 for (
auto *U : AI->
users()) {
1593 if (isa<CoroAllocaGetInst>(U)) {
1594 U->replaceAllUsesWith(Alloca);
1600 auto FI = cast<CoroAllocaFreeInst>(U);
1606 DeadInsts.
push_back(cast<Instruction>(U));
1617 auto FnTy = FunctionType::get(ValueTy, {},
false);
1620 auto Call = Builder.
CreateCall(FnTy, Fn, {});
1632 auto FnTy = FunctionType::get(Builder.
getPtrTy(),
1633 {V->getType()},
false);
1636 auto Call = Builder.
CreateCall(FnTy, Fn, { V });
1655 auto ValueBeforeCall = Builder.
CreateLoad(ValueTy, Alloca);
1661 if (isa<CallInst>(Call)) {
1664 auto Invoke = cast<InvokeInst>(Call);
1665 Builder.
SetInsertPoint(Invoke->getNormalDest()->getFirstNonPHIOrDbg());
1683 if (isa<LoadInst>(
User) || isa<StoreInst>(
User))
1687 auto Call = cast<Instruction>(
User);
1707 F.getEntryBlock().getFirstNonPHIOrDbg());
1709 auto ArgTy = cast<PointerType>(Arg.
getType());
1710 auto ValueTy = PointerType::getUnqual(
F.getContext());
1715 auto Alloca = Builder.
CreateAlloca(ValueTy, ArgTy->getAddressSpace());
1730 auto FinalValue = Builder.
CreateLoad(ValueTy, Alloca);
1745 for (
auto &Arg :
F.args()) {
1746 if (!Arg.hasSwiftErrorAttr())
continue;
1753 for (
auto &Inst :
F.getEntryBlock()) {
1754 auto Alloca = dyn_cast<AllocaInst>(&Inst);
1766 if (!AllocasToPromote.
empty()) {
1784 DomSet.
insert(&
F.getEntryBlock());
1789 "should have split coro.suspend into its own block");
1803 if (
auto*
II = dyn_cast<IntrinsicInst>(
I))
1804 return II->getIntrinsicID() == Intrinsic::lifetime_start;
1813 if (!U->hasOneUse() || U->stripPointerCasts() != AI)
1832 if (collectLifetimeStart(UI, AI))
1840 if (Valid && Lifetimes.
size() != 0) {
1841 auto *NewLifetime = Lifetimes[0]->clone();
1842 NewLifetime->replaceUsesOfWith(NewLifetime->getOperand(1), AI);
1843 NewLifetime->insertBefore(DomBB->getTerminator()->getIterator());
1847 S->eraseFromParent();
1855static std::optional<std::pair<Value &, DIExpression &>>
1860 auto InsertPt =
F->getEntryBlock().getFirstInsertionPt();
1861 while (isa<IntrinsicInst>(InsertPt))
1865 while (
auto *Inst = dyn_cast_or_null<Instruction>(Storage)) {
1866 if (
auto *LdInst = dyn_cast<LoadInst>(Inst)) {
1867 Storage = LdInst->getPointerOperand();
1874 if (!SkipOutermostLoad)
1876 }
else if (
auto *StInst = dyn_cast<StoreInst>(Inst)) {
1877 Storage = StInst->getValueOperand();
1884 if (!
Op || !AdditionalValues.
empty()) {
1892 SkipOutermostLoad =
false;
1895 return std::nullopt;
1897 auto *StorageAsArg = dyn_cast<Argument>(Storage);
1898 const bool IsSwiftAsyncArg =
1899 StorageAsArg && StorageAsArg->hasAttribute(Attribute::SwiftAsync);
1904 if (IsSwiftAsyncArg && UseEntryValue && !Expr->
isEntryValue() &&
1912 if (StorageAsArg && !IsSwiftAsyncArg) {
1913 auto &Cached = ArgToAllocaMap[StorageAsArg];
1916 Storage->
getName() +
".debug");
1931 return {{*Storage, *Expr}};
1941 bool SkipOutermostLoad = !isa<DbgValueInst>(DVI);
1950 Value *Storage = &SalvagedInfo->first;
1958 if (isa<DbgDeclareInst>(DVI)) {
1959 std::optional<BasicBlock::iterator> InsertPt;
1960 if (
auto *
I = dyn_cast<Instruction>(Storage)) {
1961 InsertPt =
I->getInsertionPointAfterDef();
1965 if (ILoc && DVILoc &&
1966 DVILoc->getScope()->getSubprogram() ==
1967 ILoc->getScope()->getSubprogram())
1969 }
else if (isa<Argument>(Storage))
1970 InsertPt =
F->getEntryBlock().begin();
1972 DVI.
moveBefore(*(*InsertPt)->getParent(), *InsertPt);
1992 Value *Storage = &SalvagedInfo->first;
2000 if (DVR.
getType() == DbgVariableRecord::LocationType::Declare) {
2001 std::optional<BasicBlock::iterator> InsertPt;
2002 if (
auto *
I = dyn_cast<Instruction>(Storage)) {
2003 InsertPt =
I->getInsertionPointAfterDef();
2007 if (ILoc && DVRLoc &&
2008 DVRLoc->getScope()->getSubprogram() ==
2009 ILoc->getScope()->getSubprogram())
2011 }
else if (isa<Argument>(Storage))
2012 InsertPt =
F->getEntryBlock().begin();
2015 (*InsertPt)->getParent()->insertDbgRecordBefore(&DVR, *InsertPt);
2026 if (
Shape.
ABI == coro::ABI::Switch &&
2035 if (
auto *Save = CSI->getCoroSave())
2048 if (
auto *AsyncEnd = dyn_cast<CoroAsyncEndInst>(CE)) {
2049 auto *MustTailCallFn = AsyncEnd->getMustTailCallFunction();
2050 if (!MustTailCallFn)
2056 AsyncEnd->getDebugLoc(), MustTailCallFn,
TTI,
Arguments, Builder);
2089 LocalAllocas,
F, Checker, DT,
Shape);
2100 FrameDataInfo FrameData(Spills, Allocas);
2109 for (
auto *
I : DeadInstructions)
2110 I->eraseFromParent();
AMDGPU Lower Kernel Arguments
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Expand Atomic instructions
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static void cleanupSinglePredPHIs(Function &F)
static std::optional< std::pair< Value &, DIExpression & > > salvageDebugInfoImpl(SmallDenseMap< Argument *, AllocaInst *, 4 > &ArgToAllocaMap, bool UseEntryValue, Function *F, Value *Storage, DIExpression *Expr, bool SkipOutermostLoad)
static void eliminateSwiftError(Function &F, coro::Shape &Shape)
Eliminate all problematic uses of swifterror arguments and allocas from the function.
static void lowerLocalAllocas(ArrayRef< CoroAllocaAllocInst * > LocalAllocas, SmallVectorImpl< Instruction * > &DeadInsts)
Turn each of the given local allocas into a normal (dynamic) alloca instruction.
static Value * emitSetSwiftErrorValue(IRBuilder<> &Builder, Value *V, coro::Shape &Shape)
Set the given value as the current swifterror value.
static Value * emitSetAndGetSwiftErrorValueAround(Instruction *Call, AllocaInst *Alloca, coro::Shape &Shape)
Set the swifterror value from the given alloca before a call, then put in back in the alloca afterwar...
static void cacheDIVar(FrameDataInfo &FrameData, DenseMap< Value *, DILocalVariable * > &DIVarCache)
static bool localAllocaNeedsStackSave(CoroAllocaAllocInst *AI)
static void dumpAllocas(const SmallVectorImpl< coro::AllocaInfo > &Allocas)
static void splitAround(Instruction *I, const Twine &Name)
static void eliminateSwiftErrorAlloca(Function &F, AllocaInst *Alloca, coro::Shape &Shape)
Eliminate a formerly-swifterror alloca by inserting the get/set intrinsics and attempting to MemToReg...
static void rewritePHIs(BasicBlock &BB)
static void movePHIValuesToInsertedBlock(BasicBlock *SuccBB, BasicBlock *InsertedBB, BasicBlock *PredBB, PHINode *UntilPHI=nullptr)
static void dumpSpills(StringRef Title, const coro::SpillInfo &Spills)
static DIType * solveDIType(DIBuilder &Builder, Type *Ty, const DataLayout &Layout, DIScope *Scope, unsigned LineNum, DenseMap< Type *, DIType * > &DITypeCache)
static bool willLeaveFunctionImmediatelyAfter(BasicBlock *BB, unsigned depth=3)
After we split the coroutine, will the given basic block be along an obvious exit path for the resump...
static StructType * buildFrameType(Function &F, coro::Shape &Shape, FrameDataInfo &FrameData, bool OptimizeFrame)
static void eliminateSwiftErrorArgument(Function &F, Argument &Arg, coro::Shape &Shape, SmallVectorImpl< AllocaInst * > &AllocasToPromote)
"Eliminate" a swifterror argument by reducing it to the alloca case and then loading and storing in t...
static void buildFrameDebugInfo(Function &F, coro::Shape &Shape, FrameDataInfo &FrameData)
Build artificial debug info for C++ coroutine frames to allow users to inspect the contents of the fr...
static BasicBlock * splitBlockIfNotFirst(Instruction *I, const Twine &Name)
static void rewritePHIsForCleanupPad(BasicBlock *CleanupPadBB, CleanupPadInst *CleanupPad)
static void sinkLifetimeStartMarkers(Function &F, coro::Shape &Shape, SuspendCrossingInfo &Checker, const DominatorTree &DT)
For each local variable that all of its user are only used inside one of suspended region,...
static StringRef solveTypeName(Type *Ty)
Create name for Type.
static Value * emitGetSwiftErrorValue(IRBuilder<> &Builder, Type *ValueTy, coro::Shape &Shape)
Get the current swifterror value.
cl::opt< bool > UseNewDbgInfoFormat
static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape)
Given that RA is a live value
static bool isLifetimeStart(const Instruction *Inst)
static MaybeAlign getAlign(Value *Ptr)
Module.h This file contains the declarations for the Module class.
uint64_t IntrinsicInst * II
This file provides an interface for laying out a sequence of fields as a struct in a way that attempt...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static unsigned getNumElements(Type *Ty)
This file defines the make_scope_exit function, which executes user-defined cleanup logic at scope ex...
This file defines the SmallString class.
static const unsigned FramePtr
an instruction to allocate memory on the stack
bool isSwiftError() const
Return true if this alloca is used as a swifterror argument to a call.
void setSwiftError(bool V)
Specify whether this alloca is used to represent a swifterror.
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
PointerType * getType() const
Overload to return most specific pointer type.
Type * getAllocatedType() const
Return the type that is being allocated by the instruction.
bool isArrayAllocation() const
Return true if there is an allocation size parameter to the allocation instruction that is not 1.
void setAlignment(Align Align)
const Value * getArraySize() const
Get the number of elements allocated.
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.
LLVM Basic Block Representation.
iterator begin()
Instruction iterator methods.
const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
InstListType::const_iterator getFirstNonPHIIt() const
Returns an iterator to the first instruction in this block that is not a PHINode instruction.
const Instruction & front() const
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 * getSingleSuccessor() const
Return the successor of this block if it has a single successor.
const Function * getParent() const
Return the enclosing method, or null if none.
InstListType::iterator iterator
Instruction iterators...
LLVMContext & getContext() const
Get the context in which this basic block lives.
static ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
This represents the llvm.coro.alloca.alloc instruction.
This represents the llvm.coro.suspend instruction.
DIDerivedType * createPointerType(DIType *PointeeTy, uint64_t SizeInBits, uint32_t AlignInBits=0, std::optional< unsigned > DWARFAddressSpace=std::nullopt, StringRef Name="", DINodeArray Annotations=nullptr)
Create debugging information entry for a pointer.
DIBasicType * createBasicType(StringRef Name, uint64_t SizeInBits, unsigned Encoding, DINode::DIFlags Flags=DINode::FlagZero, uint32_t NumExtraInhabitants=0)
Create debugging information entry for a basic type.
DISubrange * getOrCreateSubrange(int64_t Lo, int64_t Count)
Create a descriptor for a value range.
DICompositeType * createArrayType(uint64_t Size, uint32_t AlignInBits, DIType *Ty, DINodeArray Subscripts, PointerUnion< DIExpression *, DIVariable * > DataLocation=nullptr, PointerUnion< DIExpression *, DIVariable * > Associated=nullptr, PointerUnion< DIExpression *, DIVariable * > Allocated=nullptr, PointerUnion< DIExpression *, DIVariable * > Rank=nullptr)
Create debugging information entry for an array.
DINodeArray getOrCreateArray(ArrayRef< Metadata * > Elements)
Get a DINodeArray, create one if required.
DIExpression * createExpression(ArrayRef< uint64_t > Addr={})
Create a new descriptor for the specified variable which has a complex address expression for its add...
DIDerivedType * createMemberType(DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNo, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, DINode::DIFlags Flags, DIType *Ty, DINodeArray Annotations=nullptr)
Create debugging information entry for a member.
DILocalVariable * createAutoVariable(DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNo, DIType *Ty, bool AlwaysPreserve=false, DINode::DIFlags Flags=DINode::FlagZero, uint32_t AlignInBits=0)
Create a new descriptor for an auto variable.
DICompositeType * createStructType(DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, uint64_t SizeInBits, uint32_t AlignInBits, DINode::DIFlags Flags, DIType *DerivedFrom, DINodeArray Elements, unsigned RunTimeLang=0, DIType *VTableHolder=nullptr, StringRef UniqueIdentifier="", DIType *Specification=nullptr, uint32_t NumExtraInhabitants=0)
Create debugging information entry for a struct.
void replaceArrays(DICompositeType *&T, DINodeArray Elements, DINodeArray TParams=DINodeArray())
Replace arrays on a composite type.
bool isEntryValue() const
Check if the expression consists of exactly one entry value operand.
static DIExpression * appendOpsToArg(const DIExpression *Expr, ArrayRef< uint64_t > Ops, unsigned ArgNo, bool StackValue=false)
Create a copy of Expr by appending the given list of Ops to each instance of the operand DW_OP_LLVM_a...
DIExpression * foldConstantMath()
Try to shorten an expression with constant math operations that can be evaluated at compile time.
uint64_t getNumLocationOperands() const
Return the number of unique location operands referred to (via DW_OP_LLVM_arg) in this expression; th...
static DIExpression * prepend(const DIExpression *Expr, uint8_t Flags, int64_t Offset=0)
Prepend DIExpr with a deref and offset operation and optionally turn it into a stack value or/and an ...
bool isSingleLocationExpression() const
Return whether the evaluated expression makes use of a single location at the start of the expression...
Base class for scope-like contexts.
StringRef getName() const
uint64_t getSizeInBits() const
uint32_t getAlignInBits() const
This class represents an Operation in the Expression.
A parsed version of the target data layout string in and methods for querying it.
const StructLayout * getStructLayout(StructType *Ty) const
Returns a StructLayout object, indicating the alignment of the struct, its size, and the offsets of i...
Align getABITypeAlign(Type *Ty) const
Returns the minimum ABI-required alignment for the specified type.
TypeSize getTypeSizeInBits(Type *Ty) const
Size examples:
Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
DebugLoc getDebugLoc() const
void setDebugLoc(DebugLoc Loc)
This is the common base class for debug info intrinsics for variables.
void replaceVariableLocationOp(Value *OldValue, Value *NewValue, bool AllowEmpty=false)
Value * getVariableLocationOp(unsigned OpIdx) const
void setExpression(DIExpression *NewExpr)
DIExpression * getExpression() const
Record of a variable value-assignment, aka a non instruction representation of the dbg....
LocationType getType() const
void setExpression(DIExpression *NewExpr)
DIExpression * getExpression() const
Value * getVariableLocationOp(unsigned OpIdx) const
bool isDbgDeclare() const
void replaceVariableLocationOp(Value *OldValue, Value *NewValue, bool AllowEmpty=false)
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
iterator find(const_arg_type_t< KeyT > Val)
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
void reserve(size_type NumEntries)
Grow the densemap so that it can contain at least NumEntries items before resizing again.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
Module * getParent()
Get the module that this global value is contained inside of...
AllocaInst * CreateAlloca(Type *Ty, unsigned AddrSpace, Value *ArraySize=nullptr, const Twine &Name="")
CallInst * CreateStackSave(const Twine &Name="")
Create a call to llvm.stacksave.
LoadInst * CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align, const char *Name)
UnreachableInst * CreateUnreachable()
BasicBlock::iterator GetInsertPoint() const
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
Value * CreatePtrAdd(Value *Ptr, Value *Offset, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
Value * CreateInBoundsGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="")
PHINode * CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name="")
Value * CreateNot(Value *V, 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...
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateConstInBoundsGEP2_32(Type *Ty, Value *Ptr, unsigned Idx0, unsigned Idx1, const Twine &Name="")
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
PointerType * getPtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer.
BranchInst * CreateBr(BasicBlock *Dest)
Create an unconditional 'br label X' instruction.
CallInst * CreateStackRestore(Value *Ptr, const Twine &Name="")
Create a call to llvm.stackrestore.
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
StoreInst * CreateAlignedStore(Value *Val, Value *Ptr, MaybeAlign Align, bool isVolatile=false)
IntegerType * getInt8Ty()
Fetch the type representing an 8-bit integer.
Value * CreateAddrSpaceCast(Value *V, Type *DestTy, const Twine &Name="")
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
void removeFromParent()
This method unlinks 'this' from the containing basic block, but does not delete it.
void insertBefore(Instruction *InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified instruction.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
const Function * getFunction() const
Return the function this instruction belongs to.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
void insertAfter(Instruction *InsertPos)
Insert an unlinked instruction into a basic block immediately after the specified instruction.
void moveBefore(Instruction *MovePos)
Unlink this instruction from its current basic block and insert it into the basic block that MovePos ...
static IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
This is an important class for using LLVM in a threaded context.
The landingpad instruction holds all of the information necessary to generate correct exception handl...
void replaceOperandWith(unsigned I, Metadata *New)
Replace a specific operand.
LLVMContext & getContext() const
static MDString * get(LLVMContext &Context, StringRef Str)
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
StringRef str() const
Explicit conversion to StringRef.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
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.
Compute live ranges of allocas.
StringRef - Represent a constant reference to a string, i.e.
std::string str() const
str - Get the contents as an std::string.
TypeSize getElementOffsetInBits(unsigned Idx) const
Class to represent struct types.
static StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
unsigned getNumElements() const
Random access to the elements.
Type * getElementType(unsigned N) const
bool isDefinitionAcrossSuspend(BasicBlock *DefBB, User *U) const
void setDefaultDest(BasicBlock *DefaultCase)
TinyPtrVector - This class is specialized for cases where there are normally 0 or 1 element in a vect...
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
std::string str() const
Return the twine contents as a std::string.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
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.
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
StringRef getStructName() const
static IntegerType * getIntNTy(LLVMContext &C, unsigned N)
bool isStructTy() const
True if this is an instance of StructType.
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
static IntegerType * getInt8Ty(LLVMContext &C)
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
static IntegerType * getInt32Ty(LLVMContext &C)
bool isIntegerTy() const
True if this is an instance of IntegerType.
A Use represents the edge between a Value definition and its users.
User * getUser() const
Returns the User that contains this Use.
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()
void replaceUsesWithIf(Value *New, llvm::function_ref< bool(Use &U)> ShouldReplace)
Go through the uses list for this definition and make each use point to "V" if the callback ShouldRep...
LLVMContext & getContext() const
All values hold a context through their type.
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.
std::function< bool(Instruction &I)> IsMaterializable
virtual void buildCoroutineFrame(bool OptimizeFrame)
constexpr ScalarTy getFixedValue() const
const ParentTy * getParent() const
self_iterator getIterator()
A raw_ostream that writes to an SmallVector or SmallString.
@ C
The default llvm calling convention, compatible with C.
void salvageDebugInfo(SmallDenseMap< Argument *, AllocaInst *, 4 > &ArgToAllocaMap, DbgVariableIntrinsic &DVI, bool IsEntryPoint)
Attempts to rewrite the location operand of debug intrinsics in terms of the coroutine frame pointer,...
@ Async
The "async continuation" lowering, where each suspend point creates a single continuation function.
@ RetconOnce
The "unique returned-continuation" lowering, where each suspend point creates a single continuation f...
@ Retcon
The "returned-continuation" lowering, where each suspend point creates a single continuation function...
BasicBlock::iterator getSpillInsertionPt(const coro::Shape &, Value *Def, const DominatorTree &DT)
bool isSuspendBlock(BasicBlock *BB)
void normalizeCoroutine(Function &F, coro::Shape &Shape, TargetTransformInfo &TTI)
CallInst * createMustTailCall(DebugLoc Loc, Function *MustTailCallFn, TargetTransformInfo &TTI, ArrayRef< Value * > Arguments, IRBuilder<> &)
void sinkSpillUsesAfterCoroBegin(const DominatorTree &DT, CoroBeginInst *CoroBegin, coro::SpillInfo &Spills, SmallVectorImpl< coro::AllocaInfo > &Allocas)
Async and Retcon{Once} conventions assume that all spill uses can be sunk after the coro....
void doRematerializations(Function &F, SuspendCrossingInfo &Checker, std::function< bool(Instruction &)> IsMaterializable)
void collectSpillsFromArgs(SpillInfo &Spills, Function &F, const SuspendCrossingInfo &Checker)
void collectSpillsFromDbgInfo(SpillInfo &Spills, Function &F, const SuspendCrossingInfo &Checker)
void collectSpillsAndAllocasFromInsts(SpillInfo &Spills, SmallVector< AllocaInfo, 8 > &Allocas, SmallVector< Instruction *, 4 > &DeadInstructions, SmallVector< CoroAllocaAllocInst *, 4 > &LocalAllocas, Function &F, const SuspendCrossingInfo &Checker, const DominatorTree &DT, const coro::Shape &Shape)
bool isCPlusPlus(SourceLanguage S)
This is an optimization pass for GlobalISel generic memory operations.
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
TinyPtrVector< DbgDeclareInst * > findDbgDeclares(Value *V)
Finds dbg.declare intrinsics declaring local variables as living in the memory that 'V' points to.
void PromoteMemToReg(ArrayRef< AllocaInst * > Allocas, DominatorTree &DT, AssumptionCache *AC=nullptr)
Promote the specified list of alloca instructions into scalar registers, inserting PHI nodes as appro...
detail::scope_exit< std::decay_t< Callable > > make_scope_exit(Callable &&F)
unsigned Log2_64_Ceil(uint64_t Value)
Return the ceil log base 2 of the specified value, 64 if the value is zero.
bool isAligned(Align Lhs, uint64_t SizeInBytes)
Checks that SizeInBytes is a multiple of the alignment.
void findDbgUsers(SmallVectorImpl< DbgVariableIntrinsic * > &DbgInsts, Value *V, SmallVectorImpl< DbgVariableRecord * > *DbgVariableRecords=nullptr)
Finds the debug info intrinsics describing a value.
auto successors(const MachineBasicBlock *BB)
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...
auto pred_size(const MachineBasicBlock *BB)
bool isAllocaPromotable(const AllocaInst *AI)
Return true if this alloca is legal for promotion.
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
void sort(IteratorTy Start, IteratorTy End)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
BasicBlock * ehAwareSplitEdge(BasicBlock *BB, BasicBlock *Succ, LandingPadInst *OriginalPad=nullptr, PHINode *LandingPadReplacement=nullptr, const CriticalEdgeSplittingOptions &Options=CriticalEdgeSplittingOptions(), const Twine &BBName="")
Split the edge connect the specficed blocks in the case that Succ is an Exception Handling Block.
Value * salvageDebugInfoImpl(Instruction &I, uint64_t CurrentLocOps, SmallVectorImpl< uint64_t > &Ops, SmallVectorImpl< Value * > &AdditionalValues)
uint64_t offsetToAlignment(uint64_t Value, Align Alignment)
Returns the offset to the next integer (mod 2**64) that is greater than or equal to Value and is a mu...
std::pair< uint64_t, Align > performOptimizedStructLayout(MutableArrayRef< OptimizedStructLayoutField > Fields)
Compute a layout for a struct containing the given fields, making a best-effort attempt to minimize t...
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
DWARFExpression::Operation Op
constexpr unsigned BitWidth
void updatePhiNodes(BasicBlock *DestBB, BasicBlock *OldPred, BasicBlock *NewPred, PHINode *Until=nullptr)
Replaces all uses of OldPred with the NewPred block in all PHINodes in a block.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
TinyPtrVector< DbgVariableRecord * > findDVRDeclares(Value *V)
As above, for DVRDeclares.
auto predecessors(const MachineBasicBlock *BB)
void setUnwindEdgeTo(Instruction *TI, BasicBlock *Succ)
Sets the unwind edge of an instruction to a particular successor.
static auto filterDbgVars(iterator_range< simple_ilist< DbgRecord >::iterator > R)
Filter the DbgRecord range to DbgVariableRecord types only and downcast.
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.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Align Alignment
The required alignment of this field.
uint64_t Offset
The offset of this field in the final layout.
uint64_t Size
The required size of this field in bytes.
static constexpr uint64_t FlexibleOffset
A special value for Offset indicating that the field can be moved anywhere.
A MapVector that performs no allocations if smaller than a certain size.
Align getContextAlignment() const
uint64_t ContextHeaderSize
bool IsFrameInlineInStorage
AllocaInst * PromiseAlloca
AsyncLoweringStorage AsyncLowering
AnyCoroIdRetconInst * getRetconCoroId() const
CoroIdInst * getSwitchCoroId() const
SmallVector< AnyCoroSuspendInst *, 4 > CoroSuspends
AllocaInst * getPromiseAlloca() const
SwitchLoweringStorage SwitchLowering
CoroBeginInst * CoroBegin
BasicBlock::iterator getInsertPtAfterFramePtr() const
RetconLoweringStorage RetconLowering
SmallVector< AnyCoroEndInst *, 4 > CoroEnds
SmallVector< CallInst *, 2 > SwiftErrorOps
BasicBlock * AllocaSpillBlock