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" 19*480093f4SDimitry 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 540b57cec5SDimitry Andric if (o2 < o1) 550b57cec5SDimitry Andric std::swap(o1, o2); 560b57cec5SDimitry Andric errs() << " " << AR << ":\t" << o1 << ", " << o2 << "\n"; 570b57cec5SDimitry Andric } 580b57cec5SDimitry Andric } 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric static inline void PrintModRefResults(const char *Msg, bool P, Instruction *I, 610b57cec5SDimitry Andric Value *Ptr, Module *M) { 620b57cec5SDimitry Andric if (PrintAll || P) { 630b57cec5SDimitry Andric errs() << " " << Msg << ": Ptr: "; 640b57cec5SDimitry Andric Ptr->printAsOperand(errs(), true, M); 650b57cec5SDimitry Andric errs() << "\t<->" << *I << '\n'; 660b57cec5SDimitry Andric } 670b57cec5SDimitry Andric } 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric static inline void PrintModRefResults(const char *Msg, bool P, CallBase *CallA, 700b57cec5SDimitry Andric CallBase *CallB, Module *M) { 710b57cec5SDimitry Andric if (PrintAll || P) { 720b57cec5SDimitry Andric errs() << " " << Msg << ": " << *CallA << " <-> " << *CallB << '\n'; 730b57cec5SDimitry Andric } 740b57cec5SDimitry Andric } 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric static inline void PrintLoadStoreResults(AliasResult AR, bool P, 770b57cec5SDimitry Andric const Value *V1, const Value *V2, 780b57cec5SDimitry Andric const Module *M) { 790b57cec5SDimitry Andric if (PrintAll || P) { 800b57cec5SDimitry Andric errs() << " " << AR << ": " << *V1 << " <-> " << *V2 << '\n'; 810b57cec5SDimitry Andric } 820b57cec5SDimitry Andric } 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric static inline bool isInterestingPointer(Value *V) { 850b57cec5SDimitry Andric return V->getType()->isPointerTy() 860b57cec5SDimitry Andric && !isa<ConstantPointerNull>(V); 870b57cec5SDimitry Andric } 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric PreservedAnalyses AAEvaluator::run(Function &F, FunctionAnalysisManager &AM) { 900b57cec5SDimitry Andric runInternal(F, AM.getResult<AAManager>(F)); 910b57cec5SDimitry Andric return PreservedAnalyses::all(); 920b57cec5SDimitry Andric } 930b57cec5SDimitry Andric 940b57cec5SDimitry Andric void AAEvaluator::runInternal(Function &F, AAResults &AA) { 950b57cec5SDimitry Andric const DataLayout &DL = F.getParent()->getDataLayout(); 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric ++FunctionCount; 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric SetVector<Value *> Pointers; 1000b57cec5SDimitry Andric SmallSetVector<CallBase *, 16> Calls; 1010b57cec5SDimitry Andric SetVector<Value *> Loads; 1020b57cec5SDimitry Andric SetVector<Value *> Stores; 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric for (auto &I : F.args()) 1050b57cec5SDimitry Andric if (I.getType()->isPointerTy()) // Add all pointer arguments. 1060b57cec5SDimitry Andric Pointers.insert(&I); 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { 1090b57cec5SDimitry Andric if (I->getType()->isPointerTy()) // Add all pointer instructions. 1100b57cec5SDimitry Andric Pointers.insert(&*I); 1110b57cec5SDimitry Andric if (EvalAAMD && isa<LoadInst>(&*I)) 1120b57cec5SDimitry Andric Loads.insert(&*I); 1130b57cec5SDimitry Andric if (EvalAAMD && isa<StoreInst>(&*I)) 1140b57cec5SDimitry Andric Stores.insert(&*I); 1150b57cec5SDimitry Andric Instruction &Inst = *I; 1160b57cec5SDimitry Andric if (auto *Call = dyn_cast<CallBase>(&Inst)) { 1170b57cec5SDimitry Andric Value *Callee = Call->getCalledValue(); 1180b57cec5SDimitry Andric // Skip actual functions for direct function calls. 1190b57cec5SDimitry Andric if (!isa<Function>(Callee) && isInterestingPointer(Callee)) 1200b57cec5SDimitry Andric Pointers.insert(Callee); 1210b57cec5SDimitry Andric // Consider formals. 1220b57cec5SDimitry Andric for (Use &DataOp : Call->data_ops()) 1230b57cec5SDimitry Andric if (isInterestingPointer(DataOp)) 1240b57cec5SDimitry Andric Pointers.insert(DataOp); 1250b57cec5SDimitry Andric Calls.insert(Call); 1260b57cec5SDimitry Andric } else { 1270b57cec5SDimitry Andric // Consider all operands. 1280b57cec5SDimitry Andric for (Instruction::op_iterator OI = Inst.op_begin(), OE = Inst.op_end(); 1290b57cec5SDimitry Andric OI != OE; ++OI) 1300b57cec5SDimitry Andric if (isInterestingPointer(*OI)) 1310b57cec5SDimitry Andric Pointers.insert(*OI); 1320b57cec5SDimitry Andric } 1330b57cec5SDimitry Andric } 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric if (PrintAll || PrintNoAlias || PrintMayAlias || PrintPartialAlias || 1360b57cec5SDimitry Andric PrintMustAlias || PrintNoModRef || PrintMod || PrintRef || PrintModRef) 1370b57cec5SDimitry Andric errs() << "Function: " << F.getName() << ": " << Pointers.size() 1380b57cec5SDimitry Andric << " pointers, " << Calls.size() << " call sites\n"; 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric // iterate over the worklist, and run the full (n^2)/2 disambiguations 1410b57cec5SDimitry Andric for (SetVector<Value *>::iterator I1 = Pointers.begin(), E = Pointers.end(); 1420b57cec5SDimitry Andric I1 != E; ++I1) { 1430b57cec5SDimitry Andric auto I1Size = LocationSize::unknown(); 1440b57cec5SDimitry Andric Type *I1ElTy = cast<PointerType>((*I1)->getType())->getElementType(); 1450b57cec5SDimitry Andric if (I1ElTy->isSized()) 1460b57cec5SDimitry Andric I1Size = LocationSize::precise(DL.getTypeStoreSize(I1ElTy)); 1470b57cec5SDimitry Andric 1480b57cec5SDimitry Andric for (SetVector<Value *>::iterator I2 = Pointers.begin(); I2 != I1; ++I2) { 1490b57cec5SDimitry Andric auto I2Size = LocationSize::unknown(); 1500b57cec5SDimitry Andric Type *I2ElTy = cast<PointerType>((*I2)->getType())->getElementType(); 1510b57cec5SDimitry Andric if (I2ElTy->isSized()) 1520b57cec5SDimitry Andric I2Size = LocationSize::precise(DL.getTypeStoreSize(I2ElTy)); 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric AliasResult AR = AA.alias(*I1, I1Size, *I2, I2Size); 1550b57cec5SDimitry Andric switch (AR) { 1560b57cec5SDimitry Andric case NoAlias: 1570b57cec5SDimitry Andric PrintResults(AR, PrintNoAlias, *I1, *I2, F.getParent()); 1580b57cec5SDimitry Andric ++NoAliasCount; 1590b57cec5SDimitry Andric break; 1600b57cec5SDimitry Andric case MayAlias: 1610b57cec5SDimitry Andric PrintResults(AR, PrintMayAlias, *I1, *I2, F.getParent()); 1620b57cec5SDimitry Andric ++MayAliasCount; 1630b57cec5SDimitry Andric break; 1640b57cec5SDimitry Andric case PartialAlias: 1650b57cec5SDimitry Andric PrintResults(AR, PrintPartialAlias, *I1, *I2, F.getParent()); 1660b57cec5SDimitry Andric ++PartialAliasCount; 1670b57cec5SDimitry Andric break; 1680b57cec5SDimitry Andric case MustAlias: 1690b57cec5SDimitry Andric PrintResults(AR, PrintMustAlias, *I1, *I2, F.getParent()); 1700b57cec5SDimitry Andric ++MustAliasCount; 1710b57cec5SDimitry Andric break; 1720b57cec5SDimitry Andric } 1730b57cec5SDimitry Andric } 1740b57cec5SDimitry Andric } 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric if (EvalAAMD) { 1770b57cec5SDimitry Andric // iterate over all pairs of load, store 1780b57cec5SDimitry Andric for (Value *Load : Loads) { 1790b57cec5SDimitry Andric for (Value *Store : Stores) { 1800b57cec5SDimitry Andric AliasResult AR = AA.alias(MemoryLocation::get(cast<LoadInst>(Load)), 1810b57cec5SDimitry Andric MemoryLocation::get(cast<StoreInst>(Store))); 1820b57cec5SDimitry Andric switch (AR) { 1830b57cec5SDimitry Andric case NoAlias: 1840b57cec5SDimitry Andric PrintLoadStoreResults(AR, PrintNoAlias, Load, Store, F.getParent()); 1850b57cec5SDimitry Andric ++NoAliasCount; 1860b57cec5SDimitry Andric break; 1870b57cec5SDimitry Andric case MayAlias: 1880b57cec5SDimitry Andric PrintLoadStoreResults(AR, PrintMayAlias, Load, Store, F.getParent()); 1890b57cec5SDimitry Andric ++MayAliasCount; 1900b57cec5SDimitry Andric break; 1910b57cec5SDimitry Andric case PartialAlias: 1920b57cec5SDimitry Andric PrintLoadStoreResults(AR, PrintPartialAlias, Load, Store, F.getParent()); 1930b57cec5SDimitry Andric ++PartialAliasCount; 1940b57cec5SDimitry Andric break; 1950b57cec5SDimitry Andric case MustAlias: 1960b57cec5SDimitry Andric PrintLoadStoreResults(AR, PrintMustAlias, Load, Store, F.getParent()); 1970b57cec5SDimitry Andric ++MustAliasCount; 1980b57cec5SDimitry Andric break; 1990b57cec5SDimitry Andric } 2000b57cec5SDimitry Andric } 2010b57cec5SDimitry Andric } 2020b57cec5SDimitry Andric 2030b57cec5SDimitry Andric // iterate over all pairs of store, store 2040b57cec5SDimitry Andric for (SetVector<Value *>::iterator I1 = Stores.begin(), E = Stores.end(); 2050b57cec5SDimitry Andric I1 != E; ++I1) { 2060b57cec5SDimitry Andric for (SetVector<Value *>::iterator I2 = Stores.begin(); I2 != I1; ++I2) { 2070b57cec5SDimitry Andric AliasResult AR = AA.alias(MemoryLocation::get(cast<StoreInst>(*I1)), 2080b57cec5SDimitry Andric MemoryLocation::get(cast<StoreInst>(*I2))); 2090b57cec5SDimitry Andric switch (AR) { 2100b57cec5SDimitry Andric case NoAlias: 2110b57cec5SDimitry Andric PrintLoadStoreResults(AR, PrintNoAlias, *I1, *I2, F.getParent()); 2120b57cec5SDimitry Andric ++NoAliasCount; 2130b57cec5SDimitry Andric break; 2140b57cec5SDimitry Andric case MayAlias: 2150b57cec5SDimitry Andric PrintLoadStoreResults(AR, PrintMayAlias, *I1, *I2, F.getParent()); 2160b57cec5SDimitry Andric ++MayAliasCount; 2170b57cec5SDimitry Andric break; 2180b57cec5SDimitry Andric case PartialAlias: 2190b57cec5SDimitry Andric PrintLoadStoreResults(AR, PrintPartialAlias, *I1, *I2, F.getParent()); 2200b57cec5SDimitry Andric ++PartialAliasCount; 2210b57cec5SDimitry Andric break; 2220b57cec5SDimitry Andric case MustAlias: 2230b57cec5SDimitry Andric PrintLoadStoreResults(AR, PrintMustAlias, *I1, *I2, F.getParent()); 2240b57cec5SDimitry Andric ++MustAliasCount; 2250b57cec5SDimitry Andric break; 2260b57cec5SDimitry Andric } 2270b57cec5SDimitry Andric } 2280b57cec5SDimitry Andric } 2290b57cec5SDimitry Andric } 2300b57cec5SDimitry Andric 2310b57cec5SDimitry Andric // Mod/ref alias analysis: compare all pairs of calls and values 2320b57cec5SDimitry Andric for (CallBase *Call : Calls) { 2330b57cec5SDimitry Andric for (auto Pointer : Pointers) { 2340b57cec5SDimitry Andric auto Size = LocationSize::unknown(); 2350b57cec5SDimitry Andric Type *ElTy = cast<PointerType>(Pointer->getType())->getElementType(); 2360b57cec5SDimitry Andric if (ElTy->isSized()) 2370b57cec5SDimitry Andric Size = LocationSize::precise(DL.getTypeStoreSize(ElTy)); 2380b57cec5SDimitry Andric 2390b57cec5SDimitry Andric switch (AA.getModRefInfo(Call, Pointer, Size)) { 2400b57cec5SDimitry Andric case ModRefInfo::NoModRef: 2410b57cec5SDimitry Andric PrintModRefResults("NoModRef", PrintNoModRef, Call, Pointer, 2420b57cec5SDimitry Andric F.getParent()); 2430b57cec5SDimitry Andric ++NoModRefCount; 2440b57cec5SDimitry Andric break; 2450b57cec5SDimitry Andric case ModRefInfo::Mod: 2460b57cec5SDimitry Andric PrintModRefResults("Just Mod", PrintMod, Call, Pointer, F.getParent()); 2470b57cec5SDimitry Andric ++ModCount; 2480b57cec5SDimitry Andric break; 2490b57cec5SDimitry Andric case ModRefInfo::Ref: 2500b57cec5SDimitry Andric PrintModRefResults("Just Ref", PrintRef, Call, Pointer, F.getParent()); 2510b57cec5SDimitry Andric ++RefCount; 2520b57cec5SDimitry Andric break; 2530b57cec5SDimitry Andric case ModRefInfo::ModRef: 2540b57cec5SDimitry Andric PrintModRefResults("Both ModRef", PrintModRef, Call, Pointer, 2550b57cec5SDimitry Andric F.getParent()); 2560b57cec5SDimitry Andric ++ModRefCount; 2570b57cec5SDimitry Andric break; 2580b57cec5SDimitry Andric case ModRefInfo::Must: 2590b57cec5SDimitry Andric PrintModRefResults("Must", PrintMust, Call, Pointer, F.getParent()); 2600b57cec5SDimitry Andric ++MustCount; 2610b57cec5SDimitry Andric break; 2620b57cec5SDimitry Andric case ModRefInfo::MustMod: 2630b57cec5SDimitry Andric PrintModRefResults("Just Mod (MustAlias)", PrintMustMod, Call, Pointer, 2640b57cec5SDimitry Andric F.getParent()); 2650b57cec5SDimitry Andric ++MustModCount; 2660b57cec5SDimitry Andric break; 2670b57cec5SDimitry Andric case ModRefInfo::MustRef: 2680b57cec5SDimitry Andric PrintModRefResults("Just Ref (MustAlias)", PrintMustRef, Call, Pointer, 2690b57cec5SDimitry Andric F.getParent()); 2700b57cec5SDimitry Andric ++MustRefCount; 2710b57cec5SDimitry Andric break; 2720b57cec5SDimitry Andric case ModRefInfo::MustModRef: 2730b57cec5SDimitry Andric PrintModRefResults("Both ModRef (MustAlias)", PrintMustModRef, Call, 2740b57cec5SDimitry Andric Pointer, F.getParent()); 2750b57cec5SDimitry Andric ++MustModRefCount; 2760b57cec5SDimitry Andric break; 2770b57cec5SDimitry Andric } 2780b57cec5SDimitry Andric } 2790b57cec5SDimitry Andric } 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric // Mod/ref alias analysis: compare all pairs of calls 2820b57cec5SDimitry Andric for (CallBase *CallA : Calls) { 2830b57cec5SDimitry Andric for (CallBase *CallB : Calls) { 2840b57cec5SDimitry Andric if (CallA == CallB) 2850b57cec5SDimitry Andric continue; 2860b57cec5SDimitry Andric switch (AA.getModRefInfo(CallA, CallB)) { 2870b57cec5SDimitry Andric case ModRefInfo::NoModRef: 2880b57cec5SDimitry Andric PrintModRefResults("NoModRef", PrintNoModRef, CallA, CallB, 2890b57cec5SDimitry Andric F.getParent()); 2900b57cec5SDimitry Andric ++NoModRefCount; 2910b57cec5SDimitry Andric break; 2920b57cec5SDimitry Andric case ModRefInfo::Mod: 2930b57cec5SDimitry Andric PrintModRefResults("Just Mod", PrintMod, CallA, CallB, F.getParent()); 2940b57cec5SDimitry Andric ++ModCount; 2950b57cec5SDimitry Andric break; 2960b57cec5SDimitry Andric case ModRefInfo::Ref: 2970b57cec5SDimitry Andric PrintModRefResults("Just Ref", PrintRef, CallA, CallB, F.getParent()); 2980b57cec5SDimitry Andric ++RefCount; 2990b57cec5SDimitry Andric break; 3000b57cec5SDimitry Andric case ModRefInfo::ModRef: 3010b57cec5SDimitry Andric PrintModRefResults("Both ModRef", PrintModRef, CallA, CallB, 3020b57cec5SDimitry Andric F.getParent()); 3030b57cec5SDimitry Andric ++ModRefCount; 3040b57cec5SDimitry Andric break; 3050b57cec5SDimitry Andric case ModRefInfo::Must: 3060b57cec5SDimitry Andric PrintModRefResults("Must", PrintMust, CallA, CallB, F.getParent()); 3070b57cec5SDimitry Andric ++MustCount; 3080b57cec5SDimitry Andric break; 3090b57cec5SDimitry Andric case ModRefInfo::MustMod: 3100b57cec5SDimitry Andric PrintModRefResults("Just Mod (MustAlias)", PrintMustMod, CallA, CallB, 3110b57cec5SDimitry Andric F.getParent()); 3120b57cec5SDimitry Andric ++MustModCount; 3130b57cec5SDimitry Andric break; 3140b57cec5SDimitry Andric case ModRefInfo::MustRef: 3150b57cec5SDimitry Andric PrintModRefResults("Just Ref (MustAlias)", PrintMustRef, CallA, CallB, 3160b57cec5SDimitry Andric F.getParent()); 3170b57cec5SDimitry Andric ++MustRefCount; 3180b57cec5SDimitry Andric break; 3190b57cec5SDimitry Andric case ModRefInfo::MustModRef: 3200b57cec5SDimitry Andric PrintModRefResults("Both ModRef (MustAlias)", PrintMustModRef, CallA, 3210b57cec5SDimitry Andric CallB, F.getParent()); 3220b57cec5SDimitry Andric ++MustModRefCount; 3230b57cec5SDimitry Andric break; 3240b57cec5SDimitry Andric } 3250b57cec5SDimitry Andric } 3260b57cec5SDimitry Andric } 3270b57cec5SDimitry Andric } 3280b57cec5SDimitry Andric 3290b57cec5SDimitry Andric static void PrintPercent(int64_t Num, int64_t Sum) { 3300b57cec5SDimitry Andric errs() << "(" << Num * 100LL / Sum << "." << ((Num * 1000LL / Sum) % 10) 3310b57cec5SDimitry Andric << "%)\n"; 3320b57cec5SDimitry Andric } 3330b57cec5SDimitry Andric 3340b57cec5SDimitry Andric AAEvaluator::~AAEvaluator() { 3350b57cec5SDimitry Andric if (FunctionCount == 0) 3360b57cec5SDimitry Andric return; 3370b57cec5SDimitry Andric 3380b57cec5SDimitry Andric int64_t AliasSum = 3390b57cec5SDimitry Andric NoAliasCount + MayAliasCount + PartialAliasCount + MustAliasCount; 3400b57cec5SDimitry Andric errs() << "===== Alias Analysis Evaluator Report =====\n"; 3410b57cec5SDimitry Andric if (AliasSum == 0) { 3420b57cec5SDimitry Andric errs() << " Alias Analysis Evaluator Summary: No pointers!\n"; 3430b57cec5SDimitry Andric } else { 3440b57cec5SDimitry Andric errs() << " " << AliasSum << " Total Alias Queries Performed\n"; 3450b57cec5SDimitry Andric errs() << " " << NoAliasCount << " no alias responses "; 3460b57cec5SDimitry Andric PrintPercent(NoAliasCount, AliasSum); 3470b57cec5SDimitry Andric errs() << " " << MayAliasCount << " may alias responses "; 3480b57cec5SDimitry Andric PrintPercent(MayAliasCount, AliasSum); 3490b57cec5SDimitry Andric errs() << " " << PartialAliasCount << " partial alias responses "; 3500b57cec5SDimitry Andric PrintPercent(PartialAliasCount, AliasSum); 3510b57cec5SDimitry Andric errs() << " " << MustAliasCount << " must alias responses "; 3520b57cec5SDimitry Andric PrintPercent(MustAliasCount, AliasSum); 3530b57cec5SDimitry Andric errs() << " Alias Analysis Evaluator Pointer Alias Summary: " 3540b57cec5SDimitry Andric << NoAliasCount * 100 / AliasSum << "%/" 3550b57cec5SDimitry Andric << MayAliasCount * 100 / AliasSum << "%/" 3560b57cec5SDimitry Andric << PartialAliasCount * 100 / AliasSum << "%/" 3570b57cec5SDimitry Andric << MustAliasCount * 100 / AliasSum << "%\n"; 3580b57cec5SDimitry Andric } 3590b57cec5SDimitry Andric 3600b57cec5SDimitry Andric // Display the summary for mod/ref analysis 3610b57cec5SDimitry Andric int64_t ModRefSum = NoModRefCount + RefCount + ModCount + ModRefCount + 3620b57cec5SDimitry Andric MustCount + MustRefCount + MustModCount + MustModRefCount; 3630b57cec5SDimitry Andric if (ModRefSum == 0) { 3640b57cec5SDimitry Andric errs() << " Alias Analysis Mod/Ref Evaluator Summary: no " 3650b57cec5SDimitry Andric "mod/ref!\n"; 3660b57cec5SDimitry Andric } else { 3670b57cec5SDimitry Andric errs() << " " << ModRefSum << " Total ModRef Queries Performed\n"; 3680b57cec5SDimitry Andric errs() << " " << NoModRefCount << " no mod/ref responses "; 3690b57cec5SDimitry Andric PrintPercent(NoModRefCount, ModRefSum); 3700b57cec5SDimitry Andric errs() << " " << ModCount << " mod responses "; 3710b57cec5SDimitry Andric PrintPercent(ModCount, ModRefSum); 3720b57cec5SDimitry Andric errs() << " " << RefCount << " ref responses "; 3730b57cec5SDimitry Andric PrintPercent(RefCount, ModRefSum); 3740b57cec5SDimitry Andric errs() << " " << ModRefCount << " mod & ref responses "; 3750b57cec5SDimitry Andric PrintPercent(ModRefCount, ModRefSum); 3760b57cec5SDimitry Andric errs() << " " << MustCount << " must responses "; 3770b57cec5SDimitry Andric PrintPercent(MustCount, ModRefSum); 3780b57cec5SDimitry Andric errs() << " " << MustModCount << " must mod responses "; 3790b57cec5SDimitry Andric PrintPercent(MustModCount, ModRefSum); 3800b57cec5SDimitry Andric errs() << " " << MustRefCount << " must ref responses "; 3810b57cec5SDimitry Andric PrintPercent(MustRefCount, ModRefSum); 3820b57cec5SDimitry Andric errs() << " " << MustModRefCount << " must mod & ref responses "; 3830b57cec5SDimitry Andric PrintPercent(MustModRefCount, ModRefSum); 3840b57cec5SDimitry Andric errs() << " Alias Analysis Evaluator Mod/Ref Summary: " 3850b57cec5SDimitry Andric << NoModRefCount * 100 / ModRefSum << "%/" 3860b57cec5SDimitry Andric << ModCount * 100 / ModRefSum << "%/" << RefCount * 100 / ModRefSum 3870b57cec5SDimitry Andric << "%/" << ModRefCount * 100 / ModRefSum << "%/" 3880b57cec5SDimitry Andric << MustCount * 100 / ModRefSum << "%/" 3890b57cec5SDimitry Andric << MustRefCount * 100 / ModRefSum << "%/" 3900b57cec5SDimitry Andric << MustModCount * 100 / ModRefSum << "%/" 3910b57cec5SDimitry Andric << MustModRefCount * 100 / ModRefSum << "%\n"; 3920b57cec5SDimitry Andric } 3930b57cec5SDimitry Andric } 3940b57cec5SDimitry Andric 3950b57cec5SDimitry Andric namespace llvm { 3960b57cec5SDimitry Andric class AAEvalLegacyPass : public FunctionPass { 3970b57cec5SDimitry Andric std::unique_ptr<AAEvaluator> P; 3980b57cec5SDimitry Andric 3990b57cec5SDimitry Andric public: 4000b57cec5SDimitry Andric static char ID; // Pass identification, replacement for typeid 4010b57cec5SDimitry Andric AAEvalLegacyPass() : FunctionPass(ID) { 4020b57cec5SDimitry Andric initializeAAEvalLegacyPassPass(*PassRegistry::getPassRegistry()); 4030b57cec5SDimitry Andric } 4040b57cec5SDimitry Andric 4050b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 4060b57cec5SDimitry Andric AU.addRequired<AAResultsWrapperPass>(); 4070b57cec5SDimitry Andric AU.setPreservesAll(); 4080b57cec5SDimitry Andric } 4090b57cec5SDimitry Andric 4100b57cec5SDimitry Andric bool doInitialization(Module &M) override { 4110b57cec5SDimitry Andric P.reset(new AAEvaluator()); 4120b57cec5SDimitry Andric return false; 4130b57cec5SDimitry Andric } 4140b57cec5SDimitry Andric 4150b57cec5SDimitry Andric bool runOnFunction(Function &F) override { 4160b57cec5SDimitry Andric P->runInternal(F, getAnalysis<AAResultsWrapperPass>().getAAResults()); 4170b57cec5SDimitry Andric return false; 4180b57cec5SDimitry Andric } 4190b57cec5SDimitry Andric bool doFinalization(Module &M) override { 4200b57cec5SDimitry Andric P.reset(); 4210b57cec5SDimitry Andric return false; 4220b57cec5SDimitry Andric } 4230b57cec5SDimitry Andric }; 4240b57cec5SDimitry Andric } 4250b57cec5SDimitry Andric 4260b57cec5SDimitry Andric char AAEvalLegacyPass::ID = 0; 4270b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(AAEvalLegacyPass, "aa-eval", 4280b57cec5SDimitry Andric "Exhaustive Alias Analysis Precision Evaluator", false, 4290b57cec5SDimitry Andric true) 4300b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) 4310b57cec5SDimitry Andric INITIALIZE_PASS_END(AAEvalLegacyPass, "aa-eval", 4320b57cec5SDimitry Andric "Exhaustive Alias Analysis Precision Evaluator", false, 4330b57cec5SDimitry Andric true) 4340b57cec5SDimitry Andric 4350b57cec5SDimitry Andric FunctionPass *llvm::createAAEvalPass() { return new AAEvalLegacyPass(); } 436