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/InitializePasses.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 // Change offset sign for the local AR, for printing only.
59 errs() << " " << AR
<< ":\t" << o1
<< ", " << o2
<< "\n";
63 static inline void PrintModRefResults(const char *Msg
, bool P
, Instruction
*I
,
64 Value
*Ptr
, Module
*M
) {
66 errs() << " " << Msg
<< ": Ptr: ";
67 Ptr
->printAsOperand(errs(), true, M
);
68 errs() << "\t<->" << *I
<< '\n';
72 static inline void PrintModRefResults(const char *Msg
, bool P
, CallBase
*CallA
,
73 CallBase
*CallB
, Module
*M
) {
75 errs() << " " << Msg
<< ": " << *CallA
<< " <-> " << *CallB
<< '\n';
79 static inline void PrintLoadStoreResults(AliasResult AR
, bool P
,
80 const Value
*V1
, const Value
*V2
,
83 errs() << " " << AR
<< ": " << *V1
<< " <-> " << *V2
<< '\n';
87 static inline bool isInterestingPointer(Value
*V
) {
88 return V
->getType()->isPointerTy()
89 && !isa
<ConstantPointerNull
>(V
);
92 PreservedAnalyses
AAEvaluator::run(Function
&F
, FunctionAnalysisManager
&AM
) {
93 runInternal(F
, AM
.getResult
<AAManager
>(F
));
94 return PreservedAnalyses::all();
97 void AAEvaluator::runInternal(Function
&F
, AAResults
&AA
) {
98 const DataLayout
&DL
= F
.getParent()->getDataLayout();
102 SetVector
<Value
*> Pointers
;
103 SmallSetVector
<CallBase
*, 16> Calls
;
104 SetVector
<Value
*> Loads
;
105 SetVector
<Value
*> Stores
;
107 for (auto &I
: F
.args())
108 if (I
.getType()->isPointerTy()) // Add all pointer arguments.
111 for (Instruction
&Inst
: instructions(F
)) {
112 if (Inst
.getType()->isPointerTy()) // Add all pointer instructions.
113 Pointers
.insert(&Inst
);
114 if (EvalAAMD
&& isa
<LoadInst
>(&Inst
))
116 if (EvalAAMD
&& isa
<StoreInst
>(&Inst
))
117 Stores
.insert(&Inst
);
118 if (auto *Call
= dyn_cast
<CallBase
>(&Inst
)) {
119 Value
*Callee
= Call
->getCalledOperand();
120 // Skip actual functions for direct function calls.
121 if (!isa
<Function
>(Callee
) && isInterestingPointer(Callee
))
122 Pointers
.insert(Callee
);
124 for (Use
&DataOp
: Call
->data_ops())
125 if (isInterestingPointer(DataOp
))
126 Pointers
.insert(DataOp
);
129 // Consider all operands.
130 for (Use
&Op
: Inst
.operands())
131 if (isInterestingPointer(Op
))
136 if (PrintAll
|| PrintNoAlias
|| PrintMayAlias
|| PrintPartialAlias
||
137 PrintMustAlias
|| PrintNoModRef
|| PrintMod
|| PrintRef
|| PrintModRef
)
138 errs() << "Function: " << F
.getName() << ": " << Pointers
.size()
139 << " pointers, " << Calls
.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 auto I1Size
= LocationSize::afterPointer();
145 Type
*I1ElTy
= cast
<PointerType
>((*I1
)->getType())->getElementType();
146 if (I1ElTy
->isSized())
147 I1Size
= LocationSize::precise(DL
.getTypeStoreSize(I1ElTy
));
149 for (SetVector
<Value
*>::iterator I2
= Pointers
.begin(); I2
!= I1
; ++I2
) {
150 auto I2Size
= LocationSize::afterPointer();
151 Type
*I2ElTy
= cast
<PointerType
>((*I2
)->getType())->getElementType();
152 if (I2ElTy
->isSized())
153 I2Size
= LocationSize::precise(DL
.getTypeStoreSize(I2ElTy
));
155 AliasResult AR
= AA
.alias(*I1
, I1Size
, *I2
, I2Size
);
157 case AliasResult::NoAlias
:
158 PrintResults(AR
, PrintNoAlias
, *I1
, *I2
, F
.getParent());
161 case AliasResult::MayAlias
:
162 PrintResults(AR
, PrintMayAlias
, *I1
, *I2
, F
.getParent());
165 case AliasResult::PartialAlias
:
166 PrintResults(AR
, PrintPartialAlias
, *I1
, *I2
, F
.getParent());
169 case AliasResult::MustAlias
:
170 PrintResults(AR
, PrintMustAlias
, *I1
, *I2
, F
.getParent());
178 // iterate over all pairs of load, store
179 for (Value
*Load
: Loads
) {
180 for (Value
*Store
: Stores
) {
181 AliasResult AR
= AA
.alias(MemoryLocation::get(cast
<LoadInst
>(Load
)),
182 MemoryLocation::get(cast
<StoreInst
>(Store
)));
184 case AliasResult::NoAlias
:
185 PrintLoadStoreResults(AR
, PrintNoAlias
, Load
, Store
, F
.getParent());
188 case AliasResult::MayAlias
:
189 PrintLoadStoreResults(AR
, PrintMayAlias
, Load
, Store
, F
.getParent());
192 case AliasResult::PartialAlias
:
193 PrintLoadStoreResults(AR
, PrintPartialAlias
, Load
, Store
, F
.getParent());
196 case AliasResult::MustAlias
:
197 PrintLoadStoreResults(AR
, PrintMustAlias
, Load
, Store
, F
.getParent());
204 // iterate over all pairs of store, store
205 for (SetVector
<Value
*>::iterator I1
= Stores
.begin(), E
= Stores
.end();
207 for (SetVector
<Value
*>::iterator I2
= Stores
.begin(); I2
!= I1
; ++I2
) {
208 AliasResult AR
= AA
.alias(MemoryLocation::get(cast
<StoreInst
>(*I1
)),
209 MemoryLocation::get(cast
<StoreInst
>(*I2
)));
211 case AliasResult::NoAlias
:
212 PrintLoadStoreResults(AR
, PrintNoAlias
, *I1
, *I2
, F
.getParent());
215 case AliasResult::MayAlias
:
216 PrintLoadStoreResults(AR
, PrintMayAlias
, *I1
, *I2
, F
.getParent());
219 case AliasResult::PartialAlias
:
220 PrintLoadStoreResults(AR
, PrintPartialAlias
, *I1
, *I2
, F
.getParent());
223 case AliasResult::MustAlias
:
224 PrintLoadStoreResults(AR
, PrintMustAlias
, *I1
, *I2
, F
.getParent());
232 // Mod/ref alias analysis: compare all pairs of calls and values
233 for (CallBase
*Call
: Calls
) {
234 for (auto Pointer
: Pointers
) {
235 auto Size
= LocationSize::afterPointer();
236 Type
*ElTy
= cast
<PointerType
>(Pointer
->getType())->getElementType();
238 Size
= LocationSize::precise(DL
.getTypeStoreSize(ElTy
));
240 switch (AA
.getModRefInfo(Call
, Pointer
, Size
)) {
241 case ModRefInfo::NoModRef
:
242 PrintModRefResults("NoModRef", PrintNoModRef
, Call
, Pointer
,
246 case ModRefInfo::Mod
:
247 PrintModRefResults("Just Mod", PrintMod
, Call
, Pointer
, F
.getParent());
250 case ModRefInfo::Ref
:
251 PrintModRefResults("Just Ref", PrintRef
, Call
, Pointer
, F
.getParent());
254 case ModRefInfo::ModRef
:
255 PrintModRefResults("Both ModRef", PrintModRef
, Call
, Pointer
,
259 case ModRefInfo::Must
:
260 PrintModRefResults("Must", PrintMust
, Call
, Pointer
, F
.getParent());
263 case ModRefInfo::MustMod
:
264 PrintModRefResults("Just Mod (MustAlias)", PrintMustMod
, Call
, Pointer
,
268 case ModRefInfo::MustRef
:
269 PrintModRefResults("Just Ref (MustAlias)", PrintMustRef
, Call
, Pointer
,
273 case ModRefInfo::MustModRef
:
274 PrintModRefResults("Both ModRef (MustAlias)", PrintMustModRef
, Call
,
275 Pointer
, F
.getParent());
282 // Mod/ref alias analysis: compare all pairs of calls
283 for (CallBase
*CallA
: Calls
) {
284 for (CallBase
*CallB
: Calls
) {
287 switch (AA
.getModRefInfo(CallA
, CallB
)) {
288 case ModRefInfo::NoModRef
:
289 PrintModRefResults("NoModRef", PrintNoModRef
, CallA
, CallB
,
293 case ModRefInfo::Mod
:
294 PrintModRefResults("Just Mod", PrintMod
, CallA
, CallB
, F
.getParent());
297 case ModRefInfo::Ref
:
298 PrintModRefResults("Just Ref", PrintRef
, CallA
, CallB
, F
.getParent());
301 case ModRefInfo::ModRef
:
302 PrintModRefResults("Both ModRef", PrintModRef
, CallA
, CallB
,
306 case ModRefInfo::Must
:
307 PrintModRefResults("Must", PrintMust
, CallA
, CallB
, F
.getParent());
310 case ModRefInfo::MustMod
:
311 PrintModRefResults("Just Mod (MustAlias)", PrintMustMod
, CallA
, CallB
,
315 case ModRefInfo::MustRef
:
316 PrintModRefResults("Just Ref (MustAlias)", PrintMustRef
, CallA
, CallB
,
320 case ModRefInfo::MustModRef
:
321 PrintModRefResults("Both ModRef (MustAlias)", PrintMustModRef
, CallA
,
322 CallB
, F
.getParent());
330 static void PrintPercent(int64_t Num
, int64_t Sum
) {
331 errs() << "(" << Num
* 100LL / Sum
<< "." << ((Num
* 1000LL / Sum
) % 10)
335 AAEvaluator::~AAEvaluator() {
336 if (FunctionCount
== 0)
340 NoAliasCount
+ MayAliasCount
+ PartialAliasCount
+ MustAliasCount
;
341 errs() << "===== Alias Analysis Evaluator Report =====\n";
343 errs() << " Alias Analysis Evaluator Summary: No pointers!\n";
345 errs() << " " << AliasSum
<< " Total Alias Queries Performed\n";
346 errs() << " " << NoAliasCount
<< " no alias responses ";
347 PrintPercent(NoAliasCount
, AliasSum
);
348 errs() << " " << MayAliasCount
<< " may alias responses ";
349 PrintPercent(MayAliasCount
, AliasSum
);
350 errs() << " " << PartialAliasCount
<< " partial alias responses ";
351 PrintPercent(PartialAliasCount
, AliasSum
);
352 errs() << " " << MustAliasCount
<< " must alias responses ";
353 PrintPercent(MustAliasCount
, AliasSum
);
354 errs() << " Alias Analysis Evaluator Pointer Alias Summary: "
355 << NoAliasCount
* 100 / AliasSum
<< "%/"
356 << MayAliasCount
* 100 / AliasSum
<< "%/"
357 << PartialAliasCount
* 100 / AliasSum
<< "%/"
358 << MustAliasCount
* 100 / AliasSum
<< "%\n";
361 // Display the summary for mod/ref analysis
362 int64_t ModRefSum
= NoModRefCount
+ RefCount
+ ModCount
+ ModRefCount
+
363 MustCount
+ MustRefCount
+ MustModCount
+ MustModRefCount
;
364 if (ModRefSum
== 0) {
365 errs() << " Alias Analysis Mod/Ref Evaluator Summary: no "
368 errs() << " " << ModRefSum
<< " Total ModRef Queries Performed\n";
369 errs() << " " << NoModRefCount
<< " no mod/ref responses ";
370 PrintPercent(NoModRefCount
, ModRefSum
);
371 errs() << " " << ModCount
<< " mod responses ";
372 PrintPercent(ModCount
, ModRefSum
);
373 errs() << " " << RefCount
<< " ref responses ";
374 PrintPercent(RefCount
, ModRefSum
);
375 errs() << " " << ModRefCount
<< " mod & ref responses ";
376 PrintPercent(ModRefCount
, ModRefSum
);
377 errs() << " " << MustCount
<< " must responses ";
378 PrintPercent(MustCount
, ModRefSum
);
379 errs() << " " << MustModCount
<< " must mod responses ";
380 PrintPercent(MustModCount
, ModRefSum
);
381 errs() << " " << MustRefCount
<< " must ref responses ";
382 PrintPercent(MustRefCount
, ModRefSum
);
383 errs() << " " << MustModRefCount
<< " must mod & ref responses ";
384 PrintPercent(MustModRefCount
, ModRefSum
);
385 errs() << " Alias Analysis Evaluator Mod/Ref Summary: "
386 << NoModRefCount
* 100 / ModRefSum
<< "%/"
387 << ModCount
* 100 / ModRefSum
<< "%/" << RefCount
* 100 / ModRefSum
388 << "%/" << ModRefCount
* 100 / ModRefSum
<< "%/"
389 << MustCount
* 100 / ModRefSum
<< "%/"
390 << MustRefCount
* 100 / ModRefSum
<< "%/"
391 << MustModCount
* 100 / ModRefSum
<< "%/"
392 << MustModRefCount
* 100 / ModRefSum
<< "%\n";
397 class AAEvalLegacyPass
: public FunctionPass
{
398 std::unique_ptr
<AAEvaluator
> P
;
401 static char ID
; // Pass identification, replacement for typeid
402 AAEvalLegacyPass() : FunctionPass(ID
) {
403 initializeAAEvalLegacyPassPass(*PassRegistry::getPassRegistry());
406 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
407 AU
.addRequired
<AAResultsWrapperPass
>();
408 AU
.setPreservesAll();
411 bool doInitialization(Module
&M
) override
{
412 P
.reset(new AAEvaluator());
416 bool runOnFunction(Function
&F
) override
{
417 P
->runInternal(F
, getAnalysis
<AAResultsWrapperPass
>().getAAResults());
420 bool doFinalization(Module
&M
) override
{
427 char AAEvalLegacyPass::ID
= 0;
428 INITIALIZE_PASS_BEGIN(AAEvalLegacyPass
, "aa-eval",
429 "Exhaustive Alias Analysis Precision Evaluator", false,
431 INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass
)
432 INITIALIZE_PASS_END(AAEvalLegacyPass
, "aa-eval",
433 "Exhaustive Alias Analysis Precision Evaluator", false,
436 FunctionPass
*llvm::createAAEvalPass() { return new AAEvalLegacyPass(); }