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(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 updateLayoutInfo(FrameTypeBuilder &
B);
136 dbgs() <<
"------------- " << Title <<
" --------------\n";
137 for (
const auto &
E : Spills) {
140 for (
auto *
I :
E.second)
146 dbgs() <<
"------------- Allocas --------------\n";
147 for (
const auto &
A : Allocas) {
154using FieldIDType =
size_t;
159class FrameTypeBuilder {
165 uint64_t DynamicAlignBuffer;
168 const DataLayout &DL;
169 uint64_t StructSize = 0;
171 bool IsFinished =
false;
173 std::optional<Align> MaxFrameAlignment;
176 DenseMap<Value*, unsigned> FieldIndexByKey;
179 FrameTypeBuilder(
const DataLayout &DL, std::optional<Align> MaxFrameAlignment)
180 : DL(DL), MaxFrameAlignment(MaxFrameAlignment) {}
184 [[nodiscard]] FieldIDType addFieldForAlloca(AllocaInst *AI,
185 bool IsHeader =
false) {
189 "Coroutines cannot handle non static or vscale allocas yet");
190 return addField(
Size->getFixedValue(), AI->
getAlign(), IsHeader);
220 void addFieldForAllocas(
const Function &
F, FrameDataInfo &FrameData,
221 coro::Shape &Shape,
bool OptimizeFrame);
224 [[nodiscard]] FieldIDType addField(
Type *Ty, MaybeAlign MaybeFieldAlignment,
225 bool IsHeader =
false,
226 bool IsSpillOfValue =
false) {
227 assert(Ty &&
"must provide a type for a field");
229 uint64_t FieldSize = DL.getTypeAllocSize(Ty);
233 Align ABIAlign = DL.getABITypeAlign(Ty);
234 Align TyAlignment = ABIAlign;
235 if (IsSpillOfValue && MaxFrameAlignment && *MaxFrameAlignment < ABIAlign)
236 TyAlignment = *MaxFrameAlignment;
237 Align FieldAlignment = MaybeFieldAlignment.value_or(TyAlignment);
238 return addField(FieldSize, FieldAlignment, IsHeader);
242 [[nodiscard]] FieldIDType addField(uint64_t FieldSize, Align FieldAlignment,
243 bool IsHeader =
false) {
244 assert(!IsFinished &&
"adding fields to a finished builder");
254 uint64_t DynamicAlignBuffer = 0;
255 if (MaxFrameAlignment && (FieldAlignment > *MaxFrameAlignment)) {
258 FieldAlignment = *MaxFrameAlignment;
259 FieldSize = FieldSize + DynamicAlignBuffer;
266 StructSize =
Offset + FieldSize;
273 Fields.push_back({FieldSize,
Offset, FieldAlignment, DynamicAlignBuffer});
274 return Fields.size() - 1;
280 uint64_t getStructSize()
const {
281 assert(IsFinished &&
"not yet finished!");
285 Align getStructAlign()
const {
286 assert(IsFinished &&
"not yet finished!");
290 Field getLayoutField(FieldIDType Id)
const {
291 assert(IsFinished &&
"not yet finished!");
297void FrameDataInfo::updateLayoutInfo(FrameTypeBuilder &
B) {
298 auto Updater = [&](
Value *
I) {
299 uint32_t FieldIndex = getFieldIndex(
I);
300 auto Field =
B.getLayoutField(FieldIndex);
302 uint64_t dynamicAlign =
303 Field.DynamicAlignBuffer
306 setDynamicAlign(
I, dynamicAlign);
309 for (
auto &S : Spills)
311 for (
const auto &
A : Allocas)
315void FrameTypeBuilder::addFieldForAllocas(
const Function &
F,
316 FrameDataInfo &FrameData,
318 bool OptimizeFrame) {
324 for (
auto AllocaList : NonOverlapedAllocas) {
325 auto *LargestAI = *AllocaList.begin();
326 FieldIDType
Id = addFieldForAlloca(LargestAI);
327 for (
auto *Alloca : AllocaList)
332 if (!OptimizeFrame) {
334 AllocaInst *Alloca =
A.Alloca;
335 NonOverlapedAllocas.emplace_back(AllocaSetType(1, Alloca));
352 DenseMap<SwitchInst *, BasicBlock *> DefaultSuspendDest;
354 for (
auto *U : CoroSuspendInst->users()) {
356 auto *SWI =
const_cast<SwitchInst *
>(ConstSWI);
357 DefaultSuspendDest[SWI] = SWI->getDefaultDest();
358 SWI->setDefaultDest(SWI->getSuccessor(1));
363 auto ExtractAllocas = [&]() {
364 AllocaSetType Allocas;
365 Allocas.reserve(
FrameData.Allocas.size());
367 Allocas.push_back(
A.Alloca);
370 StackLifetime StackLifetimeAnalyzer(
F, ExtractAllocas(),
371 StackLifetime::LivenessType::May);
372 StackLifetimeAnalyzer.run();
373 auto DoAllocasInterfere = [&](
const AllocaInst *AI1,
const AllocaInst *AI2) {
374 return StackLifetimeAnalyzer.getLiveRange(AI1).overlaps(
375 StackLifetimeAnalyzer.getLiveRange(AI2));
377 auto GetAllocaSize = [&](
const coro::AllocaInfo &
A) {
378 std::optional<TypeSize> RetSize =
A.Alloca->getAllocationSize(
DL);
379 assert(RetSize &&
"Variable Length Arrays (VLA) are not supported.\n");
380 assert(!RetSize->isScalable() &&
"Scalable vectors are not yet supported");
381 return RetSize->getFixedValue();
387 sort(
FrameData.Allocas, [&](
const auto &Iter1,
const auto &Iter2) {
388 return GetAllocaSize(Iter1) > GetAllocaSize(Iter2);
391 AllocaInst *Alloca =
A.Alloca;
396 for (
auto &AllocaSet : NonOverlapedAllocas) {
397 assert(!AllocaSet.empty() &&
"Processing Alloca Set is not empty.\n");
398 bool NoInterference =
none_of(AllocaSet, [&](
auto Iter) {
399 return DoAllocasInterfere(Alloca, Iter);
407 bool Alignable = [&]() ->
bool {
408 auto *LargestAlloca = *AllocaSet.begin();
409 return LargestAlloca->getAlign().value() % Alloca->
getAlign().
value() ==
412 bool CouldMerge = NoInterference && Alignable;
415 AllocaSet.push_back(Alloca);
420 NonOverlapedAllocas.emplace_back(AllocaSetType(1, Alloca));
425 for (
auto SwitchAndDefaultDest : DefaultSuspendDest) {
426 SwitchInst *SWI = SwitchAndDefaultDest.first;
427 BasicBlock *DestBB = SwitchAndDefaultDest.second;
432 : NonOverlapedAllocas) {
433 if (AllocaSet.size() > 1) {
434 dbgs() <<
"In Function:" <<
F.getName() <<
"\n";
435 dbgs() <<
"Find Union Set "
437 dbgs() <<
"\tAllocas are \n";
438 for (
auto Alloca : AllocaSet)
439 dbgs() <<
"\t\t" << *Alloca <<
"\n";
444void FrameTypeBuilder::finish() {
445 assert(!IsFinished &&
"already finished!");
451 for (
auto &
Field : Fields) {
458 StructSize = SizeAndAlign.first;
459 StructAlign = SizeAndAlign.second;
461 auto getField = [](
const OptimizedStructLayoutField &LayoutField) ->
Field & {
462 return *
static_cast<Field *
>(
const_cast<void*
>(LayoutField.Id));
466 for (
auto &LayoutField : LayoutFields) {
467 auto &
F = getField(LayoutField);
468 F.Offset = LayoutField.Offset;
476 for (
auto *V : FrameData.getAllDefs()) {
480 auto CacheIt = [&DIVarCache, V](
const auto &Container) {
482 return DDI->getExpression()->getNumElements() == 0;
484 if (
I != Container.end())
485 DIVarCache.
insert({V, (*I)->getVariable()});
495 if (Ty->isIntegerTy()) {
501 return MDName->getString();
504 if (Ty->isFloatingPointTy()) {
507 if (Ty->isDoubleTy())
509 return "__floating_type_";
512 if (Ty->isPointerTy())
513 return "PointerType";
515 if (Ty->isStructTy()) {
517 return "__LiteralStructType_";
519 auto Name = Ty->getStructName();
522 for (
auto &Iter : Buffer)
523 if (Iter ==
'.' || Iter ==
':')
526 return MDName->getString();
529 return "UnknownType";
541 DIType *RetType =
nullptr;
543 if (Ty->isIntegerTy()) {
545 RetType = Builder.createBasicType(Name,
BitWidth, dwarf::DW_ATE_signed,
546 llvm::DINode::FlagArtificial);
547 }
else if (Ty->isFloatingPointTy()) {
550 llvm::DINode::FlagArtificial);
551 }
else if (Ty->isPointerTy()) {
563 }
else if (Ty->isStructTy()) {
564 auto *DIStruct = Builder.createStructType(
567 llvm::DINode::FlagArtificial,
nullptr, llvm::DINodeArray());
571 for (
unsigned I = 0;
I < StructTy->getNumElements();
I++) {
573 DIStruct, LineNum, DITypeCache);
575 Elements.push_back(Builder.createMemberType(
576 DIStruct, DITy->
getName(), DIStruct->getFile(), LineNum,
579 llvm::DINode::FlagArtificial, DITy));
582 Builder.replaceArrays(DIStruct, Builder.getOrCreateArray(Elements));
588 auto *CharSizeType = Builder.createBasicType(
589 Name, 8, dwarf::DW_ATE_unsigned_char, llvm::DINode::FlagArtificial);
592 RetType = CharSizeType;
597 RetType = Builder.createArrayType(
599 Builder.getOrCreateArray(Builder.getOrCreateSubrange(0,
Size / 8)));
603 DITypeCache.
insert({Ty, RetType});
620 FrameDataInfo &FrameData) {
625 if (!DIS || !DIS->getUnit())
629 DIS->getUnit()->getSourceLanguage().getUnversionedName())) ||
630 DIS->getUnit()->getEmissionKind() !=
635 "We could only build debug infomation for C++ coroutine now.\n");
640 unsigned LineNum = DIS->getLine();
643 DIS->getUnit(),
Twine(
F.getName() +
".coro_frame_ty").
str(), DFile,
645 llvm::DINode::FlagArtificial,
nullptr, llvm::DINodeArray());
656 unsigned UnknownTypeNum = 0;
662 FrameDITy, Name, DFile, LineNum, SizeInBits, Alignment,
Offset * 8,
663 llvm::DINode::FlagArtificial, DITy));
666 auto addDIDef = [&](
Value *V) {
669 Align Alignment = FrameData.getAlign(V);
675 auto It = DIVarCache.
find(V);
676 if (It != DIVarCache.
end()) {
678 Name = It->second->getName().str();
679 DITy = It->second->getType();
684 LineNum, DITypeCache);
687 DITy =
solveDIType(DBuilder, V->getType(), Layout, FrameDITy, LineNum,
690 assert(DITy &&
"SolveDIType shouldn't return nullptr.\n");
692 Name +=
"_" + std::to_string(UnknownTypeNum);
700 "unreachable due to addFieldForAlloca checks");
701 SizeInBits =
Size->getFixedValue() * 8;
707 addElement(Name, SizeInBits, Alignment.
value() * 8,
Offset, DITy);
717 FnPtrTy->getAddressSpace());
718 addElement(
"__resume_fn", PtrSize, PtrAlign, 0, DIPtr);
719 addElement(
"__destroy_fn", PtrSize, PtrAlign,
726 (IndexSize < 8) ? 8 : IndexSize,
727 dwarf::DW_ATE_unsigned_char));
729 auto Defs = FrameData.getAllDefs();
737 FrameDITy,
true, DINode::FlagArtificial);
746 DIS->retainNodes(&FrameDIVar, &FrameDIVar + 1);
752 assert(FrameDIVar->isValidLocationForIntrinsic(DILoc));
759 It->getParent()->insertDbgRecordBefore(NewDVR, It);
767 auto *Inst = dyn_cast<Instruction>(U.getUser());
768 if (!Inst || DT.dominates(Shape.CoroBegin, Inst))
771 if (auto *CI = dyn_cast<CallInst>(Inst)) {
776 if (CI->onlyReadsMemory() || CI->onlyReadsMemory(CI->getArgOperandNo(&U)))
801 bool OptimizeFrame) {
805 std::optional<Align> MaxFrameAlignment;
808 FrameTypeBuilder
B(
DL, MaxFrameAlignment);
811 std::optional<FieldIDType> SwitchIndexFieldId;
826 FrameData.setFieldIndex(
827 PromiseAlloca,
B.addFieldForAlloca(PromiseAlloca,
true));
834 SwitchIndexFieldId =
B.addField(SwitchIndexType,
MaybeAlign());
836 assert(PromiseAlloca ==
nullptr &&
"lowering doesn't support promises");
841 B.addFieldForAllocas(
F, FrameData, Shape, OptimizeFrame);
848 FrameData.Allocas.emplace_back(
853 for (
auto &S : FrameData.Spills) {
854 Type *FieldType = S.first->getType();
859 if (
A->hasByValAttr()) {
860 FieldType =
A->getParamByValType();
861 MA =
A->getParamAlign();
865 B.addField(FieldType, MA,
false ,
true );
866 FrameData.setFieldIndex(S.first, Id);
871 FrameData.updateLayoutInfo(
B);
882 auto IndexField =
B.getLayoutField(*SwitchIndexFieldId);
898 = (
B.getStructSize() <= Id->getStorageSize() &&
899 B.getStructAlign() <= Id->getStorageAlignment());
912 "The alignment requirment of frame variables cannot be higher than "
913 "the alignment of the async function context");
925 Arg->getParent()->removeParamAttr(Arg->getArgNo(), Attribute::Captures);
927 if (Arg->hasByValAttr())
928 return Arg->getParamByValType();
936 const FrameDataInfo &FrameData) {
943 G = Builder.CreateInBoundsPtrAdd(
G, OffsetVal,
944 Def->getName() +
Twine(
".spill.addr"));
946 auto SpillAlignment =
Align(FrameData.getAlign(Def));
950 auto &
DL = Builder.GetInsertBlock()->getDataLayout();
951 auto Size =
DL.getTypeStoreSize(ByValTy);
953 Builder.CreateMemCpy(
G, SpillAlignment, Def, SpillAlignment,
Size);
955 Builder.CreateAlignedStore(Def,
G, SpillAlignment);
967 Value *Ptr = Builder.CreateInBoundsPtrAdd(Shape.
FramePtr, OffsetVal);
970 if (FrameData.getDynamicAlign(Orig) != 0) {
974 auto *PtrValue = Builder.CreatePtrToInt(Ptr,
IntPtrTy);
976 PtrValue = Builder.CreateAdd(PtrValue, AlignMask);
977 PtrValue = Builder.CreateAnd(PtrValue, Builder.CreateNot(AlignMask));
978 return Builder.CreateIntToPtr(PtrValue, AI->
getType());
985 Ptr = Builder.CreateAddrSpaceCast(Ptr, Orig->
getType(),
993template <DbgVariableRecord::LocationType record_type>
994static TinyPtrVector<DbgVariableRecord *>
998 constexpr auto FindFunc =
1005 if (!
F.getSubprogram())
1008 Value *CurDef = Def;
1011 if (!LdInst->getType()->isPointerTy())
1013 CurDef = LdInst->getPointerOperand();
1016 Records = FindFunc(CurDef);
1029 Value *
Size = Builder.CreateAllocationSize(Builder.getInt64Ty(), Alloca);
1031 Builder.CreateMemCpy(
G, FrameData.getAlign(Alloca), Alloca,
1068 MDNode *TBAATag =
nullptr;
1074 (
F->getName() +
".Frame Slot").str(), TBAARoot);
1077 for (
auto const &
E : FrameData.Spills) {
1085 Value *CurrentReload =
nullptr;
1086 for (
auto *U :
E.second) {
1092 Builder.SetInsertPoint(CurrentBlock,
1096 GEP->setName(
E.first->getName() +
Twine(
".reload.addr"));
1098 CurrentReload =
GEP;
1100 auto SpillAlignment =
Align(FrameData.getAlign(Def));
1102 Builder.CreateAlignedLoad(
E.first->getType(),
GEP, SpillAlignment,
1103 E.first->getName() +
Twine(
".reload"));
1105 LI->setMetadata(LLVMContext::MD_tbaa, TBAATag);
1118 DDI->getExpression(), DDI->getDebugLoc(),
1120 Builder.GetInsertPoint()->getParent()->insertDbgRecordBefore(
1121 NewDVR, Builder.GetInsertPoint());
1133 auto SalvageOneCoro = [&](
auto *DDI) {
1140 Type *Ty = VAM->getValue()->getType();
1144 DDI->getExpression(), DDI->getDebugLoc(),
1147 Builder.GetInsertPoint()->getParent()->insertDbgRecordBefore(
1148 NewDVR, Builder.GetInsertPoint());
1153 for_each(DVRDeclareValues, SalvageOneCoro);
1159 assert(PN->getNumIncomingValues() == 1 &&
1160 "unexpected number of incoming "
1161 "values in the PHINode");
1162 PN->replaceAllUsesWith(CurrentReload);
1163 PN->eraseFromParent();
1169 U->replaceUsesOfWith(Def, CurrentReload);
1173 DVR.replaceVariableLocationOp(Def, CurrentReload,
true);
1188 Builder.SetInsertPoint(SpillBlock, SpillBlock->begin());
1189 for (
const auto &
P : FrameData.Allocas) {
1196 if (
I->isLifetimeStartOrEnd())
1197 I->eraseFromParent();
1202 G->takeName(Alloca);
1217 for (
const auto &
A : FrameData.Allocas) {
1219 UsersToUpdate.
clear();
1225 if (
I->isLifetimeStartOrEnd())
1226 I->eraseFromParent();
1231 if (UsersToUpdate.
empty())
1238 for (
auto *DVR : DbgVariableRecords)
1239 DVR->replaceVariableLocationOp(Alloca,
G);
1242 I->replaceUsesOfWith(Alloca,
G);
1248 for (
const auto &
A : FrameData.Allocas) {
1250 if (
A.MayWriteBeforeCoroBegin) {
1257 for (
const auto &Alias :
A.Aliases) {
1260 auto &
Value = *Alias.second;
1263 Builder.CreateInBoundsPtrAdd(
FramePtr, ConstantInt::get(ITy,
Value));
1264 Alias.first->replaceUsesWithIf(
1275 PHINode *UntilPHI =
nullptr) {
1278 int Index = PN->getBasicBlockIndex(InsertedBB);
1279 Value *V = PN->getIncomingValue(Index);
1281 V->getType(), 1, V->getName() +
Twine(
".") + SuccBB->
getName());
1284 PN->setIncomingValue(Index, InputV);
1286 }
while (PN != UntilPHI);
1323 Builder.CreateUnreachable();
1326 auto *NewCleanupPadBB =
1329 CleanupPadBB->
getParent(), CleanupPadBB);
1330 Builder.SetInsertPoint(NewCleanupPadBB);
1331 auto *SwitchType = Builder.getInt8Ty();
1332 auto *SetDispatchValuePN =
1333 Builder.CreatePHI(SwitchType,
pred_size(CleanupPadBB));
1335 CleanupPad->
insertAfter(SetDispatchValuePN->getIterator());
1336 auto *SwitchOnDispatch = Builder.CreateSwitch(SetDispatchValuePN, UnreachBB,
1339 int SwitchIndex = 0;
1345 Twine(
".from.") + Pred->getName(),
1346 CleanupPadBB->
getParent(), CleanupPadBB);
1348 CaseBB->setName(CleanupPadBB->
getName() +
Twine(
".from.") +
1350 Builder.SetInsertPoint(CaseBB);
1351 Builder.CreateBr(CleanupPadBB);
1358 auto *SwitchConstant = ConstantInt::get(SwitchType, SwitchIndex);
1359 SetDispatchValuePN->addIncoming(SwitchConstant, Pred);
1360 SwitchOnDispatch->addCase(SwitchConstant, CaseBB);
1367 for (
auto &BB :
F) {
1368 for (
auto &Phi : BB.phis()) {
1369 if (Phi.getNumIncomingValues() == 1) {
1375 while (!Worklist.
empty()) {
1377 auto *OriginalValue = Phi->getIncomingValue(0);
1378 Phi->replaceAllUsesWith(OriginalValue);
1407 if (
auto *CleanupPad =
1415 assert(CS->getUnwindDest() == &BB);
1444 IncomingBB->setName(BB.
getName() +
Twine(
".from.") + Pred->getName());
1463 if (PN->getNumIncomingValues() > 1)
1473 auto *BB =
I->getParent();
1474 if (&BB->front() ==
I) {
1475 if (BB->getSinglePredecessor()) {
1480 return BB->splitBasicBlock(
I, Name);
1493 unsigned depth = 3) {
1496 if (depth == 0)
return false;
1516 for (
auto *U : AI->
users()) {
1532 for (
auto *AI : LocalAllocas) {
1537 Value *StackSave =
nullptr;
1539 StackSave = Builder.CreateStackSave();
1542 auto Alloca = Builder.CreateAlloca(Builder.getInt8Ty(), AI->getSize());
1545 for (
auto *U : AI->
users()) {
1548 U->replaceAllUsesWith(Alloca);
1556 Builder.SetInsertPoint(FI);
1557 Builder.CreateStackRestore(StackSave);
1574 auto Call = Builder.CreateCall(FnTy, Fn, {});
1587 {V->getType()},
false);
1590 auto Call = Builder.CreateCall(FnTy, Fn, { V });
1609 auto ValueBeforeCall = Builder.CreateLoad(ValueTy, Alloca);
1616 Builder.SetInsertPoint(
Call->getNextNode());
1619 Builder.SetInsertPoint(Invoke->getNormalDest()->getFirstNonPHIOrDbg());
1624 Builder.CreateStore(ValueAfterCall, Alloca);
1661 F.getEntryBlock().getFirstNonPHIOrDbg());
1669 auto Alloca = Builder.CreateAlloca(ValueTy, ArgTy->getAddressSpace());
1674 Builder.CreateStore(InitialValue, Alloca);
1683 Builder.SetInsertPoint(End);
1684 auto FinalValue = Builder.CreateLoad(ValueTy, Alloca);
1699 for (
auto &Arg :
F.args()) {
1700 if (!Arg.hasSwiftErrorAttr())
continue;
1707 for (
auto &Inst :
F.getEntryBlock()) {
1720 if (!AllocasToPromote.
empty()) {
1738 DomSet.
insert(&
F.getEntryBlock());
1743 "should have split coro.suspend into its own block");
1758 return II->getIntrinsicID() == Intrinsic::lifetime_start;
1767 if (!U->hasOneUse() || U->stripPointerCasts() != AI)
1786 if (collectLifetimeStart(UI, AI))
1794 if (Valid && Lifetimes.
size() != 0) {
1795 auto *NewLifetime = Lifetimes[0]->clone();
1796 NewLifetime->replaceUsesOfWith(NewLifetime->getOperand(0), AI);
1797 NewLifetime->insertBefore(DomBB->getTerminator()->getIterator());
1801 S->eraseFromParent();
1809static std::optional<std::pair<Value &, DIExpression &>>
1814 auto InsertPt =
F->getEntryBlock().getFirstInsertionPt();
1817 Builder.SetInsertPoint(&
F->getEntryBlock(), InsertPt);
1821 Storage = LdInst->getPointerOperand();
1828 if (!SkipOutermostLoad)
1831 Storage = StInst->getValueOperand();
1838 if (!
Op || !AdditionalValues.
empty()) {
1846 SkipOutermostLoad =
false;
1849 return std::nullopt;
1856 const bool WillUseEntryValue =
1857 UseEntryValue && StorageAsArg &&
1858 StorageAsArg->hasAttribute(Attribute::SwiftAsync) &&
1861 if (WillUseEntryValue)
1870 if (StorageAsArg && !WillUseEntryValue && IsSingleLocationExpression) {
1871 auto &Cached = ArgToAllocaMap[StorageAsArg];
1873 Cached = Builder.CreateAlloca(Storage->
getType(), 0,
nullptr,
1874 Storage->
getName() +
".debug");
1875 Builder.CreateStore(Storage, Cached);
1889 return {{*Storage, *Expr}};
1908 Value *Storage = &SalvagedInfo->first;
1918 std::optional<BasicBlock::iterator> InsertPt;
1920 InsertPt =
I->getInsertionPointAfterDef();
1924 if (ILoc && DVRLoc &&
1925 DVRLoc->getScope()->getSubprogram() ==
1926 ILoc->getScope()->getSubprogram())
1929 InsertPt =
F->getEntryBlock().begin();
1938 Type *Ty = VAM->getValue()->getType();
1939 if (Ty->isPointerTy())
1945 (*InsertPt)->getParent()->insertDbgRecordBefore(&DVR, *InsertPt);
1965 if (
auto *Save = CSI->getCoroSave())
1979 auto *MustTailCallFn = AsyncEnd->getMustTailCallFunction();
1980 if (!MustTailCallFn)
1986 AsyncEnd->getDebugLoc(), MustTailCallFn,
TTI,
Arguments, Builder);
2019 LocalAllocas,
F, Checker, DT,
Shape);
2030 FrameDataInfo FrameData(Spills, Allocas);
2039 for (
auto *
I : DeadInstructions)
2040 I->eraseFromParent();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Lower Kernel Arguments
Rewrite undef for false bool rewritePHIs(Function &F, UniformityInfo &UA, DominatorTree *DT)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Expand Atomic instructions
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static void cleanupSinglePredPHIs(Function &F)
static TinyPtrVector< DbgVariableRecord * > findDbgRecordsThroughLoads(Function &F, Value *Def)
Find dbg.declare or dbg.declare_value records referencing Def.
static void createStoreIntoFrame(IRBuilder<> &Builder, Value *Def, Type *ByValTy, const coro::Shape &Shape, const FrameDataInfo &FrameData)
Store Def into the coroutine frame.
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 buildFrameLayout(Function &F, const DominatorTree &DT, coro::Shape &Shape, FrameDataInfo &FrameData, bool OptimizeFrame)
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 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 Value * createGEPToFramePointer(const FrameDataInfo &FrameData, IRBuilder<> &Builder, coro::Shape &Shape, Value *Orig)
Returns a pointer into the coroutine frame at the offset where Orig is located.
static bool hasAccessingPromiseBeforeCB(const DominatorTree &DT, coro::Shape &Shape)
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 Type * extractByvalIfArgument(Value *MaybeArgument)
If MaybeArgument is a byval Argument, return its byval type.
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)
static void handleAccessBeforeCoroBegin(const FrameDataInfo &FrameData, coro::Shape &Shape, IRBuilder<> &Builder, AllocaInst *Alloca)
static bool isLifetimeStart(const Instruction *Inst)
static MaybeAlign getAlign(Value *Ptr)
Module.h This file contains the declarations for the Module class.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
uint64_t IntrinsicInst * II
OptimizedStructLayoutField Field
This file provides an interface for laying out a sequence of fields as a struct in a way that attempt...
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 std::optional< TypeSize > getAllocationSize(const DataLayout &DL) const
Get allocation size in bytes.
void setAlignment(Align Align)
This class represents an incoming formal argument to a Function.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
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 BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
const Function * getParent() const
Return the enclosing method, or null if none.
LLVM_ABI InstListType::const_iterator getFirstNonPHIIt() const
Returns an iterator to the first instruction in this block that is not a PHINode instruction.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
const Instruction & front() const
LLVM_ABI const BasicBlock * getSingleSuccessor() const
Return the successor of this block if it has a single successor.
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.
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, DINodeArray Annotations=nullptr)
Create debugging information entry for a struct.
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, uint32_t DataSizeInBits=0)
Create debugging information entry for a basic type.
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
A parsed version of the target data layout string in and methods for querying it.
unsigned getPointerSizeInBits(unsigned AS=0) const
The size in bits of the pointer representation in a given address space.
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 getPointerABIAlignment(unsigned AS) const
Layout pointer alignment.
LLVM_ABI Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
LLVM_ABI void removeFromParent()
DebugLoc getDebugLoc() const
void setDebugLoc(DebugLoc Loc)
LLVM_ABI Function * getFunction()
Record of a variable value-assignment, aka a non instruction representation of the dbg....
LocationType getType() const
LocationType Type
Classification of the debug-info record that this DbgVariableRecord represents.
LLVM_ABI void replaceVariableLocationOp(Value *OldValue, Value *NewValue, bool AllowEmpty=false)
LLVM_ABI Value * getVariableLocationOp(unsigned OpIdx) const
void setExpression(DIExpression *NewExpr)
DIExpression * getExpression() const
bool isDbgDeclareValue() const
Metadata * getRawLocation() const
Returns the metadata operand for the first location description.
bool isDbgDeclare() const
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
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)
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.
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
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.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
Class to represent integer types.
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 MDNode * createTBAAScalarTypeNode(StringRef Name, MDNode *Parent, uint64_t Offset=0)
Return metadata for a TBAA scalar type node with the given name, an offset and a parent in the TBAA t...
LLVM_ABI MDNode * createTBAAStructTagNode(MDNode *BaseType, MDNode *AccessType, uint64_t Offset, bool IsConstant=false)
Return metadata for a TBAA tag node with the given base type, access type and offset relative to the ...
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
LLVMContext & getContext() const
static MDTuple * getIfExists(LLVMContext &Context, ArrayRef< Metadata * > MDs)
static LLVM_ABI MDString * getIfExists(LLVMContext &Context, StringRef Str)
static LLVM_ABI MDString * get(LLVMContext &Context, StringRef Str)
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...
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
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.
Represent a constant reference to a string, i.e.
std::string str() const
Get the contents as an std::string.
TypeSize getElementOffsetInBits(unsigned Idx) 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 * getInt64Ty(LLVMContext &C)
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
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.
LLVMContext & getContext() const
All values hold a context through their type.
iterator_range< user_iterator > users()
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.
StringRef str() const
Return a StringRef for the vector contents.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
SmallMapVector< Value *, SmallVector< Instruction *, 2 >, 8 > SpillInfo
@ 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...
@ Switch
The "resume-switch" lowering, where there are separate resume and destroy functions that are shared b...
LLVM_ABI 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<> &)
LLVM_ABI 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)
LLVM_ABI void collectSpillsFromArgs(SpillInfo &Spills, Function &F, const SuspendCrossingInfo &Checker)
LLVM_ABI 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,...
LLVM_ABI 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...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
unsigned Log2_64_Ceil(uint64_t Value)
Return the ceil log base 2 of the specified value, 64 if the value is zero.
auto successors(const MachineBasicBlock *BB)
scope_exit(Callable) -> scope_exit< Callable >
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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
auto dyn_cast_or_null(const Y &Val)
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)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
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.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
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...
DWARFExpression::Operation Op
LLVM_ABI TinyPtrVector< DbgVariableRecord * > findDVRDeclareValues(Value *V)
As above, for DVRDeclareValues.
ArrayRef(const T &OneElt) -> ArrayRef< T >
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.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
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.
constexpr 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.
Align getContextAlignment() const
uint64_t ContextHeaderSize
bool IsFrameInlineInStorage
AllocaInst * PromiseAlloca
AsyncLoweringStorage AsyncLowering
IntegerType * getIndexType() const
AnyCoroIdRetconInst * getRetconCoroId() const
PointerType * getSwitchResumePointerType() 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