46#define DEBUG_TYPE "coro-frame"
49class FrameTypeBuilder;
61 : Spills(Spills), Allocas(Allocas) {}
65 for (
const auto &
P : Spills)
67 for (
const auto &
A : Allocas)
73 auto Itr = FieldIndexMap.find(V);
74 assert(Itr != FieldIndexMap.end() &&
75 "Value does not have a frame field index");
80 assert((LayoutIndexUpdateStarted || FieldIndexMap.count(V) == 0) &&
81 "Cannot set the index for the same field twice.");
82 FieldIndexMap[V] = Index;
86 auto Iter = FieldAlignMap.find(V);
87 assert(Iter != FieldAlignMap.end());
92 assert(FieldAlignMap.count(V) == 0);
93 FieldAlignMap.insert({V, AL});
97 auto Iter = FieldDynamicAlignMap.find(V);
98 assert(Iter != FieldDynamicAlignMap.end());
103 assert(FieldDynamicAlignMap.count(V) == 0);
104 FieldDynamicAlignMap.insert({V,
Align});
108 auto Iter = FieldOffsetMap.find(V);
109 assert(Iter != FieldOffsetMap.end());
114 assert(FieldOffsetMap.count(V) == 0);
115 FieldOffsetMap.insert({V,
Offset});
119 void updateLayoutIndex(FrameTypeBuilder &
B);
124 bool LayoutIndexUpdateStarted =
false;
141 dbgs() <<
"------------- " << Title <<
" --------------\n";
142 for (
const auto &
E : Spills) {
145 for (
auto *
I :
E.second)
151 dbgs() <<
"------------- Allocas --------------\n";
152 for (
const auto &
A : Allocas) {
159using FieldIDType = size_t;
164class FrameTypeBuilder {
170 FieldIDType LayoutFieldIndex;
173 uint64_t DynamicAlignBuffer;
176 const DataLayout &DL;
177 LLVMContext &Context;
178 uint64_t StructSize = 0;
180 bool IsFinished =
false;
182 std::optional<Align> MaxFrameAlignment;
185 DenseMap<Value*, unsigned> FieldIndexByKey;
188 FrameTypeBuilder(LLVMContext &Context,
const DataLayout &DL,
189 std::optional<Align> MaxFrameAlignment)
190 : DL(DL), Context(Context), MaxFrameAlignment(MaxFrameAlignment) {}
194 [[nodiscard]] FieldIDType addFieldForAlloca(AllocaInst *AI,
195 bool IsHeader =
false) {
201 Ty = ArrayType::get(Ty, CI->getValue().getZExtValue());
206 return addField(Ty, AI->
getAlign(), IsHeader);
236 void addFieldForAllocas(
const Function &
F, FrameDataInfo &FrameData,
237 coro::Shape &Shape,
bool OptimizeFrame);
240 [[nodiscard]] FieldIDType addField(
Type *Ty, MaybeAlign MaybeFieldAlignment,
241 bool IsHeader =
false,
242 bool IsSpillOfValue =
false) {
243 assert(!IsFinished &&
"adding fields to a finished builder");
244 assert(Ty &&
"must provide a type for a field");
247 uint64_t FieldSize = DL.getTypeAllocSize(Ty);
251 if (FieldSize == 0) {
259 Align ABIAlign = DL.getABITypeAlign(Ty);
260 Align TyAlignment = ABIAlign;
261 if (IsSpillOfValue && MaxFrameAlignment && *MaxFrameAlignment < ABIAlign)
262 TyAlignment = *MaxFrameAlignment;
263 Align FieldAlignment = MaybeFieldAlignment.value_or(TyAlignment);
268 uint64_t DynamicAlignBuffer = 0;
269 if (MaxFrameAlignment && (FieldAlignment > *MaxFrameAlignment)) {
272 FieldAlignment = *MaxFrameAlignment;
273 FieldSize = FieldSize + DynamicAlignBuffer;
280 StructSize =
Offset + FieldSize;
287 Fields.push_back({FieldSize,
Offset, Ty, 0, FieldAlignment, TyAlignment,
288 DynamicAlignBuffer});
289 return Fields.size() - 1;
293 StructType *finish(StringRef Name);
295 uint64_t getStructSize()
const {
296 assert(IsFinished &&
"not yet finished!");
300 Align getStructAlign()
const {
301 assert(IsFinished &&
"not yet finished!");
305 FieldIDType getLayoutFieldIndex(FieldIDType Id)
const {
306 assert(IsFinished &&
"not yet finished!");
307 return Fields[
Id].LayoutFieldIndex;
310 Field getLayoutField(FieldIDType Id)
const {
311 assert(IsFinished &&
"not yet finished!");
317void FrameDataInfo::updateLayoutIndex(FrameTypeBuilder &
B) {
318 auto Updater = [&](
Value *
I) {
319 auto Field =
B.getLayoutField(getFieldIndex(
I));
320 setFieldIndex(
I,
Field.LayoutFieldIndex);
322 uint64_t dynamicAlign =
323 Field.DynamicAlignBuffer
326 setDynamicAlign(
I, dynamicAlign);
329 LayoutIndexUpdateStarted =
true;
330 for (
auto &S : Spills)
332 for (
const auto &
A : Allocas)
334 LayoutIndexUpdateStarted =
false;
337void FrameTypeBuilder::addFieldForAllocas(
const Function &
F,
338 FrameDataInfo &FrameData,
340 bool OptimizeFrame) {
346 for (
auto AllocaList : NonOverlapedAllocas) {
347 auto *LargestAI = *AllocaList.begin();
348 FieldIDType
Id = addFieldForAlloca(LargestAI);
349 for (
auto *Alloca : AllocaList)
354 if (!OptimizeFrame) {
356 AllocaInst *Alloca =
A.Alloca;
357 NonOverlapedAllocas.emplace_back(AllocaSetType(1, Alloca));
374 DenseMap<SwitchInst *, BasicBlock *> DefaultSuspendDest;
376 for (
auto *U : CoroSuspendInst->users()) {
378 auto *SWI =
const_cast<SwitchInst *
>(ConstSWI);
379 DefaultSuspendDest[SWI] = SWI->getDefaultDest();
380 SWI->setDefaultDest(SWI->getSuccessor(1));
385 auto ExtractAllocas = [&]() {
386 AllocaSetType Allocas;
387 Allocas.reserve(
FrameData.Allocas.size());
389 Allocas.push_back(
A.Alloca);
392 StackLifetime StackLifetimeAnalyzer(
F, ExtractAllocas(),
393 StackLifetime::LivenessType::May);
394 StackLifetimeAnalyzer.run();
395 auto DoAllocasInterfere = [&](
const AllocaInst *AI1,
const AllocaInst *AI2) {
396 return StackLifetimeAnalyzer.getLiveRange(AI1).overlaps(
397 StackLifetimeAnalyzer.getLiveRange(AI2));
399 auto GetAllocaSize = [&](
const coro::AllocaInfo &
A) {
400 std::optional<TypeSize> RetSize =
A.Alloca->getAllocationSize(
DL);
401 assert(RetSize &&
"Variable Length Arrays (VLA) are not supported.\n");
402 assert(!RetSize->isScalable() &&
"Scalable vectors are not yet supported");
403 return RetSize->getFixedValue();
409 sort(
FrameData.Allocas, [&](
const auto &Iter1,
const auto &Iter2) {
410 return GetAllocaSize(Iter1) > GetAllocaSize(Iter2);
413 AllocaInst *Alloca =
A.Alloca;
418 for (
auto &AllocaSet : NonOverlapedAllocas) {
419 assert(!AllocaSet.empty() &&
"Processing Alloca Set is not empty.\n");
420 bool NoInterference =
none_of(AllocaSet, [&](
auto Iter) {
421 return DoAllocasInterfere(Alloca, Iter);
429 bool Alignable = [&]() ->
bool {
430 auto *LargestAlloca = *AllocaSet.begin();
431 return LargestAlloca->getAlign().value() % Alloca->
getAlign().
value() ==
434 bool CouldMerge = NoInterference && Alignable;
437 AllocaSet.push_back(Alloca);
442 NonOverlapedAllocas.emplace_back(AllocaSetType(1, Alloca));
447 for (
auto SwitchAndDefaultDest : DefaultSuspendDest) {
448 SwitchInst *SWI = SwitchAndDefaultDest.first;
449 BasicBlock *DestBB = SwitchAndDefaultDest.second;
454 : NonOverlapedAllocas) {
455 if (AllocaSet.size() > 1) {
456 dbgs() <<
"In Function:" <<
F.getName() <<
"\n";
457 dbgs() <<
"Find Union Set "
459 dbgs() <<
"\tAllocas are \n";
460 for (
auto Alloca : AllocaSet)
461 dbgs() <<
"\t\t" << *Alloca <<
"\n";
466StructType *FrameTypeBuilder::finish(StringRef Name) {
467 assert(!IsFinished &&
"already finished!");
473 for (
auto &
Field : Fields) {
480 StructSize = SizeAndAlign.first;
481 StructAlign = SizeAndAlign.second;
483 auto getField = [](
const OptimizedStructLayoutField &LayoutField) ->
Field & {
484 return *
static_cast<Field *
>(
const_cast<void*
>(LayoutField.Id));
490 for (
auto &LayoutField : LayoutFields) {
491 auto &
F = getField(LayoutField);
492 if (!
isAligned(
F.TyAlignment, LayoutField.Offset))
500 FieldTypes.
reserve(LayoutFields.size() * 3 / 2);
501 uint64_t LastOffset = 0;
502 for (
auto &LayoutField : LayoutFields) {
503 auto &
F = getField(LayoutField);
505 auto Offset = LayoutField.Offset;
511 if (
Offset != LastOffset) {
518 F.LayoutFieldIndex = FieldTypes.
size();
521 if (
F.DynamicAlignBuffer) {
523 ArrayType::get(Type::getInt8Ty(
Context),
F.DynamicAlignBuffer));
532 auto Layout =
DL.getStructLayout(Ty);
533 for (
auto &
F : Fields) {
535 assert(Layout->getElementOffset(
F.LayoutFieldIndex) ==
F.Offset);
546 for (
auto *V : FrameData.getAllDefs()) {
550 auto CacheIt = [&DIVarCache, V](
const auto &Container) {
552 return DDI->getExpression()->getNumElements() == 0;
554 if (
I != Container.end())
555 DIVarCache.
insert({V, (*I)->getVariable()});
565 if (Ty->isIntegerTy()) {
571 return MDName->getString();
574 if (Ty->isFloatingPointTy()) {
577 if (Ty->isDoubleTy())
579 return "__floating_type_";
582 if (Ty->isPointerTy())
583 return "PointerType";
585 if (Ty->isStructTy()) {
587 return "__LiteralStructType_";
589 auto Name = Ty->getStructName();
592 for (
auto &Iter : Buffer)
593 if (Iter ==
'.' || Iter ==
':')
596 return MDName->getString();
599 return "UnknownType";
611 DIType *RetType =
nullptr;
613 if (Ty->isIntegerTy()) {
615 RetType = Builder.createBasicType(Name,
BitWidth, dwarf::DW_ATE_signed,
616 llvm::DINode::FlagArtificial);
617 }
else if (Ty->isFloatingPointTy()) {
620 llvm::DINode::FlagArtificial);
621 }
else if (Ty->isPointerTy()) {
633 }
else if (Ty->isStructTy()) {
634 auto *DIStruct = Builder.createStructType(
637 llvm::DINode::FlagArtificial,
nullptr, llvm::DINodeArray());
641 for (
unsigned I = 0;
I < StructTy->getNumElements();
I++) {
643 DIStruct, LineNum, DITypeCache);
645 Elements.push_back(Builder.createMemberType(
646 DIStruct, DITy->
getName(), DIStruct->getFile(), LineNum,
649 llvm::DINode::FlagArtificial, DITy));
652 Builder.replaceArrays(DIStruct, Builder.getOrCreateArray(Elements));
658 auto *CharSizeType = Builder.createBasicType(
659 Name, 8, dwarf::DW_ATE_unsigned_char, llvm::DINode::FlagArtificial);
662 RetType = CharSizeType;
667 RetType = Builder.createArrayType(
669 Builder.getOrCreateArray(Builder.getOrCreateSubrange(0,
Size / 8)));
673 DITypeCache.
insert({Ty, RetType});
690 FrameDataInfo &FrameData) {
695 if (!DIS || !DIS->getUnit())
699 DIS->getUnit()->getSourceLanguage().getUnversionedName())) ||
700 DIS->getUnit()->getEmissionKind() !=
705 "We could only build debug infomation for C++ coroutine now.\n");
710 unsigned LineNum = DIS->getLine();
713 DIS->getUnit(),
Twine(
F.getName() +
".coro_frame_ty").
str(),
716 llvm::DINodeArray());
729 NameCache.
insert({ResumeIndex,
"__resume_fn"});
730 NameCache.
insert({DestroyIndex,
"__destroy_fn"});
731 NameCache.
insert({IndexIndex,
"__coro_index"});
752 dwarf::DW_ATE_unsigned_char)});
754 for (
auto *V : FrameData.getAllDefs()) {
755 auto It = DIVarCache.
find(V);
756 if (It == DIVarCache.
end())
759 auto Index = FrameData.getFieldIndex(V);
761 NameCache.
insert({Index, It->second->getName()});
762 TyCache.
insert({Index, It->second->getType()});
768 OffsetCache.
insert({ResumeIndex, {8, 0}});
769 OffsetCache.
insert({DestroyIndex, {8, 8}});
774 for (
auto *V : FrameData.getAllDefs()) {
775 auto Index = FrameData.getFieldIndex(V);
778 {Index, {FrameData.getAlign(V).value(), FrameData.getOffset(V)}});
786 unsigned UnknownTypeNum = 0;
787 for (
unsigned Index = 0; Index < FrameTy->
getNumElements(); Index++) {
788 auto OCIt = OffsetCache.
find(Index);
789 if (OCIt == OffsetCache.
end())
799 assert(Ty->isSized() &&
"We can't handle type which is not sized.\n");
801 AlignInBits = OCIt->second.first * 8;
802 OffsetInBits = OCIt->second.second * 8;
804 if (
auto It = NameCache.
find(Index); It != NameCache.
end()) {
805 Name = It->second.str();
806 DITy = TyCache[Index];
808 DITy =
solveDIType(DBuilder, Ty, Layout, FrameDITy, LineNum, DITypeCache);
809 assert(DITy &&
"SolveDIType shouldn't return nullptr.\n");
811 Name +=
"_" + std::to_string(UnknownTypeNum);
816 FrameDITy, Name, DFile, LineNum, SizeInBits, AlignInBits, OffsetInBits,
817 llvm::DINode::FlagArtificial, DITy));
824 FrameDITy,
true, DINode::FlagArtificial);
833 auto RetainedNodes = DIS->getRetainedNodes();
835 RetainedNodes.end());
843 assert(FrameDIVar->isValidLocationForIntrinsic(DILoc));
850 It->getParent()->insertDbgRecordBefore(NewDVR, It);
862 FrameDataInfo &FrameData,
863 bool OptimizeFrame) {
868 std::optional<Align> MaxFrameAlignment;
871 FrameTypeBuilder
B(
C,
DL, MaxFrameAlignment);
874 std::optional<FieldIDType> SwitchIndexFieldId;
881 (void)
B.addField(FnPtrTy, std::nullopt,
true);
882 (void)
B.addField(FnPtrTy, std::nullopt,
true);
888 FrameData.setFieldIndex(
889 PromiseAlloca,
B.addFieldForAlloca(PromiseAlloca,
true));
896 SwitchIndexFieldId =
B.addField(IndexType, std::nullopt);
898 assert(PromiseAlloca ==
nullptr &&
"lowering doesn't support promises");
903 B.addFieldForAllocas(
F, FrameData, Shape, OptimizeFrame);
911 FrameData.Allocas.emplace_back(
914 for (
auto &S : FrameData.Spills) {
915 Type *FieldType = S.first->getType();
920 if (
A->hasByValAttr()) {
921 FieldType =
A->getParamByValType();
922 MA =
A->getParamAlign();
926 B.addField(FieldType, MA,
false ,
true );
927 FrameData.setFieldIndex(S.first, Id);
932 Name.append(
".Frame");
933 return B.finish(Name);
936 FrameData.updateLayoutIndex(
B);
943 auto IndexField =
B.getLayoutField(*SwitchIndexFieldId);
959 = (
B.getStructSize() <= Id->getStorageSize() &&
960 B.getStructAlign() <= Id->getStorageAlignment());
973 "The alignment requirment of frame variables cannot be higher than "
974 "the alignment of the async function context");
988 Arg->getParent()->removeParamAttr(Arg->getArgNo(), Attribute::Captures);
990 if (Arg->hasByValAttr())
991 return Arg->getParamByValType();
999 const FrameDataInfo &FrameData) {
1000 auto Index = FrameData.getFieldIndex(Def);
1001 auto *
G = Builder.CreateConstInBoundsGEP2_32(
1003 Def->getName() +
Twine(
".spill.addr"));
1004 auto SpillAlignment =
Align(FrameData.getAlign(Def));
1008 Builder.CreateAlignedStore(Builder.CreateLoad(ByValTy, Def),
G,
1011 Builder.CreateAlignedStore(Def,
G, SpillAlignment);
1019 FieldIDType Index = FrameData.getFieldIndex(Orig);
1029 auto Count = CI->getValue().getZExtValue();
1039 if (FrameData.getDynamicAlign(Orig) != 0) {
1043 auto *PtrValue = Builder.CreatePtrToInt(
GEP, IntPtrTy);
1044 auto *AlignMask = ConstantInt::get(IntPtrTy, AI->
getAlign().
value() - 1);
1045 PtrValue = Builder.CreateAdd(PtrValue, AlignMask);
1046 PtrValue = Builder.CreateAnd(PtrValue, Builder.CreateNot(AlignMask));
1047 return Builder.CreateIntToPtr(PtrValue, AI->
getType());
1062template <DbgVariableRecord::LocationType record_type>
1063static TinyPtrVector<DbgVariableRecord *>
1067 constexpr auto FindFunc =
1074 if (!
F.getSubprogram())
1077 Value *CurDef = Def;
1080 if (!LdInst->getType()->isPointerTy())
1082 CurDef = LdInst->getPointerOperand();
1085 Records = FindFunc(CurDef);
1125 MDNode *TBAATag =
nullptr;
1131 (
F->getName() +
".Frame Slot").str(), TBAARoot);
1134 for (
auto const &
E : FrameData.Spills) {
1142 Value *CurrentReload =
nullptr;
1143 for (
auto *U :
E.second) {
1149 Builder.SetInsertPoint(CurrentBlock,
1153 GEP->setName(
E.first->getName() +
Twine(
".reload.addr"));
1155 CurrentReload =
GEP;
1157 auto SpillAlignment =
Align(FrameData.getAlign(Def));
1158 auto *LI = Builder.CreateAlignedLoad(
1160 SpillAlignment,
E.first->getName() +
Twine(
".reload"));
1162 LI->setMetadata(LLVMContext::MD_tbaa, TBAATag);
1175 DDI->getExpression(), DDI->getDebugLoc(),
1177 Builder.GetInsertPoint()->getParent()->insertDbgRecordBefore(
1178 NewDVR, Builder.GetInsertPoint());
1190 auto SalvageOneCoro = [&](
auto *DDI) {
1197 Type *Ty = VAM->getValue()->getType();
1201 DDI->getExpression(), DDI->getDebugLoc(),
1204 Builder.GetInsertPoint()->getParent()->insertDbgRecordBefore(
1205 NewDVR, Builder.GetInsertPoint());
1210 for_each(DVRDeclareValues, SalvageOneCoro);
1216 assert(PN->getNumIncomingValues() == 1 &&
1217 "unexpected number of incoming "
1218 "values in the PHINode");
1219 PN->replaceAllUsesWith(CurrentReload);
1220 PN->eraseFromParent();
1226 U->replaceUsesOfWith(Def, CurrentReload);
1230 DVR.replaceVariableLocationOp(Def, CurrentReload,
true);
1245 Builder.SetInsertPoint(SpillBlock, SpillBlock->begin());
1246 for (
const auto &
P : FrameData.Allocas) {
1253 if (
I->isLifetimeStartOrEnd())
1254 I->eraseFromParent();
1259 G->takeName(Alloca);
1274 for (
const auto &
A : FrameData.Allocas) {
1276 UsersToUpdate.
clear();
1282 if (
I->isLifetimeStartOrEnd())
1283 I->eraseFromParent();
1288 if (UsersToUpdate.
empty())
1295 for (
auto *DVR : DbgVariableRecords)
1296 DVR->replaceVariableLocationOp(Alloca,
G);
1299 I->replaceUsesOfWith(Alloca,
G);
1302 for (
const auto &
A : FrameData.Allocas) {
1304 if (
A.MayWriteBeforeCoroBegin) {
1308 "Coroutines cannot handle copying of array allocas yet");
1312 Builder.CreateStore(
Value,
G);
1317 for (
const auto &Alias :
A.Aliases) {
1320 auto &
Value = *Alias.second;
1323 Builder.CreatePtrAdd(
FramePtr, ConstantInt::get(ITy,
Value));
1324 Alias.first->replaceUsesWithIf(
1337 auto *Inst = dyn_cast<Instruction>(U.getUser());
1338 if (!Inst || DT.dominates(Shape.CoroBegin, Inst))
1341 if (auto *CI = dyn_cast<CallInst>(Inst)) {
1346 if (CI->onlyReadsMemory() ||
1347 CI->onlyReadsMemory(CI->getArgOperandNo(&U)))
1362 if (HasAccessingPromiseBeforeCB) {
1365 auto *
Value = Builder.CreateLoad(PA->getAllocatedType(), PA);
1366 Builder.CreateStore(
Value,
G);
1376 PHINode *UntilPHI =
nullptr) {
1379 int Index = PN->getBasicBlockIndex(InsertedBB);
1380 Value *V = PN->getIncomingValue(Index);
1382 V->getType(), 1, V->getName() +
Twine(
".") + SuccBB->
getName());
1385 PN->setIncomingValue(Index, InputV);
1387 }
while (PN != UntilPHI);
1424 Builder.CreateUnreachable();
1427 auto *NewCleanupPadBB =
1430 CleanupPadBB->
getParent(), CleanupPadBB);
1431 Builder.SetInsertPoint(NewCleanupPadBB);
1432 auto *SwitchType = Builder.getInt8Ty();
1433 auto *SetDispatchValuePN =
1434 Builder.CreatePHI(SwitchType,
pred_size(CleanupPadBB));
1436 CleanupPad->
insertAfter(SetDispatchValuePN->getIterator());
1437 auto *SwitchOnDispatch = Builder.CreateSwitch(SetDispatchValuePN, UnreachBB,
1440 int SwitchIndex = 0;
1446 Twine(
".from.") + Pred->getName(),
1447 CleanupPadBB->
getParent(), CleanupPadBB);
1449 CaseBB->setName(CleanupPadBB->
getName() +
Twine(
".from.") +
1451 Builder.SetInsertPoint(CaseBB);
1452 Builder.CreateBr(CleanupPadBB);
1459 auto *SwitchConstant = ConstantInt::get(SwitchType, SwitchIndex);
1460 SetDispatchValuePN->addIncoming(SwitchConstant, Pred);
1461 SwitchOnDispatch->addCase(SwitchConstant, CaseBB);
1468 for (
auto &BB :
F) {
1469 for (
auto &Phi : BB.phis()) {
1470 if (Phi.getNumIncomingValues() == 1) {
1476 while (!Worklist.
empty()) {
1478 auto *OriginalValue = Phi->getIncomingValue(0);
1479 Phi->replaceAllUsesWith(OriginalValue);
1508 if (
auto *CleanupPad =
1516 assert(CS->getUnwindDest() == &BB);
1545 IncomingBB->setName(BB.
getName() +
Twine(
".from.") + Pred->getName());
1564 if (PN->getNumIncomingValues() > 1)
1574 auto *BB =
I->getParent();
1575 if (&BB->front() ==
I) {
1576 if (BB->getSinglePredecessor()) {
1581 return BB->splitBasicBlock(
I, Name);
1594 unsigned depth = 3) {
1597 if (depth == 0)
return false;
1617 for (
auto *U : AI->
users()) {
1633 for (
auto *AI : LocalAllocas) {
1638 Value *StackSave =
nullptr;
1640 StackSave = Builder.CreateStackSave();
1643 auto Alloca = Builder.CreateAlloca(Builder.getInt8Ty(), AI->getSize());
1646 for (
auto *U : AI->
users()) {
1649 U->replaceAllUsesWith(Alloca);
1657 Builder.SetInsertPoint(FI);
1658 Builder.CreateStackRestore(StackSave);
1675 auto Call = Builder.CreateCall(FnTy, Fn, {});
1688 {V->getType()},
false);
1691 auto Call = Builder.CreateCall(FnTy, Fn, { V });
1710 auto ValueBeforeCall = Builder.CreateLoad(ValueTy, Alloca);
1717 Builder.SetInsertPoint(
Call->getNextNode());
1720 Builder.SetInsertPoint(Invoke->getNormalDest()->getFirstNonPHIOrDbg());
1725 Builder.CreateStore(ValueAfterCall, Alloca);
1762 F.getEntryBlock().getFirstNonPHIOrDbg());
1770 auto Alloca = Builder.CreateAlloca(ValueTy, ArgTy->getAddressSpace());
1775 Builder.CreateStore(InitialValue, Alloca);
1784 Builder.SetInsertPoint(End);
1785 auto FinalValue = Builder.CreateLoad(ValueTy, Alloca);
1800 for (
auto &Arg :
F.args()) {
1801 if (!Arg.hasSwiftErrorAttr())
continue;
1808 for (
auto &Inst :
F.getEntryBlock()) {
1821 if (!AllocasToPromote.
empty()) {
1839 DomSet.
insert(&
F.getEntryBlock());
1844 "should have split coro.suspend into its own block");
1859 return II->getIntrinsicID() == Intrinsic::lifetime_start;
1868 if (!U->hasOneUse() || U->stripPointerCasts() != AI)
1887 if (collectLifetimeStart(UI, AI))
1895 if (Valid && Lifetimes.
size() != 0) {
1896 auto *NewLifetime = Lifetimes[0]->clone();
1897 NewLifetime->replaceUsesOfWith(NewLifetime->getOperand(0), AI);
1898 NewLifetime->insertBefore(DomBB->getTerminator()->getIterator());
1902 S->eraseFromParent();
1910static std::optional<std::pair<Value &, DIExpression &>>
1915 auto InsertPt =
F->getEntryBlock().getFirstInsertionPt();
1918 Builder.SetInsertPoint(&
F->getEntryBlock(), InsertPt);
1922 Storage = LdInst->getPointerOperand();
1929 if (!SkipOutermostLoad)
1932 Storage = StInst->getValueOperand();
1939 if (!
Op || !AdditionalValues.
empty()) {
1947 SkipOutermostLoad =
false;
1950 return std::nullopt;
1957 const bool WillUseEntryValue =
1958 UseEntryValue && StorageAsArg &&
1959 StorageAsArg->hasAttribute(Attribute::SwiftAsync) &&
1962 if (WillUseEntryValue)
1971 if (StorageAsArg && !WillUseEntryValue && IsSingleLocationExpression) {
1972 auto &Cached = ArgToAllocaMap[StorageAsArg];
1974 Cached = Builder.CreateAlloca(Storage->
getType(), 0,
nullptr,
1975 Storage->
getName() +
".debug");
1976 Builder.CreateStore(Storage, Cached);
1990 return {{*Storage, *Expr}};
2009 Value *Storage = &SalvagedInfo->first;
2019 std::optional<BasicBlock::iterator> InsertPt;
2021 InsertPt =
I->getInsertionPointAfterDef();
2025 if (ILoc && DVRLoc &&
2026 DVRLoc->getScope()->getSubprogram() ==
2027 ILoc->getScope()->getSubprogram())
2030 InsertPt =
F->getEntryBlock().begin();
2039 Type *Ty = VAM->getValue()->getType();
2040 if (Ty->isPointerTy())
2046 (*InsertPt)->getParent()->insertDbgRecordBefore(&DVR, *InsertPt);
2066 if (
auto *Save = CSI->getCoroSave())
2080 auto *MustTailCallFn = AsyncEnd->getMustTailCallFunction();
2081 if (!MustTailCallFn)
2087 AsyncEnd->getDebugLoc(), MustTailCallFn,
TTI,
Arguments, Builder);
2120 LocalAllocas,
F, Checker, DT,
Shape);
2131 FrameDataInfo FrameData(Spills, Allocas);
2140 for (
auto *
I : DeadInstructions)
2141 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 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 Value * createGEPToFramePointer(const FrameDataInfo &FrameData, IRBuilder<> &Builder, coro::Shape &Shape, Value *Orig)
Returns a GEP into the coroutine frame at the offset where Orig is located.
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 bool isLifetimeStart(const Instruction *Inst)
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 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),...
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...
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.
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="", bool Before=false)
Split the basic block into two basic blocks at the specified instruction.
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.
This is the shared class of boolean and integer constants.
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 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 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
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 IntegerType * getIntPtrType(LLVMContext &C, unsigned AddressSpace=0) const
Returns an integer type with size at least as big as that of a pointer in the given address space.
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()
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
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)
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.
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 ...
LLVM_ABI void replaceOperandWith(unsigned I, Metadata *New)
Replace a specific operand.
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)
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
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.
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 * getInt32Ty(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...
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.
FunctionAddr VTableAddr Value
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
MaybeAlign getAlign(const CallInst &I, unsigned Index)
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.
bool isAligned(Align Lhs, uint64_t SizeInBytes)
Checks that SizeInBytes is a multiple of the alignment.
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.
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)
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.
FunctionAddr VTableAddr Count
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...
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
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
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