LLVM  3.7.0
AliasAnalysisEvaluator.cpp
Go to the documentation of this file.
1 //===- AliasAnalysisEvaluator.cpp - Alias Analysis Accuracy Evaluator -----===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements a simple N^2 alias analysis accuracy evaluator.
11 // Basically, for each function in the program, it simply queries to see how the
12 // alias analysis implementation answers alias queries between each pair of
13 // pointers in the function.
14 //
15 // This is inspired and adapted from code by: Naveen Neelakantam, Francesco
16 // Spadini, and Wojciech Stryjewski.
17 //
18 //===----------------------------------------------------------------------===//
19 
20 #include "llvm/Analysis/Passes.h"
21 #include "llvm/ADT/SetVector.h"
23 #include "llvm/IR/Constants.h"
24 #include "llvm/IR/DerivedTypes.h"
25 #include "llvm/IR/Function.h"
26 #include "llvm/IR/InstIterator.h"
27 #include "llvm/IR/Instructions.h"
28 #include "llvm/Pass.h"
30 #include "llvm/Support/Debug.h"
32 using namespace llvm;
33 
34 static cl::opt<bool> PrintAll("print-all-alias-modref-info", cl::ReallyHidden);
35 
36 static cl::opt<bool> PrintNoAlias("print-no-aliases", cl::ReallyHidden);
37 static cl::opt<bool> PrintMayAlias("print-may-aliases", cl::ReallyHidden);
38 static cl::opt<bool> PrintPartialAlias("print-partial-aliases", cl::ReallyHidden);
39 static cl::opt<bool> PrintMustAlias("print-must-aliases", cl::ReallyHidden);
40 
41 static cl::opt<bool> PrintNoModRef("print-no-modref", cl::ReallyHidden);
42 static cl::opt<bool> PrintMod("print-mod", cl::ReallyHidden);
43 static cl::opt<bool> PrintRef("print-ref", cl::ReallyHidden);
44 static cl::opt<bool> PrintModRef("print-modref", cl::ReallyHidden);
45 
46 static cl::opt<bool> EvalAAMD("evaluate-aa-metadata", cl::ReallyHidden);
47 
48 namespace {
49  class AAEval : public FunctionPass {
50  unsigned NoAliasCount, MayAliasCount, PartialAliasCount, MustAliasCount;
51  unsigned NoModRefCount, ModCount, RefCount, ModRefCount;
52 
53  public:
54  static char ID; // Pass identification, replacement for typeid
55  AAEval() : FunctionPass(ID) {
57  }
58 
59  void getAnalysisUsage(AnalysisUsage &AU) const override {
61  AU.setPreservesAll();
62  }
63 
64  bool doInitialization(Module &M) override {
65  NoAliasCount = MayAliasCount = PartialAliasCount = MustAliasCount = 0;
66  NoModRefCount = ModCount = RefCount = ModRefCount = 0;
67 
68  if (PrintAll) {
69  PrintNoAlias = PrintMayAlias = true;
72  }
73  return false;
74  }
75 
76  bool runOnFunction(Function &F) override;
77  bool doFinalization(Module &M) override;
78  };
79 }
80 
81 char AAEval::ID = 0;
82 INITIALIZE_PASS_BEGIN(AAEval, "aa-eval",
83  "Exhaustive Alias Analysis Precision Evaluator", false, true)
86  "Exhaustive Alias Analysis Precision Evaluator", false, true)
87 
88 FunctionPass *llvm::createAAEvalPass() { return new AAEval(); }
89 
90 static void PrintResults(const char *Msg, bool P, const Value *V1,
91  const Value *V2, const Module *M) {
92  if (P) {
93  std::string o1, o2;
94  {
95  raw_string_ostream os1(o1), os2(o2);
96  V1->printAsOperand(os1, true, M);
97  V2->printAsOperand(os2, true, M);
98  }
99 
100  if (o2 < o1)
101  std::swap(o1, o2);
102  errs() << " " << Msg << ":\t"
103  << o1 << ", "
104  << o2 << "\n";
105  }
106 }
107 
108 static inline void
109 PrintModRefResults(const char *Msg, bool P, Instruction *I, Value *Ptr,
110  Module *M) {
111  if (P) {
112  errs() << " " << Msg << ": Ptr: ";
113  Ptr->printAsOperand(errs(), true, M);
114  errs() << "\t<->" << *I << '\n';
115  }
116 }
117 
118 static inline void
119 PrintModRefResults(const char *Msg, bool P, CallSite CSA, CallSite CSB,
120  Module *M) {
121  if (P) {
122  errs() << " " << Msg << ": " << *CSA.getInstruction()
123  << " <-> " << *CSB.getInstruction() << '\n';
124  }
125 }
126 
127 static inline void
128 PrintLoadStoreResults(const char *Msg, bool P, const Value *V1,
129  const Value *V2, const Module *M) {
130  if (P) {
131  errs() << " " << Msg << ": " << *V1
132  << " <-> " << *V2 << '\n';
133  }
134 }
135 
136 static inline bool isInterestingPointer(Value *V) {
137  return V->getType()->isPointerTy()
138  && !isa<ConstantPointerNull>(V);
139 }
140 
141 bool AAEval::runOnFunction(Function &F) {
142  AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
143 
144  SetVector<Value *> Pointers;
145  SetVector<CallSite> CallSites;
147  SetVector<Value *> Stores;
148 
149  for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I)
150  if (I->getType()->isPointerTy()) // Add all pointer arguments.
151  Pointers.insert(I);
152 
153  for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
154  if (I->getType()->isPointerTy()) // Add all pointer instructions.
155  Pointers.insert(&*I);
156  if (EvalAAMD && isa<LoadInst>(&*I))
157  Loads.insert(&*I);
158  if (EvalAAMD && isa<StoreInst>(&*I))
159  Stores.insert(&*I);
160  Instruction &Inst = *I;
161  if (auto CS = CallSite(&Inst)) {
162  Value *Callee = CS.getCalledValue();
163  // Skip actual functions for direct function calls.
164  if (!isa<Function>(Callee) && isInterestingPointer(Callee))
165  Pointers.insert(Callee);
166  // Consider formals.
167  for (CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end();
168  AI != AE; ++AI)
169  if (isInterestingPointer(*AI))
170  Pointers.insert(*AI);
171  CallSites.insert(CS);
172  } else {
173  // Consider all operands.
174  for (Instruction::op_iterator OI = Inst.op_begin(), OE = Inst.op_end();
175  OI != OE; ++OI)
176  if (isInterestingPointer(*OI))
177  Pointers.insert(*OI);
178  }
179  }
180 
183  errs() << "Function: " << F.getName() << ": " << Pointers.size()
184  << " pointers, " << CallSites.size() << " call sites\n";
185 
186  // iterate over the worklist, and run the full (n^2)/2 disambiguations
187  for (SetVector<Value *>::iterator I1 = Pointers.begin(), E = Pointers.end();
188  I1 != E; ++I1) {
189  uint64_t I1Size = MemoryLocation::UnknownSize;
190  Type *I1ElTy = cast<PointerType>((*I1)->getType())->getElementType();
191  if (I1ElTy->isSized()) I1Size = AA.getTypeStoreSize(I1ElTy);
192 
193  for (SetVector<Value *>::iterator I2 = Pointers.begin(); I2 != I1; ++I2) {
194  uint64_t I2Size = MemoryLocation::UnknownSize;
195  Type *I2ElTy =cast<PointerType>((*I2)->getType())->getElementType();
196  if (I2ElTy->isSized()) I2Size = AA.getTypeStoreSize(I2ElTy);
197 
198  switch (AA.alias(*I1, I1Size, *I2, I2Size)) {
199  case NoAlias:
200  PrintResults("NoAlias", PrintNoAlias, *I1, *I2, F.getParent());
201  ++NoAliasCount;
202  break;
203  case MayAlias:
204  PrintResults("MayAlias", PrintMayAlias, *I1, *I2, F.getParent());
205  ++MayAliasCount;
206  break;
207  case PartialAlias:
208  PrintResults("PartialAlias", PrintPartialAlias, *I1, *I2,
209  F.getParent());
210  ++PartialAliasCount;
211  break;
212  case MustAlias:
213  PrintResults("MustAlias", PrintMustAlias, *I1, *I2, F.getParent());
214  ++MustAliasCount;
215  break;
216  }
217  }
218  }
219 
220  if (EvalAAMD) {
221  // iterate over all pairs of load, store
222  for (SetVector<Value *>::iterator I1 = Loads.begin(), E = Loads.end();
223  I1 != E; ++I1) {
224  for (SetVector<Value *>::iterator I2 = Stores.begin(), E2 = Stores.end();
225  I2 != E2; ++I2) {
226  switch (AA.alias(MemoryLocation::get(cast<LoadInst>(*I1)),
227  MemoryLocation::get(cast<StoreInst>(*I2)))) {
228  case NoAlias:
229  PrintLoadStoreResults("NoAlias", PrintNoAlias, *I1, *I2,
230  F.getParent());
231  ++NoAliasCount;
232  break;
233  case MayAlias:
234  PrintLoadStoreResults("MayAlias", PrintMayAlias, *I1, *I2,
235  F.getParent());
236  ++MayAliasCount;
237  break;
238  case PartialAlias:
239  PrintLoadStoreResults("PartialAlias", PrintPartialAlias, *I1, *I2,
240  F.getParent());
241  ++PartialAliasCount;
242  break;
243  case MustAlias:
244  PrintLoadStoreResults("MustAlias", PrintMustAlias, *I1, *I2,
245  F.getParent());
246  ++MustAliasCount;
247  break;
248  }
249  }
250  }
251 
252  // iterate over all pairs of store, store
253  for (SetVector<Value *>::iterator I1 = Stores.begin(), E = Stores.end();
254  I1 != E; ++I1) {
255  for (SetVector<Value *>::iterator I2 = Stores.begin(); I2 != I1; ++I2) {
256  switch (AA.alias(MemoryLocation::get(cast<StoreInst>(*I1)),
257  MemoryLocation::get(cast<StoreInst>(*I2)))) {
258  case NoAlias:
259  PrintLoadStoreResults("NoAlias", PrintNoAlias, *I1, *I2,
260  F.getParent());
261  ++NoAliasCount;
262  break;
263  case MayAlias:
264  PrintLoadStoreResults("MayAlias", PrintMayAlias, *I1, *I2,
265  F.getParent());
266  ++MayAliasCount;
267  break;
268  case PartialAlias:
269  PrintLoadStoreResults("PartialAlias", PrintPartialAlias, *I1, *I2,
270  F.getParent());
271  ++PartialAliasCount;
272  break;
273  case MustAlias:
274  PrintLoadStoreResults("MustAlias", PrintMustAlias, *I1, *I2,
275  F.getParent());
276  ++MustAliasCount;
277  break;
278  }
279  }
280  }
281  }
282 
283  // Mod/ref alias analysis: compare all pairs of calls and values
284  for (SetVector<CallSite>::iterator C = CallSites.begin(),
285  Ce = CallSites.end(); C != Ce; ++C) {
286  Instruction *I = C->getInstruction();
287 
288  for (SetVector<Value *>::iterator V = Pointers.begin(), Ve = Pointers.end();
289  V != Ve; ++V) {
290  uint64_t Size = MemoryLocation::UnknownSize;
291  Type *ElTy = cast<PointerType>((*V)->getType())->getElementType();
292  if (ElTy->isSized()) Size = AA.getTypeStoreSize(ElTy);
293 
294  switch (AA.getModRefInfo(*C, *V, Size)) {
296  PrintModRefResults("NoModRef", PrintNoModRef, I, *V, F.getParent());
297  ++NoModRefCount;
298  break;
299  case AliasAnalysis::Mod:
300  PrintModRefResults("Just Mod", PrintMod, I, *V, F.getParent());
301  ++ModCount;
302  break;
303  case AliasAnalysis::Ref:
304  PrintModRefResults("Just Ref", PrintRef, I, *V, F.getParent());
305  ++RefCount;
306  break;
308  PrintModRefResults("Both ModRef", PrintModRef, I, *V, F.getParent());
309  ++ModRefCount;
310  break;
311  }
312  }
313  }
314 
315  // Mod/ref alias analysis: compare all pairs of calls
316  for (SetVector<CallSite>::iterator C = CallSites.begin(),
317  Ce = CallSites.end(); C != Ce; ++C) {
318  for (SetVector<CallSite>::iterator D = CallSites.begin(); D != Ce; ++D) {
319  if (D == C)
320  continue;
321  switch (AA.getModRefInfo(*C, *D)) {
323  PrintModRefResults("NoModRef", PrintNoModRef, *C, *D, F.getParent());
324  ++NoModRefCount;
325  break;
326  case AliasAnalysis::Mod:
327  PrintModRefResults("Just Mod", PrintMod, *C, *D, F.getParent());
328  ++ModCount;
329  break;
330  case AliasAnalysis::Ref:
331  PrintModRefResults("Just Ref", PrintRef, *C, *D, F.getParent());
332  ++RefCount;
333  break;
335  PrintModRefResults("Both ModRef", PrintModRef, *C, *D, F.getParent());
336  ++ModRefCount;
337  break;
338  }
339  }
340  }
341 
342  return false;
343 }
344 
345 static void PrintPercent(unsigned Num, unsigned Sum) {
346  errs() << "(" << Num*100ULL/Sum << "."
347  << ((Num*1000ULL/Sum) % 10) << "%)\n";
348 }
349 
350 bool AAEval::doFinalization(Module &M) {
351  unsigned AliasSum =
352  NoAliasCount + MayAliasCount + PartialAliasCount + MustAliasCount;
353  errs() << "===== Alias Analysis Evaluator Report =====\n";
354  if (AliasSum == 0) {
355  errs() << " Alias Analysis Evaluator Summary: No pointers!\n";
356  } else {
357  errs() << " " << AliasSum << " Total Alias Queries Performed\n";
358  errs() << " " << NoAliasCount << " no alias responses ";
359  PrintPercent(NoAliasCount, AliasSum);
360  errs() << " " << MayAliasCount << " may alias responses ";
361  PrintPercent(MayAliasCount, AliasSum);
362  errs() << " " << PartialAliasCount << " partial alias responses ";
363  PrintPercent(PartialAliasCount, AliasSum);
364  errs() << " " << MustAliasCount << " must alias responses ";
365  PrintPercent(MustAliasCount, AliasSum);
366  errs() << " Alias Analysis Evaluator Pointer Alias Summary: "
367  << NoAliasCount * 100 / AliasSum << "%/"
368  << MayAliasCount * 100 / AliasSum << "%/"
369  << PartialAliasCount * 100 / AliasSum << "%/"
370  << MustAliasCount * 100 / AliasSum << "%\n";
371  }
372 
373  // Display the summary for mod/ref analysis
374  unsigned ModRefSum = NoModRefCount + ModCount + RefCount + ModRefCount;
375  if (ModRefSum == 0) {
376  errs() << " Alias Analysis Mod/Ref Evaluator Summary: no "
377  "mod/ref!\n";
378  } else {
379  errs() << " " << ModRefSum << " Total ModRef Queries Performed\n";
380  errs() << " " << NoModRefCount << " no mod/ref responses ";
381  PrintPercent(NoModRefCount, ModRefSum);
382  errs() << " " << ModCount << " mod responses ";
383  PrintPercent(ModCount, ModRefSum);
384  errs() << " " << RefCount << " ref responses ";
385  PrintPercent(RefCount, ModRefSum);
386  errs() << " " << ModRefCount << " mod & ref responses ";
387  PrintPercent(ModRefCount, ModRefSum);
388  errs() << " Alias Analysis Evaluator Mod/Ref Summary: "
389  << NoModRefCount * 100 / ModRefSum << "%/"
390  << ModCount * 100 / ModRefSum << "%/" << RefCount * 100 / ModRefSum
391  << "%/" << ModRefCount * 100 / ModRefSum << "%\n";
392  }
393 
394  return false;
395 }
The two locations precisely alias each other.
Definition: AliasAnalysis.h:84
static cl::opt< bool > PrintPartialAlias("print-partial-aliases", cl::ReallyHidden)
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
size_t size() const
size - Get the string size.
Definition: StringRef.h:113
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:114
InstrTy * getInstruction() const
Definition: CallSite.h:82
The two locations alias, but only due to a partial overlap.
Definition: AliasAnalysis.h:82
static void PrintModRefResults(const char *Msg, bool P, Instruction *I, Value *Ptr, Module *M)
static cl::opt< bool > PrintMod("print-mod", cl::ReallyHidden)
static cl::opt< bool > PrintModRef("print-modref", cl::ReallyHidden)
arg_iterator arg_end()
Definition: Function.h:480
The two locations do not alias at all.
Definition: AliasAnalysis.h:78
FunctionPass * createAAEvalPass()
F(f)
User::op_iterator arg_iterator
arg_iterator - The type of iterator to use when looping over actual arguments at this call site...
Definition: CallSite.h:147
iterator end()
Get an iterator to the end of the SetVector.
Definition: SetVector.h:79
size_type size() const
Determine the number of elements in the SetVector.
Definition: SetVector.h:64
op_iterator op_begin()
Definition: User.h:183
The two locations may or may not alias. This is the least precise result.
Definition: AliasAnalysis.h:80
aa Exhaustive Alias Analysis Precision false
static cl::opt< bool > PrintMustAlias("print-must-aliases", cl::ReallyHidden)
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:188
AnalysisUsage & addRequired()
inst_iterator inst_begin(Function *F)
Definition: InstIterator.h:127
globalsmodref aa
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:75
bool isSized(SmallPtrSetImpl< const Type * > *Visited=nullptr) const
isSized - Return true if it makes sense to take the size of this type.
Definition: Type.h:268
load Combine Adjacent Loads
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition: SetVector.h:102
void printAsOperand(raw_ostream &O, bool PrintType=true, const Module *M=nullptr) const
Print the name of this Value out to the specified raw_ostream.
Definition: AsmWriter.cpp:3287
iterator begin()
Get an iterator to the beginning of the SetVector.
Definition: SetVector.h:69
uint64_t getTypeStoreSize(Type *Ty)
getTypeStoreSize - Return the DataLayout store size for the given type, if known, or a conservative v...
static void PrintResults(const char *Msg, bool P, const Value *V1, const Value *V2, const Module *M)
static void PrintLoadStoreResults(const char *Msg, bool P, const Value *V1, const Value *V2, const Module *M)
aa Exhaustive Alias Analysis Precision Evaluator
static bool isInterestingPointer(Value *V)
static cl::opt< bool > PrintRef("print-ref", cl::ReallyHidden)
#define P(N)
static MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
#define true
Definition: ConvertUTF.c:66
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:45
static cl::opt< bool > PrintMayAlias("print-may-aliases", cl::ReallyHidden)
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Represent the analysis usage information of a pass.
op_iterator op_end()
Definition: User.h:185
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:294
arg_iterator arg_begin()
Definition: Function.h:472
#define INITIALIZE_AG_DEPENDENCY(depName)
Definition: PassSupport.h:72
bool isPointerTy() const
isPointerTy - True if this is an instance of PointerType.
Definition: Type.h:217
void initializeAAEvalPass(PassRegistry &)
virtual AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB)
Alias Queries...
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:222
ModRefResult getModRefInfo(const Instruction *I)
getModRefInfo - Return information about whether or not an instruction may read or write memory (with...
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:576
void setPreservesAll()
Set by analyses that do not transform their input at all.
block Block Frequency Analysis
INITIALIZE_PASS_BEGIN(AAEval,"aa-eval","Exhaustive Alias Analysis Precision Evaluator", false, true) INITIALIZE_PASS_END(AAEval
static cl::opt< bool > EvalAAMD("evaluate-aa-metadata", cl::ReallyHidden)
#define I(x, y, z)
Definition: MD5.cpp:54
static cl::opt< bool > PrintNoModRef("print-no-modref", cl::ReallyHidden)
Use * op_iterator
Definition: User.h:178
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:465
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:365
LLVM Value Representation.
Definition: Value.h:69
vector_type::const_iterator iterator
Definition: SetVector.h:45
A vector that has set insertion semantics.
Definition: SetVector.h:37
static void PrintPercent(unsigned Num, unsigned Sum)
C - The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
inst_iterator inst_end(Function *F)
Definition: InstIterator.h:128
static cl::opt< bool > PrintAll("print-all-alias-modref-info", cl::ReallyHidden)
static cl::opt< bool > PrintNoAlias("print-no-aliases", cl::ReallyHidden)