Go to the documentation of this file.
70 #define DEBUG_TYPE "function-attrs"
72 STATISTIC(NumArgMemOnly,
"Number of functions marked argmemonly");
73 STATISTIC(NumReadNone,
"Number of functions marked readnone");
74 STATISTIC(NumReadOnly,
"Number of functions marked readonly");
75 STATISTIC(NumWriteOnly,
"Number of functions marked writeonly");
76 STATISTIC(NumNoCapture,
"Number of arguments marked nocapture");
77 STATISTIC(NumReturned,
"Number of arguments marked returned");
78 STATISTIC(NumReadNoneArg,
"Number of arguments marked readnone");
79 STATISTIC(NumReadOnlyArg,
"Number of arguments marked readonly");
80 STATISTIC(NumWriteOnlyArg,
"Number of arguments marked writeonly");
81 STATISTIC(NumNoAlias,
"Number of function returns marked noalias");
82 STATISTIC(NumNonNullReturn,
"Number of function returns marked nonnull");
83 STATISTIC(NumNoRecurse,
"Number of functions marked as norecurse");
84 STATISTIC(NumNoUnwind,
"Number of functions marked as nounwind");
85 STATISTIC(NumNoFree,
"Number of functions marked as nofree");
86 STATISTIC(NumWillReturn,
"Number of functions marked as willreturn");
87 STATISTIC(NumNoSync,
"Number of functions marked as nosync");
90 "Number of functions marked as norecurse during thinlink");
92 "Number of functions marked as nounwind during thinlink");
96 cl::desc(
"Try to propagate nonnull argument attributes from callsites to "
97 "caller functions."));
101 cl::desc(
"Stop inferring nounwind attribute during function-attrs pass"));
105 cl::desc(
"Stop inferring nofree attribute during function-attrs pass"));
109 cl::desc(
"Don't propagate function-attrs in thinLTO"));
127 const SCCNodeSet &SCCNodes) {
137 bool ReadsMemory =
false;
138 bool WritesMemory =
false;
141 bool AccessesNonArgsOrAlloca =
false;
143 auto IsArgumentOrAlloca = [](
const Value *Ptr) {
145 return isa<Argument>(UO) || isa<AllocaInst>(UO);
150 if (
auto *Call = dyn_cast<CallBase>(&
I)) {
155 if (!Call->hasOperandBundles() && Call->getCalledFunction() &&
156 SCCNodes.count(Call->getCalledFunction()))
169 if (isa<PseudoProbeInst>(
I))
179 AccessesNonArgsOrAlloca =
true;
185 for (
const Use &U : Call->args()) {
187 if (!
Arg->getType()->isPtrOrPtrVectorTy())
197 AccessesNonArgsOrAlloca |= !IsArgumentOrAlloca(Loc.
Ptr);
207 }
else if (
LoadInst *LI = dyn_cast<LoadInst>(&
I)) {
210 if (!LI->isVolatile() &&
213 AccessesNonArgsOrAlloca |= !IsArgumentOrAlloca(Loc.
Ptr);
217 if (!
SI->isVolatile() &&
220 AccessesNonArgsOrAlloca |= !IsArgumentOrAlloca(Loc.
Ptr);
226 AccessesNonArgsOrAlloca |= !IsArgumentOrAlloca(Loc.
Ptr);
230 AccessesNonArgsOrAlloca |=
I.mayReadOrWriteMemory();
237 WritesMemory |=
I.mayWriteToMemory();
240 ReadsMemory |=
I.mayReadFromMemory();
243 if (!WritesMemory && !ReadsMemory)
247 if (!AccessesNonArgsOrAlloca)
262 template <
typename AARGetterT>
267 bool ReadsMemory =
false;
268 bool WritesMemory =
false;
270 bool ArgMemOnly =
true;
287 if (ReadsMemory && WritesMemory && !ArgMemOnly)
291 assert((!ReadsMemory || !WritesMemory || ArgMemOnly) &&
292 "no memory attributes can be added for this SCC, should have exited "
300 if (ArgMemOnly && !
F->onlyAccessesArgMemory() &&
301 (ReadsMemory || WritesMemory)) {
303 F->addFnAttr(Attribute::ArgMemOnly);
309 if (ReadsMemory && WritesMemory)
311 if (
F->doesNotAccessMemory())
315 if (
F->onlyReadsMemory() && ReadsMemory)
319 if (
F->onlyWritesMemory() && WritesMemory)
330 if (!WritesMemory && !ReadsMemory) {
333 AttrsToRemove.
addAttribute(Attribute::InaccessibleMemOnly);
334 AttrsToRemove.
addAttribute(Attribute::InaccessibleMemOrArgMemOnly);
336 F->removeFnAttrs(AttrsToRemove);
339 if (WritesMemory && !ReadsMemory)
340 F->addFnAttr(Attribute::WriteOnly);
342 F->addFnAttr(ReadsMemory ? Attribute::ReadOnly : Attribute::ReadNone);
344 if (WritesMemory && !ReadsMemory)
346 else if (ReadsMemory)
361 if (CachedPrevailingSummary.
count(
VI))
362 return CachedPrevailingSummary[
VI];
404 CachedPrevailingSummary[
VI] =
nullptr;
408 for (
const auto &GVS :
VI.getSummaryList()) {
414 if (!
FS ||
FS->fflags().HasUnknownCall)
417 const auto &Linkage = GVS->linkage();
422 <<
"ThinLTO FunctionAttrs: Multiple Local Linkage, bailing on "
424 <<
VI.name() <<
" from " <<
FS->modulePath() <<
". Previous module "
425 << Local->modulePath() <<
"\n");
430 assert(IsPrevailing(
VI.getGUID(), GVS.get()));
437 if (IsPrevailing(
VI.getGUID(), GVS.get())) {
449 CachedPrevailingSummary[
VI] = Local;
450 }
else if (Prevailing) {
452 CachedPrevailingSummary[
VI] = Prevailing;
455 return CachedPrevailingSummary[
VI];
468 bool Changed =
false;
470 auto PropagateAttributes = [&](std::vector<ValueInfo> &SCCNodes) {
473 InferredFlags.
NoRecurse = (SCCNodes.size() == 1);
476 for (
auto &V : SCCNodes) {
487 for (
const auto &
Callee : CallerSummary->
calls()) {
489 Callee.first, CachedPrevailingSummary, IsPrevailing);
507 for (
auto &V : SCCNodes) {
509 LLVM_DEBUG(
dbgs() <<
"ThinLTO FunctionAttrs: Propagated NoRecurse to "
510 << V.name() <<
"\n");
511 ++NumThinLinkNoRecurse;
515 LLVM_DEBUG(
dbgs() <<
"ThinLTO FunctionAttrs: Propagated NoUnwind to "
516 << V.name() <<
"\n");
517 ++NumThinLinkNoUnwind;
520 for (
auto &
S : V.getSummaryList()) {
521 if (
auto *
FS = dyn_cast<FunctionSummary>(
S.get())) {
536 std::vector<ValueInfo> Nodes(*
I);
537 PropagateAttributes(Nodes);
547 struct ArgumentGraphNode {
552 class ArgumentGraph {
555 using ArgumentMapTy = std::map<Argument *, ArgumentGraphNode>;
557 ArgumentMapTy ArgumentMap;
565 ArgumentGraphNode SyntheticRoot;
568 ArgumentGraph() { SyntheticRoot.Definition =
nullptr; }
572 iterator
begin() {
return SyntheticRoot.Uses.begin(); }
573 iterator
end() {
return SyntheticRoot.Uses.end(); }
574 ArgumentGraphNode *getEntryNode() {
return &SyntheticRoot; }
576 ArgumentGraphNode *operator[](
Argument *A) {
577 ArgumentGraphNode &Node = ArgumentMap[
A];
579 SyntheticRoot.Uses.push_back(&Node);
588 ArgumentUsesTracker(
const SCCNodeSet &SCCNodes) : SCCNodes(SCCNodes) {}
590 void tooManyUses()
override { Captured =
true; }
592 bool captured(
const Use *U)
override {
593 CallBase *CB = dyn_cast<CallBase>(U->getUser());
600 if (!
F || !
F->hasExactDefinition() || !SCCNodes.count(
F)) {
619 if (UseIndex >=
F->arg_size()) {
620 assert(
F->isVarArg() &&
"More params than args in non-varargs call");
625 Uses.push_back(&*std::next(
F->arg_begin(), UseIndex));
630 bool Captured =
false;
635 const SCCNodeSet &SCCNodes;
672 if (
A->hasInAllocaAttr() ||
A->hasPreallocatedAttr())
676 bool IsWrite =
false;
678 for (
Use &U :
A->uses()) {
680 Worklist.push_back(&U);
683 while (!Worklist.empty()) {
684 if (IsWrite && IsRead)
691 switch (
I->getOpcode()) {
692 case Instruction::BitCast:
693 case Instruction::GetElementPtr:
694 case Instruction::PHI:
696 case Instruction::AddrSpaceCast:
698 for (
Use &UU :
I->uses())
699 if (Visited.
insert(&UU).second)
700 Worklist.push_back(&UU);
704 case Instruction::Invoke: {
725 if (!
I->getType()->isVoidTy())
726 for (
Use &UU :
I->uses())
727 if (Visited.
insert(&UU).second)
728 Worklist.push_back(&UU);
736 SCCNodes.
count(
F->getArg(UseIndex)))
748 }
else if (CB.
hasFnAttr(Attribute::WriteOnly) ||
760 if (cast<LoadInst>(
I)->isVolatile())
767 if (cast<StoreInst>(
I)->getValueOperand() == *U)
773 if (cast<StoreInst>(
I)->isVolatile())
779 case Instruction::ICmp:
788 if (IsWrite && IsRead)
791 return Attribute::ReadOnly;
793 return Attribute::WriteOnly;
795 return Attribute::ReadNone;
806 if (!
F->hasExactDefinition())
809 if (
F->getReturnType()->isVoidTy())
814 [](
const Argument &
Arg) { return Arg.hasReturnedAttr(); }))
817 auto FindRetArg = [&]() ->
Value * {
818 Value *RetArg =
nullptr;
820 if (
auto *
Ret = dyn_cast<ReturnInst>(
BB.getTerminator())) {
823 Value *RetVal =
Ret->getReturnValue()->stripPointerCasts();
824 if (!isa<Argument>(RetVal) || RetVal->
getType() !=
F->getReturnType())
829 else if (RetArg != RetVal)
836 if (
Value *RetArg = FindRetArg()) {
837 auto *
A = cast<Argument>(RetArg);
838 A->addAttr(Attribute::Returned);
853 bool Changed =
false;
864 if (
auto *CB = dyn_cast<CallBase>(&
I)) {
866 for (
auto &CSArg : CalledFunc->args()) {
867 if (!CSArg.hasNonNullAttr(
false))
873 auto *FArg = dyn_cast<Argument>(CB->
getArgOperand(CSArg.getArgNo()));
874 if (FArg && !FArg->hasNonNullAttr()) {
875 FArg->addAttr(Attribute::NonNull);
889 assert((
R == Attribute::ReadOnly ||
R == Attribute::ReadNone ||
890 R == Attribute::WriteOnly)
891 &&
"Must be an access attribute.");
892 assert(
A &&
"Argument must not be null.");
895 if (
A->hasAttribute(
R))
900 A->removeAttr(Attribute::WriteOnly);
901 A->removeAttr(Attribute::ReadOnly);
902 A->removeAttr(Attribute::ReadNone);
904 if (
R == Attribute::ReadOnly)
906 else if (
R == Attribute::WriteOnly)
924 if (!
F->hasExactDefinition())
932 if (
F->onlyReadsMemory() &&
F->doesNotThrow() &&
933 F->getReturnType()->isVoidTy()) {
936 if (
A->getType()->isPointerTy() && !
A->hasNoCaptureAttr()) {
937 A->addAttr(Attribute::NoCapture);
947 if (!
A->getType()->isPointerTy())
949 bool HasNonLocalUses =
false;
950 if (!
A->hasNoCaptureAttr()) {
951 ArgumentUsesTracker Tracker(SCCNodes);
953 if (!Tracker.Captured) {
954 if (Tracker.Uses.empty()) {
956 A->addAttr(Attribute::NoCapture);
963 ArgumentGraphNode *Node = AG[&*
A];
965 Node->Uses.push_back(AG[
Use]);
967 HasNonLocalUses =
true;
973 if (!HasNonLocalUses && !
A->onlyReadsMemory()) {
996 const std::vector<ArgumentGraphNode *> &ArgumentSCC = *
I;
997 if (ArgumentSCC.size() == 1) {
998 if (!ArgumentSCC[0]->Definition)
1002 if (ArgumentSCC[0]->
Uses.size() == 1 &&
1003 ArgumentSCC[0]->Uses[0] == ArgumentSCC[0]) {
1004 Argument *
A = ArgumentSCC[0]->Definition;
1005 A->addAttr(Attribute::NoCapture);
1007 Changed.
insert(
A->getParent());
1019 bool SCCCaptured =
false;
1020 for (
auto I = ArgumentSCC.begin(),
E = ArgumentSCC.end();
1021 I !=
E && !SCCCaptured; ++
I) {
1022 ArgumentGraphNode *Node = *
I;
1023 if (Node->Uses.empty()) {
1024 if (!Node->Definition->hasNoCaptureAttr())
1034 for (ArgumentGraphNode *
I : ArgumentSCC) {
1035 ArgumentSCCNodes.
insert(
I->Definition);
1038 for (
auto I = ArgumentSCC.begin(),
E = ArgumentSCC.end();
1039 I !=
E && !SCCCaptured; ++
I) {
1040 ArgumentGraphNode *
N = *
I;
1041 for (ArgumentGraphNode *
Use :
N->Uses) {
1043 if (
A->hasNoCaptureAttr() || ArgumentSCCNodes.
count(
A))
1052 for (
unsigned i = 0,
e = ArgumentSCC.size();
i !=
e; ++
i) {
1054 A->addAttr(Attribute::NoCapture);
1056 Changed.
insert(
A->getParent());
1073 if (
A == Attribute::ReadNone)
1075 if (
B == Attribute::ReadNone)
1081 for (
unsigned i = 0,
e = ArgumentSCC.size();
1085 AccessAttr = meetAccessAttr(AccessAttr, K);
1089 for (
unsigned i = 0,
e = ArgumentSCC.size();
i !=
e; ++
i) {
1092 Changed.
insert(
A->getParent());
1106 FlowsToReturn.
insert(
Ret->getReturnValue());
1108 for (
unsigned i = 0;
i != FlowsToReturn.
size(); ++
i) {
1109 Value *RetVal = FlowsToReturn[
i];
1111 if (
Constant *
C = dyn_cast<Constant>(RetVal)) {
1112 if (!
C->isNullValue() && !isa<UndefValue>(
C))
1118 if (isa<Argument>(RetVal))
1121 if (
Instruction *RVI = dyn_cast<Instruction>(RetVal))
1122 switch (RVI->getOpcode()) {
1124 case Instruction::BitCast:
1125 case Instruction::GetElementPtr:
1126 case Instruction::AddrSpaceCast:
1127 FlowsToReturn.
insert(RVI->getOperand(0));
1131 FlowsToReturn.
insert(
SI->getTrueValue());
1132 FlowsToReturn.
insert(
SI->getFalseValue());
1135 case Instruction::PHI: {
1136 PHINode *PN = cast<PHINode>(RVI);
1138 FlowsToReturn.
insert(IncValue);
1143 case Instruction::Alloca:
1146 case Instruction::Invoke: {
1147 CallBase &CB = cast<CallBase>(*RVI);
1172 if (
F->returnDoesNotAlias())
1178 if (!
F->hasExactDefinition())
1183 if (!
F->getReturnType()->isPointerTy())
1191 if (
F->returnDoesNotAlias() ||
1192 !
F->getReturnType()->isPointerTy())
1195 F->setReturnDoesNotAlias();
1209 bool &Speculative) {
1210 assert(
F->getReturnType()->isPointerTy() &&
1211 "nonnull only meaningful on pointer types");
1212 Speculative =
false;
1216 if (
auto *
Ret = dyn_cast<ReturnInst>(
BB.getTerminator()))
1217 FlowsToReturn.
insert(
Ret->getReturnValue());
1219 auto &
DL =
F->getParent()->getDataLayout();
1221 for (
unsigned i = 0;
i != FlowsToReturn.
size(); ++
i) {
1222 Value *RetVal = FlowsToReturn[
i];
1235 case Instruction::BitCast:
1236 case Instruction::GetElementPtr:
1237 case Instruction::AddrSpaceCast:
1242 FlowsToReturn.
insert(
SI->getTrueValue());
1243 FlowsToReturn.
insert(
SI->getFalseValue());
1246 case Instruction::PHI: {
1247 PHINode *PN = cast<PHINode>(RVI);
1253 case Instruction::Invoke: {
1254 CallBase &CB = cast<CallBase>(*RVI);
1278 bool SCCReturnsNonNull =
true;
1284 if (
F->getAttributes().hasRetAttr(Attribute::NonNull))
1290 if (!
F->hasExactDefinition())
1295 if (!
F->getReturnType()->isPointerTy())
1298 bool Speculative =
false;
1304 <<
" as nonnull\n");
1305 F->addRetAttr(Attribute::NonNull);
1313 SCCReturnsNonNull =
false;
1316 if (SCCReturnsNonNull) {
1318 if (
F->getAttributes().hasRetAttr(Attribute::NonNull) ||
1319 !
F->getReturnType()->isPointerTy())
1322 LLVM_DEBUG(
dbgs() <<
"SCC marking " <<
F->getName() <<
" as nonnull\n");
1323 F->addRetAttr(Attribute::NonNull);
1338 class AttributeInferer {
1341 struct InferenceDescriptor {
1360 bool RequiresExactDefinition;
1367 : SkipFunction(SkipFunc), InstrBreaksAttribute(InstrScan),
1368 SetAttribute(SetAttr), AKind(AK),
1369 RequiresExactDefinition(ReqExactDef) {}
1376 void registerAttrInference(InferenceDescriptor AttrInference) {
1377 InferenceDescriptors.push_back(AttrInference);
1394 if (InferInSCC.empty())
1399 if (
ID.SkipFunction(*
F))
1404 return F->isDeclaration() ||
1405 (
ID.RequiresExactDefinition && !
F->hasExactDefinition());
1412 InferInSCC, std::back_inserter(InferInThisFunc),
1413 [
F](
const InferenceDescriptor &
ID) {
return !
ID.SkipFunction(*
F); });
1415 if (InferInThisFunc.empty())
1421 if (!
ID.InstrBreaksAttribute(
I))
1426 return D.AKind == ID.AKind;
1432 if (InferInThisFunc.empty())
1437 if (InferInSCC.empty())
1445 for (
auto &
ID : InferInSCC) {
1446 if (
ID.SkipFunction(*
F))
1449 ID.SetAttribute(*
F);
1453 struct SCCNodesResult {
1454 SCCNodeSet SCCNodes;
1455 bool HasUnknownCall;
1462 const SCCNodeSet &SCCNodes) {
1463 const CallBase *CB = dyn_cast<CallBase>(&
I);
1474 if (
const auto *CI = dyn_cast<CallInst>(&
I)) {
1479 if (SCCNodes.contains(
Callee))
1497 if (SCCNodes.contains(
Callee))
1508 AttributeInferer AI;
1515 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
1518 [](
const Function &
F) {
return !
F.isConvergent(); },
1524 LLVM_DEBUG(
dbgs() <<
"Removing convergent attr from fn " <<
F.getName()
1526 F.setNotConvergent();
1530 AI.run(SCCNodes, Changed);
1541 AttributeInferer AI;
1549 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
1550 Attribute::NoUnwind,
1552 [](
const Function &
F) {
return F.doesNotThrow(); },
1559 <<
"Adding nounwind attr to fn " <<
F.getName() <<
"\n");
1560 F.setDoesNotThrow();
1572 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
1575 [](
const Function &
F) {
return F.doesNotFreeMemory(); },
1582 <<
"Adding nofree attr to fn " <<
F.getName() <<
"\n");
1583 F.setDoesNotFreeMemory();
1589 AI.run(SCCNodes, Changed);
1597 if (SCCNodes.size() != 1)
1601 if (!
F || !
F->hasExactDefinition() ||
F->doesNotRecurse())
1608 for (
auto &
I :
BB.instructionsWithoutDebug())
1609 if (
auto *CB = dyn_cast<CallBase>(&
I)) {
1619 F->setDoesNotRecurse();
1625 if (
auto *CB = dyn_cast<CallBase>(&
I))
1626 return CB->
hasFnAttr(Attribute::NoReturn);
1633 if (!isa<ReturnInst>(
BB.getTerminator()))
1644 Worklist.push_back(&
F.front());
1651 if (Visited.
insert(Succ).second)
1652 Worklist.push_back(Succ);
1653 }
while (!Worklist.empty());
1662 if (!
F || !
F->hasExactDefinition() ||
F->hasFnAttribute(Attribute::Naked) ||
1667 F->setDoesNotReturn();
1677 if (!
F.hasExactDefinition())
1681 if (
F.mustProgress() &&
F.onlyReadsMemory())
1685 if (
F.isDeclaration())
1692 if (!Backedges.empty())
1698 return I.willReturn();
1724 if (
auto *FI = dyn_cast<FenceInst>(
I))
1727 else if (isa<AtomicCmpXchgInst>(
I) || isa<AtomicRMWInst>(
I))
1729 else if (
auto *
SI = dyn_cast<StoreInst>(
I))
1730 return !
SI->isUnordered();
1731 else if (
auto *LI = dyn_cast<LoadInst>(
I))
1732 return !LI->isUnordered();
1747 auto *CB = dyn_cast<CallBase>(&
I);
1758 if (
auto *
MI = dyn_cast<MemIntrinsic>(&
I))
1759 if (!
MI->isVolatile())
1764 if (SCCNodes.contains(
Callee))
1773 AttributeInferer AI;
1774 AI.registerAttrInference(AttributeInferer::InferenceDescriptor{
1777 [](
const Function &
F) {
return F.hasNoSync(); },
1784 <<
"Adding nosync attr to fn " <<
F.getName() <<
"\n");
1789 AI.run(SCCNodes, Changed);
1794 Res.HasUnknownCall =
false;
1796 if (!
F ||
F->hasOptNone() ||
F->hasFnAttribute(Attribute::Naked) ||
1797 F->isPresplitCoroutine()) {
1800 Res.HasUnknownCall =
true;
1807 if (!Res.HasUnknownCall) {
1809 if (
auto *CB = dyn_cast<CallBase>(&
I)) {
1811 Res.HasUnknownCall =
true;
1817 Res.SCCNodes.insert(
F);
1822 template <
typename AARGetterT>
1828 if (Nodes.SCCNodes.empty())
1842 if (!Nodes.HasUnknownCall) {
1878 Functions.push_back(&
N.getFunction());
1882 if (ChangedFunctions.empty())
1890 for (
Function *Changed : ChangedFunctions) {
1896 for (
auto *U : Changed->users()) {
1897 if (
auto *Call = dyn_cast<CallBase>(U)) {
1898 if (Call->getCalledFunction() == Changed)
1937 "Deduce function attributes",
false,
false)
1944 return new PostOrderFunctionAttrsLegacyPass();
1947 template <
typename AARGetterT>
1951 Functions.push_back(
I->getFunction());
1965 struct ReversePostOrderFunctionAttrsLegacyPass :
public ModulePass {
1969 ReversePostOrderFunctionAttrsLegacyPass() :
ModulePass(
ID) {
1974 bool runOnModule(
Module &M)
override;
1988 "rpo-function-attrs",
"Deduce function attributes in RPO",
1996 return new ReversePostOrderFunctionAttrsLegacyPass();
2003 assert(!
F.isDeclaration() &&
"Cannot deduce norecurse without a definition!");
2005 "This function has already been deduced as norecurs!");
2006 assert(
F.hasInternalLinkage() &&
2007 "Can only do top-down deduction for internal linkage functions!");
2017 for (
auto *U :
F.users()) {
2018 auto *
I = dyn_cast<Instruction>(U);
2025 F.setDoesNotRecurse();
2044 if (
F && !
F->isDeclaration() && !
F->doesNotRecurse() &&
2045 F->hasInternalLinkage())
2046 Worklist.push_back(
F);
2049 bool Changed =
false;
2056 bool ReversePostOrderFunctionAttrsLegacyPass::runOnModule(
Module &M) {
2060 auto &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
A set of analyses that are preserved following a run of a transformation pass.
This class represents an incoming formal argument to a Function.
A manager for alias analyses.
static MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
This is an optimization pass for GlobalISel generic memory operations.
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
Return a value (possibly void), from a function.
This class represents the va_arg llvm instruction, which returns an argument of the specified type gi...
op_range incoming_values()
An analysis pass to compute the CallGraph for a Module.
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.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
const Function * getParent() const
Return the enclosing method, or null if none.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
const Value * Ptr
The address of the start of the location.
ArrayRef< EdgeTy > calls() const
Return the list of <CalleeValueInfo, CalleeInfo> pairs.
FFlags fflags() const
Get function summary flags.
void invalidate(IRUnitT &IR, const PreservedAnalyses &PA)
Invalidate cached analyses for an IR unit.
INITIALIZE_PASS_BEGIN(PostOrderFunctionAttrsLegacyPass, "function-attrs", "Deduce function attributes", false, false) INITIALIZE_PASS_END(PostOrderFunctionAttrsLegacyPass
This callback is used in conjunction with PointerMayBeCaptured.
size_type size() const
Determine the number of elements in the SetVector.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
static bool isLocalLinkage(LinkageTypes Linkage)
static void addNoSyncAttr(const SCCNodeSet &SCCNodes, SmallSet< Function *, 8 > &Changed)
This templated class represents "all analyses that operate over <a particular IR unit>" (e....
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_NODISCARD ModRefInfo createModRefInfo(const FunctionModRefBehavior FMRB)
rpo function Deduce function attributes in RPO
static bool canReturn(Function &F)
The basic data container for the call graph of a Module of IR.
FunctionAnalysisManager FAM
bool hasFnAttr(Attribute::AttrKind Kind) const
Determine whether this call has the given attribute.
static bool onlyAccessesArgPointees(FunctionModRefBehavior MRB)
Checks if functions with the specified behavior are known to read and write at most from objects poin...
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.
auto reverse(ContainerTy &&C, std::enable_if_t< has_rbegin< ContainerTy >::value > *=nullptr)
const_iterator end(StringRef path)
Get end iterator over path.
static bool instructionDoesNotReturn(Instruction &I)
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
bool isCallee(Value::const_user_iterator UI) const
Determine whether the passed iterator points to the callee operand's Use.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
ArgumentGraphNode * NodeRef
auto successors(MachineBasicBlock *BB)
static bool isReturnNonNull(Function *F, const SCCNodeSet &SCCNodes, bool &Speculative)
Tests whether this function is known to not return null.
LLVM_NODISCARD T pop_back_val()
static cl::opt< bool > DisableNoUnwindInference("disable-nounwind-inference", cl::Hidden, cl::desc("Stop inferring nounwind attribute during function-attrs pass"))
static bool isLinkOnceODRLinkage(LinkageTypes Linkage)
static SCCNodesResult createSCCNodeSet(ArrayRef< Function * > Functions)
static ChildIteratorType child_end(NodeRef N)
@ FMRL_Anywhere
Access to any memory.
static void addArgumentReturnedAttrs(const SCCNodeSet &SCCNodes, SmallSet< Function *, 8 > &Changed)
Deduce returned attributes for the SCC.
static bool runImpl(CallGraphSCC &SCC, AARGetterT AARGetter)
void getAAResultsAnalysisUsage(AnalysisUsage &AU)
A helper for the legacy pass manager to populate AU to add uses to make sure the analyses required by...
static bool addAccessAttr(Argument *A, Attribute::AttrKind R)
SmallPtrSet< MachineInstr *, 2 > Uses
static bool isFunctionMallocLike(Function *F, const SCCNodeSet &SCCNodes)
Tests whether a function is "malloc-like".
LLVM Basic Block Representation.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
Function and variable summary information to aid decisions and implementation of importing.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
static bool functionWillReturn(const Function &F)
CallGraphSCC - This is a single SCC that a CallGraphSCCPass is run on.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
An SCC of the call graph.
@ Ref
The access may reference the value stored in memory.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
static bool isLinkOnceAnyLinkage(LinkageTypes Linkage)
Value * getIncomingValue(unsigned i) const
Return incoming value number x.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static bool InstrBreaksNonThrowing(Instruction &I, const SCCNodeSet &SCCNodes)
Helper for NoUnwind inference predicate InstrBreaksAttribute.
(vector float) vec_cmpeq(*A, *B) C
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
static SmallSet< Function *, 8 > deriveAttrsInPostOrder(ArrayRef< Function * > Functions, AARGetterT &&AARGetter)
Represent the analysis usage information of a pass.
static bool addNoRecurseAttrsTopDown(Function &F)
static cl::opt< bool > DisableThinLTOPropagation("disable-thinlto-funcattrs", cl::init(true), cl::Hidden, cl::desc("Don't propagate function-attrs in thinLTO"))
bool isConvergent() const
Determine if the invoke is convergent.
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."))
bool inferAttributesFromOthers(Function &F)
If we can infer one attribute from another on the declaration of a function, explicitly materialize t...
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool isWeakODRLinkage(LinkageTypes Linkage)
@ FMRL_ArgumentPointees
Access to memory via argument pointers.
The object format emitted by the WebAssembly backed is documented in
static void addNoAliasAttrs(const SCCNodeSet &SCCNodes, SmallSet< Function *, 8 > &Changed)
Deduce noalias attributes for the SCC.
STATISTIC(NumFunctions, "Total number of functions")
static bool addArgumentAttrsFromCallsites(Function &F)
If a callsite has arguments that are also arguments to the parent function, try to propagate attribut...
static void addArgumentAttrs(const SCCNodeSet &SCCNodes, SmallSet< Function *, 8 > &Changed)
Deduce nocapture attributes for the SCC.
const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=6)
This method strips off any GEP address adjustments and pointer casts from the specified value,...
A node in the call graph for a module.
static ChildIteratorType nodes_end(ArgumentGraph *AG)
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 cl::opt< bool > DisableNoFreeInference("disable-nofree-inference", cl::Hidden, cl::desc("Stop inferring nofree attribute during function-attrs pass"))
LLVM_NODISCARD bool isModSet(const ModRefInfo MRI)
unsigned getNumIncomingValues() const
Return the number of incoming edges.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
bool onlyReadsMemory(unsigned OpNo) const
Struct that holds a reference to a particular GUID in a global value summary.
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
scc_iterator< T > scc_begin(const T &G)
Construct the begin iterator for a deduced graph type T.
An efficient, type-erasing, non-owning reference to a callable.
static void addWillReturn(const SCCNodeSet &SCCNodes, SmallSet< Function *, 8 > &Changed)
static void addNoReturnAttrs(const SCCNodeSet &SCCNodes, SmallSet< Function *, 8 > &Changed)
inst_range instructions(Function *F)
An instruction for storing to memory.
LLVM_NODISCARD bool isNoModRef(const ModRefInfo MRI)
This is an important base class in LLVM.
bool doesNotAccessMemory(unsigned OpNo) const
void getAnalysisUsage(AnalysisUsage &Info) const override
getAnalysisUsage - For this class, we declare that we require and preserve the call graph.
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
@ None
No attributes have been set.
Pass * createReversePostOrderFunctionAttrsPass()
createReversePostOrderFunctionAttrsPass - This pass walks SCCs of the call graph in RPO to deduce and...
Enumerate the SCCs of a directed graph in reverse topological order of the SCC DAG.
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
void preserve()
Mark an analysis as preserved.
static void addNonNullAttrs(const SCCNodeSet &SCCNodes, SmallSet< Function *, 8 > &Changed)
Deduce nonnull attributes for the SCC.
The ModulePass which wraps up a CallGraph and the logic to build it.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
AttrKind
This enumeration lists the attributes that can be associated with parameters, function results,...
initializer< Ty > init(const Ty &Val)
bool doesNotCapture(unsigned OpNo) const
Determine whether this data operand is not captured.
Pass * createPostOrderFunctionAttrsLegacyPass()
Create a legacy pass manager instance of a pass to compute function attrs in post-order.
ModRefInfo
Flags indicating whether a memory access modifies or references memory.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool isExternalLinkage(LinkageTypes Linkage)
bool hasOperandBundles() const
Return true if this User has any operand bundles.
static bool InstrBreaksNonConvergent(Instruction &I, const SCCNodeSet &SCCNodes)
Helper for non-Convergent inference predicate InstrBreaksAttribute.
StandardInstrumentations SI(Debug, VerifyEach)
static Attribute::AttrKind determinePointerAccessAttrs(Argument *A, const SmallPtrSet< Argument *, 8 > &SCCNodes)
Returns Attribute::None, Attribute::ReadOnly or Attribute::ReadNone.
This class represents the LLVM 'select' instruction.
print Print MemDeps of function
static bool isAvailableExternallyLinkage(LinkageTypes Linkage)
A Module instance is used to store all the information related to an LLVM module.
bool doesNotRecurse() const
Determine if the function is known not to recurse, directly or indirectly.
@ FMRB_DoesNotAccessMemory
This function does not perform any non-local loads or stores to memory.
Flags specific to function summaries.
A node in the call graph.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
FunctionModRefBehavior computeFunctionBodyMemoryAccess(Function &F, AAResults &AAR)
Returns the memory access properties of this copy of the function.
bool insert(const value_type &X)
Insert a new element into the SetVector.
static FunctionModRefBehavior 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...
void initializeReversePostOrderFunctionAttrsLegacyPassPass(PassRegistry &)
static FunctionSummary * calculatePrevailingSummary(ValueInfo VI, DenseMap< ValueInfo, FunctionSummary * > &CachedPrevailingSummary, function_ref< bool(GlobalValue::GUID, const GlobalValueSummary *)> IsPrevailing)
An immutable pass that tracks lazily created AssumptionCache objects.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
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...
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
static NodeRef getEntryNode(ArgumentGraph *AG)
void initializePostOrderFunctionAttrsLegacyPassPass(PassRegistry &)
void setPreservesCFG()
This function should be called by the pass, iff they do not:
static bool basicBlockCanReturn(BasicBlock &BB)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Type * getType() const
All values are typed, get the type of this value.
Represents analyses that only rely on functions' control flow.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
@ Mod
The access may modify the value stored in memory.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
FunctionModRefBehavior
Summary of how a function affects memory in the program.
SmallVectorImpl< ArgumentGraphNode * >::iterator ChildIteratorType
std::pair< NoneType, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
bool hasRetAttr(Attribute::AttrKind Kind) const
Determine whether the return value has the given attribute.
bool dataOperandHasImpliedAttr(unsigned i, Attribute::AttrKind Kind) const
Return true if the data operand at index i has the attribute A.
#define LLVM_FALLTHROUGH
LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
An instruction for reading from memory.
FunctionModRefBehavior getModRefBehavior(const CallBase *Call)
Return the behavior of the given call site.
unsigned const MachineRegisterInfo * MRI
amdgpu Simplify well known AMD library false FunctionCallee Callee
Support structure for SCC passes to communicate updates the call graph back to the CGSCC pass manager...
Function summary information to aid decisions and implementation of importing.
unsigned getDataOperandNo(Value::const_user_iterator UI) const
Given a value use iterator, return the data operand corresponding to it.
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 isArgOperand(const Use *U) const
PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR)
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
unsigned arg_size() const
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.
bool isGuaranteedToTransferExecutionToSuccessor(const Instruction *I)
Return true if this function can prove that the instruction I will always transfer execution to one o...
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)
bool pointsToConstantMemory(const MemoryLocation &Loc, bool OrLocal=false)
Checks whether the given location points to constant memory, or if OrLocal is true whether it points ...
static void addMemoryAttrs(const SCCNodeSet &SCCNodes, AARGetterT &&AARGetter, SmallSet< Function *, 8 > &Changed)
Deduce readonly/readnone/writeonly attributes for the SCC.
static bool InstrBreaksNoFree(Instruction &I, const SCCNodeSet &SCCNodes)
Helper for NoFree inference predicate InstrBreaksAttribute.
static NodeRef getEntryNode(NodeRef A)
Pass interface - Implemented by all 'passes'.
void preserveSet()
Mark an analysis set as preserved.
static ChildIteratorType nodes_begin(ArgumentGraph *AG)
Class to hold module path string table and global value map, and encapsulate methods for operating on...
LLVM_NODISCARD bool isRefSet(const ModRefInfo MRI)
typename SuperClass::iterator iterator
Value * getArgOperand(unsigned i) const
function Deduce function attributes
const BasicBlock * getParent() const
static bool isWeakAnyLinkage(LinkageTypes Linkage)
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...
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
A SetVector that performs no allocations if smaller than a certain size.
A container for analyses that lazily runs them and caches their results.
Common register allocation spilling lr str ldr sxth r3 ldr mla r4 can lr mov lr str ldr sxth r3 mla r4 and then merge mul and lr str ldr sxth r3 mla r4 It also increase the likelihood the store may become dead bb27 Successors according to LLVM BB
AnalysisUsage & addRequired()
Value * getOperand(unsigned i) const
AttributeMask & addAttribute(Attribute::AttrKind Val)
Add an attribute to the mask.
A lazily constructed view of the call graph of a module.
static bool isOrderedAtomic(Instruction *I)
A proxy from a FunctionAnalysisManager to an SCC.
static bool deduceFunctionAttributeInRPO(Module &M, CallGraph &CG)
This class is a functor to be used in legacy module or SCC passes for computing AA results for a func...
LLVM Value Representation.
static ChildIteratorType child_begin(NodeRef N)
Representation for a specific memory location.
A Use represents the edge between a Value definition and its users.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.