LLVM API Documentation
00001 //===- AliasAnalysisEvaluator.cpp - Alias Analysis Accuracy Evaluator -----===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements a simple N^2 alias analysis accuracy evaluator. 00011 // Basically, for each function in the program, it simply queries to see how the 00012 // alias analysis implementation answers alias queries between each pair of 00013 // pointers in the function. 00014 // 00015 // This is inspired and adapted from code by: Naveen Neelakantam, Francesco 00016 // Spadini, and Wojciech Stryjewski. 00017 // 00018 //===----------------------------------------------------------------------===// 00019 00020 #include "llvm/Analysis/Passes.h" 00021 #include "llvm/ADT/SetVector.h" 00022 #include "llvm/Analysis/AliasAnalysis.h" 00023 #include "llvm/Assembly/Writer.h" 00024 #include "llvm/IR/Constants.h" 00025 #include "llvm/IR/DerivedTypes.h" 00026 #include "llvm/IR/Function.h" 00027 #include "llvm/IR/Instructions.h" 00028 #include "llvm/Pass.h" 00029 #include "llvm/Support/CommandLine.h" 00030 #include "llvm/Support/Debug.h" 00031 #include "llvm/Support/InstIterator.h" 00032 #include "llvm/Support/raw_ostream.h" 00033 using namespace llvm; 00034 00035 static cl::opt<bool> PrintAll("print-all-alias-modref-info", cl::ReallyHidden); 00036 00037 static cl::opt<bool> PrintNoAlias("print-no-aliases", cl::ReallyHidden); 00038 static cl::opt<bool> PrintMayAlias("print-may-aliases", cl::ReallyHidden); 00039 static cl::opt<bool> PrintPartialAlias("print-partial-aliases", cl::ReallyHidden); 00040 static cl::opt<bool> PrintMustAlias("print-must-aliases", cl::ReallyHidden); 00041 00042 static cl::opt<bool> PrintNoModRef("print-no-modref", cl::ReallyHidden); 00043 static cl::opt<bool> PrintMod("print-mod", cl::ReallyHidden); 00044 static cl::opt<bool> PrintRef("print-ref", cl::ReallyHidden); 00045 static cl::opt<bool> PrintModRef("print-modref", cl::ReallyHidden); 00046 00047 static cl::opt<bool> EvalTBAA("evaluate-tbaa", cl::ReallyHidden); 00048 00049 namespace { 00050 class AAEval : public FunctionPass { 00051 unsigned NoAlias, MayAlias, PartialAlias, MustAlias; 00052 unsigned NoModRef, Mod, Ref, ModRef; 00053 00054 public: 00055 static char ID; // Pass identification, replacement for typeid 00056 AAEval() : FunctionPass(ID) { 00057 initializeAAEvalPass(*PassRegistry::getPassRegistry()); 00058 } 00059 00060 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 00061 AU.addRequired<AliasAnalysis>(); 00062 AU.setPreservesAll(); 00063 } 00064 00065 bool doInitialization(Module &M) { 00066 NoAlias = MayAlias = PartialAlias = MustAlias = 0; 00067 NoModRef = Mod = Ref = ModRef = 0; 00068 00069 if (PrintAll) { 00070 PrintNoAlias = PrintMayAlias = true; 00071 PrintPartialAlias = PrintMustAlias = true; 00072 PrintNoModRef = PrintMod = PrintRef = PrintModRef = true; 00073 } 00074 return false; 00075 } 00076 00077 bool runOnFunction(Function &F); 00078 bool doFinalization(Module &M); 00079 }; 00080 } 00081 00082 char AAEval::ID = 0; 00083 INITIALIZE_PASS_BEGIN(AAEval, "aa-eval", 00084 "Exhaustive Alias Analysis Precision Evaluator", false, true) 00085 INITIALIZE_AG_DEPENDENCY(AliasAnalysis) 00086 INITIALIZE_PASS_END(AAEval, "aa-eval", 00087 "Exhaustive Alias Analysis Precision Evaluator", false, true) 00088 00089 FunctionPass *llvm::createAAEvalPass() { return new AAEval(); } 00090 00091 static void PrintResults(const char *Msg, bool P, const Value *V1, 00092 const Value *V2, const Module *M) { 00093 if (P) { 00094 std::string o1, o2; 00095 { 00096 raw_string_ostream os1(o1), os2(o2); 00097 WriteAsOperand(os1, V1, true, M); 00098 WriteAsOperand(os2, V2, true, M); 00099 } 00100 00101 if (o2 < o1) 00102 std::swap(o1, o2); 00103 errs() << " " << Msg << ":\t" 00104 << o1 << ", " 00105 << o2 << "\n"; 00106 } 00107 } 00108 00109 static inline void 00110 PrintModRefResults(const char *Msg, bool P, Instruction *I, Value *Ptr, 00111 Module *M) { 00112 if (P) { 00113 errs() << " " << Msg << ": Ptr: "; 00114 WriteAsOperand(errs(), Ptr, true, M); 00115 errs() << "\t<->" << *I << '\n'; 00116 } 00117 } 00118 00119 static inline void 00120 PrintModRefResults(const char *Msg, bool P, CallSite CSA, CallSite CSB, 00121 Module *M) { 00122 if (P) { 00123 errs() << " " << Msg << ": " << *CSA.getInstruction() 00124 << " <-> " << *CSB.getInstruction() << '\n'; 00125 } 00126 } 00127 00128 static inline void 00129 PrintLoadStoreResults(const char *Msg, bool P, const Value *V1, 00130 const Value *V2, const Module *M) { 00131 if (P) { 00132 errs() << " " << Msg << ": " << *V1 00133 << " <-> " << *V2 << '\n'; 00134 } 00135 } 00136 00137 static inline bool isInterestingPointer(Value *V) { 00138 return V->getType()->isPointerTy() 00139 && !isa<ConstantPointerNull>(V); 00140 } 00141 00142 bool AAEval::runOnFunction(Function &F) { 00143 AliasAnalysis &AA = getAnalysis<AliasAnalysis>(); 00144 00145 SetVector<Value *> Pointers; 00146 SetVector<CallSite> CallSites; 00147 SetVector<Value *> Loads; 00148 SetVector<Value *> Stores; 00149 00150 for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) 00151 if (I->getType()->isPointerTy()) // Add all pointer arguments. 00152 Pointers.insert(I); 00153 00154 for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { 00155 if (I->getType()->isPointerTy()) // Add all pointer instructions. 00156 Pointers.insert(&*I); 00157 if (EvalTBAA && isa<LoadInst>(&*I)) 00158 Loads.insert(&*I); 00159 if (EvalTBAA && isa<StoreInst>(&*I)) 00160 Stores.insert(&*I); 00161 Instruction &Inst = *I; 00162 if (CallSite CS = cast<Value>(&Inst)) { 00163 Value *Callee = CS.getCalledValue(); 00164 // Skip actual functions for direct function calls. 00165 if (!isa<Function>(Callee) && isInterestingPointer(Callee)) 00166 Pointers.insert(Callee); 00167 // Consider formals. 00168 for (CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end(); 00169 AI != AE; ++AI) 00170 if (isInterestingPointer(*AI)) 00171 Pointers.insert(*AI); 00172 CallSites.insert(CS); 00173 } else { 00174 // Consider all operands. 00175 for (Instruction::op_iterator OI = Inst.op_begin(), OE = Inst.op_end(); 00176 OI != OE; ++OI) 00177 if (isInterestingPointer(*OI)) 00178 Pointers.insert(*OI); 00179 } 00180 } 00181 00182 if (PrintNoAlias || PrintMayAlias || PrintPartialAlias || PrintMustAlias || 00183 PrintNoModRef || PrintMod || PrintRef || PrintModRef) 00184 errs() << "Function: " << F.getName() << ": " << Pointers.size() 00185 << " pointers, " << CallSites.size() << " call sites\n"; 00186 00187 // iterate over the worklist, and run the full (n^2)/2 disambiguations 00188 for (SetVector<Value *>::iterator I1 = Pointers.begin(), E = Pointers.end(); 00189 I1 != E; ++I1) { 00190 uint64_t I1Size = AliasAnalysis::UnknownSize; 00191 Type *I1ElTy = cast<PointerType>((*I1)->getType())->getElementType(); 00192 if (I1ElTy->isSized()) I1Size = AA.getTypeStoreSize(I1ElTy); 00193 00194 for (SetVector<Value *>::iterator I2 = Pointers.begin(); I2 != I1; ++I2) { 00195 uint64_t I2Size = AliasAnalysis::UnknownSize; 00196 Type *I2ElTy =cast<PointerType>((*I2)->getType())->getElementType(); 00197 if (I2ElTy->isSized()) I2Size = AA.getTypeStoreSize(I2ElTy); 00198 00199 switch (AA.alias(*I1, I1Size, *I2, I2Size)) { 00200 case AliasAnalysis::NoAlias: 00201 PrintResults("NoAlias", PrintNoAlias, *I1, *I2, F.getParent()); 00202 ++NoAlias; break; 00203 case AliasAnalysis::MayAlias: 00204 PrintResults("MayAlias", PrintMayAlias, *I1, *I2, F.getParent()); 00205 ++MayAlias; break; 00206 case AliasAnalysis::PartialAlias: 00207 PrintResults("PartialAlias", PrintPartialAlias, *I1, *I2, 00208 F.getParent()); 00209 ++PartialAlias; break; 00210 case AliasAnalysis::MustAlias: 00211 PrintResults("MustAlias", PrintMustAlias, *I1, *I2, F.getParent()); 00212 ++MustAlias; break; 00213 } 00214 } 00215 } 00216 00217 if (EvalTBAA) { 00218 // iterate over all pairs of load, store 00219 for (SetVector<Value *>::iterator I1 = Loads.begin(), E = Loads.end(); 00220 I1 != E; ++I1) { 00221 for (SetVector<Value *>::iterator I2 = Stores.begin(), E2 = Stores.end(); 00222 I2 != E2; ++I2) { 00223 switch (AA.alias(AA.getLocation(cast<LoadInst>(*I1)), 00224 AA.getLocation(cast<StoreInst>(*I2)))) { 00225 case AliasAnalysis::NoAlias: 00226 PrintLoadStoreResults("NoAlias", PrintNoAlias, *I1, *I2, 00227 F.getParent()); 00228 ++NoAlias; break; 00229 case AliasAnalysis::MayAlias: 00230 PrintLoadStoreResults("MayAlias", PrintMayAlias, *I1, *I2, 00231 F.getParent()); 00232 ++MayAlias; break; 00233 case AliasAnalysis::PartialAlias: 00234 PrintLoadStoreResults("PartialAlias", PrintPartialAlias, *I1, *I2, 00235 F.getParent()); 00236 ++PartialAlias; break; 00237 case AliasAnalysis::MustAlias: 00238 PrintLoadStoreResults("MustAlias", PrintMustAlias, *I1, *I2, 00239 F.getParent()); 00240 ++MustAlias; break; 00241 } 00242 } 00243 } 00244 00245 // iterate over all pairs of store, store 00246 for (SetVector<Value *>::iterator I1 = Stores.begin(), E = Stores.end(); 00247 I1 != E; ++I1) { 00248 for (SetVector<Value *>::iterator I2 = Stores.begin(); I2 != I1; ++I2) { 00249 switch (AA.alias(AA.getLocation(cast<StoreInst>(*I1)), 00250 AA.getLocation(cast<StoreInst>(*I2)))) { 00251 case AliasAnalysis::NoAlias: 00252 PrintLoadStoreResults("NoAlias", PrintNoAlias, *I1, *I2, 00253 F.getParent()); 00254 ++NoAlias; break; 00255 case AliasAnalysis::MayAlias: 00256 PrintLoadStoreResults("MayAlias", PrintMayAlias, *I1, *I2, 00257 F.getParent()); 00258 ++MayAlias; break; 00259 case AliasAnalysis::PartialAlias: 00260 PrintLoadStoreResults("PartialAlias", PrintPartialAlias, *I1, *I2, 00261 F.getParent()); 00262 ++PartialAlias; break; 00263 case AliasAnalysis::MustAlias: 00264 PrintLoadStoreResults("MustAlias", PrintMustAlias, *I1, *I2, 00265 F.getParent()); 00266 ++MustAlias; break; 00267 } 00268 } 00269 } 00270 } 00271 00272 // Mod/ref alias analysis: compare all pairs of calls and values 00273 for (SetVector<CallSite>::iterator C = CallSites.begin(), 00274 Ce = CallSites.end(); C != Ce; ++C) { 00275 Instruction *I = C->getInstruction(); 00276 00277 for (SetVector<Value *>::iterator V = Pointers.begin(), Ve = Pointers.end(); 00278 V != Ve; ++V) { 00279 uint64_t Size = AliasAnalysis::UnknownSize; 00280 Type *ElTy = cast<PointerType>((*V)->getType())->getElementType(); 00281 if (ElTy->isSized()) Size = AA.getTypeStoreSize(ElTy); 00282 00283 switch (AA.getModRefInfo(*C, *V, Size)) { 00284 case AliasAnalysis::NoModRef: 00285 PrintModRefResults("NoModRef", PrintNoModRef, I, *V, F.getParent()); 00286 ++NoModRef; break; 00287 case AliasAnalysis::Mod: 00288 PrintModRefResults("Just Mod", PrintMod, I, *V, F.getParent()); 00289 ++Mod; break; 00290 case AliasAnalysis::Ref: 00291 PrintModRefResults("Just Ref", PrintRef, I, *V, F.getParent()); 00292 ++Ref; break; 00293 case AliasAnalysis::ModRef: 00294 PrintModRefResults("Both ModRef", PrintModRef, I, *V, F.getParent()); 00295 ++ModRef; break; 00296 } 00297 } 00298 } 00299 00300 // Mod/ref alias analysis: compare all pairs of calls 00301 for (SetVector<CallSite>::iterator C = CallSites.begin(), 00302 Ce = CallSites.end(); C != Ce; ++C) { 00303 for (SetVector<CallSite>::iterator D = CallSites.begin(); D != Ce; ++D) { 00304 if (D == C) 00305 continue; 00306 switch (AA.getModRefInfo(*C, *D)) { 00307 case AliasAnalysis::NoModRef: 00308 PrintModRefResults("NoModRef", PrintNoModRef, *C, *D, F.getParent()); 00309 ++NoModRef; break; 00310 case AliasAnalysis::Mod: 00311 PrintModRefResults("Just Mod", PrintMod, *C, *D, F.getParent()); 00312 ++Mod; break; 00313 case AliasAnalysis::Ref: 00314 PrintModRefResults("Just Ref", PrintRef, *C, *D, F.getParent()); 00315 ++Ref; break; 00316 case AliasAnalysis::ModRef: 00317 PrintModRefResults("Both ModRef", PrintModRef, *C, *D, F.getParent()); 00318 ++ModRef; break; 00319 } 00320 } 00321 } 00322 00323 return false; 00324 } 00325 00326 static void PrintPercent(unsigned Num, unsigned Sum) { 00327 errs() << "(" << Num*100ULL/Sum << "." 00328 << ((Num*1000ULL/Sum) % 10) << "%)\n"; 00329 } 00330 00331 bool AAEval::doFinalization(Module &M) { 00332 unsigned AliasSum = NoAlias + MayAlias + PartialAlias + MustAlias; 00333 errs() << "===== Alias Analysis Evaluator Report =====\n"; 00334 if (AliasSum == 0) { 00335 errs() << " Alias Analysis Evaluator Summary: No pointers!\n"; 00336 } else { 00337 errs() << " " << AliasSum << " Total Alias Queries Performed\n"; 00338 errs() << " " << NoAlias << " no alias responses "; 00339 PrintPercent(NoAlias, AliasSum); 00340 errs() << " " << MayAlias << " may alias responses "; 00341 PrintPercent(MayAlias, AliasSum); 00342 errs() << " " << PartialAlias << " partial alias responses "; 00343 PrintPercent(PartialAlias, AliasSum); 00344 errs() << " " << MustAlias << " must alias responses "; 00345 PrintPercent(MustAlias, AliasSum); 00346 errs() << " Alias Analysis Evaluator Pointer Alias Summary: " 00347 << NoAlias*100/AliasSum << "%/" << MayAlias*100/AliasSum << "%/" 00348 << PartialAlias*100/AliasSum << "%/" 00349 << MustAlias*100/AliasSum << "%\n"; 00350 } 00351 00352 // Display the summary for mod/ref analysis 00353 unsigned ModRefSum = NoModRef + Mod + Ref + ModRef; 00354 if (ModRefSum == 0) { 00355 errs() << " Alias Analysis Mod/Ref Evaluator Summary: no mod/ref!\n"; 00356 } else { 00357 errs() << " " << ModRefSum << " Total ModRef Queries Performed\n"; 00358 errs() << " " << NoModRef << " no mod/ref responses "; 00359 PrintPercent(NoModRef, ModRefSum); 00360 errs() << " " << Mod << " mod responses "; 00361 PrintPercent(Mod, ModRefSum); 00362 errs() << " " << Ref << " ref responses "; 00363 PrintPercent(Ref, ModRefSum); 00364 errs() << " " << ModRef << " mod & ref responses "; 00365 PrintPercent(ModRef, ModRefSum); 00366 errs() << " Alias Analysis Evaluator Mod/Ref Summary: " 00367 << NoModRef*100/ModRefSum << "%/" << Mod*100/ModRefSum << "%/" 00368 << Ref*100/ModRefSum << "%/" << ModRef*100/ModRefSum << "%\n"; 00369 } 00370 00371 return false; 00372 }