69#define DEBUG_TYPE "function-attrs"
71STATISTIC(NumMemoryAttr,
"Number of functions with improved memory attribute");
72STATISTIC(NumNoCapture,
"Number of arguments marked nocapture");
73STATISTIC(NumReturned,
"Number of arguments marked returned");
74STATISTIC(NumReadNoneArg,
"Number of arguments marked readnone");
75STATISTIC(NumReadOnlyArg,
"Number of arguments marked readonly");
76STATISTIC(NumWriteOnlyArg,
"Number of arguments marked writeonly");
77STATISTIC(NumNoAlias,
"Number of function returns marked noalias");
78STATISTIC(NumNonNullReturn,
"Number of function returns marked nonnull");
79STATISTIC(NumNoUndefReturn,
"Number of function returns marked noundef");
80STATISTIC(NumNoRecurse,
"Number of functions marked as norecurse");
81STATISTIC(NumNoUnwind,
"Number of functions marked as nounwind");
82STATISTIC(NumNoFree,
"Number of functions marked as nofree");
83STATISTIC(NumWillReturn,
"Number of functions marked as willreturn");
84STATISTIC(NumNoSync,
"Number of functions marked as nosync");
87 "Number of functions marked as norecurse during thinlink");
89 "Number of functions marked as nounwind during thinlink");
93 cl::desc(
"Try to propagate nonnull argument attributes from callsites to "
94 "caller functions."));
98 cl::desc(
"Stop inferring nounwind attribute during function-attrs pass"));
102 cl::desc(
"Stop inferring nofree attribute during function-attrs pass"));
106 cl::desc(
"Don't propagate function-attrs in thinLTO"));
122 if (isa<AllocaInst>(UO))
124 if (isa<Argument>(UO)) {
137 for (
const Value *Arg : Call->args()) {
138 if (!Arg->getType()->isPtrOrPtrVectorTy())
159static std::pair<MemoryEffects, MemoryEffects>
161 const SCCNodeSet &SCCNodes) {
175 if (
F.getAttributes().hasAttrSomewhere(Attribute::InAlloca) ||
176 F.getAttributes().hasAttrSomewhere(Attribute::Preallocated))
183 if (
auto *Call = dyn_cast<CallBase>(&
I)) {
189 if (!Call->hasOperandBundles() && Call->getCalledFunction() &&
190 SCCNodes.count(Call->getCalledFunction())) {
193 addArgLocs(RecursiveArgME, Call, ModRefInfo::ModRef, AAR);
207 if (isa<PseudoProbeInst>(
I))
221 if (ArgMR != ModRefInfo::NoModRef)
227 if (
I.mayWriteToMemory())
228 MR |= ModRefInfo::Mod;
229 if (
I.mayReadFromMemory())
230 MR |= ModRefInfo::Ref;
231 if (MR == ModRefInfo::NoModRef)
249 return {OrigME & ME, RecursiveArgME};
258template <
typename AARGetterT>
269 auto [FnME, FnRecursiveArgME] =
272 RecursiveArgME |= FnRecursiveArgME;
280 if (ArgMR != ModRefInfo::NoModRef)
286 if (NewME != OldME) {
288 F->setMemoryEffects(NewME);
292 A.removeAttr(Attribute::Writable);
306 if (CachedPrevailingSummary.
count(VI))
307 return CachedPrevailingSummary[VI];
349 CachedPrevailingSummary[VI] =
nullptr;
353 for (
const auto &GVS : VI.getSummaryList()) {
359 if (!FS || FS->fflags().HasUnknownCall)
362 const auto &Linkage = GVS->linkage();
367 <<
"ThinLTO FunctionAttrs: Multiple Local Linkage, bailing on "
369 << VI.name() <<
" from " << FS->modulePath() <<
". Previous module "
370 << Local->modulePath() <<
"\n");
375 assert(IsPrevailing(VI.getGUID(), GVS.get()));
382 if (IsPrevailing(VI.getGUID(), GVS.get())) {
394 CachedPrevailingSummary[VI] = Local;
395 }
else if (Prevailing) {
397 CachedPrevailingSummary[VI] = Prevailing;
400 return CachedPrevailingSummary[VI];
413 bool Changed =
false;
415 auto PropagateAttributes = [&](std::vector<ValueInfo> &SCCNodes) {
418 InferredFlags.
NoRecurse = (SCCNodes.size() == 1);
421 for (
auto &V : SCCNodes) {
432 for (
const auto &Callee : CallerSummary->
calls()) {
434 Callee.first, CachedPrevailingSummary, IsPrevailing);
452 for (
auto &V : SCCNodes) {
454 LLVM_DEBUG(
dbgs() <<
"ThinLTO FunctionAttrs: Propagated NoRecurse to "
455 << V.name() <<
"\n");
456 ++NumThinLinkNoRecurse;
460 LLVM_DEBUG(
dbgs() <<
"ThinLTO FunctionAttrs: Propagated NoUnwind to "
461 << V.name() <<
"\n");
462 ++NumThinLinkNoUnwind;
465 for (
const auto &S : V.getSummaryList()) {
466 if (
auto *FS = dyn_cast<FunctionSummary>(S.get())) {
481 std::vector<ValueInfo> Nodes(*
I);
482 PropagateAttributes(Nodes);
492struct ArgumentGraphNode {
500 using ArgumentMapTy = std::map<Argument *, ArgumentGraphNode>;
502 ArgumentMapTy ArgumentMap;
510 ArgumentGraphNode SyntheticRoot;
513 ArgumentGraph() { SyntheticRoot.Definition =
nullptr; }
517 iterator
begin() {
return SyntheticRoot.Uses.begin(); }
518 iterator
end() {
return SyntheticRoot.Uses.end(); }
519 ArgumentGraphNode *getEntryNode() {
return &SyntheticRoot; }
521 ArgumentGraphNode *operator[](
Argument *
A) {
522 ArgumentGraphNode &
Node = ArgumentMap[
A];
524 SyntheticRoot.Uses.push_back(&
Node);
533 ArgumentUsesTracker(
const SCCNodeSet &SCCNodes) : SCCNodes(SCCNodes) {}
538 CallBase *CB = dyn_cast<CallBase>(
U->getUser());
545 if (!
F || !
F->hasExactDefinition() || !SCCNodes.count(
F)) {
564 if (UseIndex >=
F->arg_size()) {
565 assert(
F->isVarArg() &&
"More params than args in non-varargs call");
570 Uses.push_back(&*std::next(
F->arg_begin(), UseIndex));
575 bool Captured =
false;
580 const SCCNodeSet &SCCNodes;
617 if (
A->hasInAllocaAttr() ||
A->hasPreallocatedAttr())
621 bool IsWrite =
false;
623 for (
Use &U :
A->uses()) {
628 while (!Worklist.
empty()) {
629 if (IsWrite && IsRead)
636 switch (
I->getOpcode()) {
637 case Instruction::BitCast:
638 case Instruction::GetElementPtr:
639 case Instruction::PHI:
640 case Instruction::Select:
641 case Instruction::AddrSpaceCast:
643 for (
Use &UU :
I->uses())
644 if (Visited.
insert(&UU).second)
648 case Instruction::Call:
649 case Instruction::Invoke: {
668 if (Visited.
insert(&UU).second)
678 if (!
I->getType()->isVoidTy())
679 for (
Use &UU :
I->uses())
680 if (Visited.
insert(&UU).second)
690 SCCNodes.
count(
F->getArg(UseIndex)))
711 case Instruction::Load:
714 if (cast<LoadInst>(
I)->isVolatile())
720 case Instruction::Store:
721 if (cast<StoreInst>(
I)->getValueOperand() == *U)
727 if (cast<StoreInst>(
I)->isVolatile())
733 case Instruction::ICmp:
734 case Instruction::Ret:
742 if (IsWrite && IsRead)
745 return Attribute::ReadOnly;
747 return Attribute::WriteOnly;
749 return Attribute::ReadNone;
760 if (!
F->hasExactDefinition())
763 if (
F->getReturnType()->isVoidTy())
767 if (
F->getAttributes().hasAttrSomewhere(Attribute::Returned))
770 auto FindRetArg = [&]() ->
Argument * {
773 if (
auto *Ret = dyn_cast<ReturnInst>(BB.getTerminator())) {
777 dyn_cast<Argument>(Ret->getReturnValue()->stripPointerCasts());
778 if (!RetVal || RetVal->getType() !=
F->getReturnType())
783 else if (RetArg != RetVal)
790 if (
Argument *RetArg = FindRetArg()) {
791 RetArg->
addAttr(Attribute::Returned);
806 bool Changed =
false;
817 if (
auto *CB = dyn_cast<CallBase>(&
I)) {
819 for (
auto &CSArg : CalledFunc->args()) {
820 if (!CSArg.hasNonNullAttr(
false))
826 auto *FArg = dyn_cast<Argument>(CB->
getArgOperand(CSArg.getArgNo()));
827 if (FArg && !FArg->hasNonNullAttr()) {
828 FArg->addAttr(Attribute::NonNull);
842 assert((R == Attribute::ReadOnly || R == Attribute::ReadNone ||
843 R == Attribute::WriteOnly)
844 &&
"Must be an access attribute.");
845 assert(
A &&
"Argument must not be null.");
848 if (
A->hasAttribute(R))
853 A->removeAttr(Attribute::WriteOnly);
854 A->removeAttr(Attribute::ReadOnly);
855 A->removeAttr(Attribute::ReadNone);
857 if (R == Attribute::ReadNone || R == Attribute::ReadOnly)
858 A->removeAttr(Attribute::Writable);
860 if (R == Attribute::ReadOnly)
862 else if (R == Attribute::WriteOnly)
880 if (!
F->hasExactDefinition())
888 if (
F->onlyReadsMemory() &&
F->doesNotThrow() &&
889 F->getReturnType()->isVoidTy()) {
891 if (
A.getType()->isPointerTy() && !
A.hasNoCaptureAttr()) {
892 A.addAttr(Attribute::NoCapture);
901 if (!
A.getType()->isPointerTy())
903 bool HasNonLocalUses =
false;
904 if (!
A.hasNoCaptureAttr()) {
905 ArgumentUsesTracker Tracker(SCCNodes);
907 if (!Tracker.Captured) {
908 if (Tracker.Uses.empty()) {
910 A.addAttr(Attribute::NoCapture);
917 ArgumentGraphNode *
Node = AG[&
A];
921 HasNonLocalUses =
true;
927 if (!HasNonLocalUses && !
A.onlyReadsMemory()) {
950 const std::vector<ArgumentGraphNode *> &ArgumentSCC = *
I;
951 if (ArgumentSCC.size() == 1) {
952 if (!ArgumentSCC[0]->Definition)
956 if (ArgumentSCC[0]->
Uses.size() == 1 &&
957 ArgumentSCC[0]->Uses[0] == ArgumentSCC[0]) {
958 Argument *
A = ArgumentSCC[0]->Definition;
959 A->addAttr(Attribute::NoCapture);
961 Changed.
insert(
A->getParent());
973 bool SCCCaptured =
false;
974 for (ArgumentGraphNode *
Node : ArgumentSCC) {
975 if (
Node->Uses.empty() && !
Node->Definition->hasNoCaptureAttr()) {
986 for (ArgumentGraphNode *
I : ArgumentSCC) {
987 ArgumentSCCNodes.
insert(
I->Definition);
990 for (ArgumentGraphNode *
N : ArgumentSCC) {
991 for (ArgumentGraphNode *
Use :
N->Uses) {
993 if (
A->hasNoCaptureAttr() || ArgumentSCCNodes.
count(
A))
1004 for (ArgumentGraphNode *
N : ArgumentSCC) {
1006 A->addAttr(Attribute::NoCapture);
1008 Changed.
insert(
A->getParent());
1025 if (
A == Attribute::ReadNone)
1027 if (
B == Attribute::ReadNone)
1033 for (ArgumentGraphNode *
N : ArgumentSCC) {
1036 AccessAttr = meetAccessAttr(AccessAttr, K);
1042 for (ArgumentGraphNode *
N : ArgumentSCC) {
1045 Changed.
insert(
A->getParent());
1058 if (
ReturnInst *Ret = dyn_cast<ReturnInst>(BB.getTerminator()))
1059 FlowsToReturn.
insert(Ret->getReturnValue());
1061 for (
unsigned i = 0; i != FlowsToReturn.
size(); ++i) {
1062 Value *RetVal = FlowsToReturn[i];
1064 if (
Constant *
C = dyn_cast<Constant>(RetVal)) {
1065 if (!
C->isNullValue() && !isa<UndefValue>(
C))
1071 if (isa<Argument>(RetVal))
1074 if (
Instruction *RVI = dyn_cast<Instruction>(RetVal))
1075 switch (RVI->getOpcode()) {
1077 case Instruction::BitCast:
1078 case Instruction::GetElementPtr:
1079 case Instruction::AddrSpaceCast:
1080 FlowsToReturn.
insert(RVI->getOperand(0));
1082 case Instruction::Select: {
1084 FlowsToReturn.
insert(SI->getTrueValue());
1085 FlowsToReturn.
insert(SI->getFalseValue());
1088 case Instruction::PHI: {
1089 PHINode *PN = cast<PHINode>(RVI);
1091 FlowsToReturn.
insert(IncValue);
1096 case Instruction::Alloca:
1098 case Instruction::Call:
1099 case Instruction::Invoke: {
1100 CallBase &CB = cast<CallBase>(*RVI);
1125 if (
F->returnDoesNotAlias())
1131 if (!
F->hasExactDefinition())
1136 if (!
F->getReturnType()->isPointerTy())
1144 if (
F->returnDoesNotAlias() ||
1145 !
F->getReturnType()->isPointerTy())
1148 F->setReturnDoesNotAlias();
1162 bool &Speculative) {
1163 assert(
F->getReturnType()->isPointerTy() &&
1164 "nonnull only meaningful on pointer types");
1165 Speculative =
false;
1169 if (
auto *Ret = dyn_cast<ReturnInst>(BB.getTerminator()))
1170 FlowsToReturn.
insert(Ret->getReturnValue());
1172 auto &
DL =
F->getDataLayout();
1174 for (
unsigned i = 0; i != FlowsToReturn.
size(); ++i) {
1175 Value *RetVal = FlowsToReturn[i];
1188 case Instruction::BitCast:
1189 case Instruction::AddrSpaceCast:
1192 case Instruction::GetElementPtr:
1193 if (cast<GEPOperator>(RVI)->isInBounds()) {
1198 case Instruction::Select: {
1200 FlowsToReturn.
insert(SI->getTrueValue());
1201 FlowsToReturn.
insert(SI->getFalseValue());
1204 case Instruction::PHI: {
1205 PHINode *PN = cast<PHINode>(RVI);
1210 case Instruction::Call:
1211 case Instruction::Invoke: {
1212 CallBase &CB = cast<CallBase>(*RVI);
1216 if (Callee && SCCNodes.count(Callee)) {
1236 bool SCCReturnsNonNull =
true;
1242 if (
F->getAttributes().hasRetAttr(Attribute::NonNull))
1248 if (!
F->hasExactDefinition())
1253 if (!
F->getReturnType()->isPointerTy())
1256 bool Speculative =
false;
1262 <<
" as nonnull\n");
1263 F->addRetAttr(Attribute::NonNull);
1271 SCCReturnsNonNull =
false;
1274 if (SCCReturnsNonNull) {
1276 if (
F->getAttributes().hasRetAttr(Attribute::NonNull) ||
1277 !
F->getReturnType()->isPointerTy())
1280 LLVM_DEBUG(
dbgs() <<
"SCC marking " <<
F->getName() <<
" as nonnull\n");
1281 F->addRetAttr(Attribute::NonNull);
1296 if (Attrs.hasRetAttr(Attribute::NoUndef))
1302 if (!
F->hasExactDefinition())
1308 if (
F->hasFnAttribute(Attribute::SanitizeMemory))
1311 if (
F->getReturnType()->isVoidTy())
1318 Value *RetVal = Ret->getReturnValue();
1319 if (!isGuaranteedNotToBeUndefOrPoison(RetVal))
1325 if (Attrs.hasRetAttr(Attribute::NonNull) &&
1326 !isKnownNonZero(RetVal, DL))
1329 if (MaybeAlign Align = Attrs.getRetAlignment())
1330 if (RetVal->getPointerAlignment(DL) < *Align)
1333 Attribute Attr = Attrs.getRetAttr(Attribute::Range);
1334 if (Attr.isValid() &&
1335 !Attr.getRange().contains(
1336 computeConstantRange(RetVal, false)))
1341 F->addRetAttr(Attribute::NoUndef);
1356class AttributeInferer {
1359 struct InferenceDescriptor {
1371 std::function<void(
Function &)> SetAttribute;
1378 bool RequiresExactDefinition;
1381 std::function<
bool(
const Function &)> SkipFunc,
1383 std::function<
void(
Function &)> SetAttr,
1385 : SkipFunction(SkipFunc), InstrBreaksAttribute(InstrScan),
1386 SetAttribute(SetAttr), AKind(AK),
1387 RequiresExactDefinition(ReqExactDef) {}
1394 void registerAttrInference(InferenceDescriptor AttrInference) {
1395 InferenceDescriptors.
push_back(AttrInference);
1403void AttributeInferer::run(
const SCCNodeSet &SCCNodes,
1412 if (InferInSCC.
empty())
1417 if (
ID.SkipFunction(*
F))
1422 return F->isDeclaration() ||
1423 (
ID.RequiresExactDefinition && !
F->hasExactDefinition());
1430 InferInSCC, std::back_inserter(InferInThisFunc),
1431 [
F](
const InferenceDescriptor &
ID) {
return !
ID.SkipFunction(*
F); });
1433 if (InferInThisFunc.empty())
1439 if (!
ID.InstrBreaksAttribute(
I))
1444 return D.AKind == ID.AKind;
1450 if (InferInThisFunc.empty())
1455 if (InferInSCC.
empty())
1463 for (
auto &
ID : InferInSCC) {
1464 if (
ID.SkipFunction(*
F))
1467 ID.SetAttribute(*
F);
1471struct SCCNodesResult {
1472 SCCNodeSet SCCNodes;
1473 bool HasUnknownCall;
1480 const SCCNodeSet &SCCNodes) {
1481 const CallBase *CB = dyn_cast<CallBase>(&
I);
1490 if (!
I.mayThrow(
true))
1492 if (
const auto *CI = dyn_cast<CallInst>(&
I)) {
1493 if (
Function *Callee = CI->getCalledFunction()) {
1497 if (SCCNodes.contains(Callee))
1515 if (SCCNodes.contains(Callee))
1530 if (
auto *FI = dyn_cast<FenceInst>(
I))
1533 else if (isa<AtomicCmpXchgInst>(
I) || isa<AtomicRMWInst>(
I))
1535 else if (
auto *SI = dyn_cast<StoreInst>(
I))
1536 return !SI->isUnordered();
1537 else if (
auto *LI = dyn_cast<LoadInst>(
I))
1538 return !LI->isUnordered();
1553 auto *CB = dyn_cast<CallBase>(&
I);
1564 if (
auto *
MI = dyn_cast<MemIntrinsic>(&
I))
1565 if (!
MI->isVolatile())
1570 if (SCCNodes.contains(Callee))
1581 AttributeInferer AI;
1588 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
1589 Attribute::Convergent,
1591 [](
const Function &
F) {
return !
F.isConvergent(); },
1597 LLVM_DEBUG(
dbgs() <<
"Removing convergent attr from fn " <<
F.getName()
1599 F.setNotConvergent();
1603 AI.run(SCCNodes, Changed);
1612 AttributeInferer AI;
1620 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
1621 Attribute::NoUnwind,
1623 [](
const Function &
F) {
return F.doesNotThrow(); },
1630 <<
"Adding nounwind attr to fn " <<
F.getName() <<
"\n");
1631 F.setDoesNotThrow();
1643 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
1646 [](
const Function &
F) {
return F.doesNotFreeMemory(); },
1653 <<
"Adding nofree attr to fn " <<
F.getName() <<
"\n");
1654 F.setDoesNotFreeMemory();
1659 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
1662 [](
const Function &
F) {
return F.hasNoSync(); },
1669 <<
"Adding nosync attr to fn " <<
F.getName() <<
"\n");
1676 AI.run(SCCNodes, Changed);
1684 if (SCCNodes.size() != 1)
1688 if (!
F || !
F->hasExactDefinition() ||
F->doesNotRecurse())
1695 for (
auto &
I : BB.instructionsWithoutDebug())
1696 if (
auto *CB = dyn_cast<CallBase>(&
I)) {
1698 if (!Callee || Callee ==
F ||
1699 (!Callee->doesNotRecurse() &&
1700 !(Callee->isDeclaration() &&
1701 Callee->hasFnAttribute(Attribute::NoCallback))))
1709 F->setDoesNotRecurse();
1715 if (
auto *CB = dyn_cast<CallBase>(&
I))
1716 return CB->
hasFnAttr(Attribute::NoReturn);
1741 if (Visited.
insert(Succ).second)
1743 }
while (!Worklist.
empty());
1752 if (!
F || !
F->hasExactDefinition() ||
F->hasFnAttribute(Attribute::Naked) ||
1757 F->setDoesNotReturn();
1767 if (!
F.hasExactDefinition())
1771 if (
F.mustProgress() &&
F.onlyReadsMemory())
1775 if (
F.isDeclaration())
1782 if (!Backedges.
empty())
1788 return I.willReturn();
1807 Res.HasUnknownCall =
false;
1809 if (!
F ||
F->hasOptNone() ||
F->hasFnAttribute(Attribute::Naked) ||
1810 F->isPresplitCoroutine()) {
1813 Res.HasUnknownCall =
true;
1820 if (!Res.HasUnknownCall) {
1822 if (
auto *CB = dyn_cast<CallBase>(&
I)) {
1824 Res.HasUnknownCall =
true;
1830 Res.SCCNodes.insert(
F);
1835template <
typename AARGetterT>
1838 bool ArgAttrsOnly) {
1842 if (Nodes.SCCNodes.empty())
1861 if (!Nodes.HasUnknownCall) {
1887 bool ArgAttrsOnly =
false;
1888 if (
C.size() == 1 && SkipNonRecursive) {
1891 ArgAttrsOnly =
true;
1908 auto ChangedFunctions =
1910 if (ChangedFunctions.empty())
1918 for (
Function *Changed : ChangedFunctions) {
1924 for (
auto *U : Changed->users()) {
1925 if (
auto *Call = dyn_cast<CallBase>(U)) {
1926 if (Call->getCalledFunction() == Changed)
1943 OS, MapClassName2PassName);
1944 if (SkipNonRecursive)
1945 OS <<
"<skip-non-recursive-function-attrs>";
1948template <
typename AARGetterT>
1962 assert(!
F.isDeclaration() &&
"Cannot deduce norecurse without a definition!");
1964 "This function has already been deduced as norecurs!");
1965 assert(
F.hasInternalLinkage() &&
1966 "Can only do top-down deduction for internal linkage functions!");
1976 for (
auto &U :
F.uses()) {
1977 auto *
I = dyn_cast<Instruction>(U.getUser());
1982 !CB->
getParent()->getParent()->doesNotRecurse())
1985 F.setDoesNotRecurse();
2003 if (SCC.size() != 1)
2005 Function &
F = SCC.begin()->getFunction();
2006 if (!
F.isDeclaration() && !
F.doesNotRecurse() &&
F.hasInternalLinkage())
2010 bool Changed =
false;
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.
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 void addNoReturnAttrs(const SCCNodeSet &SCCNodes, SmallSet< Function *, 8 > &Changed)
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 addAccessAttr(Argument *A, Attribute::AttrKind R)
static FunctionSummary * calculatePrevailingSummary(ValueInfo VI, DenseMap< ValueInfo, FunctionSummary * > &CachedPrevailingSummary, function_ref< bool(GlobalValue::GUID, const GlobalValueSummary *)> IsPrevailing)
static bool addArgumentAttrsFromCallsites(Function &F)
If a callsite has arguments that are also arguments to the parent function, try to propagate attribut...
static void addNoUndefAttrs(const SCCNodeSet &SCCNodes, SmallSet< Function *, 8 > &Changed)
Deduce noundef attributes for the SCC.
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 addArgumentAttrs(const SCCNodeSet &SCCNodes, SmallSet< Function *, 8 > &Changed)
Deduce nocapture attributes for the SCC.
static bool canReturn(Function &F)
static cl::opt< bool > DisableNoUnwindInference("disable-nounwind-inference", cl::Hidden, cl::desc("Stop inferring nounwind attribute during function-attrs pass"))
static void inferAttrsFromFunctionBodies(const SCCNodeSet &SCCNodes, SmallSet< Function *, 8 > &Changed)
Infer attributes from all functions in the SCC by scanning every instruction for compliance to the at...
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 bool basicBlockCanReturn(BasicBlock &BB)
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 void addMemoryAttrs(const SCCNodeSet &SCCNodes, AARGetterT &&AARGetter, SmallSet< Function *, 8 > &Changed)
Deduce readonly/readnone/writeonly attributes for the SCC.
static void addNoRecurseAttrs(const SCCNodeSet &SCCNodes, SmallSet< Function *, 8 > &Changed)
static void inferConvergent(const SCCNodeSet &SCCNodes, SmallSet< Function *, 8 > &Changed)
Attempt to remove convergent function attribute when possible.
static bool InstrBreaksNoSync(Instruction &I, const SCCNodeSet &SCCNodes)
static bool deduceFunctionAttributeInRPO(Module &M, LazyCallGraph &CG)
static SmallSet< Function *, 8 > deriveAttrsInPostOrder(ArrayRef< Function * > Functions, AARGetterT &&AARGetter, bool ArgAttrsOnly)
static bool InstrBreaksNoFree(Instruction &I, const SCCNodeSet &SCCNodes)
Helper for NoFree inference predicate InstrBreaksAttribute.
static void addNoAliasAttrs(const SCCNodeSet &SCCNodes, SmallSet< Function *, 8 > &Changed)
Deduce noalias attributes for the SCC.
static bool addNoRecurseAttrsTopDown(Function &F)
static bool instructionDoesNotReturn(Instruction &I)
static void addWillReturn(const SCCNodeSet &SCCNodes, SmallSet< Function *, 8 > &Changed)
static void addLocAccess(MemoryEffects &ME, const MemoryLocation &Loc, ModRefInfo MR, AAResults &AAR)
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 addArgumentReturnedAttrs(const SCCNodeSet &SCCNodes, SmallSet< Function *, 8 > &Changed)
Deduce returned attributes for the SCC.
static bool functionWillReturn(const Function &F)
static void addNonNullAttrs(const SCCNodeSet &SCCNodes, SmallSet< Function *, 8 > &Changed)
Deduce nonnull attributes for the SCC.
Provides passes for computing function attributes based on interprocedural analyses.
Rewrite Partial Register Uses
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 header defines various interfaces for pass management in LLVM.
This builds on the llvm/ADT/GraphTraits.h file to find the strongly connected components (SCCs) of a ...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallPtrSet class.
This file defines the SmallSet 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.
ModRefInfo getModRefInfoMask(const MemoryLocation &Loc, bool IgnoreLocals=false)
Returns a bitmask that should be unconditionally applied to the ModRef info of a memory location.
MemoryEffects getMemoryEffects(const CallBase *Call)
Return the behavior of the given call site.
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.
void addAttr(Attribute::AttrKind Kind)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
AttrKind
This enumeration lists the attributes that can be associated with parameters, function results,...
@ None
No attributes have been set.
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...
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.
bool dataOperandHasImpliedAttr(unsigned i, Attribute::AttrKind Kind) const
Return true if the data operand at index i has the attribute A.
bool isCallee(Value::const_user_iterator UI) const
Determine whether the passed iterator points to the callee operand's Use.
bool onlyReadsMemory(unsigned OpNo) const
Value * getArgOperand(unsigned i) const
bool isConvergent() const
Determine if the invoke is convergent.
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.
This is an important base class in LLVM.
A parsed version of the target data layout string in and methods for querying it.
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
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.
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 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.
void preserveSet()
Mark an analysis set as preserved.
void preserve()
Mark an analysis as preserved.
Return a value (possibly void), from a function.
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.
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.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
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.
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()
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.
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
const_iterator end(StringRef path)
Get end iterator over path.
This is an optimization pass for GlobalISel generic memory operations.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
MemoryEffects computeFunctionBodyMemoryAccess(Function &F, AAResults &AAR)
Returns the memory access properties of this copy of the function.
auto successors(const MachineBasicBlock *BB)
scc_iterator< T > scc_begin(const T &G)
Construct the begin iterator for a deduced graph type T.
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.
auto reverse(ContainerTy &&C)
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)
MemoryEffectsBase< IRMemLocation > MemoryEffects
Summary of how a function affects memory in the program.
bool PointerMayBeCaptured(const Value *V, bool ReturnCaptures, bool StoreCaptures, unsigned MaxUsesToExplore=0)
PointerMayBeCaptured - Return true if this pointer value may be captured by the enclosing function (w...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
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.
const Value * getUnderlyingObjectAggressive(const Value *V)
Like getUnderlyingObject(), but will try harder to find a single underlying object.
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...
bool inferAttributesFromOthers(Function &F)
If we can infer one attribute from another on the declaration of a function, explicitly materialize t...
bool isNoModRef(const ModRefInfo MRI)
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.
bool isIdentifiedObject(const Value *V)
Return true if this pointer refers to a distinct and identifiable object.
bool isRefSet(const ModRefInfo MRI)
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.
virtual void tooManyUses()=0
tooManyUses - The depth of traversal has breached a limit.
virtual bool captured(const Use *U)=0
captured - Information about the pointer was captured by the user of use U.
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.
PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR)
void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
Struct that holds a reference to a particular GUID in a global value summary.