blob: acb200481aa177a760afd621ea779ded0b4ddf0a [file] [log] [blame]
Chris Lattner009cc3d2002-09-26 21:49:07 +00001//===- AliasSetTracker.cpp - Alias Sets Tracker implementation-------------===//
2//
3// This file implements the AliasSetTracker and AliasSet classes.
4//
5//===----------------------------------------------------------------------===//
6
7#include "llvm/Analysis/AliasSetTracker.h"
8#include "llvm/Analysis/AliasAnalysis.h"
9#include "llvm/iMemory.h"
10#include "llvm/iOther.h"
11#include "llvm/iTerminators.h"
Chris Lattner9971ac42003-02-24 20:37:56 +000012#include "llvm/Pass.h"
13#include "llvm/Assembly/Writer.h"
14#include "llvm/Support/InstIterator.h"
Chris Lattner009cc3d2002-09-26 21:49:07 +000015
Chris Lattner2d0a4a42003-02-26 19:28:57 +000016// FIXME: This should keep sizes associated with pointers!
17
Chris Lattner009cc3d2002-09-26 21:49:07 +000018/// mergeSetIn - Merge the specified alias set into this alias set...
19///
Chris Lattner9971ac42003-02-24 20:37:56 +000020void AliasSet::mergeSetIn(AliasSet &AS) {
21 assert(!AS.Forward && "Alias set is already forwarding!");
22 assert(!Forward && "This set is a forwarding set!!");
Chris Lattner009cc3d2002-09-26 21:49:07 +000023
24 // Update the alias and access types of this set...
Chris Lattner9971ac42003-02-24 20:37:56 +000025 AccessTy |= AS.AccessTy;
26 AliasTy |= AS.AliasTy;
27
28 if (CallSites.empty()) { // Merge call sites...
29 if (!AS.CallSites.empty())
30 std::swap(CallSites, AS.CallSites);
31 } else if (!AS.CallSites.empty()) {
32 CallSites.insert(CallSites.end(), AS.CallSites.begin(), AS.CallSites.end());
33 AS.CallSites.clear();
34 }
35
36 // FIXME: If AS's refcount is zero, nuke it now...
37 assert(RefCount != 0);
38
39 AS.Forward = this; // Forward across AS now...
40 RefCount++; // AS is now pointing to us...
41
42 // Merge the list of constituent pointers...
43 PtrListTail->second.setTail(AS.PtrListHead);
44 PtrListTail = AS.PtrListTail;
45 AS.PtrListHead = AS.PtrListTail = 0;
Chris Lattner009cc3d2002-09-26 21:49:07 +000046}
47
Chris Lattner9971ac42003-02-24 20:37:56 +000048void AliasSetTracker::removeAliasSet(AliasSet *AS) {
49 AliasSets.erase(AS);
50}
51
52void AliasSet::removeFromTracker(AliasSetTracker &AST) {
53 assert(RefCount == 0 && "Cannot remove non-dead alias set from tracker!");
54 AST.removeAliasSet(this);
55}
56
57void AliasSet::addPointer(AliasSetTracker &AST, HashNodePair &Entry){
58 assert(!Entry.second.hasAliasSet() && "Entry already in set!");
59
60 AliasAnalysis &AA = AST.getAliasAnalysis();
61
62 if (isMustAlias()) // Check to see if we have to downgrade to _may_ alias
63 if (Value *V = getSomePointer())
Chris Lattner2d0a4a42003-02-26 19:28:57 +000064 if (AA.alias(V, ~0, Entry.first, ~0) == AliasAnalysis::MayAlias)
Chris Lattner9971ac42003-02-24 20:37:56 +000065 AliasTy = MayAlias;
66
67 Entry.second.setAliasSet(this);
68
69 // Add it to the end of the list...
70 if (PtrListTail)
71 PtrListTail->second.setTail(&Entry);
72 else
73 PtrListHead = &Entry;
74 PtrListTail = &Entry;
75 RefCount++; // Entry points to alias set...
76}
77
78void AliasSet::addCallSite(CallSite CS) {
79 CallSites.push_back(CS);
80 AliasTy = MayAlias; // FIXME: Too conservative
81}
82
83/// aliasesPointer - Return true if the specified pointer "may" (or must)
Chris Lattner009cc3d2002-09-26 21:49:07 +000084/// alias one of the members in the set.
85///
Chris Lattner9971ac42003-02-24 20:37:56 +000086bool AliasSet::aliasesPointer(const Value *Ptr, AliasAnalysis &AA) const {
87 if (AliasTy == MustAlias) {
88 assert(CallSites.empty() && "Illegal must alias set!");
89
90 // If this is a set of MustAliases, only check to see if the pointer aliases
91 // SOME value in the set...
92 Value *SomePtr = getSomePointer();
93 assert(SomePtr && "Empty must-alias set??");
Chris Lattner2d0a4a42003-02-26 19:28:57 +000094 return AA.alias(SomePtr, ~0, Ptr, ~0);
Chris Lattner9971ac42003-02-24 20:37:56 +000095 }
96
97 // If this is a may-alias set, we have to check all of the pointers in the set
98 // to be sure it doesn't alias the set...
99 for (iterator I = begin(), E = end(); I != E; ++I)
Chris Lattner2d0a4a42003-02-26 19:28:57 +0000100 if (AA.alias(Ptr, ~0, *I, ~0))
Chris Lattner9971ac42003-02-24 20:37:56 +0000101 return true;
102
103 // Check the call sites list and invoke list...
104 if (!CallSites.empty())
105 // FIXME: this is pessimistic!
Chris Lattner009cc3d2002-09-26 21:49:07 +0000106 return true;
Chris Lattner9971ac42003-02-24 20:37:56 +0000107
Chris Lattner009cc3d2002-09-26 21:49:07 +0000108 return false;
109}
110
Chris Lattner9971ac42003-02-24 20:37:56 +0000111bool AliasSet::aliasesCallSite(CallSite CS, AliasAnalysis &AA) const {
112 // FIXME: Too conservative!
113 return true;
Chris Lattner009cc3d2002-09-26 21:49:07 +0000114}
115
116
Chris Lattner009cc3d2002-09-26 21:49:07 +0000117/// findAliasSetForPointer - Given a pointer, find the one alias set to put the
118/// instruction referring to the pointer into. If there are multiple alias sets
119/// that may alias the pointer, merge them together and return the unified set.
120///
121AliasSet *AliasSetTracker::findAliasSetForPointer(const Value *Ptr) {
122 AliasSet *FoundSet = 0;
Chris Lattner9971ac42003-02-24 20:37:56 +0000123 for (iterator I = begin(), E = end(); I != E; ++I)
Chris Lattner2d0a4a42003-02-26 19:28:57 +0000124 if (!I->Forward && I->aliasesPointer(Ptr, AA)) {
Chris Lattner009cc3d2002-09-26 21:49:07 +0000125 if (FoundSet == 0) { // If this is the first alias set ptr can go into...
Chris Lattner9971ac42003-02-24 20:37:56 +0000126 FoundSet = I; // Remember it.
Chris Lattner009cc3d2002-09-26 21:49:07 +0000127 } else { // Otherwise, we must merge the sets...
Chris Lattner9971ac42003-02-24 20:37:56 +0000128 FoundSet->mergeSetIn(*I); // Merge in contents...
Chris Lattner009cc3d2002-09-26 21:49:07 +0000129 }
130 }
Chris Lattner9971ac42003-02-24 20:37:56 +0000131
132 return FoundSet;
133}
134
135AliasSet *AliasSetTracker::findAliasSetForCallSite(CallSite CS) {
136 AliasSet *FoundSet = 0;
137 for (iterator I = begin(), E = end(); I != E; ++I)
Chris Lattner2d0a4a42003-02-26 19:28:57 +0000138 if (!I->Forward && I->aliasesCallSite(CS, AA)) {
Chris Lattner9971ac42003-02-24 20:37:56 +0000139 if (FoundSet == 0) { // If this is the first alias set ptr can go into...
140 FoundSet = I; // Remember it.
Chris Lattner2d0a4a42003-02-26 19:28:57 +0000141 } else if (!I->Forward) { // Otherwise, we must merge the sets...
Chris Lattner9971ac42003-02-24 20:37:56 +0000142 FoundSet->mergeSetIn(*I); // Merge in contents...
143 }
144 }
Chris Lattner009cc3d2002-09-26 21:49:07 +0000145
146 return FoundSet;
147}
148
149
Chris Lattner009cc3d2002-09-26 21:49:07 +0000150
Chris Lattner9971ac42003-02-24 20:37:56 +0000151
152/// getAliasSetForPointer - Return the alias set that the specified pointer
153/// lives in...
154AliasSet &AliasSetTracker::getAliasSetForPointer(Value *Pointer) {
155 AliasSet::HashNodePair &Entry = getEntryFor(Pointer);
156
157 // Check to see if the pointer is already known...
158 if (Entry.second.hasAliasSet()) {
159 // Return the set!
160 return *Entry.second.getAliasSet(*this)->getForwardedTarget(*this);
161 } else if (AliasSet *AS = findAliasSetForPointer(Pointer)) {
162 // Add it to the alias set it aliases...
163 AS->addPointer(*this, Entry);
164 return *AS;
Chris Lattner009cc3d2002-09-26 21:49:07 +0000165 } else {
Chris Lattner9971ac42003-02-24 20:37:56 +0000166 // Otherwise create a new alias set to hold the loaded pointer...
Chris Lattner009cc3d2002-09-26 21:49:07 +0000167 AliasSets.push_back(AliasSet());
Chris Lattner9971ac42003-02-24 20:37:56 +0000168 AliasSets.back().addPointer(*this, Entry);
169 return AliasSets.back();
Chris Lattner009cc3d2002-09-26 21:49:07 +0000170 }
171}
172
Chris Lattner9971ac42003-02-24 20:37:56 +0000173void AliasSetTracker::add(LoadInst *LI) {
174 addPointer(LI->getOperand(0), AliasSet::Refs);
175}
176
Chris Lattner009cc3d2002-09-26 21:49:07 +0000177void AliasSetTracker::add(StoreInst *SI) {
Chris Lattner9971ac42003-02-24 20:37:56 +0000178 addPointer(SI->getOperand(1), AliasSet::Mods);
Chris Lattner009cc3d2002-09-26 21:49:07 +0000179}
180
Chris Lattner9971ac42003-02-24 20:37:56 +0000181void AliasSetTracker::add(CallSite CS) {
182 AliasSet *AS = findAliasSetForCallSite(CS);
183 if (!AS) {
184 AliasSets.push_back(AliasSet());
185 AS = &AliasSets.back();
186 }
187 AS->addCallSite(CS);
Chris Lattner009cc3d2002-09-26 21:49:07 +0000188}
189
Chris Lattner9971ac42003-02-24 20:37:56 +0000190void AliasSetTracker::add(Instruction *I) {
191 // Dispatch to one of the other add methods...
192 if (LoadInst *LI = dyn_cast<LoadInst>(I))
193 add(LI);
194 else if (StoreInst *SI = dyn_cast<StoreInst>(I))
195 add(SI);
196 else if (CallInst *CI = dyn_cast<CallInst>(I))
197 add(CI);
198 else if (InvokeInst *II = dyn_cast<InvokeInst>(I))
199 add(II);
Chris Lattner009cc3d2002-09-26 21:49:07 +0000200}
201
Chris Lattner9971ac42003-02-24 20:37:56 +0000202//===----------------------------------------------------------------------===//
203// AliasSet/AliasSetTracker Printing Support
204//===----------------------------------------------------------------------===//
205
206void AliasSet::print(std::ostream &OS) const {
207 OS << " AliasSet[" << (void*)this << "," << RefCount << "] ";
208 OS << (AliasTy == MustAlias ? "must" : "may ") << " alias, ";
209 switch (AccessTy) {
210 case NoModRef: OS << "No access "; break;
211 case Refs : OS << "Ref "; break;
212 case Mods : OS << "Mod "; break;
213 case ModRef : OS << "Mod/Ref "; break;
214 default: assert(0 && "Bad value for AccessTy!");
Chris Lattner009cc3d2002-09-26 21:49:07 +0000215 }
Chris Lattner9971ac42003-02-24 20:37:56 +0000216 if (Forward)
217 OS << " forwarding to " << (void*)Forward;
218
219
220 if (begin() != end()) {
221 OS << "Pointers: ";
222 for (iterator I = begin(), E = end(); I != E; ++I) {
223 if (I != begin()) OS << ", ";
224 WriteAsOperand(OS, *I);
225 }
226 }
227 if (!CallSites.empty()) {
228 OS << "\n " << CallSites.size() << " Call Sites: ";
229 for (unsigned i = 0, e = CallSites.size(); i != e; ++i) {
230 if (i) OS << ", ";
231 WriteAsOperand(OS, CallSites[i].getCalledValue());
232 }
233 }
234 OS << "\n";
235}
236
237void AliasSetTracker::print(std::ostream &OS) const {
238 OS << "Alias Set Tracker: " << AliasSets.size() << " alias sets for "
239 << PointerMap.size() << " pointer values.\n";
240 for (const_iterator I = begin(), E = end(); I != E; ++I)
241 I->print(OS);
242 OS << "\n";
243}
244
245void AliasSet::dump() const { print (std::cerr); }
246void AliasSetTracker::dump() const { print(std::cerr); }
247
248
249//===----------------------------------------------------------------------===//
250// AliasSetPrinter Pass
251//===----------------------------------------------------------------------===//
252
253namespace {
254 class AliasSetPrinter : public FunctionPass {
255 AliasSetTracker *Tracker;
256 public:
257 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
258 AU.setPreservesAll();
259 AU.addRequired<AliasAnalysis>();
260 }
261
262 virtual bool runOnFunction(Function &F) {
263 Tracker = new AliasSetTracker(getAnalysis<AliasAnalysis>());
264
265 for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I)
266 Tracker->add(*I);
267 return false;
268 }
269
270 /// print - Convert to human readable form
271 virtual void print(std::ostream &OS) const {
272 Tracker->print(OS);
273 }
274
275 virtual void releaseMemory() {
276 delete Tracker;
277 }
278 };
279 RegisterPass<AliasSetPrinter> X("print-alias-sets", "Alias Set Printer",
280 PassInfo::Analysis | PassInfo::Optimization);
Chris Lattner009cc3d2002-09-26 21:49:07 +0000281}