10b57cec5SDimitry Andric //===- AliasAnalysisEvaluator.cpp - Alias Analysis Accuracy Evaluator -----===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "llvm/Analysis/AliasAnalysisEvaluator.h" 100b57cec5SDimitry Andric #include "llvm/ADT/SetVector.h" 110b57cec5SDimitry Andric #include "llvm/Analysis/AliasAnalysis.h" 120b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 130b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 140b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h" 150b57cec5SDimitry Andric #include "llvm/IR/Function.h" 160b57cec5SDimitry Andric #include "llvm/IR/InstIterator.h" 170b57cec5SDimitry Andric #include "llvm/IR/Instructions.h" 180b57cec5SDimitry Andric #include "llvm/IR/Module.h" 19480093f4SDimitry Andric #include "llvm/InitializePasses.h" 200b57cec5SDimitry Andric #include "llvm/Pass.h" 210b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 220b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 230b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 240b57cec5SDimitry Andric using namespace llvm; 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric static cl::opt<bool> PrintAll("print-all-alias-modref-info", cl::ReallyHidden); 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric static cl::opt<bool> PrintNoAlias("print-no-aliases", cl::ReallyHidden); 290b57cec5SDimitry Andric static cl::opt<bool> PrintMayAlias("print-may-aliases", cl::ReallyHidden); 300b57cec5SDimitry Andric static cl::opt<bool> PrintPartialAlias("print-partial-aliases", cl::ReallyHidden); 310b57cec5SDimitry Andric static cl::opt<bool> PrintMustAlias("print-must-aliases", cl::ReallyHidden); 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric static cl::opt<bool> PrintNoModRef("print-no-modref", cl::ReallyHidden); 340b57cec5SDimitry Andric static cl::opt<bool> PrintRef("print-ref", cl::ReallyHidden); 350b57cec5SDimitry Andric static cl::opt<bool> PrintMod("print-mod", cl::ReallyHidden); 360b57cec5SDimitry Andric static cl::opt<bool> PrintModRef("print-modref", cl::ReallyHidden); 370b57cec5SDimitry Andric static cl::opt<bool> PrintMust("print-must", cl::ReallyHidden); 380b57cec5SDimitry Andric static cl::opt<bool> PrintMustRef("print-mustref", cl::ReallyHidden); 390b57cec5SDimitry Andric static cl::opt<bool> PrintMustMod("print-mustmod", cl::ReallyHidden); 400b57cec5SDimitry Andric static cl::opt<bool> PrintMustModRef("print-mustmodref", cl::ReallyHidden); 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric static cl::opt<bool> EvalAAMD("evaluate-aa-metadata", cl::ReallyHidden); 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric static void PrintResults(AliasResult AR, bool P, const Value *V1, 450b57cec5SDimitry Andric const Value *V2, const Module *M) { 460b57cec5SDimitry Andric if (PrintAll || P) { 470b57cec5SDimitry Andric std::string o1, o2; 480b57cec5SDimitry Andric { 490b57cec5SDimitry Andric raw_string_ostream os1(o1), os2(o2); 500b57cec5SDimitry Andric V1->printAsOperand(os1, true, M); 510b57cec5SDimitry Andric V2->printAsOperand(os2, true, M); 520b57cec5SDimitry Andric } 530b57cec5SDimitry Andric 54*fe6060f1SDimitry Andric if (o2 < o1) { 550b57cec5SDimitry Andric std::swap(o1, o2); 56*fe6060f1SDimitry Andric // Change offset sign for the local AR, for printing only. 57*fe6060f1SDimitry Andric AR.swap(); 58*fe6060f1SDimitry Andric } 590b57cec5SDimitry Andric errs() << " " << AR << ":\t" << o1 << ", " << o2 << "\n"; 600b57cec5SDimitry Andric } 610b57cec5SDimitry Andric } 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric static inline void PrintModRefResults(const char *Msg, bool P, Instruction *I, 640b57cec5SDimitry Andric Value *Ptr, Module *M) { 650b57cec5SDimitry Andric if (PrintAll || P) { 660b57cec5SDimitry Andric errs() << " " << Msg << ": Ptr: "; 670b57cec5SDimitry Andric Ptr->printAsOperand(errs(), true, M); 680b57cec5SDimitry Andric errs() << "\t<->" << *I << '\n'; 690b57cec5SDimitry Andric } 700b57cec5SDimitry Andric } 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric static inline void PrintModRefResults(const char *Msg, bool P, CallBase *CallA, 730b57cec5SDimitry Andric CallBase *CallB, Module *M) { 740b57cec5SDimitry Andric if (PrintAll || P) { 750b57cec5SDimitry Andric errs() << " " << Msg << ": " << *CallA << " <-> " << *CallB << '\n'; 760b57cec5SDimitry Andric } 770b57cec5SDimitry Andric } 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric static inline void PrintLoadStoreResults(AliasResult AR, bool P, 800b57cec5SDimitry Andric const Value *V1, const Value *V2, 810b57cec5SDimitry Andric const Module *M) { 820b57cec5SDimitry Andric if (PrintAll || P) { 830b57cec5SDimitry Andric errs() << " " << AR << ": " << *V1 << " <-> " << *V2 << '\n'; 840b57cec5SDimitry Andric } 850b57cec5SDimitry Andric } 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric static inline bool isInterestingPointer(Value *V) { 880b57cec5SDimitry Andric return V->getType()->isPointerTy() 890b57cec5SDimitry Andric && !isa<ConstantPointerNull>(V); 900b57cec5SDimitry Andric } 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric PreservedAnalyses AAEvaluator::run(Function &F, FunctionAnalysisManager &AM) { 930b57cec5SDimitry Andric runInternal(F, AM.getResult<AAManager>(F)); 940b57cec5SDimitry Andric return PreservedAnalyses::all(); 950b57cec5SDimitry Andric } 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric void AAEvaluator::runInternal(Function &F, AAResults &AA) { 980b57cec5SDimitry Andric const DataLayout &DL = F.getParent()->getDataLayout(); 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric ++FunctionCount; 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric SetVector<Value *> Pointers; 1030b57cec5SDimitry Andric SmallSetVector<CallBase *, 16> Calls; 1040b57cec5SDimitry Andric SetVector<Value *> Loads; 1050b57cec5SDimitry Andric SetVector<Value *> Stores; 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric for (auto &I : F.args()) 1080b57cec5SDimitry Andric if (I.getType()->isPointerTy()) // Add all pointer arguments. 1090b57cec5SDimitry Andric Pointers.insert(&I); 1100b57cec5SDimitry Andric 111*fe6060f1SDimitry Andric for (Instruction &Inst : instructions(F)) { 112*fe6060f1SDimitry Andric if (Inst.getType()->isPointerTy()) // Add all pointer instructions. 113*fe6060f1SDimitry Andric Pointers.insert(&Inst); 114*fe6060f1SDimitry Andric if (EvalAAMD && isa<LoadInst>(&Inst)) 115*fe6060f1SDimitry Andric Loads.insert(&Inst); 116*fe6060f1SDimitry Andric if (EvalAAMD && isa<StoreInst>(&Inst)) 117*fe6060f1SDimitry Andric Stores.insert(&Inst); 1180b57cec5SDimitry Andric if (auto *Call = dyn_cast<CallBase>(&Inst)) { 1195ffd83dbSDimitry Andric Value *Callee = Call->getCalledOperand(); 1200b57cec5SDimitry Andric // Skip actual functions for direct function calls. 1210b57cec5SDimitry Andric if (!isa<Function>(Callee) && isInterestingPointer(Callee)) 1220b57cec5SDimitry Andric Pointers.insert(Callee); 1230b57cec5SDimitry Andric // Consider formals. 1240b57cec5SDimitry Andric for (Use &DataOp : Call->data_ops()) 1250b57cec5SDimitry Andric if (isInterestingPointer(DataOp)) 1260b57cec5SDimitry Andric Pointers.insert(DataOp); 1270b57cec5SDimitry Andric Calls.insert(Call); 1280b57cec5SDimitry Andric } else { 1290b57cec5SDimitry Andric // Consider all operands. 130*fe6060f1SDimitry Andric for (Use &Op : Inst.operands()) 131*fe6060f1SDimitry Andric if (isInterestingPointer(Op)) 132*fe6060f1SDimitry Andric Pointers.insert(Op); 1330b57cec5SDimitry Andric } 1340b57cec5SDimitry Andric } 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric if (PrintAll || PrintNoAlias || PrintMayAlias || PrintPartialAlias || 1370b57cec5SDimitry Andric PrintMustAlias || PrintNoModRef || PrintMod || PrintRef || PrintModRef) 1380b57cec5SDimitry Andric errs() << "Function: " << F.getName() << ": " << Pointers.size() 1390b57cec5SDimitry Andric << " pointers, " << Calls.size() << " call sites\n"; 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric // iterate over the worklist, and run the full (n^2)/2 disambiguations 1420b57cec5SDimitry Andric for (SetVector<Value *>::iterator I1 = Pointers.begin(), E = Pointers.end(); 1430b57cec5SDimitry Andric I1 != E; ++I1) { 144e8d8bef9SDimitry Andric auto I1Size = LocationSize::afterPointer(); 1450b57cec5SDimitry Andric Type *I1ElTy = cast<PointerType>((*I1)->getType())->getElementType(); 1460b57cec5SDimitry Andric if (I1ElTy->isSized()) 1470b57cec5SDimitry Andric I1Size = LocationSize::precise(DL.getTypeStoreSize(I1ElTy)); 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric for (SetVector<Value *>::iterator I2 = Pointers.begin(); I2 != I1; ++I2) { 150e8d8bef9SDimitry Andric auto I2Size = LocationSize::afterPointer(); 1510b57cec5SDimitry Andric Type *I2ElTy = cast<PointerType>((*I2)->getType())->getElementType(); 1520b57cec5SDimitry Andric if (I2ElTy->isSized()) 1530b57cec5SDimitry Andric I2Size = LocationSize::precise(DL.getTypeStoreSize(I2ElTy)); 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric AliasResult AR = AA.alias(*I1, I1Size, *I2, I2Size); 1560b57cec5SDimitry Andric switch (AR) { 157*fe6060f1SDimitry Andric case AliasResult::NoAlias: 1580b57cec5SDimitry Andric PrintResults(AR, PrintNoAlias, *I1, *I2, F.getParent()); 1590b57cec5SDimitry Andric ++NoAliasCount; 1600b57cec5SDimitry Andric break; 161*fe6060f1SDimitry Andric case AliasResult::MayAlias: 1620b57cec5SDimitry Andric PrintResults(AR, PrintMayAlias, *I1, *I2, F.getParent()); 1630b57cec5SDimitry Andric ++MayAliasCount; 1640b57cec5SDimitry Andric break; 165*fe6060f1SDimitry Andric case AliasResult::PartialAlias: 1660b57cec5SDimitry Andric PrintResults(AR, PrintPartialAlias, *I1, *I2, F.getParent()); 1670b57cec5SDimitry Andric ++PartialAliasCount; 1680b57cec5SDimitry Andric break; 169*fe6060f1SDimitry Andric case AliasResult::MustAlias: 1700b57cec5SDimitry Andric PrintResults(AR, PrintMustAlias, *I1, *I2, F.getParent()); 1710b57cec5SDimitry Andric ++MustAliasCount; 1720b57cec5SDimitry Andric break; 1730b57cec5SDimitry Andric } 1740b57cec5SDimitry Andric } 1750b57cec5SDimitry Andric } 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric if (EvalAAMD) { 1780b57cec5SDimitry Andric // iterate over all pairs of load, store 1790b57cec5SDimitry Andric for (Value *Load : Loads) { 1800b57cec5SDimitry Andric for (Value *Store : Stores) { 1810b57cec5SDimitry Andric AliasResult AR = AA.alias(MemoryLocation::get(cast<LoadInst>(Load)), 1820b57cec5SDimitry Andric MemoryLocation::get(cast<StoreInst>(Store))); 1830b57cec5SDimitry Andric switch (AR) { 184*fe6060f1SDimitry Andric case AliasResult::NoAlias: 1850b57cec5SDimitry Andric PrintLoadStoreResults(AR, PrintNoAlias, Load, Store, F.getParent()); 1860b57cec5SDimitry Andric ++NoAliasCount; 1870b57cec5SDimitry Andric break; 188*fe6060f1SDimitry Andric case AliasResult::MayAlias: 1890b57cec5SDimitry Andric PrintLoadStoreResults(AR, PrintMayAlias, Load, Store, F.getParent()); 1900b57cec5SDimitry Andric ++MayAliasCount; 1910b57cec5SDimitry Andric break; 192*fe6060f1SDimitry Andric case AliasResult::PartialAlias: 1930b57cec5SDimitry Andric PrintLoadStoreResults(AR, PrintPartialAlias, Load, Store, F.getParent()); 1940b57cec5SDimitry Andric ++PartialAliasCount; 1950b57cec5SDimitry Andric break; 196*fe6060f1SDimitry Andric case AliasResult::MustAlias: 1970b57cec5SDimitry Andric PrintLoadStoreResults(AR, PrintMustAlias, Load, Store, F.getParent()); 1980b57cec5SDimitry Andric ++MustAliasCount; 1990b57cec5SDimitry Andric break; 2000b57cec5SDimitry Andric } 2010b57cec5SDimitry Andric } 2020b57cec5SDimitry Andric } 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric // iterate over all pairs of store, store 2050b57cec5SDimitry Andric for (SetVector<Value *>::iterator I1 = Stores.begin(), E = Stores.end(); 2060b57cec5SDimitry Andric I1 != E; ++I1) { 2070b57cec5SDimitry Andric for (SetVector<Value *>::iterator I2 = Stores.begin(); I2 != I1; ++I2) { 2080b57cec5SDimitry Andric AliasResult AR = AA.alias(MemoryLocation::get(cast<StoreInst>(*I1)), 2090b57cec5SDimitry Andric MemoryLocation::get(cast<StoreInst>(*I2))); 2100b57cec5SDimitry Andric switch (AR) { 211*fe6060f1SDimitry Andric case AliasResult::NoAlias: 2120b57cec5SDimitry Andric PrintLoadStoreResults(AR, PrintNoAlias, *I1, *I2, F.getParent()); 2130b57cec5SDimitry Andric ++NoAliasCount; 2140b57cec5SDimitry Andric break; 215*fe6060f1SDimitry Andric case AliasResult::MayAlias: 2160b57cec5SDimitry Andric PrintLoadStoreResults(AR, PrintMayAlias, *I1, *I2, F.getParent()); 2170b57cec5SDimitry Andric ++MayAliasCount; 2180b57cec5SDimitry Andric break; 219*fe6060f1SDimitry Andric case AliasResult::PartialAlias: 2200b57cec5SDimitry Andric PrintLoadStoreResults(AR, PrintPartialAlias, *I1, *I2, F.getParent()); 2210b57cec5SDimitry Andric ++PartialAliasCount; 2220b57cec5SDimitry Andric break; 223*fe6060f1SDimitry Andric case AliasResult::MustAlias: 2240b57cec5SDimitry Andric PrintLoadStoreResults(AR, PrintMustAlias, *I1, *I2, F.getParent()); 2250b57cec5SDimitry Andric ++MustAliasCount; 2260b57cec5SDimitry Andric break; 2270b57cec5SDimitry Andric } 2280b57cec5SDimitry Andric } 2290b57cec5SDimitry Andric } 2300b57cec5SDimitry Andric } 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric // Mod/ref alias analysis: compare all pairs of calls and values 2330b57cec5SDimitry Andric for (CallBase *Call : Calls) { 2340b57cec5SDimitry Andric for (auto Pointer : Pointers) { 235e8d8bef9SDimitry Andric auto Size = LocationSize::afterPointer(); 2360b57cec5SDimitry Andric Type *ElTy = cast<PointerType>(Pointer->getType())->getElementType(); 2370b57cec5SDimitry Andric if (ElTy->isSized()) 2380b57cec5SDimitry Andric Size = LocationSize::precise(DL.getTypeStoreSize(ElTy)); 2390b57cec5SDimitry Andric 2400b57cec5SDimitry Andric switch (AA.getModRefInfo(Call, Pointer, Size)) { 2410b57cec5SDimitry Andric case ModRefInfo::NoModRef: 2420b57cec5SDimitry Andric PrintModRefResults("NoModRef", PrintNoModRef, Call, Pointer, 2430b57cec5SDimitry Andric F.getParent()); 2440b57cec5SDimitry Andric ++NoModRefCount; 2450b57cec5SDimitry Andric break; 2460b57cec5SDimitry Andric case ModRefInfo::Mod: 2470b57cec5SDimitry Andric PrintModRefResults("Just Mod", PrintMod, Call, Pointer, F.getParent()); 2480b57cec5SDimitry Andric ++ModCount; 2490b57cec5SDimitry Andric break; 2500b57cec5SDimitry Andric case ModRefInfo::Ref: 2510b57cec5SDimitry Andric PrintModRefResults("Just Ref", PrintRef, Call, Pointer, F.getParent()); 2520b57cec5SDimitry Andric ++RefCount; 2530b57cec5SDimitry Andric break; 2540b57cec5SDimitry Andric case ModRefInfo::ModRef: 2550b57cec5SDimitry Andric PrintModRefResults("Both ModRef", PrintModRef, Call, Pointer, 2560b57cec5SDimitry Andric F.getParent()); 2570b57cec5SDimitry Andric ++ModRefCount; 2580b57cec5SDimitry Andric break; 2590b57cec5SDimitry Andric case ModRefInfo::Must: 2600b57cec5SDimitry Andric PrintModRefResults("Must", PrintMust, Call, Pointer, F.getParent()); 2610b57cec5SDimitry Andric ++MustCount; 2620b57cec5SDimitry Andric break; 2630b57cec5SDimitry Andric case ModRefInfo::MustMod: 2640b57cec5SDimitry Andric PrintModRefResults("Just Mod (MustAlias)", PrintMustMod, Call, Pointer, 2650b57cec5SDimitry Andric F.getParent()); 2660b57cec5SDimitry Andric ++MustModCount; 2670b57cec5SDimitry Andric break; 2680b57cec5SDimitry Andric case ModRefInfo::MustRef: 2690b57cec5SDimitry Andric PrintModRefResults("Just Ref (MustAlias)", PrintMustRef, Call, Pointer, 2700b57cec5SDimitry Andric F.getParent()); 2710b57cec5SDimitry Andric ++MustRefCount; 2720b57cec5SDimitry Andric break; 2730b57cec5SDimitry Andric case ModRefInfo::MustModRef: 2740b57cec5SDimitry Andric PrintModRefResults("Both ModRef (MustAlias)", PrintMustModRef, Call, 2750b57cec5SDimitry Andric Pointer, F.getParent()); 2760b57cec5SDimitry Andric ++MustModRefCount; 2770b57cec5SDimitry Andric break; 2780b57cec5SDimitry Andric } 2790b57cec5SDimitry Andric } 2800b57cec5SDimitry Andric } 2810b57cec5SDimitry Andric 2820b57cec5SDimitry Andric // Mod/ref alias analysis: compare all pairs of calls 2830b57cec5SDimitry Andric for (CallBase *CallA : Calls) { 2840b57cec5SDimitry Andric for (CallBase *CallB : Calls) { 2850b57cec5SDimitry Andric if (CallA == CallB) 2860b57cec5SDimitry Andric continue; 2870b57cec5SDimitry Andric switch (AA.getModRefInfo(CallA, CallB)) { 2880b57cec5SDimitry Andric case ModRefInfo::NoModRef: 2890b57cec5SDimitry Andric PrintModRefResults("NoModRef", PrintNoModRef, CallA, CallB, 2900b57cec5SDimitry Andric F.getParent()); 2910b57cec5SDimitry Andric ++NoModRefCount; 2920b57cec5SDimitry Andric break; 2930b57cec5SDimitry Andric case ModRefInfo::Mod: 2940b57cec5SDimitry Andric PrintModRefResults("Just Mod", PrintMod, CallA, CallB, F.getParent()); 2950b57cec5SDimitry Andric ++ModCount; 2960b57cec5SDimitry Andric break; 2970b57cec5SDimitry Andric case ModRefInfo::Ref: 2980b57cec5SDimitry Andric PrintModRefResults("Just Ref", PrintRef, CallA, CallB, F.getParent()); 2990b57cec5SDimitry Andric ++RefCount; 3000b57cec5SDimitry Andric break; 3010b57cec5SDimitry Andric case ModRefInfo::ModRef: 3020b57cec5SDimitry Andric PrintModRefResults("Both ModRef", PrintModRef, CallA, CallB, 3030b57cec5SDimitry Andric F.getParent()); 3040b57cec5SDimitry Andric ++ModRefCount; 3050b57cec5SDimitry Andric break; 3060b57cec5SDimitry Andric case ModRefInfo::Must: 3070b57cec5SDimitry Andric PrintModRefResults("Must", PrintMust, CallA, CallB, F.getParent()); 3080b57cec5SDimitry Andric ++MustCount; 3090b57cec5SDimitry Andric break; 3100b57cec5SDimitry Andric case ModRefInfo::MustMod: 3110b57cec5SDimitry Andric PrintModRefResults("Just Mod (MustAlias)", PrintMustMod, CallA, CallB, 3120b57cec5SDimitry Andric F.getParent()); 3130b57cec5SDimitry Andric ++MustModCount; 3140b57cec5SDimitry Andric break; 3150b57cec5SDimitry Andric case ModRefInfo::MustRef: 3160b57cec5SDimitry Andric PrintModRefResults("Just Ref (MustAlias)", PrintMustRef, CallA, CallB, 3170b57cec5SDimitry Andric F.getParent()); 3180b57cec5SDimitry Andric ++MustRefCount; 3190b57cec5SDimitry Andric break; 3200b57cec5SDimitry Andric case ModRefInfo::MustModRef: 3210b57cec5SDimitry Andric PrintModRefResults("Both ModRef (MustAlias)", PrintMustModRef, CallA, 3220b57cec5SDimitry Andric CallB, F.getParent()); 3230b57cec5SDimitry Andric ++MustModRefCount; 3240b57cec5SDimitry Andric break; 3250b57cec5SDimitry Andric } 3260b57cec5SDimitry Andric } 3270b57cec5SDimitry Andric } 3280b57cec5SDimitry Andric } 3290b57cec5SDimitry Andric 3300b57cec5SDimitry Andric static void PrintPercent(int64_t Num, int64_t Sum) { 3310b57cec5SDimitry Andric errs() << "(" << Num * 100LL / Sum << "." << ((Num * 1000LL / Sum) % 10) 3320b57cec5SDimitry Andric << "%)\n"; 3330b57cec5SDimitry Andric } 3340b57cec5SDimitry Andric 3350b57cec5SDimitry Andric AAEvaluator::~AAEvaluator() { 3360b57cec5SDimitry Andric if (FunctionCount == 0) 3370b57cec5SDimitry Andric return; 3380b57cec5SDimitry Andric 3390b57cec5SDimitry Andric int64_t AliasSum = 3400b57cec5SDimitry Andric NoAliasCount + MayAliasCount + PartialAliasCount + MustAliasCount; 3410b57cec5SDimitry Andric errs() << "===== Alias Analysis Evaluator Report =====\n"; 3420b57cec5SDimitry Andric if (AliasSum == 0) { 3430b57cec5SDimitry Andric errs() << " Alias Analysis Evaluator Summary: No pointers!\n"; 3440b57cec5SDimitry Andric } else { 3450b57cec5SDimitry Andric errs() << " " << AliasSum << " Total Alias Queries Performed\n"; 3460b57cec5SDimitry Andric errs() << " " << NoAliasCount << " no alias responses "; 3470b57cec5SDimitry Andric PrintPercent(NoAliasCount, AliasSum); 3480b57cec5SDimitry Andric errs() << " " << MayAliasCount << " may alias responses "; 3490b57cec5SDimitry Andric PrintPercent(MayAliasCount, AliasSum); 3500b57cec5SDimitry Andric errs() << " " << PartialAliasCount << " partial alias responses "; 3510b57cec5SDimitry Andric PrintPercent(PartialAliasCount, AliasSum); 3520b57cec5SDimitry Andric errs() << " " << MustAliasCount << " must alias responses "; 3530b57cec5SDimitry Andric PrintPercent(MustAliasCount, AliasSum); 3540b57cec5SDimitry Andric errs() << " Alias Analysis Evaluator Pointer Alias Summary: " 3550b57cec5SDimitry Andric << NoAliasCount * 100 / AliasSum << "%/" 3560b57cec5SDimitry Andric << MayAliasCount * 100 / AliasSum << "%/" 3570b57cec5SDimitry Andric << PartialAliasCount * 100 / AliasSum << "%/" 3580b57cec5SDimitry Andric << MustAliasCount * 100 / AliasSum << "%\n"; 3590b57cec5SDimitry Andric } 3600b57cec5SDimitry Andric 3610b57cec5SDimitry Andric // Display the summary for mod/ref analysis 3620b57cec5SDimitry Andric int64_t ModRefSum = NoModRefCount + RefCount + ModCount + ModRefCount + 3630b57cec5SDimitry Andric MustCount + MustRefCount + MustModCount + MustModRefCount; 3640b57cec5SDimitry Andric if (ModRefSum == 0) { 3650b57cec5SDimitry Andric errs() << " Alias Analysis Mod/Ref Evaluator Summary: no " 3660b57cec5SDimitry Andric "mod/ref!\n"; 3670b57cec5SDimitry Andric } else { 3680b57cec5SDimitry Andric errs() << " " << ModRefSum << " Total ModRef Queries Performed\n"; 3690b57cec5SDimitry Andric errs() << " " << NoModRefCount << " no mod/ref responses "; 3700b57cec5SDimitry Andric PrintPercent(NoModRefCount, ModRefSum); 3710b57cec5SDimitry Andric errs() << " " << ModCount << " mod responses "; 3720b57cec5SDimitry Andric PrintPercent(ModCount, ModRefSum); 3730b57cec5SDimitry Andric errs() << " " << RefCount << " ref responses "; 3740b57cec5SDimitry Andric PrintPercent(RefCount, ModRefSum); 3750b57cec5SDimitry Andric errs() << " " << ModRefCount << " mod & ref responses "; 3760b57cec5SDimitry Andric PrintPercent(ModRefCount, ModRefSum); 3770b57cec5SDimitry Andric errs() << " " << MustCount << " must responses "; 3780b57cec5SDimitry Andric PrintPercent(MustCount, ModRefSum); 3790b57cec5SDimitry Andric errs() << " " << MustModCount << " must mod responses "; 3800b57cec5SDimitry Andric PrintPercent(MustModCount, ModRefSum); 3810b57cec5SDimitry Andric errs() << " " << MustRefCount << " must ref responses "; 3820b57cec5SDimitry Andric PrintPercent(MustRefCount, ModRefSum); 3830b57cec5SDimitry Andric errs() << " " << MustModRefCount << " must mod & ref responses "; 3840b57cec5SDimitry Andric PrintPercent(MustModRefCount, ModRefSum); 3850b57cec5SDimitry Andric errs() << " Alias Analysis Evaluator Mod/Ref Summary: " 3860b57cec5SDimitry Andric << NoModRefCount * 100 / ModRefSum << "%/" 3870b57cec5SDimitry Andric << ModCount * 100 / ModRefSum << "%/" << RefCount * 100 / ModRefSum 3880b57cec5SDimitry Andric << "%/" << ModRefCount * 100 / ModRefSum << "%/" 3890b57cec5SDimitry Andric << MustCount * 100 / ModRefSum << "%/" 3900b57cec5SDimitry Andric << MustRefCount * 100 / ModRefSum << "%/" 3910b57cec5SDimitry Andric << MustModCount * 100 / ModRefSum << "%/" 3920b57cec5SDimitry Andric << MustModRefCount * 100 / ModRefSum << "%\n"; 3930b57cec5SDimitry Andric } 3940b57cec5SDimitry Andric } 3950b57cec5SDimitry Andric 3960b57cec5SDimitry Andric namespace llvm { 3970b57cec5SDimitry Andric class AAEvalLegacyPass : public FunctionPass { 3980b57cec5SDimitry Andric std::unique_ptr<AAEvaluator> P; 3990b57cec5SDimitry Andric 4000b57cec5SDimitry Andric public: 4010b57cec5SDimitry Andric static char ID; // Pass identification, replacement for typeid 4020b57cec5SDimitry Andric AAEvalLegacyPass() : FunctionPass(ID) { 4030b57cec5SDimitry Andric initializeAAEvalLegacyPassPass(*PassRegistry::getPassRegistry()); 4040b57cec5SDimitry Andric } 4050b57cec5SDimitry Andric 4060b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 4070b57cec5SDimitry Andric AU.addRequired<AAResultsWrapperPass>(); 4080b57cec5SDimitry Andric AU.setPreservesAll(); 4090b57cec5SDimitry Andric } 4100b57cec5SDimitry Andric 4110b57cec5SDimitry Andric bool doInitialization(Module &M) override { 4120b57cec5SDimitry Andric P.reset(new AAEvaluator()); 4130b57cec5SDimitry Andric return false; 4140b57cec5SDimitry Andric } 4150b57cec5SDimitry Andric 4160b57cec5SDimitry Andric bool runOnFunction(Function &F) override { 4170b57cec5SDimitry Andric P->runInternal(F, getAnalysis<AAResultsWrapperPass>().getAAResults()); 4180b57cec5SDimitry Andric return false; 4190b57cec5SDimitry Andric } 4200b57cec5SDimitry Andric bool doFinalization(Module &M) override { 4210b57cec5SDimitry Andric P.reset(); 4220b57cec5SDimitry Andric return false; 4230b57cec5SDimitry Andric } 4240b57cec5SDimitry Andric }; 4250b57cec5SDimitry Andric } 4260b57cec5SDimitry Andric 4270b57cec5SDimitry Andric char AAEvalLegacyPass::ID = 0; 4280b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(AAEvalLegacyPass, "aa-eval", 4290b57cec5SDimitry Andric "Exhaustive Alias Analysis Precision Evaluator", false, 4300b57cec5SDimitry Andric true) 4310b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) 4320b57cec5SDimitry Andric INITIALIZE_PASS_END(AAEvalLegacyPass, "aa-eval", 4330b57cec5SDimitry Andric "Exhaustive Alias Analysis Precision Evaluator", false, 4340b57cec5SDimitry Andric true) 4350b57cec5SDimitry Andric 4360b57cec5SDimitry Andric FunctionPass *llvm::createAAEvalPass() { return new AAEvalLegacyPass(); } 437