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