70#define DEBUG_TYPE "function-attrs"
72STATISTIC(NumMemoryAttr,
"Number of functions with improved memory attribute");
73STATISTIC(NumCapturesNone,
"Number of arguments marked captures(none)");
74STATISTIC(NumCapturesPartial,
"Number of arguments marked with captures "
75 "attribute other than captures(none)");
76STATISTIC(NumReturned,
"Number of arguments marked returned");
77STATISTIC(NumReadNoneArg,
"Number of arguments marked readnone");
78STATISTIC(NumReadOnlyArg,
"Number of arguments marked readonly");
79STATISTIC(NumWriteOnlyArg,
"Number of arguments marked writeonly");
80STATISTIC(NumNoAlias,
"Number of function returns marked noalias");
81STATISTIC(NumNonNullReturn,
"Number of function returns marked nonnull");
82STATISTIC(NumNoUndefReturn,
"Number of function returns marked noundef");
83STATISTIC(NumNoRecurse,
"Number of functions marked as norecurse");
84STATISTIC(NumNoUnwind,
"Number of functions marked as nounwind");
85STATISTIC(NumNoFree,
"Number of functions marked as nofree");
86STATISTIC(NumWillReturn,
"Number of functions marked as willreturn");
87STATISTIC(NumNoSync,
"Number of functions marked as nosync");
88STATISTIC(NumCold,
"Number of functions marked as cold");
91 "Number of functions marked as norecurse during thinlink");
93 "Number of functions marked as nounwind during thinlink");
97 cl::desc(
"Try to propagate nonnull argument attributes from callsites to "
98 "caller functions."));
102 cl::desc(
"Stop inferring nounwind attribute during function-attrs pass"));
106 cl::desc(
"Stop inferring nofree attribute during function-attrs pass"));
110 cl::desc(
"Don't propagate function-attrs in thinLTO"));
116 ++NumCapturesPartial;
133 if (isa<AllocaInst>(UO))
135 if (isa<Argument>(UO)) {
149 for (
const Value *Arg : Call->args()) {
150 if (!Arg->getType()->isPtrOrPtrVectorTy())
171static std::pair<MemoryEffects, MemoryEffects>
173 const SCCNodeSet &SCCNodes) {
187 if (
F.getAttributes().hasAttrSomewhere(Attribute::InAlloca) ||
188 F.getAttributes().hasAttrSomewhere(Attribute::Preallocated))
195 if (
auto *Call = dyn_cast<CallBase>(&
I)) {
201 if (!Call->hasOperandBundles() && Call->getCalledFunction() &&
202 SCCNodes.count(Call->getCalledFunction())) {
205 addArgLocs(RecursiveArgME, Call, ModRefInfo::ModRef, AAR);
219 if (isa<PseudoProbeInst>(
I))
236 if (ArgMR != ModRefInfo::NoModRef)
242 if (
I.mayWriteToMemory())
243 MR |= ModRefInfo::Mod;
244 if (
I.mayReadFromMemory())
245 MR |= ModRefInfo::Ref;
246 if (MR == ModRefInfo::NoModRef)
264 return {OrigME & ME, RecursiveArgME};
273template <
typename AARGetterT>
284 auto [FnME, FnRecursiveArgME] =
287 RecursiveArgME |= FnRecursiveArgME;
295 if (ArgMR != ModRefInfo::NoModRef)
301 if (NewME != OldME) {
303 F->setMemoryEffects(NewME);
307 A.removeAttr(Attribute::Writable);
321 auto [It, Inserted] = CachedPrevailingSummary.
try_emplace(VI);
368 for (
const auto &GVS : VI.getSummaryList()) {
374 if (!FS || FS->fflags().HasUnknownCall)
377 const auto &Linkage = GVS->linkage();
382 <<
"ThinLTO FunctionAttrs: Multiple Local Linkage, bailing on "
384 << VI.name() <<
" from " << FS->modulePath() <<
". Previous module "
385 <<
Local->modulePath() <<
"\n");
390 assert(IsPrevailing(VI.getGUID(), GVS.get()));
397 if (IsPrevailing(VI.getGUID(), GVS.get())) {
407 auto &CPS = CachedPrevailingSummary[VI];
411 }
else if (Prevailing) {
429 bool Changed =
false;
431 auto PropagateAttributes = [&](std::vector<ValueInfo> &SCCNodes) {
434 InferredFlags.
NoRecurse = (SCCNodes.size() == 1);
437 for (
auto &V : SCCNodes) {
448 for (
const auto &Callee : CallerSummary->
calls()) {
450 Callee.first, CachedPrevailingSummary, IsPrevailing);
468 for (
auto &V : SCCNodes) {
470 LLVM_DEBUG(
dbgs() <<
"ThinLTO FunctionAttrs: Propagated NoRecurse to "
471 << V.name() <<
"\n");
472 ++NumThinLinkNoRecurse;
476 LLVM_DEBUG(
dbgs() <<
"ThinLTO FunctionAttrs: Propagated NoUnwind to "
477 << V.name() <<
"\n");
478 ++NumThinLinkNoUnwind;
481 for (
const auto &S : V.getSummaryList()) {
482 if (
auto *FS = dyn_cast<FunctionSummary>(S.get())) {
497 std::vector<ValueInfo> Nodes(*
I);
498 PropagateAttributes(Nodes);
508struct ArgumentGraphNode {
519 using ArgumentMapTy = std::map<Argument *, ArgumentGraphNode>;
521 ArgumentMapTy ArgumentMap;
529 ArgumentGraphNode SyntheticRoot;
532 ArgumentGraph() { SyntheticRoot.Definition =
nullptr; }
536 iterator
begin() {
return SyntheticRoot.Uses.begin(); }
537 iterator
end() {
return SyntheticRoot.Uses.end(); }
538 ArgumentGraphNode *getEntryNode() {
return &SyntheticRoot; }
540 ArgumentGraphNode *operator[](
Argument *
A) {
541 ArgumentGraphNode &
Node = ArgumentMap[
A];
543 SyntheticRoot.Uses.push_back(&
Node);
552 ArgumentUsesTracker(
const SCCNodeSet &SCCNodes) : SCCNodes(SCCNodes) {}
557 if (updateCaptureInfo(U, UseCI.
UseCC)) {
570 CallBase *CB = dyn_cast<CallBase>(
U->getUser());
572 if (isa<ReturnInst>(
U->getUser()))
582 if (!
F || !
F->hasExactDefinition() || !SCCNodes.count(
F)) {
601 if (UseIndex >=
F->arg_size()) {
602 assert(
F->isVarArg() &&
"More params than args in non-varargs call");
609 Uses.push_back(&*std::next(
F->arg_begin(), UseIndex));
619 const SCCNodeSet &SCCNodes;
627 std::optional<int64_t>
Offset;
634struct ArgumentAccessInfo {
636 AccessType ArgAccessType;
641struct UsesPerBlockInfo {
643 bool HasWrites =
false;
644 bool HasUnknownAccess =
false;
648struct ArgumentUsesSummary {
649 bool HasAnyWrite =
false;
650 bool HasWriteOutsideEntryBB =
false;
654ArgumentAccessInfo getArgumentAccessInfo(
const Instruction *
I,
655 const ArgumentUse &ArgUse,
657 auto GetTypeAccessRange =
659 std::optional<int64_t>
Offset) -> std::optional<ConstantRange> {
673 auto GetConstantIntRange =
675 std::optional<int64_t>
Offset) -> std::optional<ConstantRange> {
676 auto *ConstantLength = dyn_cast<ConstantInt>(
Length);
677 if (ConstantLength &&
Offset) {
678 int64_t
Len = ConstantLength->getSExtValue();
695 if (
auto *SI = dyn_cast<StoreInst>(
I)) {
696 if (
SI->isSimple() && &
SI->getOperandUse(1) == ArgUse.U) {
701 if (
auto TypeAccessRange =
702 GetTypeAccessRange(
SI->getAccessType(), ArgUse.Offset))
703 AccessRanges.
insert(*TypeAccessRange);
704 return {ArgumentAccessInfo::AccessType::Write, std::move(AccessRanges)};
706 }
else if (
auto *LI = dyn_cast<LoadInst>(
I)) {
707 if (LI->isSimple()) {
708 assert(&LI->getOperandUse(0) == ArgUse.U);
712 if (
auto TypeAccessRange =
713 GetTypeAccessRange(LI->getAccessType(), ArgUse.Offset))
714 return {ArgumentAccessInfo::AccessType::Read, {*TypeAccessRange}};
716 }
else if (
auto *MemSet = dyn_cast<MemSetInst>(
I)) {
717 if (!MemSet->isVolatile()) {
719 if (
auto AccessRange =
720 GetConstantIntRange(MemSet->getLength(), ArgUse.Offset))
721 AccessRanges.
insert(*AccessRange);
722 return {ArgumentAccessInfo::AccessType::Write, AccessRanges};
724 }
else if (
auto *MTI = dyn_cast<MemTransferInst>(
I)) {
725 if (!MTI->isVolatile()) {
726 if (&MTI->getOperandUse(0) == ArgUse.U) {
728 if (
auto AccessRange =
729 GetConstantIntRange(MTI->getLength(), ArgUse.Offset))
730 AccessRanges.
insert(*AccessRange);
731 return {ArgumentAccessInfo::AccessType::Write, AccessRanges};
732 }
else if (&MTI->getOperandUse(1) == ArgUse.U) {
733 if (
auto AccessRange =
734 GetConstantIntRange(MTI->getLength(), ArgUse.Offset))
735 return {ArgumentAccessInfo::AccessType::Read, {*AccessRange}};
738 }
else if (
auto *CB = dyn_cast<CallBase>(
I)) {
742 bool IsInitialize = CB->
paramHasAttr(ArgNo, Attribute::Initializes);
743 if (IsInitialize && ArgUse.Offset) {
747 ? ArgumentAccessInfo::AccessType::Write
748 : ArgumentAccessInfo::AccessType::WriteWithSideEffect;
754 CR.getUpper() + *ArgUse.Offset));
755 return {
Access, AccessRanges};
760 return {ArgumentAccessInfo::AccessType::Unknown, {}};
765 auto &
DL =
F.getParent()->getDataLayout();
767 DL.getIndexSizeInBits(
A.getType()->getPointerAddressSpace());
768 ArgumentUsesSummary
Result;
772 for (
Use &U :
A.uses())
778 auto *BB =
I->getParent();
779 auto &BBInfo =
Result.UsesPerBlock[BB];
780 auto [It,
Inserted] = BBInfo.Insts.try_emplace(
I);
781 auto &IInfo = It->second;
786 IInfo = {ArgumentAccessInfo::AccessType::Unknown, {}};
787 BBInfo.HasUnknownAccess =
true;
791 IInfo = std::move(Info);
792 BBInfo.HasUnknownAccess |=
793 IInfo.ArgAccessType == ArgumentAccessInfo::AccessType::Unknown;
795 (IInfo.ArgAccessType == ArgumentAccessInfo::AccessType::Write ||
796 IInfo.ArgAccessType ==
797 ArgumentAccessInfo::AccessType::WriteWithSideEffect) &&
798 !IInfo.AccessRanges.empty();
799 BBInfo.HasWrites |= InfoHasWrites;
800 return InfoHasWrites;
805 while (!Worklist.
empty()) {
807 User *
U = ArgUse.U->getUser();
810 if (
auto *
GEP = dyn_cast<GEPOperator>(U)) {
811 std::optional<int64_t> NewOffset = std::nullopt;
815 NewOffset = *ArgUse.Offset +
Offset.getSExtValue();
817 for (
Use &U :
GEP->uses())
822 auto *
I = cast<Instruction>(U);
823 bool HasWrite = UpdateUseInfo(
I, getArgumentAccessInfo(
I, ArgUse,
DL));
825 Result.HasAnyWrite |= HasWrite;
827 if (HasWrite &&
I->getParent() != &EntryBB)
828 Result.HasWriteOutsideEntryBB =
true;
867 if (
A->hasInAllocaAttr() ||
A->hasPreallocatedAttr())
871 bool IsWrite =
false;
873 for (
Use &U :
A->uses()) {
878 while (!Worklist.
empty()) {
879 if (IsWrite && IsRead)
886 switch (
I->getOpcode()) {
887 case Instruction::BitCast:
888 case Instruction::GetElementPtr:
889 case Instruction::PHI:
890 case Instruction::Select:
891 case Instruction::AddrSpaceCast:
893 for (
Use &UU :
I->uses())
894 if (Visited.
insert(&UU).second)
898 case Instruction::Call:
899 case Instruction::Invoke: {
918 if (Visited.
insert(&UU).second)
928 if (!
I->getType()->isVoidTy())
929 for (
Use &UU :
I->uses())
930 if (Visited.
insert(&UU).second)
940 SCCNodes.
count(
F->getArg(UseIndex)))
961 case Instruction::Load:
964 if (cast<LoadInst>(
I)->isVolatile())
970 case Instruction::Store:
971 if (cast<StoreInst>(
I)->getValueOperand() == *U)
977 if (cast<StoreInst>(
I)->isVolatile())
983 case Instruction::ICmp:
984 case Instruction::Ret:
992 if (IsWrite && IsRead)
995 return Attribute::ReadOnly;
997 return Attribute::WriteOnly;
999 return Attribute::ReadNone;
1010 if (!
F->hasExactDefinition())
1013 if (
F->getReturnType()->isVoidTy())
1017 if (
F->getAttributes().hasAttrSomewhere(Attribute::Returned))
1020 auto FindRetArg = [&]() ->
Argument * {
1023 if (
auto *Ret = dyn_cast<ReturnInst>(BB.getTerminator())) {
1027 dyn_cast<Argument>(Ret->getReturnValue()->stripPointerCasts());
1028 if (!RetVal || RetVal->getType() !=
F->getReturnType())
1033 else if (RetArg != RetVal)
1040 if (
Argument *RetArg = FindRetArg()) {
1041 RetArg->
addAttr(Attribute::Returned);
1056 bool Changed =
false;
1067 if (
auto *CB = dyn_cast<CallBase>(&
I)) {
1069 for (
auto &CSArg : CalledFunc->args()) {
1070 if (!CSArg.hasNonNullAttr(
false))
1076 auto *FArg = dyn_cast<Argument>(CB->
getArgOperand(CSArg.getArgNo()));
1077 if (FArg && !FArg->hasNonNullAttr()) {
1078 FArg->addAttr(Attribute::NonNull);
1092 assert((R == Attribute::ReadOnly || R == Attribute::ReadNone ||
1093 R == Attribute::WriteOnly)
1094 &&
"Must be an access attribute.");
1095 assert(
A &&
"Argument must not be null.");
1098 if (
A->hasAttribute(R))
1103 A->removeAttr(Attribute::WriteOnly);
1104 A->removeAttr(Attribute::ReadOnly);
1105 A->removeAttr(Attribute::ReadNone);
1107 if (R == Attribute::ReadNone || R == Attribute::ReadOnly)
1108 A->removeAttr(Attribute::Writable);
1110 if (R == Attribute::ReadOnly)
1112 else if (R == Attribute::WriteOnly)
1120 auto ArgumentUses = collectArgumentUsesPerBlock(
A,
F);
1122 if (!ArgumentUses.HasAnyWrite)
1125 auto &UsesPerBlock = ArgumentUses.UsesPerBlock;
1134 auto UPB = UsesPerBlock.find(BB);
1141 if (UPB == UsesPerBlock.end() || !UPB->second.HasUnknownAccess) {
1142 bool HasAddedSuccessor =
false;
1144 if (
auto SuccI = Initialized.
find(Succ); SuccI != Initialized.
end()) {
1145 if (HasAddedSuccessor) {
1148 CRL = SuccI->second;
1149 HasAddedSuccessor =
true;
1158 if (UPB != UsesPerBlock.end()) {
1162 sort(Insts, [](std::pair<Instruction *, ArgumentAccessInfo> &
LHS,
1163 std::pair<Instruction *, ArgumentAccessInfo> &
RHS) {
1164 return LHS.first->comesBefore(
RHS.first);
1170 if (
Info.ArgAccessType == ArgumentAccessInfo::AccessType::Unknown ||
1171 Info.ArgAccessType ==
1172 ArgumentAccessInfo::AccessType::WriteWithSideEffect)
1174 if (!
Info.AccessRanges.empty()) {
1175 if (
Info.ArgAccessType == ArgumentAccessInfo::AccessType::Write ||
1176 Info.ArgAccessType ==
1177 ArgumentAccessInfo::AccessType::WriteWithSideEffect) {
1180 assert(
Info.ArgAccessType == ArgumentAccessInfo::AccessType::Read);
1181 for (
const auto &ReadRange :
Info.AccessRanges)
1193 bool OnlyScanEntryBlock = !ArgumentUses.HasWriteOutsideEntryBB;
1194 if (!OnlyScanEntryBlock)
1195 if (
auto EntryUPB = UsesPerBlock.find(&EntryBB);
1196 EntryUPB != UsesPerBlock.end())
1197 OnlyScanEntryBlock = EntryUPB->second.HasUnknownAccess;
1198 if (OnlyScanEntryBlock) {
1199 EntryCRL = VisitBlock(&EntryBB);
1200 if (EntryCRL.
empty())
1211 Initialized[BB] = CRL;
1214 auto EntryCRLI = Initialized.
find(&EntryBB);
1215 if (EntryCRLI == Initialized.
end())
1218 EntryCRL = EntryCRLI->second;
1222 "should have bailed already if EntryCRL is empty");
1224 if (
A.hasAttribute(Attribute::Initializes)) {
1226 A.getAttribute(Attribute::Initializes).getValueAsConstantRangeList();
1227 if (PreviousCRL == EntryCRL)
1229 EntryCRL = EntryCRL.
unionWith(PreviousCRL);
1241 bool SkipInitializes) {
1244 auto DetermineAccessAttrsForSingleton = [](
Argument *
A) {
1259 if (!
F->hasExactDefinition())
1267 if (
F->onlyReadsMemory() &&
F->doesNotThrow() &&
F->willReturn() &&
1268 F->getReturnType()->isVoidTy()) {
1270 if (
A.getType()->isPointerTy() && !
A.hasNoCaptureAttr()) {
1281 if (!
A.getType()->isPointerTy())
1283 bool HasNonLocalUses =
false;
1284 CaptureInfo OrigCI =
A.getAttributes().getCaptureInfo();
1286 ArgumentUsesTracker Tracker(SCCNodes);
1289 if (NewCI != OrigCI) {
1290 if (Tracker.Uses.empty()) {
1299 ArgumentGraphNode *
Node = AG[&
A];
1302 Node->Uses.push_back(AG[
Use]);
1304 HasNonLocalUses =
true;
1310 if (!HasNonLocalUses && !
A.onlyReadsMemory()) {
1315 if (DetermineAccessAttrsForSingleton(&
A))
1318 if (!SkipInitializes && !
A.onlyReadsMemory()) {
1333 const std::vector<ArgumentGraphNode *> &ArgumentSCC = *
I;
1334 if (ArgumentSCC.size() == 1) {
1335 if (!ArgumentSCC[0]->Definition)
1339 if (ArgumentSCC[0]->
Uses.size() == 1 &&
1340 ArgumentSCC[0]->Uses[0] == ArgumentSCC[0]) {
1341 Argument *
A = ArgumentSCC[0]->Definition;
1342 CaptureInfo OrigCI =
A->getAttributes().getCaptureInfo();
1344 if (NewCI != OrigCI) {
1347 Changed.
insert(
A->getParent());
1351 if (DetermineAccessAttrsForSingleton(
A))
1352 Changed.
insert(
A->getParent());
1360 for (ArgumentGraphNode *
I : ArgumentSCC) {
1361 ArgumentSCCNodes.
insert(
I->Definition);
1368 for (ArgumentGraphNode *
N : ArgumentSCC) {
1369 for (ArgumentGraphNode *
Use :
N->Uses) {
1371 if (ArgumentSCCNodes.
count(
A))
1382 for (ArgumentGraphNode *
N : ArgumentSCC) {
1384 CaptureInfo OrigCI =
A->getAttributes().getCaptureInfo();
1386 if (NewCI != OrigCI) {
1389 Changed.
insert(
A->getParent());
1397 for (ArgumentGraphNode *
N : ArgumentSCC) {
1398 if (DetermineAccessAttrsForSingleton(
N->Definition))
1399 Changed.
insert(
N->Definition->getParent());
1418 if (
A == Attribute::ReadNone)
1420 if (
B == Attribute::ReadNone)
1426 for (ArgumentGraphNode *
N : ArgumentSCC) {
1429 AccessAttr = meetAccessAttr(AccessAttr, K);
1435 for (ArgumentGraphNode *
N : ArgumentSCC) {
1438 Changed.
insert(
A->getParent());
1451 if (
ReturnInst *Ret = dyn_cast<ReturnInst>(BB.getTerminator()))
1452 FlowsToReturn.
insert(Ret->getReturnValue());
1454 for (
unsigned i = 0; i != FlowsToReturn.
size(); ++i) {
1455 Value *RetVal = FlowsToReturn[i];
1457 if (
Constant *
C = dyn_cast<Constant>(RetVal)) {
1458 if (!
C->isNullValue() && !isa<UndefValue>(
C))
1464 if (isa<Argument>(RetVal))
1467 if (
Instruction *RVI = dyn_cast<Instruction>(RetVal))
1468 switch (RVI->getOpcode()) {
1470 case Instruction::BitCast:
1471 case Instruction::GetElementPtr:
1472 case Instruction::AddrSpaceCast:
1473 FlowsToReturn.
insert(RVI->getOperand(0));
1475 case Instruction::Select: {
1477 FlowsToReturn.
insert(SI->getTrueValue());
1478 FlowsToReturn.
insert(SI->getFalseValue());
1481 case Instruction::PHI: {
1482 PHINode *PN = cast<PHINode>(RVI);
1488 case Instruction::Alloca:
1490 case Instruction::Call:
1491 case Instruction::Invoke: {
1492 CallBase &CB = cast<CallBase>(*RVI);
1517 if (
F->returnDoesNotAlias())
1523 if (!
F->hasExactDefinition())
1528 if (!
F->getReturnType()->isPointerTy())
1536 if (
F->returnDoesNotAlias() ||
1537 !
F->getReturnType()->isPointerTy())
1540 F->setReturnDoesNotAlias();
1554 bool &Speculative) {
1555 assert(
F->getReturnType()->isPointerTy() &&
1556 "nonnull only meaningful on pointer types");
1557 Speculative =
false;
1561 if (
auto *Ret = dyn_cast<ReturnInst>(BB.getTerminator()))
1562 FlowsToReturn.
insert(Ret->getReturnValue());
1564 auto &
DL =
F->getDataLayout();
1566 for (
unsigned i = 0; i != FlowsToReturn.
size(); ++i) {
1567 Value *RetVal = FlowsToReturn[i];
1580 case Instruction::BitCast:
1581 case Instruction::AddrSpaceCast:
1584 case Instruction::GetElementPtr:
1585 if (cast<GEPOperator>(RVI)->isInBounds()) {
1590 case Instruction::Select: {
1592 FlowsToReturn.
insert(SI->getTrueValue());
1593 FlowsToReturn.
insert(SI->getFalseValue());
1596 case Instruction::PHI: {
1597 PHINode *PN = cast<PHINode>(RVI);
1602 case Instruction::Call:
1603 case Instruction::Invoke: {
1604 CallBase &CB = cast<CallBase>(*RVI);
1608 if (Callee && SCCNodes.count(Callee)) {
1628 bool SCCReturnsNonNull =
true;
1634 if (
F->getAttributes().hasRetAttr(Attribute::NonNull))
1640 if (!
F->hasExactDefinition())
1645 if (!
F->getReturnType()->isPointerTy())
1648 bool Speculative =
false;
1654 <<
" as nonnull\n");
1655 F->addRetAttr(Attribute::NonNull);
1663 SCCReturnsNonNull =
false;
1666 if (SCCReturnsNonNull) {
1668 if (
F->getAttributes().hasRetAttr(Attribute::NonNull) ||
1669 !
F->getReturnType()->isPointerTy())
1672 LLVM_DEBUG(
dbgs() <<
"SCC marking " <<
F->getName() <<
" as nonnull\n");
1673 F->addRetAttr(Attribute::NonNull);
1688 if (Attrs.hasRetAttr(Attribute::NoUndef))
1694 if (!
F->hasExactDefinition())
1700 if (
F->hasFnAttribute(Attribute::SanitizeMemory))
1703 if (
F->getReturnType()->isVoidTy())
1710 Value *RetVal = Ret->getReturnValue();
1711 if (!isGuaranteedNotToBeUndefOrPoison(RetVal))
1717 if (Attrs.hasRetAttr(Attribute::NonNull) &&
1718 !isKnownNonZero(RetVal, DL))
1721 if (MaybeAlign Align = Attrs.getRetAlignment())
1722 if (RetVal->getPointerAlignment(DL) < *Align)
1725 Attribute Attr = Attrs.getRetAttr(Attribute::Range);
1726 if (Attr.isValid() &&
1727 !Attr.getRange().contains(
1728 computeConstantRange(RetVal, false)))
1733 F->addRetAttr(Attribute::NoUndef);
1748class AttributeInferer {
1751 struct InferenceDescriptor {
1763 std::function<void(
Function &)> SetAttribute;
1770 bool RequiresExactDefinition;
1773 std::function<
bool(
const Function &)> SkipFunc,
1775 std::function<
void(
Function &)> SetAttr,
1777 : SkipFunction(SkipFunc), InstrBreaksAttribute(InstrScan),
1778 SetAttribute(SetAttr), AKind(AK),
1779 RequiresExactDefinition(ReqExactDef) {}
1786 void registerAttrInference(InferenceDescriptor AttrInference) {
1787 InferenceDescriptors.
push_back(AttrInference);
1795void AttributeInferer::run(
const SCCNodeSet &SCCNodes,
1804 if (InferInSCC.
empty())
1809 if (
ID.SkipFunction(*
F))
1814 return F->isDeclaration() ||
1815 (
ID.RequiresExactDefinition && !
F->hasExactDefinition());
1822 InferInSCC, std::back_inserter(InferInThisFunc),
1823 [
F](
const InferenceDescriptor &
ID) {
return !
ID.SkipFunction(*
F); });
1825 if (InferInThisFunc.empty())
1831 if (!
ID.InstrBreaksAttribute(
I))
1836 return D.AKind == ID.AKind;
1842 if (InferInThisFunc.empty())
1847 if (InferInSCC.
empty())
1855 for (
auto &
ID : InferInSCC) {
1856 if (
ID.SkipFunction(*
F))
1859 ID.SetAttribute(*
F);
1863struct SCCNodesResult {
1864 SCCNodeSet SCCNodes;
1871 const SCCNodeSet &SCCNodes) {
1872 const CallBase *CB = dyn_cast<CallBase>(&
I);
1881 if (!
I.mayThrow(
true))
1883 if (
const auto *CI = dyn_cast<CallInst>(&
I)) {
1884 if (
Function *Callee = CI->getCalledFunction()) {
1888 if (SCCNodes.contains(Callee))
1906 if (SCCNodes.contains(Callee))
1921 if (
auto *FI = dyn_cast<FenceInst>(
I))
1924 else if (isa<AtomicCmpXchgInst>(
I) || isa<AtomicRMWInst>(
I))
1926 else if (
auto *SI = dyn_cast<StoreInst>(
I))
1927 return !SI->isUnordered();
1928 else if (
auto *LI = dyn_cast<LoadInst>(
I))
1929 return !LI->isUnordered();
1944 auto *CB = dyn_cast<CallBase>(&
I);
1955 if (
auto *
MI = dyn_cast<MemIntrinsic>(&
I))
1956 if (!
MI->isVolatile())
1961 if (SCCNodes.contains(Callee))
1972 AttributeInferer AI;
1979 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
1980 Attribute::Convergent,
1982 [](
const Function &
F) {
return !
F.isConvergent(); },
1988 LLVM_DEBUG(
dbgs() <<
"Removing convergent attr from fn " <<
F.getName()
1990 F.setNotConvergent();
1994 AI.run(SCCNodes, Changed);
2003 AttributeInferer AI;
2011 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
2012 Attribute::NoUnwind,
2014 [](
const Function &
F) {
return F.doesNotThrow(); },
2021 <<
"Adding nounwind attr to fn " <<
F.getName() <<
"\n");
2022 F.setDoesNotThrow();
2034 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
2037 [](
const Function &
F) {
return F.doesNotFreeMemory(); },
2044 <<
"Adding nofree attr to fn " <<
F.getName() <<
"\n");
2045 F.setDoesNotFreeMemory();
2050 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
2053 [](
const Function &
F) {
return F.hasNoSync(); },
2060 <<
"Adding nosync attr to fn " <<
F.getName() <<
"\n");
2067 AI.run(SCCNodes, Changed);
2075 if (SCCNodes.size() != 1)
2079 if (!
F || !
F->hasExactDefinition() ||
F->doesNotRecurse())
2086 for (
auto &
I : BB.instructionsWithoutDebug())
2087 if (
auto *CB = dyn_cast<CallBase>(&
I)) {
2089 if (!Callee || Callee ==
F ||
2090 (!Callee->doesNotRecurse() &&
2091 !(Callee->isDeclaration() &&
2092 Callee->hasFnAttribute(Attribute::NoCallback))))
2100 F->setDoesNotRecurse();
2109 if (!
F || !
F->hasExactDefinition() ||
F->hasFnAttribute(Attribute::Naked) ||
2114 F->setDoesNotReturn();
2122 ColdPaths[&
F.front()] =
false;
2126 while (!Jobs.
empty()) {
2133 if (
auto *CB = dyn_cast<CallBase>(&
I))
2137 ColdPaths[BB] =
true;
2154 auto [Iter, Inserted] = ColdPaths.
try_emplace(Succ,
false);
2170 if (!
F || !
F->hasExactDefinition() ||
F->hasFnAttribute(Attribute::Naked) ||
2171 F->hasFnAttribute(Attribute::Cold) ||
F->hasFnAttribute(Attribute::Hot))
2176 F->addFnAttr(Attribute::Cold);
2188 if (!
F.hasExactDefinition())
2192 if (
F.mustProgress() &&
F.onlyReadsMemory())
2196 if (
F.isDeclaration())
2203 if (!Backedges.
empty())
2209 return I.willReturn();
2229 if (!
F ||
F->hasOptNone() ||
F->hasFnAttribute(Attribute::Naked) ||
2230 F->isPresplitCoroutine()) {
2235 Res.SCCNodes.insert(
F);
2240template <
typename AARGetterT>
2243 bool ArgAttrsOnly) {
2247 if (Nodes.SCCNodes.empty())
2291 bool ArgAttrsOnly =
false;
2292 if (
C.size() == 1 && SkipNonRecursive) {
2295 ArgAttrsOnly =
true;
2312 auto ChangedFunctions =
2314 if (ChangedFunctions.empty())
2322 for (
Function *Changed : ChangedFunctions) {
2328 for (
auto *U : Changed->users()) {
2329 if (
auto *Call = dyn_cast<CallBase>(U)) {
2330 if (Call->getCalledOperand() == Changed)
2347 OS, MapClassName2PassName);
2348 if (SkipNonRecursive)
2349 OS <<
"<skip-non-recursive-function-attrs>";
2352template <
typename AARGetterT>
2366 assert(!
F.isDeclaration() &&
"Cannot deduce norecurse without a definition!");
2368 "This function has already been deduced as norecurs!");
2369 assert(
F.hasInternalLinkage() &&
2370 "Can only do top-down deduction for internal linkage functions!");
2380 for (
auto &U :
F.uses()) {
2381 auto *
I = dyn_cast<Instruction>(U.getUser());
2386 !CB->
getParent()->getParent()->doesNotRecurse())
2389 F.setDoesNotRecurse();
2407 if (SCC.size() != 1)
2409 Function &
F = SCC.begin()->getFunction();
2410 if (!
F.isDeclaration() && !
F.doesNotRecurse() &&
F.hasInternalLinkage())
2414 bool Changed =
false;
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< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
This header provides classes for managing passes over SCCs of the call graph.
Analysis containing CSE Info
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)
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 void addNoReturnAttrs(const SCCNodeSet &SCCNodes, SmallPtrSet< Function *, 8 > &Changed)
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 cl::opt< bool > EnableNonnullArgPropagation("enable-nonnull-arg-prop", cl::init(true), cl::Hidden, cl::desc("Try to propagate nonnull argument attributes from callsites to " "caller functions."))
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 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
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.
A private abstract base class describing the concept of an individual alias analysis implementation.
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 <a particular IR unit>" (e....
A container for analyses that lazily runs them and caches their results.
void invalidate(IRUnitT &IR, const PreservedAnalyses &PA)
Invalidate cached analyses for an IR unit.
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.
LLVM_ABI void addAttr(Attribute::AttrKind Kind)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
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.
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)
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 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.
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)
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.
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)
Create MemoryEffectsBase that can only access argument memory.
static MemoryEffectsBase inaccessibleMemOnly(ModRefInfo MR=ModRefInfo::ModRef)
Create MemoryEffectsBase that can only access inaccessible memory.
ModRefInfo getModRef(Location Loc) const
Get ModRefInfo for the given Location.
static MemoryEffectsBase none()
Create MemoryEffectsBase that cannot read or write any memory.
static MemoryEffectsBase unknown()
Create MemoryEffectsBase that can read and write any memory.
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...
const Value * Ptr
The address of the start of the location.
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.
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.
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.
@ C
The default llvm calling convention, compatible with C.
@ 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.
LLVM_ABI const_iterator begin(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get begin iterator over path.
LLVM_ABI const_iterator end(StringRef path LLVM_LIFETIME_BOUND)
Get end iterator over path.
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.
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)
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.
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)
MemoryEffectsBase< IRMemLocation > MemoryEffects
Summary of how a function affects memory in the program.
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.
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.
@ 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 isGuaranteedToTransferExecutionToSuccessor(const Instruction *I)
Return true if this function can prove that the instruction I will always transfer execution to one o...
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...
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)
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.
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.
@ ContinueIgnoringReturn
Continue traversal, but do not follow the return value of the user, even if it has additional capture...
@ Continue
Continue traversal, and also follow the return value of the user if it has additional capture compone...
@ Stop
Stop the traversal.
virtual Action captured(const Use *U, UseCaptureInfo CI)=0
Use U directly captures CI.UseCC and additionally CI.ResultCC through the return value of the user of...
virtual void tooManyUses()=0
tooManyUses - The depth of traversal has breached a limit.
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)
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)
Capture information for a specific Use.
CaptureComponents UseCC
Components captured by this use.
Struct that holds a reference to a particular GUID in a global value summary.