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/Support/CommandLine.h"
18 #include "llvm/Support/raw_ostream.h"
21 static cl::opt
<bool> PrintAll("print-all-alias-modref-info", cl::ReallyHidden
);
23 static cl::opt
<bool> PrintNoAlias("print-no-aliases", cl::ReallyHidden
);
24 static cl::opt
<bool> PrintMayAlias("print-may-aliases", cl::ReallyHidden
);
25 static cl::opt
<bool> PrintPartialAlias("print-partial-aliases", cl::ReallyHidden
);
26 static cl::opt
<bool> PrintMustAlias("print-must-aliases", cl::ReallyHidden
);
28 static cl::opt
<bool> PrintNoModRef("print-no-modref", cl::ReallyHidden
);
29 static cl::opt
<bool> PrintRef("print-ref", cl::ReallyHidden
);
30 static cl::opt
<bool> PrintMod("print-mod", cl::ReallyHidden
);
31 static cl::opt
<bool> PrintModRef("print-modref", cl::ReallyHidden
);
33 static cl::opt
<bool> EvalAAMD("evaluate-aa-metadata", cl::ReallyHidden
);
35 static void PrintResults(AliasResult AR
, bool P
,
36 std::pair
<const Value
*, Type
*> Loc1
,
37 std::pair
<const Value
*, Type
*> Loc2
,
40 Type
*Ty1
= Loc1
.second
, *Ty2
= Loc2
.second
;
41 unsigned AS1
= Loc1
.first
->getType()->getPointerAddressSpace();
42 unsigned AS2
= Loc2
.first
->getType()->getPointerAddressSpace();
45 raw_string_ostream
os1(o1
), os2(o2
);
46 Loc1
.first
->printAsOperand(os1
, false, M
);
47 Loc2
.first
->printAsOperand(os2
, false, M
);
54 // Change offset sign for the local AR, for printing only.
57 errs() << " " << AR
<< ":\t";
58 Ty1
->print(errs(), false, /* NoDetails */ true);
60 errs() << " addrspace(" << AS1
<< ")";
61 errs() << "* " << o1
<< ", ";
62 Ty2
->print(errs(), false, /* NoDetails */ true);
64 errs() << " addrspace(" << AS2
<< ")";
65 errs() << "* " << o2
<< "\n";
69 static inline void PrintModRefResults(
70 const char *Msg
, bool P
, Instruction
*I
,
71 std::pair
<const Value
*, Type
*> Loc
, Module
*M
) {
73 errs() << " " << Msg
<< ": Ptr: ";
74 Loc
.second
->print(errs(), false, /* NoDetails */ true);
76 Loc
.first
->printAsOperand(errs(), false, M
);
77 errs() << "\t<->" << *I
<< '\n';
81 static inline void PrintModRefResults(const char *Msg
, bool P
, CallBase
*CallA
,
82 CallBase
*CallB
, Module
*M
) {
84 errs() << " " << Msg
<< ": " << *CallA
<< " <-> " << *CallB
<< '\n';
88 static inline void PrintLoadStoreResults(AliasResult AR
, bool P
,
89 const Value
*V1
, const Value
*V2
,
92 errs() << " " << AR
<< ": " << *V1
<< " <-> " << *V2
<< '\n';
96 PreservedAnalyses
AAEvaluator::run(Function
&F
, FunctionAnalysisManager
&AM
) {
97 runInternal(F
, AM
.getResult
<AAManager
>(F
));
98 return PreservedAnalyses::all();
101 void AAEvaluator::runInternal(Function
&F
, AAResults
&AA
) {
102 const DataLayout
&DL
= F
.getParent()->getDataLayout();
106 SetVector
<std::pair
<const Value
*, Type
*>> Pointers
;
107 SmallSetVector
<CallBase
*, 16> Calls
;
108 SetVector
<Value
*> Loads
;
109 SetVector
<Value
*> Stores
;
111 for (Instruction
&Inst
: instructions(F
)) {
112 if (auto *LI
= dyn_cast
<LoadInst
>(&Inst
)) {
113 Pointers
.insert({LI
->getPointerOperand(), LI
->getType()});
115 } else if (auto *SI
= dyn_cast
<StoreInst
>(&Inst
)) {
116 Pointers
.insert({SI
->getPointerOperand(),
117 SI
->getValueOperand()->getType()});
119 } else if (auto *CB
= dyn_cast
<CallBase
>(&Inst
))
123 if (PrintAll
|| PrintNoAlias
|| PrintMayAlias
|| PrintPartialAlias
||
124 PrintMustAlias
|| PrintNoModRef
|| PrintMod
|| PrintRef
|| PrintModRef
)
125 errs() << "Function: " << F
.getName() << ": " << Pointers
.size()
126 << " pointers, " << Calls
.size() << " call sites\n";
128 // iterate over the worklist, and run the full (n^2)/2 disambiguations
129 for (auto I1
= Pointers
.begin(), E
= Pointers
.end(); I1
!= E
; ++I1
) {
130 LocationSize Size1
= LocationSize::precise(DL
.getTypeStoreSize(I1
->second
));
131 for (auto I2
= Pointers
.begin(); I2
!= I1
; ++I2
) {
133 LocationSize::precise(DL
.getTypeStoreSize(I2
->second
));
134 AliasResult AR
= AA
.alias(I1
->first
, Size1
, I2
->first
, Size2
);
136 case AliasResult::NoAlias
:
137 PrintResults(AR
, PrintNoAlias
, *I1
, *I2
, F
.getParent());
140 case AliasResult::MayAlias
:
141 PrintResults(AR
, PrintMayAlias
, *I1
, *I2
, F
.getParent());
144 case AliasResult::PartialAlias
:
145 PrintResults(AR
, PrintPartialAlias
, *I1
, *I2
, F
.getParent());
148 case AliasResult::MustAlias
:
149 PrintResults(AR
, PrintMustAlias
, *I1
, *I2
, F
.getParent());
157 // iterate over all pairs of load, store
158 for (Value
*Load
: Loads
) {
159 for (Value
*Store
: Stores
) {
160 AliasResult AR
= AA
.alias(MemoryLocation::get(cast
<LoadInst
>(Load
)),
161 MemoryLocation::get(cast
<StoreInst
>(Store
)));
163 case AliasResult::NoAlias
:
164 PrintLoadStoreResults(AR
, PrintNoAlias
, Load
, Store
, F
.getParent());
167 case AliasResult::MayAlias
:
168 PrintLoadStoreResults(AR
, PrintMayAlias
, Load
, Store
, F
.getParent());
171 case AliasResult::PartialAlias
:
172 PrintLoadStoreResults(AR
, PrintPartialAlias
, Load
, Store
, F
.getParent());
175 case AliasResult::MustAlias
:
176 PrintLoadStoreResults(AR
, PrintMustAlias
, Load
, Store
, F
.getParent());
183 // iterate over all pairs of store, store
184 for (SetVector
<Value
*>::iterator I1
= Stores
.begin(), E
= Stores
.end();
186 for (SetVector
<Value
*>::iterator I2
= Stores
.begin(); I2
!= I1
; ++I2
) {
187 AliasResult AR
= AA
.alias(MemoryLocation::get(cast
<StoreInst
>(*I1
)),
188 MemoryLocation::get(cast
<StoreInst
>(*I2
)));
190 case AliasResult::NoAlias
:
191 PrintLoadStoreResults(AR
, PrintNoAlias
, *I1
, *I2
, F
.getParent());
194 case AliasResult::MayAlias
:
195 PrintLoadStoreResults(AR
, PrintMayAlias
, *I1
, *I2
, F
.getParent());
198 case AliasResult::PartialAlias
:
199 PrintLoadStoreResults(AR
, PrintPartialAlias
, *I1
, *I2
, F
.getParent());
202 case AliasResult::MustAlias
:
203 PrintLoadStoreResults(AR
, PrintMustAlias
, *I1
, *I2
, F
.getParent());
211 // Mod/ref alias analysis: compare all pairs of calls and values
212 for (CallBase
*Call
: Calls
) {
213 for (const auto &Pointer
: Pointers
) {
215 LocationSize::precise(DL
.getTypeStoreSize(Pointer
.second
));
216 switch (AA
.getModRefInfo(Call
, Pointer
.first
, Size
)) {
217 case ModRefInfo::NoModRef
:
218 PrintModRefResults("NoModRef", PrintNoModRef
, Call
, Pointer
,
222 case ModRefInfo::Mod
:
223 PrintModRefResults("Just Mod", PrintMod
, Call
, Pointer
, F
.getParent());
226 case ModRefInfo::Ref
:
227 PrintModRefResults("Just Ref", PrintRef
, Call
, Pointer
, F
.getParent());
230 case ModRefInfo::ModRef
:
231 PrintModRefResults("Both ModRef", PrintModRef
, Call
, Pointer
,
239 // Mod/ref alias analysis: compare all pairs of calls
240 for (CallBase
*CallA
: Calls
) {
241 for (CallBase
*CallB
: Calls
) {
244 switch (AA
.getModRefInfo(CallA
, CallB
)) {
245 case ModRefInfo::NoModRef
:
246 PrintModRefResults("NoModRef", PrintNoModRef
, CallA
, CallB
,
250 case ModRefInfo::Mod
:
251 PrintModRefResults("Just Mod", PrintMod
, CallA
, CallB
, F
.getParent());
254 case ModRefInfo::Ref
:
255 PrintModRefResults("Just Ref", PrintRef
, CallA
, CallB
, F
.getParent());
258 case ModRefInfo::ModRef
:
259 PrintModRefResults("Both ModRef", PrintModRef
, CallA
, CallB
,
268 static void PrintPercent(int64_t Num
, int64_t Sum
) {
269 errs() << "(" << Num
* 100LL / Sum
<< "." << ((Num
* 1000LL / Sum
) % 10)
273 AAEvaluator::~AAEvaluator() {
274 if (FunctionCount
== 0)
278 NoAliasCount
+ MayAliasCount
+ PartialAliasCount
+ MustAliasCount
;
279 errs() << "===== Alias Analysis Evaluator Report =====\n";
281 errs() << " Alias Analysis Evaluator Summary: No pointers!\n";
283 errs() << " " << AliasSum
<< " Total Alias Queries Performed\n";
284 errs() << " " << NoAliasCount
<< " no alias responses ";
285 PrintPercent(NoAliasCount
, AliasSum
);
286 errs() << " " << MayAliasCount
<< " may alias responses ";
287 PrintPercent(MayAliasCount
, AliasSum
);
288 errs() << " " << PartialAliasCount
<< " partial alias responses ";
289 PrintPercent(PartialAliasCount
, AliasSum
);
290 errs() << " " << MustAliasCount
<< " must alias responses ";
291 PrintPercent(MustAliasCount
, AliasSum
);
292 errs() << " Alias Analysis Evaluator Pointer Alias Summary: "
293 << NoAliasCount
* 100 / AliasSum
<< "%/"
294 << MayAliasCount
* 100 / AliasSum
<< "%/"
295 << PartialAliasCount
* 100 / AliasSum
<< "%/"
296 << MustAliasCount
* 100 / AliasSum
<< "%\n";
299 // Display the summary for mod/ref analysis
300 int64_t ModRefSum
= NoModRefCount
+ RefCount
+ ModCount
+ ModRefCount
;
301 if (ModRefSum
== 0) {
302 errs() << " Alias Analysis Mod/Ref Evaluator Summary: no "
305 errs() << " " << ModRefSum
<< " Total ModRef Queries Performed\n";
306 errs() << " " << NoModRefCount
<< " no mod/ref responses ";
307 PrintPercent(NoModRefCount
, ModRefSum
);
308 errs() << " " << ModCount
<< " mod responses ";
309 PrintPercent(ModCount
, ModRefSum
);
310 errs() << " " << RefCount
<< " ref responses ";
311 PrintPercent(RefCount
, ModRefSum
);
312 errs() << " " << ModRefCount
<< " mod & ref responses ";
313 PrintPercent(ModRefCount
, ModRefSum
);
314 errs() << " Alias Analysis Evaluator Mod/Ref Summary: "
315 << NoModRefCount
* 100 / ModRefSum
<< "%/"
316 << ModCount
* 100 / ModRefSum
<< "%/" << RefCount
* 100 / ModRefSum
317 << "%/" << ModRefCount
* 100 / ModRefSum
<< "%\n";