From 009cc3d2e85674f01f70d915e0c802d89d0b672f Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Thu, 26 Sep 2002 21:49:07 +0000 Subject: [PATCH] First try at implementing the AliasSetTracker class. I'm sure it will need revision as I start to use it though. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@3954 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Analysis/AliasSetTracker.h | 109 +++++++++++++++ lib/Analysis/AliasSetTracker.cpp | 172 ++++++++++++++++++++++++ 2 files changed, 281 insertions(+) create mode 100644 include/llvm/Analysis/AliasSetTracker.h create mode 100644 lib/Analysis/AliasSetTracker.cpp diff --git a/include/llvm/Analysis/AliasSetTracker.h b/include/llvm/Analysis/AliasSetTracker.h new file mode 100644 index 00000000000..b7de04ce27f --- /dev/null +++ b/include/llvm/Analysis/AliasSetTracker.h @@ -0,0 +1,109 @@ +//===- llvm/Analysis/AliasSetTracker.h - Build Alias Sets -------*- C++ -*-===// +// +// This file defines two classes: AliasSetTracker and AliasSet. These interface +// are used to classify a collection of pointer references into a maximal number +// of disjoint sets. Each AliasSet object constructed by the AliasSetTracker +// object refers to memory disjoint from the other sets. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_ALIASSETTRACKER_H +#define LLVM_ANALYSIS_ALIASSETTRACKER_H + +#include +class AliasAnalysis; +class LoadInst; +class StoreInst; +class CallInst; +class InvokeInst; +class Value; +class AliasSetTracker; + +class AliasSet { + friend class AliasSetTracker; + std::vector Loads; + std::vector Stores; + std::vector Calls; + std::vector Invokes; +public: + /// AccessType - Keep track of whether this alias set merely refers to the + /// locations of memory, whether it modifies the memory, or whether it does + /// both. The lattice goes from "None" (alias set not present) to either Refs + /// or Mods, then to ModRef as neccesary. + /// + enum AccessType { + Refs, Mods, ModRef + }; + + /// AliasType - Keep track the relationships between the pointers in the set. + /// Lattice goes from MustAlias to MayAlias. + /// + enum AliasType { + MustAlias, MayAlias + }; +private: + enum AccessType AccessTy; + enum AliasType AliasTy; +public: + /// Accessors... + enum AccessType getAccessType() const { return AccessTy; } + enum AliasType getAliasType() const { return AliasTy; } + + // TODO: in the future, add a fixed size (4? 2?) cache of pointers that we + // know are in the alias set, to cut down time answering "pointeraliasesset" + // queries. + + /// pointerAliasesSet - Return true if the specified pointer "may" (or must) + /// alias one of the members in the set. + /// + bool pointerAliasesSet(const Value *Ptr, AliasAnalysis &AA) const; + + /// mergeSetIn - Merge the specified alias set into this alias set... + /// + void mergeSetIn(const AliasSet &AS); + + const std::vector &getLoads() const { return Loads; } + const std::vector &getStores() const { return Stores; } + const std::vector &getCalls() const { return Calls; } + const std::vector &getInvokes() const { return Invokes; } + +private: + AliasSet() : AliasTy(MustAlias) {} // Can only be created by AliasSetTracker + void updateAccessType(); + Value *getSomePointer() const; +}; + + +class AliasSetTracker { + AliasAnalysis &AA; + std::vector AliasSets; +public: + /// AliasSetTracker ctor - Create an empty collection of AliasSets, and use + /// the specified alias analysis object to disambiguate load and store + /// addresses. + AliasSetTracker(AliasAnalysis &aa) : AA(aa) {} + + + /// add methods - These methods are used to add different types of + /// instructions to the alias sets. Adding a new instruction can result in + /// one of three actions happening: + /// + /// 1. If the instruction doesn't alias any other sets, create a new set. + /// 2. If the instruction aliases exactly one set, add it to the set + /// 3. If the instruction aliases multiple sets, merge the sets, and add + /// the instruction to the result. + /// + void add(LoadInst *LI); + void add(StoreInst *SI); + void add(CallInst *CI); + void add(InvokeInst *II); + + /// getAliasSets - Return the alias sets that are active. + const std::vector &getAliasSets() const { return AliasSets; } + +private: + AliasSet *findAliasSetForPointer(const Value *Ptr); + void mergeAllSets(); +}; + +#endif diff --git a/lib/Analysis/AliasSetTracker.cpp b/lib/Analysis/AliasSetTracker.cpp new file mode 100644 index 00000000000..1413660d92e --- /dev/null +++ b/lib/Analysis/AliasSetTracker.cpp @@ -0,0 +1,172 @@ +//===- AliasSetTracker.cpp - Alias Sets Tracker implementation-------------===// +// +// 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" + +/// updateAccessTypes - Depending on what type of accesses are in this set, +/// decide whether the set contains just references, just modifications, or a +/// mix. +/// +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; + } +} + +/// 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()); + + // Update the alias and access types of this set... + if (AS.getAliasType() == MayAlias) + AliasTy = MayAlias; + updateAccessType(); +} + +/// pointerAliasesSet - 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))) + return true; + for (unsigned i = 0, e = Stores.size(); i != e; ++i) + if (AA.alias(Ptr, Stores[i]->getOperand(1))) + 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!"); + + if (!Loads.empty()) + return Loads[0]->getOperand(0); + assert(!Stores.empty() && "There are no instructions in this set!"); + return Stores[0]->getOperand(1); +} + + + +/// 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 *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 + } + } + } + + return FoundSet; +} + + +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(); + } 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; + } +} + +void AliasSetTracker::add(StoreInst *SI) { + Value *Pointer = SI->getOperand(1); + + // 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(); + } 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; + } +} + + +void AliasSetTracker::mergeAllSets() { + if (AliasSets.size() < 2) return; // Noop + + // Merge all of the sets into set #0 + for (unsigned i = 1, e = AliasSets.size(); i != e; ++i) + AliasSets[0].mergeSetIn(AliasSets[i]); + + // Delete extraneous sets... + AliasSets.erase(AliasSets.begin()+1, AliasSets.end()); +} + +void AliasSetTracker::add(CallInst *CI) { + if (!AliasSets.empty()) { + mergeAllSets(); + } else { + AliasSets.push_back(AliasSet()); + } + AliasSets[0].AccessTy = AliasSet::ModRef; + AliasSets[0].AliasTy = AliasSet::MayAlias; + AliasSets[0].Calls.push_back(CI); +} + +void AliasSetTracker::add(InvokeInst *II) { + if (!AliasSets.empty()) { + mergeAllSets(); + } else { + AliasSets.push_back(AliasSet()); + } + AliasSets[0].AccessTy = AliasSet::ModRef; + AliasSets[0].AliasTy = AliasSet::MayAlias; + AliasSets[0].Invokes.push_back(II); +}