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/Constants.h"
13 #include "llvm/IR/DataLayout.h"
14 #include "llvm/IR/DerivedTypes.h"
15 #include "llvm/IR/Function.h"
16 #include "llvm/IR/InstIterator.h"
17 #include "llvm/IR/Instructions.h"
18 #include "llvm/IR/Module.h"
19 #include "llvm/Pass.h"
20 #include "llvm/Support/CommandLine.h"
21 #include "llvm/Support/Debug.h"
22 #include "llvm/Support/raw_ostream.h"
25 static cl::opt
<bool> PrintAll("print-all-alias-modref-info", cl::ReallyHidden
);
27 static cl::opt
<bool> PrintNoAlias("print-no-aliases", cl::ReallyHidden
);
28 static cl::opt
<bool> PrintMayAlias("print-may-aliases", cl::ReallyHidden
);
29 static cl::opt
<bool> PrintPartialAlias("print-partial-aliases", cl::ReallyHidden
);
30 static cl::opt
<bool> PrintMustAlias("print-must-aliases", cl::ReallyHidden
);
32 static cl::opt
<bool> PrintNoModRef("print-no-modref", cl::ReallyHidden
);
33 static cl::opt
<bool> PrintRef("print-ref", cl::ReallyHidden
);
34 static cl::opt
<bool> PrintMod("print-mod", cl::ReallyHidden
);
35 static cl::opt
<bool> PrintModRef("print-modref", cl::ReallyHidden
);
36 static cl::opt
<bool> PrintMust("print-must", cl::ReallyHidden
);
37 static cl::opt
<bool> PrintMustRef("print-mustref", cl::ReallyHidden
);
38 static cl::opt
<bool> PrintMustMod("print-mustmod", cl::ReallyHidden
);
39 static cl::opt
<bool> PrintMustModRef("print-mustmodref", cl::ReallyHidden
);
41 static cl::opt
<bool> EvalAAMD("evaluate-aa-metadata", cl::ReallyHidden
);
43 static void PrintResults(AliasResult AR
, bool P
, const Value
*V1
,
44 const Value
*V2
, const Module
*M
) {
48 raw_string_ostream
os1(o1
), os2(o2
);
49 V1
->printAsOperand(os1
, true, M
);
50 V2
->printAsOperand(os2
, true, M
);
55 errs() << " " << AR
<< ":\t" << o1
<< ", " << o2
<< "\n";
59 static inline void PrintModRefResults(const char *Msg
, bool P
, Instruction
*I
,
60 Value
*Ptr
, Module
*M
) {
62 errs() << " " << Msg
<< ": Ptr: ";
63 Ptr
->printAsOperand(errs(), true, M
);
64 errs() << "\t<->" << *I
<< '\n';
68 static inline void PrintModRefResults(const char *Msg
, bool P
, CallBase
*CallA
,
69 CallBase
*CallB
, Module
*M
) {
71 errs() << " " << Msg
<< ": " << *CallA
<< " <-> " << *CallB
<< '\n';
75 static inline void PrintLoadStoreResults(AliasResult AR
, bool P
,
76 const Value
*V1
, const Value
*V2
,
79 errs() << " " << AR
<< ": " << *V1
<< " <-> " << *V2
<< '\n';
83 static inline bool isInterestingPointer(Value
*V
) {
84 return V
->getType()->isPointerTy()
85 && !isa
<ConstantPointerNull
>(V
);
88 PreservedAnalyses
AAEvaluator::run(Function
&F
, FunctionAnalysisManager
&AM
) {
89 runInternal(F
, AM
.getResult
<AAManager
>(F
));
90 return PreservedAnalyses::all();
93 void AAEvaluator::runInternal(Function
&F
, AAResults
&AA
) {
94 const DataLayout
&DL
= F
.getParent()->getDataLayout();
98 SetVector
<Value
*> Pointers
;
99 SmallSetVector
<CallBase
*, 16> Calls
;
100 SetVector
<Value
*> Loads
;
101 SetVector
<Value
*> Stores
;
103 for (auto &I
: F
.args())
104 if (I
.getType()->isPointerTy()) // Add all pointer arguments.
107 for (inst_iterator I
= inst_begin(F
), E
= inst_end(F
); I
!= E
; ++I
) {
108 if (I
->getType()->isPointerTy()) // Add all pointer instructions.
109 Pointers
.insert(&*I
);
110 if (EvalAAMD
&& isa
<LoadInst
>(&*I
))
112 if (EvalAAMD
&& isa
<StoreInst
>(&*I
))
114 Instruction
&Inst
= *I
;
115 if (auto *Call
= dyn_cast
<CallBase
>(&Inst
)) {
116 Value
*Callee
= Call
->getCalledValue();
117 // Skip actual functions for direct function calls.
118 if (!isa
<Function
>(Callee
) && isInterestingPointer(Callee
))
119 Pointers
.insert(Callee
);
121 for (Use
&DataOp
: Call
->data_ops())
122 if (isInterestingPointer(DataOp
))
123 Pointers
.insert(DataOp
);
126 // Consider all operands.
127 for (Instruction::op_iterator OI
= Inst
.op_begin(), OE
= Inst
.op_end();
129 if (isInterestingPointer(*OI
))
130 Pointers
.insert(*OI
);
134 if (PrintAll
|| PrintNoAlias
|| PrintMayAlias
|| PrintPartialAlias
||
135 PrintMustAlias
|| PrintNoModRef
|| PrintMod
|| PrintRef
|| PrintModRef
)
136 errs() << "Function: " << F
.getName() << ": " << Pointers
.size()
137 << " pointers, " << Calls
.size() << " call sites\n";
139 // iterate over the worklist, and run the full (n^2)/2 disambiguations
140 for (SetVector
<Value
*>::iterator I1
= Pointers
.begin(), E
= Pointers
.end();
142 auto I1Size
= LocationSize::unknown();
143 Type
*I1ElTy
= cast
<PointerType
>((*I1
)->getType())->getElementType();
144 if (I1ElTy
->isSized())
145 I1Size
= LocationSize::precise(DL
.getTypeStoreSize(I1ElTy
));
147 for (SetVector
<Value
*>::iterator I2
= Pointers
.begin(); I2
!= I1
; ++I2
) {
148 auto I2Size
= LocationSize::unknown();
149 Type
*I2ElTy
= cast
<PointerType
>((*I2
)->getType())->getElementType();
150 if (I2ElTy
->isSized())
151 I2Size
= LocationSize::precise(DL
.getTypeStoreSize(I2ElTy
));
153 AliasResult AR
= AA
.alias(*I1
, I1Size
, *I2
, I2Size
);
156 PrintResults(AR
, PrintNoAlias
, *I1
, *I2
, F
.getParent());
160 PrintResults(AR
, PrintMayAlias
, *I1
, *I2
, F
.getParent());
164 PrintResults(AR
, PrintPartialAlias
, *I1
, *I2
, F
.getParent());
168 PrintResults(AR
, PrintMustAlias
, *I1
, *I2
, F
.getParent());
176 // iterate over all pairs of load, store
177 for (Value
*Load
: Loads
) {
178 for (Value
*Store
: Stores
) {
179 AliasResult AR
= AA
.alias(MemoryLocation::get(cast
<LoadInst
>(Load
)),
180 MemoryLocation::get(cast
<StoreInst
>(Store
)));
183 PrintLoadStoreResults(AR
, PrintNoAlias
, Load
, Store
, F
.getParent());
187 PrintLoadStoreResults(AR
, PrintMayAlias
, Load
, Store
, F
.getParent());
191 PrintLoadStoreResults(AR
, PrintPartialAlias
, Load
, Store
, F
.getParent());
195 PrintLoadStoreResults(AR
, PrintMustAlias
, Load
, Store
, F
.getParent());
202 // iterate over all pairs of store, store
203 for (SetVector
<Value
*>::iterator I1
= Stores
.begin(), E
= Stores
.end();
205 for (SetVector
<Value
*>::iterator I2
= Stores
.begin(); I2
!= I1
; ++I2
) {
206 AliasResult AR
= AA
.alias(MemoryLocation::get(cast
<StoreInst
>(*I1
)),
207 MemoryLocation::get(cast
<StoreInst
>(*I2
)));
210 PrintLoadStoreResults(AR
, PrintNoAlias
, *I1
, *I2
, F
.getParent());
214 PrintLoadStoreResults(AR
, PrintMayAlias
, *I1
, *I2
, F
.getParent());
218 PrintLoadStoreResults(AR
, PrintPartialAlias
, *I1
, *I2
, F
.getParent());
222 PrintLoadStoreResults(AR
, PrintMustAlias
, *I1
, *I2
, F
.getParent());
230 // Mod/ref alias analysis: compare all pairs of calls and values
231 for (CallBase
*Call
: Calls
) {
232 for (auto Pointer
: Pointers
) {
233 auto Size
= LocationSize::unknown();
234 Type
*ElTy
= cast
<PointerType
>(Pointer
->getType())->getElementType();
236 Size
= LocationSize::precise(DL
.getTypeStoreSize(ElTy
));
238 switch (AA
.getModRefInfo(Call
, Pointer
, Size
)) {
239 case ModRefInfo::NoModRef
:
240 PrintModRefResults("NoModRef", PrintNoModRef
, Call
, Pointer
,
244 case ModRefInfo::Mod
:
245 PrintModRefResults("Just Mod", PrintMod
, Call
, Pointer
, F
.getParent());
248 case ModRefInfo::Ref
:
249 PrintModRefResults("Just Ref", PrintRef
, Call
, Pointer
, F
.getParent());
252 case ModRefInfo::ModRef
:
253 PrintModRefResults("Both ModRef", PrintModRef
, Call
, Pointer
,
257 case ModRefInfo::Must
:
258 PrintModRefResults("Must", PrintMust
, Call
, Pointer
, F
.getParent());
261 case ModRefInfo::MustMod
:
262 PrintModRefResults("Just Mod (MustAlias)", PrintMustMod
, Call
, Pointer
,
266 case ModRefInfo::MustRef
:
267 PrintModRefResults("Just Ref (MustAlias)", PrintMustRef
, Call
, Pointer
,
271 case ModRefInfo::MustModRef
:
272 PrintModRefResults("Both ModRef (MustAlias)", PrintMustModRef
, Call
,
273 Pointer
, F
.getParent());
280 // Mod/ref alias analysis: compare all pairs of calls
281 for (CallBase
*CallA
: Calls
) {
282 for (CallBase
*CallB
: Calls
) {
285 switch (AA
.getModRefInfo(CallA
, CallB
)) {
286 case ModRefInfo::NoModRef
:
287 PrintModRefResults("NoModRef", PrintNoModRef
, CallA
, CallB
,
291 case ModRefInfo::Mod
:
292 PrintModRefResults("Just Mod", PrintMod
, CallA
, CallB
, F
.getParent());
295 case ModRefInfo::Ref
:
296 PrintModRefResults("Just Ref", PrintRef
, CallA
, CallB
, F
.getParent());
299 case ModRefInfo::ModRef
:
300 PrintModRefResults("Both ModRef", PrintModRef
, CallA
, CallB
,
304 case ModRefInfo::Must
:
305 PrintModRefResults("Must", PrintMust
, CallA
, CallB
, F
.getParent());
308 case ModRefInfo::MustMod
:
309 PrintModRefResults("Just Mod (MustAlias)", PrintMustMod
, CallA
, CallB
,
313 case ModRefInfo::MustRef
:
314 PrintModRefResults("Just Ref (MustAlias)", PrintMustRef
, CallA
, CallB
,
318 case ModRefInfo::MustModRef
:
319 PrintModRefResults("Both ModRef (MustAlias)", PrintMustModRef
, CallA
,
320 CallB
, F
.getParent());
328 static void PrintPercent(int64_t Num
, int64_t Sum
) {
329 errs() << "(" << Num
* 100LL / Sum
<< "." << ((Num
* 1000LL / Sum
) % 10)
333 AAEvaluator::~AAEvaluator() {
334 if (FunctionCount
== 0)
338 NoAliasCount
+ MayAliasCount
+ PartialAliasCount
+ MustAliasCount
;
339 errs() << "===== Alias Analysis Evaluator Report =====\n";
341 errs() << " Alias Analysis Evaluator Summary: No pointers!\n";
343 errs() << " " << AliasSum
<< " Total Alias Queries Performed\n";
344 errs() << " " << NoAliasCount
<< " no alias responses ";
345 PrintPercent(NoAliasCount
, AliasSum
);
346 errs() << " " << MayAliasCount
<< " may alias responses ";
347 PrintPercent(MayAliasCount
, AliasSum
);
348 errs() << " " << PartialAliasCount
<< " partial alias responses ";
349 PrintPercent(PartialAliasCount
, AliasSum
);
350 errs() << " " << MustAliasCount
<< " must alias responses ";
351 PrintPercent(MustAliasCount
, AliasSum
);
352 errs() << " Alias Analysis Evaluator Pointer Alias Summary: "
353 << NoAliasCount
* 100 / AliasSum
<< "%/"
354 << MayAliasCount
* 100 / AliasSum
<< "%/"
355 << PartialAliasCount
* 100 / AliasSum
<< "%/"
356 << MustAliasCount
* 100 / AliasSum
<< "%\n";
359 // Display the summary for mod/ref analysis
360 int64_t ModRefSum
= NoModRefCount
+ RefCount
+ ModCount
+ ModRefCount
+
361 MustCount
+ MustRefCount
+ MustModCount
+ MustModRefCount
;
362 if (ModRefSum
== 0) {
363 errs() << " Alias Analysis Mod/Ref Evaluator Summary: no "
366 errs() << " " << ModRefSum
<< " Total ModRef Queries Performed\n";
367 errs() << " " << NoModRefCount
<< " no mod/ref responses ";
368 PrintPercent(NoModRefCount
, ModRefSum
);
369 errs() << " " << ModCount
<< " mod responses ";
370 PrintPercent(ModCount
, ModRefSum
);
371 errs() << " " << RefCount
<< " ref responses ";
372 PrintPercent(RefCount
, ModRefSum
);
373 errs() << " " << ModRefCount
<< " mod & ref responses ";
374 PrintPercent(ModRefCount
, ModRefSum
);
375 errs() << " " << MustCount
<< " must responses ";
376 PrintPercent(MustCount
, ModRefSum
);
377 errs() << " " << MustModCount
<< " must mod responses ";
378 PrintPercent(MustModCount
, ModRefSum
);
379 errs() << " " << MustRefCount
<< " must ref responses ";
380 PrintPercent(MustRefCount
, ModRefSum
);
381 errs() << " " << MustModRefCount
<< " must mod & ref responses ";
382 PrintPercent(MustModRefCount
, ModRefSum
);
383 errs() << " Alias Analysis Evaluator Mod/Ref Summary: "
384 << NoModRefCount
* 100 / ModRefSum
<< "%/"
385 << ModCount
* 100 / ModRefSum
<< "%/" << RefCount
* 100 / ModRefSum
386 << "%/" << ModRefCount
* 100 / ModRefSum
<< "%/"
387 << MustCount
* 100 / ModRefSum
<< "%/"
388 << MustRefCount
* 100 / ModRefSum
<< "%/"
389 << MustModCount
* 100 / ModRefSum
<< "%/"
390 << MustModRefCount
* 100 / ModRefSum
<< "%\n";
395 class AAEvalLegacyPass
: public FunctionPass
{
396 std::unique_ptr
<AAEvaluator
> P
;
399 static char ID
; // Pass identification, replacement for typeid
400 AAEvalLegacyPass() : FunctionPass(ID
) {
401 initializeAAEvalLegacyPassPass(*PassRegistry::getPassRegistry());
404 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
405 AU
.addRequired
<AAResultsWrapperPass
>();
406 AU
.setPreservesAll();
409 bool doInitialization(Module
&M
) override
{
410 P
.reset(new AAEvaluator());
414 bool runOnFunction(Function
&F
) override
{
415 P
->runInternal(F
, getAnalysis
<AAResultsWrapperPass
>().getAAResults());
418 bool doFinalization(Module
&M
) override
{
425 char AAEvalLegacyPass::ID
= 0;
426 INITIALIZE_PASS_BEGIN(AAEvalLegacyPass
, "aa-eval",
427 "Exhaustive Alias Analysis Precision Evaluator", false,
429 INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass
)
430 INITIALIZE_PASS_END(AAEvalLegacyPass
, "aa-eval",
431 "Exhaustive Alias Analysis Precision Evaluator", false,
434 FunctionPass
*llvm::createAAEvalPass() { return new AAEvalLegacyPass(); }