72#define DEBUG_TYPE "function-attrs"
74STATISTIC(NumMemoryAttr,
"Number of functions with improved memory attribute");
75STATISTIC(NumCapturesNone,
"Number of arguments marked captures(none)");
76STATISTIC(NumCapturesPartial,
"Number of arguments marked with captures "
77 "attribute other than captures(none)");
78STATISTIC(NumReturned,
"Number of arguments marked returned");
79STATISTIC(NumReadNoneArg,
"Number of arguments marked readnone");
80STATISTIC(NumReadOnlyArg,
"Number of arguments marked readonly");
81STATISTIC(NumWriteOnlyArg,
"Number of arguments marked writeonly");
82STATISTIC(NumNoAlias,
"Number of function returns marked noalias");
83STATISTIC(NumNonNullReturn,
"Number of function returns marked nonnull");
84STATISTIC(NumNoUndefReturn,
"Number of function returns marked noundef");
85STATISTIC(NumNoRecurse,
"Number of functions marked as norecurse");
86STATISTIC(NumNoUnwind,
"Number of functions marked as nounwind");
87STATISTIC(NumNoFree,
"Number of functions marked as nofree");
88STATISTIC(NumWillReturn,
"Number of functions marked as willreturn");
89STATISTIC(NumNoSync,
"Number of functions marked as nosync");
90STATISTIC(NumCold,
"Number of functions marked as cold");
93 "Number of functions marked as norecurse during thinlink");
95 "Number of functions marked as nounwind during thinlink");
99 cl::desc(
"Try to propagate nonnull and nofpclass argument attributes from "
100 "callsites to caller functions."));
104 cl::desc(
"Stop inferring nounwind attribute during function-attrs pass"));
108 cl::desc(
"Stop inferring nofree attribute during function-attrs pass"));
112 cl::desc(
"Don't propagate function-attrs in thinLTO"));
118 ++NumCapturesPartial;
152 if (!Arg->getType()->isPtrOrPtrVectorTy())
173static std::pair<MemoryEffects, MemoryEffects>
175 const SCCNodeSet &SCCNodes) {
189 if (
F.getAttributes().hasAttrSomewhere(Attribute::InAlloca) ||
190 F.getAttributes().hasAttrSomewhere(Attribute::Preallocated))
203 if (!
Call->hasOperandBundles() &&
Call->getCalledFunction() &&
204 SCCNodes.count(
Call->getCalledFunction())) {
244 if (
I.mayWriteToMemory())
246 if (
I.mayReadFromMemory())
266 return {OrigME & ME, RecursiveArgME};
275template <
typename AARGetterT>
286 auto [FnME, FnRecursiveArgME] =
289 RecursiveArgME |= FnRecursiveArgME;
303 if (NewME != OldME) {
305 F->setMemoryEffects(NewME);
309 A.removeAttr(Attribute::Writable);
323 auto [It, Inserted] = CachedPrevailingSummary.
try_emplace(VI);
370 for (
const auto &GVS : VI.getSummaryList()) {
376 if (!FS || FS->fflags().HasUnknownCall)
379 const auto &
Linkage = GVS->linkage();
384 <<
"ThinLTO FunctionAttrs: Multiple Local Linkage, bailing on "
386 << VI.name() <<
" from " << FS->modulePath() <<
". Previous module "
387 <<
Local->modulePath() <<
"\n");
392 assert(IsPrevailing(VI.getGUID(), GVS.get()) || GVS->wasPromoted());
399 if (IsPrevailing(VI.getGUID(), GVS.get())) {
409 auto &CPS = CachedPrevailingSummary[VI];
413 }
else if (Prevailing) {
433 auto PropagateAttributes = [&](std::vector<ValueInfo> &SCCNodes) {
436 InferredFlags.
NoRecurse = (SCCNodes.size() == 1);
439 for (
auto &V : SCCNodes) {
450 for (
const auto &Callee : CallerSummary->
calls()) {
452 Callee.first, CachedPrevailingSummary, IsPrevailing);
470 for (
auto &V : SCCNodes) {
472 LLVM_DEBUG(
dbgs() <<
"ThinLTO FunctionAttrs: Propagated NoRecurse to "
473 << V.name() <<
"\n");
474 ++NumThinLinkNoRecurse;
478 LLVM_DEBUG(
dbgs() <<
"ThinLTO FunctionAttrs: Propagated NoUnwind to "
479 << V.name() <<
"\n");
480 ++NumThinLinkNoUnwind;
483 for (
const auto &S : V.getSummaryList()) {
499 std::vector<ValueInfo> Nodes(*
I);
500 PropagateAttributes(Nodes);
510struct ArgumentGraphNode {
521 using ArgumentMapTy = std::map<Argument *, ArgumentGraphNode>;
523 ArgumentMapTy ArgumentMap;
531 ArgumentGraphNode SyntheticRoot;
534 ArgumentGraph() { SyntheticRoot.Definition =
nullptr; }
538 iterator
begin() {
return SyntheticRoot.Uses.begin(); }
539 iterator
end() {
return SyntheticRoot.Uses.end(); }
540 ArgumentGraphNode *getEntryNode() {
return &SyntheticRoot; }
542 ArgumentGraphNode *operator[](Argument *
A) {
543 ArgumentGraphNode &
Node = ArgumentMap[
A];
545 SyntheticRoot.Uses.push_back(&Node);
554 ArgumentUsesTracker(
const SCCNodeSet &SCCNodes) : SCCNodes(SCCNodes) {}
558 Action captured(
const Use *U, UseCaptureInfo UseCI)
override {
559 if (updateCaptureInfo(U, UseCI.
UseCC)) {
568 return ContinueIgnoringReturn;
579 CI |= CaptureInfo(CC);
584 if (!
F || !
F->hasExactDefinition() || !SCCNodes.count(
F)) {
585 CI |= CaptureInfo(CC);
599 CI |= CaptureInfo(CC);
603 if (UseIndex >=
F->arg_size()) {
604 assert(
F->isVarArg() &&
"More params than args in non-varargs call");
605 CI |= CaptureInfo(CC);
611 Uses.push_back(&*std::next(
F->arg_begin(), UseIndex));
621 const SCCNodeSet &SCCNodes;
629 std::optional<int64_t> Offset;
636struct ArgumentAccessInfo {
637 enum class AccessType : uint8_t {
Write, WriteWithSideEffect,
Read,
Unknown };
638 AccessType ArgAccessType;
639 ConstantRangeList AccessRanges;
643struct UsesPerBlockInfo {
644 SmallDenseMap<Instruction *, ArgumentAccessInfo, 4> Insts;
645 bool HasWrites =
false;
646 bool HasUnknownAccess =
false;
650struct ArgumentUsesSummary {
651 bool HasAnyWrite =
false;
652 bool HasWriteOutsideEntryBB =
false;
653 SmallDenseMap<const BasicBlock *, UsesPerBlockInfo, 16> UsesPerBlock;
656ArgumentAccessInfo getArgumentAccessInfo(
const Instruction *
I,
657 const ArgumentUse &ArgUse,
659 auto GetTypeAccessRange =
661 std::optional<int64_t>
Offset) -> std::optional<ConstantRange> {
675 auto GetConstantIntRange =
677 std::optional<int64_t>
Offset) -> std::optional<ConstantRange> {
679 if (ConstantLength &&
Offset) {
680 int64_t
Len = ConstantLength->getSExtValue();
698 if (
SI->isSimple() && &
SI->getOperandUse(1) == ArgUse.U) {
703 if (
auto TypeAccessRange =
704 GetTypeAccessRange(
SI->getAccessType(), ArgUse.Offset))
705 AccessRanges.
insert(*TypeAccessRange);
706 return {ArgumentAccessInfo::AccessType::Write, std::move(AccessRanges)};
709 if (LI->isSimple()) {
710 assert(&LI->getOperandUse(0) == ArgUse.U);
714 if (
auto TypeAccessRange =
715 GetTypeAccessRange(LI->getAccessType(), ArgUse.Offset))
716 return {ArgumentAccessInfo::AccessType::Read, {*TypeAccessRange}};
719 if (!MemSet->isVolatile()) {
721 if (
auto AccessRange =
722 GetConstantIntRange(MemSet->getLength(), ArgUse.Offset))
723 AccessRanges.
insert(*AccessRange);
724 return {ArgumentAccessInfo::AccessType::Write, AccessRanges};
727 if (!MTI->isVolatile()) {
728 if (&MTI->getOperandUse(0) == ArgUse.U) {
730 if (
auto AccessRange =
731 GetConstantIntRange(MTI->getLength(), ArgUse.Offset))
732 AccessRanges.
insert(*AccessRange);
733 return {ArgumentAccessInfo::AccessType::Write, AccessRanges};
734 }
else if (&MTI->getOperandUse(1) == ArgUse.U) {
735 if (
auto AccessRange =
736 GetConstantIntRange(MTI->getLength(), ArgUse.Offset))
737 return {ArgumentAccessInfo::AccessType::Read, {*AccessRange}};
744 bool IsInitialize = CB->
paramHasAttr(ArgNo, Attribute::Initializes);
745 if (IsInitialize && ArgUse.Offset) {
749 ? ArgumentAccessInfo::AccessType::Write
750 : ArgumentAccessInfo::AccessType::WriteWithSideEffect;
756 CR.getUpper() + *ArgUse.Offset));
757 return {
Access, AccessRanges};
762 return {ArgumentAccessInfo::AccessType::Unknown, {}};
767 auto &
DL =
F.getParent()->getDataLayout();
769 DL.getIndexSizeInBits(
A.getType()->getPointerAddressSpace());
770 ArgumentUsesSummary
Result;
774 for (
Use &U :
A.uses())
780 auto *BB =
I->getParent();
781 auto &BBInfo =
Result.UsesPerBlock[BB];
782 auto [It,
Inserted] = BBInfo.Insts.try_emplace(
I);
783 auto &IInfo = It->second;
788 IInfo = {ArgumentAccessInfo::AccessType::Unknown, {}};
789 BBInfo.HasUnknownAccess =
true;
793 IInfo = std::move(Info);
794 BBInfo.HasUnknownAccess |=
795 IInfo.ArgAccessType == ArgumentAccessInfo::AccessType::Unknown;
797 (IInfo.ArgAccessType == ArgumentAccessInfo::AccessType::Write ||
798 IInfo.ArgAccessType ==
799 ArgumentAccessInfo::AccessType::WriteWithSideEffect) &&
800 !IInfo.AccessRanges.empty();
801 BBInfo.HasWrites |= InfoHasWrites;
802 return InfoHasWrites;
807 while (!Worklist.
empty()) {
809 User *U = ArgUse.U->getUser();
813 std::optional<int64_t> NewOffset = std::nullopt;
817 NewOffset = *ArgUse.Offset +
Offset.getSExtValue();
819 for (
Use &U :
GEP->uses())
825 bool HasWrite = UpdateUseInfo(
I, getArgumentAccessInfo(
I, ArgUse,
DL));
827 Result.HasAnyWrite |= HasWrite;
829 if (HasWrite &&
I->getParent() != &EntryBB)
830 Result.HasWriteOutsideEntryBB =
true;
869 if (
A->hasInAllocaAttr() ||
A->hasPreallocatedAttr())
873 bool IsWrite =
false;
875 for (
Use &U :
A->uses()) {
880 while (!Worklist.
empty()) {
881 if (IsWrite && IsRead)
888 switch (
I->getOpcode()) {
889 case Instruction::BitCast:
890 case Instruction::GetElementPtr:
891 case Instruction::PHI:
892 case Instruction::Select:
893 case Instruction::AddrSpaceCast:
895 for (
Use &UU :
I->uses())
896 if (Visited.
insert(&UU).second)
900 case Instruction::Call:
901 case Instruction::Invoke: {
920 if (Visited.
insert(&UU).second)
930 if (!
I->getType()->isVoidTy())
931 for (
Use &UU :
I->uses())
932 if (Visited.
insert(&UU).second)
942 SCCNodes.
count(
F->getArg(UseIndex)))
963 case Instruction::Load:
972 case Instruction::Store:
985 case Instruction::ICmp:
986 case Instruction::Ret:
994 if (IsWrite && IsRead)
997 return Attribute::ReadOnly;
999 return Attribute::WriteOnly;
1001 return Attribute::ReadNone;
1012 if (!
F->hasExactDefinition())
1015 if (
F->getReturnType()->isVoidTy())
1019 if (
F->getAttributes().hasAttrSomewhere(Attribute::Returned))
1022 auto FindRetArg = [&]() ->
Argument * {
1030 if (!RetVal || RetVal->getType() !=
F->getReturnType())
1035 else if (RetArg != RetVal)
1042 if (
Argument *RetArg = FindRetArg()) {
1043 RetArg->addAttr(Attribute::Returned);
1071 for (
auto &CSArg : CalledFunc->args()) {
1072 unsigned ArgNo = CSArg.getArgNo();
1077 if (CSArg.hasNonNullAttr(
false)) {
1081 if (!FArg->hasNonNullAttr()) {
1082 FArg->addAttr(Attribute::NonNull);
1090 if ((CSNoFPClass | ArgNoFPClass) != ArgNoFPClass) {
1092 FArg->getContext(), CSNoFPClass | ArgNoFPClass));
1107 assert((R == Attribute::ReadOnly || R == Attribute::ReadNone ||
1108 R == Attribute::WriteOnly)
1109 &&
"Must be an access attribute.");
1110 assert(
A &&
"Argument must not be null.");
1113 if (
A->hasAttribute(R))
1118 A->removeAttr(Attribute::WriteOnly);
1119 A->removeAttr(Attribute::ReadOnly);
1120 A->removeAttr(Attribute::ReadNone);
1122 if (R == Attribute::ReadNone || R == Attribute::ReadOnly)
1123 A->removeAttr(Attribute::Writable);
1125 if (R == Attribute::ReadOnly)
1127 else if (R == Attribute::WriteOnly)
1135 auto ArgumentUses = collectArgumentUsesPerBlock(
A,
F);
1137 if (!ArgumentUses.HasAnyWrite)
1140 auto &UsesPerBlock = ArgumentUses.UsesPerBlock;
1149 auto UPB = UsesPerBlock.find(BB);
1156 if (UPB == UsesPerBlock.end() || !UPB->second.HasUnknownAccess) {
1157 bool HasAddedSuccessor =
false;
1159 if (
auto SuccI = Initialized.
find(Succ); SuccI != Initialized.
end()) {
1160 if (HasAddedSuccessor) {
1163 CRL = SuccI->second;
1164 HasAddedSuccessor =
true;
1173 if (UPB != UsesPerBlock.end()) {
1177 sort(Insts, [](std::pair<Instruction *, ArgumentAccessInfo> &
LHS,
1178 std::pair<Instruction *, ArgumentAccessInfo> &
RHS) {
1179 return LHS.first->comesBefore(
RHS.first);
1184 for (
auto &[
_, Info] :
reverse(Insts)) {
1185 if (Info.ArgAccessType == ArgumentAccessInfo::AccessType::Unknown ||
1186 Info.ArgAccessType ==
1187 ArgumentAccessInfo::AccessType::WriteWithSideEffect)
1189 if (!Info.AccessRanges.empty()) {
1190 if (Info.ArgAccessType == ArgumentAccessInfo::AccessType::Write ||
1191 Info.ArgAccessType ==
1192 ArgumentAccessInfo::AccessType::WriteWithSideEffect) {
1195 assert(Info.ArgAccessType == ArgumentAccessInfo::AccessType::Read);
1196 for (
const auto &ReadRange : Info.AccessRanges)
1208 bool OnlyScanEntryBlock = !ArgumentUses.HasWriteOutsideEntryBB;
1209 if (!OnlyScanEntryBlock)
1210 if (
auto EntryUPB = UsesPerBlock.find(&EntryBB);
1211 EntryUPB != UsesPerBlock.end())
1212 OnlyScanEntryBlock = EntryUPB->second.HasUnknownAccess;
1213 if (OnlyScanEntryBlock) {
1214 EntryCRL = VisitBlock(&EntryBB);
1215 if (EntryCRL.
empty())
1226 Initialized[BB] = CRL;
1229 auto EntryCRLI = Initialized.
find(&EntryBB);
1230 if (EntryCRLI == Initialized.
end())
1233 EntryCRL = EntryCRLI->second;
1237 "should have bailed already if EntryCRL is empty");
1239 if (
A.hasAttribute(Attribute::Initializes)) {
1241 A.getAttribute(Attribute::Initializes).getValueAsConstantRangeList();
1242 if (PreviousCRL == EntryCRL)
1244 EntryCRL = EntryCRL.
unionWith(PreviousCRL);
1256 bool SkipInitializes) {
1259 auto DetermineAccessAttrsForSingleton = [](
Argument *
A) {
1274 if (!
F->hasExactDefinition())
1282 if (
F->onlyReadsMemory() &&
F->doesNotThrow() &&
F->willReturn() &&
1283 F->getReturnType()->isVoidTy()) {
1285 if (
A.getType()->isPointerTy() && !
A.hasNoCaptureAttr()) {
1296 if (!
A.getType()->isPointerTy())
1298 bool HasNonLocalUses =
false;
1299 CaptureInfo OrigCI =
A.getAttributes().getCaptureInfo();
1301 ArgumentUsesTracker Tracker(SCCNodes);
1304 if (NewCI != OrigCI) {
1305 if (Tracker.Uses.empty()) {
1314 ArgumentGraphNode *
Node = AG[&
A];
1317 Node->Uses.push_back(AG[
Use]);
1319 HasNonLocalUses =
true;
1325 if (!HasNonLocalUses && !
A.onlyReadsMemory()) {
1330 if (DetermineAccessAttrsForSingleton(&
A))
1333 if (!SkipInitializes && !
A.onlyReadsMemory()) {
1348 const std::vector<ArgumentGraphNode *> &ArgumentSCC = *
I;
1349 if (ArgumentSCC.size() == 1) {
1350 if (!ArgumentSCC[0]->Definition)
1354 if (ArgumentSCC[0]->
Uses.size() == 1 &&
1355 ArgumentSCC[0]->Uses[0] == ArgumentSCC[0]) {
1356 Argument *
A = ArgumentSCC[0]->Definition;
1357 CaptureInfo OrigCI =
A->getAttributes().getCaptureInfo();
1359 if (NewCI != OrigCI) {
1366 if (DetermineAccessAttrsForSingleton(
A))
1375 for (ArgumentGraphNode *
I : ArgumentSCC) {
1376 ArgumentSCCNodes.
insert(
I->Definition);
1383 for (ArgumentGraphNode *
N : ArgumentSCC) {
1384 for (ArgumentGraphNode *
Use :
N->Uses) {
1386 if (ArgumentSCCNodes.
count(
A))
1397 for (ArgumentGraphNode *
N : ArgumentSCC) {
1399 CaptureInfo OrigCI =
A->getAttributes().getCaptureInfo();
1401 if (NewCI != OrigCI) {
1412 for (ArgumentGraphNode *
N : ArgumentSCC) {
1413 if (DetermineAccessAttrsForSingleton(
N->Definition))
1414 Changed.insert(
N->Definition->getParent());
1433 if (
A == Attribute::ReadNone)
1435 if (
B == Attribute::ReadNone)
1441 for (ArgumentGraphNode *
N : ArgumentSCC) {
1444 AccessAttr = meetAccessAttr(AccessAttr, K);
1450 for (ArgumentGraphNode *
N : ArgumentSCC) {
1467 FlowsToReturn.
insert(Ret->getReturnValue());
1469 for (
unsigned i = 0; i != FlowsToReturn.
size(); ++i) {
1470 Value *RetVal = FlowsToReturn[i];
1483 switch (RVI->getOpcode()) {
1485 case Instruction::BitCast:
1486 case Instruction::GetElementPtr:
1487 case Instruction::AddrSpaceCast:
1488 FlowsToReturn.
insert(RVI->getOperand(0));
1490 case Instruction::Select: {
1492 FlowsToReturn.
insert(
SI->getTrueValue());
1493 FlowsToReturn.
insert(
SI->getFalseValue());
1496 case Instruction::PHI: {
1503 case Instruction::Alloca:
1505 case Instruction::Call:
1506 case Instruction::Invoke: {
1532 if (
F->returnDoesNotAlias())
1538 if (!
F->hasExactDefinition())
1543 if (!
F->getReturnType()->isPointerTy())
1551 if (
F->returnDoesNotAlias() ||
1552 !
F->getReturnType()->isPointerTy())
1555 F->setReturnDoesNotAlias();
1569 bool &Speculative) {
1570 assert(
F->getReturnType()->isPointerTy() &&
1571 "nonnull only meaningful on pointer types");
1572 Speculative =
false;
1577 FlowsToReturn.
insert(Ret->getReturnValue());
1579 auto &
DL =
F->getDataLayout();
1581 for (
unsigned i = 0; i != FlowsToReturn.
size(); ++i) {
1582 Value *RetVal = FlowsToReturn[i];
1595 case Instruction::BitCast:
1596 case Instruction::AddrSpaceCast:
1599 case Instruction::GetElementPtr:
1605 case Instruction::Select: {
1607 FlowsToReturn.
insert(
SI->getTrueValue());
1608 FlowsToReturn.
insert(
SI->getFalseValue());
1611 case Instruction::PHI: {
1617 case Instruction::Call:
1618 case Instruction::Invoke: {
1623 if (Callee && SCCNodes.count(Callee)) {
1643 bool SCCReturnsNonNull =
true;
1649 if (
F->getAttributes().hasRetAttr(Attribute::NonNull))
1655 if (!
F->hasExactDefinition())
1660 if (!
F->getReturnType()->isPointerTy())
1663 bool Speculative =
false;
1669 <<
" as nonnull\n");
1670 F->addRetAttr(Attribute::NonNull);
1678 SCCReturnsNonNull =
false;
1681 if (SCCReturnsNonNull) {
1683 if (
F->getAttributes().hasRetAttr(Attribute::NonNull) ||
1684 !
F->getReturnType()->isPointerTy())
1687 LLVM_DEBUG(
dbgs() <<
"SCC marking " <<
F->getName() <<
" as nonnull\n");
1688 F->addRetAttr(Attribute::NonNull);
1702 AttributeList Attrs =
F->getAttributes();
1703 if (Attrs.hasRetAttr(Attribute::NoUndef))
1709 if (!
F->hasExactDefinition())
1715 if (
F->hasFnAttribute(Attribute::SanitizeMemory))
1718 if (
F->getReturnType()->isVoidTy())
1725 Value *RetVal = Ret->getReturnValue();
1732 if (Attrs.hasRetAttr(Attribute::NonNull) &&
1740 Attribute Attr = Attrs.getRetAttr(Attribute::Range);
1748 F->addRetAttr(Attribute::NoUndef);
1763class AttributeInferer {
1766 struct InferenceDescriptor {
1772 std::function<bool(
const Function &)> SkipFunction;
1775 std::function<bool(Instruction &)> InstrBreaksAttribute;
1778 std::function<void(Function &)> SetAttribute;
1781 Attribute::AttrKind AKind;
1785 bool RequiresExactDefinition;
1787 InferenceDescriptor(Attribute::AttrKind AK,
1788 std::function<
bool(
const Function &)> SkipFunc,
1789 std::function<
bool(Instruction &)> InstrScan,
1790 std::function<
void(Function &)> SetAttr,
1792 : SkipFunction(SkipFunc), InstrBreaksAttribute(InstrScan),
1793 SetAttribute(SetAttr), AKind(AK),
1794 RequiresExactDefinition(ReqExactDef) {}
1801 void registerAttrInference(InferenceDescriptor AttrInference) {
1802 InferenceDescriptors.
push_back(AttrInference);
1805 void run(
const SCCNodeSet &SCCNodes, SmallPtrSet<Function *, 8> &
Changed);
1810void AttributeInferer::run(
const SCCNodeSet &SCCNodes,
1811 SmallPtrSet<Function *, 8> &
Changed) {
1816 for (Function *
F : SCCNodes) {
1819 if (InferInSCC.
empty())
1824 if (
ID.SkipFunction(*
F))
1829 return F->isDeclaration() ||
1830 (
ID.RequiresExactDefinition && !
F->hasExactDefinition());
1837 InferInSCC, std::back_inserter(InferInThisFunc),
1838 [
F](
const InferenceDescriptor &
ID) {
return !
ID.SkipFunction(*
F); });
1840 if (InferInThisFunc.empty())
1846 if (!
ID.InstrBreaksAttribute(
I))
1851 return D.AKind ==
ID.AKind;
1857 if (InferInThisFunc.empty())
1862 if (InferInSCC.
empty())
1865 for (Function *
F : SCCNodes)
1870 for (
auto &
ID : InferInSCC) {
1871 if (
ID.SkipFunction(*
F))
1874 ID.SetAttribute(*
F);
1878struct SCCNodesResult {
1879 SCCNodeSet SCCNodes;
1886 const SCCNodeSet &SCCNodes) {
1896 if (!
I.mayThrow(
true))
1899 if (
Function *Callee = CI->getCalledFunction()) {
1903 if (SCCNodes.contains(Callee))
1921 if (SCCNodes.contains(Callee))
1942 return !
SI->isUnordered();
1944 return !LI->isUnordered();
1971 if (!
MI->isVolatile())
1976 if (SCCNodes.contains(Callee))
1987 AttributeInferer AI;
1994 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
1995 Attribute::Convergent,
1997 [](
const Function &
F) {
return !
F.isConvergent(); },
2003 LLVM_DEBUG(
dbgs() <<
"Removing convergent attr from fn " <<
F.getName()
2005 F.setNotConvergent();
2018 AttributeInferer AI;
2026 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
2027 Attribute::NoUnwind,
2029 [](
const Function &
F) {
return F.doesNotThrow(); },
2036 <<
"Adding nounwind attr to fn " <<
F.getName() <<
"\n");
2037 F.setDoesNotThrow();
2049 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
2052 [](
const Function &
F) {
return F.doesNotFreeMemory(); },
2059 <<
"Adding nofree attr to fn " <<
F.getName() <<
"\n");
2060 F.setDoesNotFreeMemory();
2065 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
2068 [](
const Function &
F) {
return F.hasNoSync(); },
2075 <<
"Adding nosync attr to fn " <<
F.getName() <<
"\n");
2093 bool AnyFunctionsAddressIsTaken =
true) {
2094 for (
const auto &BB :
F) {
2095 for (
const auto &
I : BB.instructionsWithoutDebug()) {
2098 if (!Callee || Callee == &
F)
2101 if (Callee->doesNotRecurse())
2104 if (!AnyFunctionsAddressIsTaken ||
2105 (Callee->isDeclaration() &&
2106 Callee->hasFnAttribute(Attribute::NoCallback)))
2120 if (SCCNodes.size() != 1)
2124 if (!
F || !
F->hasExactDefinition() ||
F->doesNotRecurse())
2130 F->setDoesNotRecurse();
2140 if (!
F || !
F->hasExactDefinition() ||
F->hasFnAttribute(Attribute::Naked) ||
2145 F->setDoesNotReturn();
2153 ColdPaths[&
F.front()] =
false;
2157 while (!Jobs.
empty()) {
2168 ColdPaths[BB] =
true;
2185 auto [Iter, Inserted] = ColdPaths.
try_emplace(Succ,
false);
2201 if (!
F || !
F->hasExactDefinition() ||
F->hasFnAttribute(Attribute::Naked) ||
2202 F->hasFnAttribute(Attribute::Cold) ||
F->hasFnAttribute(Attribute::Hot))
2207 F->addFnAttr(Attribute::Cold);
2219 if (!
F.hasExactDefinition())
2223 if (
F.mustProgress() &&
F.onlyReadsMemory())
2227 if (
F.isDeclaration())
2234 if (!Backedges.
empty())
2240 return I.willReturn();
2260 if (!
F ||
F->hasOptNone() ||
F->hasFnAttribute(Attribute::Naked) ||
2261 F->isPresplitCoroutine()) {
2266 Res.SCCNodes.insert(
F);
2271template <
typename AARGetterT>
2274 bool ArgAttrsOnly) {
2278 if (Nodes.SCCNodes.empty())
2322 bool ArgAttrsOnly =
false;
2323 if (
C.size() == 1 && SkipNonRecursive) {
2326 ArgAttrsOnly =
true;
2340 Functions.push_back(&
N.getFunction());
2343 auto ChangedFunctions =
2345 if (ChangedFunctions.empty())
2359 for (
auto *U :
Changed->users()) {
2362 FAM.invalidate(*
Call->getFunction(), FuncPA);
2378 OS, MapClassName2PassName);
2379 if (SkipNonRecursive)
2380 OS <<
"<skip-non-recursive-function-attrs>";
2383template <
typename AARGetterT>
2387 Functions.push_back(
I->getFunction());
2394 if (
F.doesNotRecurse())
2400 assert(!
F.isDeclaration() &&
"Cannot deduce norecurse without a definition!");
2401 assert(
F.hasInternalLinkage() &&
2402 "Can only do top-down deduction for internal linkage functions!");
2412 for (
auto &U :
F.uses()) {
2415 !CB->
getParent()->getParent()->doesNotRecurse())
2418 F.setDoesNotRecurse();
2424 assert(!
F.isDeclaration() &&
"Cannot deduce nofpclass without a definition!");
2425 unsigned NumArgs =
F.arg_size();
2430 for (
User *U :
F.users()) {
2436 for (
unsigned I = 0;
I != NumArgs; ++
I) {
2441 ArgsNoFPClass[
I] &= ~Cst->classify();
2449 if (RetNoFPClass !=
fcNone) {
2450 FPClassTest OldAttr =
F.getAttributes().getRetNoFPClass();
2451 if (OldAttr != RetNoFPClass) {
2457 for (
unsigned I = 0;
I != NumArgs; ++
I) {
2459 if (ArgNoFPClass ==
fcNone)
2462 if (OldAttr == ArgNoFPClass)
2485 if (SCC.size() != 1)
2487 Function &
F = SCC.begin()->getFunction();
2488 if (!
F.isDeclaration() &&
F.hasInternalLinkage() && !
F.use_empty())
2521 bool AnyFunctionsAddressIsTaken =
false;
2523 if (
F.isDeclaration() ||
F.doesNotRecurse())
2525 if (!
F.hasLocalLinkage() ||
F.hasAddressTaken()) {
2526 AnyFunctionsAddressIsTaken =
true;
2551 if (!
F.hasExactDefinition() ||
F.doesNotRecurse())
2558 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 bool isOrderedAtomic(Instruction *I)
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.
ArrayRef - 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 if the block is well formed or null if the block is not well forme...
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)
static MemoryEffectsBase inaccessibleMemOnly(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.
StringRef - 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...
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
initializer< Ty > init(const Ty &Val)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the 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.
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.
iterator_range< po_iterator< T > > post_order(const T &G)
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.
LLVM_ABI ConstantRange computeConstantRange(const Value *V, bool ForSigned, bool UseInstrInfo=true, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, unsigned Depth=0)
Determine the possible constant range of an integer or vector of integer value.
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)
LLVM_ABI bool isIntrinsicReturningPointerAliasingArgumentWithoutCapturing(const CallBase *Call, bool MustPreserveNullness)
{launder,strip}.invariant.group returns pointer that aliases its argument, and it only captures point...
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...
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.
@ Ref
The access may reference the value stored in memory.
@ ModRef
The access may reference and may modify the value stored in memory.
@ Mod
The access 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.
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
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.