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) {
190 if (
F.getAttributes().hasAttrSomewhere(Attribute::InAlloca) ||
191 F.getAttributes().hasAttrSomewhere(Attribute::Preallocated))
204 if (!
Call->hasOperandBundles() &&
Call->getCalledFunction() &&
205 SCCNodes.count(
Call->getCalledFunction())) {
245 if (
I.mayWriteToMemory())
247 if (
I.mayReadFromMemory())
267 return {OrigME & ME, RecursiveArgME};
276template <
typename AARGetterT>
287 auto [FnME, FnRecursiveArgME] =
290 RecursiveArgME |= FnRecursiveArgME;
304 if (NewME != OldME) {
306 F->setMemoryEffects(NewME);
310 A.removeAttr(Attribute::Writable);
324 auto [It, Inserted] = CachedPrevailingSummary.
try_emplace(VI);
371 for (
const auto &GVS : VI.getSummaryList()) {
377 if (!FS || FS->fflags().HasUnknownCall)
380 const auto &
Linkage = GVS->linkage();
385 <<
"ThinLTO FunctionAttrs: Multiple Local Linkage, bailing on "
387 << VI.name() <<
" from " << FS->modulePath() <<
". Previous module "
388 <<
Local->modulePath() <<
"\n");
393 assert(IsPrevailing(VI.getGUID(), GVS.get()) || GVS->wasPromoted());
400 if (IsPrevailing(VI.getGUID(), GVS.get())) {
410 auto &CPS = CachedPrevailingSummary[VI];
414 }
else if (Prevailing) {
434 auto PropagateAttributes = [&](std::vector<ValueInfo> &SCCNodes) {
437 InferredFlags.
NoRecurse = (SCCNodes.size() == 1);
440 for (
auto &V : SCCNodes) {
451 for (
const auto &Callee : CallerSummary->
calls()) {
453 Callee.first, CachedPrevailingSummary, IsPrevailing);
471 for (
auto &V : SCCNodes) {
473 LLVM_DEBUG(
dbgs() <<
"ThinLTO FunctionAttrs: Propagated NoRecurse to "
474 << V.name() <<
"\n");
475 ++NumThinLinkNoRecurse;
479 LLVM_DEBUG(
dbgs() <<
"ThinLTO FunctionAttrs: Propagated NoUnwind to "
480 << V.name() <<
"\n");
481 ++NumThinLinkNoUnwind;
484 for (
const auto &S : V.getSummaryList()) {
500 std::vector<ValueInfo> Nodes(*
I);
501 PropagateAttributes(Nodes);
511struct ArgumentGraphNode {
522 using ArgumentMapTy = std::map<Argument *, ArgumentGraphNode>;
524 ArgumentMapTy ArgumentMap;
532 ArgumentGraphNode SyntheticRoot;
535 ArgumentGraph() { SyntheticRoot.Definition =
nullptr; }
539 iterator
begin() {
return SyntheticRoot.Uses.begin(); }
540 iterator
end() {
return SyntheticRoot.Uses.end(); }
541 ArgumentGraphNode *getEntryNode() {
return &SyntheticRoot; }
543 ArgumentGraphNode *operator[](Argument *
A) {
544 ArgumentGraphNode &
Node = ArgumentMap[
A];
546 SyntheticRoot.Uses.push_back(&Node);
555 ArgumentUsesTracker(
const SCCNodeSet &SCCNodes) : SCCNodes(SCCNodes) {}
559 Action captured(
const Use *U, UseCaptureInfo UseCI)
override {
560 if (updateCaptureInfo(U, UseCI.
UseCC)) {
569 return ContinueIgnoringReturn;
580 CI |= CaptureInfo(CC);
585 if (!
F || !
F->hasExactDefinition() || !SCCNodes.count(
F)) {
586 CI |= CaptureInfo(CC);
600 CI |= CaptureInfo(CC);
604 if (UseIndex >=
F->arg_size()) {
605 assert(
F->isVarArg() &&
"More params than args in non-varargs call");
606 CI |= CaptureInfo(CC);
612 Uses.push_back(&*std::next(
F->arg_begin(), UseIndex));
622 const SCCNodeSet &SCCNodes;
630 std::optional<int64_t> Offset;
637struct ArgumentAccessInfo {
638 enum class AccessType : uint8_t {
Write, WriteWithSideEffect,
Read,
Unknown };
639 AccessType ArgAccessType;
640 ConstantRangeList AccessRanges;
644struct UsesPerBlockInfo {
645 SmallDenseMap<Instruction *, ArgumentAccessInfo, 4> Insts;
646 bool HasWrites =
false;
647 bool HasUnknownAccess =
false;
651struct ArgumentUsesSummary {
652 bool HasAnyWrite =
false;
653 bool HasWriteOutsideEntryBB =
false;
654 SmallDenseMap<const BasicBlock *, UsesPerBlockInfo, 16> UsesPerBlock;
657ArgumentAccessInfo getArgumentAccessInfo(
const Instruction *
I,
658 const ArgumentUse &ArgUse,
660 auto GetTypeAccessRange =
662 std::optional<int64_t>
Offset) -> std::optional<ConstantRange> {
676 auto GetConstantIntRange =
678 std::optional<int64_t>
Offset) -> std::optional<ConstantRange> {
680 if (ConstantLength &&
Offset) {
681 int64_t
Len = ConstantLength->getSExtValue();
699 if (
SI->isSimple() && &
SI->getOperandUse(1) == ArgUse.U) {
704 if (
auto TypeAccessRange =
705 GetTypeAccessRange(
SI->getAccessType(), ArgUse.Offset))
706 AccessRanges.
insert(*TypeAccessRange);
707 return {ArgumentAccessInfo::AccessType::Write, std::move(AccessRanges)};
710 if (LI->isSimple()) {
711 assert(&LI->getOperandUse(0) == ArgUse.U);
715 if (
auto TypeAccessRange =
716 GetTypeAccessRange(LI->getAccessType(), ArgUse.Offset))
717 return {ArgumentAccessInfo::AccessType::Read, {*TypeAccessRange}};
720 if (!MemSet->isVolatile()) {
722 if (
auto AccessRange =
723 GetConstantIntRange(MemSet->getLength(), ArgUse.Offset))
724 AccessRanges.
insert(*AccessRange);
725 return {ArgumentAccessInfo::AccessType::Write, AccessRanges};
728 if (!MTI->isVolatile()) {
729 if (&MTI->getOperandUse(0) == ArgUse.U) {
731 if (
auto AccessRange =
732 GetConstantIntRange(MTI->getLength(), ArgUse.Offset))
733 AccessRanges.
insert(*AccessRange);
734 return {ArgumentAccessInfo::AccessType::Write, AccessRanges};
735 }
else if (&MTI->getOperandUse(1) == ArgUse.U) {
736 if (
auto AccessRange =
737 GetConstantIntRange(MTI->getLength(), ArgUse.Offset))
738 return {ArgumentAccessInfo::AccessType::Read, {*AccessRange}};
745 bool IsInitialize = CB->
paramHasAttr(ArgNo, Attribute::Initializes);
746 if (IsInitialize && ArgUse.Offset) {
750 ? ArgumentAccessInfo::AccessType::Write
751 : ArgumentAccessInfo::AccessType::WriteWithSideEffect;
757 CR.getUpper() + *ArgUse.Offset));
758 return {
Access, AccessRanges};
763 return {ArgumentAccessInfo::AccessType::Unknown, {}};
768 auto &
DL =
F.getParent()->getDataLayout();
770 DL.getIndexSizeInBits(
A.getType()->getPointerAddressSpace());
771 ArgumentUsesSummary
Result;
775 for (
Use &U :
A.uses())
781 auto *BB =
I->getParent();
782 auto &BBInfo =
Result.UsesPerBlock[BB];
783 auto [It,
Inserted] = BBInfo.Insts.try_emplace(
I);
784 auto &IInfo = It->second;
789 IInfo = {ArgumentAccessInfo::AccessType::Unknown, {}};
790 BBInfo.HasUnknownAccess =
true;
794 IInfo = std::move(Info);
795 BBInfo.HasUnknownAccess |=
796 IInfo.ArgAccessType == ArgumentAccessInfo::AccessType::Unknown;
798 (IInfo.ArgAccessType == ArgumentAccessInfo::AccessType::Write ||
799 IInfo.ArgAccessType ==
800 ArgumentAccessInfo::AccessType::WriteWithSideEffect) &&
801 !IInfo.AccessRanges.empty();
802 BBInfo.HasWrites |= InfoHasWrites;
803 return InfoHasWrites;
808 while (!Worklist.
empty()) {
810 User *U = ArgUse.U->getUser();
814 std::optional<int64_t> NewOffset = std::nullopt;
818 NewOffset = *ArgUse.Offset +
Offset.getSExtValue();
820 for (
Use &U :
GEP->uses())
826 bool HasWrite = UpdateUseInfo(
I, getArgumentAccessInfo(
I, ArgUse,
DL));
828 Result.HasAnyWrite |= HasWrite;
830 if (HasWrite &&
I->getParent() != &EntryBB)
831 Result.HasWriteOutsideEntryBB =
true;
870 if (
A->hasInAllocaAttr() ||
A->hasPreallocatedAttr())
874 bool IsWrite =
false;
876 for (
Use &U :
A->uses()) {
881 while (!Worklist.
empty()) {
882 if (IsWrite && IsRead)
889 switch (
I->getOpcode()) {
890 case Instruction::BitCast:
891 case Instruction::GetElementPtr:
892 case Instruction::PHI:
893 case Instruction::Select:
894 case Instruction::AddrSpaceCast:
896 for (
Use &UU :
I->uses())
897 if (Visited.
insert(&UU).second)
901 case Instruction::Call:
902 case Instruction::Invoke: {
921 if (Visited.
insert(&UU).second)
931 if (!
I->getType()->isVoidTy())
932 for (
Use &UU :
I->uses())
933 if (Visited.
insert(&UU).second)
943 SCCNodes.
count(
F->getArg(UseIndex)))
964 case Instruction::Load:
973 case Instruction::Store:
986 case Instruction::ICmp:
987 case Instruction::Ret:
995 if (IsWrite && IsRead)
998 return Attribute::ReadOnly;
1000 return Attribute::WriteOnly;
1002 return Attribute::ReadNone;
1013 if (!
F->hasExactDefinition())
1016 if (
F->getReturnType()->isVoidTy())
1020 if (
F->getAttributes().hasAttrSomewhere(Attribute::Returned))
1023 auto FindRetArg = [&]() ->
Argument * {
1031 if (!RetVal || RetVal->getType() !=
F->getReturnType())
1036 else if (RetArg != RetVal)
1043 if (
Argument *RetArg = FindRetArg()) {
1044 RetArg->addAttr(Attribute::Returned);
1072 for (
auto &CSArg : CalledFunc->args()) {
1073 unsigned ArgNo = CSArg.getArgNo();
1078 if (CSArg.hasNonNullAttr(
false)) {
1082 if (!FArg->hasNonNullAttr()) {
1083 FArg->addAttr(Attribute::NonNull);
1091 if ((CSNoFPClass | ArgNoFPClass) != ArgNoFPClass) {
1093 FArg->getContext(), CSNoFPClass | ArgNoFPClass));
1108 assert((R == Attribute::ReadOnly || R == Attribute::ReadNone ||
1109 R == Attribute::WriteOnly)
1110 &&
"Must be an access attribute.");
1111 assert(
A &&
"Argument must not be null.");
1114 if (
A->hasAttribute(R))
1119 A->removeAttr(Attribute::WriteOnly);
1120 A->removeAttr(Attribute::ReadOnly);
1121 A->removeAttr(Attribute::ReadNone);
1123 if (R == Attribute::ReadNone || R == Attribute::ReadOnly)
1124 A->removeAttr(Attribute::Writable);
1126 if (R == Attribute::ReadOnly)
1128 else if (R == Attribute::WriteOnly)
1136 auto ArgumentUses = collectArgumentUsesPerBlock(
A,
F);
1138 if (!ArgumentUses.HasAnyWrite)
1141 auto &UsesPerBlock = ArgumentUses.UsesPerBlock;
1150 auto UPB = UsesPerBlock.find(BB);
1157 if (UPB == UsesPerBlock.end() || !UPB->second.HasUnknownAccess) {
1158 bool HasAddedSuccessor =
false;
1160 if (
auto SuccI = Initialized.
find(Succ); SuccI != Initialized.
end()) {
1161 if (HasAddedSuccessor) {
1164 CRL = SuccI->second;
1165 HasAddedSuccessor =
true;
1174 if (UPB != UsesPerBlock.end()) {
1178 sort(Insts, [](std::pair<Instruction *, ArgumentAccessInfo> &
LHS,
1179 std::pair<Instruction *, ArgumentAccessInfo> &
RHS) {
1180 return LHS.first->comesBefore(
RHS.first);
1185 for (
auto &[
_, Info] :
reverse(Insts)) {
1186 if (Info.ArgAccessType == ArgumentAccessInfo::AccessType::Unknown ||
1187 Info.ArgAccessType ==
1188 ArgumentAccessInfo::AccessType::WriteWithSideEffect)
1190 if (!Info.AccessRanges.empty()) {
1191 if (Info.ArgAccessType == ArgumentAccessInfo::AccessType::Write ||
1192 Info.ArgAccessType ==
1193 ArgumentAccessInfo::AccessType::WriteWithSideEffect) {
1196 assert(Info.ArgAccessType == ArgumentAccessInfo::AccessType::Read);
1197 for (
const auto &ReadRange : Info.AccessRanges)
1209 bool OnlyScanEntryBlock = !ArgumentUses.HasWriteOutsideEntryBB;
1210 if (!OnlyScanEntryBlock)
1211 if (
auto EntryUPB = UsesPerBlock.find(&EntryBB);
1212 EntryUPB != UsesPerBlock.end())
1213 OnlyScanEntryBlock = EntryUPB->second.HasUnknownAccess;
1214 if (OnlyScanEntryBlock) {
1215 EntryCRL = VisitBlock(&EntryBB);
1216 if (EntryCRL.
empty())
1227 Initialized[BB] = CRL;
1230 auto EntryCRLI = Initialized.
find(&EntryBB);
1231 if (EntryCRLI == Initialized.
end())
1234 EntryCRL = EntryCRLI->second;
1238 "should have bailed already if EntryCRL is empty");
1240 if (
A.hasAttribute(Attribute::Initializes)) {
1242 A.getAttribute(Attribute::Initializes).getValueAsConstantRangeList();
1243 if (PreviousCRL == EntryCRL)
1245 EntryCRL = EntryCRL.
unionWith(PreviousCRL);
1257 bool SkipInitializes) {
1260 auto DetermineAccessAttrsForSingleton = [](
Argument *
A) {
1275 if (!
F->hasExactDefinition())
1283 if (
F->onlyReadsMemory() &&
F->doesNotThrow() &&
F->willReturn() &&
1284 F->getReturnType()->isVoidTy()) {
1286 if (
A.getType()->isPointerTy() && !
A.hasNoCaptureAttr()) {
1297 if (!
A.getType()->isPointerTy())
1299 bool HasNonLocalUses =
false;
1300 CaptureInfo OrigCI =
A.getAttributes().getCaptureInfo();
1302 ArgumentUsesTracker Tracker(SCCNodes);
1305 if (NewCI != OrigCI) {
1306 if (Tracker.Uses.empty()) {
1315 ArgumentGraphNode *
Node = AG[&
A];
1318 Node->Uses.push_back(AG[
Use]);
1320 HasNonLocalUses =
true;
1326 if (!HasNonLocalUses && !
A.onlyReadsMemory()) {
1331 if (DetermineAccessAttrsForSingleton(&
A))
1334 if (!SkipInitializes && !
A.onlyReadsMemory()) {
1349 const std::vector<ArgumentGraphNode *> &ArgumentSCC = *
I;
1350 if (ArgumentSCC.size() == 1) {
1351 if (!ArgumentSCC[0]->Definition)
1355 if (ArgumentSCC[0]->
Uses.size() == 1 &&
1356 ArgumentSCC[0]->Uses[0] == ArgumentSCC[0]) {
1357 Argument *
A = ArgumentSCC[0]->Definition;
1358 CaptureInfo OrigCI =
A->getAttributes().getCaptureInfo();
1360 if (NewCI != OrigCI) {
1367 if (DetermineAccessAttrsForSingleton(
A))
1376 for (ArgumentGraphNode *
I : ArgumentSCC) {
1377 ArgumentSCCNodes.
insert(
I->Definition);
1384 for (ArgumentGraphNode *
N : ArgumentSCC) {
1385 for (ArgumentGraphNode *
Use :
N->Uses) {
1387 if (ArgumentSCCNodes.
count(
A))
1398 for (ArgumentGraphNode *
N : ArgumentSCC) {
1400 CaptureInfo OrigCI =
A->getAttributes().getCaptureInfo();
1402 if (NewCI != OrigCI) {
1413 for (ArgumentGraphNode *
N : ArgumentSCC) {
1414 if (DetermineAccessAttrsForSingleton(
N->Definition))
1415 Changed.insert(
N->Definition->getParent());
1434 if (
A == Attribute::ReadNone)
1436 if (
B == Attribute::ReadNone)
1442 for (ArgumentGraphNode *
N : ArgumentSCC) {
1445 AccessAttr = meetAccessAttr(AccessAttr, K);
1451 for (ArgumentGraphNode *
N : ArgumentSCC) {
1468 FlowsToReturn.
insert(Ret->getReturnValue());
1470 for (
unsigned i = 0; i != FlowsToReturn.
size(); ++i) {
1471 Value *RetVal = FlowsToReturn[i];
1484 switch (RVI->getOpcode()) {
1486 case Instruction::BitCast:
1487 case Instruction::GetElementPtr:
1488 case Instruction::AddrSpaceCast:
1489 FlowsToReturn.
insert(RVI->getOperand(0));
1491 case Instruction::Select: {
1493 FlowsToReturn.
insert(
SI->getTrueValue());
1494 FlowsToReturn.
insert(
SI->getFalseValue());
1497 case Instruction::PHI: {
1504 case Instruction::Alloca:
1506 case Instruction::Call:
1507 case Instruction::Invoke: {
1533 if (
F->returnDoesNotAlias())
1539 if (!
F->hasExactDefinition())
1544 if (!
F->getReturnType()->isPointerTy())
1552 if (
F->returnDoesNotAlias() ||
1553 !
F->getReturnType()->isPointerTy())
1556 F->setReturnDoesNotAlias();
1570 bool &Speculative) {
1571 assert(
F->getReturnType()->isPointerTy() &&
1572 "nonnull only meaningful on pointer types");
1573 Speculative =
false;
1578 FlowsToReturn.
insert(Ret->getReturnValue());
1580 auto &
DL =
F->getDataLayout();
1582 for (
unsigned i = 0; i != FlowsToReturn.
size(); ++i) {
1583 Value *RetVal = FlowsToReturn[i];
1596 case Instruction::BitCast:
1597 case Instruction::AddrSpaceCast:
1600 case Instruction::GetElementPtr:
1606 case Instruction::Select: {
1608 FlowsToReturn.
insert(
SI->getTrueValue());
1609 FlowsToReturn.
insert(
SI->getFalseValue());
1612 case Instruction::PHI: {
1618 case Instruction::Call:
1619 case Instruction::Invoke: {
1624 if (Callee && SCCNodes.count(Callee)) {
1644 bool SCCReturnsNonNull =
true;
1650 if (
F->getAttributes().hasRetAttr(Attribute::NonNull))
1656 if (!
F->hasExactDefinition())
1661 if (!
F->getReturnType()->isPointerTy())
1664 bool Speculative =
false;
1670 <<
" as nonnull\n");
1671 F->addRetAttr(Attribute::NonNull);
1679 SCCReturnsNonNull =
false;
1682 if (SCCReturnsNonNull) {
1684 if (
F->getAttributes().hasRetAttr(Attribute::NonNull) ||
1685 !
F->getReturnType()->isPointerTy())
1688 LLVM_DEBUG(
dbgs() <<
"SCC marking " <<
F->getName() <<
" as nonnull\n");
1689 F->addRetAttr(Attribute::NonNull);
1703 AttributeList Attrs =
F->getAttributes();
1704 if (Attrs.hasRetAttr(Attribute::NoUndef))
1710 if (!
F->hasExactDefinition())
1716 if (
F->hasFnAttribute(Attribute::SanitizeMemory))
1719 if (
F->getReturnType()->isVoidTy())
1726 Value *RetVal = Ret->getReturnValue();
1733 if (Attrs.hasRetAttr(Attribute::NonNull) &&
1741 Attribute Attr = Attrs.getRetAttr(Attribute::Range);
1748 FPClassTest AttrFPClass = Attrs.getRetNoFPClass();
1749 if (AttrFPClass !=
fcNone) {
1757 F->addRetAttr(Attribute::NoUndef);
1772class AttributeInferer {
1775 struct InferenceDescriptor {
1781 std::function<bool(
const Function &)> SkipFunction;
1784 std::function<bool(Instruction &)> InstrBreaksAttribute;
1787 std::function<void(Function &)> SetAttribute;
1790 Attribute::AttrKind AKind;
1794 bool RequiresExactDefinition;
1796 InferenceDescriptor(Attribute::AttrKind AK,
1797 std::function<
bool(
const Function &)> SkipFunc,
1798 std::function<
bool(Instruction &)> InstrScan,
1799 std::function<
void(Function &)> SetAttr,
1801 : SkipFunction(SkipFunc), InstrBreaksAttribute(InstrScan),
1802 SetAttribute(SetAttr), AKind(AK),
1803 RequiresExactDefinition(ReqExactDef) {}
1810 void registerAttrInference(InferenceDescriptor AttrInference) {
1811 InferenceDescriptors.
push_back(AttrInference);
1814 void run(
const SCCNodeSet &SCCNodes, SmallPtrSet<Function *, 8> &
Changed);
1819void AttributeInferer::run(
const SCCNodeSet &SCCNodes,
1820 SmallPtrSet<Function *, 8> &
Changed) {
1825 for (Function *
F : SCCNodes) {
1828 if (InferInSCC.
empty())
1833 if (
ID.SkipFunction(*
F))
1838 return F->isDeclaration() ||
1839 (
ID.RequiresExactDefinition && !
F->hasExactDefinition());
1846 InferInSCC, std::back_inserter(InferInThisFunc),
1847 [
F](
const InferenceDescriptor &
ID) {
return !
ID.SkipFunction(*
F); });
1849 if (InferInThisFunc.empty())
1855 if (!
ID.InstrBreaksAttribute(
I))
1860 return D.AKind ==
ID.AKind;
1866 if (InferInThisFunc.empty())
1871 if (InferInSCC.
empty())
1874 for (Function *
F : SCCNodes)
1879 for (
auto &
ID : InferInSCC) {
1880 if (
ID.SkipFunction(*
F))
1883 ID.SetAttribute(*
F);
1887struct SCCNodesResult {
1888 SCCNodeSet SCCNodes;
1895 const SCCNodeSet &SCCNodes) {
1905 if (!
I.mayThrow(
true))
1908 if (
Function *Callee = CI->getCalledFunction()) {
1912 if (SCCNodes.contains(Callee))
1930 if (SCCNodes.contains(Callee))
1951 return !
SI->isUnordered();
1953 return !LI->isUnordered();
1980 if (!
MI->isVolatile())
1985 if (SCCNodes.contains(Callee))
1996 AttributeInferer AI;
2003 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
2004 Attribute::Convergent,
2006 [](
const Function &
F) {
return !
F.isConvergent(); },
2012 LLVM_DEBUG(
dbgs() <<
"Removing convergent attr from fn " <<
F.getName()
2014 F.setNotConvergent();
2027 AttributeInferer AI;
2035 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
2036 Attribute::NoUnwind,
2038 [](
const Function &
F) {
return F.doesNotThrow(); },
2045 <<
"Adding nounwind attr to fn " <<
F.getName() <<
"\n");
2046 F.setDoesNotThrow();
2058 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
2061 [](
const Function &
F) {
return F.doesNotFreeMemory(); },
2068 <<
"Adding nofree attr to fn " <<
F.getName() <<
"\n");
2069 F.setDoesNotFreeMemory();
2074 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
2077 [](
const Function &
F) {
return F.hasNoSync(); },
2084 <<
"Adding nosync attr to fn " <<
F.getName() <<
"\n");
2102 bool AnyFunctionsAddressIsTaken =
true) {
2103 for (
const auto &BB :
F) {
2104 for (
const auto &
I : BB) {
2107 if (!Callee || Callee == &
F)
2110 if (Callee->doesNotRecurse())
2113 if (!AnyFunctionsAddressIsTaken ||
2114 (Callee->isDeclaration() &&
2115 Callee->hasFnAttribute(Attribute::NoCallback)))
2129 if (SCCNodes.size() != 1)
2133 if (!
F || !
F->hasExactDefinition() ||
F->doesNotRecurse())
2139 F->setDoesNotRecurse();
2149 if (!
F || !
F->hasExactDefinition() ||
F->hasFnAttribute(Attribute::Naked) ||
2154 F->setDoesNotReturn();
2162 ColdPaths[&
F.front()] =
false;
2166 while (!Jobs.
empty()) {
2177 ColdPaths[BB] =
true;
2194 auto [Iter, Inserted] = ColdPaths.
try_emplace(Succ,
false);
2210 if (!
F || !
F->hasExactDefinition() ||
F->hasFnAttribute(Attribute::Naked) ||
2211 F->hasFnAttribute(Attribute::Cold) ||
F->hasFnAttribute(Attribute::Hot))
2216 F->addFnAttr(Attribute::Cold);
2228 if (!
F.hasExactDefinition())
2232 if (
F.mustProgress() &&
F.onlyReadsMemory())
2236 if (
F.isDeclaration())
2243 if (!Backedges.
empty())
2249 return I.willReturn();
2269 if (!
F ||
F->hasOptNone() ||
F->hasFnAttribute(Attribute::Naked) ||
2270 F->isPresplitCoroutine()) {
2275 Res.SCCNodes.insert(
F);
2280template <
typename AARGetterT>
2283 bool ArgAttrsOnly) {
2287 if (Nodes.SCCNodes.empty())
2331 bool ArgAttrsOnly =
false;
2332 if (
C.size() == 1 && SkipNonRecursive) {
2335 ArgAttrsOnly =
true;
2349 Functions.push_back(&
N.getFunction());
2352 auto ChangedFunctions =
2354 if (ChangedFunctions.empty())
2368 for (
auto *U :
Changed->users()) {
2371 FAM.invalidate(*
Call->getFunction(), FuncPA);
2387 OS, MapClassName2PassName);
2388 if (SkipNonRecursive)
2389 OS <<
"<skip-non-recursive-function-attrs>";
2392template <
typename AARGetterT>
2396 Functions.push_back(
I->getFunction());
2403 if (
F.doesNotRecurse())
2409 assert(!
F.isDeclaration() &&
"Cannot deduce norecurse without a definition!");
2410 assert(
F.hasInternalLinkage() &&
2411 "Can only do top-down deduction for internal linkage functions!");
2421 for (
auto &U :
F.uses()) {
2424 !CB->
getParent()->getParent()->doesNotRecurse())
2427 F.setDoesNotRecurse();
2433 assert(!
F.isDeclaration() &&
"Cannot deduce nofpclass without a definition!");
2434 unsigned NumArgs =
F.arg_size();
2439 for (
User *U :
F.users()) {
2445 for (
unsigned I = 0;
I != NumArgs; ++
I) {
2450 ArgsNoFPClass[
I] &= ~Cst->classify();
2458 if (RetNoFPClass !=
fcNone) {
2459 FPClassTest OldAttr =
F.getAttributes().getRetNoFPClass();
2460 if (OldAttr != RetNoFPClass) {
2466 for (
unsigned I = 0;
I != NumArgs; ++
I) {
2468 if (ArgNoFPClass ==
fcNone)
2471 if (OldAttr == ArgNoFPClass)
2494 if (SCC.size() != 1)
2496 Function &
F = SCC.begin()->getFunction();
2497 if (!
F.isDeclaration() &&
F.hasInternalLinkage() && !
F.use_empty())
2530 bool AnyFunctionsAddressIsTaken =
false;
2532 if (
F.isDeclaration() ||
F.doesNotRecurse())
2534 if (!
F.hasLocalLinkage() ||
F.hasAddressTaken()) {
2535 AnyFunctionsAddressIsTaken =
true;
2560 if (!
F.hasExactDefinition() ||
F.doesNotRecurse())
2567 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; 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)
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.
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.
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)
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...
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.
@ 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.
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.