45#define DEBUG_TYPE "coro-frame"
48class FrameTypeBuilder;
60 : Spills(Spills), Allocas(Allocas) {}
64 for (
const auto &
P : Spills)
66 for (
const auto &
A : Allocas)
72 auto Itr = FieldIndexMap.find(V);
73 assert(Itr != FieldIndexMap.end() &&
74 "Value does not have a frame field index");
79 assert((LayoutIndexUpdateStarted || FieldIndexMap.count(V) == 0) &&
80 "Cannot set the index for the same field twice.");
81 FieldIndexMap[V] = Index;
85 auto Iter = FieldAlignMap.find(V);
86 assert(Iter != FieldAlignMap.end());
91 assert(FieldAlignMap.count(V) == 0);
92 FieldAlignMap.insert({V, AL});
96 auto Iter = FieldDynamicAlignMap.find(V);
97 assert(Iter != FieldDynamicAlignMap.end());
102 assert(FieldDynamicAlignMap.count(V) == 0);
103 FieldDynamicAlignMap.insert({V,
Align});
107 auto Iter = FieldOffsetMap.find(V);
108 assert(Iter != FieldOffsetMap.end());
113 assert(FieldOffsetMap.count(V) == 0);
114 FieldOffsetMap.insert({V,
Offset});
118 void updateLayoutIndex(FrameTypeBuilder &
B);
123 bool LayoutIndexUpdateStarted =
false;
140 dbgs() <<
"------------- " << Title <<
" --------------\n";
141 for (
const auto &E : Spills) {
144 for (
auto *
I : E.second)
150 dbgs() <<
"------------- Allocas --------------\n";
151 for (
const auto &
A : Allocas) {
158using FieldIDType = size_t;
163class FrameTypeBuilder {
169 FieldIDType LayoutFieldIndex;
179 bool IsFinished =
false;
181 std::optional<Align> MaxFrameAlignment;
188 std::optional<Align> MaxFrameAlignment)
193 [[nodiscard]] FieldIDType addFieldForAlloca(
AllocaInst *AI,
194 bool IsHeader =
false) {
199 if (
auto *CI = dyn_cast<ConstantInt>(AI->
getArraySize()))
200 Ty = ArrayType::get(Ty, CI->getValue().getZExtValue());
205 return addField(Ty, AI->
getAlign(), IsHeader);
235 void addFieldForAllocas(
const Function &
F, FrameDataInfo &FrameData,
239 [[nodiscard]] FieldIDType addField(
Type *Ty,
MaybeAlign MaybeFieldAlignment,
240 bool IsHeader =
false,
241 bool IsSpillOfValue =
false) {
242 assert(!IsFinished &&
"adding fields to a finished builder");
243 assert(Ty &&
"must provide a type for a field");
250 if (FieldSize == 0) {
258 Align ABIAlign =
DL.getABITypeAlign(Ty);
259 Align TyAlignment = ABIAlign;
260 if (IsSpillOfValue && MaxFrameAlignment && *MaxFrameAlignment < ABIAlign)
261 TyAlignment = *MaxFrameAlignment;
262 Align FieldAlignment = MaybeFieldAlignment.value_or(TyAlignment);
268 if (MaxFrameAlignment && (FieldAlignment > *MaxFrameAlignment)) {
271 FieldAlignment = *MaxFrameAlignment;
272 FieldSize = FieldSize + DynamicAlignBuffer;
279 StructSize =
Offset + FieldSize;
286 Fields.
push_back({FieldSize,
Offset, Ty, 0, FieldAlignment, TyAlignment,
287 DynamicAlignBuffer});
288 return Fields.
size() - 1;
295 assert(IsFinished &&
"not yet finished!");
299 Align getStructAlign()
const {
300 assert(IsFinished &&
"not yet finished!");
304 FieldIDType getLayoutFieldIndex(FieldIDType Id)
const {
305 assert(IsFinished &&
"not yet finished!");
306 return Fields[
Id].LayoutFieldIndex;
309 Field getLayoutField(FieldIDType Id)
const {
310 assert(IsFinished &&
"not yet finished!");
316void FrameDataInfo::updateLayoutIndex(FrameTypeBuilder &
B) {
317 auto Updater = [&](
Value *
I) {
318 auto Field =
B.getLayoutField(getFieldIndex(
I));
319 setFieldIndex(
I,
Field.LayoutFieldIndex);
322 Field.DynamicAlignBuffer
325 setDynamicAlign(
I, dynamicAlign);
328 LayoutIndexUpdateStarted =
true;
329 for (
auto &S : Spills)
331 for (
const auto &
A : Allocas)
333 LayoutIndexUpdateStarted =
false;
336void FrameTypeBuilder::addFieldForAllocas(
const Function &
F,
337 FrameDataInfo &FrameData,
339 bool OptimizeFrame) {
345 for (
auto AllocaList : NonOverlapedAllocas) {
346 auto *LargestAI = *AllocaList.begin();
347 FieldIDType
Id = addFieldForAlloca(LargestAI);
348 for (
auto *Alloca : AllocaList)
353 if (!OptimizeFrame) {
356 NonOverlapedAllocas.emplace_back(AllocaSetType(1, Alloca));
376 if (
auto *ConstSWI = dyn_cast<SwitchInst>(U)) {
377 auto *SWI =
const_cast<SwitchInst *
>(ConstSWI);
378 DefaultSuspendDest[SWI] = SWI->getDefaultDest();
379 SWI->setDefaultDest(SWI->getSuccessor(1));
384 auto ExtractAllocas = [&]() {
385 AllocaSetType Allocas;
388 Allocas.push_back(
A.Alloca);
392 StackLifetime::LivenessType::May);
393 StackLifetimeAnalyzer.run();
395 return StackLifetimeAnalyzer.getLiveRange(AI1).overlaps(
396 StackLifetimeAnalyzer.getLiveRange(AI2));
399 std::optional<TypeSize> RetSize =
A.Alloca->getAllocationSize(
DL);
400 assert(RetSize &&
"Variable Length Arrays (VLA) are not supported.\n");
401 assert(!RetSize->isScalable() &&
"Scalable vectors are not yet supported");
402 return RetSize->getFixedValue();
408 sort(
FrameData.Allocas, [&](
const auto &Iter1,
const auto &Iter2) {
409 return GetAllocaSize(Iter1) > GetAllocaSize(Iter2);
417 for (
auto &AllocaSet : NonOverlapedAllocas) {
418 assert(!AllocaSet.empty() &&
"Processing Alloca Set is not empty.\n");
419 bool NoInterference =
none_of(AllocaSet, [&](
auto Iter) {
420 return DoAllocasInterfere(Alloca, Iter);
428 bool Alignable = [&]() ->
bool {
429 auto *LargestAlloca = *AllocaSet.begin();
430 return LargestAlloca->getAlign().value() % Alloca->
getAlign().
value() ==
433 bool CouldMerge = NoInterference && Alignable;
436 AllocaSet.push_back(Alloca);
441 NonOverlapedAllocas.emplace_back(AllocaSetType(1, Alloca));
446 for (
auto SwitchAndDefaultDest : DefaultSuspendDest) {
448 BasicBlock *DestBB = SwitchAndDefaultDest.second;
453 : NonOverlapedAllocas) {
454 if (AllocaSet.size() > 1) {
455 dbgs() <<
"In Function:" << F.getName() <<
"\n";
456 dbgs() <<
"Find Union Set "
458 dbgs() <<
"\tAllocas are \n";
459 for (auto Alloca : AllocaSet)
460 dbgs() <<
"\t\t" << *Alloca <<
"\n";
466 assert(!IsFinished &&
"already finished!");
472 for (
auto &
Field : Fields) {
479 StructSize = SizeAndAlign.first;
480 StructAlign = SizeAndAlign.second;
483 return *
static_cast<Field *
>(
const_cast<void*
>(LayoutField.Id));
489 for (
auto &LayoutField : LayoutFields) {
490 auto &
F = getField(LayoutField);
491 if (!
isAligned(
F.TyAlignment, LayoutField.Offset))
499 FieldTypes.
reserve(LayoutFields.size() * 3 / 2);
501 for (
auto &LayoutField : LayoutFields) {
502 auto &
F = getField(LayoutField);
504 auto Offset = LayoutField.Offset;
510 if (
Offset != LastOffset) {
517 F.LayoutFieldIndex = FieldTypes.
size();
520 if (
F.DynamicAlignBuffer) {
531 auto Layout =
DL.getStructLayout(Ty);
532 for (
auto &
F : Fields) {
534 assert(Layout->getElementOffset(
F.LayoutFieldIndex) ==
F.Offset);
545 for (
auto *V : FrameData.getAllDefs()) {
549 auto CacheIt = [&DIVarCache, V](
const auto &Container) {
553 if (
I != Container.end())
554 DIVarCache.
insert({V, (*I)->getVariable()});
567 OS <<
"__int_" << cast<IntegerType>(Ty)->getBitWidth();
569 return MDName->getString();
577 return "__floating_type_";
581 return "PointerType";
584 if (!cast<StructType>(Ty)->hasName())
585 return "__LiteralStructType_";
590 for (
auto &Iter : Buffer)
591 if (Iter ==
'.' || Iter ==
':')
594 return MDName->getString();
597 return "UnknownType";
609 DIType *RetType =
nullptr;
612 auto BitWidth = cast<IntegerType>(Ty)->getBitWidth();
614 llvm::DINode::FlagArtificial);
618 llvm::DINode::FlagArtificial);
635 llvm::DINode::FlagArtificial,
nullptr, llvm::DINodeArray());
637 auto *StructTy = cast<StructType>(Ty);
639 for (
unsigned I = 0;
I < StructTy->getNumElements();
I++) {
641 DIStruct, LineNum, DITypeCache);
644 DIStruct, DITy->
getName(), DIStruct->getFile(), LineNum,
647 llvm::DINode::FlagArtificial, DITy));
657 Name, 8, dwarf::DW_ATE_unsigned_char, llvm::DINode::FlagArtificial);
660 RetType = CharSizeType;
671 DITypeCache.
insert({Ty, RetType});
688 FrameDataInfo &FrameData) {
692 if (!DIS || !DIS->getUnit() ||
695 DIS->getUnit()->getEmissionKind() != DICompileUnit::DebugEmissionKind::FullDebug)
699 "We could only build debug infomation for C++ coroutine now.\n");
704 "Coroutine with switch ABI should own Promise alloca");
707 unsigned LineNum = DIS->getLine();
710 DIS->getUnit(),
Twine(
F.getName() +
".coro_frame_ty").
str(),
713 llvm::DINodeArray());
726 NameCache.
insert({ResumeIndex,
"__resume_fn"});
727 NameCache.
insert({DestroyIndex,
"__destroy_fn"});
728 NameCache.
insert({IndexIndex,
"__coro_index"});
749 dwarf::DW_ATE_unsigned_char)});
751 for (
auto *V : FrameData.getAllDefs()) {
752 auto It = DIVarCache.
find(V);
753 if (It == DIVarCache.
end())
756 auto Index = FrameData.getFieldIndex(V);
758 NameCache.
insert({Index, It->second->getName()});
759 TyCache.
insert({Index, It->second->getType()});
765 OffsetCache.
insert({ResumeIndex, {8, 0}});
766 OffsetCache.
insert({DestroyIndex, {8, 8}});
771 for (
auto *V : FrameData.getAllDefs()) {
772 auto Index = FrameData.getFieldIndex(V);
775 {Index, {FrameData.getAlign(V).
value(), FrameData.getOffset(V)}});
783 unsigned UnknownTypeNum = 0;
784 for (
unsigned Index = 0; Index < FrameTy->
getNumElements(); Index++) {
785 auto OCIt = OffsetCache.
find(Index);
786 if (OCIt == OffsetCache.
end())
796 assert(Ty->
isSized() &&
"We can't handle type which is not sized.\n");
798 AlignInBits = OCIt->second.first * 8;
799 OffsetInBits = OCIt->second.second * 8;
801 if (
auto It = NameCache.
find(Index); It != NameCache.
end()) {
802 Name = It->second.str();
803 DITy = TyCache[Index];
805 DITy =
solveDIType(DBuilder, Ty, Layout, FrameDITy, LineNum, DITypeCache);
806 assert(DITy &&
"SolveDIType shouldn't return nullptr.\n");
808 Name +=
"_" + std::to_string(UnknownTypeNum);
813 FrameDITy,
Name, DFile, LineNum, SizeInBits, AlignInBits, OffsetInBits,
814 llvm::DINode::FlagArtificial, DITy));
821 FrameDITy,
true, DINode::FlagArtificial);
830 auto RetainedNodes = DIS->getRetainedNodes();
832 RetainedNodes.end());
839 DILocation::get(DIS->
getContext(), LineNum, 1, DIS);
840 assert(FrameDIVar->isValidLocationForIntrinsic(DILoc));
845 DbgVariableRecord::LocationType::Declare);
847 It->getParent()->insertDbgRecordBefore(NewDVR, It);
859 FrameDataInfo &FrameData,
860 bool OptimizeFrame) {
865 std::optional<Align> MaxFrameAlignment;
866 if (Shape.
ABI == coro::ABI::Async)
868 FrameTypeBuilder
B(
C,
DL, MaxFrameAlignment);
871 std::optional<FieldIDType> SwitchIndexFieldId;
873 if (Shape.
ABI == coro::ABI::Switch) {
874 auto *FnPtrTy = PointerType::getUnqual(
C);
878 (void)
B.addField(FnPtrTy, std::nullopt,
true);
879 (void)
B.addField(FnPtrTy, std::nullopt,
true);
885 FrameData.setFieldIndex(
886 PromiseAlloca,
B.addFieldForAlloca(PromiseAlloca,
true));
893 SwitchIndexFieldId =
B.addField(IndexType, std::nullopt);
895 assert(PromiseAlloca ==
nullptr &&
"lowering doesn't support promises");
900 B.addFieldForAllocas(
F, FrameData, Shape, OptimizeFrame);
905 if (Shape.
ABI == coro::ABI::Switch && PromiseAlloca)
908 FrameData.Allocas.emplace_back(
911 for (
auto &S : FrameData.Spills) {
912 Type *FieldType = S.first->getType();
915 if (
const Argument *
A = dyn_cast<Argument>(S.first))
916 if (
A->hasByValAttr())
917 FieldType =
A->getParamByValType();
918 FieldIDType Id =
B.addField(FieldType, std::nullopt,
false ,
920 FrameData.setFieldIndex(S.first, Id);
925 Name.append(
".Frame");
926 return B.finish(
Name);
929 FrameData.updateLayoutIndex(
B);
934 case coro::ABI::Switch: {
936 auto IndexField =
B.getLayoutField(*SwitchIndexFieldId);
948 case coro::ABI::Retcon:
949 case coro::ABI::RetconOnce: {
952 = (
B.getStructSize() <= Id->getStorageSize() &&
953 B.getStructAlign() <= Id->getStorageAlignment());
956 case coro::ABI::Async: {
966 "The alignment requirment of frame variables cannot be higher than "
967 "the alignment of the async function context");
1009 auto GetFramePointer = [&](
Value *Orig) ->
Value * {
1010 FieldIDType Index = FrameData.getFieldIndex(Orig);
1016 if (
auto *AI = dyn_cast<AllocaInst>(Orig)) {
1017 if (
auto *CI = dyn_cast<ConstantInt>(AI->
getArraySize())) {
1018 auto Count = CI->getValue().getZExtValue();
1027 auto GEP = cast<GetElementPtrInst>(
1029 if (
auto *AI = dyn_cast<AllocaInst>(Orig)) {
1030 if (FrameData.getDynamicAlign(Orig) != 0) {
1033 auto *IntPtrTy = M->getDataLayout().getIntPtrType(AI->
getType());
1037 PtrValue = Builder.
CreateAdd(PtrValue, AlignMask);
1048 if (
GEP->getType() != Orig->getType())
1050 Orig->getName() +
Twine(
".cast"));
1055 for (
auto const &E : FrameData.Spills) {
1056 Value *Def = E.first;
1057 auto SpillAlignment =
Align(FrameData.getAlign(Def));
1062 Type *ByValTy =
nullptr;
1063 if (
auto *Arg = dyn_cast<Argument>(Def)) {
1066 Arg->getParent()->removeParamAttr(Arg->getArgNo(), Attribute::Captures);
1068 if (Arg->hasByValAttr())
1069 ByValTy = Arg->getParamByValType();
1072 auto Index = FrameData.getFieldIndex(Def);
1075 FrameTy,
FramePtr, 0, Index, Def->getName() +
Twine(
".spill.addr"));
1086 Value *CurrentReload =
nullptr;
1087 for (
auto *U : E.second) {
1091 if (CurrentBlock != U->getParent()) {
1092 CurrentBlock = U->getParent();
1096 auto *
GEP = GetFramePointer(E.first);
1097 GEP->setName(E.first->getName() +
Twine(
".reload.addr"));
1099 CurrentReload =
GEP;
1103 SpillAlignment, E.first->getName() +
Twine(
".reload"));
1109 if (
F->getSubprogram()) {
1111 while (DVRs.
empty() && isa<LoadInst>(CurDef)) {
1112 auto *LdInst = cast<LoadInst>(CurDef);
1114 if (LdInst->getPointerOperandType() != LdInst->getType())
1116 CurDef = LdInst->getPointerOperand();
1117 if (!isa<AllocaInst, LoadInst>(CurDef))
1129 DDI->getExpression(), DDI->getDebugLoc(),
1130 DbgVariableRecord::LocationType::Declare);
1143 if (
auto *PN = dyn_cast<PHINode>(U)) {
1144 assert(PN->getNumIncomingValues() == 1 &&
1145 "unexpected number of incoming "
1146 "values in the PHINode");
1147 PN->replaceAllUsesWith(CurrentReload);
1148 PN->eraseFromParent();
1154 U->replaceUsesOfWith(Def, CurrentReload);
1158 DVR.replaceVariableLocationOp(Def, CurrentReload,
true);
1170 if (Shape.
ABI == coro::ABI::Retcon || Shape.
ABI == coro::ABI::RetconOnce ||
1171 Shape.
ABI == coro::ABI::Async) {
1174 for (
const auto &
P : FrameData.Allocas) {
1176 auto *
G = GetFramePointer(Alloca);
1180 auto *
I = cast<Instruction>(U);
1181 if (
I->isLifetimeStartOrEnd())
1182 I->eraseFromParent();
1187 G->takeName(Alloca);
1202 for (
const auto &
A : FrameData.Allocas) {
1204 UsersToUpdate.
clear();
1206 auto *
I = cast<Instruction>(U);
1210 if (
I->isLifetimeStartOrEnd())
1211 I->eraseFromParent();
1216 if (UsersToUpdate.
empty())
1218 auto *
G = GetFramePointer(Alloca);
1223 for (
auto *DVR : DbgVariableRecords)
1224 DVR->replaceVariableLocationOp(Alloca,
G);
1227 I->replaceUsesOfWith(Alloca,
G);
1230 for (
const auto &
A : FrameData.Allocas) {
1232 if (
A.MayWriteBeforeCoroBegin) {
1236 "Coroutines cannot handle copying of array allocas yet");
1238 auto *
G = GetFramePointer(Alloca);
1245 for (
const auto &Alias :
A.Aliases) {
1246 auto *
FramePtr = GetFramePointer(Alloca);
1247 auto &
Value = *Alias.second;
1264 auto *Inst = dyn_cast<Instruction>(U.getUser());
1265 if (!Inst || DT.dominates(Shape.CoroBegin, Inst))
1268 if (auto *CI = dyn_cast<CallInst>(Inst)) {
1273 if (CI->onlyReadsMemory() ||
1274 CI->onlyReadsMemory(CI->getArgOperandNo(&U)))
1279 return isa<StoreInst>(Inst) ||
1282 isa<GetElementPtrInst>(Inst) ||
1287 isa<BitCastInst>(Inst);
1289 if (HasAccessingPromiseBeforeCB) {
1291 auto *
G = GetFramePointer(PA);
1303 PHINode *UntilPHI =
nullptr) {
1304 auto *PN = cast<PHINode>(&SuccBB->
front());
1306 int Index = PN->getBasicBlockIndex(InsertedBB);
1307 Value *V = PN->getIncomingValue(Index);
1309 V->getType(), 1, V->getName() +
Twine(
".") + SuccBB->
getName());
1312 PN->setIncomingValue(Index, InputV);
1313 PN = dyn_cast<PHINode>(PN->getNextNode());
1314 }
while (PN != UntilPHI);
1354 auto *NewCleanupPadBB =
1357 CleanupPadBB->
getParent(), CleanupPadBB);
1360 auto *SetDispatchValuePN =
1363 CleanupPad->
insertAfter(SetDispatchValuePN->getIterator());
1364 auto *SwitchOnDispatch = Builder.
CreateSwitch(SetDispatchValuePN, UnreachBB,
1367 int SwitchIndex = 0;
1373 Twine(
".from.") + Pred->getName(),
1374 CleanupPadBB->
getParent(), CleanupPadBB);
1376 CaseBB->setName(CleanupPadBB->
getName() +
Twine(
".from.") +
1386 auto *SwitchConstant = ConstantInt::get(SwitchType, SwitchIndex);
1387 SetDispatchValuePN->addIncoming(SwitchConstant, Pred);
1388 SwitchOnDispatch->addCase(SwitchConstant, CaseBB);
1395 for (
auto &BB :
F) {
1396 for (
auto &Phi : BB.phis()) {
1397 if (Phi.getNumIncomingValues() == 1) {
1403 while (!Worklist.
empty()) {
1405 auto *OriginalValue = Phi->getIncomingValue(0);
1406 Phi->replaceAllUsesWith(OriginalValue);
1435 if (
auto *CleanupPad =
1440 dyn_cast<CatchSwitchInst>(Pred->getTerminator())) {
1443 assert(CS->getUnwindDest() == &BB);
1472 IncomingBB->setName(BB.
getName() +
Twine(
".from.") + Pred->getName());
1490 if (
auto *PN = dyn_cast<PHINode>(&BB.front()))
1491 if (PN->getNumIncomingValues() > 1)
1501 auto *BB =
I->getParent();
1502 if (&BB->front() ==
I) {
1503 if (BB->getSinglePredecessor()) {
1508 return BB->splitBasicBlock(
I,
Name);
1521 unsigned depth = 3) {
1524 if (depth == 0)
return false;
1544 for (
auto *U : AI->
users()) {
1545 auto FI = dyn_cast<CoroAllocaFreeInst>(U);
1560 for (
auto *AI : LocalAllocas) {
1565 Value *StackSave =
nullptr;
1573 for (
auto *U : AI->
users()) {
1575 if (isa<CoroAllocaGetInst>(U)) {
1576 U->replaceAllUsesWith(Alloca);
1582 auto FI = cast<CoroAllocaFreeInst>(U);
1588 DeadInsts.
push_back(cast<Instruction>(U));
1599 auto FnTy = FunctionType::get(ValueTy, {},
false);
1602 auto Call = Builder.
CreateCall(FnTy, Fn, {});
1614 auto FnTy = FunctionType::get(Builder.
getPtrTy(),
1615 {V->getType()},
false);
1618 auto Call = Builder.
CreateCall(FnTy, Fn, { V });
1637 auto ValueBeforeCall = Builder.
CreateLoad(ValueTy, Alloca);
1643 if (isa<CallInst>(Call)) {
1646 auto Invoke = cast<InvokeInst>(Call);
1647 Builder.
SetInsertPoint(Invoke->getNormalDest()->getFirstNonPHIOrDbg());
1665 if (isa<LoadInst>(
User) || isa<StoreInst>(
User))
1669 auto Call = cast<Instruction>(
User);
1689 F.getEntryBlock().getFirstNonPHIOrDbg());
1691 auto ArgTy = cast<PointerType>(Arg.
getType());
1692 auto ValueTy = PointerType::getUnqual(
F.getContext());
1697 auto Alloca = Builder.
CreateAlloca(ValueTy, ArgTy->getAddressSpace());
1712 auto FinalValue = Builder.
CreateLoad(ValueTy, Alloca);
1727 for (
auto &Arg :
F.args()) {
1728 if (!Arg.hasSwiftErrorAttr())
continue;
1735 for (
auto &Inst :
F.getEntryBlock()) {
1736 auto Alloca = dyn_cast<AllocaInst>(&Inst);
1748 if (!AllocasToPromote.
empty()) {
1766 DomSet.
insert(&
F.getEntryBlock());
1771 "should have split coro.suspend into its own block");
1785 if (
auto*
II = dyn_cast<IntrinsicInst>(
I))
1786 return II->getIntrinsicID() == Intrinsic::lifetime_start;
1795 if (!U->hasOneUse() || U->stripPointerCasts() != AI)
1814 if (collectLifetimeStart(UI, AI))
1822 if (Valid && Lifetimes.
size() != 0) {
1823 auto *NewLifetime = Lifetimes[0]->clone();
1824 NewLifetime->replaceUsesOfWith(NewLifetime->getOperand(0), AI);
1825 NewLifetime->insertBefore(DomBB->getTerminator()->getIterator());
1829 S->eraseFromParent();
1837static std::optional<std::pair<Value &, DIExpression &>>
1842 auto InsertPt =
F->getEntryBlock().getFirstInsertionPt();
1843 while (isa<IntrinsicInst>(InsertPt))
1847 while (
auto *Inst = dyn_cast_or_null<Instruction>(Storage)) {
1848 if (
auto *LdInst = dyn_cast<LoadInst>(Inst)) {
1849 Storage = LdInst->getPointerOperand();
1856 if (!SkipOutermostLoad)
1858 }
else if (
auto *StInst = dyn_cast<StoreInst>(Inst)) {
1859 Storage = StInst->getValueOperand();
1866 if (!
Op || !AdditionalValues.
empty()) {
1874 SkipOutermostLoad =
false;
1877 return std::nullopt;
1879 auto *StorageAsArg = dyn_cast<Argument>(Storage);
1880 const bool IsSwiftAsyncArg =
1881 StorageAsArg && StorageAsArg->hasAttribute(Attribute::SwiftAsync);
1886 if (IsSwiftAsyncArg && UseEntryValue && !Expr->
isEntryValue() &&
1894 if (StorageAsArg && !IsSwiftAsyncArg) {
1895 auto &Cached = ArgToAllocaMap[StorageAsArg];
1898 Storage->
getName() +
".debug");
1913 return {{*Storage, *Expr}};
1932 Value *Storage = &SalvagedInfo->first;
1940 if (DVR.
getType() == DbgVariableRecord::LocationType::Declare) {
1941 std::optional<BasicBlock::iterator> InsertPt;
1942 if (
auto *
I = dyn_cast<Instruction>(Storage)) {
1943 InsertPt =
I->getInsertionPointAfterDef();
1947 if (ILoc && DVRLoc &&
1948 DVRLoc->getScope()->getSubprogram() ==
1949 ILoc->getScope()->getSubprogram())
1951 }
else if (isa<Argument>(Storage))
1952 InsertPt =
F->getEntryBlock().begin();
1955 (*InsertPt)->getParent()->insertDbgRecordBefore(&DVR, *InsertPt);
1966 if (
Shape.
ABI == coro::ABI::Switch &&
1975 if (
auto *Save = CSI->getCoroSave())
1988 if (
auto *AsyncEnd = dyn_cast<CoroAsyncEndInst>(CE)) {
1989 auto *MustTailCallFn = AsyncEnd->getMustTailCallFunction();
1990 if (!MustTailCallFn)
1996 AsyncEnd->getDebugLoc(), MustTailCallFn,
TTI,
Arguments, Builder);
2029 LocalAllocas,
F, Checker, DT,
Shape);
2040 FrameDataInfo FrameData(Spills, Allocas);
2049 for (
auto *
I : DeadInstructions)
2050 I->eraseFromParent();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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.
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...
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.
LLVM_ABI 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.
LLVM_ABI const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
LLVM_ABI 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.
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="", bool Before=false)
Split the basic block into two basic blocks at the specified instruction.
LLVM_ABI 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...
LLVM_ABI LLVMContext & getContext() const
Get the context in which this basic block lives.
static LLVM_ABI ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
static LLVM_ABI 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.
LLVM_ABI DIDerivedType * createMemberType(DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNo, Metadata *SizeInBits, uint32_t AlignInBits, Metadata *OffsetInBits, DINode::DIFlags Flags, DIType *Ty, DINodeArray Annotations=nullptr)
Create debugging information entry for a member.
LLVM_ABI 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.
LLVM_ABI 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.
LLVM_ABI DISubrange * getOrCreateSubrange(int64_t Lo, int64_t Count)
Create a descriptor for a value range.
LLVM_ABI 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.
LLVM_ABI DICompositeType * createStructType(DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, Metadata *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.
LLVM_ABI DINodeArray getOrCreateArray(ArrayRef< Metadata * > Elements)
Get a DINodeArray, create one if required.
LLVM_ABI DIExpression * createExpression(ArrayRef< uint64_t > Addr={})
Create a new descriptor for the specified variable which has a complex address expression for its add...
LLVM_ABI 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.
LLVM_ABI void replaceArrays(DICompositeType *&T, DINodeArray Elements, DINodeArray TParams=DINodeArray())
Replace arrays on a composite type.
LLVM_ABI bool isEntryValue() const
Check if the expression consists of exactly one entry value operand.
static LLVM_ABI 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...
LLVM_ABI DIExpression * foldConstantMath()
Try to shorten an expression with constant math operations that can be evaluated at compile time.
LLVM_ABI uint64_t getNumLocationOperands() const
Return the number of unique location operands referred to (via DW_OP_LLVM_arg) in this expression; th...
static LLVM_ABI 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 ...
LLVM_ABI 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.
Subprogram description. Uses SubclassData1.
StringRef getName() const
uint64_t getSizeInBits() const
LLVM_ABI 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.
LLVM_ABI const StructLayout * getStructLayout(StructType *Ty) const
Returns a StructLayout object, indicating the alignment of the struct, its size, and the offsets of i...
LLVM_ABI Align getABITypeAlign(Type *Ty) const
Returns the minimum ABI-required alignment for the specified type.
TypeSize getTypeSizeInBits(Type *Ty) const
Size examples:
LLVM_ABI Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
LLVM_ABI void removeFromParent()
LLVM_ABI Function * getFunction()
DebugLoc getDebugLoc() const
void setDebugLoc(DebugLoc Loc)
Record of a variable value-assignment, aka a non instruction representation of the dbg....
LocationType getType() const
void setExpression(DIExpression *NewExpr)
DIExpression * getExpression() const
LLVM_ABI Value * getVariableLocationOp(unsigned OpIdx) const
bool isDbgDeclare() const
LLVM_ABI 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.
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
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...
LLVM_ABI void removeFromParent()
This method unlinks 'this' from the containing basic block, but does not delete it.
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
LLVM_ABI void insertBefore(InstListType::iterator InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified position.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
LLVM_ABI void insertAfter(Instruction *InsertPos)
Insert an unlinked instruction into a basic block immediately after the specified instruction.
static LLVM_ABI 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...
LLVM_ABI void replaceOperandWith(unsigned I, Metadata *New)
Replace a specific operand.
LLVMContext & getContext() const
static LLVM_ABI 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 LLVM_ABI 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...
LLVM_ABI 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.
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
bool isPointerTy() const
True if this is an instance of PointerType.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
LLVM_ABI StringRef getStructName() const
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.
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.
bool isIntegerTy() const
True if this is an instance of IntegerType.
A Use represents the edge between a Value definition and its users.
LLVM_ABI void set(Value *Val)
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.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
LLVM_ABI 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...
LLVM_ABI LLVMContext & getContext() const
All values hold a context through their type.
iterator_range< use_iterator > uses()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
LLVM_ABI 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.
@ 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....
LLVM_ABI 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 salvageDebugInfo(SmallDenseMap< Argument *, AllocaInst *, 4 > &ArgToAllocaMap, DbgVariableRecord &DVR, bool UseEntryValue)
Attempts to rewrite the location operand of debug records in terms of the coroutine frame pointer,...
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.
LLVM_ABI 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.
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)
LLVM_ABI 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)
LLVM_ABI 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.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
LLVM_ABI 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.
LLVM_ABI 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...
LLVM_ABI 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
LLVM_ABI 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.
LLVM_ABI TinyPtrVector< DbgVariableRecord * > findDVRDeclares(Value *V)
Finds dbg.declare records declaring local variables as living in the memory that 'V' points to.
auto predecessors(const MachineBasicBlock *BB)
LLVM_ABI 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.
LLVM_ABI void findDbgUsers(Value *V, SmallVectorImpl< DbgVariableRecord * > &DbgVariableRecords)
Finds the debug info records describing a value.
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