1*9880d681SAndroid Build Coastguard Worker //===- FunctionAttrs.cpp - Pass which marks functions attributes ----------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker ///
10*9880d681SAndroid Build Coastguard Worker /// \file
11*9880d681SAndroid Build Coastguard Worker /// This file implements interprocedural passes which walk the
12*9880d681SAndroid Build Coastguard Worker /// call-graph deducing and/or propagating function attributes.
13*9880d681SAndroid Build Coastguard Worker ///
14*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
15*9880d681SAndroid Build Coastguard Worker
16*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/IPO/FunctionAttrs.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/IPO.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SCCIterator.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SetVector.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallSet.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Statistic.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/StringSwitch.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/AliasAnalysis.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/AssumptionCache.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/BasicAliasAnalysis.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/CallGraph.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/CallGraphSCCPass.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/CaptureTracking.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/TargetLibraryInfo.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/ValueTracking.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/GlobalVariable.h"
32*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/InstIterator.h"
33*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/IntrinsicInst.h"
34*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/LLVMContext.h"
35*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
36*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
37*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/TargetLibraryInfo.h"
38*9880d681SAndroid Build Coastguard Worker using namespace llvm;
39*9880d681SAndroid Build Coastguard Worker
40*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "functionattrs"
41*9880d681SAndroid Build Coastguard Worker
42*9880d681SAndroid Build Coastguard Worker STATISTIC(NumReadNone, "Number of functions marked readnone");
43*9880d681SAndroid Build Coastguard Worker STATISTIC(NumReadOnly, "Number of functions marked readonly");
44*9880d681SAndroid Build Coastguard Worker STATISTIC(NumNoCapture, "Number of arguments marked nocapture");
45*9880d681SAndroid Build Coastguard Worker STATISTIC(NumReadNoneArg, "Number of arguments marked readnone");
46*9880d681SAndroid Build Coastguard Worker STATISTIC(NumReadOnlyArg, "Number of arguments marked readonly");
47*9880d681SAndroid Build Coastguard Worker STATISTIC(NumNoAlias, "Number of function returns marked noalias");
48*9880d681SAndroid Build Coastguard Worker STATISTIC(NumNonNullReturn, "Number of function returns marked nonnull");
49*9880d681SAndroid Build Coastguard Worker STATISTIC(NumNoRecurse, "Number of functions marked as norecurse");
50*9880d681SAndroid Build Coastguard Worker
51*9880d681SAndroid Build Coastguard Worker namespace {
52*9880d681SAndroid Build Coastguard Worker typedef SmallSetVector<Function *, 8> SCCNodeSet;
53*9880d681SAndroid Build Coastguard Worker }
54*9880d681SAndroid Build Coastguard Worker
55*9880d681SAndroid Build Coastguard Worker namespace {
56*9880d681SAndroid Build Coastguard Worker /// The three kinds of memory access relevant to 'readonly' and
57*9880d681SAndroid Build Coastguard Worker /// 'readnone' attributes.
58*9880d681SAndroid Build Coastguard Worker enum MemoryAccessKind {
59*9880d681SAndroid Build Coastguard Worker MAK_ReadNone = 0,
60*9880d681SAndroid Build Coastguard Worker MAK_ReadOnly = 1,
61*9880d681SAndroid Build Coastguard Worker MAK_MayWrite = 2
62*9880d681SAndroid Build Coastguard Worker };
63*9880d681SAndroid Build Coastguard Worker }
64*9880d681SAndroid Build Coastguard Worker
checkFunctionMemoryAccess(Function & F,AAResults & AAR,const SCCNodeSet & SCCNodes)65*9880d681SAndroid Build Coastguard Worker static MemoryAccessKind checkFunctionMemoryAccess(Function &F, AAResults &AAR,
66*9880d681SAndroid Build Coastguard Worker const SCCNodeSet &SCCNodes) {
67*9880d681SAndroid Build Coastguard Worker FunctionModRefBehavior MRB = AAR.getModRefBehavior(&F);
68*9880d681SAndroid Build Coastguard Worker if (MRB == FMRB_DoesNotAccessMemory)
69*9880d681SAndroid Build Coastguard Worker // Already perfect!
70*9880d681SAndroid Build Coastguard Worker return MAK_ReadNone;
71*9880d681SAndroid Build Coastguard Worker
72*9880d681SAndroid Build Coastguard Worker // Non-exact function definitions may not be selected at link time, and an
73*9880d681SAndroid Build Coastguard Worker // alternative version that writes to memory may be selected. See the comment
74*9880d681SAndroid Build Coastguard Worker // on GlobalValue::isDefinitionExact for more details.
75*9880d681SAndroid Build Coastguard Worker if (!F.hasExactDefinition()) {
76*9880d681SAndroid Build Coastguard Worker if (AliasAnalysis::onlyReadsMemory(MRB))
77*9880d681SAndroid Build Coastguard Worker return MAK_ReadOnly;
78*9880d681SAndroid Build Coastguard Worker
79*9880d681SAndroid Build Coastguard Worker // Conservatively assume it writes to memory.
80*9880d681SAndroid Build Coastguard Worker return MAK_MayWrite;
81*9880d681SAndroid Build Coastguard Worker }
82*9880d681SAndroid Build Coastguard Worker
83*9880d681SAndroid Build Coastguard Worker // Scan the function body for instructions that may read or write memory.
84*9880d681SAndroid Build Coastguard Worker bool ReadsMemory = false;
85*9880d681SAndroid Build Coastguard Worker for (inst_iterator II = inst_begin(F), E = inst_end(F); II != E; ++II) {
86*9880d681SAndroid Build Coastguard Worker Instruction *I = &*II;
87*9880d681SAndroid Build Coastguard Worker
88*9880d681SAndroid Build Coastguard Worker // Some instructions can be ignored even if they read or write memory.
89*9880d681SAndroid Build Coastguard Worker // Detect these now, skipping to the next instruction if one is found.
90*9880d681SAndroid Build Coastguard Worker CallSite CS(cast<Value>(I));
91*9880d681SAndroid Build Coastguard Worker if (CS) {
92*9880d681SAndroid Build Coastguard Worker // Ignore calls to functions in the same SCC, as long as the call sites
93*9880d681SAndroid Build Coastguard Worker // don't have operand bundles. Calls with operand bundles are allowed to
94*9880d681SAndroid Build Coastguard Worker // have memory effects not described by the memory effects of the call
95*9880d681SAndroid Build Coastguard Worker // target.
96*9880d681SAndroid Build Coastguard Worker if (!CS.hasOperandBundles() && CS.getCalledFunction() &&
97*9880d681SAndroid Build Coastguard Worker SCCNodes.count(CS.getCalledFunction()))
98*9880d681SAndroid Build Coastguard Worker continue;
99*9880d681SAndroid Build Coastguard Worker FunctionModRefBehavior MRB = AAR.getModRefBehavior(CS);
100*9880d681SAndroid Build Coastguard Worker
101*9880d681SAndroid Build Coastguard Worker // If the call doesn't access memory, we're done.
102*9880d681SAndroid Build Coastguard Worker if (!(MRB & MRI_ModRef))
103*9880d681SAndroid Build Coastguard Worker continue;
104*9880d681SAndroid Build Coastguard Worker
105*9880d681SAndroid Build Coastguard Worker if (!AliasAnalysis::onlyAccessesArgPointees(MRB)) {
106*9880d681SAndroid Build Coastguard Worker // The call could access any memory. If that includes writes, give up.
107*9880d681SAndroid Build Coastguard Worker if (MRB & MRI_Mod)
108*9880d681SAndroid Build Coastguard Worker return MAK_MayWrite;
109*9880d681SAndroid Build Coastguard Worker // If it reads, note it.
110*9880d681SAndroid Build Coastguard Worker if (MRB & MRI_Ref)
111*9880d681SAndroid Build Coastguard Worker ReadsMemory = true;
112*9880d681SAndroid Build Coastguard Worker continue;
113*9880d681SAndroid Build Coastguard Worker }
114*9880d681SAndroid Build Coastguard Worker
115*9880d681SAndroid Build Coastguard Worker // Check whether all pointer arguments point to local memory, and
116*9880d681SAndroid Build Coastguard Worker // ignore calls that only access local memory.
117*9880d681SAndroid Build Coastguard Worker for (CallSite::arg_iterator CI = CS.arg_begin(), CE = CS.arg_end();
118*9880d681SAndroid Build Coastguard Worker CI != CE; ++CI) {
119*9880d681SAndroid Build Coastguard Worker Value *Arg = *CI;
120*9880d681SAndroid Build Coastguard Worker if (!Arg->getType()->isPtrOrPtrVectorTy())
121*9880d681SAndroid Build Coastguard Worker continue;
122*9880d681SAndroid Build Coastguard Worker
123*9880d681SAndroid Build Coastguard Worker AAMDNodes AAInfo;
124*9880d681SAndroid Build Coastguard Worker I->getAAMetadata(AAInfo);
125*9880d681SAndroid Build Coastguard Worker MemoryLocation Loc(Arg, MemoryLocation::UnknownSize, AAInfo);
126*9880d681SAndroid Build Coastguard Worker
127*9880d681SAndroid Build Coastguard Worker // Skip accesses to local or constant memory as they don't impact the
128*9880d681SAndroid Build Coastguard Worker // externally visible mod/ref behavior.
129*9880d681SAndroid Build Coastguard Worker if (AAR.pointsToConstantMemory(Loc, /*OrLocal=*/true))
130*9880d681SAndroid Build Coastguard Worker continue;
131*9880d681SAndroid Build Coastguard Worker
132*9880d681SAndroid Build Coastguard Worker if (MRB & MRI_Mod)
133*9880d681SAndroid Build Coastguard Worker // Writes non-local memory. Give up.
134*9880d681SAndroid Build Coastguard Worker return MAK_MayWrite;
135*9880d681SAndroid Build Coastguard Worker if (MRB & MRI_Ref)
136*9880d681SAndroid Build Coastguard Worker // Ok, it reads non-local memory.
137*9880d681SAndroid Build Coastguard Worker ReadsMemory = true;
138*9880d681SAndroid Build Coastguard Worker }
139*9880d681SAndroid Build Coastguard Worker continue;
140*9880d681SAndroid Build Coastguard Worker } else if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
141*9880d681SAndroid Build Coastguard Worker // Ignore non-volatile loads from local memory. (Atomic is okay here.)
142*9880d681SAndroid Build Coastguard Worker if (!LI->isVolatile()) {
143*9880d681SAndroid Build Coastguard Worker MemoryLocation Loc = MemoryLocation::get(LI);
144*9880d681SAndroid Build Coastguard Worker if (AAR.pointsToConstantMemory(Loc, /*OrLocal=*/true))
145*9880d681SAndroid Build Coastguard Worker continue;
146*9880d681SAndroid Build Coastguard Worker }
147*9880d681SAndroid Build Coastguard Worker } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
148*9880d681SAndroid Build Coastguard Worker // Ignore non-volatile stores to local memory. (Atomic is okay here.)
149*9880d681SAndroid Build Coastguard Worker if (!SI->isVolatile()) {
150*9880d681SAndroid Build Coastguard Worker MemoryLocation Loc = MemoryLocation::get(SI);
151*9880d681SAndroid Build Coastguard Worker if (AAR.pointsToConstantMemory(Loc, /*OrLocal=*/true))
152*9880d681SAndroid Build Coastguard Worker continue;
153*9880d681SAndroid Build Coastguard Worker }
154*9880d681SAndroid Build Coastguard Worker } else if (VAArgInst *VI = dyn_cast<VAArgInst>(I)) {
155*9880d681SAndroid Build Coastguard Worker // Ignore vaargs on local memory.
156*9880d681SAndroid Build Coastguard Worker MemoryLocation Loc = MemoryLocation::get(VI);
157*9880d681SAndroid Build Coastguard Worker if (AAR.pointsToConstantMemory(Loc, /*OrLocal=*/true))
158*9880d681SAndroid Build Coastguard Worker continue;
159*9880d681SAndroid Build Coastguard Worker }
160*9880d681SAndroid Build Coastguard Worker
161*9880d681SAndroid Build Coastguard Worker // Any remaining instructions need to be taken seriously! Check if they
162*9880d681SAndroid Build Coastguard Worker // read or write memory.
163*9880d681SAndroid Build Coastguard Worker if (I->mayWriteToMemory())
164*9880d681SAndroid Build Coastguard Worker // Writes memory. Just give up.
165*9880d681SAndroid Build Coastguard Worker return MAK_MayWrite;
166*9880d681SAndroid Build Coastguard Worker
167*9880d681SAndroid Build Coastguard Worker // If this instruction may read memory, remember that.
168*9880d681SAndroid Build Coastguard Worker ReadsMemory |= I->mayReadFromMemory();
169*9880d681SAndroid Build Coastguard Worker }
170*9880d681SAndroid Build Coastguard Worker
171*9880d681SAndroid Build Coastguard Worker return ReadsMemory ? MAK_ReadOnly : MAK_ReadNone;
172*9880d681SAndroid Build Coastguard Worker }
173*9880d681SAndroid Build Coastguard Worker
174*9880d681SAndroid Build Coastguard Worker /// Deduce readonly/readnone attributes for the SCC.
175*9880d681SAndroid Build Coastguard Worker template <typename AARGetterT>
addReadAttrs(const SCCNodeSet & SCCNodes,AARGetterT AARGetter)176*9880d681SAndroid Build Coastguard Worker static bool addReadAttrs(const SCCNodeSet &SCCNodes, AARGetterT AARGetter) {
177*9880d681SAndroid Build Coastguard Worker // Check if any of the functions in the SCC read or write memory. If they
178*9880d681SAndroid Build Coastguard Worker // write memory then they can't be marked readnone or readonly.
179*9880d681SAndroid Build Coastguard Worker bool ReadsMemory = false;
180*9880d681SAndroid Build Coastguard Worker for (Function *F : SCCNodes) {
181*9880d681SAndroid Build Coastguard Worker // Call the callable parameter to look up AA results for this function.
182*9880d681SAndroid Build Coastguard Worker AAResults &AAR = AARGetter(*F);
183*9880d681SAndroid Build Coastguard Worker
184*9880d681SAndroid Build Coastguard Worker switch (checkFunctionMemoryAccess(*F, AAR, SCCNodes)) {
185*9880d681SAndroid Build Coastguard Worker case MAK_MayWrite:
186*9880d681SAndroid Build Coastguard Worker return false;
187*9880d681SAndroid Build Coastguard Worker case MAK_ReadOnly:
188*9880d681SAndroid Build Coastguard Worker ReadsMemory = true;
189*9880d681SAndroid Build Coastguard Worker break;
190*9880d681SAndroid Build Coastguard Worker case MAK_ReadNone:
191*9880d681SAndroid Build Coastguard Worker // Nothing to do!
192*9880d681SAndroid Build Coastguard Worker break;
193*9880d681SAndroid Build Coastguard Worker }
194*9880d681SAndroid Build Coastguard Worker }
195*9880d681SAndroid Build Coastguard Worker
196*9880d681SAndroid Build Coastguard Worker // Success! Functions in this SCC do not access memory, or only read memory.
197*9880d681SAndroid Build Coastguard Worker // Give them the appropriate attribute.
198*9880d681SAndroid Build Coastguard Worker bool MadeChange = false;
199*9880d681SAndroid Build Coastguard Worker for (Function *F : SCCNodes) {
200*9880d681SAndroid Build Coastguard Worker if (F->doesNotAccessMemory())
201*9880d681SAndroid Build Coastguard Worker // Already perfect!
202*9880d681SAndroid Build Coastguard Worker continue;
203*9880d681SAndroid Build Coastguard Worker
204*9880d681SAndroid Build Coastguard Worker if (F->onlyReadsMemory() && ReadsMemory)
205*9880d681SAndroid Build Coastguard Worker // No change.
206*9880d681SAndroid Build Coastguard Worker continue;
207*9880d681SAndroid Build Coastguard Worker
208*9880d681SAndroid Build Coastguard Worker MadeChange = true;
209*9880d681SAndroid Build Coastguard Worker
210*9880d681SAndroid Build Coastguard Worker // Clear out any existing attributes.
211*9880d681SAndroid Build Coastguard Worker AttrBuilder B;
212*9880d681SAndroid Build Coastguard Worker B.addAttribute(Attribute::ReadOnly).addAttribute(Attribute::ReadNone);
213*9880d681SAndroid Build Coastguard Worker F->removeAttributes(
214*9880d681SAndroid Build Coastguard Worker AttributeSet::FunctionIndex,
215*9880d681SAndroid Build Coastguard Worker AttributeSet::get(F->getContext(), AttributeSet::FunctionIndex, B));
216*9880d681SAndroid Build Coastguard Worker
217*9880d681SAndroid Build Coastguard Worker // Add in the new attribute.
218*9880d681SAndroid Build Coastguard Worker F->addAttribute(AttributeSet::FunctionIndex,
219*9880d681SAndroid Build Coastguard Worker ReadsMemory ? Attribute::ReadOnly : Attribute::ReadNone);
220*9880d681SAndroid Build Coastguard Worker
221*9880d681SAndroid Build Coastguard Worker if (ReadsMemory)
222*9880d681SAndroid Build Coastguard Worker ++NumReadOnly;
223*9880d681SAndroid Build Coastguard Worker else
224*9880d681SAndroid Build Coastguard Worker ++NumReadNone;
225*9880d681SAndroid Build Coastguard Worker }
226*9880d681SAndroid Build Coastguard Worker
227*9880d681SAndroid Build Coastguard Worker return MadeChange;
228*9880d681SAndroid Build Coastguard Worker }
229*9880d681SAndroid Build Coastguard Worker
230*9880d681SAndroid Build Coastguard Worker namespace {
231*9880d681SAndroid Build Coastguard Worker /// For a given pointer Argument, this retains a list of Arguments of functions
232*9880d681SAndroid Build Coastguard Worker /// in the same SCC that the pointer data flows into. We use this to build an
233*9880d681SAndroid Build Coastguard Worker /// SCC of the arguments.
234*9880d681SAndroid Build Coastguard Worker struct ArgumentGraphNode {
235*9880d681SAndroid Build Coastguard Worker Argument *Definition;
236*9880d681SAndroid Build Coastguard Worker SmallVector<ArgumentGraphNode *, 4> Uses;
237*9880d681SAndroid Build Coastguard Worker };
238*9880d681SAndroid Build Coastguard Worker
239*9880d681SAndroid Build Coastguard Worker class ArgumentGraph {
240*9880d681SAndroid Build Coastguard Worker // We store pointers to ArgumentGraphNode objects, so it's important that
241*9880d681SAndroid Build Coastguard Worker // that they not move around upon insert.
242*9880d681SAndroid Build Coastguard Worker typedef std::map<Argument *, ArgumentGraphNode> ArgumentMapTy;
243*9880d681SAndroid Build Coastguard Worker
244*9880d681SAndroid Build Coastguard Worker ArgumentMapTy ArgumentMap;
245*9880d681SAndroid Build Coastguard Worker
246*9880d681SAndroid Build Coastguard Worker // There is no root node for the argument graph, in fact:
247*9880d681SAndroid Build Coastguard Worker // void f(int *x, int *y) { if (...) f(x, y); }
248*9880d681SAndroid Build Coastguard Worker // is an example where the graph is disconnected. The SCCIterator requires a
249*9880d681SAndroid Build Coastguard Worker // single entry point, so we maintain a fake ("synthetic") root node that
250*9880d681SAndroid Build Coastguard Worker // uses every node. Because the graph is directed and nothing points into
251*9880d681SAndroid Build Coastguard Worker // the root, it will not participate in any SCCs (except for its own).
252*9880d681SAndroid Build Coastguard Worker ArgumentGraphNode SyntheticRoot;
253*9880d681SAndroid Build Coastguard Worker
254*9880d681SAndroid Build Coastguard Worker public:
ArgumentGraph()255*9880d681SAndroid Build Coastguard Worker ArgumentGraph() { SyntheticRoot.Definition = nullptr; }
256*9880d681SAndroid Build Coastguard Worker
257*9880d681SAndroid Build Coastguard Worker typedef SmallVectorImpl<ArgumentGraphNode *>::iterator iterator;
258*9880d681SAndroid Build Coastguard Worker
begin()259*9880d681SAndroid Build Coastguard Worker iterator begin() { return SyntheticRoot.Uses.begin(); }
end()260*9880d681SAndroid Build Coastguard Worker iterator end() { return SyntheticRoot.Uses.end(); }
getEntryNode()261*9880d681SAndroid Build Coastguard Worker ArgumentGraphNode *getEntryNode() { return &SyntheticRoot; }
262*9880d681SAndroid Build Coastguard Worker
operator [](Argument * A)263*9880d681SAndroid Build Coastguard Worker ArgumentGraphNode *operator[](Argument *A) {
264*9880d681SAndroid Build Coastguard Worker ArgumentGraphNode &Node = ArgumentMap[A];
265*9880d681SAndroid Build Coastguard Worker Node.Definition = A;
266*9880d681SAndroid Build Coastguard Worker SyntheticRoot.Uses.push_back(&Node);
267*9880d681SAndroid Build Coastguard Worker return &Node;
268*9880d681SAndroid Build Coastguard Worker }
269*9880d681SAndroid Build Coastguard Worker };
270*9880d681SAndroid Build Coastguard Worker
271*9880d681SAndroid Build Coastguard Worker /// This tracker checks whether callees are in the SCC, and if so it does not
272*9880d681SAndroid Build Coastguard Worker /// consider that a capture, instead adding it to the "Uses" list and
273*9880d681SAndroid Build Coastguard Worker /// continuing with the analysis.
274*9880d681SAndroid Build Coastguard Worker struct ArgumentUsesTracker : public CaptureTracker {
ArgumentUsesTracker__anon5ca92ef10311::ArgumentUsesTracker275*9880d681SAndroid Build Coastguard Worker ArgumentUsesTracker(const SCCNodeSet &SCCNodes)
276*9880d681SAndroid Build Coastguard Worker : Captured(false), SCCNodes(SCCNodes) {}
277*9880d681SAndroid Build Coastguard Worker
tooManyUses__anon5ca92ef10311::ArgumentUsesTracker278*9880d681SAndroid Build Coastguard Worker void tooManyUses() override { Captured = true; }
279*9880d681SAndroid Build Coastguard Worker
captured__anon5ca92ef10311::ArgumentUsesTracker280*9880d681SAndroid Build Coastguard Worker bool captured(const Use *U) override {
281*9880d681SAndroid Build Coastguard Worker CallSite CS(U->getUser());
282*9880d681SAndroid Build Coastguard Worker if (!CS.getInstruction()) {
283*9880d681SAndroid Build Coastguard Worker Captured = true;
284*9880d681SAndroid Build Coastguard Worker return true;
285*9880d681SAndroid Build Coastguard Worker }
286*9880d681SAndroid Build Coastguard Worker
287*9880d681SAndroid Build Coastguard Worker Function *F = CS.getCalledFunction();
288*9880d681SAndroid Build Coastguard Worker if (!F || !F->hasExactDefinition() || !SCCNodes.count(F)) {
289*9880d681SAndroid Build Coastguard Worker Captured = true;
290*9880d681SAndroid Build Coastguard Worker return true;
291*9880d681SAndroid Build Coastguard Worker }
292*9880d681SAndroid Build Coastguard Worker
293*9880d681SAndroid Build Coastguard Worker // Note: the callee and the two successor blocks *follow* the argument
294*9880d681SAndroid Build Coastguard Worker // operands. This means there is no need to adjust UseIndex to account for
295*9880d681SAndroid Build Coastguard Worker // these.
296*9880d681SAndroid Build Coastguard Worker
297*9880d681SAndroid Build Coastguard Worker unsigned UseIndex =
298*9880d681SAndroid Build Coastguard Worker std::distance(const_cast<const Use *>(CS.arg_begin()), U);
299*9880d681SAndroid Build Coastguard Worker
300*9880d681SAndroid Build Coastguard Worker assert(UseIndex < CS.data_operands_size() &&
301*9880d681SAndroid Build Coastguard Worker "Indirect function calls should have been filtered above!");
302*9880d681SAndroid Build Coastguard Worker
303*9880d681SAndroid Build Coastguard Worker if (UseIndex >= CS.getNumArgOperands()) {
304*9880d681SAndroid Build Coastguard Worker // Data operand, but not a argument operand -- must be a bundle operand
305*9880d681SAndroid Build Coastguard Worker assert(CS.hasOperandBundles() && "Must be!");
306*9880d681SAndroid Build Coastguard Worker
307*9880d681SAndroid Build Coastguard Worker // CaptureTracking told us that we're being captured by an operand bundle
308*9880d681SAndroid Build Coastguard Worker // use. In this case it does not matter if the callee is within our SCC
309*9880d681SAndroid Build Coastguard Worker // or not -- we've been captured in some unknown way, and we have to be
310*9880d681SAndroid Build Coastguard Worker // conservative.
311*9880d681SAndroid Build Coastguard Worker Captured = true;
312*9880d681SAndroid Build Coastguard Worker return true;
313*9880d681SAndroid Build Coastguard Worker }
314*9880d681SAndroid Build Coastguard Worker
315*9880d681SAndroid Build Coastguard Worker if (UseIndex >= F->arg_size()) {
316*9880d681SAndroid Build Coastguard Worker assert(F->isVarArg() && "More params than args in non-varargs call");
317*9880d681SAndroid Build Coastguard Worker Captured = true;
318*9880d681SAndroid Build Coastguard Worker return true;
319*9880d681SAndroid Build Coastguard Worker }
320*9880d681SAndroid Build Coastguard Worker
321*9880d681SAndroid Build Coastguard Worker Uses.push_back(&*std::next(F->arg_begin(), UseIndex));
322*9880d681SAndroid Build Coastguard Worker return false;
323*9880d681SAndroid Build Coastguard Worker }
324*9880d681SAndroid Build Coastguard Worker
325*9880d681SAndroid Build Coastguard Worker bool Captured; // True only if certainly captured (used outside our SCC).
326*9880d681SAndroid Build Coastguard Worker SmallVector<Argument *, 4> Uses; // Uses within our SCC.
327*9880d681SAndroid Build Coastguard Worker
328*9880d681SAndroid Build Coastguard Worker const SCCNodeSet &SCCNodes;
329*9880d681SAndroid Build Coastguard Worker };
330*9880d681SAndroid Build Coastguard Worker }
331*9880d681SAndroid Build Coastguard Worker
332*9880d681SAndroid Build Coastguard Worker namespace llvm {
333*9880d681SAndroid Build Coastguard Worker template <> struct GraphTraits<ArgumentGraphNode *> {
334*9880d681SAndroid Build Coastguard Worker typedef ArgumentGraphNode NodeType;
335*9880d681SAndroid Build Coastguard Worker typedef SmallVectorImpl<ArgumentGraphNode *>::iterator ChildIteratorType;
336*9880d681SAndroid Build Coastguard Worker
getEntryNodellvm::GraphTraits337*9880d681SAndroid Build Coastguard Worker static inline NodeType *getEntryNode(NodeType *A) { return A; }
child_beginllvm::GraphTraits338*9880d681SAndroid Build Coastguard Worker static inline ChildIteratorType child_begin(NodeType *N) {
339*9880d681SAndroid Build Coastguard Worker return N->Uses.begin();
340*9880d681SAndroid Build Coastguard Worker }
child_endllvm::GraphTraits341*9880d681SAndroid Build Coastguard Worker static inline ChildIteratorType child_end(NodeType *N) {
342*9880d681SAndroid Build Coastguard Worker return N->Uses.end();
343*9880d681SAndroid Build Coastguard Worker }
344*9880d681SAndroid Build Coastguard Worker };
345*9880d681SAndroid Build Coastguard Worker template <>
346*9880d681SAndroid Build Coastguard Worker struct GraphTraits<ArgumentGraph *> : public GraphTraits<ArgumentGraphNode *> {
getEntryNodellvm::GraphTraits347*9880d681SAndroid Build Coastguard Worker static NodeType *getEntryNode(ArgumentGraph *AG) {
348*9880d681SAndroid Build Coastguard Worker return AG->getEntryNode();
349*9880d681SAndroid Build Coastguard Worker }
nodes_beginllvm::GraphTraits350*9880d681SAndroid Build Coastguard Worker static ChildIteratorType nodes_begin(ArgumentGraph *AG) {
351*9880d681SAndroid Build Coastguard Worker return AG->begin();
352*9880d681SAndroid Build Coastguard Worker }
nodes_endllvm::GraphTraits353*9880d681SAndroid Build Coastguard Worker static ChildIteratorType nodes_end(ArgumentGraph *AG) { return AG->end(); }
354*9880d681SAndroid Build Coastguard Worker };
355*9880d681SAndroid Build Coastguard Worker }
356*9880d681SAndroid Build Coastguard Worker
357*9880d681SAndroid Build Coastguard Worker /// Returns Attribute::None, Attribute::ReadOnly or Attribute::ReadNone.
358*9880d681SAndroid Build Coastguard Worker static Attribute::AttrKind
determinePointerReadAttrs(Argument * A,const SmallPtrSet<Argument *,8> & SCCNodes)359*9880d681SAndroid Build Coastguard Worker determinePointerReadAttrs(Argument *A,
360*9880d681SAndroid Build Coastguard Worker const SmallPtrSet<Argument *, 8> &SCCNodes) {
361*9880d681SAndroid Build Coastguard Worker
362*9880d681SAndroid Build Coastguard Worker SmallVector<Use *, 32> Worklist;
363*9880d681SAndroid Build Coastguard Worker SmallSet<Use *, 32> Visited;
364*9880d681SAndroid Build Coastguard Worker
365*9880d681SAndroid Build Coastguard Worker // inalloca arguments are always clobbered by the call.
366*9880d681SAndroid Build Coastguard Worker if (A->hasInAllocaAttr())
367*9880d681SAndroid Build Coastguard Worker return Attribute::None;
368*9880d681SAndroid Build Coastguard Worker
369*9880d681SAndroid Build Coastguard Worker bool IsRead = false;
370*9880d681SAndroid Build Coastguard Worker // We don't need to track IsWritten. If A is written to, return immediately.
371*9880d681SAndroid Build Coastguard Worker
372*9880d681SAndroid Build Coastguard Worker for (Use &U : A->uses()) {
373*9880d681SAndroid Build Coastguard Worker Visited.insert(&U);
374*9880d681SAndroid Build Coastguard Worker Worklist.push_back(&U);
375*9880d681SAndroid Build Coastguard Worker }
376*9880d681SAndroid Build Coastguard Worker
377*9880d681SAndroid Build Coastguard Worker while (!Worklist.empty()) {
378*9880d681SAndroid Build Coastguard Worker Use *U = Worklist.pop_back_val();
379*9880d681SAndroid Build Coastguard Worker Instruction *I = cast<Instruction>(U->getUser());
380*9880d681SAndroid Build Coastguard Worker
381*9880d681SAndroid Build Coastguard Worker switch (I->getOpcode()) {
382*9880d681SAndroid Build Coastguard Worker case Instruction::BitCast:
383*9880d681SAndroid Build Coastguard Worker case Instruction::GetElementPtr:
384*9880d681SAndroid Build Coastguard Worker case Instruction::PHI:
385*9880d681SAndroid Build Coastguard Worker case Instruction::Select:
386*9880d681SAndroid Build Coastguard Worker case Instruction::AddrSpaceCast:
387*9880d681SAndroid Build Coastguard Worker // The original value is not read/written via this if the new value isn't.
388*9880d681SAndroid Build Coastguard Worker for (Use &UU : I->uses())
389*9880d681SAndroid Build Coastguard Worker if (Visited.insert(&UU).second)
390*9880d681SAndroid Build Coastguard Worker Worklist.push_back(&UU);
391*9880d681SAndroid Build Coastguard Worker break;
392*9880d681SAndroid Build Coastguard Worker
393*9880d681SAndroid Build Coastguard Worker case Instruction::Call:
394*9880d681SAndroid Build Coastguard Worker case Instruction::Invoke: {
395*9880d681SAndroid Build Coastguard Worker bool Captures = true;
396*9880d681SAndroid Build Coastguard Worker
397*9880d681SAndroid Build Coastguard Worker if (I->getType()->isVoidTy())
398*9880d681SAndroid Build Coastguard Worker Captures = false;
399*9880d681SAndroid Build Coastguard Worker
400*9880d681SAndroid Build Coastguard Worker auto AddUsersToWorklistIfCapturing = [&] {
401*9880d681SAndroid Build Coastguard Worker if (Captures)
402*9880d681SAndroid Build Coastguard Worker for (Use &UU : I->uses())
403*9880d681SAndroid Build Coastguard Worker if (Visited.insert(&UU).second)
404*9880d681SAndroid Build Coastguard Worker Worklist.push_back(&UU);
405*9880d681SAndroid Build Coastguard Worker };
406*9880d681SAndroid Build Coastguard Worker
407*9880d681SAndroid Build Coastguard Worker CallSite CS(I);
408*9880d681SAndroid Build Coastguard Worker if (CS.doesNotAccessMemory()) {
409*9880d681SAndroid Build Coastguard Worker AddUsersToWorklistIfCapturing();
410*9880d681SAndroid Build Coastguard Worker continue;
411*9880d681SAndroid Build Coastguard Worker }
412*9880d681SAndroid Build Coastguard Worker
413*9880d681SAndroid Build Coastguard Worker Function *F = CS.getCalledFunction();
414*9880d681SAndroid Build Coastguard Worker if (!F) {
415*9880d681SAndroid Build Coastguard Worker if (CS.onlyReadsMemory()) {
416*9880d681SAndroid Build Coastguard Worker IsRead = true;
417*9880d681SAndroid Build Coastguard Worker AddUsersToWorklistIfCapturing();
418*9880d681SAndroid Build Coastguard Worker continue;
419*9880d681SAndroid Build Coastguard Worker }
420*9880d681SAndroid Build Coastguard Worker return Attribute::None;
421*9880d681SAndroid Build Coastguard Worker }
422*9880d681SAndroid Build Coastguard Worker
423*9880d681SAndroid Build Coastguard Worker // Note: the callee and the two successor blocks *follow* the argument
424*9880d681SAndroid Build Coastguard Worker // operands. This means there is no need to adjust UseIndex to account
425*9880d681SAndroid Build Coastguard Worker // for these.
426*9880d681SAndroid Build Coastguard Worker
427*9880d681SAndroid Build Coastguard Worker unsigned UseIndex = std::distance(CS.arg_begin(), U);
428*9880d681SAndroid Build Coastguard Worker
429*9880d681SAndroid Build Coastguard Worker // U cannot be the callee operand use: since we're exploring the
430*9880d681SAndroid Build Coastguard Worker // transitive uses of an Argument, having such a use be a callee would
431*9880d681SAndroid Build Coastguard Worker // imply the CallSite is an indirect call or invoke; and we'd take the
432*9880d681SAndroid Build Coastguard Worker // early exit above.
433*9880d681SAndroid Build Coastguard Worker assert(UseIndex < CS.data_operands_size() &&
434*9880d681SAndroid Build Coastguard Worker "Data operand use expected!");
435*9880d681SAndroid Build Coastguard Worker
436*9880d681SAndroid Build Coastguard Worker bool IsOperandBundleUse = UseIndex >= CS.getNumArgOperands();
437*9880d681SAndroid Build Coastguard Worker
438*9880d681SAndroid Build Coastguard Worker if (UseIndex >= F->arg_size() && !IsOperandBundleUse) {
439*9880d681SAndroid Build Coastguard Worker assert(F->isVarArg() && "More params than args in non-varargs call");
440*9880d681SAndroid Build Coastguard Worker return Attribute::None;
441*9880d681SAndroid Build Coastguard Worker }
442*9880d681SAndroid Build Coastguard Worker
443*9880d681SAndroid Build Coastguard Worker Captures &= !CS.doesNotCapture(UseIndex);
444*9880d681SAndroid Build Coastguard Worker
445*9880d681SAndroid Build Coastguard Worker // Since the optimizer (by design) cannot see the data flow corresponding
446*9880d681SAndroid Build Coastguard Worker // to a operand bundle use, these cannot participate in the optimistic SCC
447*9880d681SAndroid Build Coastguard Worker // analysis. Instead, we model the operand bundle uses as arguments in
448*9880d681SAndroid Build Coastguard Worker // call to a function external to the SCC.
449*9880d681SAndroid Build Coastguard Worker if (!SCCNodes.count(&*std::next(F->arg_begin(), UseIndex)) ||
450*9880d681SAndroid Build Coastguard Worker IsOperandBundleUse) {
451*9880d681SAndroid Build Coastguard Worker
452*9880d681SAndroid Build Coastguard Worker // The accessors used on CallSite here do the right thing for calls and
453*9880d681SAndroid Build Coastguard Worker // invokes with operand bundles.
454*9880d681SAndroid Build Coastguard Worker
455*9880d681SAndroid Build Coastguard Worker if (!CS.onlyReadsMemory() && !CS.onlyReadsMemory(UseIndex))
456*9880d681SAndroid Build Coastguard Worker return Attribute::None;
457*9880d681SAndroid Build Coastguard Worker if (!CS.doesNotAccessMemory(UseIndex))
458*9880d681SAndroid Build Coastguard Worker IsRead = true;
459*9880d681SAndroid Build Coastguard Worker }
460*9880d681SAndroid Build Coastguard Worker
461*9880d681SAndroid Build Coastguard Worker AddUsersToWorklistIfCapturing();
462*9880d681SAndroid Build Coastguard Worker break;
463*9880d681SAndroid Build Coastguard Worker }
464*9880d681SAndroid Build Coastguard Worker
465*9880d681SAndroid Build Coastguard Worker case Instruction::Load:
466*9880d681SAndroid Build Coastguard Worker // A volatile load has side effects beyond what readonly can be relied
467*9880d681SAndroid Build Coastguard Worker // upon.
468*9880d681SAndroid Build Coastguard Worker if (cast<LoadInst>(I)->isVolatile())
469*9880d681SAndroid Build Coastguard Worker return Attribute::None;
470*9880d681SAndroid Build Coastguard Worker
471*9880d681SAndroid Build Coastguard Worker IsRead = true;
472*9880d681SAndroid Build Coastguard Worker break;
473*9880d681SAndroid Build Coastguard Worker
474*9880d681SAndroid Build Coastguard Worker case Instruction::ICmp:
475*9880d681SAndroid Build Coastguard Worker case Instruction::Ret:
476*9880d681SAndroid Build Coastguard Worker break;
477*9880d681SAndroid Build Coastguard Worker
478*9880d681SAndroid Build Coastguard Worker default:
479*9880d681SAndroid Build Coastguard Worker return Attribute::None;
480*9880d681SAndroid Build Coastguard Worker }
481*9880d681SAndroid Build Coastguard Worker }
482*9880d681SAndroid Build Coastguard Worker
483*9880d681SAndroid Build Coastguard Worker return IsRead ? Attribute::ReadOnly : Attribute::ReadNone;
484*9880d681SAndroid Build Coastguard Worker }
485*9880d681SAndroid Build Coastguard Worker
486*9880d681SAndroid Build Coastguard Worker /// Deduce nocapture attributes for the SCC.
addArgumentAttrs(const SCCNodeSet & SCCNodes)487*9880d681SAndroid Build Coastguard Worker static bool addArgumentAttrs(const SCCNodeSet &SCCNodes) {
488*9880d681SAndroid Build Coastguard Worker bool Changed = false;
489*9880d681SAndroid Build Coastguard Worker
490*9880d681SAndroid Build Coastguard Worker ArgumentGraph AG;
491*9880d681SAndroid Build Coastguard Worker
492*9880d681SAndroid Build Coastguard Worker AttrBuilder B;
493*9880d681SAndroid Build Coastguard Worker B.addAttribute(Attribute::NoCapture);
494*9880d681SAndroid Build Coastguard Worker
495*9880d681SAndroid Build Coastguard Worker // Check each function in turn, determining which pointer arguments are not
496*9880d681SAndroid Build Coastguard Worker // captured.
497*9880d681SAndroid Build Coastguard Worker for (Function *F : SCCNodes) {
498*9880d681SAndroid Build Coastguard Worker // We can infer and propagate function attributes only when we know that the
499*9880d681SAndroid Build Coastguard Worker // definition we'll get at link time is *exactly* the definition we see now.
500*9880d681SAndroid Build Coastguard Worker // For more details, see GlobalValue::mayBeDerefined.
501*9880d681SAndroid Build Coastguard Worker if (!F->hasExactDefinition())
502*9880d681SAndroid Build Coastguard Worker continue;
503*9880d681SAndroid Build Coastguard Worker
504*9880d681SAndroid Build Coastguard Worker // Functions that are readonly (or readnone) and nounwind and don't return
505*9880d681SAndroid Build Coastguard Worker // a value can't capture arguments. Don't analyze them.
506*9880d681SAndroid Build Coastguard Worker if (F->onlyReadsMemory() && F->doesNotThrow() &&
507*9880d681SAndroid Build Coastguard Worker F->getReturnType()->isVoidTy()) {
508*9880d681SAndroid Build Coastguard Worker for (Function::arg_iterator A = F->arg_begin(), E = F->arg_end(); A != E;
509*9880d681SAndroid Build Coastguard Worker ++A) {
510*9880d681SAndroid Build Coastguard Worker if (A->getType()->isPointerTy() && !A->hasNoCaptureAttr()) {
511*9880d681SAndroid Build Coastguard Worker A->addAttr(AttributeSet::get(F->getContext(), A->getArgNo() + 1, B));
512*9880d681SAndroid Build Coastguard Worker ++NumNoCapture;
513*9880d681SAndroid Build Coastguard Worker Changed = true;
514*9880d681SAndroid Build Coastguard Worker }
515*9880d681SAndroid Build Coastguard Worker }
516*9880d681SAndroid Build Coastguard Worker continue;
517*9880d681SAndroid Build Coastguard Worker }
518*9880d681SAndroid Build Coastguard Worker
519*9880d681SAndroid Build Coastguard Worker for (Function::arg_iterator A = F->arg_begin(), E = F->arg_end(); A != E;
520*9880d681SAndroid Build Coastguard Worker ++A) {
521*9880d681SAndroid Build Coastguard Worker if (!A->getType()->isPointerTy())
522*9880d681SAndroid Build Coastguard Worker continue;
523*9880d681SAndroid Build Coastguard Worker bool HasNonLocalUses = false;
524*9880d681SAndroid Build Coastguard Worker if (!A->hasNoCaptureAttr()) {
525*9880d681SAndroid Build Coastguard Worker ArgumentUsesTracker Tracker(SCCNodes);
526*9880d681SAndroid Build Coastguard Worker PointerMayBeCaptured(&*A, &Tracker);
527*9880d681SAndroid Build Coastguard Worker if (!Tracker.Captured) {
528*9880d681SAndroid Build Coastguard Worker if (Tracker.Uses.empty()) {
529*9880d681SAndroid Build Coastguard Worker // If it's trivially not captured, mark it nocapture now.
530*9880d681SAndroid Build Coastguard Worker A->addAttr(
531*9880d681SAndroid Build Coastguard Worker AttributeSet::get(F->getContext(), A->getArgNo() + 1, B));
532*9880d681SAndroid Build Coastguard Worker ++NumNoCapture;
533*9880d681SAndroid Build Coastguard Worker Changed = true;
534*9880d681SAndroid Build Coastguard Worker } else {
535*9880d681SAndroid Build Coastguard Worker // If it's not trivially captured and not trivially not captured,
536*9880d681SAndroid Build Coastguard Worker // then it must be calling into another function in our SCC. Save
537*9880d681SAndroid Build Coastguard Worker // its particulars for Argument-SCC analysis later.
538*9880d681SAndroid Build Coastguard Worker ArgumentGraphNode *Node = AG[&*A];
539*9880d681SAndroid Build Coastguard Worker for (Argument *Use : Tracker.Uses) {
540*9880d681SAndroid Build Coastguard Worker Node->Uses.push_back(AG[Use]);
541*9880d681SAndroid Build Coastguard Worker if (Use != &*A)
542*9880d681SAndroid Build Coastguard Worker HasNonLocalUses = true;
543*9880d681SAndroid Build Coastguard Worker }
544*9880d681SAndroid Build Coastguard Worker }
545*9880d681SAndroid Build Coastguard Worker }
546*9880d681SAndroid Build Coastguard Worker // Otherwise, it's captured. Don't bother doing SCC analysis on it.
547*9880d681SAndroid Build Coastguard Worker }
548*9880d681SAndroid Build Coastguard Worker if (!HasNonLocalUses && !A->onlyReadsMemory()) {
549*9880d681SAndroid Build Coastguard Worker // Can we determine that it's readonly/readnone without doing an SCC?
550*9880d681SAndroid Build Coastguard Worker // Note that we don't allow any calls at all here, or else our result
551*9880d681SAndroid Build Coastguard Worker // will be dependent on the iteration order through the functions in the
552*9880d681SAndroid Build Coastguard Worker // SCC.
553*9880d681SAndroid Build Coastguard Worker SmallPtrSet<Argument *, 8> Self;
554*9880d681SAndroid Build Coastguard Worker Self.insert(&*A);
555*9880d681SAndroid Build Coastguard Worker Attribute::AttrKind R = determinePointerReadAttrs(&*A, Self);
556*9880d681SAndroid Build Coastguard Worker if (R != Attribute::None) {
557*9880d681SAndroid Build Coastguard Worker AttrBuilder B;
558*9880d681SAndroid Build Coastguard Worker B.addAttribute(R);
559*9880d681SAndroid Build Coastguard Worker A->addAttr(AttributeSet::get(A->getContext(), A->getArgNo() + 1, B));
560*9880d681SAndroid Build Coastguard Worker Changed = true;
561*9880d681SAndroid Build Coastguard Worker R == Attribute::ReadOnly ? ++NumReadOnlyArg : ++NumReadNoneArg;
562*9880d681SAndroid Build Coastguard Worker }
563*9880d681SAndroid Build Coastguard Worker }
564*9880d681SAndroid Build Coastguard Worker }
565*9880d681SAndroid Build Coastguard Worker }
566*9880d681SAndroid Build Coastguard Worker
567*9880d681SAndroid Build Coastguard Worker // The graph we've collected is partial because we stopped scanning for
568*9880d681SAndroid Build Coastguard Worker // argument uses once we solved the argument trivially. These partial nodes
569*9880d681SAndroid Build Coastguard Worker // show up as ArgumentGraphNode objects with an empty Uses list, and for
570*9880d681SAndroid Build Coastguard Worker // these nodes the final decision about whether they capture has already been
571*9880d681SAndroid Build Coastguard Worker // made. If the definition doesn't have a 'nocapture' attribute by now, it
572*9880d681SAndroid Build Coastguard Worker // captures.
573*9880d681SAndroid Build Coastguard Worker
574*9880d681SAndroid Build Coastguard Worker for (scc_iterator<ArgumentGraph *> I = scc_begin(&AG); !I.isAtEnd(); ++I) {
575*9880d681SAndroid Build Coastguard Worker const std::vector<ArgumentGraphNode *> &ArgumentSCC = *I;
576*9880d681SAndroid Build Coastguard Worker if (ArgumentSCC.size() == 1) {
577*9880d681SAndroid Build Coastguard Worker if (!ArgumentSCC[0]->Definition)
578*9880d681SAndroid Build Coastguard Worker continue; // synthetic root node
579*9880d681SAndroid Build Coastguard Worker
580*9880d681SAndroid Build Coastguard Worker // eg. "void f(int* x) { if (...) f(x); }"
581*9880d681SAndroid Build Coastguard Worker if (ArgumentSCC[0]->Uses.size() == 1 &&
582*9880d681SAndroid Build Coastguard Worker ArgumentSCC[0]->Uses[0] == ArgumentSCC[0]) {
583*9880d681SAndroid Build Coastguard Worker Argument *A = ArgumentSCC[0]->Definition;
584*9880d681SAndroid Build Coastguard Worker A->addAttr(AttributeSet::get(A->getContext(), A->getArgNo() + 1, B));
585*9880d681SAndroid Build Coastguard Worker ++NumNoCapture;
586*9880d681SAndroid Build Coastguard Worker Changed = true;
587*9880d681SAndroid Build Coastguard Worker }
588*9880d681SAndroid Build Coastguard Worker continue;
589*9880d681SAndroid Build Coastguard Worker }
590*9880d681SAndroid Build Coastguard Worker
591*9880d681SAndroid Build Coastguard Worker bool SCCCaptured = false;
592*9880d681SAndroid Build Coastguard Worker for (auto I = ArgumentSCC.begin(), E = ArgumentSCC.end();
593*9880d681SAndroid Build Coastguard Worker I != E && !SCCCaptured; ++I) {
594*9880d681SAndroid Build Coastguard Worker ArgumentGraphNode *Node = *I;
595*9880d681SAndroid Build Coastguard Worker if (Node->Uses.empty()) {
596*9880d681SAndroid Build Coastguard Worker if (!Node->Definition->hasNoCaptureAttr())
597*9880d681SAndroid Build Coastguard Worker SCCCaptured = true;
598*9880d681SAndroid Build Coastguard Worker }
599*9880d681SAndroid Build Coastguard Worker }
600*9880d681SAndroid Build Coastguard Worker if (SCCCaptured)
601*9880d681SAndroid Build Coastguard Worker continue;
602*9880d681SAndroid Build Coastguard Worker
603*9880d681SAndroid Build Coastguard Worker SmallPtrSet<Argument *, 8> ArgumentSCCNodes;
604*9880d681SAndroid Build Coastguard Worker // Fill ArgumentSCCNodes with the elements of the ArgumentSCC. Used for
605*9880d681SAndroid Build Coastguard Worker // quickly looking up whether a given Argument is in this ArgumentSCC.
606*9880d681SAndroid Build Coastguard Worker for (ArgumentGraphNode *I : ArgumentSCC) {
607*9880d681SAndroid Build Coastguard Worker ArgumentSCCNodes.insert(I->Definition);
608*9880d681SAndroid Build Coastguard Worker }
609*9880d681SAndroid Build Coastguard Worker
610*9880d681SAndroid Build Coastguard Worker for (auto I = ArgumentSCC.begin(), E = ArgumentSCC.end();
611*9880d681SAndroid Build Coastguard Worker I != E && !SCCCaptured; ++I) {
612*9880d681SAndroid Build Coastguard Worker ArgumentGraphNode *N = *I;
613*9880d681SAndroid Build Coastguard Worker for (ArgumentGraphNode *Use : N->Uses) {
614*9880d681SAndroid Build Coastguard Worker Argument *A = Use->Definition;
615*9880d681SAndroid Build Coastguard Worker if (A->hasNoCaptureAttr() || ArgumentSCCNodes.count(A))
616*9880d681SAndroid Build Coastguard Worker continue;
617*9880d681SAndroid Build Coastguard Worker SCCCaptured = true;
618*9880d681SAndroid Build Coastguard Worker break;
619*9880d681SAndroid Build Coastguard Worker }
620*9880d681SAndroid Build Coastguard Worker }
621*9880d681SAndroid Build Coastguard Worker if (SCCCaptured)
622*9880d681SAndroid Build Coastguard Worker continue;
623*9880d681SAndroid Build Coastguard Worker
624*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = ArgumentSCC.size(); i != e; ++i) {
625*9880d681SAndroid Build Coastguard Worker Argument *A = ArgumentSCC[i]->Definition;
626*9880d681SAndroid Build Coastguard Worker A->addAttr(AttributeSet::get(A->getContext(), A->getArgNo() + 1, B));
627*9880d681SAndroid Build Coastguard Worker ++NumNoCapture;
628*9880d681SAndroid Build Coastguard Worker Changed = true;
629*9880d681SAndroid Build Coastguard Worker }
630*9880d681SAndroid Build Coastguard Worker
631*9880d681SAndroid Build Coastguard Worker // We also want to compute readonly/readnone. With a small number of false
632*9880d681SAndroid Build Coastguard Worker // negatives, we can assume that any pointer which is captured isn't going
633*9880d681SAndroid Build Coastguard Worker // to be provably readonly or readnone, since by definition we can't
634*9880d681SAndroid Build Coastguard Worker // analyze all uses of a captured pointer.
635*9880d681SAndroid Build Coastguard Worker //
636*9880d681SAndroid Build Coastguard Worker // The false negatives happen when the pointer is captured by a function
637*9880d681SAndroid Build Coastguard Worker // that promises readonly/readnone behaviour on the pointer, then the
638*9880d681SAndroid Build Coastguard Worker // pointer's lifetime ends before anything that writes to arbitrary memory.
639*9880d681SAndroid Build Coastguard Worker // Also, a readonly/readnone pointer may be returned, but returning a
640*9880d681SAndroid Build Coastguard Worker // pointer is capturing it.
641*9880d681SAndroid Build Coastguard Worker
642*9880d681SAndroid Build Coastguard Worker Attribute::AttrKind ReadAttr = Attribute::ReadNone;
643*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = ArgumentSCC.size(); i != e; ++i) {
644*9880d681SAndroid Build Coastguard Worker Argument *A = ArgumentSCC[i]->Definition;
645*9880d681SAndroid Build Coastguard Worker Attribute::AttrKind K = determinePointerReadAttrs(A, ArgumentSCCNodes);
646*9880d681SAndroid Build Coastguard Worker if (K == Attribute::ReadNone)
647*9880d681SAndroid Build Coastguard Worker continue;
648*9880d681SAndroid Build Coastguard Worker if (K == Attribute::ReadOnly) {
649*9880d681SAndroid Build Coastguard Worker ReadAttr = Attribute::ReadOnly;
650*9880d681SAndroid Build Coastguard Worker continue;
651*9880d681SAndroid Build Coastguard Worker }
652*9880d681SAndroid Build Coastguard Worker ReadAttr = K;
653*9880d681SAndroid Build Coastguard Worker break;
654*9880d681SAndroid Build Coastguard Worker }
655*9880d681SAndroid Build Coastguard Worker
656*9880d681SAndroid Build Coastguard Worker if (ReadAttr != Attribute::None) {
657*9880d681SAndroid Build Coastguard Worker AttrBuilder B, R;
658*9880d681SAndroid Build Coastguard Worker B.addAttribute(ReadAttr);
659*9880d681SAndroid Build Coastguard Worker R.addAttribute(Attribute::ReadOnly).addAttribute(Attribute::ReadNone);
660*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = ArgumentSCC.size(); i != e; ++i) {
661*9880d681SAndroid Build Coastguard Worker Argument *A = ArgumentSCC[i]->Definition;
662*9880d681SAndroid Build Coastguard Worker // Clear out existing readonly/readnone attributes
663*9880d681SAndroid Build Coastguard Worker A->removeAttr(AttributeSet::get(A->getContext(), A->getArgNo() + 1, R));
664*9880d681SAndroid Build Coastguard Worker A->addAttr(AttributeSet::get(A->getContext(), A->getArgNo() + 1, B));
665*9880d681SAndroid Build Coastguard Worker ReadAttr == Attribute::ReadOnly ? ++NumReadOnlyArg : ++NumReadNoneArg;
666*9880d681SAndroid Build Coastguard Worker Changed = true;
667*9880d681SAndroid Build Coastguard Worker }
668*9880d681SAndroid Build Coastguard Worker }
669*9880d681SAndroid Build Coastguard Worker }
670*9880d681SAndroid Build Coastguard Worker
671*9880d681SAndroid Build Coastguard Worker return Changed;
672*9880d681SAndroid Build Coastguard Worker }
673*9880d681SAndroid Build Coastguard Worker
674*9880d681SAndroid Build Coastguard Worker /// Tests whether a function is "malloc-like".
675*9880d681SAndroid Build Coastguard Worker ///
676*9880d681SAndroid Build Coastguard Worker /// A function is "malloc-like" if it returns either null or a pointer that
677*9880d681SAndroid Build Coastguard Worker /// doesn't alias any other pointer visible to the caller.
isFunctionMallocLike(Function * F,const SCCNodeSet & SCCNodes)678*9880d681SAndroid Build Coastguard Worker static bool isFunctionMallocLike(Function *F, const SCCNodeSet &SCCNodes) {
679*9880d681SAndroid Build Coastguard Worker SmallSetVector<Value *, 8> FlowsToReturn;
680*9880d681SAndroid Build Coastguard Worker for (BasicBlock &BB : *F)
681*9880d681SAndroid Build Coastguard Worker if (ReturnInst *Ret = dyn_cast<ReturnInst>(BB.getTerminator()))
682*9880d681SAndroid Build Coastguard Worker FlowsToReturn.insert(Ret->getReturnValue());
683*9880d681SAndroid Build Coastguard Worker
684*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i != FlowsToReturn.size(); ++i) {
685*9880d681SAndroid Build Coastguard Worker Value *RetVal = FlowsToReturn[i];
686*9880d681SAndroid Build Coastguard Worker
687*9880d681SAndroid Build Coastguard Worker if (Constant *C = dyn_cast<Constant>(RetVal)) {
688*9880d681SAndroid Build Coastguard Worker if (!C->isNullValue() && !isa<UndefValue>(C))
689*9880d681SAndroid Build Coastguard Worker return false;
690*9880d681SAndroid Build Coastguard Worker
691*9880d681SAndroid Build Coastguard Worker continue;
692*9880d681SAndroid Build Coastguard Worker }
693*9880d681SAndroid Build Coastguard Worker
694*9880d681SAndroid Build Coastguard Worker if (isa<Argument>(RetVal))
695*9880d681SAndroid Build Coastguard Worker return false;
696*9880d681SAndroid Build Coastguard Worker
697*9880d681SAndroid Build Coastguard Worker if (Instruction *RVI = dyn_cast<Instruction>(RetVal))
698*9880d681SAndroid Build Coastguard Worker switch (RVI->getOpcode()) {
699*9880d681SAndroid Build Coastguard Worker // Extend the analysis by looking upwards.
700*9880d681SAndroid Build Coastguard Worker case Instruction::BitCast:
701*9880d681SAndroid Build Coastguard Worker case Instruction::GetElementPtr:
702*9880d681SAndroid Build Coastguard Worker case Instruction::AddrSpaceCast:
703*9880d681SAndroid Build Coastguard Worker FlowsToReturn.insert(RVI->getOperand(0));
704*9880d681SAndroid Build Coastguard Worker continue;
705*9880d681SAndroid Build Coastguard Worker case Instruction::Select: {
706*9880d681SAndroid Build Coastguard Worker SelectInst *SI = cast<SelectInst>(RVI);
707*9880d681SAndroid Build Coastguard Worker FlowsToReturn.insert(SI->getTrueValue());
708*9880d681SAndroid Build Coastguard Worker FlowsToReturn.insert(SI->getFalseValue());
709*9880d681SAndroid Build Coastguard Worker continue;
710*9880d681SAndroid Build Coastguard Worker }
711*9880d681SAndroid Build Coastguard Worker case Instruction::PHI: {
712*9880d681SAndroid Build Coastguard Worker PHINode *PN = cast<PHINode>(RVI);
713*9880d681SAndroid Build Coastguard Worker for (Value *IncValue : PN->incoming_values())
714*9880d681SAndroid Build Coastguard Worker FlowsToReturn.insert(IncValue);
715*9880d681SAndroid Build Coastguard Worker continue;
716*9880d681SAndroid Build Coastguard Worker }
717*9880d681SAndroid Build Coastguard Worker
718*9880d681SAndroid Build Coastguard Worker // Check whether the pointer came from an allocation.
719*9880d681SAndroid Build Coastguard Worker case Instruction::Alloca:
720*9880d681SAndroid Build Coastguard Worker break;
721*9880d681SAndroid Build Coastguard Worker case Instruction::Call:
722*9880d681SAndroid Build Coastguard Worker case Instruction::Invoke: {
723*9880d681SAndroid Build Coastguard Worker CallSite CS(RVI);
724*9880d681SAndroid Build Coastguard Worker if (CS.paramHasAttr(0, Attribute::NoAlias))
725*9880d681SAndroid Build Coastguard Worker break;
726*9880d681SAndroid Build Coastguard Worker if (CS.getCalledFunction() && SCCNodes.count(CS.getCalledFunction()))
727*9880d681SAndroid Build Coastguard Worker break;
728*9880d681SAndroid Build Coastguard Worker } // fall-through
729*9880d681SAndroid Build Coastguard Worker default:
730*9880d681SAndroid Build Coastguard Worker return false; // Did not come from an allocation.
731*9880d681SAndroid Build Coastguard Worker }
732*9880d681SAndroid Build Coastguard Worker
733*9880d681SAndroid Build Coastguard Worker if (PointerMayBeCaptured(RetVal, false, /*StoreCaptures=*/false))
734*9880d681SAndroid Build Coastguard Worker return false;
735*9880d681SAndroid Build Coastguard Worker }
736*9880d681SAndroid Build Coastguard Worker
737*9880d681SAndroid Build Coastguard Worker return true;
738*9880d681SAndroid Build Coastguard Worker }
739*9880d681SAndroid Build Coastguard Worker
740*9880d681SAndroid Build Coastguard Worker /// Deduce noalias attributes for the SCC.
addNoAliasAttrs(const SCCNodeSet & SCCNodes)741*9880d681SAndroid Build Coastguard Worker static bool addNoAliasAttrs(const SCCNodeSet &SCCNodes) {
742*9880d681SAndroid Build Coastguard Worker // Check each function in turn, determining which functions return noalias
743*9880d681SAndroid Build Coastguard Worker // pointers.
744*9880d681SAndroid Build Coastguard Worker for (Function *F : SCCNodes) {
745*9880d681SAndroid Build Coastguard Worker // Already noalias.
746*9880d681SAndroid Build Coastguard Worker if (F->doesNotAlias(0))
747*9880d681SAndroid Build Coastguard Worker continue;
748*9880d681SAndroid Build Coastguard Worker
749*9880d681SAndroid Build Coastguard Worker // We can infer and propagate function attributes only when we know that the
750*9880d681SAndroid Build Coastguard Worker // definition we'll get at link time is *exactly* the definition we see now.
751*9880d681SAndroid Build Coastguard Worker // For more details, see GlobalValue::mayBeDerefined.
752*9880d681SAndroid Build Coastguard Worker if (!F->hasExactDefinition())
753*9880d681SAndroid Build Coastguard Worker return false;
754*9880d681SAndroid Build Coastguard Worker
755*9880d681SAndroid Build Coastguard Worker // We annotate noalias return values, which are only applicable to
756*9880d681SAndroid Build Coastguard Worker // pointer types.
757*9880d681SAndroid Build Coastguard Worker if (!F->getReturnType()->isPointerTy())
758*9880d681SAndroid Build Coastguard Worker continue;
759*9880d681SAndroid Build Coastguard Worker
760*9880d681SAndroid Build Coastguard Worker if (!isFunctionMallocLike(F, SCCNodes))
761*9880d681SAndroid Build Coastguard Worker return false;
762*9880d681SAndroid Build Coastguard Worker }
763*9880d681SAndroid Build Coastguard Worker
764*9880d681SAndroid Build Coastguard Worker bool MadeChange = false;
765*9880d681SAndroid Build Coastguard Worker for (Function *F : SCCNodes) {
766*9880d681SAndroid Build Coastguard Worker if (F->doesNotAlias(0) || !F->getReturnType()->isPointerTy())
767*9880d681SAndroid Build Coastguard Worker continue;
768*9880d681SAndroid Build Coastguard Worker
769*9880d681SAndroid Build Coastguard Worker F->setDoesNotAlias(0);
770*9880d681SAndroid Build Coastguard Worker ++NumNoAlias;
771*9880d681SAndroid Build Coastguard Worker MadeChange = true;
772*9880d681SAndroid Build Coastguard Worker }
773*9880d681SAndroid Build Coastguard Worker
774*9880d681SAndroid Build Coastguard Worker return MadeChange;
775*9880d681SAndroid Build Coastguard Worker }
776*9880d681SAndroid Build Coastguard Worker
777*9880d681SAndroid Build Coastguard Worker /// Tests whether this function is known to not return null.
778*9880d681SAndroid Build Coastguard Worker ///
779*9880d681SAndroid Build Coastguard Worker /// Requires that the function returns a pointer.
780*9880d681SAndroid Build Coastguard Worker ///
781*9880d681SAndroid Build Coastguard Worker /// Returns true if it believes the function will not return a null, and sets
782*9880d681SAndroid Build Coastguard Worker /// \p Speculative based on whether the returned conclusion is a speculative
783*9880d681SAndroid Build Coastguard Worker /// conclusion due to SCC calls.
isReturnNonNull(Function * F,const SCCNodeSet & SCCNodes,bool & Speculative)784*9880d681SAndroid Build Coastguard Worker static bool isReturnNonNull(Function *F, const SCCNodeSet &SCCNodes,
785*9880d681SAndroid Build Coastguard Worker bool &Speculative) {
786*9880d681SAndroid Build Coastguard Worker assert(F->getReturnType()->isPointerTy() &&
787*9880d681SAndroid Build Coastguard Worker "nonnull only meaningful on pointer types");
788*9880d681SAndroid Build Coastguard Worker Speculative = false;
789*9880d681SAndroid Build Coastguard Worker
790*9880d681SAndroid Build Coastguard Worker SmallSetVector<Value *, 8> FlowsToReturn;
791*9880d681SAndroid Build Coastguard Worker for (BasicBlock &BB : *F)
792*9880d681SAndroid Build Coastguard Worker if (auto *Ret = dyn_cast<ReturnInst>(BB.getTerminator()))
793*9880d681SAndroid Build Coastguard Worker FlowsToReturn.insert(Ret->getReturnValue());
794*9880d681SAndroid Build Coastguard Worker
795*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i != FlowsToReturn.size(); ++i) {
796*9880d681SAndroid Build Coastguard Worker Value *RetVal = FlowsToReturn[i];
797*9880d681SAndroid Build Coastguard Worker
798*9880d681SAndroid Build Coastguard Worker // If this value is locally known to be non-null, we're good
799*9880d681SAndroid Build Coastguard Worker if (isKnownNonNull(RetVal))
800*9880d681SAndroid Build Coastguard Worker continue;
801*9880d681SAndroid Build Coastguard Worker
802*9880d681SAndroid Build Coastguard Worker // Otherwise, we need to look upwards since we can't make any local
803*9880d681SAndroid Build Coastguard Worker // conclusions.
804*9880d681SAndroid Build Coastguard Worker Instruction *RVI = dyn_cast<Instruction>(RetVal);
805*9880d681SAndroid Build Coastguard Worker if (!RVI)
806*9880d681SAndroid Build Coastguard Worker return false;
807*9880d681SAndroid Build Coastguard Worker switch (RVI->getOpcode()) {
808*9880d681SAndroid Build Coastguard Worker // Extend the analysis by looking upwards.
809*9880d681SAndroid Build Coastguard Worker case Instruction::BitCast:
810*9880d681SAndroid Build Coastguard Worker case Instruction::GetElementPtr:
811*9880d681SAndroid Build Coastguard Worker case Instruction::AddrSpaceCast:
812*9880d681SAndroid Build Coastguard Worker FlowsToReturn.insert(RVI->getOperand(0));
813*9880d681SAndroid Build Coastguard Worker continue;
814*9880d681SAndroid Build Coastguard Worker case Instruction::Select: {
815*9880d681SAndroid Build Coastguard Worker SelectInst *SI = cast<SelectInst>(RVI);
816*9880d681SAndroid Build Coastguard Worker FlowsToReturn.insert(SI->getTrueValue());
817*9880d681SAndroid Build Coastguard Worker FlowsToReturn.insert(SI->getFalseValue());
818*9880d681SAndroid Build Coastguard Worker continue;
819*9880d681SAndroid Build Coastguard Worker }
820*9880d681SAndroid Build Coastguard Worker case Instruction::PHI: {
821*9880d681SAndroid Build Coastguard Worker PHINode *PN = cast<PHINode>(RVI);
822*9880d681SAndroid Build Coastguard Worker for (int i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
823*9880d681SAndroid Build Coastguard Worker FlowsToReturn.insert(PN->getIncomingValue(i));
824*9880d681SAndroid Build Coastguard Worker continue;
825*9880d681SAndroid Build Coastguard Worker }
826*9880d681SAndroid Build Coastguard Worker case Instruction::Call:
827*9880d681SAndroid Build Coastguard Worker case Instruction::Invoke: {
828*9880d681SAndroid Build Coastguard Worker CallSite CS(RVI);
829*9880d681SAndroid Build Coastguard Worker Function *Callee = CS.getCalledFunction();
830*9880d681SAndroid Build Coastguard Worker // A call to a node within the SCC is assumed to return null until
831*9880d681SAndroid Build Coastguard Worker // proven otherwise
832*9880d681SAndroid Build Coastguard Worker if (Callee && SCCNodes.count(Callee)) {
833*9880d681SAndroid Build Coastguard Worker Speculative = true;
834*9880d681SAndroid Build Coastguard Worker continue;
835*9880d681SAndroid Build Coastguard Worker }
836*9880d681SAndroid Build Coastguard Worker return false;
837*9880d681SAndroid Build Coastguard Worker }
838*9880d681SAndroid Build Coastguard Worker default:
839*9880d681SAndroid Build Coastguard Worker return false; // Unknown source, may be null
840*9880d681SAndroid Build Coastguard Worker };
841*9880d681SAndroid Build Coastguard Worker llvm_unreachable("should have either continued or returned");
842*9880d681SAndroid Build Coastguard Worker }
843*9880d681SAndroid Build Coastguard Worker
844*9880d681SAndroid Build Coastguard Worker return true;
845*9880d681SAndroid Build Coastguard Worker }
846*9880d681SAndroid Build Coastguard Worker
847*9880d681SAndroid Build Coastguard Worker /// Deduce nonnull attributes for the SCC.
addNonNullAttrs(const SCCNodeSet & SCCNodes)848*9880d681SAndroid Build Coastguard Worker static bool addNonNullAttrs(const SCCNodeSet &SCCNodes) {
849*9880d681SAndroid Build Coastguard Worker // Speculative that all functions in the SCC return only nonnull
850*9880d681SAndroid Build Coastguard Worker // pointers. We may refute this as we analyze functions.
851*9880d681SAndroid Build Coastguard Worker bool SCCReturnsNonNull = true;
852*9880d681SAndroid Build Coastguard Worker
853*9880d681SAndroid Build Coastguard Worker bool MadeChange = false;
854*9880d681SAndroid Build Coastguard Worker
855*9880d681SAndroid Build Coastguard Worker // Check each function in turn, determining which functions return nonnull
856*9880d681SAndroid Build Coastguard Worker // pointers.
857*9880d681SAndroid Build Coastguard Worker for (Function *F : SCCNodes) {
858*9880d681SAndroid Build Coastguard Worker // Already nonnull.
859*9880d681SAndroid Build Coastguard Worker if (F->getAttributes().hasAttribute(AttributeSet::ReturnIndex,
860*9880d681SAndroid Build Coastguard Worker Attribute::NonNull))
861*9880d681SAndroid Build Coastguard Worker continue;
862*9880d681SAndroid Build Coastguard Worker
863*9880d681SAndroid Build Coastguard Worker // We can infer and propagate function attributes only when we know that the
864*9880d681SAndroid Build Coastguard Worker // definition we'll get at link time is *exactly* the definition we see now.
865*9880d681SAndroid Build Coastguard Worker // For more details, see GlobalValue::mayBeDerefined.
866*9880d681SAndroid Build Coastguard Worker if (!F->hasExactDefinition())
867*9880d681SAndroid Build Coastguard Worker return false;
868*9880d681SAndroid Build Coastguard Worker
869*9880d681SAndroid Build Coastguard Worker // We annotate nonnull return values, which are only applicable to
870*9880d681SAndroid Build Coastguard Worker // pointer types.
871*9880d681SAndroid Build Coastguard Worker if (!F->getReturnType()->isPointerTy())
872*9880d681SAndroid Build Coastguard Worker continue;
873*9880d681SAndroid Build Coastguard Worker
874*9880d681SAndroid Build Coastguard Worker bool Speculative = false;
875*9880d681SAndroid Build Coastguard Worker if (isReturnNonNull(F, SCCNodes, Speculative)) {
876*9880d681SAndroid Build Coastguard Worker if (!Speculative) {
877*9880d681SAndroid Build Coastguard Worker // Mark the function eagerly since we may discover a function
878*9880d681SAndroid Build Coastguard Worker // which prevents us from speculating about the entire SCC
879*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Eagerly marking " << F->getName() << " as nonnull\n");
880*9880d681SAndroid Build Coastguard Worker F->addAttribute(AttributeSet::ReturnIndex, Attribute::NonNull);
881*9880d681SAndroid Build Coastguard Worker ++NumNonNullReturn;
882*9880d681SAndroid Build Coastguard Worker MadeChange = true;
883*9880d681SAndroid Build Coastguard Worker }
884*9880d681SAndroid Build Coastguard Worker continue;
885*9880d681SAndroid Build Coastguard Worker }
886*9880d681SAndroid Build Coastguard Worker // At least one function returns something which could be null, can't
887*9880d681SAndroid Build Coastguard Worker // speculate any more.
888*9880d681SAndroid Build Coastguard Worker SCCReturnsNonNull = false;
889*9880d681SAndroid Build Coastguard Worker }
890*9880d681SAndroid Build Coastguard Worker
891*9880d681SAndroid Build Coastguard Worker if (SCCReturnsNonNull) {
892*9880d681SAndroid Build Coastguard Worker for (Function *F : SCCNodes) {
893*9880d681SAndroid Build Coastguard Worker if (F->getAttributes().hasAttribute(AttributeSet::ReturnIndex,
894*9880d681SAndroid Build Coastguard Worker Attribute::NonNull) ||
895*9880d681SAndroid Build Coastguard Worker !F->getReturnType()->isPointerTy())
896*9880d681SAndroid Build Coastguard Worker continue;
897*9880d681SAndroid Build Coastguard Worker
898*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "SCC marking " << F->getName() << " as nonnull\n");
899*9880d681SAndroid Build Coastguard Worker F->addAttribute(AttributeSet::ReturnIndex, Attribute::NonNull);
900*9880d681SAndroid Build Coastguard Worker ++NumNonNullReturn;
901*9880d681SAndroid Build Coastguard Worker MadeChange = true;
902*9880d681SAndroid Build Coastguard Worker }
903*9880d681SAndroid Build Coastguard Worker }
904*9880d681SAndroid Build Coastguard Worker
905*9880d681SAndroid Build Coastguard Worker return MadeChange;
906*9880d681SAndroid Build Coastguard Worker }
907*9880d681SAndroid Build Coastguard Worker
908*9880d681SAndroid Build Coastguard Worker /// Remove the convergent attribute from all functions in the SCC if every
909*9880d681SAndroid Build Coastguard Worker /// callsite within the SCC is not convergent (except for calls to functions
910*9880d681SAndroid Build Coastguard Worker /// within the SCC). Returns true if changes were made.
removeConvergentAttrs(const SCCNodeSet & SCCNodes)911*9880d681SAndroid Build Coastguard Worker static bool removeConvergentAttrs(const SCCNodeSet &SCCNodes) {
912*9880d681SAndroid Build Coastguard Worker // For every function in SCC, ensure that either
913*9880d681SAndroid Build Coastguard Worker // * it is not convergent, or
914*9880d681SAndroid Build Coastguard Worker // * we can remove its convergent attribute.
915*9880d681SAndroid Build Coastguard Worker bool HasConvergentFn = false;
916*9880d681SAndroid Build Coastguard Worker for (Function *F : SCCNodes) {
917*9880d681SAndroid Build Coastguard Worker if (!F->isConvergent()) continue;
918*9880d681SAndroid Build Coastguard Worker HasConvergentFn = true;
919*9880d681SAndroid Build Coastguard Worker
920*9880d681SAndroid Build Coastguard Worker // Can't remove convergent from function declarations.
921*9880d681SAndroid Build Coastguard Worker if (F->isDeclaration()) return false;
922*9880d681SAndroid Build Coastguard Worker
923*9880d681SAndroid Build Coastguard Worker // Can't remove convergent if any of our functions has a convergent call to a
924*9880d681SAndroid Build Coastguard Worker // function not in the SCC.
925*9880d681SAndroid Build Coastguard Worker for (Instruction &I : instructions(*F)) {
926*9880d681SAndroid Build Coastguard Worker CallSite CS(&I);
927*9880d681SAndroid Build Coastguard Worker // Bail if CS is a convergent call to a function not in the SCC.
928*9880d681SAndroid Build Coastguard Worker if (CS && CS.isConvergent() &&
929*9880d681SAndroid Build Coastguard Worker SCCNodes.count(CS.getCalledFunction()) == 0)
930*9880d681SAndroid Build Coastguard Worker return false;
931*9880d681SAndroid Build Coastguard Worker }
932*9880d681SAndroid Build Coastguard Worker }
933*9880d681SAndroid Build Coastguard Worker
934*9880d681SAndroid Build Coastguard Worker // If the SCC doesn't have any convergent functions, we have nothing to do.
935*9880d681SAndroid Build Coastguard Worker if (!HasConvergentFn) return false;
936*9880d681SAndroid Build Coastguard Worker
937*9880d681SAndroid Build Coastguard Worker // If we got here, all of the calls the SCC makes to functions not in the SCC
938*9880d681SAndroid Build Coastguard Worker // are non-convergent. Therefore all of the SCC's functions can also be made
939*9880d681SAndroid Build Coastguard Worker // non-convergent. We'll remove the attr from the callsites in
940*9880d681SAndroid Build Coastguard Worker // InstCombineCalls.
941*9880d681SAndroid Build Coastguard Worker for (Function *F : SCCNodes) {
942*9880d681SAndroid Build Coastguard Worker if (!F->isConvergent()) continue;
943*9880d681SAndroid Build Coastguard Worker
944*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Removing convergent attr from fn " << F->getName()
945*9880d681SAndroid Build Coastguard Worker << "\n");
946*9880d681SAndroid Build Coastguard Worker F->setNotConvergent();
947*9880d681SAndroid Build Coastguard Worker }
948*9880d681SAndroid Build Coastguard Worker return true;
949*9880d681SAndroid Build Coastguard Worker }
950*9880d681SAndroid Build Coastguard Worker
setDoesNotRecurse(Function & F)951*9880d681SAndroid Build Coastguard Worker static bool setDoesNotRecurse(Function &F) {
952*9880d681SAndroid Build Coastguard Worker if (F.doesNotRecurse())
953*9880d681SAndroid Build Coastguard Worker return false;
954*9880d681SAndroid Build Coastguard Worker F.setDoesNotRecurse();
955*9880d681SAndroid Build Coastguard Worker ++NumNoRecurse;
956*9880d681SAndroid Build Coastguard Worker return true;
957*9880d681SAndroid Build Coastguard Worker }
958*9880d681SAndroid Build Coastguard Worker
addNoRecurseAttrs(const SCCNodeSet & SCCNodes)959*9880d681SAndroid Build Coastguard Worker static bool addNoRecurseAttrs(const SCCNodeSet &SCCNodes) {
960*9880d681SAndroid Build Coastguard Worker // Try and identify functions that do not recurse.
961*9880d681SAndroid Build Coastguard Worker
962*9880d681SAndroid Build Coastguard Worker // If the SCC contains multiple nodes we know for sure there is recursion.
963*9880d681SAndroid Build Coastguard Worker if (SCCNodes.size() != 1)
964*9880d681SAndroid Build Coastguard Worker return false;
965*9880d681SAndroid Build Coastguard Worker
966*9880d681SAndroid Build Coastguard Worker Function *F = *SCCNodes.begin();
967*9880d681SAndroid Build Coastguard Worker if (!F || F->isDeclaration() || F->doesNotRecurse())
968*9880d681SAndroid Build Coastguard Worker return false;
969*9880d681SAndroid Build Coastguard Worker
970*9880d681SAndroid Build Coastguard Worker // If all of the calls in F are identifiable and are to norecurse functions, F
971*9880d681SAndroid Build Coastguard Worker // is norecurse. This check also detects self-recursion as F is not currently
972*9880d681SAndroid Build Coastguard Worker // marked norecurse, so any called from F to F will not be marked norecurse.
973*9880d681SAndroid Build Coastguard Worker for (Instruction &I : instructions(*F))
974*9880d681SAndroid Build Coastguard Worker if (auto CS = CallSite(&I)) {
975*9880d681SAndroid Build Coastguard Worker Function *Callee = CS.getCalledFunction();
976*9880d681SAndroid Build Coastguard Worker if (!Callee || Callee == F || !Callee->doesNotRecurse())
977*9880d681SAndroid Build Coastguard Worker // Function calls a potentially recursive function.
978*9880d681SAndroid Build Coastguard Worker return false;
979*9880d681SAndroid Build Coastguard Worker }
980*9880d681SAndroid Build Coastguard Worker
981*9880d681SAndroid Build Coastguard Worker // Every call was to a non-recursive function other than this function, and
982*9880d681SAndroid Build Coastguard Worker // we have no indirect recursion as the SCC size is one. This function cannot
983*9880d681SAndroid Build Coastguard Worker // recurse.
984*9880d681SAndroid Build Coastguard Worker return setDoesNotRecurse(*F);
985*9880d681SAndroid Build Coastguard Worker }
986*9880d681SAndroid Build Coastguard Worker
run(LazyCallGraph::SCC & C,CGSCCAnalysisManager & AM)987*9880d681SAndroid Build Coastguard Worker PreservedAnalyses PostOrderFunctionAttrsPass::run(LazyCallGraph::SCC &C,
988*9880d681SAndroid Build Coastguard Worker CGSCCAnalysisManager &AM) {
989*9880d681SAndroid Build Coastguard Worker FunctionAnalysisManager &FAM =
990*9880d681SAndroid Build Coastguard Worker AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C).getManager();
991*9880d681SAndroid Build Coastguard Worker
992*9880d681SAndroid Build Coastguard Worker // We pass a lambda into functions to wire them up to the analysis manager
993*9880d681SAndroid Build Coastguard Worker // for getting function analyses.
994*9880d681SAndroid Build Coastguard Worker auto AARGetter = [&](Function &F) -> AAResults & {
995*9880d681SAndroid Build Coastguard Worker return FAM.getResult<AAManager>(F);
996*9880d681SAndroid Build Coastguard Worker };
997*9880d681SAndroid Build Coastguard Worker
998*9880d681SAndroid Build Coastguard Worker // Fill SCCNodes with the elements of the SCC. Also track whether there are
999*9880d681SAndroid Build Coastguard Worker // any external or opt-none nodes that will prevent us from optimizing any
1000*9880d681SAndroid Build Coastguard Worker // part of the SCC.
1001*9880d681SAndroid Build Coastguard Worker SCCNodeSet SCCNodes;
1002*9880d681SAndroid Build Coastguard Worker bool HasUnknownCall = false;
1003*9880d681SAndroid Build Coastguard Worker for (LazyCallGraph::Node &N : C) {
1004*9880d681SAndroid Build Coastguard Worker Function &F = N.getFunction();
1005*9880d681SAndroid Build Coastguard Worker if (F.hasFnAttribute(Attribute::OptimizeNone)) {
1006*9880d681SAndroid Build Coastguard Worker // Treat any function we're trying not to optimize as if it were an
1007*9880d681SAndroid Build Coastguard Worker // indirect call and omit it from the node set used below.
1008*9880d681SAndroid Build Coastguard Worker HasUnknownCall = true;
1009*9880d681SAndroid Build Coastguard Worker continue;
1010*9880d681SAndroid Build Coastguard Worker }
1011*9880d681SAndroid Build Coastguard Worker // Track whether any functions in this SCC have an unknown call edge.
1012*9880d681SAndroid Build Coastguard Worker // Note: if this is ever a performance hit, we can common it with
1013*9880d681SAndroid Build Coastguard Worker // subsequent routines which also do scans over the instructions of the
1014*9880d681SAndroid Build Coastguard Worker // function.
1015*9880d681SAndroid Build Coastguard Worker if (!HasUnknownCall)
1016*9880d681SAndroid Build Coastguard Worker for (Instruction &I : instructions(F))
1017*9880d681SAndroid Build Coastguard Worker if (auto CS = CallSite(&I))
1018*9880d681SAndroid Build Coastguard Worker if (!CS.getCalledFunction()) {
1019*9880d681SAndroid Build Coastguard Worker HasUnknownCall = true;
1020*9880d681SAndroid Build Coastguard Worker break;
1021*9880d681SAndroid Build Coastguard Worker }
1022*9880d681SAndroid Build Coastguard Worker
1023*9880d681SAndroid Build Coastguard Worker SCCNodes.insert(&F);
1024*9880d681SAndroid Build Coastguard Worker }
1025*9880d681SAndroid Build Coastguard Worker
1026*9880d681SAndroid Build Coastguard Worker bool Changed = false;
1027*9880d681SAndroid Build Coastguard Worker Changed |= addReadAttrs(SCCNodes, AARGetter);
1028*9880d681SAndroid Build Coastguard Worker Changed |= addArgumentAttrs(SCCNodes);
1029*9880d681SAndroid Build Coastguard Worker
1030*9880d681SAndroid Build Coastguard Worker // If we have no external nodes participating in the SCC, we can deduce some
1031*9880d681SAndroid Build Coastguard Worker // more precise attributes as well.
1032*9880d681SAndroid Build Coastguard Worker if (!HasUnknownCall) {
1033*9880d681SAndroid Build Coastguard Worker Changed |= addNoAliasAttrs(SCCNodes);
1034*9880d681SAndroid Build Coastguard Worker Changed |= addNonNullAttrs(SCCNodes);
1035*9880d681SAndroid Build Coastguard Worker Changed |= removeConvergentAttrs(SCCNodes);
1036*9880d681SAndroid Build Coastguard Worker Changed |= addNoRecurseAttrs(SCCNodes);
1037*9880d681SAndroid Build Coastguard Worker }
1038*9880d681SAndroid Build Coastguard Worker
1039*9880d681SAndroid Build Coastguard Worker return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all();
1040*9880d681SAndroid Build Coastguard Worker }
1041*9880d681SAndroid Build Coastguard Worker
1042*9880d681SAndroid Build Coastguard Worker namespace {
1043*9880d681SAndroid Build Coastguard Worker struct PostOrderFunctionAttrsLegacyPass : public CallGraphSCCPass {
1044*9880d681SAndroid Build Coastguard Worker static char ID; // Pass identification, replacement for typeid
PostOrderFunctionAttrsLegacyPass__anon5ca92ef10611::PostOrderFunctionAttrsLegacyPass1045*9880d681SAndroid Build Coastguard Worker PostOrderFunctionAttrsLegacyPass() : CallGraphSCCPass(ID) {
1046*9880d681SAndroid Build Coastguard Worker initializePostOrderFunctionAttrsLegacyPassPass(*PassRegistry::getPassRegistry());
1047*9880d681SAndroid Build Coastguard Worker }
1048*9880d681SAndroid Build Coastguard Worker
1049*9880d681SAndroid Build Coastguard Worker bool runOnSCC(CallGraphSCC &SCC) override;
1050*9880d681SAndroid Build Coastguard Worker
getAnalysisUsage__anon5ca92ef10611::PostOrderFunctionAttrsLegacyPass1051*9880d681SAndroid Build Coastguard Worker void getAnalysisUsage(AnalysisUsage &AU) const override {
1052*9880d681SAndroid Build Coastguard Worker AU.setPreservesCFG();
1053*9880d681SAndroid Build Coastguard Worker AU.addRequired<AssumptionCacheTracker>();
1054*9880d681SAndroid Build Coastguard Worker getAAResultsAnalysisUsage(AU);
1055*9880d681SAndroid Build Coastguard Worker CallGraphSCCPass::getAnalysisUsage(AU);
1056*9880d681SAndroid Build Coastguard Worker }
1057*9880d681SAndroid Build Coastguard Worker };
1058*9880d681SAndroid Build Coastguard Worker }
1059*9880d681SAndroid Build Coastguard Worker
1060*9880d681SAndroid Build Coastguard Worker char PostOrderFunctionAttrsLegacyPass::ID = 0;
1061*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_BEGIN(PostOrderFunctionAttrsLegacyPass, "functionattrs",
1062*9880d681SAndroid Build Coastguard Worker "Deduce function attributes", false, false)
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)1063*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
1064*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
1065*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_END(PostOrderFunctionAttrsLegacyPass, "functionattrs",
1066*9880d681SAndroid Build Coastguard Worker "Deduce function attributes", false, false)
1067*9880d681SAndroid Build Coastguard Worker
1068*9880d681SAndroid Build Coastguard Worker Pass *llvm::createPostOrderFunctionAttrsLegacyPass() { return new PostOrderFunctionAttrsLegacyPass(); }
1069*9880d681SAndroid Build Coastguard Worker
1070*9880d681SAndroid Build Coastguard Worker template <typename AARGetterT>
runImpl(CallGraphSCC & SCC,AARGetterT AARGetter)1071*9880d681SAndroid Build Coastguard Worker static bool runImpl(CallGraphSCC &SCC, AARGetterT AARGetter) {
1072*9880d681SAndroid Build Coastguard Worker bool Changed = false;
1073*9880d681SAndroid Build Coastguard Worker
1074*9880d681SAndroid Build Coastguard Worker // Fill SCCNodes with the elements of the SCC. Used for quickly looking up
1075*9880d681SAndroid Build Coastguard Worker // whether a given CallGraphNode is in this SCC. Also track whether there are
1076*9880d681SAndroid Build Coastguard Worker // any external or opt-none nodes that will prevent us from optimizing any
1077*9880d681SAndroid Build Coastguard Worker // part of the SCC.
1078*9880d681SAndroid Build Coastguard Worker SCCNodeSet SCCNodes;
1079*9880d681SAndroid Build Coastguard Worker bool ExternalNode = false;
1080*9880d681SAndroid Build Coastguard Worker for (CallGraphNode *I : SCC) {
1081*9880d681SAndroid Build Coastguard Worker Function *F = I->getFunction();
1082*9880d681SAndroid Build Coastguard Worker if (!F || F->hasFnAttribute(Attribute::OptimizeNone)) {
1083*9880d681SAndroid Build Coastguard Worker // External node or function we're trying not to optimize - we both avoid
1084*9880d681SAndroid Build Coastguard Worker // transform them and avoid leveraging information they provide.
1085*9880d681SAndroid Build Coastguard Worker ExternalNode = true;
1086*9880d681SAndroid Build Coastguard Worker continue;
1087*9880d681SAndroid Build Coastguard Worker }
1088*9880d681SAndroid Build Coastguard Worker
1089*9880d681SAndroid Build Coastguard Worker SCCNodes.insert(F);
1090*9880d681SAndroid Build Coastguard Worker }
1091*9880d681SAndroid Build Coastguard Worker
1092*9880d681SAndroid Build Coastguard Worker Changed |= addReadAttrs(SCCNodes, AARGetter);
1093*9880d681SAndroid Build Coastguard Worker Changed |= addArgumentAttrs(SCCNodes);
1094*9880d681SAndroid Build Coastguard Worker
1095*9880d681SAndroid Build Coastguard Worker // If we have no external nodes participating in the SCC, we can deduce some
1096*9880d681SAndroid Build Coastguard Worker // more precise attributes as well.
1097*9880d681SAndroid Build Coastguard Worker if (!ExternalNode) {
1098*9880d681SAndroid Build Coastguard Worker Changed |= addNoAliasAttrs(SCCNodes);
1099*9880d681SAndroid Build Coastguard Worker Changed |= addNonNullAttrs(SCCNodes);
1100*9880d681SAndroid Build Coastguard Worker Changed |= removeConvergentAttrs(SCCNodes);
1101*9880d681SAndroid Build Coastguard Worker Changed |= addNoRecurseAttrs(SCCNodes);
1102*9880d681SAndroid Build Coastguard Worker }
1103*9880d681SAndroid Build Coastguard Worker
1104*9880d681SAndroid Build Coastguard Worker return Changed;
1105*9880d681SAndroid Build Coastguard Worker }
1106*9880d681SAndroid Build Coastguard Worker
runOnSCC(CallGraphSCC & SCC)1107*9880d681SAndroid Build Coastguard Worker bool PostOrderFunctionAttrsLegacyPass::runOnSCC(CallGraphSCC &SCC) {
1108*9880d681SAndroid Build Coastguard Worker if (skipSCC(SCC))
1109*9880d681SAndroid Build Coastguard Worker return false;
1110*9880d681SAndroid Build Coastguard Worker
1111*9880d681SAndroid Build Coastguard Worker // We compute dedicated AA results for each function in the SCC as needed. We
1112*9880d681SAndroid Build Coastguard Worker // use a lambda referencing external objects so that they live long enough to
1113*9880d681SAndroid Build Coastguard Worker // be queried, but we re-use them each time.
1114*9880d681SAndroid Build Coastguard Worker Optional<BasicAAResult> BAR;
1115*9880d681SAndroid Build Coastguard Worker Optional<AAResults> AAR;
1116*9880d681SAndroid Build Coastguard Worker auto AARGetter = [&](Function &F) -> AAResults & {
1117*9880d681SAndroid Build Coastguard Worker BAR.emplace(createLegacyPMBasicAAResult(*this, F));
1118*9880d681SAndroid Build Coastguard Worker AAR.emplace(createLegacyPMAAResults(*this, F, *BAR));
1119*9880d681SAndroid Build Coastguard Worker return *AAR;
1120*9880d681SAndroid Build Coastguard Worker };
1121*9880d681SAndroid Build Coastguard Worker
1122*9880d681SAndroid Build Coastguard Worker return runImpl(SCC, AARGetter);
1123*9880d681SAndroid Build Coastguard Worker }
1124*9880d681SAndroid Build Coastguard Worker
1125*9880d681SAndroid Build Coastguard Worker namespace {
1126*9880d681SAndroid Build Coastguard Worker struct ReversePostOrderFunctionAttrsLegacyPass : public ModulePass {
1127*9880d681SAndroid Build Coastguard Worker static char ID; // Pass identification, replacement for typeid
ReversePostOrderFunctionAttrsLegacyPass__anon5ca92ef10811::ReversePostOrderFunctionAttrsLegacyPass1128*9880d681SAndroid Build Coastguard Worker ReversePostOrderFunctionAttrsLegacyPass() : ModulePass(ID) {
1129*9880d681SAndroid Build Coastguard Worker initializeReversePostOrderFunctionAttrsLegacyPassPass(*PassRegistry::getPassRegistry());
1130*9880d681SAndroid Build Coastguard Worker }
1131*9880d681SAndroid Build Coastguard Worker
1132*9880d681SAndroid Build Coastguard Worker bool runOnModule(Module &M) override;
1133*9880d681SAndroid Build Coastguard Worker
getAnalysisUsage__anon5ca92ef10811::ReversePostOrderFunctionAttrsLegacyPass1134*9880d681SAndroid Build Coastguard Worker void getAnalysisUsage(AnalysisUsage &AU) const override {
1135*9880d681SAndroid Build Coastguard Worker AU.setPreservesCFG();
1136*9880d681SAndroid Build Coastguard Worker AU.addRequired<CallGraphWrapperPass>();
1137*9880d681SAndroid Build Coastguard Worker AU.addPreserved<CallGraphWrapperPass>();
1138*9880d681SAndroid Build Coastguard Worker }
1139*9880d681SAndroid Build Coastguard Worker };
1140*9880d681SAndroid Build Coastguard Worker }
1141*9880d681SAndroid Build Coastguard Worker
1142*9880d681SAndroid Build Coastguard Worker char ReversePostOrderFunctionAttrsLegacyPass::ID = 0;
1143*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_BEGIN(ReversePostOrderFunctionAttrsLegacyPass, "rpo-functionattrs",
1144*9880d681SAndroid Build Coastguard Worker "Deduce function attributes in RPO", false, false)
INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)1145*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
1146*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_END(ReversePostOrderFunctionAttrsLegacyPass, "rpo-functionattrs",
1147*9880d681SAndroid Build Coastguard Worker "Deduce function attributes in RPO", false, false)
1148*9880d681SAndroid Build Coastguard Worker
1149*9880d681SAndroid Build Coastguard Worker Pass *llvm::createReversePostOrderFunctionAttrsPass() {
1150*9880d681SAndroid Build Coastguard Worker return new ReversePostOrderFunctionAttrsLegacyPass();
1151*9880d681SAndroid Build Coastguard Worker }
1152*9880d681SAndroid Build Coastguard Worker
addNoRecurseAttrsTopDown(Function & F)1153*9880d681SAndroid Build Coastguard Worker static bool addNoRecurseAttrsTopDown(Function &F) {
1154*9880d681SAndroid Build Coastguard Worker // We check the preconditions for the function prior to calling this to avoid
1155*9880d681SAndroid Build Coastguard Worker // the cost of building up a reversible post-order list. We assert them here
1156*9880d681SAndroid Build Coastguard Worker // to make sure none of the invariants this relies on were violated.
1157*9880d681SAndroid Build Coastguard Worker assert(!F.isDeclaration() && "Cannot deduce norecurse without a definition!");
1158*9880d681SAndroid Build Coastguard Worker assert(!F.doesNotRecurse() &&
1159*9880d681SAndroid Build Coastguard Worker "This function has already been deduced as norecurs!");
1160*9880d681SAndroid Build Coastguard Worker assert(F.hasInternalLinkage() &&
1161*9880d681SAndroid Build Coastguard Worker "Can only do top-down deduction for internal linkage functions!");
1162*9880d681SAndroid Build Coastguard Worker
1163*9880d681SAndroid Build Coastguard Worker // If F is internal and all of its uses are calls from a non-recursive
1164*9880d681SAndroid Build Coastguard Worker // functions, then none of its calls could in fact recurse without going
1165*9880d681SAndroid Build Coastguard Worker // through a function marked norecurse, and so we can mark this function too
1166*9880d681SAndroid Build Coastguard Worker // as norecurse. Note that the uses must actually be calls -- otherwise
1167*9880d681SAndroid Build Coastguard Worker // a pointer to this function could be returned from a norecurse function but
1168*9880d681SAndroid Build Coastguard Worker // this function could be recursively (indirectly) called. Note that this
1169*9880d681SAndroid Build Coastguard Worker // also detects if F is directly recursive as F is not yet marked as
1170*9880d681SAndroid Build Coastguard Worker // a norecurse function.
1171*9880d681SAndroid Build Coastguard Worker for (auto *U : F.users()) {
1172*9880d681SAndroid Build Coastguard Worker auto *I = dyn_cast<Instruction>(U);
1173*9880d681SAndroid Build Coastguard Worker if (!I)
1174*9880d681SAndroid Build Coastguard Worker return false;
1175*9880d681SAndroid Build Coastguard Worker CallSite CS(I);
1176*9880d681SAndroid Build Coastguard Worker if (!CS || !CS.getParent()->getParent()->doesNotRecurse())
1177*9880d681SAndroid Build Coastguard Worker return false;
1178*9880d681SAndroid Build Coastguard Worker }
1179*9880d681SAndroid Build Coastguard Worker return setDoesNotRecurse(F);
1180*9880d681SAndroid Build Coastguard Worker }
1181*9880d681SAndroid Build Coastguard Worker
deduceFunctionAttributeInRPO(Module & M,CallGraph & CG)1182*9880d681SAndroid Build Coastguard Worker static bool deduceFunctionAttributeInRPO(Module &M, CallGraph &CG) {
1183*9880d681SAndroid Build Coastguard Worker // We only have a post-order SCC traversal (because SCCs are inherently
1184*9880d681SAndroid Build Coastguard Worker // discovered in post-order), so we accumulate them in a vector and then walk
1185*9880d681SAndroid Build Coastguard Worker // it in reverse. This is simpler than using the RPO iterator infrastructure
1186*9880d681SAndroid Build Coastguard Worker // because we need to combine SCC detection and the PO walk of the call
1187*9880d681SAndroid Build Coastguard Worker // graph. We can also cheat egregiously because we're primarily interested in
1188*9880d681SAndroid Build Coastguard Worker // synthesizing norecurse and so we can only save the singular SCCs as SCCs
1189*9880d681SAndroid Build Coastguard Worker // with multiple functions in them will clearly be recursive.
1190*9880d681SAndroid Build Coastguard Worker SmallVector<Function *, 16> Worklist;
1191*9880d681SAndroid Build Coastguard Worker for (scc_iterator<CallGraph *> I = scc_begin(&CG); !I.isAtEnd(); ++I) {
1192*9880d681SAndroid Build Coastguard Worker if (I->size() != 1)
1193*9880d681SAndroid Build Coastguard Worker continue;
1194*9880d681SAndroid Build Coastguard Worker
1195*9880d681SAndroid Build Coastguard Worker Function *F = I->front()->getFunction();
1196*9880d681SAndroid Build Coastguard Worker if (F && !F->isDeclaration() && !F->doesNotRecurse() &&
1197*9880d681SAndroid Build Coastguard Worker F->hasInternalLinkage())
1198*9880d681SAndroid Build Coastguard Worker Worklist.push_back(F);
1199*9880d681SAndroid Build Coastguard Worker }
1200*9880d681SAndroid Build Coastguard Worker
1201*9880d681SAndroid Build Coastguard Worker bool Changed = false;
1202*9880d681SAndroid Build Coastguard Worker for (auto *F : reverse(Worklist))
1203*9880d681SAndroid Build Coastguard Worker Changed |= addNoRecurseAttrsTopDown(*F);
1204*9880d681SAndroid Build Coastguard Worker
1205*9880d681SAndroid Build Coastguard Worker return Changed;
1206*9880d681SAndroid Build Coastguard Worker }
1207*9880d681SAndroid Build Coastguard Worker
runOnModule(Module & M)1208*9880d681SAndroid Build Coastguard Worker bool ReversePostOrderFunctionAttrsLegacyPass::runOnModule(Module &M) {
1209*9880d681SAndroid Build Coastguard Worker if (skipModule(M))
1210*9880d681SAndroid Build Coastguard Worker return false;
1211*9880d681SAndroid Build Coastguard Worker
1212*9880d681SAndroid Build Coastguard Worker auto &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
1213*9880d681SAndroid Build Coastguard Worker
1214*9880d681SAndroid Build Coastguard Worker return deduceFunctionAttributeInRPO(M, CG);
1215*9880d681SAndroid Build Coastguard Worker }
1216*9880d681SAndroid Build Coastguard Worker
1217*9880d681SAndroid Build Coastguard Worker PreservedAnalyses
run(Module & M,AnalysisManager<Module> & AM)1218*9880d681SAndroid Build Coastguard Worker ReversePostOrderFunctionAttrsPass::run(Module &M, AnalysisManager<Module> &AM) {
1219*9880d681SAndroid Build Coastguard Worker auto &CG = AM.getResult<CallGraphAnalysis>(M);
1220*9880d681SAndroid Build Coastguard Worker
1221*9880d681SAndroid Build Coastguard Worker bool Changed = deduceFunctionAttributeInRPO(M, CG);
1222*9880d681SAndroid Build Coastguard Worker if (!Changed)
1223*9880d681SAndroid Build Coastguard Worker return PreservedAnalyses::all();
1224*9880d681SAndroid Build Coastguard Worker PreservedAnalyses PA;
1225*9880d681SAndroid Build Coastguard Worker PA.preserve<CallGraphAnalysis>();
1226*9880d681SAndroid Build Coastguard Worker return PA;
1227*9880d681SAndroid Build Coastguard Worker }
1228