AliasAnalysisEvaluator.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. //===- AliasAnalysisEvaluator.cpp - Alias Analysis Accuracy Evaluator -----===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "llvm/Analysis/AliasAnalysisEvaluator.h"
  9. #include "llvm/ADT/SetVector.h"
  10. #include "llvm/Analysis/AliasAnalysis.h"
  11. #include "llvm/IR/DataLayout.h"
  12. #include "llvm/IR/Function.h"
  13. #include "llvm/IR/InstIterator.h"
  14. #include "llvm/IR/Instructions.h"
  15. #include "llvm/IR/Module.h"
  16. #include "llvm/InitializePasses.h"
  17. #include "llvm/Pass.h"
  18. #include "llvm/Support/CommandLine.h"
  19. #include "llvm/Support/raw_ostream.h"
  20. using namespace llvm;
  21. static cl::opt<bool> PrintAll("print-all-alias-modref-info", cl::ReallyHidden);
  22. static cl::opt<bool> PrintNoAlias("print-no-aliases", cl::ReallyHidden);
  23. static cl::opt<bool> PrintMayAlias("print-may-aliases", cl::ReallyHidden);
  24. static cl::opt<bool> PrintPartialAlias("print-partial-aliases", cl::ReallyHidden);
  25. static cl::opt<bool> PrintMustAlias("print-must-aliases", cl::ReallyHidden);
  26. static cl::opt<bool> PrintNoModRef("print-no-modref", cl::ReallyHidden);
  27. static cl::opt<bool> PrintRef("print-ref", cl::ReallyHidden);
  28. static cl::opt<bool> PrintMod("print-mod", cl::ReallyHidden);
  29. static cl::opt<bool> PrintModRef("print-modref", cl::ReallyHidden);
  30. static cl::opt<bool> EvalAAMD("evaluate-aa-metadata", cl::ReallyHidden);
  31. static void PrintResults(AliasResult AR, bool P,
  32. std::pair<const Value *, Type *> Loc1,
  33. std::pair<const Value *, Type *> Loc2,
  34. const Module *M) {
  35. if (PrintAll || P) {
  36. Type *Ty1 = Loc1.second, *Ty2 = Loc2.second;
  37. unsigned AS1 = Loc1.first->getType()->getPointerAddressSpace();
  38. unsigned AS2 = Loc2.first->getType()->getPointerAddressSpace();
  39. std::string o1, o2;
  40. {
  41. raw_string_ostream os1(o1), os2(o2);
  42. Loc1.first->printAsOperand(os1, false, M);
  43. Loc2.first->printAsOperand(os2, false, M);
  44. }
  45. if (o2 < o1) {
  46. std::swap(o1, o2);
  47. std::swap(Ty1, Ty2);
  48. std::swap(AS1, AS2);
  49. // Change offset sign for the local AR, for printing only.
  50. AR.swap();
  51. }
  52. errs() << " " << AR << ":\t";
  53. Ty1->print(errs(), false, /* NoDetails */ true);
  54. if (AS1 != 0)
  55. errs() << " addrspace(" << AS1 << ")";
  56. errs() << "* " << o1 << ", ";
  57. Ty2->print(errs(), false, /* NoDetails */ true);
  58. if (AS2 != 0)
  59. errs() << " addrspace(" << AS2 << ")";
  60. errs() << "* " << o2 << "\n";
  61. }
  62. }
  63. static inline void PrintModRefResults(
  64. const char *Msg, bool P, Instruction *I,
  65. std::pair<const Value *, Type *> Loc, Module *M) {
  66. if (PrintAll || P) {
  67. errs() << " " << Msg << ": Ptr: ";
  68. Loc.second->print(errs(), false, /* NoDetails */ true);
  69. errs() << "* ";
  70. Loc.first->printAsOperand(errs(), false, M);
  71. errs() << "\t<->" << *I << '\n';
  72. }
  73. }
  74. static inline void PrintModRefResults(const char *Msg, bool P, CallBase *CallA,
  75. CallBase *CallB, Module *M) {
  76. if (PrintAll || P) {
  77. errs() << " " << Msg << ": " << *CallA << " <-> " << *CallB << '\n';
  78. }
  79. }
  80. static inline void PrintLoadStoreResults(AliasResult AR, bool P,
  81. const Value *V1, const Value *V2,
  82. const Module *M) {
  83. if (PrintAll || P) {
  84. errs() << " " << AR << ": " << *V1 << " <-> " << *V2 << '\n';
  85. }
  86. }
  87. PreservedAnalyses AAEvaluator::run(Function &F, FunctionAnalysisManager &AM) {
  88. runInternal(F, AM.getResult<AAManager>(F));
  89. return PreservedAnalyses::all();
  90. }
  91. void AAEvaluator::runInternal(Function &F, AAResults &AA) {
  92. const DataLayout &DL = F.getParent()->getDataLayout();
  93. ++FunctionCount;
  94. SetVector<std::pair<const Value *, Type *>> Pointers;
  95. SmallSetVector<CallBase *, 16> Calls;
  96. SetVector<Value *> Loads;
  97. SetVector<Value *> Stores;
  98. for (Instruction &Inst : instructions(F)) {
  99. if (auto *LI = dyn_cast<LoadInst>(&Inst)) {
  100. Pointers.insert({LI->getPointerOperand(), LI->getType()});
  101. Loads.insert(LI);
  102. } else if (auto *SI = dyn_cast<StoreInst>(&Inst)) {
  103. Pointers.insert({SI->getPointerOperand(),
  104. SI->getValueOperand()->getType()});
  105. Stores.insert(SI);
  106. } else if (auto *CB = dyn_cast<CallBase>(&Inst))
  107. Calls.insert(CB);
  108. }
  109. if (PrintAll || PrintNoAlias || PrintMayAlias || PrintPartialAlias ||
  110. PrintMustAlias || PrintNoModRef || PrintMod || PrintRef || PrintModRef)
  111. errs() << "Function: " << F.getName() << ": " << Pointers.size()
  112. << " pointers, " << Calls.size() << " call sites\n";
  113. // iterate over the worklist, and run the full (n^2)/2 disambiguations
  114. for (auto I1 = Pointers.begin(), E = Pointers.end(); I1 != E; ++I1) {
  115. LocationSize Size1 = LocationSize::precise(DL.getTypeStoreSize(I1->second));
  116. for (auto I2 = Pointers.begin(); I2 != I1; ++I2) {
  117. LocationSize Size2 =
  118. LocationSize::precise(DL.getTypeStoreSize(I2->second));
  119. AliasResult AR = AA.alias(I1->first, Size1, I2->first, Size2);
  120. switch (AR) {
  121. case AliasResult::NoAlias:
  122. PrintResults(AR, PrintNoAlias, *I1, *I2, F.getParent());
  123. ++NoAliasCount;
  124. break;
  125. case AliasResult::MayAlias:
  126. PrintResults(AR, PrintMayAlias, *I1, *I2, F.getParent());
  127. ++MayAliasCount;
  128. break;
  129. case AliasResult::PartialAlias:
  130. PrintResults(AR, PrintPartialAlias, *I1, *I2, F.getParent());
  131. ++PartialAliasCount;
  132. break;
  133. case AliasResult::MustAlias:
  134. PrintResults(AR, PrintMustAlias, *I1, *I2, F.getParent());
  135. ++MustAliasCount;
  136. break;
  137. }
  138. }
  139. }
  140. if (EvalAAMD) {
  141. // iterate over all pairs of load, store
  142. for (Value *Load : Loads) {
  143. for (Value *Store : Stores) {
  144. AliasResult AR = AA.alias(MemoryLocation::get(cast<LoadInst>(Load)),
  145. MemoryLocation::get(cast<StoreInst>(Store)));
  146. switch (AR) {
  147. case AliasResult::NoAlias:
  148. PrintLoadStoreResults(AR, PrintNoAlias, Load, Store, F.getParent());
  149. ++NoAliasCount;
  150. break;
  151. case AliasResult::MayAlias:
  152. PrintLoadStoreResults(AR, PrintMayAlias, Load, Store, F.getParent());
  153. ++MayAliasCount;
  154. break;
  155. case AliasResult::PartialAlias:
  156. PrintLoadStoreResults(AR, PrintPartialAlias, Load, Store, F.getParent());
  157. ++PartialAliasCount;
  158. break;
  159. case AliasResult::MustAlias:
  160. PrintLoadStoreResults(AR, PrintMustAlias, Load, Store, F.getParent());
  161. ++MustAliasCount;
  162. break;
  163. }
  164. }
  165. }
  166. // iterate over all pairs of store, store
  167. for (SetVector<Value *>::iterator I1 = Stores.begin(), E = Stores.end();
  168. I1 != E; ++I1) {
  169. for (SetVector<Value *>::iterator I2 = Stores.begin(); I2 != I1; ++I2) {
  170. AliasResult AR = AA.alias(MemoryLocation::get(cast<StoreInst>(*I1)),
  171. MemoryLocation::get(cast<StoreInst>(*I2)));
  172. switch (AR) {
  173. case AliasResult::NoAlias:
  174. PrintLoadStoreResults(AR, PrintNoAlias, *I1, *I2, F.getParent());
  175. ++NoAliasCount;
  176. break;
  177. case AliasResult::MayAlias:
  178. PrintLoadStoreResults(AR, PrintMayAlias, *I1, *I2, F.getParent());
  179. ++MayAliasCount;
  180. break;
  181. case AliasResult::PartialAlias:
  182. PrintLoadStoreResults(AR, PrintPartialAlias, *I1, *I2, F.getParent());
  183. ++PartialAliasCount;
  184. break;
  185. case AliasResult::MustAlias:
  186. PrintLoadStoreResults(AR, PrintMustAlias, *I1, *I2, F.getParent());
  187. ++MustAliasCount;
  188. break;
  189. }
  190. }
  191. }
  192. }
  193. // Mod/ref alias analysis: compare all pairs of calls and values
  194. for (CallBase *Call : Calls) {
  195. for (const auto &Pointer : Pointers) {
  196. LocationSize Size =
  197. LocationSize::precise(DL.getTypeStoreSize(Pointer.second));
  198. switch (AA.getModRefInfo(Call, Pointer.first, Size)) {
  199. case ModRefInfo::NoModRef:
  200. PrintModRefResults("NoModRef", PrintNoModRef, Call, Pointer,
  201. F.getParent());
  202. ++NoModRefCount;
  203. break;
  204. case ModRefInfo::Mod:
  205. PrintModRefResults("Just Mod", PrintMod, Call, Pointer, F.getParent());
  206. ++ModCount;
  207. break;
  208. case ModRefInfo::Ref:
  209. PrintModRefResults("Just Ref", PrintRef, Call, Pointer, F.getParent());
  210. ++RefCount;
  211. break;
  212. case ModRefInfo::ModRef:
  213. PrintModRefResults("Both ModRef", PrintModRef, Call, Pointer,
  214. F.getParent());
  215. ++ModRefCount;
  216. break;
  217. }
  218. }
  219. }
  220. // Mod/ref alias analysis: compare all pairs of calls
  221. for (CallBase *CallA : Calls) {
  222. for (CallBase *CallB : Calls) {
  223. if (CallA == CallB)
  224. continue;
  225. switch (AA.getModRefInfo(CallA, CallB)) {
  226. case ModRefInfo::NoModRef:
  227. PrintModRefResults("NoModRef", PrintNoModRef, CallA, CallB,
  228. F.getParent());
  229. ++NoModRefCount;
  230. break;
  231. case ModRefInfo::Mod:
  232. PrintModRefResults("Just Mod", PrintMod, CallA, CallB, F.getParent());
  233. ++ModCount;
  234. break;
  235. case ModRefInfo::Ref:
  236. PrintModRefResults("Just Ref", PrintRef, CallA, CallB, F.getParent());
  237. ++RefCount;
  238. break;
  239. case ModRefInfo::ModRef:
  240. PrintModRefResults("Both ModRef", PrintModRef, CallA, CallB,
  241. F.getParent());
  242. ++ModRefCount;
  243. break;
  244. }
  245. }
  246. }
  247. }
  248. static void PrintPercent(int64_t Num, int64_t Sum) {
  249. errs() << "(" << Num * 100LL / Sum << "." << ((Num * 1000LL / Sum) % 10)
  250. << "%)\n";
  251. }
  252. AAEvaluator::~AAEvaluator() {
  253. if (FunctionCount == 0)
  254. return;
  255. int64_t AliasSum =
  256. NoAliasCount + MayAliasCount + PartialAliasCount + MustAliasCount;
  257. errs() << "===== Alias Analysis Evaluator Report =====\n";
  258. if (AliasSum == 0) {
  259. errs() << " Alias Analysis Evaluator Summary: No pointers!\n";
  260. } else {
  261. errs() << " " << AliasSum << " Total Alias Queries Performed\n";
  262. errs() << " " << NoAliasCount << " no alias responses ";
  263. PrintPercent(NoAliasCount, AliasSum);
  264. errs() << " " << MayAliasCount << " may alias responses ";
  265. PrintPercent(MayAliasCount, AliasSum);
  266. errs() << " " << PartialAliasCount << " partial alias responses ";
  267. PrintPercent(PartialAliasCount, AliasSum);
  268. errs() << " " << MustAliasCount << " must alias responses ";
  269. PrintPercent(MustAliasCount, AliasSum);
  270. errs() << " Alias Analysis Evaluator Pointer Alias Summary: "
  271. << NoAliasCount * 100 / AliasSum << "%/"
  272. << MayAliasCount * 100 / AliasSum << "%/"
  273. << PartialAliasCount * 100 / AliasSum << "%/"
  274. << MustAliasCount * 100 / AliasSum << "%\n";
  275. }
  276. // Display the summary for mod/ref analysis
  277. int64_t ModRefSum = NoModRefCount + RefCount + ModCount + ModRefCount;
  278. if (ModRefSum == 0) {
  279. errs() << " Alias Analysis Mod/Ref Evaluator Summary: no "
  280. "mod/ref!\n";
  281. } else {
  282. errs() << " " << ModRefSum << " Total ModRef Queries Performed\n";
  283. errs() << " " << NoModRefCount << " no mod/ref responses ";
  284. PrintPercent(NoModRefCount, ModRefSum);
  285. errs() << " " << ModCount << " mod responses ";
  286. PrintPercent(ModCount, ModRefSum);
  287. errs() << " " << RefCount << " ref responses ";
  288. PrintPercent(RefCount, ModRefSum);
  289. errs() << " " << ModRefCount << " mod & ref responses ";
  290. PrintPercent(ModRefCount, ModRefSum);
  291. errs() << " Alias Analysis Evaluator Mod/Ref Summary: "
  292. << NoModRefCount * 100 / ModRefSum << "%/"
  293. << ModCount * 100 / ModRefSum << "%/" << RefCount * 100 / ModRefSum
  294. << "%/" << ModRefCount * 100 / ModRefSum << "%\n";
  295. }
  296. }
  297. namespace llvm {
  298. class AAEvalLegacyPass : public FunctionPass {
  299. std::unique_ptr<AAEvaluator> P;
  300. public:
  301. static char ID; // Pass identification, replacement for typeid
  302. AAEvalLegacyPass() : FunctionPass(ID) {
  303. initializeAAEvalLegacyPassPass(*PassRegistry::getPassRegistry());
  304. }
  305. void getAnalysisUsage(AnalysisUsage &AU) const override {
  306. AU.addRequired<AAResultsWrapperPass>();
  307. AU.setPreservesAll();
  308. }
  309. bool doInitialization(Module &M) override {
  310. P.reset(new AAEvaluator());
  311. return false;
  312. }
  313. bool runOnFunction(Function &F) override {
  314. P->runInternal(F, getAnalysis<AAResultsWrapperPass>().getAAResults());
  315. return false;
  316. }
  317. bool doFinalization(Module &M) override {
  318. P.reset();
  319. return false;
  320. }
  321. };
  322. }
  323. char AAEvalLegacyPass::ID = 0;
  324. INITIALIZE_PASS_BEGIN(AAEvalLegacyPass, "aa-eval",
  325. "Exhaustive Alias Analysis Precision Evaluator", false,
  326. true)
  327. INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
  328. INITIALIZE_PASS_END(AAEvalLegacyPass, "aa-eval",
  329. "Exhaustive Alias Analysis Precision Evaluator", false,
  330. true)
  331. FunctionPass *llvm::createAAEvalPass() { return new AAEvalLegacyPass(); }