1274955Ssvnmir//===- AliasAnalysisEvaluator.cpp - Alias Analysis Accuracy Evaluator -----===// 2274955Ssvnmir// 3274955Ssvnmir// The LLVM Compiler Infrastructure 4274955Ssvnmir// 5274955Ssvnmir// This file is distributed under the University of Illinois Open Source 6274955Ssvnmir// License. See LICENSE.TXT for details. 7274955Ssvnmir// 8274955Ssvnmir//===----------------------------------------------------------------------===// 9274955Ssvnmir// 10280031Sdim// This file implements a simple N^2 alias analysis accuracy evaluator. 11280031Sdim// Basically, for each function in the program, it simply queries to see how the 12274955Ssvnmir// alias analysis implementation answers alias queries between each pair of 13274955Ssvnmir// pointers in the function. 14274955Ssvnmir// 15274955Ssvnmir// This is inspired and adapted from code by: Naveen Neelakantam, Francesco 16274955Ssvnmir// Spadini, and Wojciech Stryjewski. 17274955Ssvnmir// 18274955Ssvnmir//===----------------------------------------------------------------------===// 19274955Ssvnmir 20274955Ssvnmir#include "llvm/Analysis/Passes.h" 21274955Ssvnmir#include "llvm/ADT/SetVector.h" 22280031Sdim#include "llvm/Analysis/AliasAnalysis.h" 23280031Sdim#include "llvm/Assembly/Writer.h" 24280031Sdim#include "llvm/IR/Constants.h" 25288943Sdim#include "llvm/IR/DerivedTypes.h" 26288943Sdim#include "llvm/IR/Function.h" 27288943Sdim#include "llvm/IR/Instructions.h" 28274955Ssvnmir#include "llvm/Pass.h" 29274955Ssvnmir#include "llvm/Support/CommandLine.h" 30274955Ssvnmir#include "llvm/Support/Debug.h" 31274955Ssvnmir#include "llvm/Support/InstIterator.h" 32274955Ssvnmir#include "llvm/Support/raw_ostream.h" 33274955Ssvnmirusing namespace llvm; 34274955Ssvnmir 35280031Sdimstatic cl::opt<bool> PrintAll("print-all-alias-modref-info", cl::ReallyHidden); 36280031Sdim 37280031Sdimstatic cl::opt<bool> PrintNoAlias("print-no-aliases", cl::ReallyHidden); 38274955Ssvnmirstatic cl::opt<bool> PrintMayAlias("print-may-aliases", cl::ReallyHidden); 39280031Sdimstatic cl::opt<bool> PrintPartialAlias("print-partial-aliases", cl::ReallyHidden); 40274955Ssvnmirstatic cl::opt<bool> PrintMustAlias("print-must-aliases", cl::ReallyHidden); 41274955Ssvnmir 42274955Ssvnmirstatic cl::opt<bool> PrintNoModRef("print-no-modref", cl::ReallyHidden); 43274955Ssvnmirstatic cl::opt<bool> PrintMod("print-mod", cl::ReallyHidden); 44274955Ssvnmirstatic cl::opt<bool> PrintRef("print-ref", cl::ReallyHidden); 45274955Ssvnmirstatic cl::opt<bool> PrintModRef("print-modref", cl::ReallyHidden); 46274955Ssvnmir 47280031Sdimstatic cl::opt<bool> EvalTBAA("evaluate-tbaa", cl::ReallyHidden); 48274955Ssvnmir 49280031Sdimnamespace { 50296417Sdim class AAEval : public FunctionPass { 51274955Ssvnmir unsigned NoAlias, MayAlias, PartialAlias, MustAlias; 52274955Ssvnmir unsigned NoModRef, Mod, Ref, ModRef; 53274955Ssvnmir 54280031Sdim public: 55280031Sdim static char ID; // Pass identification, replacement for typeid 56274955Ssvnmir AAEval() : FunctionPass(ID) { 57280031Sdim initializeAAEvalPass(*PassRegistry::getPassRegistry()); 58274955Ssvnmir } 59274955Ssvnmir 60274955Ssvnmir virtual void getAnalysisUsage(AnalysisUsage &AU) const { 61274955Ssvnmir AU.addRequired<AliasAnalysis>(); 62274955Ssvnmir AU.setPreservesAll(); 63274955Ssvnmir } 64274955Ssvnmir 65274955Ssvnmir bool doInitialization(Module &M) { 66274955Ssvnmir NoAlias = MayAlias = PartialAlias = MustAlias = 0; 67274955Ssvnmir NoModRef = Mod = Ref = ModRef = 0; 68274955Ssvnmir 69274955Ssvnmir if (PrintAll) { 70288943Sdim PrintNoAlias = PrintMayAlias = true; 71274955Ssvnmir PrintPartialAlias = PrintMustAlias = true; 72280031Sdim PrintNoModRef = PrintMod = PrintRef = PrintModRef = true; 73274955Ssvnmir } 74274955Ssvnmir return false; 75274955Ssvnmir } 76274955Ssvnmir 77274955Ssvnmir bool runOnFunction(Function &F); 78274955Ssvnmir bool doFinalization(Module &M); 79274955Ssvnmir }; 80274955Ssvnmir} 81274955Ssvnmir 82280031Sdimchar AAEval::ID = 0; 83274955SsvnmirINITIALIZE_PASS_BEGIN(AAEval, "aa-eval", 84274955Ssvnmir "Exhaustive Alias Analysis Precision Evaluator", false, true) 85274955SsvnmirINITIALIZE_AG_DEPENDENCY(AliasAnalysis) 86296417SdimINITIALIZE_PASS_END(AAEval, "aa-eval", 87274955Ssvnmir "Exhaustive Alias Analysis Precision Evaluator", false, true) 88274955Ssvnmir 89296417SdimFunctionPass *llvm::createAAEvalPass() { return new AAEval(); } 90274955Ssvnmir 91274955Ssvnmirstatic void PrintResults(const char *Msg, bool P, const Value *V1, 92274955Ssvnmir const Value *V2, const Module *M) { 93274955Ssvnmir if (P) { 94274955Ssvnmir std::string o1, o2; 95274955Ssvnmir { 96274955Ssvnmir raw_string_ostream os1(o1), os2(o2); 97280031Sdim WriteAsOperand(os1, V1, true, M); 98274955Ssvnmir WriteAsOperand(os2, V2, true, M); 99274955Ssvnmir } 100274955Ssvnmir 101296417Sdim if (o2 < o1) 102296417Sdim std::swap(o1, o2); 103274955Ssvnmir errs() << " " << Msg << ":\t" 104274955Ssvnmir << o1 << ", " 105274955Ssvnmir << o2 << "\n"; 106280031Sdim } 107274955Ssvnmir} 108274955Ssvnmir 109274955Ssvnmirstatic inline void 110274955SsvnmirPrintModRefResults(const char *Msg, bool P, Instruction *I, Value *Ptr, 111274955Ssvnmir Module *M) { 112274955Ssvnmir if (P) { 113274955Ssvnmir errs() << " " << Msg << ": Ptr: "; 114280031Sdim WriteAsOperand(errs(), Ptr, true, M); 115274955Ssvnmir errs() << "\t<->" << *I << '\n'; 116274955Ssvnmir } 117274955Ssvnmir} 118274955Ssvnmir 119274955Ssvnmirstatic inline void 120280031SdimPrintModRefResults(const char *Msg, bool P, CallSite CSA, CallSite CSB, 121274955Ssvnmir Module *M) { 122280031Sdim if (P) { 123280031Sdim errs() << " " << Msg << ": " << *CSA.getInstruction() 124274955Ssvnmir << " <-> " << *CSB.getInstruction() << '\n'; 125274955Ssvnmir } 126274955Ssvnmir} 127274955Ssvnmir 128274955Ssvnmirstatic inline void 129280031SdimPrintLoadStoreResults(const char *Msg, bool P, const Value *V1, 130274955Ssvnmir const Value *V2, const Module *M) { 131280031Sdim if (P) { 132280031Sdim errs() << " " << Msg << ": " << *V1 133274955Ssvnmir << " <-> " << *V2 << '\n'; 134280031Sdim } 135274955Ssvnmir} 136274955Ssvnmir 137280031Sdimstatic inline bool isInterestingPointer(Value *V) { 138280031Sdim return V->getType()->isPointerTy() 139280031Sdim && !isa<ConstantPointerNull>(V); 140288943Sdim} 141296417Sdim 142274955Ssvnmirbool AAEval::runOnFunction(Function &F) { 143280031Sdim AliasAnalysis &AA = getAnalysis<AliasAnalysis>(); 144274955Ssvnmir 145274955Ssvnmir SetVector<Value *> Pointers; 146274955Ssvnmir SetVector<CallSite> CallSites; 147280031Sdim SetVector<Value *> Loads; 148274955Ssvnmir SetVector<Value *> Stores; 149280031Sdim 150280031Sdim for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) 151280031Sdim if (I->getType()->isPointerTy()) // Add all pointer arguments. 152280031Sdim Pointers.insert(I); 153274955Ssvnmir 154274955Ssvnmir for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { 155280031Sdim if (I->getType()->isPointerTy()) // Add all pointer instructions. 156274955Ssvnmir Pointers.insert(&*I); 157274955Ssvnmir if (EvalTBAA && isa<LoadInst>(&*I)) 158274955Ssvnmir Loads.insert(&*I); 159280031Sdim if (EvalTBAA && isa<StoreInst>(&*I)) 160280031Sdim Stores.insert(&*I); 161280031Sdim Instruction &Inst = *I; 162280031Sdim if (CallSite CS = cast<Value>(&Inst)) { 163274955Ssvnmir Value *Callee = CS.getCalledValue(); 164274955Ssvnmir // Skip actual functions for direct function calls. 165274955Ssvnmir if (!isa<Function>(Callee) && isInterestingPointer(Callee)) 166274955Ssvnmir Pointers.insert(Callee); 167274955Ssvnmir // Consider formals. 168288943Sdim for (CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end(); 169288943Sdim AI != AE; ++AI) 170274955Ssvnmir if (isInterestingPointer(*AI)) 171274955Ssvnmir Pointers.insert(*AI); 172274955Ssvnmir CallSites.insert(CS); 173274955Ssvnmir } else { 174274955Ssvnmir // Consider all operands. 175274955Ssvnmir for (Instruction::op_iterator OI = Inst.op_begin(), OE = Inst.op_end(); 176288943Sdim OI != OE; ++OI) 177288943Sdim if (isInterestingPointer(*OI)) 178288943Sdim Pointers.insert(*OI); 179274955Ssvnmir } 180274955Ssvnmir } 181274955Ssvnmir 182274955Ssvnmir if (PrintNoAlias || PrintMayAlias || PrintPartialAlias || PrintMustAlias || 183274955Ssvnmir PrintNoModRef || PrintMod || PrintRef || PrintModRef) 184274955Ssvnmir errs() << "Function: " << F.getName() << ": " << Pointers.size() 185274955Ssvnmir << " pointers, " << CallSites.size() << " call sites\n"; 186280031Sdim 187274955Ssvnmir // iterate over the worklist, and run the full (n^2)/2 disambiguations 188274955Ssvnmir for (SetVector<Value *>::iterator I1 = Pointers.begin(), E = Pointers.end(); 189274955Ssvnmir I1 != E; ++I1) { 190274955Ssvnmir uint64_t I1Size = AliasAnalysis::UnknownSize; 191274955Ssvnmir Type *I1ElTy = cast<PointerType>((*I1)->getType())->getElementType(); 192274955Ssvnmir if (I1ElTy->isSized()) I1Size = AA.getTypeStoreSize(I1ElTy); 193274955Ssvnmir 194274955Ssvnmir for (SetVector<Value *>::iterator I2 = Pointers.begin(); I2 != I1; ++I2) { 195274955Ssvnmir uint64_t I2Size = AliasAnalysis::UnknownSize; 196274955Ssvnmir Type *I2ElTy =cast<PointerType>((*I2)->getType())->getElementType(); 197274955Ssvnmir if (I2ElTy->isSized()) I2Size = AA.getTypeStoreSize(I2ElTy); 198274955Ssvnmir 199274955Ssvnmir switch (AA.alias(*I1, I1Size, *I2, I2Size)) { 200274955Ssvnmir case AliasAnalysis::NoAlias: 201274955Ssvnmir PrintResults("NoAlias", PrintNoAlias, *I1, *I2, F.getParent()); 202274955Ssvnmir ++NoAlias; break; 203274955Ssvnmir case AliasAnalysis::MayAlias: 204274955Ssvnmir PrintResults("MayAlias", PrintMayAlias, *I1, *I2, F.getParent()); 205274955Ssvnmir ++MayAlias; break; 206274955Ssvnmir case AliasAnalysis::PartialAlias: 207288943Sdim PrintResults("PartialAlias", PrintPartialAlias, *I1, *I2, 208288943Sdim F.getParent()); 209288943Sdim ++PartialAlias; break; 210274955Ssvnmir case AliasAnalysis::MustAlias: 211274955Ssvnmir PrintResults("MustAlias", PrintMustAlias, *I1, *I2, F.getParent()); 212274955Ssvnmir ++MustAlias; break; 213274955Ssvnmir } 214288943Sdim } 215274955Ssvnmir } 216274955Ssvnmir 217274955Ssvnmir if (EvalTBAA) { 218274955Ssvnmir // iterate over all pairs of load, store 219274955Ssvnmir for (SetVector<Value *>::iterator I1 = Loads.begin(), E = Loads.end(); 220274955Ssvnmir I1 != E; ++I1) { 221274955Ssvnmir for (SetVector<Value *>::iterator I2 = Stores.begin(), E2 = Stores.end(); 222274955Ssvnmir I2 != E2; ++I2) { 223274955Ssvnmir switch (AA.alias(AA.getLocation(cast<LoadInst>(*I1)), 224280031Sdim 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 326static void PrintPercent(unsigned Num, unsigned Sum) { 327 errs() << "(" << Num*100ULL/Sum << "." 328 << ((Num*1000ULL/Sum) % 10) << "%)\n"; 329} 330 331bool 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