1*9880d681SAndroid Build Coastguard Worker //- CFLSteensAliasAnalysis.cpp - Unification-based Alias Analysis ---*- C++-*-//
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 // This file implements a CFL-base, summary-based alias analysis algorithm. It
11*9880d681SAndroid Build Coastguard Worker // does not depend on types. The algorithm is a mixture of the one described in
12*9880d681SAndroid Build Coastguard Worker // "Demand-driven alias analysis for C" by Xin Zheng and Radu Rugina, and "Fast
13*9880d681SAndroid Build Coastguard Worker // algorithms for Dyck-CFL-reachability with applications to Alias Analysis" by
14*9880d681SAndroid Build Coastguard Worker // Zhang Q, Lyu M R, Yuan H, and Su Z. -- to summarize the papers, we build a
15*9880d681SAndroid Build Coastguard Worker // graph of the uses of a variable, where each node is a memory location, and
16*9880d681SAndroid Build Coastguard Worker // each edge is an action that happened on that memory location. The "actions"
17*9880d681SAndroid Build Coastguard Worker // can be one of Dereference, Reference, or Assign. The precision of this
18*9880d681SAndroid Build Coastguard Worker // analysis is roughly the same as that of an one level context-sensitive
19*9880d681SAndroid Build Coastguard Worker // Steensgaard's algorithm.
20*9880d681SAndroid Build Coastguard Worker //
21*9880d681SAndroid Build Coastguard Worker // Two variables are considered as aliasing iff you can reach one value's node
22*9880d681SAndroid Build Coastguard Worker // from the other value's node and the language formed by concatenating all of
23*9880d681SAndroid Build Coastguard Worker // the edge labels (actions) conforms to a context-free grammar.
24*9880d681SAndroid Build Coastguard Worker //
25*9880d681SAndroid Build Coastguard Worker // Because this algorithm requires a graph search on each query, we execute the
26*9880d681SAndroid Build Coastguard Worker // algorithm outlined in "Fast algorithms..." (mentioned above)
27*9880d681SAndroid Build Coastguard Worker // in order to transform the graph into sets of variables that may alias in
28*9880d681SAndroid Build Coastguard Worker // ~nlogn time (n = number of variables), which makes queries take constant
29*9880d681SAndroid Build Coastguard Worker // time.
30*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
31*9880d681SAndroid Build Coastguard Worker
32*9880d681SAndroid Build Coastguard Worker // N.B. AliasAnalysis as a whole is phrased as a FunctionPass at the moment, and
33*9880d681SAndroid Build Coastguard Worker // CFLSteensAA is interprocedural. This is *technically* A Bad Thing, because
34*9880d681SAndroid Build Coastguard Worker // FunctionPasses are only allowed to inspect the Function that they're being
35*9880d681SAndroid Build Coastguard Worker // run on. Realistically, this likely isn't a problem until we allow
36*9880d681SAndroid Build Coastguard Worker // FunctionPasses to run concurrently.
37*9880d681SAndroid Build Coastguard Worker
38*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/CFLSteensAliasAnalysis.h"
39*9880d681SAndroid Build Coastguard Worker #include "CFLGraph.h"
40*9880d681SAndroid Build Coastguard Worker #include "StratifiedSets.h"
41*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/DenseMap.h"
42*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/None.h"
43*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Optional.h"
44*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/TargetLibraryInfo.h"
45*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Constants.h"
46*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Function.h"
47*9880d681SAndroid Build Coastguard Worker #include "llvm/Pass.h"
48*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Compiler.h"
49*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
50*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h"
51*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
52*9880d681SAndroid Build Coastguard Worker #include <algorithm>
53*9880d681SAndroid Build Coastguard Worker #include <cassert>
54*9880d681SAndroid Build Coastguard Worker #include <memory>
55*9880d681SAndroid Build Coastguard Worker #include <tuple>
56*9880d681SAndroid Build Coastguard Worker
57*9880d681SAndroid Build Coastguard Worker using namespace llvm;
58*9880d681SAndroid Build Coastguard Worker using namespace llvm::cflaa;
59*9880d681SAndroid Build Coastguard Worker
60*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "cfl-steens-aa"
61*9880d681SAndroid Build Coastguard Worker
CFLSteensAAResult(const TargetLibraryInfo & TLI)62*9880d681SAndroid Build Coastguard Worker CFLSteensAAResult::CFLSteensAAResult(const TargetLibraryInfo &TLI)
63*9880d681SAndroid Build Coastguard Worker : AAResultBase(), TLI(TLI) {}
CFLSteensAAResult(CFLSteensAAResult && Arg)64*9880d681SAndroid Build Coastguard Worker CFLSteensAAResult::CFLSteensAAResult(CFLSteensAAResult &&Arg)
65*9880d681SAndroid Build Coastguard Worker : AAResultBase(std::move(Arg)), TLI(Arg.TLI) {}
~CFLSteensAAResult()66*9880d681SAndroid Build Coastguard Worker CFLSteensAAResult::~CFLSteensAAResult() {}
67*9880d681SAndroid Build Coastguard Worker
68*9880d681SAndroid Build Coastguard Worker /// Information we have about a function and would like to keep around.
69*9880d681SAndroid Build Coastguard Worker class CFLSteensAAResult::FunctionInfo {
70*9880d681SAndroid Build Coastguard Worker StratifiedSets<InstantiatedValue> Sets;
71*9880d681SAndroid Build Coastguard Worker AliasSummary Summary;
72*9880d681SAndroid Build Coastguard Worker
73*9880d681SAndroid Build Coastguard Worker public:
74*9880d681SAndroid Build Coastguard Worker FunctionInfo(Function &Fn, const SmallVectorImpl<Value *> &RetVals,
75*9880d681SAndroid Build Coastguard Worker StratifiedSets<InstantiatedValue> S);
76*9880d681SAndroid Build Coastguard Worker
getStratifiedSets() const77*9880d681SAndroid Build Coastguard Worker const StratifiedSets<InstantiatedValue> &getStratifiedSets() const {
78*9880d681SAndroid Build Coastguard Worker return Sets;
79*9880d681SAndroid Build Coastguard Worker }
getAliasSummary() const80*9880d681SAndroid Build Coastguard Worker const AliasSummary &getAliasSummary() const { return Summary; }
81*9880d681SAndroid Build Coastguard Worker };
82*9880d681SAndroid Build Coastguard Worker
83*9880d681SAndroid Build Coastguard Worker /// Try to go from a Value* to a Function*. Never returns nullptr.
84*9880d681SAndroid Build Coastguard Worker static Optional<Function *> parentFunctionOfValue(Value *);
85*9880d681SAndroid Build Coastguard Worker
86*9880d681SAndroid Build Coastguard Worker const StratifiedIndex StratifiedLink::SetSentinel =
87*9880d681SAndroid Build Coastguard Worker std::numeric_limits<StratifiedIndex>::max();
88*9880d681SAndroid Build Coastguard Worker
89*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
90*9880d681SAndroid Build Coastguard Worker // Function declarations that require types defined in the namespace above
91*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
92*9880d681SAndroid Build Coastguard Worker
93*9880d681SAndroid Build Coastguard Worker /// Determines whether it would be pointless to add the given Value to our sets.
94*9880d681SAndroid Build Coastguard Worker static bool canSkipAddingToSets(Value *Val);
95*9880d681SAndroid Build Coastguard Worker
parentFunctionOfValue(Value * Val)96*9880d681SAndroid Build Coastguard Worker static Optional<Function *> parentFunctionOfValue(Value *Val) {
97*9880d681SAndroid Build Coastguard Worker if (auto *Inst = dyn_cast<Instruction>(Val)) {
98*9880d681SAndroid Build Coastguard Worker auto *Bb = Inst->getParent();
99*9880d681SAndroid Build Coastguard Worker return Bb->getParent();
100*9880d681SAndroid Build Coastguard Worker }
101*9880d681SAndroid Build Coastguard Worker
102*9880d681SAndroid Build Coastguard Worker if (auto *Arg = dyn_cast<Argument>(Val))
103*9880d681SAndroid Build Coastguard Worker return Arg->getParent();
104*9880d681SAndroid Build Coastguard Worker return None;
105*9880d681SAndroid Build Coastguard Worker }
106*9880d681SAndroid Build Coastguard Worker
canSkipAddingToSets(Value * Val)107*9880d681SAndroid Build Coastguard Worker static bool canSkipAddingToSets(Value *Val) {
108*9880d681SAndroid Build Coastguard Worker // Constants can share instances, which may falsely unify multiple
109*9880d681SAndroid Build Coastguard Worker // sets, e.g. in
110*9880d681SAndroid Build Coastguard Worker // store i32* null, i32** %ptr1
111*9880d681SAndroid Build Coastguard Worker // store i32* null, i32** %ptr2
112*9880d681SAndroid Build Coastguard Worker // clearly ptr1 and ptr2 should not be unified into the same set, so
113*9880d681SAndroid Build Coastguard Worker // we should filter out the (potentially shared) instance to
114*9880d681SAndroid Build Coastguard Worker // i32* null.
115*9880d681SAndroid Build Coastguard Worker if (isa<Constant>(Val)) {
116*9880d681SAndroid Build Coastguard Worker // TODO: Because all of these things are constant, we can determine whether
117*9880d681SAndroid Build Coastguard Worker // the data is *actually* mutable at graph building time. This will probably
118*9880d681SAndroid Build Coastguard Worker // come for free/cheap with offset awareness.
119*9880d681SAndroid Build Coastguard Worker bool CanStoreMutableData = isa<GlobalValue>(Val) ||
120*9880d681SAndroid Build Coastguard Worker isa<ConstantExpr>(Val) ||
121*9880d681SAndroid Build Coastguard Worker isa<ConstantAggregate>(Val);
122*9880d681SAndroid Build Coastguard Worker return !CanStoreMutableData;
123*9880d681SAndroid Build Coastguard Worker }
124*9880d681SAndroid Build Coastguard Worker
125*9880d681SAndroid Build Coastguard Worker return false;
126*9880d681SAndroid Build Coastguard Worker }
127*9880d681SAndroid Build Coastguard Worker
FunctionInfo(Function & Fn,const SmallVectorImpl<Value * > & RetVals,StratifiedSets<InstantiatedValue> S)128*9880d681SAndroid Build Coastguard Worker CFLSteensAAResult::FunctionInfo::FunctionInfo(
129*9880d681SAndroid Build Coastguard Worker Function &Fn, const SmallVectorImpl<Value *> &RetVals,
130*9880d681SAndroid Build Coastguard Worker StratifiedSets<InstantiatedValue> S)
131*9880d681SAndroid Build Coastguard Worker : Sets(std::move(S)) {
132*9880d681SAndroid Build Coastguard Worker // Historically, an arbitrary upper-bound of 50 args was selected. We may want
133*9880d681SAndroid Build Coastguard Worker // to remove this if it doesn't really matter in practice.
134*9880d681SAndroid Build Coastguard Worker if (Fn.arg_size() > MaxSupportedArgsInSummary)
135*9880d681SAndroid Build Coastguard Worker return;
136*9880d681SAndroid Build Coastguard Worker
137*9880d681SAndroid Build Coastguard Worker DenseMap<StratifiedIndex, InterfaceValue> InterfaceMap;
138*9880d681SAndroid Build Coastguard Worker
139*9880d681SAndroid Build Coastguard Worker // Our intention here is to record all InterfaceValues that share the same
140*9880d681SAndroid Build Coastguard Worker // StratifiedIndex in RetParamRelations. For each valid InterfaceValue, we
141*9880d681SAndroid Build Coastguard Worker // have its StratifiedIndex scanned here and check if the index is presented
142*9880d681SAndroid Build Coastguard Worker // in InterfaceMap: if it is not, we add the correspondence to the map;
143*9880d681SAndroid Build Coastguard Worker // otherwise, an aliasing relation is found and we add it to
144*9880d681SAndroid Build Coastguard Worker // RetParamRelations.
145*9880d681SAndroid Build Coastguard Worker
146*9880d681SAndroid Build Coastguard Worker auto AddToRetParamRelations = [&](unsigned InterfaceIndex,
147*9880d681SAndroid Build Coastguard Worker StratifiedIndex SetIndex) {
148*9880d681SAndroid Build Coastguard Worker unsigned Level = 0;
149*9880d681SAndroid Build Coastguard Worker while (true) {
150*9880d681SAndroid Build Coastguard Worker InterfaceValue CurrValue{InterfaceIndex, Level};
151*9880d681SAndroid Build Coastguard Worker
152*9880d681SAndroid Build Coastguard Worker auto Itr = InterfaceMap.find(SetIndex);
153*9880d681SAndroid Build Coastguard Worker if (Itr != InterfaceMap.end()) {
154*9880d681SAndroid Build Coastguard Worker if (CurrValue != Itr->second)
155*9880d681SAndroid Build Coastguard Worker Summary.RetParamRelations.push_back(
156*9880d681SAndroid Build Coastguard Worker ExternalRelation{CurrValue, Itr->second});
157*9880d681SAndroid Build Coastguard Worker break;
158*9880d681SAndroid Build Coastguard Worker }
159*9880d681SAndroid Build Coastguard Worker
160*9880d681SAndroid Build Coastguard Worker auto &Link = Sets.getLink(SetIndex);
161*9880d681SAndroid Build Coastguard Worker InterfaceMap.insert(std::make_pair(SetIndex, CurrValue));
162*9880d681SAndroid Build Coastguard Worker auto ExternalAttrs = getExternallyVisibleAttrs(Link.Attrs);
163*9880d681SAndroid Build Coastguard Worker if (ExternalAttrs.any())
164*9880d681SAndroid Build Coastguard Worker Summary.RetParamAttributes.push_back(
165*9880d681SAndroid Build Coastguard Worker ExternalAttribute{CurrValue, ExternalAttrs});
166*9880d681SAndroid Build Coastguard Worker
167*9880d681SAndroid Build Coastguard Worker if (!Link.hasBelow())
168*9880d681SAndroid Build Coastguard Worker break;
169*9880d681SAndroid Build Coastguard Worker
170*9880d681SAndroid Build Coastguard Worker ++Level;
171*9880d681SAndroid Build Coastguard Worker SetIndex = Link.Below;
172*9880d681SAndroid Build Coastguard Worker }
173*9880d681SAndroid Build Coastguard Worker };
174*9880d681SAndroid Build Coastguard Worker
175*9880d681SAndroid Build Coastguard Worker // Populate RetParamRelations for return values
176*9880d681SAndroid Build Coastguard Worker for (auto *RetVal : RetVals) {
177*9880d681SAndroid Build Coastguard Worker assert(RetVal != nullptr);
178*9880d681SAndroid Build Coastguard Worker assert(RetVal->getType()->isPointerTy());
179*9880d681SAndroid Build Coastguard Worker auto RetInfo = Sets.find(InstantiatedValue{RetVal, 0});
180*9880d681SAndroid Build Coastguard Worker if (RetInfo.hasValue())
181*9880d681SAndroid Build Coastguard Worker AddToRetParamRelations(0, RetInfo->Index);
182*9880d681SAndroid Build Coastguard Worker }
183*9880d681SAndroid Build Coastguard Worker
184*9880d681SAndroid Build Coastguard Worker // Populate RetParamRelations for parameters
185*9880d681SAndroid Build Coastguard Worker unsigned I = 0;
186*9880d681SAndroid Build Coastguard Worker for (auto &Param : Fn.args()) {
187*9880d681SAndroid Build Coastguard Worker if (Param.getType()->isPointerTy()) {
188*9880d681SAndroid Build Coastguard Worker auto ParamInfo = Sets.find(InstantiatedValue{&Param, 0});
189*9880d681SAndroid Build Coastguard Worker if (ParamInfo.hasValue())
190*9880d681SAndroid Build Coastguard Worker AddToRetParamRelations(I + 1, ParamInfo->Index);
191*9880d681SAndroid Build Coastguard Worker }
192*9880d681SAndroid Build Coastguard Worker ++I;
193*9880d681SAndroid Build Coastguard Worker }
194*9880d681SAndroid Build Coastguard Worker }
195*9880d681SAndroid Build Coastguard Worker
196*9880d681SAndroid Build Coastguard Worker // Builds the graph + StratifiedSets for a function.
buildSetsFrom(Function * Fn)197*9880d681SAndroid Build Coastguard Worker CFLSteensAAResult::FunctionInfo CFLSteensAAResult::buildSetsFrom(Function *Fn) {
198*9880d681SAndroid Build Coastguard Worker CFLGraphBuilder<CFLSteensAAResult> GraphBuilder(*this, TLI, *Fn);
199*9880d681SAndroid Build Coastguard Worker StratifiedSetsBuilder<InstantiatedValue> SetBuilder;
200*9880d681SAndroid Build Coastguard Worker
201*9880d681SAndroid Build Coastguard Worker // Add all CFLGraph nodes and all Dereference edges to StratifiedSets
202*9880d681SAndroid Build Coastguard Worker auto &Graph = GraphBuilder.getCFLGraph();
203*9880d681SAndroid Build Coastguard Worker for (const auto &Mapping : Graph.value_mappings()) {
204*9880d681SAndroid Build Coastguard Worker auto Val = Mapping.first;
205*9880d681SAndroid Build Coastguard Worker if (canSkipAddingToSets(Val))
206*9880d681SAndroid Build Coastguard Worker continue;
207*9880d681SAndroid Build Coastguard Worker auto &ValueInfo = Mapping.second;
208*9880d681SAndroid Build Coastguard Worker
209*9880d681SAndroid Build Coastguard Worker assert(ValueInfo.getNumLevels() > 0);
210*9880d681SAndroid Build Coastguard Worker SetBuilder.add(InstantiatedValue{Val, 0});
211*9880d681SAndroid Build Coastguard Worker SetBuilder.noteAttributes(InstantiatedValue{Val, 0},
212*9880d681SAndroid Build Coastguard Worker ValueInfo.getNodeInfoAtLevel(0).Attr);
213*9880d681SAndroid Build Coastguard Worker for (unsigned I = 0, E = ValueInfo.getNumLevels() - 1; I < E; ++I) {
214*9880d681SAndroid Build Coastguard Worker SetBuilder.add(InstantiatedValue{Val, I + 1});
215*9880d681SAndroid Build Coastguard Worker SetBuilder.noteAttributes(InstantiatedValue{Val, I + 1},
216*9880d681SAndroid Build Coastguard Worker ValueInfo.getNodeInfoAtLevel(I + 1).Attr);
217*9880d681SAndroid Build Coastguard Worker SetBuilder.addBelow(InstantiatedValue{Val, I},
218*9880d681SAndroid Build Coastguard Worker InstantiatedValue{Val, I + 1});
219*9880d681SAndroid Build Coastguard Worker }
220*9880d681SAndroid Build Coastguard Worker }
221*9880d681SAndroid Build Coastguard Worker
222*9880d681SAndroid Build Coastguard Worker // Add all assign edges to StratifiedSets
223*9880d681SAndroid Build Coastguard Worker for (const auto &Mapping : Graph.value_mappings()) {
224*9880d681SAndroid Build Coastguard Worker auto Val = Mapping.first;
225*9880d681SAndroid Build Coastguard Worker if (canSkipAddingToSets(Val))
226*9880d681SAndroid Build Coastguard Worker continue;
227*9880d681SAndroid Build Coastguard Worker auto &ValueInfo = Mapping.second;
228*9880d681SAndroid Build Coastguard Worker
229*9880d681SAndroid Build Coastguard Worker for (unsigned I = 0, E = ValueInfo.getNumLevels(); I < E; ++I) {
230*9880d681SAndroid Build Coastguard Worker auto Src = InstantiatedValue{Val, I};
231*9880d681SAndroid Build Coastguard Worker for (auto &Edge : ValueInfo.getNodeInfoAtLevel(I).Edges)
232*9880d681SAndroid Build Coastguard Worker SetBuilder.addWith(Src, Edge.Other);
233*9880d681SAndroid Build Coastguard Worker }
234*9880d681SAndroid Build Coastguard Worker }
235*9880d681SAndroid Build Coastguard Worker
236*9880d681SAndroid Build Coastguard Worker return FunctionInfo(*Fn, GraphBuilder.getReturnValues(), SetBuilder.build());
237*9880d681SAndroid Build Coastguard Worker }
238*9880d681SAndroid Build Coastguard Worker
scan(Function * Fn)239*9880d681SAndroid Build Coastguard Worker void CFLSteensAAResult::scan(Function *Fn) {
240*9880d681SAndroid Build Coastguard Worker auto InsertPair = Cache.insert(std::make_pair(Fn, Optional<FunctionInfo>()));
241*9880d681SAndroid Build Coastguard Worker (void)InsertPair;
242*9880d681SAndroid Build Coastguard Worker assert(InsertPair.second &&
243*9880d681SAndroid Build Coastguard Worker "Trying to scan a function that has already been cached");
244*9880d681SAndroid Build Coastguard Worker
245*9880d681SAndroid Build Coastguard Worker // Note that we can't do Cache[Fn] = buildSetsFrom(Fn) here: the function call
246*9880d681SAndroid Build Coastguard Worker // may get evaluated after operator[], potentially triggering a DenseMap
247*9880d681SAndroid Build Coastguard Worker // resize and invalidating the reference returned by operator[]
248*9880d681SAndroid Build Coastguard Worker auto FunInfo = buildSetsFrom(Fn);
249*9880d681SAndroid Build Coastguard Worker Cache[Fn] = std::move(FunInfo);
250*9880d681SAndroid Build Coastguard Worker
251*9880d681SAndroid Build Coastguard Worker Handles.push_front(FunctionHandle(Fn, this));
252*9880d681SAndroid Build Coastguard Worker }
253*9880d681SAndroid Build Coastguard Worker
evict(Function * Fn)254*9880d681SAndroid Build Coastguard Worker void CFLSteensAAResult::evict(Function *Fn) { Cache.erase(Fn); }
255*9880d681SAndroid Build Coastguard Worker
256*9880d681SAndroid Build Coastguard Worker /// Ensures that the given function is available in the cache, and returns the
257*9880d681SAndroid Build Coastguard Worker /// entry.
258*9880d681SAndroid Build Coastguard Worker const Optional<CFLSteensAAResult::FunctionInfo> &
ensureCached(Function * Fn)259*9880d681SAndroid Build Coastguard Worker CFLSteensAAResult::ensureCached(Function *Fn) {
260*9880d681SAndroid Build Coastguard Worker auto Iter = Cache.find(Fn);
261*9880d681SAndroid Build Coastguard Worker if (Iter == Cache.end()) {
262*9880d681SAndroid Build Coastguard Worker scan(Fn);
263*9880d681SAndroid Build Coastguard Worker Iter = Cache.find(Fn);
264*9880d681SAndroid Build Coastguard Worker assert(Iter != Cache.end());
265*9880d681SAndroid Build Coastguard Worker assert(Iter->second.hasValue());
266*9880d681SAndroid Build Coastguard Worker }
267*9880d681SAndroid Build Coastguard Worker return Iter->second;
268*9880d681SAndroid Build Coastguard Worker }
269*9880d681SAndroid Build Coastguard Worker
getAliasSummary(Function & Fn)270*9880d681SAndroid Build Coastguard Worker const AliasSummary *CFLSteensAAResult::getAliasSummary(Function &Fn) {
271*9880d681SAndroid Build Coastguard Worker auto &FunInfo = ensureCached(&Fn);
272*9880d681SAndroid Build Coastguard Worker if (FunInfo.hasValue())
273*9880d681SAndroid Build Coastguard Worker return &FunInfo->getAliasSummary();
274*9880d681SAndroid Build Coastguard Worker else
275*9880d681SAndroid Build Coastguard Worker return nullptr;
276*9880d681SAndroid Build Coastguard Worker }
277*9880d681SAndroid Build Coastguard Worker
query(const MemoryLocation & LocA,const MemoryLocation & LocB)278*9880d681SAndroid Build Coastguard Worker AliasResult CFLSteensAAResult::query(const MemoryLocation &LocA,
279*9880d681SAndroid Build Coastguard Worker const MemoryLocation &LocB) {
280*9880d681SAndroid Build Coastguard Worker auto *ValA = const_cast<Value *>(LocA.Ptr);
281*9880d681SAndroid Build Coastguard Worker auto *ValB = const_cast<Value *>(LocB.Ptr);
282*9880d681SAndroid Build Coastguard Worker
283*9880d681SAndroid Build Coastguard Worker if (!ValA->getType()->isPointerTy() || !ValB->getType()->isPointerTy())
284*9880d681SAndroid Build Coastguard Worker return NoAlias;
285*9880d681SAndroid Build Coastguard Worker
286*9880d681SAndroid Build Coastguard Worker Function *Fn = nullptr;
287*9880d681SAndroid Build Coastguard Worker auto MaybeFnA = parentFunctionOfValue(ValA);
288*9880d681SAndroid Build Coastguard Worker auto MaybeFnB = parentFunctionOfValue(ValB);
289*9880d681SAndroid Build Coastguard Worker if (!MaybeFnA.hasValue() && !MaybeFnB.hasValue()) {
290*9880d681SAndroid Build Coastguard Worker // The only times this is known to happen are when globals + InlineAsm are
291*9880d681SAndroid Build Coastguard Worker // involved
292*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs()
293*9880d681SAndroid Build Coastguard Worker << "CFLSteensAA: could not extract parent function information.\n");
294*9880d681SAndroid Build Coastguard Worker return MayAlias;
295*9880d681SAndroid Build Coastguard Worker }
296*9880d681SAndroid Build Coastguard Worker
297*9880d681SAndroid Build Coastguard Worker if (MaybeFnA.hasValue()) {
298*9880d681SAndroid Build Coastguard Worker Fn = *MaybeFnA;
299*9880d681SAndroid Build Coastguard Worker assert((!MaybeFnB.hasValue() || *MaybeFnB == *MaybeFnA) &&
300*9880d681SAndroid Build Coastguard Worker "Interprocedural queries not supported");
301*9880d681SAndroid Build Coastguard Worker } else {
302*9880d681SAndroid Build Coastguard Worker Fn = *MaybeFnB;
303*9880d681SAndroid Build Coastguard Worker }
304*9880d681SAndroid Build Coastguard Worker
305*9880d681SAndroid Build Coastguard Worker assert(Fn != nullptr);
306*9880d681SAndroid Build Coastguard Worker auto &MaybeInfo = ensureCached(Fn);
307*9880d681SAndroid Build Coastguard Worker assert(MaybeInfo.hasValue());
308*9880d681SAndroid Build Coastguard Worker
309*9880d681SAndroid Build Coastguard Worker auto &Sets = MaybeInfo->getStratifiedSets();
310*9880d681SAndroid Build Coastguard Worker auto MaybeA = Sets.find(InstantiatedValue{ValA, 0});
311*9880d681SAndroid Build Coastguard Worker if (!MaybeA.hasValue())
312*9880d681SAndroid Build Coastguard Worker return MayAlias;
313*9880d681SAndroid Build Coastguard Worker
314*9880d681SAndroid Build Coastguard Worker auto MaybeB = Sets.find(InstantiatedValue{ValB, 0});
315*9880d681SAndroid Build Coastguard Worker if (!MaybeB.hasValue())
316*9880d681SAndroid Build Coastguard Worker return MayAlias;
317*9880d681SAndroid Build Coastguard Worker
318*9880d681SAndroid Build Coastguard Worker auto SetA = *MaybeA;
319*9880d681SAndroid Build Coastguard Worker auto SetB = *MaybeB;
320*9880d681SAndroid Build Coastguard Worker auto AttrsA = Sets.getLink(SetA.Index).Attrs;
321*9880d681SAndroid Build Coastguard Worker auto AttrsB = Sets.getLink(SetB.Index).Attrs;
322*9880d681SAndroid Build Coastguard Worker
323*9880d681SAndroid Build Coastguard Worker // If both values are local (meaning the corresponding set has attribute
324*9880d681SAndroid Build Coastguard Worker // AttrNone or AttrEscaped), then we know that CFLSteensAA fully models them:
325*9880d681SAndroid Build Coastguard Worker // they may-alias each other if and only if they are in the same set.
326*9880d681SAndroid Build Coastguard Worker // If at least one value is non-local (meaning it either is global/argument or
327*9880d681SAndroid Build Coastguard Worker // it comes from unknown sources like integer cast), the situation becomes a
328*9880d681SAndroid Build Coastguard Worker // bit more interesting. We follow three general rules described below:
329*9880d681SAndroid Build Coastguard Worker // - Non-local values may alias each other
330*9880d681SAndroid Build Coastguard Worker // - AttrNone values do not alias any non-local values
331*9880d681SAndroid Build Coastguard Worker // - AttrEscaped do not alias globals/arguments, but they may alias
332*9880d681SAndroid Build Coastguard Worker // AttrUnknown values
333*9880d681SAndroid Build Coastguard Worker if (SetA.Index == SetB.Index)
334*9880d681SAndroid Build Coastguard Worker return MayAlias;
335*9880d681SAndroid Build Coastguard Worker if (AttrsA.none() || AttrsB.none())
336*9880d681SAndroid Build Coastguard Worker return NoAlias;
337*9880d681SAndroid Build Coastguard Worker if (hasUnknownOrCallerAttr(AttrsA) || hasUnknownOrCallerAttr(AttrsB))
338*9880d681SAndroid Build Coastguard Worker return MayAlias;
339*9880d681SAndroid Build Coastguard Worker if (isGlobalOrArgAttr(AttrsA) && isGlobalOrArgAttr(AttrsB))
340*9880d681SAndroid Build Coastguard Worker return MayAlias;
341*9880d681SAndroid Build Coastguard Worker return NoAlias;
342*9880d681SAndroid Build Coastguard Worker }
343*9880d681SAndroid Build Coastguard Worker
getArgModRefInfo(ImmutableCallSite CS,unsigned ArgIdx)344*9880d681SAndroid Build Coastguard Worker ModRefInfo CFLSteensAAResult::getArgModRefInfo(ImmutableCallSite CS,
345*9880d681SAndroid Build Coastguard Worker unsigned ArgIdx) {
346*9880d681SAndroid Build Coastguard Worker if (auto CalledFunc = CS.getCalledFunction()) {
347*9880d681SAndroid Build Coastguard Worker auto &MaybeInfo = ensureCached(const_cast<Function *>(CalledFunc));
348*9880d681SAndroid Build Coastguard Worker if (!MaybeInfo.hasValue())
349*9880d681SAndroid Build Coastguard Worker return MRI_ModRef;
350*9880d681SAndroid Build Coastguard Worker auto &RetParamAttributes = MaybeInfo->getAliasSummary().RetParamAttributes;
351*9880d681SAndroid Build Coastguard Worker auto &RetParamRelations = MaybeInfo->getAliasSummary().RetParamRelations;
352*9880d681SAndroid Build Coastguard Worker
353*9880d681SAndroid Build Coastguard Worker bool ArgAttributeIsWritten =
354*9880d681SAndroid Build Coastguard Worker std::any_of(RetParamAttributes.begin(), RetParamAttributes.end(),
355*9880d681SAndroid Build Coastguard Worker [ArgIdx](const ExternalAttribute &ExtAttr) {
356*9880d681SAndroid Build Coastguard Worker return ExtAttr.IValue.Index == ArgIdx + 1;
357*9880d681SAndroid Build Coastguard Worker });
358*9880d681SAndroid Build Coastguard Worker bool ArgIsAccessed =
359*9880d681SAndroid Build Coastguard Worker std::any_of(RetParamRelations.begin(), RetParamRelations.end(),
360*9880d681SAndroid Build Coastguard Worker [ArgIdx](const ExternalRelation &ExtRelation) {
361*9880d681SAndroid Build Coastguard Worker return ExtRelation.To.Index == ArgIdx + 1 ||
362*9880d681SAndroid Build Coastguard Worker ExtRelation.From.Index == ArgIdx + 1;
363*9880d681SAndroid Build Coastguard Worker });
364*9880d681SAndroid Build Coastguard Worker
365*9880d681SAndroid Build Coastguard Worker return (!ArgIsAccessed && !ArgAttributeIsWritten) ? MRI_NoModRef
366*9880d681SAndroid Build Coastguard Worker : MRI_ModRef;
367*9880d681SAndroid Build Coastguard Worker }
368*9880d681SAndroid Build Coastguard Worker
369*9880d681SAndroid Build Coastguard Worker return MRI_ModRef;
370*9880d681SAndroid Build Coastguard Worker }
371*9880d681SAndroid Build Coastguard Worker
372*9880d681SAndroid Build Coastguard Worker FunctionModRefBehavior
getModRefBehavior(ImmutableCallSite CS)373*9880d681SAndroid Build Coastguard Worker CFLSteensAAResult::getModRefBehavior(ImmutableCallSite CS) {
374*9880d681SAndroid Build Coastguard Worker // If we know the callee, try analyzing it
375*9880d681SAndroid Build Coastguard Worker if (auto CalledFunc = CS.getCalledFunction())
376*9880d681SAndroid Build Coastguard Worker return getModRefBehavior(CalledFunc);
377*9880d681SAndroid Build Coastguard Worker
378*9880d681SAndroid Build Coastguard Worker // Otherwise, be conservative
379*9880d681SAndroid Build Coastguard Worker return FMRB_UnknownModRefBehavior;
380*9880d681SAndroid Build Coastguard Worker }
381*9880d681SAndroid Build Coastguard Worker
getModRefBehavior(const Function * F)382*9880d681SAndroid Build Coastguard Worker FunctionModRefBehavior CFLSteensAAResult::getModRefBehavior(const Function *F) {
383*9880d681SAndroid Build Coastguard Worker assert(F != nullptr);
384*9880d681SAndroid Build Coastguard Worker
385*9880d681SAndroid Build Coastguard Worker // TODO: Remove the const_cast
386*9880d681SAndroid Build Coastguard Worker auto &MaybeInfo = ensureCached(const_cast<Function *>(F));
387*9880d681SAndroid Build Coastguard Worker if (!MaybeInfo.hasValue())
388*9880d681SAndroid Build Coastguard Worker return FMRB_UnknownModRefBehavior;
389*9880d681SAndroid Build Coastguard Worker auto &RetParamAttributes = MaybeInfo->getAliasSummary().RetParamAttributes;
390*9880d681SAndroid Build Coastguard Worker auto &RetParamRelations = MaybeInfo->getAliasSummary().RetParamRelations;
391*9880d681SAndroid Build Coastguard Worker
392*9880d681SAndroid Build Coastguard Worker // First, if any argument is marked Escpaed, Unknown or Global, anything may
393*9880d681SAndroid Build Coastguard Worker // happen to them and thus we can't draw any conclusion.
394*9880d681SAndroid Build Coastguard Worker if (!RetParamAttributes.empty())
395*9880d681SAndroid Build Coastguard Worker return FMRB_UnknownModRefBehavior;
396*9880d681SAndroid Build Coastguard Worker
397*9880d681SAndroid Build Coastguard Worker // Currently we don't (and can't) distinguish reads from writes in
398*9880d681SAndroid Build Coastguard Worker // RetParamRelations. All we can say is whether there may be memory access or
399*9880d681SAndroid Build Coastguard Worker // not.
400*9880d681SAndroid Build Coastguard Worker if (RetParamRelations.empty())
401*9880d681SAndroid Build Coastguard Worker return FMRB_DoesNotAccessMemory;
402*9880d681SAndroid Build Coastguard Worker
403*9880d681SAndroid Build Coastguard Worker // Check if something beyond argmem gets touched.
404*9880d681SAndroid Build Coastguard Worker bool AccessArgMemoryOnly =
405*9880d681SAndroid Build Coastguard Worker std::all_of(RetParamRelations.begin(), RetParamRelations.end(),
406*9880d681SAndroid Build Coastguard Worker [](const ExternalRelation &ExtRelation) {
407*9880d681SAndroid Build Coastguard Worker // Both DerefLevels has to be 0, since we don't know which
408*9880d681SAndroid Build Coastguard Worker // one is a read and which is a write.
409*9880d681SAndroid Build Coastguard Worker return ExtRelation.From.DerefLevel == 0 &&
410*9880d681SAndroid Build Coastguard Worker ExtRelation.To.DerefLevel == 0;
411*9880d681SAndroid Build Coastguard Worker });
412*9880d681SAndroid Build Coastguard Worker return AccessArgMemoryOnly ? FMRB_OnlyAccessesArgumentPointees
413*9880d681SAndroid Build Coastguard Worker : FMRB_UnknownModRefBehavior;
414*9880d681SAndroid Build Coastguard Worker }
415*9880d681SAndroid Build Coastguard Worker
416*9880d681SAndroid Build Coastguard Worker char CFLSteensAA::PassID;
417*9880d681SAndroid Build Coastguard Worker
run(Function & F,AnalysisManager<Function> & AM)418*9880d681SAndroid Build Coastguard Worker CFLSteensAAResult CFLSteensAA::run(Function &F, AnalysisManager<Function> &AM) {
419*9880d681SAndroid Build Coastguard Worker return CFLSteensAAResult(AM.getResult<TargetLibraryAnalysis>(F));
420*9880d681SAndroid Build Coastguard Worker }
421*9880d681SAndroid Build Coastguard Worker
422*9880d681SAndroid Build Coastguard Worker char CFLSteensAAWrapperPass::ID = 0;
423*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS(CFLSteensAAWrapperPass, "cfl-steens-aa",
424*9880d681SAndroid Build Coastguard Worker "Unification-Based CFL Alias Analysis", false, true)
425*9880d681SAndroid Build Coastguard Worker
createCFLSteensAAWrapperPass()426*9880d681SAndroid Build Coastguard Worker ImmutablePass *llvm::createCFLSteensAAWrapperPass() {
427*9880d681SAndroid Build Coastguard Worker return new CFLSteensAAWrapperPass();
428*9880d681SAndroid Build Coastguard Worker }
429*9880d681SAndroid Build Coastguard Worker
CFLSteensAAWrapperPass()430*9880d681SAndroid Build Coastguard Worker CFLSteensAAWrapperPass::CFLSteensAAWrapperPass() : ImmutablePass(ID) {
431*9880d681SAndroid Build Coastguard Worker initializeCFLSteensAAWrapperPassPass(*PassRegistry::getPassRegistry());
432*9880d681SAndroid Build Coastguard Worker }
433*9880d681SAndroid Build Coastguard Worker
initializePass()434*9880d681SAndroid Build Coastguard Worker void CFLSteensAAWrapperPass::initializePass() {
435*9880d681SAndroid Build Coastguard Worker auto &TLIWP = getAnalysis<TargetLibraryInfoWrapperPass>();
436*9880d681SAndroid Build Coastguard Worker Result.reset(new CFLSteensAAResult(TLIWP.getTLI()));
437*9880d681SAndroid Build Coastguard Worker }
438*9880d681SAndroid Build Coastguard Worker
getAnalysisUsage(AnalysisUsage & AU) const439*9880d681SAndroid Build Coastguard Worker void CFLSteensAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
440*9880d681SAndroid Build Coastguard Worker AU.setPreservesAll();
441*9880d681SAndroid Build Coastguard Worker AU.addRequired<TargetLibraryInfoWrapperPass>();
442*9880d681SAndroid Build Coastguard Worker }
443