LLVM API Documentation

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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/Assembly/Writer.h"
24 #include "llvm/IR/Constants.h"
25 #include "llvm/IR/DerivedTypes.h"
26 #include "llvm/IR/Function.h"
27 #include "llvm/IR/Instructions.h"
28 #include "llvm/Pass.h"
30 #include "llvm/Support/Debug.h"
33 using namespace llvm;
34 
35 static cl::opt<bool> PrintAll("print-all-alias-modref-info", cl::ReallyHidden);
36 
37 static cl::opt<bool> PrintNoAlias("print-no-aliases", cl::ReallyHidden);
38 static cl::opt<bool> PrintMayAlias("print-may-aliases", cl::ReallyHidden);
39 static cl::opt<bool> PrintPartialAlias("print-partial-aliases", cl::ReallyHidden);
40 static cl::opt<bool> PrintMustAlias("print-must-aliases", cl::ReallyHidden);
41 
42 static cl::opt<bool> PrintNoModRef("print-no-modref", cl::ReallyHidden);
43 static cl::opt<bool> PrintMod("print-mod", cl::ReallyHidden);
44 static cl::opt<bool> PrintRef("print-ref", cl::ReallyHidden);
45 static cl::opt<bool> PrintModRef("print-modref", cl::ReallyHidden);
46 
47 static cl::opt<bool> EvalTBAA("evaluate-tbaa", cl::ReallyHidden);
48 
49 namespace {
50  class AAEval : public FunctionPass {
51  unsigned NoAlias, MayAlias, PartialAlias, MustAlias;
52  unsigned NoModRef, Mod, Ref, ModRef;
53 
54  public:
55  static char ID; // Pass identification, replacement for typeid
56  AAEval() : FunctionPass(ID) {
58  }
59 
60  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
62  AU.setPreservesAll();
63  }
64 
65  bool doInitialization(Module &M) {
66  NoAlias = MayAlias = PartialAlias = MustAlias = 0;
67  NoModRef = Mod = Ref = ModRef = 0;
68 
69  if (PrintAll) {
70  PrintNoAlias = PrintMayAlias = true;
73  }
74  return false;
75  }
76 
77  bool runOnFunction(Function &F);
78  bool doFinalization(Module &M);
79  };
80 }
81 
82 char AAEval::ID = 0;
83 INITIALIZE_PASS_BEGIN(AAEval, "aa-eval",
84  "Exhaustive Alias Analysis Precision Evaluator", false, true)
87  "Exhaustive Alias Analysis Precision Evaluator", false, true)
88 
89 FunctionPass *llvm::createAAEvalPass() { return new AAEval(); }
90 
91 static void PrintResults(const char *Msg, bool P, const Value *V1,
92  const Value *V2, const Module *M) {
93  if (P) {
94  std::string o1, o2;
95  {
96  raw_string_ostream os1(o1), os2(o2);
97  WriteAsOperand(os1, V1, true, M);
98  WriteAsOperand(os2, V2, true, M);
99  }
100 
101  if (o2 < o1)
102  std::swap(o1, o2);
103  errs() << " " << Msg << ":\t"
104  << o1 << ", "
105  << o2 << "\n";
106  }
107 }
108 
109 static inline void
110 PrintModRefResults(const char *Msg, bool P, Instruction *I, Value *Ptr,
111  Module *M) {
112  if (P) {
113  errs() << " " << Msg << ": Ptr: ";
114  WriteAsOperand(errs(), Ptr, true, M);
115  errs() << "\t<->" << *I << '\n';
116  }
117 }
118 
119 static inline void
120 PrintModRefResults(const char *Msg, bool P, CallSite CSA, CallSite CSB,
121  Module *M) {
122  if (P) {
123  errs() << " " << Msg << ": " << *CSA.getInstruction()
124  << " <-> " << *CSB.getInstruction() << '\n';
125  }
126 }
127 
128 static inline void
129 PrintLoadStoreResults(const char *Msg, bool P, const Value *V1,
130  const Value *V2, const Module *M) {
131  if (P) {
132  errs() << " " << Msg << ": " << *V1
133  << " <-> " << *V2 << '\n';
134  }
135 }
136 
137 static inline bool isInterestingPointer(Value *V) {
138  return V->getType()->isPointerTy()
139  && !isa<ConstantPointerNull>(V);
140 }
141 
142 bool AAEval::runOnFunction(Function &F) {
143  AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
144 
145  SetVector<Value *> Pointers;
146  SetVector<CallSite> CallSites;
147  SetVector<Value *> Loads;
148  SetVector<Value *> Stores;
149 
150  for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I)
151  if (I->getType()->isPointerTy()) // Add all pointer arguments.
152  Pointers.insert(I);
153 
154  for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
155  if (I->getType()->isPointerTy()) // Add all pointer instructions.
156  Pointers.insert(&*I);
157  if (EvalTBAA && isa<LoadInst>(&*I))
158  Loads.insert(&*I);
159  if (EvalTBAA && isa<StoreInst>(&*I))
160  Stores.insert(&*I);
161  Instruction &Inst = *I;
162  if (CallSite CS = cast<Value>(&Inst)) {
163  Value *Callee = CS.getCalledValue();
164  // Skip actual functions for direct function calls.
165  if (!isa<Function>(Callee) && isInterestingPointer(Callee))
166  Pointers.insert(Callee);
167  // Consider formals.
168  for (CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end();
169  AI != AE; ++AI)
170  if (isInterestingPointer(*AI))
171  Pointers.insert(*AI);
172  CallSites.insert(CS);
173  } else {
174  // Consider all operands.
175  for (Instruction::op_iterator OI = Inst.op_begin(), OE = Inst.op_end();
176  OI != OE; ++OI)
177  if (isInterestingPointer(*OI))
178  Pointers.insert(*OI);
179  }
180  }
181 
184  errs() << "Function: " << F.getName() << ": " << Pointers.size()
185  << " pointers, " << CallSites.size() << " call sites\n";
186 
187  // iterate over the worklist, and run the full (n^2)/2 disambiguations
188  for (SetVector<Value *>::iterator I1 = Pointers.begin(), E = Pointers.end();
189  I1 != E; ++I1) {
190  uint64_t I1Size = AliasAnalysis::UnknownSize;
191  Type *I1ElTy = cast<PointerType>((*I1)->getType())->getElementType();
192  if (I1ElTy->isSized()) I1Size = AA.getTypeStoreSize(I1ElTy);
193 
194  for (SetVector<Value *>::iterator I2 = Pointers.begin(); I2 != I1; ++I2) {
195  uint64_t I2Size = AliasAnalysis::UnknownSize;
196  Type *I2ElTy =cast<PointerType>((*I2)->getType())->getElementType();
197  if (I2ElTy->isSized()) I2Size = AA.getTypeStoreSize(I2ElTy);
198 
199  switch (AA.alias(*I1, I1Size, *I2, I2Size)) {
201  PrintResults("NoAlias", PrintNoAlias, *I1, *I2, F.getParent());
202  ++NoAlias; break;
204  PrintResults("MayAlias", PrintMayAlias, *I1, *I2, F.getParent());
205  ++MayAlias; break;
207  PrintResults("PartialAlias", PrintPartialAlias, *I1, *I2,
208  F.getParent());
209  ++PartialAlias; break;
211  PrintResults("MustAlias", PrintMustAlias, *I1, *I2, F.getParent());
212  ++MustAlias; break;
213  }
214  }
215  }
216 
217  if (EvalTBAA) {
218  // iterate over all pairs of load, store
219  for (SetVector<Value *>::iterator I1 = Loads.begin(), E = Loads.end();
220  I1 != E; ++I1) {
221  for (SetVector<Value *>::iterator I2 = Stores.begin(), E2 = Stores.end();
222  I2 != E2; ++I2) {
223  switch (AA.alias(AA.getLocation(cast<LoadInst>(*I1)),
224  AA.getLocation(cast<StoreInst>(*I2)))) {
226  PrintLoadStoreResults("NoAlias", PrintNoAlias, *I1, *I2,
227  F.getParent());
228  ++NoAlias; break;
230  PrintLoadStoreResults("MayAlias", PrintMayAlias, *I1, *I2,
231  F.getParent());
232  ++MayAlias; break;
234  PrintLoadStoreResults("PartialAlias", PrintPartialAlias, *I1, *I2,
235  F.getParent());
236  ++PartialAlias; break;
238  PrintLoadStoreResults("MustAlias", PrintMustAlias, *I1, *I2,
239  F.getParent());
240  ++MustAlias; break;
241  }
242  }
243  }
244 
245  // iterate over all pairs of store, store
246  for (SetVector<Value *>::iterator I1 = Stores.begin(), E = Stores.end();
247  I1 != E; ++I1) {
248  for (SetVector<Value *>::iterator I2 = Stores.begin(); I2 != I1; ++I2) {
249  switch (AA.alias(AA.getLocation(cast<StoreInst>(*I1)),
250  AA.getLocation(cast<StoreInst>(*I2)))) {
252  PrintLoadStoreResults("NoAlias", PrintNoAlias, *I1, *I2,
253  F.getParent());
254  ++NoAlias; break;
256  PrintLoadStoreResults("MayAlias", PrintMayAlias, *I1, *I2,
257  F.getParent());
258  ++MayAlias; break;
260  PrintLoadStoreResults("PartialAlias", PrintPartialAlias, *I1, *I2,
261  F.getParent());
262  ++PartialAlias; break;
264  PrintLoadStoreResults("MustAlias", PrintMustAlias, *I1, *I2,
265  F.getParent());
266  ++MustAlias; break;
267  }
268  }
269  }
270  }
271 
272  // Mod/ref alias analysis: compare all pairs of calls and values
273  for (SetVector<CallSite>::iterator C = CallSites.begin(),
274  Ce = CallSites.end(); C != Ce; ++C) {
275  Instruction *I = C->getInstruction();
276 
277  for (SetVector<Value *>::iterator V = Pointers.begin(), Ve = Pointers.end();
278  V != Ve; ++V) {
279  uint64_t Size = AliasAnalysis::UnknownSize;
280  Type *ElTy = cast<PointerType>((*V)->getType())->getElementType();
281  if (ElTy->isSized()) Size = AA.getTypeStoreSize(ElTy);
282 
283  switch (AA.getModRefInfo(*C, *V, Size)) {
285  PrintModRefResults("NoModRef", PrintNoModRef, I, *V, F.getParent());
286  ++NoModRef; break;
287  case AliasAnalysis::Mod:
288  PrintModRefResults("Just Mod", PrintMod, I, *V, F.getParent());
289  ++Mod; break;
290  case AliasAnalysis::Ref:
291  PrintModRefResults("Just Ref", PrintRef, I, *V, F.getParent());
292  ++Ref; break;
294  PrintModRefResults("Both ModRef", PrintModRef, I, *V, F.getParent());
295  ++ModRef; break;
296  }
297  }
298  }
299 
300  // Mod/ref alias analysis: compare all pairs of calls
301  for (SetVector<CallSite>::iterator C = CallSites.begin(),
302  Ce = CallSites.end(); C != Ce; ++C) {
303  for (SetVector<CallSite>::iterator D = CallSites.begin(); D != Ce; ++D) {
304  if (D == C)
305  continue;
306  switch (AA.getModRefInfo(*C, *D)) {
308  PrintModRefResults("NoModRef", PrintNoModRef, *C, *D, F.getParent());
309  ++NoModRef; break;
310  case AliasAnalysis::Mod:
311  PrintModRefResults("Just Mod", PrintMod, *C, *D, F.getParent());
312  ++Mod; break;
313  case AliasAnalysis::Ref:
314  PrintModRefResults("Just Ref", PrintRef, *C, *D, F.getParent());
315  ++Ref; break;
317  PrintModRefResults("Both ModRef", PrintModRef, *C, *D, F.getParent());
318  ++ModRef; break;
319  }
320  }
321  }
322 
323  return false;
324 }
325 
326 static void PrintPercent(unsigned Num, unsigned Sum) {
327  errs() << "(" << Num*100ULL/Sum << "."
328  << ((Num*1000ULL/Sum) % 10) << "%)\n";
329 }
330 
331 bool AAEval::doFinalization(Module &M) {
332  unsigned AliasSum = NoAlias + MayAlias + PartialAlias + MustAlias;
333  errs() << "===== Alias Analysis Evaluator Report =====\n";
334  if (AliasSum == 0) {
335  errs() << " Alias Analysis Evaluator Summary: No pointers!\n";
336  } else {
337  errs() << " " << AliasSum << " Total Alias Queries Performed\n";
338  errs() << " " << NoAlias << " no alias responses ";
339  PrintPercent(NoAlias, AliasSum);
340  errs() << " " << MayAlias << " may alias responses ";
341  PrintPercent(MayAlias, AliasSum);
342  errs() << " " << PartialAlias << " partial alias responses ";
343  PrintPercent(PartialAlias, AliasSum);
344  errs() << " " << MustAlias << " must alias responses ";
345  PrintPercent(MustAlias, AliasSum);
346  errs() << " Alias Analysis Evaluator Pointer Alias Summary: "
347  << NoAlias*100/AliasSum << "%/" << MayAlias*100/AliasSum << "%/"
348  << PartialAlias*100/AliasSum << "%/"
349  << MustAlias*100/AliasSum << "%\n";
350  }
351 
352  // Display the summary for mod/ref analysis
353  unsigned ModRefSum = NoModRef + Mod + Ref + ModRef;
354  if (ModRefSum == 0) {
355  errs() << " Alias Analysis Mod/Ref Evaluator Summary: no mod/ref!\n";
356  } else {
357  errs() << " " << ModRefSum << " Total ModRef Queries Performed\n";
358  errs() << " " << NoModRef << " no mod/ref responses ";
359  PrintPercent(NoModRef, ModRefSum);
360  errs() << " " << Mod << " mod responses ";
361  PrintPercent(Mod, ModRefSum);
362  errs() << " " << Ref << " ref responses ";
363  PrintPercent(Ref, ModRefSum);
364  errs() << " " << ModRef << " mod & ref responses ";
365  PrintPercent(ModRef, ModRefSum);
366  errs() << " Alias Analysis Evaluator Mod/Ref Summary: "
367  << NoModRef*100/ModRefSum << "%/" << Mod*100/ModRefSum << "%/"
368  << Ref*100/ModRefSum << "%/" << ModRef*100/ModRefSum << "%\n";
369  }
370 
371  return false;
372 }
static cl::opt< bool > PrintPartialAlias("print-partial-aliases", cl::ReallyHidden)
Pointers differ, but pointees overlap.
raw_ostream & errs()
static PassRegistry * getPassRegistry()
size_t size() const
size - Get the string size.
Definition: StringRef.h:113
ModRefResult getModRefInfo(const Instruction *I, const Location &Loc)
The main container class for the LLVM Intermediate Representation.
Definition: Module.h:112
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:418
FunctionPass * createAAEvalPass()
F(f)
static cl::opt< bool > EvalTBAA("evaluate-tbaa", cl::ReallyHidden)
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:116
aa Exhaustive Alias Analysis Precision false
static cl::opt< bool > PrintMustAlias("print-must-aliases", cl::ReallyHidden)
StringRef getName() const
Definition: Value.cpp:167
void WriteAsOperand(raw_ostream &, const Value *, bool PrintTy=true, const Module *Context=0)
Definition: AsmWriter.cpp:1179
AnalysisUsage & addRequired()
inst_iterator inst_begin(Function *F)
Definition: InstIterator.h:128
globalsmodref aa
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:172
ID
LLVM Calling Convention Representation.
Definition: CallingConv.h:26
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition: SetVector.h:102
iterator begin()
Get an iterator to the beginning of the SetVector.
Definition: SetVector.h:69
uint64_t getTypeStoreSize(Type *Ty)
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)
#define true
Definition: ConvertUTF.c:65
InstrTy * getInstruction() const
Definition: CallSite.h:79
virtual AliasResult alias(const Location &LocA, const Location &LocB)
static cl::opt< bool > PrintMayAlias("print-may-aliases", cl::ReallyHidden)
op_iterator op_end()
Definition: User.h:118
arg_iterator arg_begin()
Definition: Function.h:410
#define INITIALIZE_AG_DEPENDENCY(depName)
Definition: PassSupport.h:169
bool isPointerTy() const
Definition: Type.h:220
void initializeAAEvalPass(PassRegistry &)
Type * getType() const
Definition: Value.h:111
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:591
Location getLocation(const LoadInst *LI)
block Block Frequency Analysis
INITIALIZE_PASS_BEGIN(AAEval,"aa-eval","Exhaustive Alias Analysis Precision Evaluator", false, true) INITIALIZE_PASS_END(AAEval
#define I(x, y, z)
Definition: MD5.cpp:54
static uint64_t const UnknownSize
Definition: AliasAnalysis.h:84
static cl::opt< bool > PrintNoModRef("print-no-modref", cl::ReallyHidden)
Use * op_iterator
Definition: User.h:113
Module * getParent()
Definition: GlobalValue.h:286
LLVM Value Representation.
Definition: Value.h:66
vector_type::const_iterator iterator
Definition: SetVector.h:45
A vector that has set insertion semantics.
Definition: SetVector.h:37
bool isSized() const
Definition: Type.h:278
static void PrintPercent(unsigned Num, unsigned Sum)
inst_iterator inst_end(Function *F)
Definition: InstIterator.h:129
static cl::opt< bool > PrintAll("print-all-alias-modref-info", cl::ReallyHidden)
static cl::opt< bool > PrintNoAlias("print-no-aliases", cl::ReallyHidden)