1 //===- AliasAnalysisEvaluator.cpp - Alias Analysis Accuracy Evaluator -----===//
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
7 //===----------------------------------------------------------------------===//
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"
23 static cl::opt
<bool> PrintAll("print-all-alias-modref-info", cl::ReallyHidden
);
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
);
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
);
35 static cl::opt
<bool> EvalAAMD("evaluate-aa-metadata", cl::ReallyHidden
);
37 static void PrintResults(AliasResult AR
, bool P
,
38 std::pair
<const Value
*, Type
*> Loc1
,
39 std::pair
<const Value
*, Type
*> Loc2
,
42 Type
*Ty1
= Loc1
.second
, *Ty2
= Loc2
.second
;
43 unsigned AS1
= Loc1
.first
->getType()->getPointerAddressSpace();
44 unsigned AS2
= Loc2
.first
->getType()->getPointerAddressSpace();
47 raw_string_ostream
os1(o1
), os2(o2
);
48 Loc1
.first
->printAsOperand(os1
, false, M
);
49 Loc2
.first
->printAsOperand(os2
, false, M
);
56 // Change offset sign for the local AR, for printing only.
59 errs() << " " << AR
<< ":\t";
60 Ty1
->print(errs(), false, /* NoDetails */ true);
62 errs() << " addrspace(" << AS1
<< ")";
63 errs() << "* " << o1
<< ", ";
64 Ty2
->print(errs(), false, /* NoDetails */ true);
66 errs() << " addrspace(" << AS2
<< ")";
67 errs() << "* " << o2
<< "\n";
71 static inline void PrintModRefResults(
72 const char *Msg
, bool P
, Instruction
*I
,
73 std::pair
<const Value
*, Type
*> Loc
, Module
*M
) {
75 errs() << " " << Msg
<< ": Ptr: ";
76 Loc
.second
->print(errs(), false, /* NoDetails */ true);
78 Loc
.first
->printAsOperand(errs(), false, M
);
79 errs() << "\t<->" << *I
<< '\n';
83 static inline void PrintModRefResults(const char *Msg
, bool P
, CallBase
*CallA
,
84 CallBase
*CallB
, Module
*M
) {
86 errs() << " " << Msg
<< ": " << *CallA
<< " <-> " << *CallB
<< '\n';
90 static inline void PrintLoadStoreResults(AliasResult AR
, bool P
,
91 const Value
*V1
, const Value
*V2
,
94 errs() << " " << AR
<< ": " << *V1
<< " <-> " << *V2
<< '\n';
98 PreservedAnalyses
AAEvaluator::run(Function
&F
, FunctionAnalysisManager
&AM
) {
99 runInternal(F
, AM
.getResult
<AAManager
>(F
));
100 return PreservedAnalyses::all();
103 void AAEvaluator::runInternal(Function
&F
, AAResults
&AA
) {
104 const DataLayout
&DL
= F
.getParent()->getDataLayout();
108 SetVector
<std::pair
<const Value
*, Type
*>> Pointers
;
109 SmallSetVector
<CallBase
*, 16> Calls
;
110 SetVector
<Value
*> Loads
;
111 SetVector
<Value
*> Stores
;
113 for (Instruction
&Inst
: instructions(F
)) {
114 if (auto *LI
= dyn_cast
<LoadInst
>(&Inst
)) {
115 Pointers
.insert({LI
->getPointerOperand(), LI
->getType()});
117 } else if (auto *SI
= dyn_cast
<StoreInst
>(&Inst
)) {
118 Pointers
.insert({SI
->getPointerOperand(),
119 SI
->getValueOperand()->getType()});
121 } else if (auto *CB
= dyn_cast
<CallBase
>(&Inst
))
125 if (PrintAll
|| PrintNoAlias
|| PrintMayAlias
|| PrintPartialAlias
||
126 PrintMustAlias
|| PrintNoModRef
|| PrintMod
|| PrintRef
|| PrintModRef
)
127 errs() << "Function: " << F
.getName() << ": " << Pointers
.size()
128 << " pointers, " << Calls
.size() << " call sites\n";
130 // iterate over the worklist, and run the full (n^2)/2 disambiguations
131 for (auto I1
= Pointers
.begin(), E
= Pointers
.end(); I1
!= E
; ++I1
) {
132 LocationSize Size1
= LocationSize::precise(DL
.getTypeStoreSize(I1
->second
));
133 for (auto I2
= Pointers
.begin(); I2
!= I1
; ++I2
) {
135 LocationSize::precise(DL
.getTypeStoreSize(I2
->second
));
136 AliasResult AR
= AA
.alias(I1
->first
, Size1
, I2
->first
, Size2
);
138 case AliasResult::NoAlias
:
139 PrintResults(AR
, PrintNoAlias
, *I1
, *I2
, F
.getParent());
142 case AliasResult::MayAlias
:
143 PrintResults(AR
, PrintMayAlias
, *I1
, *I2
, F
.getParent());
146 case AliasResult::PartialAlias
:
147 PrintResults(AR
, PrintPartialAlias
, *I1
, *I2
, F
.getParent());
150 case AliasResult::MustAlias
:
151 PrintResults(AR
, PrintMustAlias
, *I1
, *I2
, F
.getParent());
159 // iterate over all pairs of load, store
160 for (Value
*Load
: Loads
) {
161 for (Value
*Store
: Stores
) {
162 AliasResult AR
= AA
.alias(MemoryLocation::get(cast
<LoadInst
>(Load
)),
163 MemoryLocation::get(cast
<StoreInst
>(Store
)));
165 case AliasResult::NoAlias
:
166 PrintLoadStoreResults(AR
, PrintNoAlias
, Load
, Store
, F
.getParent());
169 case AliasResult::MayAlias
:
170 PrintLoadStoreResults(AR
, PrintMayAlias
, Load
, Store
, F
.getParent());
173 case AliasResult::PartialAlias
:
174 PrintLoadStoreResults(AR
, PrintPartialAlias
, Load
, Store
, F
.getParent());
177 case AliasResult::MustAlias
:
178 PrintLoadStoreResults(AR
, PrintMustAlias
, Load
, Store
, F
.getParent());
185 // iterate over all pairs of store, store
186 for (SetVector
<Value
*>::iterator I1
= Stores
.begin(), E
= Stores
.end();
188 for (SetVector
<Value
*>::iterator I2
= Stores
.begin(); I2
!= I1
; ++I2
) {
189 AliasResult AR
= AA
.alias(MemoryLocation::get(cast
<StoreInst
>(*I1
)),
190 MemoryLocation::get(cast
<StoreInst
>(*I2
)));
192 case AliasResult::NoAlias
:
193 PrintLoadStoreResults(AR
, PrintNoAlias
, *I1
, *I2
, F
.getParent());
196 case AliasResult::MayAlias
:
197 PrintLoadStoreResults(AR
, PrintMayAlias
, *I1
, *I2
, F
.getParent());
200 case AliasResult::PartialAlias
:
201 PrintLoadStoreResults(AR
, PrintPartialAlias
, *I1
, *I2
, F
.getParent());
204 case AliasResult::MustAlias
:
205 PrintLoadStoreResults(AR
, PrintMustAlias
, *I1
, *I2
, F
.getParent());
213 // Mod/ref alias analysis: compare all pairs of calls and values
214 for (CallBase
*Call
: Calls
) {
215 for (const auto &Pointer
: Pointers
) {
217 LocationSize::precise(DL
.getTypeStoreSize(Pointer
.second
));
218 switch (AA
.getModRefInfo(Call
, Pointer
.first
, Size
)) {
219 case ModRefInfo::NoModRef
:
220 PrintModRefResults("NoModRef", PrintNoModRef
, Call
, Pointer
,
224 case ModRefInfo::Mod
:
225 PrintModRefResults("Just Mod", PrintMod
, Call
, Pointer
, F
.getParent());
228 case ModRefInfo::Ref
:
229 PrintModRefResults("Just Ref", PrintRef
, Call
, Pointer
, F
.getParent());
232 case ModRefInfo::ModRef
:
233 PrintModRefResults("Both ModRef", PrintModRef
, Call
, Pointer
,
241 // Mod/ref alias analysis: compare all pairs of calls
242 for (CallBase
*CallA
: Calls
) {
243 for (CallBase
*CallB
: Calls
) {
246 switch (AA
.getModRefInfo(CallA
, CallB
)) {
247 case ModRefInfo::NoModRef
:
248 PrintModRefResults("NoModRef", PrintNoModRef
, CallA
, CallB
,
252 case ModRefInfo::Mod
:
253 PrintModRefResults("Just Mod", PrintMod
, CallA
, CallB
, F
.getParent());
256 case ModRefInfo::Ref
:
257 PrintModRefResults("Just Ref", PrintRef
, CallA
, CallB
, F
.getParent());
260 case ModRefInfo::ModRef
:
261 PrintModRefResults("Both ModRef", PrintModRef
, CallA
, CallB
,
270 static void PrintPercent(int64_t Num
, int64_t Sum
) {
271 errs() << "(" << Num
* 100LL / Sum
<< "." << ((Num
* 1000LL / Sum
) % 10)
275 AAEvaluator::~AAEvaluator() {
276 if (FunctionCount
== 0)
280 NoAliasCount
+ MayAliasCount
+ PartialAliasCount
+ MustAliasCount
;
281 errs() << "===== Alias Analysis Evaluator Report =====\n";
283 errs() << " Alias Analysis Evaluator Summary: No pointers!\n";
285 errs() << " " << AliasSum
<< " Total Alias Queries Performed\n";
286 errs() << " " << NoAliasCount
<< " no alias responses ";
287 PrintPercent(NoAliasCount
, AliasSum
);
288 errs() << " " << MayAliasCount
<< " may alias responses ";
289 PrintPercent(MayAliasCount
, AliasSum
);
290 errs() << " " << PartialAliasCount
<< " partial alias responses ";
291 PrintPercent(PartialAliasCount
, AliasSum
);
292 errs() << " " << MustAliasCount
<< " must alias responses ";
293 PrintPercent(MustAliasCount
, AliasSum
);
294 errs() << " Alias Analysis Evaluator Pointer Alias Summary: "
295 << NoAliasCount
* 100 / AliasSum
<< "%/"
296 << MayAliasCount
* 100 / AliasSum
<< "%/"
297 << PartialAliasCount
* 100 / AliasSum
<< "%/"
298 << MustAliasCount
* 100 / AliasSum
<< "%\n";
301 // Display the summary for mod/ref analysis
302 int64_t ModRefSum
= NoModRefCount
+ RefCount
+ ModCount
+ ModRefCount
;
303 if (ModRefSum
== 0) {
304 errs() << " Alias Analysis Mod/Ref Evaluator Summary: no "
307 errs() << " " << ModRefSum
<< " Total ModRef Queries Performed\n";
308 errs() << " " << NoModRefCount
<< " no mod/ref responses ";
309 PrintPercent(NoModRefCount
, ModRefSum
);
310 errs() << " " << ModCount
<< " mod responses ";
311 PrintPercent(ModCount
, ModRefSum
);
312 errs() << " " << RefCount
<< " ref responses ";
313 PrintPercent(RefCount
, ModRefSum
);
314 errs() << " " << ModRefCount
<< " mod & ref responses ";
315 PrintPercent(ModRefCount
, ModRefSum
);
316 errs() << " Alias Analysis Evaluator Mod/Ref Summary: "
317 << NoModRefCount
* 100 / ModRefSum
<< "%/"
318 << ModCount
* 100 / ModRefSum
<< "%/" << RefCount
* 100 / ModRefSum
319 << "%/" << ModRefCount
* 100 / ModRefSum
<< "%\n";
324 class AAEvalLegacyPass
: public FunctionPass
{
325 std::unique_ptr
<AAEvaluator
> P
;
328 static char ID
; // Pass identification, replacement for typeid
329 AAEvalLegacyPass() : FunctionPass(ID
) {
330 initializeAAEvalLegacyPassPass(*PassRegistry::getPassRegistry());
333 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
334 AU
.addRequired
<AAResultsWrapperPass
>();
335 AU
.setPreservesAll();
338 bool doInitialization(Module
&M
) override
{
339 P
.reset(new AAEvaluator());
343 bool runOnFunction(Function
&F
) override
{
344 P
->runInternal(F
, getAnalysis
<AAResultsWrapperPass
>().getAAResults());
347 bool doFinalization(Module
&M
) override
{
354 char AAEvalLegacyPass::ID
= 0;
355 INITIALIZE_PASS_BEGIN(AAEvalLegacyPass
, "aa-eval",
356 "Exhaustive Alias Analysis Precision Evaluator", false,
358 INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass
)
359 INITIALIZE_PASS_END(AAEvalLegacyPass
, "aa-eval",
360 "Exhaustive Alias Analysis Precision Evaluator", false,
363 FunctionPass
*llvm::createAAEvalPass() { return new AAEvalLegacyPass(); }