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" 22 #include "llvm/Analysis/AliasAnalysis.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" 29 #include "llvm/Support/CommandLine.h" 30 #include "llvm/Support/Debug.h" 31 #include "llvm/Support/InstIterator.h" 32 #include "llvm/Support/raw_ostream.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) { 57 initializeAAEvalPass(*PassRegistry::getPassRegistry()); 58 } 59 60 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 61 AU.addRequired<AliasAnalysis>(); 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; 71 PrintPartialAlias = PrintMustAlias = true; 72 PrintNoModRef = PrintMod = PrintRef = PrintModRef = 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) 85 INITIALIZE_AG_DEPENDENCY(AliasAnalysis) 86 INITIALIZE_PASS_END(AAEval, "aa-eval", 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 182 if (PrintNoAlias || PrintMayAlias || PrintPartialAlias || PrintMustAlias || 183 PrintNoModRef || PrintMod || PrintRef || PrintModRef) 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)) { 200 case AliasAnalysis::NoAlias: 201 PrintResults("NoAlias", PrintNoAlias, *I1, *I2, F.getParent()); 202 ++NoAlias; break; 203 case AliasAnalysis::MayAlias: 204 PrintResults("MayAlias", PrintMayAlias, *I1, *I2, F.getParent()); 205 ++MayAlias; break; 206 case AliasAnalysis::PartialAlias: 207 PrintResults("PartialAlias", PrintPartialAlias, *I1, *I2, 208 F.getParent()); 209 ++PartialAlias; break; 210 case AliasAnalysis::MustAlias: 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)))) { 225 case AliasAnalysis::NoAlias: 226 PrintLoadStoreResults("NoAlias", PrintNoAlias, *I1, *I2, 227 F.getParent()); 228 ++NoAlias; break; 229 case AliasAnalysis::MayAlias: 230 PrintLoadStoreResults("MayAlias", PrintMayAlias, *I1, *I2, 231 F.getParent()); 232 ++MayAlias; break; 233 case AliasAnalysis::PartialAlias: 234 PrintLoadStoreResults("PartialAlias", PrintPartialAlias, *I1, *I2, 235 F.getParent()); 236 ++PartialAlias; break; 237 case AliasAnalysis::MustAlias: 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)))) { 251 case AliasAnalysis::NoAlias: 252 PrintLoadStoreResults("NoAlias", PrintNoAlias, *I1, *I2, 253 F.getParent()); 254 ++NoAlias; break; 255 case AliasAnalysis::MayAlias: 256 PrintLoadStoreResults("MayAlias", PrintMayAlias, *I1, *I2, 257 F.getParent()); 258 ++MayAlias; break; 259 case AliasAnalysis::PartialAlias: 260 PrintLoadStoreResults("PartialAlias", PrintPartialAlias, *I1, *I2, 261 F.getParent()); 262 ++PartialAlias; break; 263 case AliasAnalysis::MustAlias: 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)) { 284 case AliasAnalysis::NoModRef: 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; 293 case AliasAnalysis::ModRef: 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)) { 307 case AliasAnalysis::NoModRef: 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; 316 case AliasAnalysis::ModRef: 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 } 373