77#define DEBUG_TYPE "rewrite-statepoints-for-gc"
81#ifdef EXPENSIVE_CHECKS
115 if (
F.isDeclaration() ||
F.empty())
144struct GCPtrLivenessData {
175using RematerializedValueMapTy =
178struct PartiallyConstructedSafepointRecord {
180 StatepointLiveSetTy LiveSet;
193 RematerializedValueMapTy RematerializedValues;
196struct RematerizlizationCandidateRecord {
210 std::optional<OperandBundleUse> DeoptBundle =
214 assert(Opts.rs4gc_allow_statepoint_with_no_deopt_info &&
215 "Found non-leaf call without deopt info!");
219 return DeoptBundle->Inputs;
232 assert(GC &&
"GC Strategy for isGCPointerType cannot be null");
238 return GC->isGCManagedPointer(
T).value_or(
true);
269 [GC](
Type *Ty) { return containsGCPtrType(Ty, GC); });
285 return V->hasName() ? (V->getName() + Suffix).str() : DefaultName.
str();
294 GCPtrLivenessData &OriginalLivenessData,
CallBase *
Call,
295 PartiallyConstructedSafepointRecord &Result,
GCStrategy *GC) {
296 StatepointLiveSetTy LiveSet;
299 if (Opts.spp_print_liveset) {
300 dbgs() <<
"Live Variables:\n";
301 for (
Value *V : LiveSet)
302 dbgs() <<
" " << V->getName() <<
" " << *V <<
"\n";
304 if (Opts.spp_print_liveset_size) {
305 dbgs() <<
"Safepoint For: " <<
Call->getCalledOperand()->getName() <<
"\n";
306 dbgs() <<
"Number live values: " << LiveSet.size() <<
"\n";
308 Result.LiveSet = LiveSet;
317 IsKnownBaseMapTy &KnownBases);
320 IsKnownBaseMapTy &KnownBases);
332 IsKnownBaseMapTy &KnownBases) {
336 auto Cached = Cache.find(
I);
337 if (Cached != Cache.end())
338 return Cached->second;
419 "unknown vector instruction - no base found for vector element");
430 IsKnownBaseMapTy &KnownBases) {
431 assert(
I->getType()->isPtrOrPtrVectorTy() &&
432 "Illegal to ask for the base pointer of a non-pointer type");
433 auto Cached = Cache.find(
I);
434 if (Cached != Cache.end())
435 return Cached->second;
437 if (
I->getType()->isVectorTy())
477 Value *Def = CI->stripPointerCasts();
482 "unsupported addrspacecast");
514 switch (
II->getIntrinsicID()) {
518 case Intrinsic::experimental_gc_statepoint:
520 case Intrinsic::experimental_gc_relocate:
525 case Intrinsic::gcroot:
530 "interaction with the gcroot mechanism is not supported");
531 case Intrinsic::experimental_gc_get_pointer_base:
561 "Only Xchg is allowed for pointer values");
581 "Base pointer for a struct is meaningless");
605 "missing instruction case in findBaseDefiningValue");
611 IsKnownBaseMapTy &KnownBases) {
612 if (!Cache.contains(
I)) {
616 << Cache[
I]->getName() <<
", is known base = "
617 << KnownBases[
I] <<
"\n");
620 assert(KnownBases.contains(Cache[
I]) &&
621 "Cached value must be present in known bases map");
628 IsKnownBaseMapTy &KnownBases) {
630 auto Found = Cache.find(Def);
631 if (Found != Cache.end()) {
633 return Found->second;
651 auto It = KnownBases.find(V);
652 assert(It != KnownBases.end() &&
"Value not present in the map");
657 IsKnownBaseMapTy &KnownBases) {
659 auto It = KnownBases.find(V);
660 if (It != KnownBases.end())
661 assert(It->second == IsKnownBase &&
"Changing already present value");
663 KnownBases[V] = IsKnownBase;
694 explicit BDVState(
Value *OriginalValue)
695 : OriginalValue(OriginalValue) {}
696 explicit BDVState(
Value *OriginalValue, StatusTy Status,
Value *BaseValue =
nullptr)
697 : OriginalValue(OriginalValue), Status(Status), BaseValue(BaseValue) {
701 StatusTy getStatus()
const {
return Status; }
702 Value *getOriginalValue()
const {
return OriginalValue; }
703 Value *getBaseValue()
const {
return BaseValue; }
705 bool isBase()
const {
return getStatus() ==
Base; }
706 bool isUnknown()
const {
return getStatus() ==
Unknown; }
707 bool isConflict()
const {
return getStatus() == Conflict; }
712 void meet(
const BDVState &
Other) {
713 auto markConflict = [&]() {
714 Status = BDVState::Conflict;
722 Status =
Other.getStatus();
723 BaseValue =
Other.getBaseValue();
727 assert(isBase() &&
"Unknown state");
729 if (
Other.isUnknown())
732 if (
Other.isConflict())
733 return markConflict();
737 if (getBaseValue() !=
Other.getBaseValue())
738 return markConflict();
743 return OriginalValue ==
Other.OriginalValue && BaseValue ==
Other.BaseValue &&
744 Status ==
Other.Status;
747 bool operator!=(
const BDVState &other)
const {
return !(*
this == other); }
755 void print(raw_ostream &OS)
const {
756 switch (getStatus()) {
767 OS <<
" (base " << getBaseValue() <<
" - "
768 << (getBaseValue() ? getBaseValue()->getName() :
"nullptr") <<
")"
769 <<
" for " << OriginalValue->getName() <<
":";
773 AssertingVH<Value> OriginalValue;
775 AssertingVH<Value> BaseValue =
nullptr;
792 IsKnownBaseMapTy &KnownBases) {
821 auto isExpectedBDVType = [](
Value *BDV) {
836 auto VerifyStates = [&]() {
837 for (
auto &Entry : States) {
838 assert(Entry.first == Entry.second.getOriginalValue());
843 auto visitBDVOperands = [](
Value *BDV, std::function<void (
Value*)>
F) {
845 for (
Value *InVal : PN->incoming_values())
848 F(
SI->getTrueValue());
849 F(
SI->getFalseValue());
851 F(EE->getVectorOperand());
853 F(IE->getOperand(0));
854 F(IE->getOperand(1));
858 F(SV->getOperand(0));
859 if (!SV->isZeroEltSplat())
860 F(SV->getOperand(1));
872 States.
insert({Def, BDVState(Def)});
873 while (!Worklist.
empty()) {
877 auto visitIncomingValue = [&](
Value *InVal) {
886 assert(isExpectedBDVType(
Base) &&
"the only non-base values "
887 "we see should be base defining values");
892 visitBDVOperands(Current, visitIncomingValue);
899 for (
const auto &Pair : States) {
900 LLVM_DEBUG(
dbgs() <<
" " << Pair.second <<
" for " << *Pair.first <<
"\n");
912 for (
auto Pair : States) {
913 Value *BDV = Pair.first;
914 auto canPruneInput = [&](
Value *V) {
917 if (V->stripPointerCasts() == BDV)
920 if (V->stripPointerCasts() != VBDV)
924 return States.count(VBDV) == 0;
927 bool CanPrune =
true;
928 visitBDVOperands(BDV, [&](
Value *
Op) {
929 CanPrune = CanPrune && canPruneInput(
Op);
942 if (!States.
count(Def))
948 auto I = States.
find(BaseValue);
949 if (
I != States.
end())
952 return BDVState(BaseValue, BDVState::Base, BaseValue);
993 bool Progress =
true;
996 const size_t OldSize = States.
size();
1003 for (
auto Pair : States) {
1004 Value *BDV = Pair.first;
1010 "why did it get added?");
1012 BDVState NewState(BDV);
1013 visitBDVOperands(BDV, [&](
Value *
Op) {
1015 auto OpState = GetStateForBDV(BDV,
Op);
1016 NewState.meet(OpState);
1023 auto BV = NewState.getBaseValue();
1024 if (BV && MarkConflict(
I, BV))
1025 NewState = BDVState(
I, BDVState::Conflict);
1027 BDVState OldState = Pair.second;
1028 if (OldState != NewState) {
1030 States[BDV] = NewState;
1034 assert(OldSize == States.size() &&
1035 "fixed point shouldn't be adding any new nodes to state");
1041 for (
const auto &Pair : States) {
1042 LLVM_DEBUG(
dbgs() <<
" " << Pair.second <<
" for " << *Pair.first <<
"\n");
1047 for (
auto Pair : States) {
1049 BDVState State = Pair.second;
1050 auto *BaseValue = State.getBaseValue();
1056 "why did it get added?");
1057 assert(!State.isUnknown() &&
"Optimistic algorithm didn't complete!");
1063 for (
auto Pair : States) {
1065 BDVState State = Pair.second;
1071 "why did it get added?");
1072 assert(!State.isUnknown() &&
"Optimistic algorithm didn't complete!");
1079 if (!State.isConflict())
1082 auto getMangledName = [](
Instruction *
I) -> std::string {
1098 BaseInst->
setName(getMangledName(
I));
1101 States[
I] = BDVState(
I, BDVState::Conflict, BaseInst);
1120 if (
auto It = States.
find(BDV); It == States.
end()) {
1125 Base = It->second.getBaseValue();
1129 if (
Base->getType() !=
Input->getType() && InsertPt)
1131 InsertPt->getIterator());
1138 for (
auto Pair : States) {
1140 BDVState State = Pair.second;
1147 "why did it get added?");
1148 assert(!State.isUnknown() &&
"Optimistic algorithm didn't complete!");
1149 if (!State.isConflict())
1161 for (
unsigned i = 0; i < NumPHIValues; i++) {
1164 auto [It, Inserted] = BlockToValue.
try_emplace(InBB);
1169 Value *OldBase = It->second;
1170 Value *
Base = getBaseForInput(InVal,
nullptr);
1174 auto StripBitCasts = [](
Value *V) ->
Value * {
1176 V = BC->getOperand(0);
1185 assert(StripBitCasts(
Base) == StripBitCasts(OldBase) &&
1186 "findBaseOrBDV should be pure!");
1190 BasePHI->setIncomingValue(i,
Base);
1198 BaseSI->setTrueValue(getBaseForInput(
SI->getTrueValue(), BaseSI));
1199 BaseSI->setFalseValue(getBaseForInput(
SI->getFalseValue(), BaseSI));
1200 }
else if (
auto *BaseEE =
1205 BaseEE->setOperand(0, getBaseForInput(InVal, BaseEE));
1208 auto UpdateOperand = [&](
int OperandIdx) {
1209 Value *InVal = BdvIE->getOperand(OperandIdx);
1210 Value *
Base = getBaseForInput(InVal, BaseIE);
1211 BaseIE->setOperand(OperandIdx,
Base);
1218 auto UpdateOperand = [&](
int OperandIdx) {
1219 Value *InVal = BdvSV->getOperand(OperandIdx);
1220 Value *
Base = getBaseForInput(InVal, BaseSV);
1221 BaseSV->setOperand(OperandIdx,
Base);
1224 if (!BdvSV->isZeroEltSplat())
1228 Value *InVal = BdvSV->getOperand(1);
1239 [[maybe_unused]]
auto &
DL =
1244 for (
auto Pair : States) {
1245 auto *BDV = Pair.first;
1246 Value *
Base = Pair.second.getBaseValue();
1251 DL.getTypeAllocSize(
Base->getType()) &&
1252 "Derived and base values should have same size");
1258 "why did it get added?");
1261 dbgs() <<
"Updating base value cache"
1262 <<
" for: " << BDV->
getName() <<
" from: "
1263 << (Cache.count(BDV) ? Cache[BDV]->getName().str() :
"none")
1264 <<
" to: " <<
Base->getName() <<
"\n");
1268 assert(Cache.count(Def));
1289 DefiningValueMapTy &DVCache,
1290 IsKnownBaseMapTy &KnownBases) {
1291 for (
Value *ptr : live) {
1293 assert(base &&
"failed to find base pointer");
1294 PointerToBase[ptr] = base;
1298 "The base we found better dominate the derived pointer");
1306 PartiallyConstructedSafepointRecord &result,
1307 PointerToBaseTy &PointerToBase,
1308 IsKnownBaseMapTy &KnownBases) {
1309 StatepointLiveSetTy PotentiallyDerivedPointers = result.LiveSet;
1316 for (
Value *V : Opt->Inputs) {
1317 if (!PotentiallyDerivedPointers.count(V))
1319 PotentiallyDerivedPointers.remove(V);
1320 PointerToBase[V] = V;
1330 PartiallyConstructedSafepointRecord &result,
1331 PointerToBaseTy &PointerToBase,
1337 PointerToBaseTy &PointerToBase,
GCStrategy *GC) {
1340 GCPtrLivenessData RevisedLivenessData;
1342 for (
size_t i = 0; i < records.
size(); i++) {
1343 struct PartiallyConstructedSafepointRecord &
info = records[i];
1355 Value *AlternateLiveBase) {
1368 ClonedValue->
setName(Instr->getName() +
".remat");
1372 if (LastClonedValue) {
1380 "incorrect use in rematerialization chain");
1383 assert(OpValue != RootOfChain && OpValue != AlternateLiveBase);
1392 if (RootOfChain != AlternateLiveBase)
1396 LastClonedValue = ClonedValue;
1400 return LastClonedValue;
1420 "All PHI nodes should have been removed!");
1433 {Attribute::Memory, Attribute::NoSync, Attribute::NoFree};
1440 if (OrigAL.isEmpty())
1441 return StatepointAL;
1445 AttrBuilder FnAttrs(Ctx, OrigAL.getFnAttrs());
1447 FnAttrs.removeAttribute(Attr);
1451 FnAttrs.removeAttribute(
A);
1454 StatepointAL = StatepointAL.addFnAttributes(Ctx, FnAttrs);
1460 return StatepointAL;
1466 StatepointAL = StatepointAL.addParamAttributes(
1468 AttrBuilder(Ctx, OrigAL.getParamAttrs(
I)));
1471 return StatepointAL;
1491 assert(ValIt != LiveVec.
end() &&
"Val not found in LiveVec!");
1492 size_t Index = std::distance(LiveVec.
begin(), ValIt);
1493 assert(Index < LiveVec.
size() &&
"Bug in std::find?");
1501 Value *LiveIdx = Builder.getInt32(i);
1506 M, Intrinsic::experimental_gc_relocate, {Ty});
1510 GCRelocateDecl, {StatepointToken, BaseIdx, LiveIdx},
1522class DeferredReplacement {
1523 AssertingVH<Instruction> Old;
1524 AssertingVH<Instruction>
New;
1525 bool IsDeoptimize =
false;
1527 DeferredReplacement() =
default;
1530 static DeferredReplacement createRAUW(Instruction *Old, Instruction *New) {
1531 assert(Old != New && Old && New &&
1532 "Cannot RAUW equal values or to / from null!");
1534 DeferredReplacement
D;
1540 static DeferredReplacement createDelete(Instruction *ToErase) {
1541 DeferredReplacement
D;
1546 static DeferredReplacement createDeoptimizeReplacement(Instruction *Old) {
1549 assert(
F &&
F->getIntrinsicID() == Intrinsic::experimental_deoptimize &&
1550 "Only way to construct a deoptimize deferred replacement");
1552 DeferredReplacement
D;
1554 D.IsDeoptimize =
true;
1559 void doReplacement() {
1563 assert(OldI != NewI &&
"Disallowed at construction?!");
1564 assert((!IsDeoptimize || !New) &&
1565 "Deoptimize intrinsics are not replaced!");
1577 new UnreachableInst(RI->getContext(), RI->getIterator());
1578 RI->eraseFromParent();
1588 const char *DeoptLowering =
"deopt-lowering";
1589 if (
Call->hasFnAttr(DeoptLowering)) {
1593 if (CSAS.hasFnAttr(DeoptLowering))
1594 return CSAS.getFnAttr(DeoptLowering).getValueAsString();
1596 assert(
F &&
F->hasFnAttribute(DeoptLowering));
1597 return F->getFnAttribute(DeoptLowering).getValueAsString();
1599 return "live-through";
1606 PartiallyConstructedSafepointRecord &Result,
1607 std::vector<DeferredReplacement> &Replacements,
1608 const PointerToBaseTy &PointerToBase,
1624 std::optional<ArrayRef<Use>> DeoptArgs;
1626 DeoptArgs = Bundle->Inputs;
1627 std::optional<ArrayRef<Use>> TransitionArgs;
1629 TransitionArgs = Bundle->Inputs;
1637 bool IsDeoptimize =
false;
1638 bool IsMemIntrinsic =
false;
1649 if (DeoptLowering ==
"live-in")
1652 assert(DeoptLowering ==
"live-through" &&
"Unsupported value!");
1657 auto IID =
F->getIntrinsicID();
1658 if (IID == Intrinsic::experimental_deoptimize) {
1664 for (
Value *Arg : CallArgs)
1673 CallTarget =
F->getParent()
1674 ->getOrInsertFunction(
"__llvm_deoptimize", FTy);
1676 IsDeoptimize =
true;
1677 }
else if (IID == Intrinsic::memcpy_element_unordered_atomic ||
1678 IID == Intrinsic::memmove_element_unordered_atomic) {
1679 IsMemIntrinsic =
true;
1697 auto &Context =
Call->getContext();
1698 auto &
DL =
Call->getDataLayout();
1699 auto GetBaseAndOffset = [&](
Value *Derived) {
1709 assert(PointerToBase.count(Derived));
1710 Base = PointerToBase.find(Derived)->second;
1712 unsigned AddressSpace = Derived->getType()->getPointerAddressSpace();
1714 Value *Base_int = Builder.CreatePtrToInt(
1716 Value *Derived_int = Builder.CreatePtrToInt(
1718 return std::make_pair(
Base, Builder.CreateSub(Derived_int, Base_int));
1721 auto *Dest = CallArgs[0];
1722 Value *DestBase, *DestOffset;
1723 std::tie(DestBase, DestOffset) = GetBaseAndOffset(Dest);
1725 auto *Source = CallArgs[1];
1726 Value *SourceBase, *SourceOffset;
1727 std::tie(SourceBase, SourceOffset) = GetBaseAndOffset(Source);
1729 auto *LengthInBytes = CallArgs[2];
1740 for (
Value *Arg : CallArgs)
1746 uint64_t ElementSize = ElementSizeCI->getZExtValue();
1747 if (IID == Intrinsic::memcpy_element_unordered_atomic) {
1748 switch (ElementSize) {
1750 return "__llvm_memcpy_element_unordered_atomic_safepoint_1";
1752 return "__llvm_memcpy_element_unordered_atomic_safepoint_2";
1754 return "__llvm_memcpy_element_unordered_atomic_safepoint_4";
1756 return "__llvm_memcpy_element_unordered_atomic_safepoint_8";
1758 return "__llvm_memcpy_element_unordered_atomic_safepoint_16";
1763 assert(IID == Intrinsic::memmove_element_unordered_atomic);
1764 switch (ElementSize) {
1766 return "__llvm_memmove_element_unordered_atomic_safepoint_1";
1768 return "__llvm_memmove_element_unordered_atomic_safepoint_2";
1770 return "__llvm_memmove_element_unordered_atomic_safepoint_4";
1772 return "__llvm_memmove_element_unordered_atomic_safepoint_8";
1774 return "__llvm_memmove_element_unordered_atomic_safepoint_16";
1782 ->getOrInsertFunction(GetFunctionName(IID, ElementSizeCI), FTy);
1789 CallInst *SPCall = Builder.CreateGCStatepointCall(
1790 StatepointID, NumPatchBytes, CallTarget, Flags, CallArgs,
1791 TransitionArgs, DeoptArgs, GCLive,
"safepoint_token");
1805 assert(CI->getNextNode() &&
"Not a terminator, must have next!");
1806 Builder.SetInsertPoint(CI->getNextNode());
1807 Builder.SetCurrentDebugLocation(CI->getNextNode()->getDebugLoc());
1814 InvokeInst *SPInvoke = Builder.CreateGCStatepointInvoke(
1815 StatepointID, NumPatchBytes, CallTarget,
II->getNormalDest(),
1816 II->getUnwindDest(), Flags, CallArgs, TransitionArgs, DeoptArgs,
1817 GCLive,
"statepoint_token");
1832 "can't safely insert in this block!");
1835 Builder.SetCurrentDebugLocation(
II->getDebugLoc());
1839 Result.UnwindToken = ExceptionalToken;
1847 "can't safely insert in this block!");
1854 assert(Token &&
"Should be set in one of the above branches!");
1860 Replacements.push_back(
1861 DeferredReplacement::createDeoptimizeReplacement(
Call));
1863 Token->
setName(
"statepoint_token");
1864 if (!
Call->getType()->isVoidTy() && !
Call->use_empty()) {
1866 CallInst *GCResult = Builder.CreateGCResult(Token,
Call->getType(), Name);
1868 AttributeList::get(GCResult->
getContext(), AttributeList::ReturnIndex,
1869 Call->getAttributes().getRetAttrs()));
1877 Replacements.emplace_back(
1878 DeferredReplacement::createRAUW(
Call, GCResult));
1880 Replacements.emplace_back(DeferredReplacement::createDelete(
Call));
1884 Result.StatepointToken = Token;
1897 PartiallyConstructedSafepointRecord &Result,
1898 std::vector<DeferredReplacement> &Replacements,
1899 const PointerToBaseTy &PointerToBase,
GCStrategy *GC) {
1900 const auto &LiveSet = Result.LiveSet;
1904 LiveVec.
reserve(LiveSet.size());
1905 BaseVec.
reserve(LiveSet.size());
1906 for (
Value *L : LiveSet) {
1908 assert(PointerToBase.count(L));
1909 Value *
Base = PointerToBase.find(L)->second;
1929 for (
User *U : GCRelocs) {
1936 Value *Alloca = AllocaMap[OriginalValue];
1940 "Should always have one since it's not a terminator");
1944 VisitedLiveValues.
insert(OriginalValue);
1952 const RematerializedValueMapTy &RematerializedValues,
1955 for (
auto RematerializedValuePair: RematerializedValues) {
1956 Instruction *RematerializedValue = RematerializedValuePair.first;
1957 Value *OriginalValue = RematerializedValuePair.second;
1960 "Can not find alloca for rematerialized value");
1961 Value *Alloca = AllocaMap[OriginalValue];
1963 new StoreInst(RematerializedValue, Alloca,
1967 VisitedLiveValues.
insert(OriginalValue);
1979 int InitialAllocaNum = 0;
1989 std::size_t NumRematerializedValues = 0;
1995 auto emitAllocaFor = [&](
Value *LiveValue) {
1997 new AllocaInst(LiveValue->getType(),
DL.getAllocaAddrSpace(),
"",
1998 F.getEntryBlock().getFirstNonPHIIt());
1999 AllocaMap[LiveValue] = Alloca;
2004 for (
Value *V : Live)
2008 for (
const auto &Info : Records)
2009 for (
auto RematerializedValuePair : Info.RematerializedValues) {
2010 Value *OriginalValue = RematerializedValuePair.second;
2011 if (AllocaMap.
contains(OriginalValue))
2014 emitAllocaFor(OriginalValue);
2015 ++NumRematerializedValues;
2027 for (
const auto &Info : Records) {
2054 for (
auto Pair : AllocaMap) {
2055 Value *Def = Pair.first;
2059 if (VisitedLiveValues.
count(Def)) {
2063 ToClobber.
push_back({Def->getType(), Alloca});
2067 for (
auto &[Ty, AI] : ToClobber) {
2069 if (Ty->isVectorTy())
2080 InsertClobbersAt(
II->getNormalDest()->getFirstInsertionPt());
2081 InsertClobbersAt(
II->getUnwindDest()->getFirstInsertionPt());
2090 for (
auto Pair : AllocaMap) {
2091 Value *Def = Pair.first;
2099 Uses.reserve(Def->getNumUses());
2100 for (
User *U : Def->users()) {
2118 for (
unsigned i = 0; i < Phi->getNumIncomingValues(); i++) {
2119 if (Def == Phi->getIncomingValue(i)) {
2122 Def->getType(), Alloca,
"",
2123 Phi->getIncomingBlock(i)->getTerminator()->getIterator());
2124 Phi->setIncomingValue(i,
Load);
2130 new LoadInst(Def->getType(), Alloca,
"",
Use->getIterator());
2131 Use->replaceUsesOfWith(Def,
Load);
2139 DL.getABITypeAlign(Def->getType()));
2144 BasicBlock *NormalDest = Invoke->getNormalDest();
2147 assert(!Inst->isTerminator() &&
2148 "The only terminator that can produce a value is "
2149 "InvokeInst which is handled above.");
2150 Store->insertAfter(Inst->getIterator());
2158 assert(PromotableAllocas.
size() == Live.
size() + NumRematerializedValues &&
2159 "we must have the same allocas with lives");
2160 (void) NumRematerializedValues;
2161 if (!PromotableAllocas.
empty()) {
2167 for (
auto &
I :
F.getEntryBlock())
2170 assert(InitialAllocaNum == 0 &&
"We must not introduce any extra allocas");
2196 Func,
Values,
"",
II->getNormalDest()->getFirstInsertionPt()));
2198 Func,
Values,
"",
II->getUnwindDest()->getFirstInsertionPt()));
2206 GCPtrLivenessData OriginalLivenessData;
2208 for (
size_t i = 0; i < records.
size(); i++) {
2209 struct PartiallyConstructedSafepointRecord &
info = records[i];
2223 Value *CurrentValue) {
2227 GEP->getPointerOperand());
2231 if (!CI->isNoopCast(CI->getDataLayout()))
2241 return CurrentValue;
2253 assert(CI->isNoopCast(CI->getDataLayout()) &&
2254 "non noop cast is found during rematerialization");
2256 Type *SrcTy = CI->getOperand(0)->getType();
2257 Cost +=
TTI.getCastInstrCost(CI->getOpcode(), CI->getType(), SrcTy,
2263 Cost +=
TTI.getAddressComputationCost(
2264 GEP->getType(),
nullptr,
nullptr,
2270 if (!
GEP->hasAllConstantIndices())
2289 for (
unsigned i = 0; i < PhiNum; i++)
2295 for (
unsigned i = 0; i < PhiNum; i++) {
2298 if (CIVI == CurrentIncomingValues.
end())
2300 BasicBlock *CurrentIncomingBB = CIVI->second;
2311 RematCandTy &RematerizationCandidates,
2313 const unsigned int ChainLengthThreshold = 10;
2315 for (
auto P2B : PointerToBase) {
2316 auto *Derived = P2B.first;
2317 auto *
Base = P2B.second;
2319 if (Derived ==
Base)
2324 Value *RootOfChain =
2328 if ( ChainToBase.
size() == 0 ||
2329 ChainToBase.
size() > ChainLengthThreshold)
2334 if (
Value *BaseVal = PointerToBase[Derived]; RootOfChain != BaseVal) {
2337 if (!OrigRootPhi || !AlternateRootPhi)
2359 RematerizlizationCandidateRecord
Record;
2360 Record.ChainToBase = ChainToBase;
2361 Record.RootOfChain = RootOfChain;
2363 RematerizationCandidates.insert({ Derived,
Record });
2372 const ScalarOptions &Opts, RematCandTy &RematerizationCandidates,
2374 PointerToBaseTy &PointerToBase) {
2375 if (!Opts.rs4gc_remat_derived_at_uses)
2381 <<
"Num statepoints: " << Records.
size() <<
'\n');
2383 for (
auto &It : RematerizationCandidates) {
2385 auto &
Record = It.second;
2387 if (
Record.Cost >= Opts.spp_rematerialization_threshold)
2395 if (U->getParent() == Cand->
getParent())
2400 [](
const auto *U) { return isa<PHINode>(U); }))
2412 Records, [Cand](
const auto &R) {
return R.LiveSet.contains(Cand); });
2415 LLVM_DEBUG(
dbgs() <<
"Num uses: " << NumUses <<
" Num live statepoints: "
2416 << NumLiveStatepoints <<
" ");
2418 if (NumLiveStatepoints < NumUses) {
2426 if (NumLiveStatepoints == NumUses &&
Record.Cost > 0) {
2438 if (
Record.ChainToBase.size() > 1) {
2439 Record.ChainToBase.clear();
2456 Record.RootOfChain, PointerToBase[Cand]);
2458 PointerToBase[RematChain] = PointerToBase[Cand];
2464 <<
" derived pointers\n");
2465 for (
auto *Cand : LiveValuesToBeDeleted) {
2466 assert(Cand->use_empty() &&
"Unexpected user remain");
2467 RematerizationCandidates.erase(Cand);
2468 for (
auto &R : Records) {
2469 assert(!R.LiveSet.contains(Cand) ||
2470 R.LiveSet.contains(PointerToBase[Cand]));
2471 R.LiveSet.remove(Cand);
2477 if (!LiveValuesToBeDeleted.
empty()) {
2478 for (
auto &
P : RematerizationCandidates) {
2480 if (R.ChainToBase.size() > 1) {
2481 R.ChainToBase.clear();
2493 PartiallyConstructedSafepointRecord &Info,
2494 PointerToBaseTy &PointerToBase,
2495 RematCandTy &RematerizationCandidates,
2501 for (
Value *LiveValue : Info.LiveSet) {
2502 auto It = RematerizationCandidates.find(LiveValue);
2503 if (It == RematerizationCandidates.end())
2506 RematerizlizationCandidateRecord &
Record = It->second;
2515 if (Cost >= Opts.spp_rematerialization_threshold)
2519 LiveValuesToBeDeleted.
push_back(LiveValue);
2530 Record.RootOfChain, PointerToBase[LiveValue]);
2531 Info.RematerializedValues[RematerializedValue] = LiveValue;
2536 Invoke->getNormalDest()->getFirstInsertionPt();
2538 Invoke->getUnwindDest()->getFirstInsertionPt();
2542 Record.RootOfChain, PointerToBase[LiveValue]);
2545 Record.RootOfChain, PointerToBase[LiveValue]);
2547 Info.RematerializedValues[NormalRematerializedValue] = LiveValue;
2548 Info.RematerializedValues[UnwindRematerializedValue] = LiveValue;
2553 for (
auto *LiveValue: LiveValuesToBeDeleted) {
2554 Info.LiveSet.remove(LiveValue);
2560 DefiningValueMapTy &DVCache,
2561 IsKnownBaseMapTy &KnownBases) {
2562 auto &Context =
F.getContext();
2563 auto &
DL =
F.getDataLayout();
2566 for (
auto *Callsite : Intrinsics)
2567 switch (Callsite->getIntrinsicID()) {
2568 case Intrinsic::experimental_gc_get_pointer_base: {
2572 assert(!DVCache.count(Callsite));
2573 Callsite->replaceAllUsesWith(
Base);
2574 if (!
Base->hasName())
2575 Base->takeName(Callsite);
2576 Callsite->eraseFromParent();
2579 case Intrinsic::experimental_gc_get_pointer_offset: {
2581 Value *Derived = Callsite->getOperand(0);
2583 assert(!DVCache.count(Callsite));
2593 Value *
Offset = Builder.CreateSub(DerivedInt, BaseInt);
2594 Callsite->replaceAllUsesWith(
Offset);
2595 Offset->takeName(Callsite);
2596 Callsite->eraseFromParent();
2609 DefiningValueMapTy &DVCache,
2610 IsKnownBaseMapTy &KnownBases) {
2615 std::set<CallBase *> Uniqued;
2616 Uniqued.insert(ToUpdate.
begin(), ToUpdate.
end());
2617 assert(Uniqued.size() == ToUpdate.
size() &&
"no duplicates please!");
2645 "support for FCA unimplemented");
2660 PointerToBaseTy PointerToBase;
2663 for (
size_t i = 0; i < Records.
size(); i++) {
2664 PartiallyConstructedSafepointRecord &
info = Records[i];
2667 if (Opts.spp_print_base_pointers) {
2668 errs() <<
"Base Pairs (w/o Relocation):\n";
2669 for (
auto &Pair : PointerToBase) {
2670 errs() <<
" derived ";
2671 Pair.first->printAsOperand(
errs(),
false);
2673 Pair.second->printAsOperand(
errs(),
false);
2693 for (
size_t i = 0; i < Records.
size(); i++) {
2694 PartiallyConstructedSafepointRecord &Info = Records[i];
2697 for (
auto *Derived : Info.LiveSet) {
2698 assert(PointerToBase.count(Derived) &&
"Missed base for derived pointer");
2699 Bases.
push_back(PointerToBase[Derived]);
2710 if (Opts.spp_print_base_pointers) {
2711 errs() <<
"Base Pairs: (w/Relocation)\n";
2712 for (
auto Pair : PointerToBase) {
2713 errs() <<
" derived ";
2714 Pair.first->printAsOperand(
errs(),
false);
2716 Pair.second->printAsOperand(
errs(),
false);
2729 for (
auto &Info : Records) {
2730 Info.LiveSet.remove_if([&](
Value *LiveV) {
2731 assert(PointerToBase.count(LiveV) &&
"Missed base for derived pointer");
2737 CI->eraseFromParent();
2742 RematCandTy RematerizationCandidates;
2751 for (
size_t i = 0; i < Records.
size(); i++)
2753 RematerizationCandidates,
TTI);
2758 std::vector<DeferredReplacement> Replacements;
2766 for (
size_t i = 0; i < Records.
size(); i++)
2768 PointerToBase, GC.get());
2772 for (
auto &PR : Replacements)
2775 Replacements.clear();
2777 for (
auto &Info : Records) {
2786 Info.LiveSet.clear();
2788 PointerToBase.clear();
2794 for (
const PartiallyConstructedSafepointRecord &Info : Records) {
2807 "statepoint must be reachable or liveness is meaningless");
2808 for (
Value *V : Info.StatepointToken->gc_live()) {
2814 "unreachable values should never be live");
2816 "basic SSA liveness expectation violated by liveness analysis");
2823 for (
auto *Ptr : Live)
2825 "must be a gc pointer type");
2829 return !Records.
empty();
2837 R.addAttribute(Attribute::Dereferenceable);
2838 R.addAttribute(Attribute::DereferenceableOrNull);
2839 R.addAttribute(Attribute::ReadNone);
2840 R.addAttribute(Attribute::ReadOnly);
2841 R.addAttribute(Attribute::WriteOnly);
2842 R.addAttribute(Attribute::NoAlias);
2843 R.addAttribute(Attribute::NoFree);
2863 F.removeParamAttrs(
A.getArgNo(), R);
2866 F.removeRetAttrs(R);
2869 F.removeFnAttr(Attr);
2891 unsigned ValidMetadataAfterRS4GC[] = {LLVMContext::MD_tbaa,
2892 LLVMContext::MD_range,
2893 LLVMContext::MD_alias_scope,
2894 LLVMContext::MD_nontemporal,
2895 LLVMContext::MD_nonnull,
2896 LLVMContext::MD_align,
2897 LLVMContext::MD_type};
2900 I.dropUnknownNonDebugMetadata(ValidMetadataAfterRS4GC);
2922 if (
II->getIntrinsicID() == Intrinsic::invariant_start) {
2927 if (
MDNode *Tag =
I.getMetadata(LLVMContext::MD_tbaa)) {
2928 MDNode *MutableTBAA = Builder.createMutableTBAAAccessTag(Tag);
2929 I.setMetadata(LLVMContext::MD_tbaa, MutableTBAA);
2936 for (
int i = 0, e =
Call->arg_size(); i != e; i++)
2938 Call->removeParamAttrs(i, R);
2940 Call->removeRetAttrs(R);
2945 for (
auto *
II : InvariantStartInstructions) {
2947 II->eraseFromParent();
2968 assert(Strategy &&
"GC strategy is required by function, but was not found");
2970 return Strategy->useRS4GC();
2988 assert(!
F.isDeclaration() && !
F.empty() &&
2989 "need function body to rewrite statepoints in");
3007 if (!Opts.rs4gc_allow_statepoint_with_no_deopt_info &&
3008 !
Call->hasDeoptState()) {
3011 "Don't expect any other calls here!");
3034 if (NeedsRewrite(
I)) {
3040 "no unreachable blocks expected");
3044 if (CI->getIntrinsicID() == Intrinsic::experimental_gc_get_pointer_base ||
3045 CI->getIntrinsicID() == Intrinsic::experimental_gc_get_pointer_offset)
3050 if (ParsePointNeeded.
empty() && Intrinsics.
empty())
3058 if (BB.getUniquePredecessor())
3082 if (
auto *
Cond = getConditionInst(TI))
3101 for (
unsigned i = 0; i <
I.getNumOperands(); i++)
3110 if (!
I.getOperand(0)->getType()->isVectorTy() && VF != 0) {
3112 auto *
Splat =
B.CreateVectorSplat(VF,
I.getOperand(0));
3122 DefiningValueMapTy DVCache;
3126 IsKnownBaseMapTy KnownBases;
3128 if (!Intrinsics.
empty())
3133 if (!ParsePointNeeded.
empty())
3161 for (
Value *V :
I.operands()) {
3163 "support for FCA unimplemented");
3184 for (
auto &
I : *Succ) {
3191 "support for FCA unimplemented");
3211 for (
Value *V : Live) {
3216 if (TermOkay && TI ==
I)
3219 "basic SSA liveness expectation violated by liveness analysis");
3242 auto &LiveSet =
Data.LiveSet[&BB];
3248 assert(!
Data.LiveSet[&BB].count(
Kill) &&
"live set contains kill");
3253 auto &In =
Data.LiveIn[&BB] =
Data.LiveSet[&BB];
3255 In.set_subtract(
Data.KillSet[&BB]);
3261 while (!Worklist.
empty()) {
3267 const auto OldLiveOutSize = LiveOut.
size();
3273 if (OldLiveOutSize == LiveOut.
size()) {
3288 if (LiveIn.
size() != LiveTmp.
size()) {
3289 LiveIn = std::move(LiveTmp);
3317 Out.insert_range(LiveOut);
3322 PartiallyConstructedSafepointRecord &Info,
3323 PointerToBaseTy &PointerToBase,
3325 StatepointLiveSetTy Updated;
3330 for (
auto *V : Updated)
3331 PointerToBase.insert({ V, V });
3333 Info.LiveSet = Updated;
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
ReachingDefInfo InstSet & ToRemove
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
Expand Atomic instructions
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
Module.h This file contains the declarations for the Module class.
This file implements a map that provides insertion order iteration.
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
SmallVector< MachineOperand, 4 > Cond
Remove Loads Into Fake Uses
static void makeStatepointExplicitImpl(CallBase *Call, const SmallVectorImpl< Value * > &BasePtrs, const SmallVectorImpl< Value * > &LiveVariables, PartiallyConstructedSafepointRecord &Result, std::vector< DeferredReplacement > &Replacements, const PointerToBaseTy &PointerToBase, GCStrategy *GC)
static void findRematerializationCandidates(PointerToBaseTy PointerToBase, RematCandTy &RematerizationCandidates, TargetTransformInfo &TTI)
static std::unique_ptr< GCStrategy > findGCStrategy(Function &F)
Looks up the GC strategy for a given function, returning null if the function doesn't have a GC tag.
static void stripNonValidDataFromBody(Function &F)
static void analyzeParsePointLiveness(const ScalarOptions &Opts, DominatorTree &DT, GCPtrLivenessData &OriginalLivenessData, CallBase *Call, PartiallyConstructedSafepointRecord &Result, GCStrategy *GC)
static ArrayRef< Use > getDeoptBundleOperands(const ScalarOptions &Opts, const CallBase *Call)
static bool isKnownBase(Value *V, const IsKnownBaseMapTy &KnownBases)
Returns true if V is a known base.
static Value * findBasePointer(Value *I, DefiningValueMapTy &Cache, IsKnownBaseMapTy &KnownBases)
For a given value or instruction, figure out what base ptr its derived from.
static cl::opt< bool, true > ClobberNonLiveOverride("rs4gc-clobber-non-live", cl::location(ClobberNonLive), cl::Hidden)
static BasicBlock * normalizeForInvokeSafepoint(BasicBlock *BB, BasicBlock *InvokeParent, DominatorTree &DT)
static bool insertParsePoints(const ScalarOptions &Opts, Function &F, DominatorTree &DT, TargetTransformInfo &TTI, SmallVectorImpl< CallBase * > &ToUpdate, DefiningValueMapTy &DVCache, IsKnownBaseMapTy &KnownBases)
static void computeLiveOutSeed(BasicBlock *BB, SetVector< Value * > &LiveTmp, GCStrategy *GC)
static void relocationViaAlloca(Function &F, DominatorTree &DT, ArrayRef< Value * > Live, ArrayRef< PartiallyConstructedSafepointRecord > Records)
Do all the relocation update via allocas and mem2reg.
static bool AreEquivalentPhiNodes(PHINode &OrigRootPhi, PHINode &AlternateRootPhi)
static void rematerializeLiveValues(const ScalarOptions &Opts, CallBase *Call, PartiallyConstructedSafepointRecord &Info, PointerToBaseTy &PointerToBase, RematCandTy &RematerizationCandidates, TargetTransformInfo &TTI)
static Value * findBaseOrBDV(Value *I, DefiningValueMapTy &Cache, IsKnownBaseMapTy &KnownBases)
Return a base pointer for this value if known.
static Value * findBaseDefiningValueCached(Value *I, DefiningValueMapTy &Cache, IsKnownBaseMapTy &KnownBases)
Returns the base defining value for this value.
static void insertUseHolderAfter(CallBase *Call, const ArrayRef< Value * > Values, SmallVectorImpl< CallInst * > &Holders)
Insert holders so that each Value is obviously live through the entire lifetime of the call.
static AttributeList legalizeCallAttributes(CallBase *Call, bool IsMemIntrinsic, AttributeList StatepointAL)
static void insertRematerializationStores(const RematerializedValueMapTy &RematerializedValues, DenseMap< Value *, AllocaInst * > &AllocaMap, DenseSet< Value * > &VisitedLiveValues)
static void findBasePointers(const StatepointLiveSetTy &live, PointerToBaseTy &PointerToBase, DominatorTree *DT, DefiningValueMapTy &DVCache, IsKnownBaseMapTy &KnownBases)
static bool shouldRewriteStatepointsIn(Function &F)
Returns true if this function should be rewritten by this pass.
static Instruction * rematerializeChain(ArrayRef< Instruction * > ChainToBase, BasicBlock::iterator InsertBefore, Value *RootOfChain, Value *AlternateLiveBase)
static void stripNonValidAttributesFromPrototype(Function &F)
static void findLiveSetAtInst(Instruction *inst, GCPtrLivenessData &Data, StatepointLiveSetTy &out, GCStrategy *GC)
Given results from the dataflow liveness computation, find the set of live Values at a particular ins...
static void computeLiveInValues(DominatorTree &DT, Function &F, GCPtrLivenessData &Data, GCStrategy *GC)
Compute the live-in set for every basic block in the function.
static void stripInvalidMetadataFromInstruction(Instruction &I)
Certain metadata on instructions are invalid after running RS4GC.
static constexpr Attribute::AttrKind FnAttrsToStrip[]
static bool areBothVectorOrScalar(Value *First, Value *Second)
static bool isHandledGCPointerType(Type *T, GCStrategy *GC)
static Value * findRematerializableChainToBasePointer(SmallVectorImpl< Instruction * > &ChainToBase, Value *CurrentValue)
static Value * findBaseDefiningValueOfVector(Value *I, DefiningValueMapTy &Cache, IsKnownBaseMapTy &KnownBases)
Return a base defining value for the 'Index' element of the given vector instruction 'I'.
static void stripNonValidData(Module &M)
The IR fed into RewriteStatepointsForGC may have had attributes and metadata implying dereferenceabil...
static InstructionCost chainToBasePointerCost(SmallVectorImpl< Instruction * > &Chain, TargetTransformInfo &TTI)
static bool isUnhandledGCPointerType(Type *Ty, GCStrategy *GC)
static SetVector< Value * > computeKillSet(BasicBlock *BB, GCStrategy *GC)
static bool ClobberNonLive
static bool isOriginalBaseResult(Value *V)
This value is a base pointer that is not generated by RS4GC, i.e.
static void insertRelocationStores(iterator_range< Instruction::user_iterator > GCRelocs, DenseMap< Value *, AllocaInst * > &AllocaMap, DenseSet< Value * > &VisitedLiveValues)
static void setKnownBase(Value *V, bool IsKnownBase, IsKnownBaseMapTy &KnownBases)
Caches the IsKnownBase flag for a value and asserts that it wasn't present in the cache before.
static void makeStatepointExplicit(DominatorTree &DT, CallBase *Call, PartiallyConstructedSafepointRecord &Result, std::vector< DeferredReplacement > &Replacements, const PointerToBaseTy &PointerToBase, GCStrategy *GC)
static std::string suffixed_name_or(Value *V, StringRef Suffix, StringRef DefaultName)
static void CreateGCRelocates(ArrayRef< Value * > LiveVariables, ArrayRef< Value * > BasePtrs, Instruction *StatepointToken, IRBuilder<> &Builder, GCStrategy *GC)
Helper function to place all gc relocates necessary for the given statepoint.
static void checkBasicSSA(DominatorTree &DT, SetVector< Value * > &Live, Instruction *TI, bool TermOkay=false)
Check that the items in 'Live' dominate 'TI'.
static StringRef getDeoptLowering(CallBase *Call)
static void findLiveReferences(const ScalarOptions &Opts, Function &F, DominatorTree &DT, ArrayRef< CallBase * > toUpdate, MutableArrayRef< struct PartiallyConstructedSafepointRecord > records, GCStrategy *GC)
static AttributeMask getParamAndReturnAttributesToRemove()
static bool inlineGetBaseAndOffset(Function &F, SmallVectorImpl< CallInst * > &Intrinsics, DefiningValueMapTy &DVCache, IsKnownBaseMapTy &KnownBases)
static Value * findBaseDefiningValue(Value *I, DefiningValueMapTy &Cache, IsKnownBaseMapTy &KnownBases)
Helper function for findBasePointer - Will return a value which either a) defines the base pointer fo...
static void rematerializeLiveValuesAtUses(const ScalarOptions &Opts, RematCandTy &RematerizationCandidates, MutableArrayRef< PartiallyConstructedSafepointRecord > Records, PointerToBaseTy &PointerToBase)
static void recomputeLiveInValues(GCPtrLivenessData &RevisedLivenessData, CallBase *Call, PartiallyConstructedSafepointRecord &result, PointerToBaseTy &PointerToBase, GCStrategy *GC)
Given an updated version of the dataflow liveness results, update the liveset and base pointer maps f...
verify safepoint Safepoint IR static false bool isGCPointerType(Type *T)
static bool containsGCPtrType(Type *Ty)
Provides some synthesis utilities to produce sequences of values.
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallVector class.
an instruction to allocate memory on the stack
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
This class represents an incoming formal argument to a Function.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
Value handle that asserts if the Value is deleted.
This class stores enough information to efficiently remove some attributes from an existing AttrBuild...
Functions, function parameters, and return types can have attributes to indicate how they should be t...
AttrKind
This enumeration lists the attributes that can be associated with parameters, function results,...
LLVM Basic Block Representation.
iterator begin()
Instruction iterator methods.
LLVM_ABI const LandingPadInst * getLandingPadInst() const
Return the landingpad instruction associated with the landing pad.
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...
reverse_iterator rbegin()
LLVM_ABI InstListType::const_iterator getFirstNonPHIIt() const
Returns an iterator to the first instruction in this block that is not a PHINode instruction.
InstListType::reverse_iterator reverse_iterator
LLVM_ABI const BasicBlock * getUniquePredecessor() const
Return the predecessor of this block if it has a unique predecessor block.
InstListType::iterator iterator
Instruction iterators...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
This class represents a no-op cast from one type to another.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
void setCallingConv(CallingConv::ID CC)
void setAttributes(AttributeList A)
Set the attributes for this call.
AttributeList getAttributes() const
Return the attributes for this call.
This class represents a function call, abstracting a target machine's calling convention.
void setTailCallKind(TailCallKind TCK)
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
This is the base class for all instructions that perform data casts.
static LLVM_ABI ConstantAggregateZero * get(Type *Ty)
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.
This is an important base class in LLVM.
A parsed version of the target data layout string in and methods for querying it.
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Implements a dense probed hash-table based set.
Analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
LLVM_ABI bool isReachableFromEntry(const Use &U) const
Provide an overload for a Use.
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.
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
Represents calls to the gc.relocate intrinsic.
LLVM_ABI Value * getDerivedPtr() const
Represents a gc.statepoint intrinsic call.
GCStrategy describes a garbage collector algorithm's code generation requirements,...
DomTreeT & getDomTree()
Flush DomTree updates and return DomTree.
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
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.
iterator_range< user_iterator > users()
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
user_iterator user_begin()
A wrapper class for inspecting calls to intrinsic functions.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
This class implements a map that also provides access to all stored values in a deterministic order.
iterator find(const KeyT &Key)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
size_type count(const KeyT &Key) const
A Module instance is used to store all the information related to an LLVM module.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
Value * getIncomingValueForBlock(const BasicBlock *BB) const
BasicBlock * getIncomingBlock(unsigned i) const
Return incoming basic block number i.
Value * getIncomingValue(unsigned i) const
Return incoming value number x.
unsigned getNumIncomingValues() const
Return the number of incoming edges.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
This class represents the LLVM 'select' instruction.
A vector that has set insertion semantics.
ArrayRef< value_type > getArrayRef() const
bool remove(const value_type &X)
Remove an item from the set vector.
size_type size() const
Determine the number of elements in the SetVector.
void insert_range(Range &&R)
bool set_union(const STy &S)
Compute This := This u S, return whether 'This' changed.
bool empty() const
Determine if the SetVector is empty or not.
void set_subtract(const STy &S)
Compute This := This - B TODO: We should be able to use set_subtract from SetOperations....
bool insert(const value_type &X)
Insert a new element into the SetVector.
value_type pop_back_val()
A SetVector that performs no allocations if smaller than a certain size.
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.
An instruction for storing to memory.
Represent a constant reference to a string, i.e.
std::string str() const
Get the contents as an std::string.
Class to represent struct types.
Analysis pass providing the TargetTransformInfo.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
static LLVM_ABI Type * getVoidTy(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 bool replaceUsesOfWith(Value *From, Value *To)
Replace uses of one Value with another.
iterator_range< value_op_iterator > operand_values()
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
bool hasOneUse() const
Return true if there is exactly one use 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.
LLVM_ABI User * getUniqueUndroppableUser()
Return true if there is exactly one unique user of this value that cannot be dropped (that user can h...
LLVM_ABI unsigned getNumUses() const
This method computes the number of uses of this Value.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
std::pair< iterator, bool > insert(const ValueT &V)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
const ParentTy * getParent() const
self_iterator getIterator()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
A range adaptor for a pair of iterators.
This class implements an extremely fast bulk output stream that can only output to a stream.
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ Cold
Attempts to make code in the caller as efficient as possible under the assumption that the call is no...
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
LLVM_ABI AttributeList getAttributes(LLVMContext &C, ID id, FunctionType *FT)
Return the attributes for an intrinsic.
LocationClass< Ty > location(Ty &L)
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
auto find(R &&Range, const T &Val)
Provide wrappers to std::find 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...
RelativeUniformCounterPtr Values
@ Unknown
Not known to have no common set bits.
@ Kill
The last use of a register.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto successors(const MachineBasicBlock *BB)
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
bool operator!=(uint64_t V1, const APInt &V2)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
const ScalarOptions & getScalarOptions(const LLVMContext &C)
auto unique(Range &&R, Predicate P)
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
auto make_isa_range(RangeT &&Range)
Return a range over Range containing only elements for which isa<T> holds, casting each of them to T.
LLVM_ABI bool removeUnreachableBlocks(Function &F, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr, bool FoldInstsToUnreachable=true)
Remove all blocks that can not be reached from the function's entry.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
auto reverse(ContainerTy &&C)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI StatepointDirectives parseStatepointDirectivesFromAttrs(AttributeList AS)
Parse out statepoint directives from the function attributes present in AS.
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 raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
LLVM_ABI BasicBlock * SplitBlockPredecessors(BasicBlock *BB, ArrayRef< BasicBlock * > Preds, const char *Suffix, DominatorTree *DT, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, bool PreserveLCSSA=false)
This method introduces at least one new basic block into the function and moves some of the predecess...
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
DWARFExpression::Operation Op
LLVM_ABI bool FoldSingleEntryPHINodes(BasicBlock *BB, MemoryDependenceResults *MemDep=nullptr)
We know that BB has one predecessor.
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
@ DeoptLiveIn
Mark the deopt arguments associated with the statepoint as only being "live-in".
@ GCTransition
Indicates that this statepoint is a transition from GC-aware code to code that is not GC-aware.
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
LLVM_ABI std::unique_ptr< GCStrategy > getGCStrategy(const StringRef Name)
Lookup the GCStrategy object associated with the given gc name.
auto predecessors(const MachineBasicBlock *BB)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
@ End
Run the machine verifier once, at the end of the pipeline.
LLVM_ABI bool isStatepointDirectiveAttr(Attribute Attr)
Return true if the Attr is an attribute that is a statepoint directive.
LLVM_ABI bool callsGCLeafFunction(const CallBase *Call, const TargetLibraryInfo &TLI)
Return true if this call calls a gc leaf function.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
LLVM_ABI bool runOnFunction(Function &F, DominatorTree &, TargetTransformInfo &, const TargetLibraryInfo &)
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
Call sites that get wrapped by a gc.statepoint (currently only in RewriteStatepointsForGC and potenti...
std::optional< uint32_t > NumPatchBytes
std::optional< uint64_t > StatepointID
static const uint64_t DefaultStatepointID