LLVM 24.0.0git
AliasAnalysisEvaluator.cpp
Go to the documentation of this file.
1//===- AliasAnalysisEvaluator.cpp - Alias Analysis Accuracy Evaluator -----===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
10#include "AnalysisOptions.h"
11#include "llvm/ADT/SetVector.h"
13#include "llvm/IR/DataLayout.h"
14#include "llvm/IR/Function.h"
17#include "llvm/IR/Module.h"
19using namespace llvm;
20
21static void printResults(const AnalysisOptions &Opts, AliasResult AR, bool P,
22 std::pair<const Value *, Type *> Loc1,
23 std::pair<const Value *, Type *> Loc2,
24 const Module *M) {
25 if (Opts.print_all_alias_modref_info || P) {
26 Type *Ty1 = Loc1.second, *Ty2 = Loc2.second;
27 unsigned AS1 = Loc1.first->getType()->getPointerAddressSpace();
28 unsigned AS2 = Loc2.first->getType()->getPointerAddressSpace();
29 std::string o1, o2;
30 {
31 raw_string_ostream os1(o1), os2(o2);
32 Loc1.first->printAsOperand(os1, false, M);
33 Loc2.first->printAsOperand(os2, false, M);
34 }
35
36 if (o2 < o1) {
37 std::swap(o1, o2);
38 std::swap(Ty1, Ty2);
39 std::swap(AS1, AS2);
40 // Change offset sign for the local AR, for printing only.
41 AR.swap();
42 }
43 errs() << " " << AR << ":\t";
44 Ty1->print(errs(), false, /* NoDetails */ true);
45 if (AS1 != 0)
46 errs() << " addrspace(" << AS1 << ")";
47 errs() << "* " << o1 << ", ";
48 Ty2->print(errs(), false, /* NoDetails */ true);
49 if (AS2 != 0)
50 errs() << " addrspace(" << AS2 << ")";
51 errs() << "* " << o2 << "\n";
52 }
53}
54
55static inline void printModRefResults(const AnalysisOptions &Opts,
56 const char *Msg, bool P, Instruction *I,
57 std::pair<const Value *, Type *> Loc,
58 Module *M) {
59 if (Opts.print_all_alias_modref_info || P) {
60 errs() << " " << Msg << ": Ptr: ";
61 Loc.second->print(errs(), false, /* NoDetails */ true);
62 errs() << "* ";
63 Loc.first->printAsOperand(errs(), false, M);
64 errs() << "\t<->" << *I << '\n';
65 }
66}
67
68static inline void printModRefResults(const AnalysisOptions &Opts,
69 const char *Msg, bool P,
70 Instruction *MemOpA, Instruction *MemOpB,
71 Module *M) {
72 if (Opts.print_all_alias_modref_info || P) {
73 errs() << " " << Msg << ": " << *MemOpA << " <-> " << *MemOpB << '\n';
74 }
75}
76
77static inline void printLoadStoreResults(const AnalysisOptions &Opts,
78 AliasResult AR, bool P,
79 const Value *V1, const Value *V2,
80 const Module *M) {
81 if (Opts.print_all_alias_modref_info || P) {
82 errs() << " " << AR << ": " << *V1 << " <-> " << *V2 << '\n';
83 }
84}
85
90
91void AAEvaluator::runInternal(Function &F, AAResults &AA) {
92 const AnalysisOptions &Opts = getAnalysisOptions(F);
93 const DataLayout &DL = F.getDataLayout();
94
95 ++FunctionCount;
96
100 SetVector<Value *> Stores;
101
102 for (Instruction &Inst : instructions(F)) {
103 if (auto *LI = dyn_cast<LoadInst>(&Inst)) {
104 Pointers.insert({LI->getPointerOperand(), LI->getType()});
105 Loads.insert(LI);
106 } else if (auto *SI = dyn_cast<StoreInst>(&Inst)) {
107 Pointers.insert({SI->getPointerOperand(),
108 SI->getValueOperand()->getType()});
109 Stores.insert(SI);
110 }
111
112 if (isa<CallBase>(Inst) || Inst.isAtomic())
113 OtherMemOps.insert(&Inst);
114 }
115
116 if (Opts.print_all_alias_modref_info || Opts.print_no_aliases ||
117 Opts.print_may_aliases || Opts.print_partial_aliases ||
118 Opts.print_must_aliases || Opts.print_no_modref || Opts.print_mod ||
119 Opts.print_ref || Opts.print_modref)
120 errs() << "Function: " << F.getName() << ": " << Pointers.size()
121 << " pointers, " << OtherMemOps.size() << " call sites\n";
122
123 // iterate over the worklist, and run the full (n^2)/2 disambiguations
124 for (auto I1 = Pointers.begin(), E = Pointers.end(); I1 != E; ++I1) {
125 LocationSize Size1 = LocationSize::precise(DL.getTypeStoreSize(I1->second));
126 for (auto I2 = Pointers.begin(); I2 != I1; ++I2) {
127 LocationSize Size2 =
128 LocationSize::precise(DL.getTypeStoreSize(I2->second));
129 AliasResult AR = AA.alias(I1->first, Size1, I2->first, Size2);
130 switch (AR) {
132 printResults(Opts, AR, Opts.print_no_aliases, *I1, *I2, F.getParent());
133 ++NoAliasCount;
134 break;
136 printResults(Opts, AR, Opts.print_may_aliases, *I1, *I2, F.getParent());
137 ++MayAliasCount;
138 break;
140 printResults(Opts, AR, Opts.print_partial_aliases, *I1, *I2,
141 F.getParent());
142 ++PartialAliasCount;
143 break;
145 printResults(Opts, AR, Opts.print_must_aliases, *I1, *I2,
146 F.getParent());
147 ++MustAliasCount;
148 break;
149 }
150 }
151 }
152
153 if (Opts.evaluate_aa_metadata) {
154 // iterate over all pairs of load, store
155 for (Value *Load : Loads) {
156 for (Value *Store : Stores) {
157 AliasResult AR = AA.alias(MemoryLocation::get(cast<LoadInst>(Load)),
159 switch (AR) {
161 printLoadStoreResults(Opts, AR, Opts.print_no_aliases, Load, Store,
162 F.getParent());
163 ++NoAliasCount;
164 break;
166 printLoadStoreResults(Opts, AR, Opts.print_may_aliases, Load, Store,
167 F.getParent());
168 ++MayAliasCount;
169 break;
171 printLoadStoreResults(Opts, AR, Opts.print_partial_aliases, Load,
172 Store, F.getParent());
173 ++PartialAliasCount;
174 break;
176 printLoadStoreResults(Opts, AR, Opts.print_must_aliases, Load, Store,
177 F.getParent());
178 ++MustAliasCount;
179 break;
180 }
181 }
182 }
183
184 // iterate over all pairs of store, store
185 for (SetVector<Value *>::iterator I1 = Stores.begin(), E = Stores.end();
186 I1 != E; ++I1) {
187 for (SetVector<Value *>::iterator I2 = Stores.begin(); I2 != I1; ++I2) {
188 AliasResult AR = AA.alias(MemoryLocation::get(cast<StoreInst>(*I1)),
190 switch (AR) {
192 printLoadStoreResults(Opts, AR, Opts.print_no_aliases, *I1, *I2,
193 F.getParent());
194 ++NoAliasCount;
195 break;
197 printLoadStoreResults(Opts, AR, Opts.print_may_aliases, *I1, *I2,
198 F.getParent());
199 ++MayAliasCount;
200 break;
202 printLoadStoreResults(Opts, AR, Opts.print_partial_aliases, *I1, *I2,
203 F.getParent());
204 ++PartialAliasCount;
205 break;
207 printLoadStoreResults(Opts, AR, Opts.print_must_aliases, *I1, *I2,
208 F.getParent());
209 ++MustAliasCount;
210 break;
211 }
212 }
213 }
214 }
215
216 // Mod/ref alias analysis: compare all pairs of mem ops and values
217 for (Instruction *MemOp : OtherMemOps) {
218 for (const auto &Pointer : Pointers) {
219 LocationSize Size =
220 LocationSize::precise(DL.getTypeStoreSize(Pointer.second));
221 switch (AA.getModRefInfo(MemOp, Pointer.first, Size)) {
223 printModRefResults(Opts, "NoModRef", Opts.print_no_modref, MemOp,
224 Pointer, F.getParent());
225 ++NoModRefCount;
226 break;
227 case ModRefInfo::Mod:
228 printModRefResults(Opts, "Just Mod", Opts.print_mod, MemOp, Pointer,
229 F.getParent());
230 ++ModCount;
231 break;
232 case ModRefInfo::Ref:
233 printModRefResults(Opts, "Just Ref", Opts.print_ref, MemOp, Pointer,
234 F.getParent());
235 ++RefCount;
236 break;
238 printModRefResults(Opts, "Both ModRef", Opts.print_modref, MemOp,
239 Pointer, F.getParent());
240 ++ModRefCount;
241 break;
242 }
243 }
244 }
245
246 // Mod/ref alias analysis: compare all pairs of mem ops
247 for (Instruction *MemOpA : OtherMemOps) {
248 for (Instruction *MemOpB : OtherMemOps) {
249 if (MemOpA == MemOpB)
250 continue;
251 switch (AA.getModRefInfo(MemOpA, MemOpB)) {
253 printModRefResults(Opts, "NoModRef", Opts.print_no_modref, MemOpA,
254 MemOpB, F.getParent());
255 ++NoModRefCount;
256 break;
257 case ModRefInfo::Mod:
258 printModRefResults(Opts, "Just Mod", Opts.print_mod, MemOpA, MemOpB,
259 F.getParent());
260 ++ModCount;
261 break;
262 case ModRefInfo::Ref:
263 printModRefResults(Opts, "Just Ref", Opts.print_ref, MemOpA, MemOpB,
264 F.getParent());
265 ++RefCount;
266 break;
268 printModRefResults(Opts, "Both ModRef", Opts.print_modref, MemOpA,
269 MemOpB, F.getParent());
270 ++ModRefCount;
271 break;
272 }
273 }
274 }
275}
276
277static void PrintPercent(int64_t Num, int64_t Sum) {
278 errs() << "(" << Num * 100LL / Sum << "." << ((Num * 1000LL / Sum) % 10)
279 << "%)\n";
280}
281
283 if (FunctionCount == 0)
284 return;
285
286 int64_t AliasSum =
287 NoAliasCount + MayAliasCount + PartialAliasCount + MustAliasCount;
288 errs() << "===== Alias Analysis Evaluator Report =====\n";
289 if (AliasSum == 0) {
290 errs() << " Alias Analysis Evaluator Summary: No pointers!\n";
291 } else {
292 errs() << " " << AliasSum << " Total Alias Queries Performed\n";
293 errs() << " " << NoAliasCount << " no alias responses ";
294 PrintPercent(NoAliasCount, AliasSum);
295 errs() << " " << MayAliasCount << " may alias responses ";
296 PrintPercent(MayAliasCount, AliasSum);
297 errs() << " " << PartialAliasCount << " partial alias responses ";
298 PrintPercent(PartialAliasCount, AliasSum);
299 errs() << " " << MustAliasCount << " must alias responses ";
300 PrintPercent(MustAliasCount, AliasSum);
301 errs() << " Alias Analysis Evaluator Pointer Alias Summary: "
302 << NoAliasCount * 100 / AliasSum << "%/"
303 << MayAliasCount * 100 / AliasSum << "%/"
304 << PartialAliasCount * 100 / AliasSum << "%/"
305 << MustAliasCount * 100 / AliasSum << "%\n";
306 }
307
308 // Display the summary for mod/ref analysis
309 int64_t ModRefSum = NoModRefCount + RefCount + ModCount + ModRefCount;
310 if (ModRefSum == 0) {
311 errs() << " Alias Analysis Mod/Ref Evaluator Summary: no "
312 "mod/ref!\n";
313 } else {
314 errs() << " " << ModRefSum << " Total ModRef Queries Performed\n";
315 errs() << " " << NoModRefCount << " no mod/ref responses ";
316 PrintPercent(NoModRefCount, ModRefSum);
317 errs() << " " << ModCount << " mod responses ";
318 PrintPercent(ModCount, ModRefSum);
319 errs() << " " << RefCount << " ref responses ";
320 PrintPercent(RefCount, ModRefSum);
321 errs() << " " << ModRefCount << " mod & ref responses ";
322 PrintPercent(ModRefCount, ModRefSum);
323 errs() << " Alias Analysis Evaluator Mod/Ref Summary: "
324 << NoModRefCount * 100 / ModRefSum << "%/"
325 << ModCount * 100 / ModRefSum << "%/" << RefCount * 100 / ModRefSum
326 << "%/" << ModRefCount * 100 / ModRefSum << "%\n";
327 }
328}
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static void printResults(const AnalysisOptions &Opts, AliasResult AR, bool P, std::pair< const Value *, Type * > Loc1, std::pair< const Value *, Type * > Loc2, const Module *M)
static void PrintPercent(int64_t Num, int64_t Sum)
static void printModRefResults(const AnalysisOptions &Opts, const char *Msg, bool P, Instruction *I, std::pair< const Value *, Type * > Loc, Module *M)
static void printLoadStoreResults(const AnalysisOptions &Opts, AliasResult AR, bool P, const Value *V1, const Value *V2, const Module *M)
This file implements a simple N^2 alias analysis accuracy evaluator.
Expand Atomic instructions
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Module.h This file contains the declarations for the Module class.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define P(N)
const char * Msg
This file implements a set that has insertion order iteration characteristics.
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Run the pass over the function.
A manager for alias analyses.
ModRefInfo getModRefInfo(const Instruction *I, const std::optional< MemoryLocation > &OptLoc)
Check whether or not an instruction may read or write the optionally specified memory location.
LLVM_ABI AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB)
The main low level interface to the alias analysis implementation.
The possible results of an alias query.
void swap(bool DoSwap=true)
Helper for processing AliasResult for swapped memory location pairs.
@ MayAlias
The two locations may or may not alias.
@ NoAlias
The two locations do not alias at all.
@ PartialAlias
The two locations alias, but only due to a partial overlap.
@ MustAlias
The two locations precisely alias each other.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
static LocationSize precise(uint64_t Value)
static LLVM_ABI MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
A vector that has set insertion semantics.
Definition SetVector.h:57
size_type size() const
Determine the number of elements in the SetVector.
Definition SetVector.h:103
typename vector_type::const_iterator iterator
Definition SetVector.h:72
iterator end()
Get an iterator to the end of the SetVector.
Definition SetVector.h:118
iterator begin()
Get an iterator to the beginning of the SetVector.
Definition SetVector.h:112
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition SetVector.h:157
A SetVector that performs no allocations if smaller than a certain size.
Definition SetVector.h:345
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
LLVM_ABI void print(raw_ostream &O, bool IsForDebug=false, bool NoDetails=false) const
Print the current type.
LLVM Value Representation.
Definition Value.h:75
A raw_ostream that writes to an std::string.
Abstract Attribute helper functions.
Definition Attributor.h:164
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
const AnalysisOptions & getAnalysisOptions(const LLVMContext &C)
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ Ref
The access may reference the value stored in memory.
Definition ModRef.h:32
@ ModRef
The access may reference and may modify the value stored in memory.
Definition ModRef.h:36
@ Mod
The access may modify the value stored in memory.
Definition ModRef.h:34
@ NoModRef
The access neither references nor modifies the value stored in memory.
Definition ModRef.h:30
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880