1 //===- AliasAnalysisEvaluator.cpp - Alias Analysis Accuracy Evaluator -----===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/Analysis/AliasAnalysisEvaluator.h"
11 #include "llvm/ADT/SetVector.h"
12 #include "llvm/Analysis/AliasAnalysis.h"
13 #include "llvm/IR/Constants.h"
14 #include "llvm/IR/DataLayout.h"
15 #include "llvm/IR/DerivedTypes.h"
16 #include "llvm/IR/Function.h"
17 #include "llvm/IR/InstIterator.h"
18 #include "llvm/IR/Instructions.h"
19 #include "llvm/IR/Module.h"
20 #include "llvm/Pass.h"
21 #include "llvm/Support/CommandLine.h"
22 #include "llvm/Support/Debug.h"
23 #include "llvm/Support/raw_ostream.h"
26 static cl::opt
<bool> PrintAll("print-all-alias-modref-info", cl::ReallyHidden
);
28 static cl::opt
<bool> PrintNoAlias("print-no-aliases", cl::ReallyHidden
);
29 static cl::opt
<bool> PrintMayAlias("print-may-aliases", cl::ReallyHidden
);
30 static cl::opt
<bool> PrintPartialAlias("print-partial-aliases", cl::ReallyHidden
);
31 static cl::opt
<bool> PrintMustAlias("print-must-aliases", cl::ReallyHidden
);
33 static cl::opt
<bool> PrintNoModRef("print-no-modref", cl::ReallyHidden
);
34 static cl::opt
<bool> PrintRef("print-ref", cl::ReallyHidden
);
35 static cl::opt
<bool> PrintMod("print-mod", cl::ReallyHidden
);
36 static cl::opt
<bool> PrintModRef("print-modref", cl::ReallyHidden
);
37 static cl::opt
<bool> PrintMust("print-must", cl::ReallyHidden
);
38 static cl::opt
<bool> PrintMustRef("print-mustref", cl::ReallyHidden
);
39 static cl::opt
<bool> PrintMustMod("print-mustmod", cl::ReallyHidden
);
40 static cl::opt
<bool> PrintMustModRef("print-mustmodref", cl::ReallyHidden
);
42 static cl::opt
<bool> EvalAAMD("evaluate-aa-metadata", cl::ReallyHidden
);
44 static void PrintResults(AliasResult AR
, bool P
, const Value
*V1
,
45 const Value
*V2
, const Module
*M
) {
49 raw_string_ostream
os1(o1
), os2(o2
);
50 V1
->printAsOperand(os1
, true, M
);
51 V2
->printAsOperand(os2
, true, M
);
56 errs() << " " << AR
<< ":\t" << o1
<< ", " << o2
<< "\n";
60 static inline void PrintModRefResults(const char *Msg
, bool P
, Instruction
*I
,
61 Value
*Ptr
, Module
*M
) {
63 errs() << " " << Msg
<< ": Ptr: ";
64 Ptr
->printAsOperand(errs(), true, M
);
65 errs() << "\t<->" << *I
<< '\n';
69 static inline void PrintModRefResults(const char *Msg
, bool P
, CallSite CSA
,
70 CallSite CSB
, Module
*M
) {
72 errs() << " " << Msg
<< ": " << *CSA
.getInstruction() << " <-> "
73 << *CSB
.getInstruction() << '\n';
77 static inline void PrintLoadStoreResults(AliasResult AR
, bool P
,
78 const Value
*V1
, const Value
*V2
,
81 errs() << " " << AR
<< ": " << *V1
<< " <-> " << *V2
<< '\n';
85 static inline bool isInterestingPointer(Value
*V
) {
86 return V
->getType()->isPointerTy()
87 && !isa
<ConstantPointerNull
>(V
);
90 PreservedAnalyses
AAEvaluator::run(Function
&F
, FunctionAnalysisManager
&AM
) {
91 runInternal(F
, AM
.getResult
<AAManager
>(F
));
92 return PreservedAnalyses::all();
95 void AAEvaluator::runInternal(Function
&F
, AAResults
&AA
) {
96 const DataLayout
&DL
= F
.getParent()->getDataLayout();
100 SetVector
<Value
*> Pointers
;
101 SmallSetVector
<CallSite
, 16> CallSites
;
102 SetVector
<Value
*> Loads
;
103 SetVector
<Value
*> Stores
;
105 for (auto &I
: F
.args())
106 if (I
.getType()->isPointerTy()) // Add all pointer arguments.
109 for (inst_iterator I
= inst_begin(F
), E
= inst_end(F
); I
!= E
; ++I
) {
110 if (I
->getType()->isPointerTy()) // Add all pointer instructions.
111 Pointers
.insert(&*I
);
112 if (EvalAAMD
&& isa
<LoadInst
>(&*I
))
114 if (EvalAAMD
&& isa
<StoreInst
>(&*I
))
116 Instruction
&Inst
= *I
;
117 if (auto CS
= CallSite(&Inst
)) {
118 Value
*Callee
= CS
.getCalledValue();
119 // Skip actual functions for direct function calls.
120 if (!isa
<Function
>(Callee
) && isInterestingPointer(Callee
))
121 Pointers
.insert(Callee
);
123 for (Use
&DataOp
: CS
.data_ops())
124 if (isInterestingPointer(DataOp
))
125 Pointers
.insert(DataOp
);
126 CallSites
.insert(CS
);
128 // Consider all operands.
129 for (Instruction::op_iterator OI
= Inst
.op_begin(), OE
= Inst
.op_end();
131 if (isInterestingPointer(*OI
))
132 Pointers
.insert(*OI
);
136 if (PrintAll
|| PrintNoAlias
|| PrintMayAlias
|| PrintPartialAlias
||
137 PrintMustAlias
|| PrintNoModRef
|| PrintMod
|| PrintRef
|| PrintModRef
)
138 errs() << "Function: " << F
.getName() << ": " << Pointers
.size()
139 << " pointers, " << CallSites
.size() << " call sites\n";
141 // iterate over the worklist, and run the full (n^2)/2 disambiguations
142 for (SetVector
<Value
*>::iterator I1
= Pointers
.begin(), E
= Pointers
.end();
144 uint64_t I1Size
= MemoryLocation::UnknownSize
;
145 Type
*I1ElTy
= cast
<PointerType
>((*I1
)->getType())->getElementType();
146 if (I1ElTy
->isSized()) I1Size
= DL
.getTypeStoreSize(I1ElTy
);
148 for (SetVector
<Value
*>::iterator I2
= Pointers
.begin(); I2
!= I1
; ++I2
) {
149 uint64_t I2Size
= MemoryLocation::UnknownSize
;
150 Type
*I2ElTy
=cast
<PointerType
>((*I2
)->getType())->getElementType();
151 if (I2ElTy
->isSized()) I2Size
= 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 (CallSite C
: CallSites
) {
232 Instruction
*I
= C
.getInstruction();
234 for (auto Pointer
: Pointers
) {
235 uint64_t Size
= MemoryLocation::UnknownSize
;
236 Type
*ElTy
= cast
<PointerType
>(Pointer
->getType())->getElementType();
237 if (ElTy
->isSized()) Size
= DL
.getTypeStoreSize(ElTy
);
239 switch (AA
.getModRefInfo(C
, Pointer
, Size
)) {
240 case ModRefInfo::NoModRef
:
241 PrintModRefResults("NoModRef", PrintNoModRef
, I
, Pointer
,
245 case ModRefInfo::Mod
:
246 PrintModRefResults("Just Mod", PrintMod
, I
, Pointer
, F
.getParent());
249 case ModRefInfo::Ref
:
250 PrintModRefResults("Just Ref", PrintRef
, I
, Pointer
, F
.getParent());
253 case ModRefInfo::ModRef
:
254 PrintModRefResults("Both ModRef", PrintModRef
, I
, Pointer
,
258 case ModRefInfo::Must
:
259 PrintModRefResults("Must", PrintMust
, I
, Pointer
, F
.getParent());
262 case ModRefInfo::MustMod
:
263 PrintModRefResults("Just Mod (MustAlias)", PrintMustMod
, I
, Pointer
,
267 case ModRefInfo::MustRef
:
268 PrintModRefResults("Just Ref (MustAlias)", PrintMustRef
, I
, Pointer
,
272 case ModRefInfo::MustModRef
:
273 PrintModRefResults("Both ModRef (MustAlias)", PrintMustModRef
, I
,
274 Pointer
, F
.getParent());
281 // Mod/ref alias analysis: compare all pairs of calls
282 for (auto C
= CallSites
.begin(), Ce
= CallSites
.end(); C
!= Ce
; ++C
) {
283 for (auto D
= CallSites
.begin(); D
!= Ce
; ++D
) {
286 switch (AA
.getModRefInfo(*C
, *D
)) {
287 case ModRefInfo::NoModRef
:
288 PrintModRefResults("NoModRef", PrintNoModRef
, *C
, *D
, F
.getParent());
291 case ModRefInfo::Mod
:
292 PrintModRefResults("Just Mod", PrintMod
, *C
, *D
, F
.getParent());
295 case ModRefInfo::Ref
:
296 PrintModRefResults("Just Ref", PrintRef
, *C
, *D
, F
.getParent());
299 case ModRefInfo::ModRef
:
300 PrintModRefResults("Both ModRef", PrintModRef
, *C
, *D
, F
.getParent());
303 case ModRefInfo::Must
:
304 PrintModRefResults("Must", PrintMust
, *C
, *D
, F
.getParent());
307 case ModRefInfo::MustMod
:
308 PrintModRefResults("Just Mod (MustAlias)", PrintMustMod
, *C
, *D
,
312 case ModRefInfo::MustRef
:
313 PrintModRefResults("Just Ref (MustAlias)", PrintMustRef
, *C
, *D
,
317 case ModRefInfo::MustModRef
:
318 PrintModRefResults("Both ModRef (MustAlias)", PrintMustModRef
, *C
, *D
,
327 static void PrintPercent(int64_t Num
, int64_t Sum
) {
328 errs() << "(" << Num
* 100LL / Sum
<< "." << ((Num
* 1000LL / Sum
) % 10)
332 AAEvaluator::~AAEvaluator() {
333 if (FunctionCount
== 0)
337 NoAliasCount
+ MayAliasCount
+ PartialAliasCount
+ MustAliasCount
;
338 errs() << "===== Alias Analysis Evaluator Report =====\n";
340 errs() << " Alias Analysis Evaluator Summary: No pointers!\n";
342 errs() << " " << AliasSum
<< " Total Alias Queries Performed\n";
343 errs() << " " << NoAliasCount
<< " no alias responses ";
344 PrintPercent(NoAliasCount
, AliasSum
);
345 errs() << " " << MayAliasCount
<< " may alias responses ";
346 PrintPercent(MayAliasCount
, AliasSum
);
347 errs() << " " << PartialAliasCount
<< " partial alias responses ";
348 PrintPercent(PartialAliasCount
, AliasSum
);
349 errs() << " " << MustAliasCount
<< " must alias responses ";
350 PrintPercent(MustAliasCount
, AliasSum
);
351 errs() << " Alias Analysis Evaluator Pointer Alias Summary: "
352 << NoAliasCount
* 100 / AliasSum
<< "%/"
353 << MayAliasCount
* 100 / AliasSum
<< "%/"
354 << PartialAliasCount
* 100 / AliasSum
<< "%/"
355 << MustAliasCount
* 100 / AliasSum
<< "%\n";
358 // Display the summary for mod/ref analysis
359 int64_t ModRefSum
= NoModRefCount
+ RefCount
+ ModCount
+ ModRefCount
+
360 MustCount
+ MustRefCount
+ MustModCount
+ MustModRefCount
;
361 if (ModRefSum
== 0) {
362 errs() << " Alias Analysis Mod/Ref Evaluator Summary: no "
365 errs() << " " << ModRefSum
<< " Total ModRef Queries Performed\n";
366 errs() << " " << NoModRefCount
<< " no mod/ref responses ";
367 PrintPercent(NoModRefCount
, ModRefSum
);
368 errs() << " " << ModCount
<< " mod responses ";
369 PrintPercent(ModCount
, ModRefSum
);
370 errs() << " " << RefCount
<< " ref responses ";
371 PrintPercent(RefCount
, ModRefSum
);
372 errs() << " " << ModRefCount
<< " mod & ref responses ";
373 PrintPercent(ModRefCount
, ModRefSum
);
374 errs() << " " << MustCount
<< " must responses ";
375 PrintPercent(MustCount
, ModRefSum
);
376 errs() << " " << MustModCount
<< " must mod responses ";
377 PrintPercent(MustModCount
, ModRefSum
);
378 errs() << " " << MustRefCount
<< " must ref responses ";
379 PrintPercent(MustRefCount
, ModRefSum
);
380 errs() << " " << MustModRefCount
<< " must mod & ref responses ";
381 PrintPercent(MustModRefCount
, ModRefSum
);
382 errs() << " Alias Analysis Evaluator Mod/Ref Summary: "
383 << NoModRefCount
* 100 / ModRefSum
<< "%/"
384 << ModCount
* 100 / ModRefSum
<< "%/" << RefCount
* 100 / ModRefSum
385 << "%/" << ModRefCount
* 100 / ModRefSum
<< "%/"
386 << MustCount
* 100 / ModRefSum
<< "%/"
387 << MustRefCount
* 100 / ModRefSum
<< "%/"
388 << MustModCount
* 100 / ModRefSum
<< "%/"
389 << MustModRefCount
* 100 / ModRefSum
<< "%\n";
394 class AAEvalLegacyPass
: public FunctionPass
{
395 std::unique_ptr
<AAEvaluator
> P
;
398 static char ID
; // Pass identification, replacement for typeid
399 AAEvalLegacyPass() : FunctionPass(ID
) {
400 initializeAAEvalLegacyPassPass(*PassRegistry::getPassRegistry());
403 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
404 AU
.addRequired
<AAResultsWrapperPass
>();
405 AU
.setPreservesAll();
408 bool doInitialization(Module
&M
) override
{
409 P
.reset(new AAEvaluator());
413 bool runOnFunction(Function
&F
) override
{
414 P
->runInternal(F
, getAnalysis
<AAResultsWrapperPass
>().getAAResults());
417 bool doFinalization(Module
&M
) override
{
424 char AAEvalLegacyPass::ID
= 0;
425 INITIALIZE_PASS_BEGIN(AAEvalLegacyPass
, "aa-eval",
426 "Exhaustive Alias Analysis Precision Evaluator", false,
428 INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass
)
429 INITIALIZE_PASS_END(AAEvalLegacyPass
, "aa-eval",
430 "Exhaustive Alias Analysis Precision Evaluator", false,
433 FunctionPass
*llvm::createAAEvalPass() { return new AAEvalLegacyPass(); }