71#define DEBUG_TYPE "function-attrs"
73STATISTIC(NumMemoryAttr,
"Number of functions with improved memory attribute");
74STATISTIC(NumNoCapture,
"Number of arguments marked nocapture");
75STATISTIC(NumReturned,
"Number of arguments marked returned");
76STATISTIC(NumReadNoneArg,
"Number of arguments marked readnone");
77STATISTIC(NumReadOnlyArg,
"Number of arguments marked readonly");
78STATISTIC(NumWriteOnlyArg,
"Number of arguments marked writeonly");
79STATISTIC(NumNoAlias,
"Number of function returns marked noalias");
80STATISTIC(NumNonNullReturn,
"Number of function returns marked nonnull");
81STATISTIC(NumNoRecurse,
"Number of functions marked as norecurse");
82STATISTIC(NumNoUnwind,
"Number of functions marked as nounwind");
83STATISTIC(NumNoFree,
"Number of functions marked as nofree");
84STATISTIC(NumWillReturn,
"Number of functions marked as willreturn");
85STATISTIC(NumNoSync,
"Number of functions marked as nosync");
88 "Number of functions marked as norecurse during thinlink");
90 "Number of functions marked as nounwind during thinlink");
94 cl::desc(
"Try to propagate nonnull argument attributes from callsites to "
95 "caller functions."));
99 cl::desc(
"Stop inferring nounwind attribute during function-attrs pass"));
103 cl::desc(
"Stop inferring nofree attribute during function-attrs pass"));
107 cl::desc(
"Don't propagate function-attrs in thinLTO"));
125 const SCCNodeSet &SCCNodes) {
136 if (
F.getAttributes().hasAttrSomewhere(Attribute::InAlloca) ||
137 F.getAttributes().hasAttrSomewhere(Attribute::Preallocated))
147 assert(!isa<AllocaInst>(UO) &&
148 "Should have been handled by getModRefInfoMask()");
149 if (isa<Argument>(UO)) {
163 if (
auto *Call = dyn_cast<CallBase>(&
I)) {
168 if (!Call->hasOperandBundles() && Call->getCalledFunction() &&
169 SCCNodes.count(Call->getCalledFunction()))
181 if (isa<PseudoProbeInst>(
I))
195 if (ArgMR != ModRefInfo::NoModRef) {
196 for (
const Use &U : Call->args()) {
198 if (!
Arg->getType()->isPtrOrPtrVectorTy())
208 if (
I.mayWriteToMemory())
209 MR |= ModRefInfo::Mod;
210 if (
I.mayReadFromMemory())
211 MR |= ModRefInfo::Ref;
212 if (MR == ModRefInfo::NoModRef)
227 AddLocAccess(*Loc, MR);
239template <
typename AARGetterT>
258 if (NewME != OldME) {
260 F->setMemoryEffects(NewME);
274 if (CachedPrevailingSummary.
count(
VI))
275 return CachedPrevailingSummary[
VI];
317 CachedPrevailingSummary[
VI] =
nullptr;
321 for (
const auto &GVS :
VI.getSummaryList()) {
327 if (!FS || FS->fflags().HasUnknownCall)
330 const auto &Linkage = GVS->linkage();
335 <<
"ThinLTO FunctionAttrs: Multiple Local Linkage, bailing on "
337 <<
VI.name() <<
" from " << FS->modulePath() <<
". Previous module "
338 << Local->modulePath() <<
"\n");
343 assert(IsPrevailing(
VI.getGUID(), GVS.get()));
350 if (IsPrevailing(
VI.getGUID(), GVS.get())) {
362 CachedPrevailingSummary[
VI] = Local;
363 }
else if (Prevailing) {
365 CachedPrevailingSummary[
VI] = Prevailing;
368 return CachedPrevailingSummary[
VI];
381 bool Changed =
false;
383 auto PropagateAttributes = [&](std::vector<ValueInfo> &SCCNodes) {
386 InferredFlags.
NoRecurse = (SCCNodes.size() == 1);
389 for (
auto &V : SCCNodes) {
400 for (
const auto &
Callee : CallerSummary->
calls()) {
402 Callee.first, CachedPrevailingSummary, IsPrevailing);
420 for (
auto &V : SCCNodes) {
422 LLVM_DEBUG(
dbgs() <<
"ThinLTO FunctionAttrs: Propagated NoRecurse to "
423 << V.name() <<
"\n");
424 ++NumThinLinkNoRecurse;
428 LLVM_DEBUG(
dbgs() <<
"ThinLTO FunctionAttrs: Propagated NoUnwind to "
429 << V.name() <<
"\n");
430 ++NumThinLinkNoUnwind;
433 for (
const auto &S : V.getSummaryList()) {
434 if (
auto *FS = dyn_cast<FunctionSummary>(S.get())) {
449 std::vector<ValueInfo> Nodes(*
I);
450 PropagateAttributes(Nodes);
460struct ArgumentGraphNode {
468 using ArgumentMapTy = std::map<Argument *, ArgumentGraphNode>;
470 ArgumentMapTy ArgumentMap;
478 ArgumentGraphNode SyntheticRoot;
481 ArgumentGraph() { SyntheticRoot.Definition =
nullptr; }
485 iterator
begin() {
return SyntheticRoot.Uses.begin(); }
486 iterator
end() {
return SyntheticRoot.Uses.end(); }
487 ArgumentGraphNode *getEntryNode() {
return &SyntheticRoot; }
489 ArgumentGraphNode *operator[](
Argument *
A) {
490 ArgumentGraphNode &
Node = ArgumentMap[
A];
492 SyntheticRoot.Uses.push_back(&
Node);
501 ArgumentUsesTracker(
const SCCNodeSet &SCCNodes) : SCCNodes(SCCNodes) {}
506 CallBase *CB = dyn_cast<CallBase>(
U->getUser());
513 if (!
F || !
F->hasExactDefinition() || !SCCNodes.count(
F)) {
532 if (UseIndex >=
F->arg_size()) {
533 assert(
F->isVarArg() &&
"More params than args in non-varargs call");
538 Uses.push_back(&*std::next(
F->arg_begin(), UseIndex));
543 bool Captured =
false;
548 const SCCNodeSet &SCCNodes;
585 if (
A->hasInAllocaAttr() ||
A->hasPreallocatedAttr())
589 bool IsWrite =
false;
591 for (
Use &U :
A->uses()) {
596 while (!Worklist.
empty()) {
597 if (IsWrite && IsRead)
604 switch (
I->getOpcode()) {
605 case Instruction::BitCast:
606 case Instruction::GetElementPtr:
607 case Instruction::PHI:
608 case Instruction::Select:
609 case Instruction::AddrSpaceCast:
611 for (
Use &UU :
I->uses())
612 if (Visited.
insert(&UU).second)
616 case Instruction::Call:
617 case Instruction::Invoke: {
638 if (!
I->getType()->isVoidTy())
639 for (
Use &UU :
I->uses())
640 if (Visited.
insert(&UU).second)
649 SCCNodes.
count(
F->getArg(UseIndex)))
661 }
else if (CB.
hasFnAttr(Attribute::WriteOnly) ||
670 case Instruction::Load:
673 if (cast<LoadInst>(
I)->isVolatile())
679 case Instruction::Store:
680 if (cast<StoreInst>(
I)->getValueOperand() == *U)
686 if (cast<StoreInst>(
I)->isVolatile())
692 case Instruction::ICmp:
693 case Instruction::Ret:
701 if (IsWrite && IsRead)
704 return Attribute::ReadOnly;
706 return Attribute::WriteOnly;
708 return Attribute::ReadNone;
719 if (!
F->hasExactDefinition())
722 if (
F->getReturnType()->isVoidTy())
726 if (
F->getAttributes().hasAttrSomewhere(Attribute::Returned))
729 auto FindRetArg = [&]() ->
Argument * {
732 if (
auto *Ret = dyn_cast<ReturnInst>(BB.getTerminator())) {
736 dyn_cast<Argument>(Ret->getReturnValue()->stripPointerCasts());
737 if (!RetVal || RetVal->getType() !=
F->getReturnType())
742 else if (RetArg != RetVal)
749 if (
Argument *RetArg = FindRetArg()) {
750 RetArg->
addAttr(Attribute::Returned);
765 bool Changed =
false;
776 if (
auto *CB = dyn_cast<CallBase>(&
I)) {
778 for (
auto &CSArg : CalledFunc->args()) {
779 if (!CSArg.hasNonNullAttr(
false))
785 auto *FArg = dyn_cast<Argument>(CB->
getArgOperand(CSArg.getArgNo()));
786 if (FArg && !FArg->hasNonNullAttr()) {
787 FArg->addAttr(Attribute::NonNull);
801 assert((R == Attribute::ReadOnly || R == Attribute::ReadNone ||
802 R == Attribute::WriteOnly)
803 &&
"Must be an access attribute.");
804 assert(
A &&
"Argument must not be null.");
807 if (
A->hasAttribute(R))
812 A->removeAttr(Attribute::WriteOnly);
813 A->removeAttr(Attribute::ReadOnly);
814 A->removeAttr(Attribute::ReadNone);
816 if (R == Attribute::ReadOnly)
818 else if (R == Attribute::WriteOnly)
836 if (!
F->hasExactDefinition())
844 if (
F->onlyReadsMemory() &&
F->doesNotThrow() &&
845 F->getReturnType()->isVoidTy()) {
847 if (
A.getType()->isPointerTy() && !
A.hasNoCaptureAttr()) {
848 A.addAttr(Attribute::NoCapture);
857 if (!
A.getType()->isPointerTy())
859 bool HasNonLocalUses =
false;
860 if (!
A.hasNoCaptureAttr()) {
861 ArgumentUsesTracker Tracker(SCCNodes);
863 if (!Tracker.Captured) {
864 if (Tracker.Uses.empty()) {
866 A.addAttr(Attribute::NoCapture);
873 ArgumentGraphNode *
Node = AG[&
A];
877 HasNonLocalUses =
true;
883 if (!HasNonLocalUses && !
A.onlyReadsMemory()) {
906 const std::vector<ArgumentGraphNode *> &ArgumentSCC = *
I;
907 if (ArgumentSCC.size() == 1) {
908 if (!ArgumentSCC[0]->Definition)
912 if (ArgumentSCC[0]->
Uses.size() == 1 &&
913 ArgumentSCC[0]->Uses[0] == ArgumentSCC[0]) {
914 Argument *
A = ArgumentSCC[0]->Definition;
915 A->addAttr(Attribute::NoCapture);
917 Changed.
insert(
A->getParent());
929 bool SCCCaptured =
false;
930 for (ArgumentGraphNode *
Node : ArgumentSCC) {
931 if (
Node->Uses.empty() && !
Node->Definition->hasNoCaptureAttr()) {
942 for (ArgumentGraphNode *
I : ArgumentSCC) {
943 ArgumentSCCNodes.
insert(
I->Definition);
946 for (ArgumentGraphNode *
N : ArgumentSCC) {
947 for (ArgumentGraphNode *
Use :
N->Uses) {
949 if (
A->hasNoCaptureAttr() || ArgumentSCCNodes.
count(
A))
960 for (ArgumentGraphNode *
N : ArgumentSCC) {
962 A->addAttr(Attribute::NoCapture);
964 Changed.
insert(
A->getParent());
981 if (
A == Attribute::ReadNone)
983 if (
B == Attribute::ReadNone)
989 for (ArgumentGraphNode *
N : ArgumentSCC) {
992 AccessAttr = meetAccessAttr(AccessAttr, K);
998 for (ArgumentGraphNode *
N : ArgumentSCC) {
1001 Changed.
insert(
A->getParent());
1014 if (
ReturnInst *Ret = dyn_cast<ReturnInst>(BB.getTerminator()))
1015 FlowsToReturn.
insert(Ret->getReturnValue());
1017 for (
unsigned i = 0; i != FlowsToReturn.
size(); ++i) {
1018 Value *RetVal = FlowsToReturn[i];
1020 if (
Constant *
C = dyn_cast<Constant>(RetVal)) {
1021 if (!
C->isNullValue() && !isa<UndefValue>(
C))
1027 if (isa<Argument>(RetVal))
1030 if (
Instruction *RVI = dyn_cast<Instruction>(RetVal))
1031 switch (RVI->getOpcode()) {
1033 case Instruction::BitCast:
1034 case Instruction::GetElementPtr:
1035 case Instruction::AddrSpaceCast:
1036 FlowsToReturn.
insert(RVI->getOperand(0));
1038 case Instruction::Select: {
1040 FlowsToReturn.
insert(
SI->getTrueValue());
1041 FlowsToReturn.
insert(
SI->getFalseValue());
1044 case Instruction::PHI: {
1045 PHINode *PN = cast<PHINode>(RVI);
1047 FlowsToReturn.
insert(IncValue);
1052 case Instruction::Alloca:
1054 case Instruction::Call:
1055 case Instruction::Invoke: {
1056 CallBase &CB = cast<CallBase>(*RVI);
1081 if (
F->returnDoesNotAlias())
1087 if (!
F->hasExactDefinition())
1092 if (!
F->getReturnType()->isPointerTy())
1100 if (
F->returnDoesNotAlias() ||
1101 !
F->getReturnType()->isPointerTy())
1104 F->setReturnDoesNotAlias();
1118 bool &Speculative) {
1119 assert(
F->getReturnType()->isPointerTy() &&
1120 "nonnull only meaningful on pointer types");
1121 Speculative =
false;
1125 if (
auto *Ret = dyn_cast<ReturnInst>(BB.getTerminator()))
1126 FlowsToReturn.
insert(Ret->getReturnValue());
1128 auto &
DL =
F->getParent()->getDataLayout();
1130 for (
unsigned i = 0; i != FlowsToReturn.
size(); ++i) {
1131 Value *RetVal = FlowsToReturn[i];
1144 case Instruction::BitCast:
1145 case Instruction::GetElementPtr:
1146 case Instruction::AddrSpaceCast:
1149 case Instruction::Select: {
1151 FlowsToReturn.
insert(
SI->getTrueValue());
1152 FlowsToReturn.
insert(
SI->getFalseValue());
1155 case Instruction::PHI: {
1156 PHINode *PN = cast<PHINode>(RVI);
1161 case Instruction::Call:
1162 case Instruction::Invoke: {
1163 CallBase &CB = cast<CallBase>(*RVI);
1187 bool SCCReturnsNonNull =
true;
1193 if (
F->getAttributes().hasRetAttr(Attribute::NonNull))
1199 if (!
F->hasExactDefinition())
1204 if (!
F->getReturnType()->isPointerTy())
1207 bool Speculative =
false;
1213 <<
" as nonnull\n");
1214 F->addRetAttr(Attribute::NonNull);
1222 SCCReturnsNonNull =
false;
1225 if (SCCReturnsNonNull) {
1227 if (
F->getAttributes().hasRetAttr(Attribute::NonNull) ||
1228 !
F->getReturnType()->isPointerTy())
1231 LLVM_DEBUG(
dbgs() <<
"SCC marking " <<
F->getName() <<
" as nonnull\n");
1232 F->addRetAttr(Attribute::NonNull);
1247class AttributeInferer {
1250 struct InferenceDescriptor {
1262 std::function<void(
Function &)> SetAttribute;
1269 bool RequiresExactDefinition;
1272 std::function<
bool(
const Function &)> SkipFunc,
1274 std::function<
void(
Function &)> SetAttr,
1276 : SkipFunction(SkipFunc), InstrBreaksAttribute(InstrScan),
1277 SetAttribute(SetAttr), AKind(AK),
1278 RequiresExactDefinition(ReqExactDef) {}
1285 void registerAttrInference(InferenceDescriptor AttrInference) {
1286 InferenceDescriptors.
push_back(AttrInference);
1294void AttributeInferer::run(
const SCCNodeSet &SCCNodes,
1303 if (InferInSCC.
empty())
1308 if (
ID.SkipFunction(*
F))
1313 return F->isDeclaration() ||
1314 (
ID.RequiresExactDefinition && !
F->hasExactDefinition());
1321 InferInSCC, std::back_inserter(InferInThisFunc),
1322 [
F](
const InferenceDescriptor &
ID) {
return !
ID.SkipFunction(*
F); });
1324 if (InferInThisFunc.empty())
1330 if (!
ID.InstrBreaksAttribute(
I))
1335 return D.AKind == ID.AKind;
1341 if (InferInThisFunc.empty())
1346 if (InferInSCC.
empty())
1354 for (
auto &
ID : InferInSCC) {
1355 if (
ID.SkipFunction(*
F))
1358 ID.SetAttribute(*
F);
1362struct SCCNodesResult {
1363 SCCNodeSet SCCNodes;
1364 bool HasUnknownCall;
1371 const SCCNodeSet &SCCNodes) {
1372 const CallBase *CB = dyn_cast<CallBase>(&
I);
1383 if (
const auto *CI = dyn_cast<CallInst>(&
I)) {
1388 if (SCCNodes.contains(
Callee))
1406 if (SCCNodes.contains(
Callee))
1421 if (
auto *FI = dyn_cast<FenceInst>(
I))
1424 else if (isa<AtomicCmpXchgInst>(
I) || isa<AtomicRMWInst>(
I))
1426 else if (
auto *
SI = dyn_cast<StoreInst>(
I))
1427 return !
SI->isUnordered();
1428 else if (
auto *LI = dyn_cast<LoadInst>(
I))
1429 return !LI->isUnordered();
1444 auto *CB = dyn_cast<CallBase>(&
I);
1455 if (
auto *
MI = dyn_cast<MemIntrinsic>(&
I))
1456 if (!
MI->isVolatile())
1461 if (SCCNodes.contains(
Callee))
1472 AttributeInferer AI;
1479 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
1480 Attribute::Convergent,
1482 [](
const Function &
F) {
return !
F.isConvergent(); },
1488 LLVM_DEBUG(
dbgs() <<
"Removing convergent attr from fn " <<
F.getName()
1490 F.setNotConvergent();
1494 AI.run(SCCNodes, Changed);
1503 AttributeInferer AI;
1511 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
1512 Attribute::NoUnwind,
1514 [](
const Function &
F) {
return F.doesNotThrow(); },
1521 <<
"Adding nounwind attr to fn " <<
F.getName() <<
"\n");
1522 F.setDoesNotThrow();
1534 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
1537 [](
const Function &
F) {
return F.doesNotFreeMemory(); },
1544 <<
"Adding nofree attr to fn " <<
F.getName() <<
"\n");
1545 F.setDoesNotFreeMemory();
1550 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
1553 [](
const Function &
F) {
return F.hasNoSync(); },
1560 <<
"Adding nosync attr to fn " <<
F.getName() <<
"\n");
1567 AI.run(SCCNodes, Changed);
1575 if (SCCNodes.size() != 1)
1579 if (!
F || !
F->hasExactDefinition() ||
F->doesNotRecurse())
1586 for (
auto &
I : BB.instructionsWithoutDebug())
1587 if (
auto *CB = dyn_cast<CallBase>(&
I)) {
1597 F->setDoesNotRecurse();
1603 if (
auto *CB = dyn_cast<CallBase>(&
I))
1604 return CB->
hasFnAttr(Attribute::NoReturn);
1629 if (Visited.
insert(Succ).second)
1631 }
while (!Worklist.
empty());
1640 if (!
F || !
F->hasExactDefinition() ||
F->hasFnAttribute(Attribute::Naked) ||
1645 F->setDoesNotReturn();
1655 if (!
F.hasExactDefinition())
1659 if (
F.mustProgress() &&
F.onlyReadsMemory())
1663 if (
F.isDeclaration())
1670 if (!Backedges.
empty())
1676 return I.willReturn();
1695 Res.HasUnknownCall =
false;
1697 if (!
F ||
F->hasOptNone() ||
F->hasFnAttribute(Attribute::Naked) ||
1698 F->isPresplitCoroutine()) {
1701 Res.HasUnknownCall =
true;
1708 if (!Res.HasUnknownCall) {
1710 if (
auto *CB = dyn_cast<CallBase>(&
I)) {
1712 Res.HasUnknownCall =
true;
1718 Res.SCCNodes.insert(
F);
1723template <
typename AARGetterT>
1729 if (Nodes.SCCNodes.empty())
1743 if (!Nodes.HasUnknownCall) {
1767 if (
C.size() == 1 && SkipNonRecursive) {
1788 if (ChangedFunctions.empty())
1796 for (
Function *Changed : ChangedFunctions) {
1802 for (
auto *U : Changed->users()) {
1803 if (
auto *Call = dyn_cast<CallBase>(U)) {
1804 if (Call->getCalledFunction() == Changed)
1821 OS, MapClassName2PassName);
1822 if (SkipNonRecursive)
1823 OS <<
"<skip-non-recursive>";
1826template <
typename AARGetterT>
1840 assert(!
F.isDeclaration() &&
"Cannot deduce norecurse without a definition!");
1842 "This function has already been deduced as norecurs!");
1843 assert(
F.hasInternalLinkage() &&
1844 "Can only do top-down deduction for internal linkage functions!");
1854 for (
auto &U :
F.uses()) {
1855 auto *
I = dyn_cast<Instruction>(U.getUser());
1863 F.setDoesNotRecurse();
1881 if (SCC.size() != 1)
1883 Function &
F = SCC.begin()->getFunction();
1884 if (!
F.isDeclaration() && !
F.doesNotRecurse() &&
F.hasInternalLinkage())
1888 bool Changed =
false;
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
amdgpu Simplify well known AMD library false FunctionCallee Callee
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
SmallPtrSet< MachineInstr *, 2 > Uses
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 SmallSet< Function *, 8 > deriveAttrsInPostOrder(ArrayRef< Function * > Functions, AARGetterT &&AARGetter)
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 bool isOrderedAtomic(Instruction *I)
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 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 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 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 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.
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...
print must be executed print the must be executed context for all instructions
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)
This defines the Use class.
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 Function * getParent() const
Return the enclosing method, or null if none.
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...
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.
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.
bool doesNotRecurse() const
Determine if the function is known not to recurse, directly or indirectly.
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)
const BasicBlock * getParent() const
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()
Summary of how a function affects memory in the program.
static MemoryEffects inaccessibleMemOnly(ModRefInfo MR=ModRefInfo::ModRef)
Create MemoryEffects that can only access inaccessible memory.
bool doesNotAccessMemory() const
Whether this function accesses no memory.
@ ArgMem
Access to memory via argument pointers.
MemoryEffects getWithoutLoc(Location Loc) const
Get new MemoryEffects with NoModRef on the given Loc.
ModRefInfo getModRef(Location Loc) const
Get ModRefInfo for the given Location.
static MemoryEffects none()
Create MemoryEffects that cannot read or write any memory.
static MemoryEffects argMemOnly(ModRefInfo MR=ModRefInfo::ModRef)
Create MemoryEffects that can only access argument memory.
static MemoryEffects unknown()
Create MemoryEffects 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.
An efficient, type-erasing, non-owning reference to a callable.
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 isKnownNonZero(const Value *V, const DataLayout &DL, unsigned Depth=0, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true)
Return true if the given value is known to be non-zero when defined.
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)
const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=6)
This method strips off any GEP address adjustments and pointer casts from the specified value,...
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 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.
ModRefInfo
Flags indicating whether a memory access modifies or references memory.
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.
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.