73#define DEBUG_TYPE "function-attrs"
75STATISTIC(NumMemoryAttr,
"Number of functions with improved memory attribute");
76STATISTIC(NumCapturesNone,
"Number of arguments marked captures(none)");
77STATISTIC(NumCapturesPartial,
"Number of arguments marked with captures "
78 "attribute other than captures(none)");
79STATISTIC(NumReturned,
"Number of arguments marked returned");
80STATISTIC(NumReadNoneArg,
"Number of arguments marked readnone");
81STATISTIC(NumReadOnlyArg,
"Number of arguments marked readonly");
82STATISTIC(NumWriteOnlyArg,
"Number of arguments marked writeonly");
83STATISTIC(NumNoAlias,
"Number of function returns marked noalias");
84STATISTIC(NumNonNullReturn,
"Number of function returns marked nonnull");
85STATISTIC(NumNoUndefReturn,
"Number of function returns marked noundef");
86STATISTIC(NumNoRecurse,
"Number of functions marked as norecurse");
87STATISTIC(NumNoUnwind,
"Number of functions marked as nounwind");
88STATISTIC(NumNoFree,
"Number of functions marked as nofree");
89STATISTIC(NumWillReturn,
"Number of functions marked as willreturn");
90STATISTIC(NumNoSync,
"Number of functions marked as nosync");
91STATISTIC(NumCold,
"Number of functions marked as cold");
94 "Number of functions marked as norecurse during thinlink");
96 "Number of functions marked as nounwind during thinlink");
100 cl::desc(
"Try to propagate nonnull and nofpclass argument attributes from "
101 "callsites to caller functions."));
105 cl::desc(
"Stop inferring nounwind attribute during function-attrs pass"));
109 cl::desc(
"Stop inferring nofree attribute during function-attrs pass"));
113 cl::desc(
"Don't propagate function-attrs in thinLTO"));
119 ++NumCapturesPartial;
153 if (!Arg->getType()->isPtrOrPtrVectorTy())
174static std::pair<MemoryEffects, MemoryEffects>
176 const SCCNodeSet &SCCNodes) {
202 if (
F.getAttributes().hasAttrSomewhere(Attribute::InAlloca) ||
203 F.getAttributes().hasAttrSomewhere(Attribute::Preallocated))
216 if (!
Call->hasOperandBundles() &&
Call->getCalledFunction() &&
217 SCCNodes.count(
Call->getCalledFunction())) {
237 AddNonArgMemoryEffects(CallME);
259 AddNonArgMemoryEffects(InstME);
263 return {OrigME & ME, RecursiveArgME};
272template <
typename AARGetterT>
283 auto [FnME, FnRecursiveArgME] =
286 RecursiveArgME |= FnRecursiveArgME;
300 if (NewME != OldME) {
302 F->setMemoryEffects(NewME);
306 A.removeAttr(Attribute::Writable);
320 auto [It, Inserted] = CachedPrevailingSummary.
try_emplace(VI);
367 for (
const auto &GVS : VI.getSummaryList()) {
373 if (!FS || FS->fflags().HasUnknownCall)
376 const auto &
Linkage = GVS->linkage();
381 <<
"ThinLTO FunctionAttrs: Multiple Local Linkage, bailing on "
383 << VI.name() <<
" from " << FS->modulePath() <<
". Previous module "
384 <<
Local->modulePath() <<
"\n");
389 assert(IsPrevailing(VI.getGUID(), GVS.get()) || GVS->wasPromoted());
396 if (IsPrevailing(VI.getGUID(), GVS.get())) {
406 auto &CPS = CachedPrevailingSummary[VI];
410 }
else if (Prevailing) {
430 auto PropagateAttributes = [&](std::vector<ValueInfo> &SCCNodes) {
433 InferredFlags.
NoRecurse = (SCCNodes.size() == 1);
436 for (
auto &V : SCCNodes) {
447 for (
const auto &Callee : CallerSummary->
calls()) {
449 Callee.first, CachedPrevailingSummary, IsPrevailing);
467 for (
auto &V : SCCNodes) {
469 LLVM_DEBUG(
dbgs() <<
"ThinLTO FunctionAttrs: Propagated NoRecurse to "
470 << V.name() <<
"\n");
471 ++NumThinLinkNoRecurse;
475 LLVM_DEBUG(
dbgs() <<
"ThinLTO FunctionAttrs: Propagated NoUnwind to "
476 << V.name() <<
"\n");
477 ++NumThinLinkNoUnwind;
480 for (
const auto &S : V.getSummaryList()) {
496 std::vector<ValueInfo> Nodes(*
I);
497 PropagateAttributes(Nodes);
507struct ArgumentGraphNode {
518 using ArgumentMapTy = std::map<Argument *, ArgumentGraphNode>;
520 ArgumentMapTy ArgumentMap;
528 ArgumentGraphNode SyntheticRoot;
531 ArgumentGraph() { SyntheticRoot.Definition =
nullptr; }
535 iterator
begin() {
return SyntheticRoot.Uses.begin(); }
536 iterator
end() {
return SyntheticRoot.Uses.end(); }
537 ArgumentGraphNode *getEntryNode() {
return &SyntheticRoot; }
539 ArgumentGraphNode *operator[](Argument *
A) {
540 ArgumentGraphNode &
Node = ArgumentMap[
A];
542 SyntheticRoot.Uses.push_back(&Node);
551 ArgumentUsesTracker(
const SCCNodeSet &SCCNodes) : SCCNodes(SCCNodes) {}
555 Action captured(
const Use *U, UseCaptureInfo UseCI)
override {
556 if (updateCaptureInfo(U, UseCI.
UseCC)) {
565 return ContinueIgnoringReturn;
576 CI |= CaptureInfo(CC);
581 if (!
F || !
F->hasExactDefinition() || !SCCNodes.count(
F)) {
582 CI |= CaptureInfo(CC);
596 CI |= CaptureInfo(CC);
600 if (UseIndex >=
F->arg_size()) {
601 assert(
F->isVarArg() &&
"More params than args in non-varargs call");
602 CI |= CaptureInfo(CC);
608 Uses.push_back(&*std::next(
F->arg_begin(), UseIndex));
618 const SCCNodeSet &SCCNodes;
626 std::optional<int64_t> Offset;
633struct ArgumentAccessInfo {
634 enum class AccessType : uint8_t {
Write, WriteWithSideEffect,
Read,
Unknown };
635 AccessType ArgAccessType;
636 ConstantRangeList AccessRanges;
640struct UsesPerBlockInfo {
641 SmallDenseMap<Instruction *, ArgumentAccessInfo, 4> Insts;
642 bool HasWrites =
false;
643 bool HasUnknownAccess =
false;
647struct ArgumentUsesSummary {
648 bool HasAnyWrite =
false;
649 bool HasWriteOutsideEntryBB =
false;
650 SmallDenseMap<const BasicBlock *, UsesPerBlockInfo, 16> UsesPerBlock;
653ArgumentAccessInfo getArgumentAccessInfo(
const Instruction *
I,
654 const ArgumentUse &ArgUse,
656 auto GetTypeAccessRange =
658 std::optional<int64_t>
Offset) -> std::optional<ConstantRange> {
672 auto GetConstantIntRange =
674 std::optional<int64_t>
Offset) -> std::optional<ConstantRange> {
676 if (ConstantLength &&
Offset) {
677 int64_t
Len = ConstantLength->getSExtValue();
695 if (
SI->isSimple() && &
SI->getOperandUse(1) == ArgUse.U) {
700 if (
auto TypeAccessRange =
701 GetTypeAccessRange(
SI->getAccessType(), ArgUse.Offset))
702 AccessRanges.
insert(*TypeAccessRange);
703 return {ArgumentAccessInfo::AccessType::Write, std::move(AccessRanges)};
706 if (LI->isSimple()) {
707 assert(&LI->getOperandUse(0) == ArgUse.U);
711 if (
auto TypeAccessRange =
712 GetTypeAccessRange(LI->getAccessType(), ArgUse.Offset))
713 return {ArgumentAccessInfo::AccessType::Read, {*TypeAccessRange}};
716 if (!MemSet->isVolatile()) {
718 if (
auto AccessRange =
719 GetConstantIntRange(MemSet->getLength(), ArgUse.Offset))
720 AccessRanges.
insert(*AccessRange);
721 return {ArgumentAccessInfo::AccessType::Write, AccessRanges};
724 if (!MTI->isVolatile()) {
725 if (&MTI->getOperandUse(0) == ArgUse.U) {
727 if (
auto AccessRange =
728 GetConstantIntRange(MTI->getLength(), ArgUse.Offset))
729 AccessRanges.
insert(*AccessRange);
730 return {ArgumentAccessInfo::AccessType::Write, AccessRanges};
731 }
else if (&MTI->getOperandUse(1) == ArgUse.U) {
732 if (
auto AccessRange =
733 GetConstantIntRange(MTI->getLength(), ArgUse.Offset))
734 return {ArgumentAccessInfo::AccessType::Read, {*AccessRange}};
741 bool IsInitialize = CB->
paramHasAttr(ArgNo, Attribute::Initializes);
742 if (IsInitialize && ArgUse.Offset) {
746 ? ArgumentAccessInfo::AccessType::Write
747 : ArgumentAccessInfo::AccessType::WriteWithSideEffect;
753 CR.getUpper() + *ArgUse.Offset));
754 return {
Access, AccessRanges};
759 return {ArgumentAccessInfo::AccessType::Unknown, {}};
764 auto &
DL =
F.getParent()->getDataLayout();
766 DL.getIndexSizeInBits(
A.getType()->getPointerAddressSpace());
767 ArgumentUsesSummary
Result;
771 for (
Use &U :
A.uses())
777 auto *BB =
I->getParent();
778 auto &BBInfo =
Result.UsesPerBlock[BB];
779 auto [It,
Inserted] = BBInfo.Insts.try_emplace(
I);
780 auto &IInfo = It->second;
785 IInfo = {ArgumentAccessInfo::AccessType::Unknown, {}};
786 BBInfo.HasUnknownAccess =
true;
790 IInfo = std::move(Info);
791 BBInfo.HasUnknownAccess |=
792 IInfo.ArgAccessType == ArgumentAccessInfo::AccessType::Unknown;
794 (IInfo.ArgAccessType == ArgumentAccessInfo::AccessType::Write ||
795 IInfo.ArgAccessType ==
796 ArgumentAccessInfo::AccessType::WriteWithSideEffect) &&
797 !IInfo.AccessRanges.empty();
798 BBInfo.HasWrites |= InfoHasWrites;
799 return InfoHasWrites;
804 while (!Worklist.
empty()) {
806 User *U = ArgUse.U->getUser();
810 std::optional<int64_t> NewOffset = std::nullopt;
814 NewOffset = *ArgUse.Offset +
Offset.getSExtValue();
816 for (
Use &U :
GEP->uses())
822 bool HasWrite = UpdateUseInfo(
I, getArgumentAccessInfo(
I, ArgUse,
DL));
824 Result.HasAnyWrite |= HasWrite;
826 if (HasWrite &&
I->getParent() != &EntryBB)
827 Result.HasWriteOutsideEntryBB =
true;
866 if (
A->hasInAllocaAttr() ||
A->hasPreallocatedAttr())
870 bool IsWrite =
false;
872 for (
Use &U :
A->uses()) {
877 while (!Worklist.
empty()) {
878 if (IsWrite && IsRead)
885 switch (
I->getOpcode()) {
886 case Instruction::BitCast:
887 case Instruction::GetElementPtr:
888 case Instruction::PHI:
889 case Instruction::Select:
890 case Instruction::AddrSpaceCast:
892 for (
Use &UU :
I->uses())
893 if (Visited.
insert(&UU).second)
897 case Instruction::Call:
898 case Instruction::Invoke: {
917 if (Visited.
insert(&UU).second)
927 if (!
I->getType()->isVoidTy())
928 for (
Use &UU :
I->uses())
929 if (Visited.
insert(&UU).second)
939 SCCNodes.
count(
F->getArg(UseIndex)))
960 case Instruction::Load:
969 case Instruction::Store:
982 case Instruction::ICmp:
983 case Instruction::Ret:
991 if (IsWrite && IsRead)
994 return Attribute::ReadOnly;
996 return Attribute::WriteOnly;
998 return Attribute::ReadNone;
1009 if (!
F->hasExactDefinition())
1012 if (
F->getReturnType()->isVoidTy())
1016 if (
F->getAttributes().hasAttrSomewhere(Attribute::Returned))
1019 auto FindRetArg = [&]() ->
Argument * {
1027 if (!RetVal || RetVal->getType() !=
F->getReturnType())
1032 else if (RetArg != RetVal)
1039 if (
Argument *RetArg = FindRetArg()) {
1040 RetArg->addAttr(Attribute::Returned);
1068 for (
auto &CSArg : CalledFunc->args()) {
1069 unsigned ArgNo = CSArg.getArgNo();
1074 if (CSArg.hasNonNullAttr(
false)) {
1078 if (!FArg->hasNonNullAttr()) {
1079 FArg->addAttr(Attribute::NonNull);
1087 if ((CSNoFPClass | ArgNoFPClass) != ArgNoFPClass) {
1089 FArg->getContext(), CSNoFPClass | ArgNoFPClass));
1104 assert((R == Attribute::ReadOnly || R == Attribute::ReadNone ||
1105 R == Attribute::WriteOnly)
1106 &&
"Must be an access attribute.");
1107 assert(
A &&
"Argument must not be null.");
1110 if (
A->hasAttribute(R))
1115 A->removeAttr(Attribute::WriteOnly);
1116 A->removeAttr(Attribute::ReadOnly);
1117 A->removeAttr(Attribute::ReadNone);
1119 if (R == Attribute::ReadNone || R == Attribute::ReadOnly)
1120 A->removeAttr(Attribute::Writable);
1122 if (R == Attribute::ReadOnly)
1124 else if (R == Attribute::WriteOnly)
1132 auto ArgumentUses = collectArgumentUsesPerBlock(
A,
F);
1134 if (!ArgumentUses.HasAnyWrite)
1137 auto &UsesPerBlock = ArgumentUses.UsesPerBlock;
1146 auto UPB = UsesPerBlock.find(BB);
1153 if (UPB == UsesPerBlock.end() || !UPB->second.HasUnknownAccess) {
1154 bool HasAddedSuccessor =
false;
1156 if (
auto SuccI = Initialized.
find(Succ); SuccI != Initialized.
end()) {
1157 if (HasAddedSuccessor) {
1160 CRL = SuccI->second;
1161 HasAddedSuccessor =
true;
1170 if (UPB != UsesPerBlock.end()) {
1174 sort(Insts, [](std::pair<Instruction *, ArgumentAccessInfo> &
LHS,
1175 std::pair<Instruction *, ArgumentAccessInfo> &
RHS) {
1176 return LHS.first->comesBefore(
RHS.first);
1181 for (
auto &[
_, Info] :
reverse(Insts)) {
1182 if (Info.ArgAccessType == ArgumentAccessInfo::AccessType::Unknown ||
1183 Info.ArgAccessType ==
1184 ArgumentAccessInfo::AccessType::WriteWithSideEffect)
1186 if (!Info.AccessRanges.empty()) {
1187 if (Info.ArgAccessType == ArgumentAccessInfo::AccessType::Write ||
1188 Info.ArgAccessType ==
1189 ArgumentAccessInfo::AccessType::WriteWithSideEffect) {
1192 assert(Info.ArgAccessType == ArgumentAccessInfo::AccessType::Read);
1193 for (
const auto &ReadRange : Info.AccessRanges)
1205 bool OnlyScanEntryBlock = !ArgumentUses.HasWriteOutsideEntryBB;
1206 if (!OnlyScanEntryBlock)
1207 if (
auto EntryUPB = UsesPerBlock.find(&EntryBB);
1208 EntryUPB != UsesPerBlock.end())
1209 OnlyScanEntryBlock = EntryUPB->second.HasUnknownAccess;
1210 if (OnlyScanEntryBlock) {
1211 EntryCRL = VisitBlock(&EntryBB);
1212 if (EntryCRL.
empty())
1223 Initialized[BB] = CRL;
1226 auto EntryCRLI = Initialized.
find(&EntryBB);
1227 if (EntryCRLI == Initialized.
end())
1230 EntryCRL = EntryCRLI->second;
1234 "should have bailed already if EntryCRL is empty");
1236 if (
A.hasAttribute(Attribute::Initializes)) {
1238 A.getAttribute(Attribute::Initializes).getValueAsConstantRangeList();
1239 if (PreviousCRL == EntryCRL)
1241 EntryCRL = EntryCRL.
unionWith(PreviousCRL);
1253 bool SkipInitializes) {
1256 auto DetermineAccessAttrsForSingleton = [](
Argument *
A) {
1271 if (!
F->hasExactDefinition())
1279 if (
F->onlyReadsMemory() &&
F->doesNotThrow() &&
F->willReturn() &&
1280 F->getReturnType()->isVoidTy()) {
1282 if (
A.getType()->isPointerTy() && !
A.hasNoCaptureAttr()) {
1293 if (!
A.getType()->isPointerTy())
1295 bool HasNonLocalUses =
false;
1296 CaptureInfo OrigCI =
A.getAttributes().getCaptureInfo();
1298 ArgumentUsesTracker Tracker(SCCNodes);
1301 if (NewCI != OrigCI) {
1302 if (Tracker.Uses.empty()) {
1311 ArgumentGraphNode *
Node = AG[&
A];
1314 Node->Uses.push_back(AG[
Use]);
1316 HasNonLocalUses =
true;
1322 if (!HasNonLocalUses && !
A.onlyReadsMemory()) {
1327 if (DetermineAccessAttrsForSingleton(&
A))
1330 if (!SkipInitializes && !
A.onlyReadsMemory()) {
1345 const std::vector<ArgumentGraphNode *> &ArgumentSCC = *
I;
1346 if (ArgumentSCC.size() == 1) {
1347 if (!ArgumentSCC[0]->Definition)
1351 if (ArgumentSCC[0]->
Uses.size() == 1 &&
1352 ArgumentSCC[0]->Uses[0] == ArgumentSCC[0]) {
1353 Argument *
A = ArgumentSCC[0]->Definition;
1354 CaptureInfo OrigCI =
A->getAttributes().getCaptureInfo();
1356 if (NewCI != OrigCI) {
1363 if (DetermineAccessAttrsForSingleton(
A))
1372 for (ArgumentGraphNode *
I : ArgumentSCC) {
1373 ArgumentSCCNodes.
insert(
I->Definition);
1380 for (ArgumentGraphNode *
N : ArgumentSCC) {
1381 for (ArgumentGraphNode *
Use :
N->Uses) {
1383 if (ArgumentSCCNodes.
count(
A))
1394 for (ArgumentGraphNode *
N : ArgumentSCC) {
1396 CaptureInfo OrigCI =
A->getAttributes().getCaptureInfo();
1398 if (NewCI != OrigCI) {
1409 for (ArgumentGraphNode *
N : ArgumentSCC) {
1410 if (DetermineAccessAttrsForSingleton(
N->Definition))
1411 Changed.insert(
N->Definition->getParent());
1430 if (
A == Attribute::ReadNone)
1432 if (
B == Attribute::ReadNone)
1438 for (ArgumentGraphNode *
N : ArgumentSCC) {
1441 AccessAttr = meetAccessAttr(AccessAttr, K);
1447 for (ArgumentGraphNode *
N : ArgumentSCC) {
1464 FlowsToReturn.
insert(Ret->getReturnValue());
1466 for (
unsigned i = 0; i != FlowsToReturn.
size(); ++i) {
1467 Value *RetVal = FlowsToReturn[i];
1480 switch (RVI->getOpcode()) {
1482 case Instruction::BitCast:
1483 case Instruction::GetElementPtr:
1484 case Instruction::AddrSpaceCast:
1485 FlowsToReturn.
insert(RVI->getOperand(0));
1487 case Instruction::Select: {
1489 FlowsToReturn.
insert(
SI->getTrueValue());
1490 FlowsToReturn.
insert(
SI->getFalseValue());
1493 case Instruction::PHI: {
1500 case Instruction::Alloca:
1502 case Instruction::Call:
1503 case Instruction::Invoke: {
1529 if (
F->returnDoesNotAlias())
1535 if (!
F->hasExactDefinition())
1540 if (!
F->getReturnType()->isPointerTy())
1548 if (
F->returnDoesNotAlias() ||
1549 !
F->getReturnType()->isPointerTy())
1552 F->setReturnDoesNotAlias();
1566 bool &Speculative) {
1567 assert(
F->getReturnType()->isPointerTy() &&
1568 "nonnull only meaningful on pointer types");
1569 Speculative =
false;
1574 FlowsToReturn.
insert(Ret->getReturnValue());
1576 auto &
DL =
F->getDataLayout();
1578 for (
unsigned i = 0; i != FlowsToReturn.
size(); ++i) {
1579 Value *RetVal = FlowsToReturn[i];
1592 case Instruction::BitCast:
1593 case Instruction::AddrSpaceCast:
1596 case Instruction::GetElementPtr:
1602 case Instruction::Select: {
1604 FlowsToReturn.
insert(
SI->getTrueValue());
1605 FlowsToReturn.
insert(
SI->getFalseValue());
1608 case Instruction::PHI: {
1614 case Instruction::Call:
1615 case Instruction::Invoke: {
1620 if (Callee && SCCNodes.count(Callee)) {
1640 bool SCCReturnsNonNull =
true;
1646 if (
F->getAttributes().hasRetAttr(Attribute::NonNull))
1652 if (!
F->hasExactDefinition())
1657 if (!
F->getReturnType()->isPointerTy())
1660 bool Speculative =
false;
1666 <<
" as nonnull\n");
1667 F->addRetAttr(Attribute::NonNull);
1675 SCCReturnsNonNull =
false;
1678 if (SCCReturnsNonNull) {
1680 if (
F->getAttributes().hasRetAttr(Attribute::NonNull) ||
1681 !
F->getReturnType()->isPointerTy())
1684 LLVM_DEBUG(
dbgs() <<
"SCC marking " <<
F->getName() <<
" as nonnull\n");
1685 F->addRetAttr(Attribute::NonNull);
1699 AttributeList Attrs =
F->getAttributes();
1700 if (Attrs.hasRetAttr(Attribute::NoUndef))
1706 if (!
F->hasExactDefinition())
1712 if (
F->hasFnAttribute(Attribute::SanitizeMemory))
1715 if (
F->getReturnType()->isVoidTy())
1722 Value *RetVal = Ret->getReturnValue();
1729 if (Attrs.hasRetAttr(Attribute::NonNull) &&
1737 Attribute Attr = Attrs.getRetAttr(Attribute::Range);
1744 FPClassTest AttrFPClass = Attrs.getRetNoFPClass();
1745 if (AttrFPClass !=
fcNone) {
1753 F->addRetAttr(Attribute::NoUndef);
1768class AttributeInferer {
1771 struct InferenceDescriptor {
1777 std::function<bool(
const Function &)> SkipFunction;
1780 std::function<bool(Instruction &)> InstrBreaksAttribute;
1783 std::function<void(Function &)> SetAttribute;
1786 Attribute::AttrKind AKind;
1790 bool RequiresExactDefinition;
1792 InferenceDescriptor(Attribute::AttrKind AK,
1793 std::function<
bool(
const Function &)> SkipFunc,
1794 std::function<
bool(Instruction &)> InstrScan,
1795 std::function<
void(Function &)> SetAttr,
1797 : SkipFunction(SkipFunc), InstrBreaksAttribute(InstrScan),
1798 SetAttribute(SetAttr), AKind(AK),
1799 RequiresExactDefinition(ReqExactDef) {}
1806 void registerAttrInference(InferenceDescriptor AttrInference) {
1807 InferenceDescriptors.
push_back(AttrInference);
1810 void run(
const SCCNodeSet &SCCNodes, SmallPtrSet<Function *, 8> &
Changed);
1815void AttributeInferer::run(
const SCCNodeSet &SCCNodes,
1816 SmallPtrSet<Function *, 8> &
Changed) {
1821 for (Function *
F : SCCNodes) {
1824 if (InferInSCC.
empty())
1829 if (
ID.SkipFunction(*
F))
1834 return F->isDeclaration() ||
1835 (
ID.RequiresExactDefinition && !
F->hasExactDefinition());
1842 InferInSCC, std::back_inserter(InferInThisFunc),
1843 [
F](
const InferenceDescriptor &
ID) {
return !
ID.SkipFunction(*
F); });
1845 if (InferInThisFunc.empty())
1851 if (!
ID.InstrBreaksAttribute(
I))
1856 return D.AKind ==
ID.AKind;
1862 if (InferInThisFunc.empty())
1867 if (InferInSCC.
empty())
1870 for (Function *
F : SCCNodes)
1875 for (
auto &
ID : InferInSCC) {
1876 if (
ID.SkipFunction(*
F))
1879 ID.SetAttribute(*
F);
1883struct SCCNodesResult {
1884 SCCNodeSet SCCNodes;
1891 const SCCNodeSet &SCCNodes) {
1901 if (!
I.mayThrow(
true))
1904 if (
Function *Callee = CI->getCalledFunction()) {
1908 if (SCCNodes.contains(Callee))
1921 return I.maySynchronize();
1929 if (SCCNodes.contains(Callee))
1936 if (!
I.maySynchronize())
1943 if (SCCNodes.contains(Callee))
1954 AttributeInferer AI;
1961 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
1962 Attribute::Convergent,
1964 [](
const Function &
F) {
return !
F.isConvergent(); },
1970 LLVM_DEBUG(
dbgs() <<
"Removing convergent attr from fn " <<
F.getName()
1972 F.setNotConvergent();
1985 AttributeInferer AI;
1993 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
1994 Attribute::NoUnwind,
1996 [](
const Function &
F) {
return F.doesNotThrow(); },
2003 <<
"Adding nounwind attr to fn " <<
F.getName() <<
"\n");
2004 F.setDoesNotThrow();
2016 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
2019 [](
const Function &
F) {
return F.doesNotFreeMemory(); },
2026 <<
"Adding nofree attr to fn " <<
F.getName() <<
"\n");
2027 F.setDoesNotFreeMemory();
2032 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
2035 [](
const Function &
F) {
return F.hasNoSync(); },
2042 <<
"Adding nosync attr to fn " <<
F.getName() <<
"\n");
2060 bool AnyFunctionsAddressIsTaken =
true) {
2061 for (
const auto &BB :
F) {
2062 for (
const auto &
I : BB) {
2065 if (!Callee || Callee == &
F)
2068 if (Callee->doesNotRecurse())
2071 if (!AnyFunctionsAddressIsTaken ||
2072 (Callee->isDeclaration() &&
2073 Callee->hasFnAttribute(Attribute::NoCallback)))
2087 if (SCCNodes.size() != 1)
2091 if (!
F || !
F->hasExactDefinition() ||
F->doesNotRecurse())
2097 F->setDoesNotRecurse();
2107 if (!
F || !
F->hasExactDefinition() ||
F->hasFnAttribute(Attribute::Naked) ||
2112 F->setDoesNotReturn();
2120 ColdPaths[&
F.front()] =
false;
2124 while (!Jobs.
empty()) {
2135 ColdPaths[BB] =
true;
2152 auto [Iter, Inserted] = ColdPaths.
try_emplace(Succ,
false);
2168 if (!
F || !
F->hasExactDefinition() ||
F->hasFnAttribute(Attribute::Naked) ||
2169 F->hasFnAttribute(Attribute::Cold) ||
F->hasFnAttribute(Attribute::Hot))
2174 F->addFnAttr(Attribute::Cold);
2186 if (!
F.hasExactDefinition())
2190 if (
F.mustProgress() &&
F.onlyReadsMemory())
2194 if (
F.isDeclaration())
2201 if (!Backedges.
empty())
2207 return I.willReturn();
2227 if (!
F ||
F->hasOptNone() ||
F->hasFnAttribute(Attribute::Naked) ||
2228 F->isPresplitCoroutine()) {
2233 Res.SCCNodes.insert(
F);
2238template <
typename AARGetterT>
2241 bool ArgAttrsOnly) {
2245 if (Nodes.SCCNodes.empty())
2289 bool ArgAttrsOnly =
false;
2290 if (
C.size() == 1 && SkipNonRecursive) {
2293 ArgAttrsOnly =
true;
2307 Functions.push_back(&
N.getFunction());
2310 auto ChangedFunctions =
2312 if (ChangedFunctions.empty())
2326 for (
auto *U :
Changed->users()) {
2329 FAM.invalidate(*
Call->getFunction(), FuncPA);
2345 OS, MapClassName2PassName);
2346 if (SkipNonRecursive)
2347 OS <<
"<skip-non-recursive-function-attrs>";
2350template <
typename AARGetterT>
2354 Functions.push_back(
I->getFunction());
2361 if (
F.doesNotRecurse())
2367 assert(!
F.isDeclaration() &&
"Cannot deduce norecurse without a definition!");
2368 assert(
F.hasInternalLinkage() &&
2369 "Can only do top-down deduction for internal linkage functions!");
2379 for (
auto &U :
F.uses()) {
2382 !CB->
getParent()->getParent()->doesNotRecurse())
2385 F.setDoesNotRecurse();
2391 assert(!
F.isDeclaration() &&
"Cannot deduce nofpclass without a definition!");
2392 unsigned NumArgs =
F.arg_size();
2397 for (
User *U :
F.users()) {
2403 for (
unsigned I = 0;
I != NumArgs; ++
I) {
2408 ArgsNoFPClass[
I] &= ~Cst->classify();
2416 if (RetNoFPClass !=
fcNone) {
2417 FPClassTest OldAttr =
F.getAttributes().getRetNoFPClass();
2418 if (OldAttr != RetNoFPClass) {
2424 for (
unsigned I = 0;
I != NumArgs; ++
I) {
2426 if (ArgNoFPClass ==
fcNone)
2429 if (OldAttr == ArgNoFPClass)
2452 if (SCC.size() != 1)
2454 Function &
F = SCC.begin()->getFunction();
2455 if (!
F.isDeclaration() &&
F.hasInternalLinkage() && !
F.use_empty())
2488 bool AnyFunctionsAddressIsTaken =
false;
2490 if (
F.isDeclaration() ||
F.doesNotRecurse())
2492 if (!
F.hasLocalLinkage() ||
F.hasAddressTaken()) {
2493 AnyFunctionsAddressIsTaken =
true;
2518 if (!
F.hasExactDefinition() ||
F.doesNotRecurse())
2525 F.setDoesNotRecurse();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Expand Atomic instructions
This file contains the simple types necessary to represent the attributes associated with functions a...
This is the interface for LLVM's primary stateless and local alias analysis.
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")
This header provides classes for managing passes over SCCs of the call graph.
This file provides interfaces used to build and manipulate a call graph, which is a very useful tool ...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file defines the DenseMap class.
static bool runImpl(Function &F, const TargetLowering &TLI, const LibcallLoweringInfo &Libcalls, AssumptionCache *AC)
static SmallPtrSet< Function *, 8 > deriveAttrsInPostOrder(ArrayRef< Function * > Functions, AARGetterT &&AARGetter, bool ArgAttrsOnly)
static Attribute::AttrKind determinePointerAccessAttrs(Argument *A, const SmallPtrSet< Argument *, 8 > &SCCNodes)
Returns Attribute::None, Attribute::ReadOnly or Attribute::ReadNone.
static cl::opt< bool > DisableNoFreeInference("disable-nofree-inference", cl::Hidden, cl::desc("Stop inferring nofree attribute during function-attrs pass"))
static bool inferInitializes(Argument &A, Function &F)
static bool allPathsGoThroughCold(Function &F)
static bool addAccessAttr(Argument *A, Attribute::AttrKind R)
static FunctionSummary * calculatePrevailingSummary(ValueInfo VI, DenseMap< ValueInfo, FunctionSummary * > &CachedPrevailingSummary, function_ref< bool(GlobalValue::GUID, const GlobalValueSummary *)> IsPrevailing)
static void addMemoryAttrs(const SCCNodeSet &SCCNodes, AARGetterT &&AARGetter, SmallPtrSet< Function *, 8 > &Changed)
Deduce readonly/readnone/writeonly attributes for the SCC.
static bool addArgumentAttrsFromCallsites(Function &F)
If a callsite has arguments that are also arguments to the parent function, try to propagate attribut...
static void addCapturesStat(CaptureInfo CI)
static void addArgLocs(MemoryEffects &ME, const CallBase *Call, ModRefInfo ArgMR, AAResults &AAR)
static bool isFunctionMallocLike(Function *F, const SCCNodeSet &SCCNodes)
Tests whether a function is "malloc-like".
static void addColdAttrs(const SCCNodeSet &SCCNodes, SmallPtrSet< Function *, 8 > &Changed)
static bool mayHaveRecursiveCallee(Function &F, bool AnyFunctionsAddressIsTaken=true)
static void addNoReturnAttrs(const SCCNodeSet &SCCNodes, SmallPtrSet< Function *, 8 > &Changed)
static bool addNoFPClassAttrsTopDown(Function &F)
static cl::opt< bool > DisableNoUnwindInference("disable-nounwind-inference", cl::Hidden, cl::desc("Stop inferring nounwind attribute during function-attrs pass"))
static void addWillReturn(const SCCNodeSet &SCCNodes, SmallPtrSet< Function *, 8 > &Changed)
static void addNonNullAttrs(const SCCNodeSet &SCCNodes, SmallPtrSet< Function *, 8 > &Changed)
Deduce nonnull attributes for the SCC.
static std::pair< MemoryEffects, MemoryEffects > checkFunctionMemoryAccess(Function &F, bool ThisBody, AAResults &AAR, const SCCNodeSet &SCCNodes)
Returns the memory access attribute for function F using AAR for AA results, where SCCNodes is the cu...
static bool InstrBreaksNonThrowing(Instruction &I, const SCCNodeSet &SCCNodes)
Helper for NoUnwind inference predicate InstrBreaksAttribute.
static void inferAttrsFromFunctionBodies(const SCCNodeSet &SCCNodes, SmallPtrSet< Function *, 8 > &Changed)
Infer attributes from all functions in the SCC by scanning every instruction for compliance to the at...
static bool isReturnNonNull(Function *F, const SCCNodeSet &SCCNodes, bool &Speculative)
Tests whether this function is known to not return null.
static bool InstrBreaksNoSync(Instruction &I, const SCCNodeSet &SCCNodes)
static bool deduceFunctionAttributeInRPO(Module &M, LazyCallGraph &CG)
static bool InstrBreaksNoFree(Instruction &I, const SCCNodeSet &SCCNodes)
Helper for NoFree inference predicate InstrBreaksAttribute.
static cl::opt< bool > EnablePoisonArgAttrPropagation("enable-poison-arg-attr-prop", cl::init(true), cl::Hidden, cl::desc("Try to propagate nonnull and nofpclass argument attributes from " "callsites to caller functions."))
static void addNoAliasAttrs(const SCCNodeSet &SCCNodes, SmallPtrSet< Function *, 8 > &Changed)
Deduce noalias attributes for the SCC.
static bool addNoRecurseAttrsTopDown(Function &F)
static void addLocAccess(MemoryEffects &ME, const MemoryLocation &Loc, ModRefInfo MR, AAResults &AAR)
static void inferConvergent(const SCCNodeSet &SCCNodes, SmallPtrSet< Function *, 8 > &Changed)
Attempt to remove convergent function attribute when possible.
static cl::opt< bool > DisableThinLTOPropagation("disable-thinlto-funcattrs", cl::init(true), cl::Hidden, cl::desc("Don't propagate function-attrs in thinLTO"))
static SCCNodesResult createSCCNodeSet(ArrayRef< Function * > Functions)
static bool InstrBreaksNonConvergent(Instruction &I, const SCCNodeSet &SCCNodes)
Helper for non-Convergent inference predicate InstrBreaksAttribute.
static void addArgumentAttrs(const SCCNodeSet &SCCNodes, SmallPtrSet< Function *, 8 > &Changed, bool SkipInitializes)
Deduce nocapture attributes for the SCC.
static void addNoRecurseAttrs(const SCCNodeSet &SCCNodes, SmallPtrSet< Function *, 8 > &Changed)
static bool functionWillReturn(const Function &F)
static void addNoUndefAttrs(const SCCNodeSet &SCCNodes, SmallPtrSet< Function *, 8 > &Changed)
Deduce noundef attributes for the SCC.
static void addArgumentReturnedAttrs(const SCCNodeSet &SCCNodes, SmallPtrSet< Function *, 8 > &Changed)
Deduce returned attributes for the SCC.
Provides passes for computing function attributes based on interprocedural analyses.
This header defines various interfaces for pass management in LLVM.
This defines the Use class.
Implements a lazy call graph analysis and related passes for the new pass manager.
This file provides utility analysis objects describing memory locations.
ModuleSummaryIndex.h This file contains the declarations the classes that hold the module index and s...
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
Remove Loads Into Fake Uses
This builds on the llvm/ADT/GraphTraits.h file to find the strongly connected components (SCCs) of a ...
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
A manager for alias analyses.
LLVM_ABI ModRefInfo getModRefInfoMask(const MemoryLocation &Loc, bool IgnoreLocals=false)
Returns a bitmask that should be unconditionally applied to the ModRef info of a memory location.
LLVM_ABI MemoryEffects getMemoryEffects(const CallBase *Call)
Return the behavior of the given call site.
Class for arbitrary precision integers.
This templated class represents "all analyses that operate over <aparticular IR unit>" (e....
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),...
Functions, function parameters, and return types can have attributes to indicate how they should be t...
LLVM_ABI const ConstantRange & getRange() const
Returns the value of the range attribute.
static LLVM_ABI Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
LLVM_ABI ArrayRef< ConstantRange > getValueAsConstantRangeList() const
Return the attribute's value as a ConstantRange array.
static LLVM_ABI Attribute getWithNoFPClass(LLVMContext &Context, FPClassTest Mask)
AttrKind
This enumeration lists the attributes that can be associated with parameters, function results,...
@ None
No attributes have been set.
static LLVM_ABI Attribute getWithCaptureInfo(LLVMContext &Context, CaptureInfo CI)
bool isValid() const
Return true if the attribute is any kind of attribute.
LLVM Basic Block Representation.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Represents analyses that only rely on functions' control flow.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
LLVM_ABI FPClassTest getParamNoFPClass(unsigned i) const
Extract a test mask for disallowed floating-point value classes for the parameter.
LLVM_ABI FPClassTest getRetNoFPClass() const
Extract a test mask for disallowed floating-point value classes for the return value.
LLVM_ABI MemoryEffects getMemoryEffects() const
bool doesNotCapture(unsigned OpNo) const
Determine whether this data operand is not captured.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
bool doesNotAccessMemory(unsigned OpNo) const
bool hasFnAttr(Attribute::AttrKind Kind) const
Determine whether this call has the given attribute.
bool hasRetAttr(Attribute::AttrKind Kind) const
Determine whether the return value has the given attribute.
unsigned getDataOperandNo(Value::const_user_iterator UI) const
Given a value use iterator, return the data operand corresponding to it.
LLVM_ABI bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const
Determine whether the argument or parameter has the given attribute.
Attribute getParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) const
Get the attribute of a given kind from a given arg.
bool dataOperandHasImpliedAttr(unsigned i, Attribute::AttrKind Kind) const
Return true if the data operand at index i has the attribute A.
bool isByValArgument(unsigned ArgNo) const
Determine whether this argument is passed by value.
bool onlyWritesMemory(unsigned OpNo) const
bool isCallee(Value::const_user_iterator UI) const
Determine whether the passed iterator points to the callee operand's Use.
LLVM_ABI CaptureInfo getCaptureInfo(unsigned OpNo) const
Return which pointer components this operand may capture.
bool onlyReadsMemory(unsigned OpNo) const
Value * getArgOperand(unsigned i) const
bool isConvergent() const
Determine if the invoke is convergent.
unsigned getArgOperandNo(const Use *U) const
Given a use for a arg operand, get the arg operand number that corresponds to it.
unsigned arg_size() const
bool isArgOperand(const Use *U) const
bool hasOperandBundles() const
Return true if this User has any operand bundles.
A node in the call graph for a module.
CallGraphSCC - This is a single SCC that a CallGraphSCCPass is run on.
Represents which components of the pointer may be captured in which location.
static CaptureInfo none()
Create CaptureInfo that does not capture any components of the pointer.
static CaptureInfo retOnly(CaptureComponents RetComponents=CaptureComponents::All)
Create CaptureInfo that may only capture via the return value.
static CaptureInfo all()
Create CaptureInfo that may capture all components of the pointer.
This class represents a list of constant ranges.
LLVM_ABI void subtract(const ConstantRange &SubRange)
LLVM_ABI void insert(const ConstantRange &NewRange)
Insert a new range to Ranges and keep the list ordered.
bool empty() const
Return true if this list contains no members.
ArrayRef< ConstantRange > rangesRef() const
LLVM_ABI ConstantRangeList intersectWith(const ConstantRangeList &CRL) const
Return the range list that results from the intersection of this ConstantRangeList with another Const...
LLVM_ABI ConstantRangeList unionWith(const ConstantRangeList &CRL) const
Return the range list that results from the union of this ConstantRangeList with another ConstantRang...
This class represents a range of values.
LLVM_ABI bool contains(const APInt &Val) const
Return true if the specified value is in the set.
This is an important base class in LLVM.
A parsed version of the target data layout string in and methods for querying it.
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
A proxy from a FunctionAnalysisManager to an SCC.
Function summary information to aid decisions and implementation of importing.
ArrayRef< EdgeTy > calls() const
Return the list of <CalleeValueInfo, CalleeInfo> pairs.
FFlags fflags() const
Get function summary flags.
Function and variable summary information to aid decisions and implementation of importing.
static bool isWeakAnyLinkage(LinkageTypes Linkage)
static bool isLinkOnceAnyLinkage(LinkageTypes Linkage)
static bool isLocalLinkage(LinkageTypes Linkage)
static bool isWeakODRLinkage(LinkageTypes Linkage)
uint64_t GUID
Declare a type to represent a global unique identifier for a global value.
static bool isAvailableExternallyLinkage(LinkageTypes Linkage)
static bool isExternalLinkage(LinkageTypes Linkage)
static bool isLinkOnceODRLinkage(LinkageTypes Linkage)
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
This is an important class for using LLVM in a threaded context.
An analysis pass which computes the call graph for a module.
A node in the call graph.
A RefSCC of the call graph.
An SCC of the call graph.
A lazily constructed view of the call graph of a module.
LLVM_ABI void buildRefSCCs()
iterator_range< postorder_ref_scc_iterator > postorder_ref_sccs()
MemoryEffectsBase getWithoutLoc(Location Loc) const
Get new MemoryEffectsBase with NoModRef on the given Loc.
bool doesNotAccessMemory() const
Whether this function accesses no memory.
static MemoryEffectsBase argMemOnly(ModRefInfo MR=ModRefInfo::ModRef)
ModRefInfo getModRef(Location Loc) const
Get ModRefInfo for the given Location.
static MemoryEffectsBase none()
static MemoryEffectsBase unknown()
Representation for a specific memory location.
static MemoryLocation getBeforeOrAfter(const Value *Ptr, const AAMDNodes &AATags=AAMDNodes())
Return a location that may access any location before or after Ptr, while remaining within the underl...
static LLVM_ABI std::optional< MemoryLocation > getOrNone(const Instruction *Inst)
Class to hold module path string table and global value map, and encapsulate methods for operating on...
A Module instance is used to store all the information related to an LLVM module.
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
op_range incoming_values()
Value * getIncomingValue(unsigned i) const
Return incoming value number x.
unsigned getNumIncomingValues() const
Return the number of incoming edges.
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 & preserveSet()
Mark an analysis set as preserved.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
Return a value (possibly void), from a function.
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
This class represents the LLVM 'select' instruction.
size_type size() const
Determine the number of elements in the SetVector.
void insert_range(Range &&R)
bool insert(const value_type &X)
Insert a new element into the SetVector.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
A SetVector that performs no allocations if smaller than a certain size.
typename SuperClass::iterator iterator
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
The instances of the Type class are immutable: once they are created, they are never changed.
A Use represents the edge between a Value definition and its users.
Value * getOperand(unsigned i) const
LLVM Value Representation.
LLVM_ABI Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
iterator_range< use_iterator > uses()
constexpr ScalarTy getFixedValue() const
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
This class implements an extremely fast bulk output stream that can only output to a stream.
Enumerate the SCCs of a directed graph in reverse topological order of the SCC DAG.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
bool match(Val *V, const Pattern &P)
ap_match< APFloat > m_APFloat(const APFloat *&Res)
Match a ConstantFP or splatted ConstantVector, binding the specified pointer to the contained APFloat...
initializer< Ty > init(const Ty &Val)
DXILDebugInfoMap run(Module &M)
constexpr uint64_t PointerSize
aarch64 pointer size.
NodeAddr< UseNode * > Use
NodeAddr< NodeBase * > Node
LLVM_ABI iterator begin() const
This is an optimization pass for GlobalISel generic memory operations.
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
LLVM_ABI KnownFPClass computeKnownFPClass(const Value *V, const APInt &DemandedElts, FPClassTest InterestedClasses, const SimplifyQuery &SQ, unsigned Depth=0)
Determine which floating-point classes are valid for V, and return them in KnownFPClass bit sets.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI MemoryEffects computeFunctionBodyMemoryAccess(Function &F, AAResults &AAR)
Returns the memory access properties of this copy of the function.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto successors(const MachineBasicBlock *BB)
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
scc_iterator< T > scc_begin(const T &G)
Construct the begin iterator for a deduced graph type T.
LLVM_ABI bool isIntrinsicReturningPointerAliasingArgumentWithoutCapturing(const CallBase *Call, bool MustPreserveOffset)
{launder,strip}.invariant.group returns pointer that aliases its argument, and it only captures point...
MemoryEffectsBase< IRMemLocation > MemoryEffects
Summary of how a function affects memory in the program.
LLVM_ABI bool thinLTOPropagateFunctionAttrs(ModuleSummaryIndex &Index, function_ref< bool(GlobalValue::GUID, const GlobalValueSummary *)> isPrevailing)
Propagate function attributes for function summaries along the index's callgraph during thinlink.
OutputIt copy_if(R &&Range, OutputIt Out, UnaryPredicate P)
Provide wrappers to std::copy_if which take ranges instead of having to pass begin/end explicitly.
AnalysisManager< LazyCallGraph::SCC, LazyCallGraph & > CGSCCAnalysisManager
The CGSCC analysis manager.
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)
bool isModSet(const ModRefInfo MRI)
void sort(IteratorTy Start, IteratorTy End)
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
CaptureComponents
Components of the pointer that may be captured.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
auto post_order(const T &G)
Post-order traversal of a graph.
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 bool isKnownNonZero(const Value *V, const SimplifyQuery &Q, unsigned Depth=0)
Return true if the given value is known to be non-zero when defined.
ModRefInfo
Flags indicating whether a memory access modifies or references memory.
@ ModRef
The access may reference and may modify the value stored in memory.
@ NoModRef
The access neither references nor modifies the value stored in memory.
@ ArgMem
Access to memory via argument pointers.
LLVM_ABI const Value * getUnderlyingObjectAggressive(const Value *V)
Like getUnderlyingObject(), but will try harder to find a single underlying object.
LLVM_ABI bool PointerMayBeCaptured(const Value *V, bool ReturnCaptures, unsigned MaxUsesToExplore=0)
PointerMayBeCaptured - Return true if this pointer value may be captured by the enclosing function (w...
LLVM_ABI bool isGuaranteedNotToBeUndefOrPoison(const Value *V, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, unsigned Depth=0)
Return true if this function can prove that V does not have undef bits and is never poison.
LLVM_ABI bool isGuaranteedToTransferExecutionToSuccessor(const Instruction *I)
Return true if this function can prove that the instruction I will always transfer execution to one o...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
LLVM_ABI bool inferAttributesFromOthers(Function &F)
If we can infer one attribute from another on the declaration of a function, explicitly materialize t...
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
bool capturesAll(CaptureComponents CC)
bool capturesNothing(CaptureComponents CC)
bool isNoModRef(const ModRefInfo MRI)
LLVM_ABI void FindFunctionBackedges(const Function &F, SmallVectorImpl< std::pair< const BasicBlock *, const BasicBlock * > > &Result)
Analyze the specified function to find all of the loop backedges in the function and return them.
LLVM_ABI bool isIdentifiedObject(const Value *V)
Return true if this pointer refers to a distinct and identifiable object.
bool capturesAnyProvenance(CaptureComponents CC)
bool isRefSet(const ModRefInfo MRI)
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
LLVM_ABI bool canReturn(const Function &F)
Return true if there is at least a path through which F can return, false if there is no such path.
LLVM_ABI ConstantRange computeConstantRange(const Value *V, bool ForSigned, const SimplifyQuery &SQ, unsigned Depth=0)
Determine the possible constant range of an integer or vector of integer value.
This struct is a compact representation of a valid (non-zero power of two) alignment.
Support structure for SCC passes to communicate updates the call graph back to the CGSCC pass manager...
This callback is used in conjunction with PointerMayBeCaptured.
Flags specific to function summaries.
SmallVectorImpl< ArgumentGraphNode * >::iterator ChildIteratorType
static ChildIteratorType child_begin(NodeRef N)
static ChildIteratorType child_end(NodeRef N)
ArgumentGraphNode * NodeRef
static NodeRef getEntryNode(NodeRef A)
static ChildIteratorType nodes_end(ArgumentGraph *AG)
static NodeRef getEntryNode(ArgumentGraph *AG)
static ChildIteratorType nodes_begin(ArgumentGraph *AG)
typename ArgumentGraph *::UnknownGraphTypeError NodeRef
bool isKnownNever(FPClassTest Mask) const
Return true if it's known this can never be one of the mask entries.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
A CRTP mix-in to automatically provide informational APIs needed for passes.
LLVM_ABI PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR)
LLVM_ABI void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
CaptureComponents UseCC
Components captured by this use.
Struct that holds a reference to a particular GUID in a global value summary.