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?");
1505 auto getGCRelocateDecl = [&](
Type *Ty) {
1507 auto AS = Ty->getScalarType()->getPointerAddressSpace();
1513 M, Intrinsic::experimental_gc_relocate, {NewTy});
1524 Value *LiveIdx = Builder.getInt32(i);
1527 auto [It, Inserted] = TypeToDeclMap.
try_emplace(Ty);
1529 It->second = getGCRelocateDecl(Ty);
1530 Function *GCRelocateDecl = It->second;
1534 GCRelocateDecl, {StatepointToken, BaseIdx, LiveIdx},
1546class DeferredReplacement {
1547 AssertingVH<Instruction> Old;
1548 AssertingVH<Instruction>
New;
1549 bool IsDeoptimize =
false;
1551 DeferredReplacement() =
default;
1554 static DeferredReplacement createRAUW(Instruction *Old, Instruction *New) {
1555 assert(Old != New && Old && New &&
1556 "Cannot RAUW equal values or to / from null!");
1558 DeferredReplacement
D;
1564 static DeferredReplacement createDelete(Instruction *ToErase) {
1565 DeferredReplacement
D;
1570 static DeferredReplacement createDeoptimizeReplacement(Instruction *Old) {
1573 assert(
F &&
F->getIntrinsicID() == Intrinsic::experimental_deoptimize &&
1574 "Only way to construct a deoptimize deferred replacement");
1576 DeferredReplacement
D;
1578 D.IsDeoptimize =
true;
1583 void doReplacement() {
1587 assert(OldI != NewI &&
"Disallowed at construction?!");
1588 assert((!IsDeoptimize || !New) &&
1589 "Deoptimize intrinsics are not replaced!");
1601 new UnreachableInst(RI->getContext(), RI->getIterator());
1602 RI->eraseFromParent();
1612 const char *DeoptLowering =
"deopt-lowering";
1613 if (
Call->hasFnAttr(DeoptLowering)) {
1617 if (CSAS.hasFnAttr(DeoptLowering))
1618 return CSAS.getFnAttr(DeoptLowering).getValueAsString();
1620 assert(
F &&
F->hasFnAttribute(DeoptLowering));
1621 return F->getFnAttribute(DeoptLowering).getValueAsString();
1623 return "live-through";
1630 PartiallyConstructedSafepointRecord &Result,
1631 std::vector<DeferredReplacement> &Replacements,
1632 const PointerToBaseTy &PointerToBase,
1648 std::optional<ArrayRef<Use>> DeoptArgs;
1650 DeoptArgs = Bundle->Inputs;
1651 std::optional<ArrayRef<Use>> TransitionArgs;
1653 TransitionArgs = Bundle->Inputs;
1661 bool IsDeoptimize =
false;
1662 bool IsMemIntrinsic =
false;
1673 if (DeoptLowering ==
"live-in")
1676 assert(DeoptLowering ==
"live-through" &&
"Unsupported value!");
1681 auto IID =
F->getIntrinsicID();
1682 if (IID == Intrinsic::experimental_deoptimize) {
1688 for (
Value *Arg : CallArgs)
1697 CallTarget =
F->getParent()
1698 ->getOrInsertFunction(
"__llvm_deoptimize", FTy);
1700 IsDeoptimize =
true;
1701 }
else if (IID == Intrinsic::memcpy_element_unordered_atomic ||
1702 IID == Intrinsic::memmove_element_unordered_atomic) {
1703 IsMemIntrinsic =
true;
1721 auto &Context =
Call->getContext();
1722 auto &
DL =
Call->getDataLayout();
1723 auto GetBaseAndOffset = [&](
Value *Derived) {
1733 assert(PointerToBase.count(Derived));
1734 Base = PointerToBase.find(Derived)->second;
1736 unsigned AddressSpace = Derived->getType()->getPointerAddressSpace();
1738 Value *Base_int = Builder.CreatePtrToInt(
1740 Value *Derived_int = Builder.CreatePtrToInt(
1742 return std::make_pair(
Base, Builder.CreateSub(Derived_int, Base_int));
1745 auto *Dest = CallArgs[0];
1746 Value *DestBase, *DestOffset;
1747 std::tie(DestBase, DestOffset) = GetBaseAndOffset(Dest);
1749 auto *Source = CallArgs[1];
1750 Value *SourceBase, *SourceOffset;
1751 std::tie(SourceBase, SourceOffset) = GetBaseAndOffset(Source);
1753 auto *LengthInBytes = CallArgs[2];
1764 for (
Value *Arg : CallArgs)
1770 uint64_t ElementSize = ElementSizeCI->getZExtValue();
1771 if (IID == Intrinsic::memcpy_element_unordered_atomic) {
1772 switch (ElementSize) {
1774 return "__llvm_memcpy_element_unordered_atomic_safepoint_1";
1776 return "__llvm_memcpy_element_unordered_atomic_safepoint_2";
1778 return "__llvm_memcpy_element_unordered_atomic_safepoint_4";
1780 return "__llvm_memcpy_element_unordered_atomic_safepoint_8";
1782 return "__llvm_memcpy_element_unordered_atomic_safepoint_16";
1787 assert(IID == Intrinsic::memmove_element_unordered_atomic);
1788 switch (ElementSize) {
1790 return "__llvm_memmove_element_unordered_atomic_safepoint_1";
1792 return "__llvm_memmove_element_unordered_atomic_safepoint_2";
1794 return "__llvm_memmove_element_unordered_atomic_safepoint_4";
1796 return "__llvm_memmove_element_unordered_atomic_safepoint_8";
1798 return "__llvm_memmove_element_unordered_atomic_safepoint_16";
1806 ->getOrInsertFunction(GetFunctionName(IID, ElementSizeCI), FTy);
1813 CallInst *SPCall = Builder.CreateGCStatepointCall(
1814 StatepointID, NumPatchBytes, CallTarget, Flags, CallArgs,
1815 TransitionArgs, DeoptArgs, GCLive,
"safepoint_token");
1829 assert(CI->getNextNode() &&
"Not a terminator, must have next!");
1830 Builder.SetInsertPoint(CI->getNextNode());
1831 Builder.SetCurrentDebugLocation(CI->getNextNode()->getDebugLoc());
1838 InvokeInst *SPInvoke = Builder.CreateGCStatepointInvoke(
1839 StatepointID, NumPatchBytes, CallTarget,
II->getNormalDest(),
1840 II->getUnwindDest(), Flags, CallArgs, TransitionArgs, DeoptArgs,
1841 GCLive,
"statepoint_token");
1856 "can't safely insert in this block!");
1859 Builder.SetCurrentDebugLocation(
II->getDebugLoc());
1863 Result.UnwindToken = ExceptionalToken;
1871 "can't safely insert in this block!");
1878 assert(Token &&
"Should be set in one of the above branches!");
1884 Replacements.push_back(
1885 DeferredReplacement::createDeoptimizeReplacement(
Call));
1887 Token->
setName(
"statepoint_token");
1888 if (!
Call->getType()->isVoidTy() && !
Call->use_empty()) {
1890 CallInst *GCResult = Builder.CreateGCResult(Token,
Call->getType(), Name);
1892 AttributeList::get(GCResult->
getContext(), AttributeList::ReturnIndex,
1893 Call->getAttributes().getRetAttrs()));
1901 Replacements.emplace_back(
1902 DeferredReplacement::createRAUW(
Call, GCResult));
1904 Replacements.emplace_back(DeferredReplacement::createDelete(
Call));
1908 Result.StatepointToken = Token;
1921 PartiallyConstructedSafepointRecord &Result,
1922 std::vector<DeferredReplacement> &Replacements,
1923 const PointerToBaseTy &PointerToBase,
GCStrategy *GC) {
1924 const auto &LiveSet = Result.LiveSet;
1928 LiveVec.
reserve(LiveSet.size());
1929 BaseVec.
reserve(LiveSet.size());
1930 for (
Value *L : LiveSet) {
1932 assert(PointerToBase.count(L));
1933 Value *
Base = PointerToBase.find(L)->second;
1953 for (
User *U : GCRelocs) {
1960 Value *Alloca = AllocaMap[OriginalValue];
1964 "Should always have one since it's not a terminator");
1968 VisitedLiveValues.
insert(OriginalValue);
1976 const RematerializedValueMapTy &RematerializedValues,
1979 for (
auto RematerializedValuePair: RematerializedValues) {
1980 Instruction *RematerializedValue = RematerializedValuePair.first;
1981 Value *OriginalValue = RematerializedValuePair.second;
1984 "Can not find alloca for rematerialized value");
1985 Value *Alloca = AllocaMap[OriginalValue];
1987 new StoreInst(RematerializedValue, Alloca,
1991 VisitedLiveValues.
insert(OriginalValue);
2003 int InitialAllocaNum = 0;
2013 std::size_t NumRematerializedValues = 0;
2019 auto emitAllocaFor = [&](
Value *LiveValue) {
2021 new AllocaInst(LiveValue->getType(),
DL.getAllocaAddrSpace(),
"",
2022 F.getEntryBlock().getFirstNonPHIIt());
2023 AllocaMap[LiveValue] = Alloca;
2028 for (
Value *V : Live)
2032 for (
const auto &Info : Records)
2033 for (
auto RematerializedValuePair : Info.RematerializedValues) {
2034 Value *OriginalValue = RematerializedValuePair.second;
2035 if (AllocaMap.
contains(OriginalValue))
2038 emitAllocaFor(OriginalValue);
2039 ++NumRematerializedValues;
2051 for (
const auto &Info : Records) {
2078 for (
auto Pair : AllocaMap) {
2079 Value *Def = Pair.first;
2083 if (VisitedLiveValues.
count(Def)) {
2087 ToClobber.
push_back({Def->getType(), Alloca});
2091 for (
auto &[Ty, AI] : ToClobber) {
2093 if (Ty->isVectorTy())
2104 InsertClobbersAt(
II->getNormalDest()->getFirstInsertionPt());
2105 InsertClobbersAt(
II->getUnwindDest()->getFirstInsertionPt());
2114 for (
auto Pair : AllocaMap) {
2115 Value *Def = Pair.first;
2123 Uses.reserve(Def->getNumUses());
2124 for (
User *U : Def->users()) {
2142 for (
unsigned i = 0; i < Phi->getNumIncomingValues(); i++) {
2143 if (Def == Phi->getIncomingValue(i)) {
2146 Def->getType(), Alloca,
"",
2147 Phi->getIncomingBlock(i)->getTerminator()->getIterator());
2148 Phi->setIncomingValue(i,
Load);
2154 new LoadInst(Def->getType(), Alloca,
"",
Use->getIterator());
2155 Use->replaceUsesOfWith(Def,
Load);
2163 DL.getABITypeAlign(Def->getType()));
2168 BasicBlock *NormalDest = Invoke->getNormalDest();
2171 assert(!Inst->isTerminator() &&
2172 "The only terminator that can produce a value is "
2173 "InvokeInst which is handled above.");
2174 Store->insertAfter(Inst->getIterator());
2182 assert(PromotableAllocas.
size() == Live.
size() + NumRematerializedValues &&
2183 "we must have the same allocas with lives");
2184 (void) NumRematerializedValues;
2185 if (!PromotableAllocas.
empty()) {
2191 for (
auto &
I :
F.getEntryBlock())
2194 assert(InitialAllocaNum == 0 &&
"We must not introduce any extra allocas");
2220 Func,
Values,
"",
II->getNormalDest()->getFirstInsertionPt()));
2222 Func,
Values,
"",
II->getUnwindDest()->getFirstInsertionPt()));
2230 GCPtrLivenessData OriginalLivenessData;
2232 for (
size_t i = 0; i < records.
size(); i++) {
2233 struct PartiallyConstructedSafepointRecord &
info = records[i];
2247 Value *CurrentValue) {
2251 GEP->getPointerOperand());
2255 if (!CI->isNoopCast(CI->getDataLayout()))
2265 return CurrentValue;
2277 assert(CI->isNoopCast(CI->getDataLayout()) &&
2278 "non noop cast is found during rematerialization");
2280 Type *SrcTy = CI->getOperand(0)->getType();
2281 Cost +=
TTI.getCastInstrCost(CI->getOpcode(), CI->getType(), SrcTy,
2287 Cost +=
TTI.getAddressComputationCost(
2288 GEP->getType(),
nullptr,
nullptr,
2294 if (!
GEP->hasAllConstantIndices())
2313 for (
unsigned i = 0; i < PhiNum; i++)
2319 for (
unsigned i = 0; i < PhiNum; i++) {
2322 if (CIVI == CurrentIncomingValues.
end())
2324 BasicBlock *CurrentIncomingBB = CIVI->second;
2335 RematCandTy &RematerizationCandidates,
2337 const unsigned int ChainLengthThreshold = 10;
2339 for (
auto P2B : PointerToBase) {
2340 auto *Derived = P2B.first;
2341 auto *
Base = P2B.second;
2343 if (Derived ==
Base)
2348 Value *RootOfChain =
2352 if ( ChainToBase.
size() == 0 ||
2353 ChainToBase.
size() > ChainLengthThreshold)
2358 if (
Value *BaseVal = PointerToBase[Derived]; RootOfChain != BaseVal) {
2361 if (!OrigRootPhi || !AlternateRootPhi)
2383 RematerizlizationCandidateRecord
Record;
2384 Record.ChainToBase = ChainToBase;
2385 Record.RootOfChain = RootOfChain;
2387 RematerizationCandidates.insert({ Derived,
Record });
2396 const ScalarOptions &Opts, RematCandTy &RematerizationCandidates,
2398 PointerToBaseTy &PointerToBase) {
2399 if (!Opts.rs4gc_remat_derived_at_uses)
2405 <<
"Num statepoints: " << Records.
size() <<
'\n');
2407 for (
auto &It : RematerizationCandidates) {
2409 auto &
Record = It.second;
2411 if (
Record.Cost >= Opts.spp_rematerialization_threshold)
2419 if (U->getParent() == Cand->
getParent())
2424 [](
const auto *U) { return isa<PHINode>(U); }))
2436 Records, [Cand](
const auto &R) {
return R.LiveSet.contains(Cand); });
2439 LLVM_DEBUG(
dbgs() <<
"Num uses: " << NumUses <<
" Num live statepoints: "
2440 << NumLiveStatepoints <<
" ");
2442 if (NumLiveStatepoints < NumUses) {
2450 if (NumLiveStatepoints == NumUses &&
Record.Cost > 0) {
2462 if (
Record.ChainToBase.size() > 1) {
2463 Record.ChainToBase.clear();
2480 Record.RootOfChain, PointerToBase[Cand]);
2482 PointerToBase[RematChain] = PointerToBase[Cand];
2488 <<
" derived pointers\n");
2489 for (
auto *Cand : LiveValuesToBeDeleted) {
2490 assert(Cand->use_empty() &&
"Unexpected user remain");
2491 RematerizationCandidates.erase(Cand);
2492 for (
auto &R : Records) {
2493 assert(!R.LiveSet.contains(Cand) ||
2494 R.LiveSet.contains(PointerToBase[Cand]));
2495 R.LiveSet.remove(Cand);
2501 if (!LiveValuesToBeDeleted.
empty()) {
2502 for (
auto &
P : RematerizationCandidates) {
2504 if (R.ChainToBase.size() > 1) {
2505 R.ChainToBase.clear();
2517 PartiallyConstructedSafepointRecord &Info,
2518 PointerToBaseTy &PointerToBase,
2519 RematCandTy &RematerizationCandidates,
2525 for (
Value *LiveValue : Info.LiveSet) {
2526 auto It = RematerizationCandidates.find(LiveValue);
2527 if (It == RematerizationCandidates.end())
2530 RematerizlizationCandidateRecord &
Record = It->second;
2539 if (Cost >= Opts.spp_rematerialization_threshold)
2543 LiveValuesToBeDeleted.
push_back(LiveValue);
2554 Record.RootOfChain, PointerToBase[LiveValue]);
2555 Info.RematerializedValues[RematerializedValue] = LiveValue;
2560 Invoke->getNormalDest()->getFirstInsertionPt();
2562 Invoke->getUnwindDest()->getFirstInsertionPt();
2566 Record.RootOfChain, PointerToBase[LiveValue]);
2569 Record.RootOfChain, PointerToBase[LiveValue]);
2571 Info.RematerializedValues[NormalRematerializedValue] = LiveValue;
2572 Info.RematerializedValues[UnwindRematerializedValue] = LiveValue;
2577 for (
auto *LiveValue: LiveValuesToBeDeleted) {
2578 Info.LiveSet.remove(LiveValue);
2584 DefiningValueMapTy &DVCache,
2585 IsKnownBaseMapTy &KnownBases) {
2586 auto &Context =
F.getContext();
2587 auto &
DL =
F.getDataLayout();
2590 for (
auto *Callsite : Intrinsics)
2591 switch (Callsite->getIntrinsicID()) {
2592 case Intrinsic::experimental_gc_get_pointer_base: {
2596 assert(!DVCache.count(Callsite));
2597 Callsite->replaceAllUsesWith(
Base);
2598 if (!
Base->hasName())
2599 Base->takeName(Callsite);
2600 Callsite->eraseFromParent();
2603 case Intrinsic::experimental_gc_get_pointer_offset: {
2605 Value *Derived = Callsite->getOperand(0);
2607 assert(!DVCache.count(Callsite));
2617 Value *
Offset = Builder.CreateSub(DerivedInt, BaseInt);
2618 Callsite->replaceAllUsesWith(
Offset);
2619 Offset->takeName(Callsite);
2620 Callsite->eraseFromParent();
2633 DefiningValueMapTy &DVCache,
2634 IsKnownBaseMapTy &KnownBases) {
2639 std::set<CallBase *> Uniqued;
2640 Uniqued.insert(ToUpdate.
begin(), ToUpdate.
end());
2641 assert(Uniqued.size() == ToUpdate.
size() &&
"no duplicates please!");
2669 "support for FCA unimplemented");
2684 PointerToBaseTy PointerToBase;
2687 for (
size_t i = 0; i < Records.
size(); i++) {
2688 PartiallyConstructedSafepointRecord &
info = Records[i];
2691 if (Opts.spp_print_base_pointers) {
2692 errs() <<
"Base Pairs (w/o Relocation):\n";
2693 for (
auto &Pair : PointerToBase) {
2694 errs() <<
" derived ";
2695 Pair.first->printAsOperand(
errs(),
false);
2697 Pair.second->printAsOperand(
errs(),
false);
2717 for (
size_t i = 0; i < Records.
size(); i++) {
2718 PartiallyConstructedSafepointRecord &Info = Records[i];
2721 for (
auto *Derived : Info.LiveSet) {
2722 assert(PointerToBase.count(Derived) &&
"Missed base for derived pointer");
2723 Bases.
push_back(PointerToBase[Derived]);
2734 if (Opts.spp_print_base_pointers) {
2735 errs() <<
"Base Pairs: (w/Relocation)\n";
2736 for (
auto Pair : PointerToBase) {
2737 errs() <<
" derived ";
2738 Pair.first->printAsOperand(
errs(),
false);
2740 Pair.second->printAsOperand(
errs(),
false);
2753 for (
auto &Info : Records) {
2754 Info.LiveSet.remove_if([&](
Value *LiveV) {
2755 assert(PointerToBase.count(LiveV) &&
"Missed base for derived pointer");
2761 CI->eraseFromParent();
2766 RematCandTy RematerizationCandidates;
2775 for (
size_t i = 0; i < Records.
size(); i++)
2777 RematerizationCandidates,
TTI);
2782 std::vector<DeferredReplacement> Replacements;
2790 for (
size_t i = 0; i < Records.
size(); i++)
2792 PointerToBase, GC.get());
2796 for (
auto &PR : Replacements)
2799 Replacements.clear();
2801 for (
auto &Info : Records) {
2810 Info.LiveSet.clear();
2812 PointerToBase.clear();
2818 for (
const PartiallyConstructedSafepointRecord &Info : Records) {
2831 "statepoint must be reachable or liveness is meaningless");
2832 for (
Value *V : Info.StatepointToken->gc_live()) {
2838 "unreachable values should never be live");
2840 "basic SSA liveness expectation violated by liveness analysis");
2847 for (
auto *Ptr : Live)
2849 "must be a gc pointer type");
2853 return !Records.
empty();
2861 R.addAttribute(Attribute::Dereferenceable);
2862 R.addAttribute(Attribute::DereferenceableOrNull);
2863 R.addAttribute(Attribute::ReadNone);
2864 R.addAttribute(Attribute::ReadOnly);
2865 R.addAttribute(Attribute::WriteOnly);
2866 R.addAttribute(Attribute::NoAlias);
2867 R.addAttribute(Attribute::NoFree);
2887 F.removeParamAttrs(
A.getArgNo(), R);
2890 F.removeRetAttrs(R);
2893 F.removeFnAttr(Attr);
2915 unsigned ValidMetadataAfterRS4GC[] = {LLVMContext::MD_tbaa,
2916 LLVMContext::MD_range,
2917 LLVMContext::MD_alias_scope,
2918 LLVMContext::MD_nontemporal,
2919 LLVMContext::MD_nonnull,
2920 LLVMContext::MD_align,
2921 LLVMContext::MD_type};
2924 I.dropUnknownNonDebugMetadata(ValidMetadataAfterRS4GC);
2946 if (
II->getIntrinsicID() == Intrinsic::invariant_start) {
2951 if (
MDNode *Tag =
I.getMetadata(LLVMContext::MD_tbaa)) {
2952 MDNode *MutableTBAA = Builder.createMutableTBAAAccessTag(Tag);
2953 I.setMetadata(LLVMContext::MD_tbaa, MutableTBAA);
2960 for (
int i = 0, e =
Call->arg_size(); i != e; i++)
2962 Call->removeParamAttrs(i, R);
2964 Call->removeRetAttrs(R);
2969 for (
auto *
II : InvariantStartInstructions) {
2971 II->eraseFromParent();
2992 assert(Strategy &&
"GC strategy is required by function, but was not found");
2994 return Strategy->useRS4GC();
3012 assert(!
F.isDeclaration() && !
F.empty() &&
3013 "need function body to rewrite statepoints in");
3015 const ScalarOptions &Opts = ScalarOptions::Global;
3031 if (!Opts.rs4gc_allow_statepoint_with_no_deopt_info &&
3032 !
Call->hasDeoptState()) {
3035 "Don't expect any other calls here!");
3058 if (NeedsRewrite(
I)) {
3064 "no unreachable blocks expected");
3068 if (CI->getIntrinsicID() == Intrinsic::experimental_gc_get_pointer_base ||
3069 CI->getIntrinsicID() == Intrinsic::experimental_gc_get_pointer_offset)
3074 if (ParsePointNeeded.
empty() && Intrinsics.
empty())
3082 if (BB.getUniquePredecessor())
3106 if (
auto *
Cond = getConditionInst(TI))
3125 for (
unsigned i = 0; i <
I.getNumOperands(); i++)
3134 if (!
I.getOperand(0)->getType()->isVectorTy() && VF != 0) {
3136 auto *
Splat =
B.CreateVectorSplat(VF,
I.getOperand(0));
3146 DefiningValueMapTy DVCache;
3150 IsKnownBaseMapTy KnownBases;
3152 if (!Intrinsics.
empty())
3157 if (!ParsePointNeeded.
empty())
3185 for (
Value *V :
I.operands()) {
3187 "support for FCA unimplemented");
3208 for (
auto &
I : *Succ) {
3215 "support for FCA unimplemented");
3235 for (
Value *V : Live) {
3240 if (TermOkay && TI ==
I)
3243 "basic SSA liveness expectation violated by liveness analysis");
3266 auto &LiveSet =
Data.LiveSet[&BB];
3272 assert(!
Data.LiveSet[&BB].count(
Kill) &&
"live set contains kill");
3277 auto &In =
Data.LiveIn[&BB] =
Data.LiveSet[&BB];
3279 In.set_subtract(
Data.KillSet[&BB]);
3285 while (!Worklist.
empty()) {
3291 const auto OldLiveOutSize = LiveOut.
size();
3297 if (OldLiveOutSize == LiveOut.
size()) {
3312 if (LiveIn.
size() != LiveTmp.
size()) {
3313 LiveIn = std::move(LiveTmp);
3341 Out.insert_range(LiveOut);
3346 PartiallyConstructedSafepointRecord &Info,
3347 PointerToBaseTy &PointerToBase,
3349 StatepointLiveSetTy Updated;
3354 for (
auto *V : Updated)
3355 PointerToBase.insert({ V, V });
3357 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
const SmallVectorImpl< MachineOperand > & 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.
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
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 PointerType * get(LLVMContext &C, unsigned AddressSpace)
This constructs an opaque pointer to an object in a numbered address space.
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
@ 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.
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.
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