1*0b57cec5SDimitry Andric //===- AliasAnalysisEvaluator.cpp - Alias Analysis Accuracy Evaluator -----===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric 9*0b57cec5SDimitry Andric #include "llvm/Analysis/AliasAnalysisEvaluator.h" 10*0b57cec5SDimitry Andric #include "llvm/ADT/SetVector.h" 11*0b57cec5SDimitry Andric #include "llvm/Analysis/AliasAnalysis.h" 12*0b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 13*0b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 14*0b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h" 15*0b57cec5SDimitry Andric #include "llvm/IR/Function.h" 16*0b57cec5SDimitry Andric #include "llvm/IR/InstIterator.h" 17*0b57cec5SDimitry Andric #include "llvm/IR/Instructions.h" 18*0b57cec5SDimitry Andric #include "llvm/IR/Module.h" 19*0b57cec5SDimitry Andric #include "llvm/Pass.h" 20*0b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 21*0b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 22*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 23*0b57cec5SDimitry Andric using namespace llvm; 24*0b57cec5SDimitry Andric 25*0b57cec5SDimitry Andric static cl::opt<bool> PrintAll("print-all-alias-modref-info", cl::ReallyHidden); 26*0b57cec5SDimitry Andric 27*0b57cec5SDimitry Andric static cl::opt<bool> PrintNoAlias("print-no-aliases", cl::ReallyHidden); 28*0b57cec5SDimitry Andric static cl::opt<bool> PrintMayAlias("print-may-aliases", cl::ReallyHidden); 29*0b57cec5SDimitry Andric static cl::opt<bool> PrintPartialAlias("print-partial-aliases", cl::ReallyHidden); 30*0b57cec5SDimitry Andric static cl::opt<bool> PrintMustAlias("print-must-aliases", cl::ReallyHidden); 31*0b57cec5SDimitry Andric 32*0b57cec5SDimitry Andric static cl::opt<bool> PrintNoModRef("print-no-modref", cl::ReallyHidden); 33*0b57cec5SDimitry Andric static cl::opt<bool> PrintRef("print-ref", cl::ReallyHidden); 34*0b57cec5SDimitry Andric static cl::opt<bool> PrintMod("print-mod", cl::ReallyHidden); 35*0b57cec5SDimitry Andric static cl::opt<bool> PrintModRef("print-modref", cl::ReallyHidden); 36*0b57cec5SDimitry Andric static cl::opt<bool> PrintMust("print-must", cl::ReallyHidden); 37*0b57cec5SDimitry Andric static cl::opt<bool> PrintMustRef("print-mustref", cl::ReallyHidden); 38*0b57cec5SDimitry Andric static cl::opt<bool> PrintMustMod("print-mustmod", cl::ReallyHidden); 39*0b57cec5SDimitry Andric static cl::opt<bool> PrintMustModRef("print-mustmodref", cl::ReallyHidden); 40*0b57cec5SDimitry Andric 41*0b57cec5SDimitry Andric static cl::opt<bool> EvalAAMD("evaluate-aa-metadata", cl::ReallyHidden); 42*0b57cec5SDimitry Andric 43*0b57cec5SDimitry Andric static void PrintResults(AliasResult AR, bool P, const Value *V1, 44*0b57cec5SDimitry Andric const Value *V2, const Module *M) { 45*0b57cec5SDimitry Andric if (PrintAll || P) { 46*0b57cec5SDimitry Andric std::string o1, o2; 47*0b57cec5SDimitry Andric { 48*0b57cec5SDimitry Andric raw_string_ostream os1(o1), os2(o2); 49*0b57cec5SDimitry Andric V1->printAsOperand(os1, true, M); 50*0b57cec5SDimitry Andric V2->printAsOperand(os2, true, M); 51*0b57cec5SDimitry Andric } 52*0b57cec5SDimitry Andric 53*0b57cec5SDimitry Andric if (o2 < o1) 54*0b57cec5SDimitry Andric std::swap(o1, o2); 55*0b57cec5SDimitry Andric errs() << " " << AR << ":\t" << o1 << ", " << o2 << "\n"; 56*0b57cec5SDimitry Andric } 57*0b57cec5SDimitry Andric } 58*0b57cec5SDimitry Andric 59*0b57cec5SDimitry Andric static inline void PrintModRefResults(const char *Msg, bool P, Instruction *I, 60*0b57cec5SDimitry Andric Value *Ptr, Module *M) { 61*0b57cec5SDimitry Andric if (PrintAll || P) { 62*0b57cec5SDimitry Andric errs() << " " << Msg << ": Ptr: "; 63*0b57cec5SDimitry Andric Ptr->printAsOperand(errs(), true, M); 64*0b57cec5SDimitry Andric errs() << "\t<->" << *I << '\n'; 65*0b57cec5SDimitry Andric } 66*0b57cec5SDimitry Andric } 67*0b57cec5SDimitry Andric 68*0b57cec5SDimitry Andric static inline void PrintModRefResults(const char *Msg, bool P, CallBase *CallA, 69*0b57cec5SDimitry Andric CallBase *CallB, Module *M) { 70*0b57cec5SDimitry Andric if (PrintAll || P) { 71*0b57cec5SDimitry Andric errs() << " " << Msg << ": " << *CallA << " <-> " << *CallB << '\n'; 72*0b57cec5SDimitry Andric } 73*0b57cec5SDimitry Andric } 74*0b57cec5SDimitry Andric 75*0b57cec5SDimitry Andric static inline void PrintLoadStoreResults(AliasResult AR, bool P, 76*0b57cec5SDimitry Andric const Value *V1, const Value *V2, 77*0b57cec5SDimitry Andric const Module *M) { 78*0b57cec5SDimitry Andric if (PrintAll || P) { 79*0b57cec5SDimitry Andric errs() << " " << AR << ": " << *V1 << " <-> " << *V2 << '\n'; 80*0b57cec5SDimitry Andric } 81*0b57cec5SDimitry Andric } 82*0b57cec5SDimitry Andric 83*0b57cec5SDimitry Andric static inline bool isInterestingPointer(Value *V) { 84*0b57cec5SDimitry Andric return V->getType()->isPointerTy() 85*0b57cec5SDimitry Andric && !isa<ConstantPointerNull>(V); 86*0b57cec5SDimitry Andric } 87*0b57cec5SDimitry Andric 88*0b57cec5SDimitry Andric PreservedAnalyses AAEvaluator::run(Function &F, FunctionAnalysisManager &AM) { 89*0b57cec5SDimitry Andric runInternal(F, AM.getResult<AAManager>(F)); 90*0b57cec5SDimitry Andric return PreservedAnalyses::all(); 91*0b57cec5SDimitry Andric } 92*0b57cec5SDimitry Andric 93*0b57cec5SDimitry Andric void AAEvaluator::runInternal(Function &F, AAResults &AA) { 94*0b57cec5SDimitry Andric const DataLayout &DL = F.getParent()->getDataLayout(); 95*0b57cec5SDimitry Andric 96*0b57cec5SDimitry Andric ++FunctionCount; 97*0b57cec5SDimitry Andric 98*0b57cec5SDimitry Andric SetVector<Value *> Pointers; 99*0b57cec5SDimitry Andric SmallSetVector<CallBase *, 16> Calls; 100*0b57cec5SDimitry Andric SetVector<Value *> Loads; 101*0b57cec5SDimitry Andric SetVector<Value *> Stores; 102*0b57cec5SDimitry Andric 103*0b57cec5SDimitry Andric for (auto &I : F.args()) 104*0b57cec5SDimitry Andric if (I.getType()->isPointerTy()) // Add all pointer arguments. 105*0b57cec5SDimitry Andric Pointers.insert(&I); 106*0b57cec5SDimitry Andric 107*0b57cec5SDimitry Andric for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { 108*0b57cec5SDimitry Andric if (I->getType()->isPointerTy()) // Add all pointer instructions. 109*0b57cec5SDimitry Andric Pointers.insert(&*I); 110*0b57cec5SDimitry Andric if (EvalAAMD && isa<LoadInst>(&*I)) 111*0b57cec5SDimitry Andric Loads.insert(&*I); 112*0b57cec5SDimitry Andric if (EvalAAMD && isa<StoreInst>(&*I)) 113*0b57cec5SDimitry Andric Stores.insert(&*I); 114*0b57cec5SDimitry Andric Instruction &Inst = *I; 115*0b57cec5SDimitry Andric if (auto *Call = dyn_cast<CallBase>(&Inst)) { 116*0b57cec5SDimitry Andric Value *Callee = Call->getCalledValue(); 117*0b57cec5SDimitry Andric // Skip actual functions for direct function calls. 118*0b57cec5SDimitry Andric if (!isa<Function>(Callee) && isInterestingPointer(Callee)) 119*0b57cec5SDimitry Andric Pointers.insert(Callee); 120*0b57cec5SDimitry Andric // Consider formals. 121*0b57cec5SDimitry Andric for (Use &DataOp : Call->data_ops()) 122*0b57cec5SDimitry Andric if (isInterestingPointer(DataOp)) 123*0b57cec5SDimitry Andric Pointers.insert(DataOp); 124*0b57cec5SDimitry Andric Calls.insert(Call); 125*0b57cec5SDimitry Andric } else { 126*0b57cec5SDimitry Andric // Consider all operands. 127*0b57cec5SDimitry Andric for (Instruction::op_iterator OI = Inst.op_begin(), OE = Inst.op_end(); 128*0b57cec5SDimitry Andric OI != OE; ++OI) 129*0b57cec5SDimitry Andric if (isInterestingPointer(*OI)) 130*0b57cec5SDimitry Andric Pointers.insert(*OI); 131*0b57cec5SDimitry Andric } 132*0b57cec5SDimitry Andric } 133*0b57cec5SDimitry Andric 134*0b57cec5SDimitry Andric if (PrintAll || PrintNoAlias || PrintMayAlias || PrintPartialAlias || 135*0b57cec5SDimitry Andric PrintMustAlias || PrintNoModRef || PrintMod || PrintRef || PrintModRef) 136*0b57cec5SDimitry Andric errs() << "Function: " << F.getName() << ": " << Pointers.size() 137*0b57cec5SDimitry Andric << " pointers, " << Calls.size() << " call sites\n"; 138*0b57cec5SDimitry Andric 139*0b57cec5SDimitry Andric // iterate over the worklist, and run the full (n^2)/2 disambiguations 140*0b57cec5SDimitry Andric for (SetVector<Value *>::iterator I1 = Pointers.begin(), E = Pointers.end(); 141*0b57cec5SDimitry Andric I1 != E; ++I1) { 142*0b57cec5SDimitry Andric auto I1Size = LocationSize::unknown(); 143*0b57cec5SDimitry Andric Type *I1ElTy = cast<PointerType>((*I1)->getType())->getElementType(); 144*0b57cec5SDimitry Andric if (I1ElTy->isSized()) 145*0b57cec5SDimitry Andric I1Size = LocationSize::precise(DL.getTypeStoreSize(I1ElTy)); 146*0b57cec5SDimitry Andric 147*0b57cec5SDimitry Andric for (SetVector<Value *>::iterator I2 = Pointers.begin(); I2 != I1; ++I2) { 148*0b57cec5SDimitry Andric auto I2Size = LocationSize::unknown(); 149*0b57cec5SDimitry Andric Type *I2ElTy = cast<PointerType>((*I2)->getType())->getElementType(); 150*0b57cec5SDimitry Andric if (I2ElTy->isSized()) 151*0b57cec5SDimitry Andric I2Size = LocationSize::precise(DL.getTypeStoreSize(I2ElTy)); 152*0b57cec5SDimitry Andric 153*0b57cec5SDimitry Andric AliasResult AR = AA.alias(*I1, I1Size, *I2, I2Size); 154*0b57cec5SDimitry Andric switch (AR) { 155*0b57cec5SDimitry Andric case NoAlias: 156*0b57cec5SDimitry Andric PrintResults(AR, PrintNoAlias, *I1, *I2, F.getParent()); 157*0b57cec5SDimitry Andric ++NoAliasCount; 158*0b57cec5SDimitry Andric break; 159*0b57cec5SDimitry Andric case MayAlias: 160*0b57cec5SDimitry Andric PrintResults(AR, PrintMayAlias, *I1, *I2, F.getParent()); 161*0b57cec5SDimitry Andric ++MayAliasCount; 162*0b57cec5SDimitry Andric break; 163*0b57cec5SDimitry Andric case PartialAlias: 164*0b57cec5SDimitry Andric PrintResults(AR, PrintPartialAlias, *I1, *I2, F.getParent()); 165*0b57cec5SDimitry Andric ++PartialAliasCount; 166*0b57cec5SDimitry Andric break; 167*0b57cec5SDimitry Andric case MustAlias: 168*0b57cec5SDimitry Andric PrintResults(AR, PrintMustAlias, *I1, *I2, F.getParent()); 169*0b57cec5SDimitry Andric ++MustAliasCount; 170*0b57cec5SDimitry Andric break; 171*0b57cec5SDimitry Andric } 172*0b57cec5SDimitry Andric } 173*0b57cec5SDimitry Andric } 174*0b57cec5SDimitry Andric 175*0b57cec5SDimitry Andric if (EvalAAMD) { 176*0b57cec5SDimitry Andric // iterate over all pairs of load, store 177*0b57cec5SDimitry Andric for (Value *Load : Loads) { 178*0b57cec5SDimitry Andric for (Value *Store : Stores) { 179*0b57cec5SDimitry Andric AliasResult AR = AA.alias(MemoryLocation::get(cast<LoadInst>(Load)), 180*0b57cec5SDimitry Andric MemoryLocation::get(cast<StoreInst>(Store))); 181*0b57cec5SDimitry Andric switch (AR) { 182*0b57cec5SDimitry Andric case NoAlias: 183*0b57cec5SDimitry Andric PrintLoadStoreResults(AR, PrintNoAlias, Load, Store, F.getParent()); 184*0b57cec5SDimitry Andric ++NoAliasCount; 185*0b57cec5SDimitry Andric break; 186*0b57cec5SDimitry Andric case MayAlias: 187*0b57cec5SDimitry Andric PrintLoadStoreResults(AR, PrintMayAlias, Load, Store, F.getParent()); 188*0b57cec5SDimitry Andric ++MayAliasCount; 189*0b57cec5SDimitry Andric break; 190*0b57cec5SDimitry Andric case PartialAlias: 191*0b57cec5SDimitry Andric PrintLoadStoreResults(AR, PrintPartialAlias, Load, Store, F.getParent()); 192*0b57cec5SDimitry Andric ++PartialAliasCount; 193*0b57cec5SDimitry Andric break; 194*0b57cec5SDimitry Andric case MustAlias: 195*0b57cec5SDimitry Andric PrintLoadStoreResults(AR, PrintMustAlias, Load, Store, F.getParent()); 196*0b57cec5SDimitry Andric ++MustAliasCount; 197*0b57cec5SDimitry Andric break; 198*0b57cec5SDimitry Andric } 199*0b57cec5SDimitry Andric } 200*0b57cec5SDimitry Andric } 201*0b57cec5SDimitry Andric 202*0b57cec5SDimitry Andric // iterate over all pairs of store, store 203*0b57cec5SDimitry Andric for (SetVector<Value *>::iterator I1 = Stores.begin(), E = Stores.end(); 204*0b57cec5SDimitry Andric I1 != E; ++I1) { 205*0b57cec5SDimitry Andric for (SetVector<Value *>::iterator I2 = Stores.begin(); I2 != I1; ++I2) { 206*0b57cec5SDimitry Andric AliasResult AR = AA.alias(MemoryLocation::get(cast<StoreInst>(*I1)), 207*0b57cec5SDimitry Andric MemoryLocation::get(cast<StoreInst>(*I2))); 208*0b57cec5SDimitry Andric switch (AR) { 209*0b57cec5SDimitry Andric case NoAlias: 210*0b57cec5SDimitry Andric PrintLoadStoreResults(AR, PrintNoAlias, *I1, *I2, F.getParent()); 211*0b57cec5SDimitry Andric ++NoAliasCount; 212*0b57cec5SDimitry Andric break; 213*0b57cec5SDimitry Andric case MayAlias: 214*0b57cec5SDimitry Andric PrintLoadStoreResults(AR, PrintMayAlias, *I1, *I2, F.getParent()); 215*0b57cec5SDimitry Andric ++MayAliasCount; 216*0b57cec5SDimitry Andric break; 217*0b57cec5SDimitry Andric case PartialAlias: 218*0b57cec5SDimitry Andric PrintLoadStoreResults(AR, PrintPartialAlias, *I1, *I2, F.getParent()); 219*0b57cec5SDimitry Andric ++PartialAliasCount; 220*0b57cec5SDimitry Andric break; 221*0b57cec5SDimitry Andric case MustAlias: 222*0b57cec5SDimitry Andric PrintLoadStoreResults(AR, PrintMustAlias, *I1, *I2, F.getParent()); 223*0b57cec5SDimitry Andric ++MustAliasCount; 224*0b57cec5SDimitry Andric break; 225*0b57cec5SDimitry Andric } 226*0b57cec5SDimitry Andric } 227*0b57cec5SDimitry Andric } 228*0b57cec5SDimitry Andric } 229*0b57cec5SDimitry Andric 230*0b57cec5SDimitry Andric // Mod/ref alias analysis: compare all pairs of calls and values 231*0b57cec5SDimitry Andric for (CallBase *Call : Calls) { 232*0b57cec5SDimitry Andric for (auto Pointer : Pointers) { 233*0b57cec5SDimitry Andric auto Size = LocationSize::unknown(); 234*0b57cec5SDimitry Andric Type *ElTy = cast<PointerType>(Pointer->getType())->getElementType(); 235*0b57cec5SDimitry Andric if (ElTy->isSized()) 236*0b57cec5SDimitry Andric Size = LocationSize::precise(DL.getTypeStoreSize(ElTy)); 237*0b57cec5SDimitry Andric 238*0b57cec5SDimitry Andric switch (AA.getModRefInfo(Call, Pointer, Size)) { 239*0b57cec5SDimitry Andric case ModRefInfo::NoModRef: 240*0b57cec5SDimitry Andric PrintModRefResults("NoModRef", PrintNoModRef, Call, Pointer, 241*0b57cec5SDimitry Andric F.getParent()); 242*0b57cec5SDimitry Andric ++NoModRefCount; 243*0b57cec5SDimitry Andric break; 244*0b57cec5SDimitry Andric case ModRefInfo::Mod: 245*0b57cec5SDimitry Andric PrintModRefResults("Just Mod", PrintMod, Call, Pointer, F.getParent()); 246*0b57cec5SDimitry Andric ++ModCount; 247*0b57cec5SDimitry Andric break; 248*0b57cec5SDimitry Andric case ModRefInfo::Ref: 249*0b57cec5SDimitry Andric PrintModRefResults("Just Ref", PrintRef, Call, Pointer, F.getParent()); 250*0b57cec5SDimitry Andric ++RefCount; 251*0b57cec5SDimitry Andric break; 252*0b57cec5SDimitry Andric case ModRefInfo::ModRef: 253*0b57cec5SDimitry Andric PrintModRefResults("Both ModRef", PrintModRef, Call, Pointer, 254*0b57cec5SDimitry Andric F.getParent()); 255*0b57cec5SDimitry Andric ++ModRefCount; 256*0b57cec5SDimitry Andric break; 257*0b57cec5SDimitry Andric case ModRefInfo::Must: 258*0b57cec5SDimitry Andric PrintModRefResults("Must", PrintMust, Call, Pointer, F.getParent()); 259*0b57cec5SDimitry Andric ++MustCount; 260*0b57cec5SDimitry Andric break; 261*0b57cec5SDimitry Andric case ModRefInfo::MustMod: 262*0b57cec5SDimitry Andric PrintModRefResults("Just Mod (MustAlias)", PrintMustMod, Call, Pointer, 263*0b57cec5SDimitry Andric F.getParent()); 264*0b57cec5SDimitry Andric ++MustModCount; 265*0b57cec5SDimitry Andric break; 266*0b57cec5SDimitry Andric case ModRefInfo::MustRef: 267*0b57cec5SDimitry Andric PrintModRefResults("Just Ref (MustAlias)", PrintMustRef, Call, Pointer, 268*0b57cec5SDimitry Andric F.getParent()); 269*0b57cec5SDimitry Andric ++MustRefCount; 270*0b57cec5SDimitry Andric break; 271*0b57cec5SDimitry Andric case ModRefInfo::MustModRef: 272*0b57cec5SDimitry Andric PrintModRefResults("Both ModRef (MustAlias)", PrintMustModRef, Call, 273*0b57cec5SDimitry Andric Pointer, F.getParent()); 274*0b57cec5SDimitry Andric ++MustModRefCount; 275*0b57cec5SDimitry Andric break; 276*0b57cec5SDimitry Andric } 277*0b57cec5SDimitry Andric } 278*0b57cec5SDimitry Andric } 279*0b57cec5SDimitry Andric 280*0b57cec5SDimitry Andric // Mod/ref alias analysis: compare all pairs of calls 281*0b57cec5SDimitry Andric for (CallBase *CallA : Calls) { 282*0b57cec5SDimitry Andric for (CallBase *CallB : Calls) { 283*0b57cec5SDimitry Andric if (CallA == CallB) 284*0b57cec5SDimitry Andric continue; 285*0b57cec5SDimitry Andric switch (AA.getModRefInfo(CallA, CallB)) { 286*0b57cec5SDimitry Andric case ModRefInfo::NoModRef: 287*0b57cec5SDimitry Andric PrintModRefResults("NoModRef", PrintNoModRef, CallA, CallB, 288*0b57cec5SDimitry Andric F.getParent()); 289*0b57cec5SDimitry Andric ++NoModRefCount; 290*0b57cec5SDimitry Andric break; 291*0b57cec5SDimitry Andric case ModRefInfo::Mod: 292*0b57cec5SDimitry Andric PrintModRefResults("Just Mod", PrintMod, CallA, CallB, F.getParent()); 293*0b57cec5SDimitry Andric ++ModCount; 294*0b57cec5SDimitry Andric break; 295*0b57cec5SDimitry Andric case ModRefInfo::Ref: 296*0b57cec5SDimitry Andric PrintModRefResults("Just Ref", PrintRef, CallA, CallB, F.getParent()); 297*0b57cec5SDimitry Andric ++RefCount; 298*0b57cec5SDimitry Andric break; 299*0b57cec5SDimitry Andric case ModRefInfo::ModRef: 300*0b57cec5SDimitry Andric PrintModRefResults("Both ModRef", PrintModRef, CallA, CallB, 301*0b57cec5SDimitry Andric F.getParent()); 302*0b57cec5SDimitry Andric ++ModRefCount; 303*0b57cec5SDimitry Andric break; 304*0b57cec5SDimitry Andric case ModRefInfo::Must: 305*0b57cec5SDimitry Andric PrintModRefResults("Must", PrintMust, CallA, CallB, F.getParent()); 306*0b57cec5SDimitry Andric ++MustCount; 307*0b57cec5SDimitry Andric break; 308*0b57cec5SDimitry Andric case ModRefInfo::MustMod: 309*0b57cec5SDimitry Andric PrintModRefResults("Just Mod (MustAlias)", PrintMustMod, CallA, CallB, 310*0b57cec5SDimitry Andric F.getParent()); 311*0b57cec5SDimitry Andric ++MustModCount; 312*0b57cec5SDimitry Andric break; 313*0b57cec5SDimitry Andric case ModRefInfo::MustRef: 314*0b57cec5SDimitry Andric PrintModRefResults("Just Ref (MustAlias)", PrintMustRef, CallA, CallB, 315*0b57cec5SDimitry Andric F.getParent()); 316*0b57cec5SDimitry Andric ++MustRefCount; 317*0b57cec5SDimitry Andric break; 318*0b57cec5SDimitry Andric case ModRefInfo::MustModRef: 319*0b57cec5SDimitry Andric PrintModRefResults("Both ModRef (MustAlias)", PrintMustModRef, CallA, 320*0b57cec5SDimitry Andric CallB, F.getParent()); 321*0b57cec5SDimitry Andric ++MustModRefCount; 322*0b57cec5SDimitry Andric break; 323*0b57cec5SDimitry Andric } 324*0b57cec5SDimitry Andric } 325*0b57cec5SDimitry Andric } 326*0b57cec5SDimitry Andric } 327*0b57cec5SDimitry Andric 328*0b57cec5SDimitry Andric static void PrintPercent(int64_t Num, int64_t Sum) { 329*0b57cec5SDimitry Andric errs() << "(" << Num * 100LL / Sum << "." << ((Num * 1000LL / Sum) % 10) 330*0b57cec5SDimitry Andric << "%)\n"; 331*0b57cec5SDimitry Andric } 332*0b57cec5SDimitry Andric 333*0b57cec5SDimitry Andric AAEvaluator::~AAEvaluator() { 334*0b57cec5SDimitry Andric if (FunctionCount == 0) 335*0b57cec5SDimitry Andric return; 336*0b57cec5SDimitry Andric 337*0b57cec5SDimitry Andric int64_t AliasSum = 338*0b57cec5SDimitry Andric NoAliasCount + MayAliasCount + PartialAliasCount + MustAliasCount; 339*0b57cec5SDimitry Andric errs() << "===== Alias Analysis Evaluator Report =====\n"; 340*0b57cec5SDimitry Andric if (AliasSum == 0) { 341*0b57cec5SDimitry Andric errs() << " Alias Analysis Evaluator Summary: No pointers!\n"; 342*0b57cec5SDimitry Andric } else { 343*0b57cec5SDimitry Andric errs() << " " << AliasSum << " Total Alias Queries Performed\n"; 344*0b57cec5SDimitry Andric errs() << " " << NoAliasCount << " no alias responses "; 345*0b57cec5SDimitry Andric PrintPercent(NoAliasCount, AliasSum); 346*0b57cec5SDimitry Andric errs() << " " << MayAliasCount << " may alias responses "; 347*0b57cec5SDimitry Andric PrintPercent(MayAliasCount, AliasSum); 348*0b57cec5SDimitry Andric errs() << " " << PartialAliasCount << " partial alias responses "; 349*0b57cec5SDimitry Andric PrintPercent(PartialAliasCount, AliasSum); 350*0b57cec5SDimitry Andric errs() << " " << MustAliasCount << " must alias responses "; 351*0b57cec5SDimitry Andric PrintPercent(MustAliasCount, AliasSum); 352*0b57cec5SDimitry Andric errs() << " Alias Analysis Evaluator Pointer Alias Summary: " 353*0b57cec5SDimitry Andric << NoAliasCount * 100 / AliasSum << "%/" 354*0b57cec5SDimitry Andric << MayAliasCount * 100 / AliasSum << "%/" 355*0b57cec5SDimitry Andric << PartialAliasCount * 100 / AliasSum << "%/" 356*0b57cec5SDimitry Andric << MustAliasCount * 100 / AliasSum << "%\n"; 357*0b57cec5SDimitry Andric } 358*0b57cec5SDimitry Andric 359*0b57cec5SDimitry Andric // Display the summary for mod/ref analysis 360*0b57cec5SDimitry Andric int64_t ModRefSum = NoModRefCount + RefCount + ModCount + ModRefCount + 361*0b57cec5SDimitry Andric MustCount + MustRefCount + MustModCount + MustModRefCount; 362*0b57cec5SDimitry Andric if (ModRefSum == 0) { 363*0b57cec5SDimitry Andric errs() << " Alias Analysis Mod/Ref Evaluator Summary: no " 364*0b57cec5SDimitry Andric "mod/ref!\n"; 365*0b57cec5SDimitry Andric } else { 366*0b57cec5SDimitry Andric errs() << " " << ModRefSum << " Total ModRef Queries Performed\n"; 367*0b57cec5SDimitry Andric errs() << " " << NoModRefCount << " no mod/ref responses "; 368*0b57cec5SDimitry Andric PrintPercent(NoModRefCount, ModRefSum); 369*0b57cec5SDimitry Andric errs() << " " << ModCount << " mod responses "; 370*0b57cec5SDimitry Andric PrintPercent(ModCount, ModRefSum); 371*0b57cec5SDimitry Andric errs() << " " << RefCount << " ref responses "; 372*0b57cec5SDimitry Andric PrintPercent(RefCount, ModRefSum); 373*0b57cec5SDimitry Andric errs() << " " << ModRefCount << " mod & ref responses "; 374*0b57cec5SDimitry Andric PrintPercent(ModRefCount, ModRefSum); 375*0b57cec5SDimitry Andric errs() << " " << MustCount << " must responses "; 376*0b57cec5SDimitry Andric PrintPercent(MustCount, ModRefSum); 377*0b57cec5SDimitry Andric errs() << " " << MustModCount << " must mod responses "; 378*0b57cec5SDimitry Andric PrintPercent(MustModCount, ModRefSum); 379*0b57cec5SDimitry Andric errs() << " " << MustRefCount << " must ref responses "; 380*0b57cec5SDimitry Andric PrintPercent(MustRefCount, ModRefSum); 381*0b57cec5SDimitry Andric errs() << " " << MustModRefCount << " must mod & ref responses "; 382*0b57cec5SDimitry Andric PrintPercent(MustModRefCount, ModRefSum); 383*0b57cec5SDimitry Andric errs() << " Alias Analysis Evaluator Mod/Ref Summary: " 384*0b57cec5SDimitry Andric << NoModRefCount * 100 / ModRefSum << "%/" 385*0b57cec5SDimitry Andric << ModCount * 100 / ModRefSum << "%/" << RefCount * 100 / ModRefSum 386*0b57cec5SDimitry Andric << "%/" << ModRefCount * 100 / ModRefSum << "%/" 387*0b57cec5SDimitry Andric << MustCount * 100 / ModRefSum << "%/" 388*0b57cec5SDimitry Andric << MustRefCount * 100 / ModRefSum << "%/" 389*0b57cec5SDimitry Andric << MustModCount * 100 / ModRefSum << "%/" 390*0b57cec5SDimitry Andric << MustModRefCount * 100 / ModRefSum << "%\n"; 391*0b57cec5SDimitry Andric } 392*0b57cec5SDimitry Andric } 393*0b57cec5SDimitry Andric 394*0b57cec5SDimitry Andric namespace llvm { 395*0b57cec5SDimitry Andric class AAEvalLegacyPass : public FunctionPass { 396*0b57cec5SDimitry Andric std::unique_ptr<AAEvaluator> P; 397*0b57cec5SDimitry Andric 398*0b57cec5SDimitry Andric public: 399*0b57cec5SDimitry Andric static char ID; // Pass identification, replacement for typeid 400*0b57cec5SDimitry Andric AAEvalLegacyPass() : FunctionPass(ID) { 401*0b57cec5SDimitry Andric initializeAAEvalLegacyPassPass(*PassRegistry::getPassRegistry()); 402*0b57cec5SDimitry Andric } 403*0b57cec5SDimitry Andric 404*0b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 405*0b57cec5SDimitry Andric AU.addRequired<AAResultsWrapperPass>(); 406*0b57cec5SDimitry Andric AU.setPreservesAll(); 407*0b57cec5SDimitry Andric } 408*0b57cec5SDimitry Andric 409*0b57cec5SDimitry Andric bool doInitialization(Module &M) override { 410*0b57cec5SDimitry Andric P.reset(new AAEvaluator()); 411*0b57cec5SDimitry Andric return false; 412*0b57cec5SDimitry Andric } 413*0b57cec5SDimitry Andric 414*0b57cec5SDimitry Andric bool runOnFunction(Function &F) override { 415*0b57cec5SDimitry Andric P->runInternal(F, getAnalysis<AAResultsWrapperPass>().getAAResults()); 416*0b57cec5SDimitry Andric return false; 417*0b57cec5SDimitry Andric } 418*0b57cec5SDimitry Andric bool doFinalization(Module &M) override { 419*0b57cec5SDimitry Andric P.reset(); 420*0b57cec5SDimitry Andric return false; 421*0b57cec5SDimitry Andric } 422*0b57cec5SDimitry Andric }; 423*0b57cec5SDimitry Andric } 424*0b57cec5SDimitry Andric 425*0b57cec5SDimitry Andric char AAEvalLegacyPass::ID = 0; 426*0b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(AAEvalLegacyPass, "aa-eval", 427*0b57cec5SDimitry Andric "Exhaustive Alias Analysis Precision Evaluator", false, 428*0b57cec5SDimitry Andric true) 429*0b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) 430*0b57cec5SDimitry Andric INITIALIZE_PASS_END(AAEvalLegacyPass, "aa-eval", 431*0b57cec5SDimitry Andric "Exhaustive Alias Analysis Precision Evaluator", false, 432*0b57cec5SDimitry Andric true) 433*0b57cec5SDimitry Andric 434*0b57cec5SDimitry Andric FunctionPass *llvm::createAAEvalPass() { return new AAEvalLegacyPass(); } 435