X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FAnalysis%2FAliasSetTracker.cpp;h=0397af7e979fce11be064f15f8cb82d6bc21f05a;hb=1a957d563fe894c797e0eba00bf069fbe7ecba77;hp=1413660d92e83c2af8712d2284b3b8d4f17b1c7f;hpb=009cc3d2e85674f01f70d915e0c802d89d0b672f;p=oota-llvm.git diff --git a/lib/Analysis/AliasSetTracker.cpp b/lib/Analysis/AliasSetTracker.cpp index 1413660d92e..0397af7e979 100644 --- a/lib/Analysis/AliasSetTracker.cpp +++ b/lib/Analysis/AliasSetTracker.cpp @@ -1,172 +1,580 @@ //===- AliasSetTracker.cpp - Alias Sets Tracker implementation-------------===// // +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// // This file implements the AliasSetTracker and AliasSet classes. -// +// //===----------------------------------------------------------------------===// #include "llvm/Analysis/AliasSetTracker.h" #include "llvm/Analysis/AliasAnalysis.h" -#include "llvm/iMemory.h" -#include "llvm/iOther.h" -#include "llvm/iTerminators.h" +#include "llvm/Instructions.h" +#include "llvm/Pass.h" +#include "llvm/Type.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/InstIterator.h" +#include "llvm/Support/Streams.h" +using namespace llvm; -/// updateAccessTypes - Depending on what type of accesses are in this set, -/// decide whether the set contains just references, just modifications, or a -/// mix. +/// mergeSetIn - Merge the specified alias set into this alias set. /// -void AliasSet::updateAccessType() { - if (!Calls.empty() || !Invokes.empty()) { - AccessTy = ModRef; - } else if (!Loads.empty()) { - if (Stores.empty()) - AccessTy = Refs; - else - AccessTy = ModRef; - } else { - AccessTy = Mods; +void AliasSet::mergeSetIn(AliasSet &AS, AliasSetTracker &AST) { + assert(!AS.Forward && "Alias set is already forwarding!"); + assert(!Forward && "This set is a forwarding set!!"); + + // Update the alias and access types of this set... + AccessTy |= AS.AccessTy; + AliasTy |= AS.AliasTy; + + if (AliasTy == MustAlias) { + // Check that these two merged sets really are must aliases. Since both + // used to be must-alias sets, we can just check any pointer from each set + // for aliasing. + AliasAnalysis &AA = AST.getAliasAnalysis(); + HashNodePair *L = getSomePointer(); + HashNodePair *R = AS.getSomePointer(); + + // If the pointers are not a must-alias pair, this set becomes a may alias. + if (AA.alias(L->first, L->second.getSize(), R->first, R->second.getSize()) + != AliasAnalysis::MustAlias) + AliasTy = MayAlias; + } + + if (CallSites.empty()) { // Merge call sites... + if (!AS.CallSites.empty()) + std::swap(CallSites, AS.CallSites); + } else if (!AS.CallSites.empty()) { + CallSites.insert(CallSites.end(), AS.CallSites.begin(), AS.CallSites.end()); + AS.CallSites.clear(); + } + + AS.Forward = this; // Forward across AS now... + addRef(); // AS is now pointing to us... + + // Merge the list of constituent pointers... + if (AS.PtrList) { + *PtrListEnd = AS.PtrList; + AS.PtrList->second.setPrevInList(PtrListEnd); + PtrListEnd = AS.PtrListEnd; + + AS.PtrList = 0; + AS.PtrListEnd = &AS.PtrList; + assert(*AS.PtrListEnd == 0 && "End of list is not null?"); } } -/// mergeSetIn - Merge the specified alias set into this alias set... -/// -void AliasSet::mergeSetIn(const AliasSet &AS) { - // Merge instruction sets... - Loads.insert( Loads.end(), AS.Loads.begin() , AS.Loads.end()); - Stores.insert( Stores.end(), AS.Stores.begin() , AS.Stores.end()); - Calls.insert( Calls.end(), AS.Calls.begin() , AS.Calls.end()); - Invokes.insert(Invokes.end(), AS.Invokes.begin(), AS.Invokes.end()); +void AliasSetTracker::removeAliasSet(AliasSet *AS) { + if (AliasSet *Fwd = AS->Forward) { + Fwd->dropRef(*this); + AS->Forward = 0; + } + AliasSets.erase(AS); +} - // Update the alias and access types of this set... - if (AS.getAliasType() == MayAlias) - AliasTy = MayAlias; - updateAccessType(); +void AliasSet::removeFromTracker(AliasSetTracker &AST) { + assert(RefCount == 0 && "Cannot remove non-dead alias set from tracker!"); + AST.removeAliasSet(this); } -/// pointerAliasesSet - Return true if the specified pointer "may" (or must) +void AliasSet::addPointer(AliasSetTracker &AST, HashNodePair &Entry, + unsigned Size, bool KnownMustAlias) { + assert(!Entry.second.hasAliasSet() && "Entry already in set!"); + + // Check to see if we have to downgrade to _may_ alias. + if (isMustAlias() && !KnownMustAlias) + if (HashNodePair *P = getSomePointer()) { + AliasAnalysis &AA = AST.getAliasAnalysis(); + AliasAnalysis::AliasResult Result = + AA.alias(P->first, P->second.getSize(), Entry.first, Size); + if (Result == AliasAnalysis::MayAlias) + AliasTy = MayAlias; + else // First entry of must alias must have maximum size! + P->second.updateSize(Size); + assert(Result != AliasAnalysis::NoAlias && "Cannot be part of must set!"); + } + + Entry.second.setAliasSet(this); + Entry.second.updateSize(Size); + + // Add it to the end of the list... + assert(*PtrListEnd == 0 && "End of list is not null?"); + *PtrListEnd = &Entry; + PtrListEnd = Entry.second.setPrevInList(PtrListEnd); + assert(*PtrListEnd == 0 && "End of list is not null?"); + addRef(); // Entry points to alias set... +} + +void AliasSet::addCallSite(CallSite CS, AliasAnalysis &AA) { + CallSites.push_back(CS); + + if (Function *F = CS.getCalledFunction()) { + AliasAnalysis::ModRefBehavior Behavior = AA.getModRefBehavior(F, CS); + if (Behavior == AliasAnalysis::DoesNotAccessMemory) + return; + else if (Behavior == AliasAnalysis::OnlyReadsMemory) { + AliasTy = MayAlias; + AccessTy |= Refs; + return; + } + } + + // FIXME: This should use mod/ref information to make this not suck so bad + AliasTy = MayAlias; + AccessTy = ModRef; +} + +/// aliasesPointer - Return true if the specified pointer "may" (or must) /// alias one of the members in the set. /// -bool AliasSet::pointerAliasesSet(const Value *Ptr, AliasAnalysis &AA) const { - if (!Calls.empty() || !Invokes.empty()) - return true; - for (unsigned i = 0, e = Loads.size(); i != e; ++i) - if (AA.alias(Ptr, Loads[i]->getOperand(0))) +bool AliasSet::aliasesPointer(const Value *Ptr, unsigned Size, + AliasAnalysis &AA) const { + if (AliasTy == MustAlias) { + assert(CallSites.empty() && "Illegal must alias set!"); + + // If this is a set of MustAliases, only check to see if the pointer aliases + // SOME value in the set... + HashNodePair *SomePtr = getSomePointer(); + assert(SomePtr && "Empty must-alias set??"); + return AA.alias(SomePtr->first, SomePtr->second.getSize(), Ptr, Size); + } + + // If this is a may-alias set, we have to check all of the pointers in the set + // to be sure it doesn't alias the set... + for (iterator I = begin(), E = end(); I != E; ++I) + if (AA.alias(Ptr, Size, I.getPointer(), I.getSize())) return true; - for (unsigned i = 0, e = Stores.size(); i != e; ++i) - if (AA.alias(Ptr, Stores[i]->getOperand(1))) + + // Check the call sites list and invoke list... + if (!CallSites.empty()) { + if (AA.hasNoModRefInfoForCalls()) return true; + + for (unsigned i = 0, e = CallSites.size(); i != e; ++i) + if (AA.getModRefInfo(CallSites[i], const_cast(Ptr), Size) + != AliasAnalysis::NoModRef) + return true; + } + return false; } -/// getSomePointer - This method may only be called when the AliasType of the -/// set is MustAlias. This is used to return any old pointer (which must alias -/// all other pointers in the set) so that the caller can decide whether to turn -/// this set into a may alias set or not. -/// -Value *AliasSet::getSomePointer() const { - assert(getAliasType() == MustAlias && - "Cannot call getSomePointer on a 'MayAlias' set!"); - assert(Calls.empty() && Invokes.empty() && "Call/invokes mean may alias!"); +bool AliasSet::aliasesCallSite(CallSite CS, AliasAnalysis &AA) const { + if (Function *F = CS.getCalledFunction()) + if (AA.doesNotAccessMemory(F)) + return false; - if (!Loads.empty()) - return Loads[0]->getOperand(0); - assert(!Stores.empty() && "There are no instructions in this set!"); - return Stores[0]->getOperand(1); -} + if (AA.hasNoModRefInfoForCalls()) + return true; + + for (unsigned i = 0, e = CallSites.size(); i != e; ++i) + if (AA.getModRefInfo(CallSites[i], CS) != AliasAnalysis::NoModRef || + AA.getModRefInfo(CS, CallSites[i]) != AliasAnalysis::NoModRef) + return true; + + for (iterator I = begin(), E = end(); I != E; ++I) + if (AA.getModRefInfo(CS, I.getPointer(), I.getSize()) != + AliasAnalysis::NoModRef) + return true; + return false; +} /// findAliasSetForPointer - Given a pointer, find the one alias set to put the /// instruction referring to the pointer into. If there are multiple alias sets /// that may alias the pointer, merge them together and return the unified set. /// -AliasSet *AliasSetTracker::findAliasSetForPointer(const Value *Ptr) { +AliasSet *AliasSetTracker::findAliasSetForPointer(const Value *Ptr, + unsigned Size) { AliasSet *FoundSet = 0; - for (unsigned i = 0; i != AliasSets.size(); ++i) { - if (AliasSets[i].pointerAliasesSet(Ptr, AA)) { - if (FoundSet == 0) { // If this is the first alias set ptr can go into... - FoundSet = &AliasSets[i]; // Remember it. - } else { // Otherwise, we must merge the sets... - FoundSet->mergeSetIn(AliasSets[i]); // Merge in contents... - AliasSets.erase(AliasSets.begin()+i); // Remove the set... - --i; // Don't skip the next set + for (iterator I = begin(), E = end(); I != E; ++I) + if (!I->Forward && I->aliasesPointer(Ptr, Size, AA)) { + if (FoundSet == 0) { // If this is the first alias set ptr can go into. + FoundSet = I; // Remember it. + } else { // Otherwise, we must merge the sets. + FoundSet->mergeSetIn(*I, *this); // Merge in contents. } } - } return FoundSet; } +/// containsPointer - Return true if the specified location is represented by +/// this alias set, false otherwise. This does not modify the AST object or +/// alias sets. +bool AliasSetTracker::containsPointer(Value *Ptr, unsigned Size) const { + for (const_iterator I = begin(), E = end(); I != E; ++I) + if (!I->Forward && I->aliasesPointer(Ptr, Size, AA)) + return true; + return false; +} -void AliasSetTracker::add(LoadInst *LI) { - Value *Pointer = LI->getOperand(0); - // Check to see if the loaded pointer aliases any sets... - AliasSet *AS = findAliasSetForPointer(Pointer); - if (AS) { - AS->Loads.push_back(LI); - // Check to see if we need to change this into a MayAlias set now... - if (AS->getAliasType() == AliasSet::MustAlias) - if (AA.alias(AS->getSomePointer(), Pointer) != AliasAnalysis::MustAlias) - AS->AliasTy = AliasSet::MayAlias; - AS->updateAccessType(); + +AliasSet *AliasSetTracker::findAliasSetForCallSite(CallSite CS) { + AliasSet *FoundSet = 0; + for (iterator I = begin(), E = end(); I != E; ++I) + if (!I->Forward && I->aliasesCallSite(CS, AA)) { + if (FoundSet == 0) { // If this is the first alias set ptr can go into. + FoundSet = I; // Remember it. + } else if (!I->Forward) { // Otherwise, we must merge the sets. + FoundSet->mergeSetIn(*I, *this); // Merge in contents. + } + } + + return FoundSet; +} + + + + +/// getAliasSetForPointer - Return the alias set that the specified pointer +/// lives in... +AliasSet &AliasSetTracker::getAliasSetForPointer(Value *Pointer, unsigned Size, + bool *New) { + AliasSet::HashNodePair &Entry = getEntryFor(Pointer); + + // Check to see if the pointer is already known... + if (Entry.second.hasAliasSet()) { + Entry.second.updateSize(Size); + // Return the set! + return *Entry.second.getAliasSet(*this)->getForwardedTarget(*this); + } else if (AliasSet *AS = findAliasSetForPointer(Pointer, Size)) { + // Add it to the alias set it aliases... + AS->addPointer(*this, Entry, Size); + return *AS; } else { - // Otherwise create a new alias set to hold the load... - AliasSets.push_back(AliasSet()); - AliasSets.back().Loads.push_back(LI); - AliasSets.back().AccessTy = AliasSet::Refs; + if (New) *New = true; + // Otherwise create a new alias set to hold the loaded pointer... + AliasSets.push_back(new AliasSet()); + AliasSets.back().addPointer(*this, Entry, Size); + return AliasSets.back(); } } -void AliasSetTracker::add(StoreInst *SI) { - Value *Pointer = SI->getOperand(1); +bool AliasSetTracker::add(Value *Ptr, unsigned Size) { + bool NewPtr; + addPointer(Ptr, Size, AliasSet::NoModRef, NewPtr); + return NewPtr; +} + + +bool AliasSetTracker::add(LoadInst *LI) { + bool NewPtr; + AliasSet &AS = addPointer(LI->getOperand(0), + AA.getTargetData().getTypeSize(LI->getType()), + AliasSet::Refs, NewPtr); + if (LI->isVolatile()) AS.setVolatile(); + return NewPtr; +} - // Check to see if the loaded pointer aliases any sets... - AliasSet *AS = findAliasSetForPointer(Pointer); - if (AS) { - AS->Stores.push_back(SI); - // Check to see if we need to change this into a MayAlias set now... - if (AS->getAliasType() == AliasSet::MustAlias) - if (AA.alias(AS->getSomePointer(), Pointer) != AliasAnalysis::MustAlias) - AS->AliasTy = AliasSet::MayAlias; - AS->updateAccessType(); +bool AliasSetTracker::add(StoreInst *SI) { + bool NewPtr; + Value *Val = SI->getOperand(0); + AliasSet &AS = addPointer(SI->getOperand(1), + AA.getTargetData().getTypeSize(Val->getType()), + AliasSet::Mods, NewPtr); + if (SI->isVolatile()) AS.setVolatile(); + return NewPtr; +} + +bool AliasSetTracker::add(FreeInst *FI) { + bool NewPtr; + AliasSet &AS = addPointer(FI->getOperand(0), ~0, + AliasSet::Mods, NewPtr); + + // Free operations are volatile ops (cannot be moved). + AS.setVolatile(); + return NewPtr; +} + + +bool AliasSetTracker::add(CallSite CS) { + if (Function *F = CS.getCalledFunction()) + if (AA.doesNotAccessMemory(F)) + return true; // doesn't alias anything + + AliasSet *AS = findAliasSetForCallSite(CS); + if (!AS) { + AliasSets.push_back(new AliasSet()); + AS = &AliasSets.back(); + AS->addCallSite(CS, AA); + return true; } else { - // Otherwise create a new alias set to hold the load... - AliasSets.push_back(AliasSet()); - AliasSets.back().Stores.push_back(SI); - AliasSets.back().AccessTy = AliasSet::Mods; + AS->addCallSite(CS, AA); + return false; } } +bool AliasSetTracker::add(Instruction *I) { + // Dispatch to one of the other add methods... + if (LoadInst *LI = dyn_cast(I)) + return add(LI); + else if (StoreInst *SI = dyn_cast(I)) + return add(SI); + else if (CallInst *CI = dyn_cast(I)) + return add(CI); + else if (InvokeInst *II = dyn_cast(I)) + return add(II); + else if (FreeInst *FI = dyn_cast(I)) + return add(FI); + return true; +} + +void AliasSetTracker::add(BasicBlock &BB) { + for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I) + add(I); +} + +void AliasSetTracker::add(const AliasSetTracker &AST) { + assert(&AA == &AST.AA && + "Merging AliasSetTracker objects with different Alias Analyses!"); -void AliasSetTracker::mergeAllSets() { - if (AliasSets.size() < 2) return; // Noop + // Loop over all of the alias sets in AST, adding the pointers contained + // therein into the current alias sets. This can cause alias sets to be + // merged together in the current AST. + for (const_iterator I = AST.begin(), E = AST.end(); I != E; ++I) + if (!I->Forward) { // Ignore forwarding alias sets + AliasSet &AS = const_cast(*I); - // Merge all of the sets into set #0 - for (unsigned i = 1, e = AliasSets.size(); i != e; ++i) - AliasSets[0].mergeSetIn(AliasSets[i]); + // If there are any call sites in the alias set, add them to this AST. + for (unsigned i = 0, e = AS.CallSites.size(); i != e; ++i) + add(AS.CallSites[i]); - // Delete extraneous sets... - AliasSets.erase(AliasSets.begin()+1, AliasSets.end()); + // Loop over all of the pointers in this alias set... + AliasSet::iterator I = AS.begin(), E = AS.end(); + bool X; + for (; I != E; ++I) { + AliasSet &NewAS = addPointer(I.getPointer(), I.getSize(), + (AliasSet::AccessType)AS.AccessTy, X); + if (AS.isVolatile()) NewAS.setVolatile(); + } + } } -void AliasSetTracker::add(CallInst *CI) { - if (!AliasSets.empty()) { - mergeAllSets(); - } else { - AliasSets.push_back(AliasSet()); +/// remove - Remove the specified (potentially non-empty) alias set from the +/// tracker. +void AliasSetTracker::remove(AliasSet &AS) { + // Drop all call sites. + AS.CallSites.clear(); + + // Clear the alias set. + unsigned NumRefs = 0; + while (!AS.empty()) { + AliasSet::HashNodePair *P = AS.PtrList; + + // Unlink from the list of values. + P->second.removeFromList(); + + // Remember how many references need to be dropped. + ++NumRefs; + + // Finally, remove the entry. + Value *Remove = P->first; // Take a copy because it is invalid to pass + PointerMap.erase(Remove); // a reference to the data being erased. } - AliasSets[0].AccessTy = AliasSet::ModRef; - AliasSets[0].AliasTy = AliasSet::MayAlias; - AliasSets[0].Calls.push_back(CI); + + // Stop using the alias set, removing it. + AS.RefCount -= NumRefs; + if (AS.RefCount == 0) + AS.removeFromTracker(*this); } -void AliasSetTracker::add(InvokeInst *II) { - if (!AliasSets.empty()) { - mergeAllSets(); - } else { - AliasSets.push_back(AliasSet()); +bool AliasSetTracker::remove(Value *Ptr, unsigned Size) { + AliasSet *AS = findAliasSetForPointer(Ptr, Size); + if (!AS) return false; + remove(*AS); + return true; +} + +bool AliasSetTracker::remove(LoadInst *LI) { + unsigned Size = AA.getTargetData().getTypeSize(LI->getType()); + AliasSet *AS = findAliasSetForPointer(LI->getOperand(0), Size); + if (!AS) return false; + remove(*AS); + return true; +} + +bool AliasSetTracker::remove(StoreInst *SI) { + unsigned Size = AA.getTargetData().getTypeSize(SI->getOperand(0)->getType()); + AliasSet *AS = findAliasSetForPointer(SI->getOperand(1), Size); + if (!AS) return false; + remove(*AS); + return true; +} + +bool AliasSetTracker::remove(FreeInst *FI) { + AliasSet *AS = findAliasSetForPointer(FI->getOperand(0), ~0); + if (!AS) return false; + remove(*AS); + return true; +} + +bool AliasSetTracker::remove(CallSite CS) { + if (Function *F = CS.getCalledFunction()) + if (AA.doesNotAccessMemory(F)) + return false; // doesn't alias anything + + AliasSet *AS = findAliasSetForCallSite(CS); + if (!AS) return false; + remove(*AS); + return true; +} + +bool AliasSetTracker::remove(Instruction *I) { + // Dispatch to one of the other remove methods... + if (LoadInst *LI = dyn_cast(I)) + return remove(LI); + else if (StoreInst *SI = dyn_cast(I)) + return remove(SI); + else if (CallInst *CI = dyn_cast(I)) + return remove(CI); + else if (FreeInst *FI = dyn_cast(I)) + return remove(FI); + return true; +} + + +// deleteValue method - This method is used to remove a pointer value from the +// AliasSetTracker entirely. It should be used when an instruction is deleted +// from the program to update the AST. If you don't use this, you would have +// dangling pointers to deleted instructions. +// +void AliasSetTracker::deleteValue(Value *PtrVal) { + // Notify the alias analysis implementation that this value is gone. + AA.deleteValue(PtrVal); + + // If this is a call instruction, remove the callsite from the appropriate + // AliasSet. + CallSite CS = CallSite::get(PtrVal); + if (CS.getInstruction()) { + Function *F = CS.getCalledFunction(); + if (!F || !AA.doesNotAccessMemory(F)) { + if (AliasSet *AS = findAliasSetForCallSite(CS)) + AS->removeCallSite(CS); + } } - AliasSets[0].AccessTy = AliasSet::ModRef; - AliasSets[0].AliasTy = AliasSet::MayAlias; - AliasSets[0].Invokes.push_back(II); + + // First, look up the PointerRec for this pointer. + hash_map::iterator I = PointerMap.find(PtrVal); + if (I == PointerMap.end()) return; // Noop + + // If we found one, remove the pointer from the alias set it is in. + AliasSet::HashNodePair &PtrValEnt = *I; + AliasSet *AS = PtrValEnt.second.getAliasSet(*this); + + // Unlink from the list of values... + PtrValEnt.second.removeFromList(); + // Stop using the alias set + AS->dropRef(*this); + PointerMap.erase(I); +} + +// copyValue - This method should be used whenever a preexisting value in the +// program is copied or cloned, introducing a new value. Note that it is ok for +// clients that use this method to introduce the same value multiple times: if +// the tracker already knows about a value, it will ignore the request. +// +void AliasSetTracker::copyValue(Value *From, Value *To) { + // Notify the alias analysis implementation that this value is copied. + AA.copyValue(From, To); + + // First, look up the PointerRec for this pointer. + hash_map::iterator I = PointerMap.find(From); + if (I == PointerMap.end() || !I->second.hasAliasSet()) + return; // Noop + + AliasSet::HashNodePair &Entry = getEntryFor(To); + if (Entry.second.hasAliasSet()) return; // Already in the tracker! + + // Add it to the alias set it aliases... + AliasSet *AS = I->second.getAliasSet(*this); + AS->addPointer(*this, Entry, I->second.getSize(), true); +} + + + +//===----------------------------------------------------------------------===// +// AliasSet/AliasSetTracker Printing Support +//===----------------------------------------------------------------------===// + +void AliasSet::print(std::ostream &OS) const { + OS << " AliasSet[" << (void*)this << "," << RefCount << "] "; + OS << (AliasTy == MustAlias ? "must" : "may ") << " alias, "; + switch (AccessTy) { + case NoModRef: OS << "No access "; break; + case Refs : OS << "Ref "; break; + case Mods : OS << "Mod "; break; + case ModRef : OS << "Mod/Ref "; break; + default: assert(0 && "Bad value for AccessTy!"); + } + if (isVolatile()) OS << "[volatile] "; + if (Forward) + OS << " forwarding to " << (void*)Forward; + + + if (begin() != end()) { + OS << "Pointers: "; + for (iterator I = begin(), E = end(); I != E; ++I) { + if (I != begin()) OS << ", "; + WriteAsOperand(OS << "(", I.getPointer()); + OS << ", " << I.getSize() << ")"; + } + } + if (!CallSites.empty()) { + OS << "\n " << CallSites.size() << " Call Sites: "; + for (unsigned i = 0, e = CallSites.size(); i != e; ++i) { + if (i) OS << ", "; + WriteAsOperand(OS, CallSites[i].getCalledValue()); + } + } + OS << "\n"; +} + +void AliasSetTracker::print(std::ostream &OS) const { + OS << "Alias Set Tracker: " << AliasSets.size() << " alias sets for " + << PointerMap.size() << " pointer values.\n"; + for (const_iterator I = begin(), E = end(); I != E; ++I) + I->print(OS); + OS << "\n"; +} + +void AliasSet::dump() const { print (cerr); } +void AliasSetTracker::dump() const { print(cerr); } + +//===----------------------------------------------------------------------===// +// AliasSetPrinter Pass +//===----------------------------------------------------------------------===// + +namespace { + class VISIBILITY_HIDDEN AliasSetPrinter : public FunctionPass { + AliasSetTracker *Tracker; + public: + static char ID; // Pass identification, replacement for typeid + AliasSetPrinter() : FunctionPass((intptr_t)&ID) {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); + } + + virtual bool runOnFunction(Function &F) { + Tracker = new AliasSetTracker(getAnalysis()); + + for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) + Tracker->add(&*I); + Tracker->print(cerr); + delete Tracker; + return false; + } + }; + char AliasSetPrinter::ID = 0; + RegisterPass X("print-alias-sets", "Alias Set Printer"); }