LLVM API Documentation

AliasAnalysisEvaluator.cpp
Go to the documentation of this file.
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 }