diff options
author | Dan Gohman <gohman@apple.com> | 2010-09-14 21:25:10 +0000 |
---|---|---|
committer | Dan Gohman <gohman@apple.com> | 2010-09-14 21:25:10 +0000 |
commit | b2143b6247901ae4eca2192ee134564c4f5f7853 (patch) | |
tree | 7991b48f4a6ee8090de80fbb9cb17c6ed75d6227 | |
parent | fe3ac088ee0a536f60b3c30ad97703d5d6cd2167 (diff) |
Remove the experimental AliasAnalysis::getDependency interface, which
isn't a good level of abstraction for memdep. Instead, generalize
AliasAnalysis::alias and related interfaces with a new Location
class for describing a memory location. For now, this is the same
Pointer and Size as before, plus an additional field for a TBAA tag.
Also, introduce a fixed MD_tbaa metadata tag kind.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@113858 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/llvm/Analysis/AliasAnalysis.h | 235 | ||||
-rw-r--r-- | include/llvm/Analysis/LibCallAliasAnalysis.h | 4 | ||||
-rw-r--r-- | include/llvm/Analysis/LibCallSemantics.h | 2 | ||||
-rw-r--r-- | include/llvm/LLVMContext.h | 3 | ||||
-rw-r--r-- | lib/Analysis/AliasAnalysis.cpp | 285 | ||||
-rw-r--r-- | lib/Analysis/AliasAnalysisCounter.cpp | 30 | ||||
-rw-r--r-- | lib/Analysis/AliasDebugger.cpp | 23 | ||||
-rw-r--r-- | lib/Analysis/BasicAliasAnalysis.cpp | 89 | ||||
-rw-r--r-- | lib/Analysis/IPA/GlobalsModRef.cpp | 22 | ||||
-rw-r--r-- | lib/Analysis/LibCallAliasAnalysis.cpp | 18 | ||||
-rw-r--r-- | lib/Analysis/ScalarEvolutionAliasAnalysis.cpp | 29 | ||||
-rw-r--r-- | lib/Analysis/TypeBasedAliasAnalysis.cpp | 17 | ||||
-rw-r--r-- | lib/VMCore/LLVMContext.cpp | 9 |
13 files changed, 256 insertions, 510 deletions
diff --git a/include/llvm/Analysis/AliasAnalysis.h b/include/llvm/Analysis/AliasAnalysis.h index a03e0c8806..cae7addd3b 100644 --- a/include/llvm/Analysis/AliasAnalysis.h +++ b/include/llvm/Analysis/AliasAnalysis.h @@ -83,6 +83,22 @@ public: /// Alias Queries... /// + /// Location - A description of a memory location. + struct Location { + /// Ptr - The address of the start of the location. + const Value *Ptr; + /// Size - The size of the location. + unsigned Size; + /// TBAATag - The metadata node which describes the TBAA type of + /// the location, or null if there is no (unique) tag. + const MDNode *TBAATag; + + explicit Location(const Value *P = 0, + unsigned S = UnknownSize, + const MDNode *N = 0) + : Ptr(P), Size(S), TBAATag(N) {} + }; + /// Alias analysis result - Either we know for sure that it does not alias, we /// know for sure it must alias, or we don't know anything: The two pointers /// _might_ alias. This enum is designed so you can do things like: @@ -98,27 +114,41 @@ public: /// Returns a Result indicating whether the two pointers are aliased to each /// other. This is the interface that must be implemented by specific alias /// analysis implementations. - /// - virtual AliasResult alias(const Value *V1, unsigned V1Size, - const Value *V2, unsigned V2Size); + virtual AliasResult alias(const Location &LocA, const Location &LocB); - /// alias - A convenience wrapper for the case where the sizes are unknown. + /// alias - A convenience wrapper. + AliasResult alias(const Value *V1, unsigned V1Size, + const Value *V2, unsigned V2Size) { + return alias(Location(V1, V1Size), Location(V2, V2Size)); + } + + /// alias - A convenience wrapper. AliasResult alias(const Value *V1, const Value *V2) { return alias(V1, UnknownSize, V2, UnknownSize); } /// isNoAlias - A trivial helper function to check to see if the specified /// pointers are no-alias. + bool isNoAlias(const Location &LocA, const Location &LocB) { + return alias(LocA, LocB) == NoAlias; + } + + /// isNoAlias - A convenience wrapper. bool isNoAlias(const Value *V1, unsigned V1Size, const Value *V2, unsigned V2Size) { - return alias(V1, V1Size, V2, V2Size) == NoAlias; + return isNoAlias(Location(V1, V1Size), Location(V2, V2Size)); } - /// pointsToConstantMemory - If the specified pointer is known to point into - /// constant global memory, return true. This allows disambiguation of store + /// pointsToConstantMemory - If the specified memory location is known to be + /// constant, return true. This allows disambiguation of store /// instructions from constant pointers. /// - virtual bool pointsToConstantMemory(const Value *P); + virtual bool pointsToConstantMemory(const Location &Loc); + + /// pointsToConstantMemory - A convenient wrapper. + bool pointsToConstantMemory(const Value *P) { + return pointsToConstantMemory(Location(P)); + } //===--------------------------------------------------------------------===// /// Simple mod/ref information... @@ -220,55 +250,87 @@ public: /// getModRefInfo - Return information about whether or not an instruction may - /// read or write memory specified by the pointer operand. An instruction + /// read or write the specified memory location. An instruction /// that doesn't read or write memory may be trivially LICM'd for example. ModRefResult getModRefInfo(const Instruction *I, - const Value *P, unsigned Size) { + const Location &Loc) { switch (I->getOpcode()) { - case Instruction::VAArg: return getModRefInfo((const VAArgInst*)I, P,Size); - case Instruction::Load: return getModRefInfo((const LoadInst*)I, P, Size); - case Instruction::Store: return getModRefInfo((const StoreInst*)I, P,Size); - case Instruction::Call: return getModRefInfo((const CallInst*)I, P, Size); - case Instruction::Invoke: return getModRefInfo((const InvokeInst*)I,P,Size); + case Instruction::VAArg: return getModRefInfo((const VAArgInst*)I, Loc); + case Instruction::Load: return getModRefInfo((const LoadInst*)I, Loc); + case Instruction::Store: return getModRefInfo((const StoreInst*)I, Loc); + case Instruction::Call: return getModRefInfo((const CallInst*)I, Loc); + case Instruction::Invoke: return getModRefInfo((const InvokeInst*)I,Loc); default: return NoModRef; } } + /// getModRefInfo - A convenience wrapper. + ModRefResult getModRefInfo(const Instruction *I, + const Value *P, unsigned Size) { + return getModRefInfo(I, Location(P, Size)); + } + /// getModRefInfo (for call sites) - Return whether information about whether - /// a particular call site modifies or reads the memory specified by the - /// pointer. + /// a particular call site modifies or reads the specified memory location. virtual ModRefResult getModRefInfo(ImmutableCallSite CS, - const Value *P, unsigned Size); + const Location &Loc); + + /// getModRefInfo (for call sites) - A convenience wrapper. + ModRefResult getModRefInfo(ImmutableCallSite CS, + const Value *P, unsigned Size) { + return getModRefInfo(CS, Location(P, Size)); + } /// getModRefInfo (for calls) - Return whether information about whether - /// a particular call modifies or reads the memory specified by the - /// pointer. + /// a particular call modifies or reads the specified memory location. + ModRefResult getModRefInfo(const CallInst *C, const Location &Loc) { + return getModRefInfo(ImmutableCallSite(C), Loc); + } + + /// getModRefInfo (for calls) - A convenience wrapper. ModRefResult getModRefInfo(const CallInst *C, const Value *P, unsigned Size) { - return getModRefInfo(ImmutableCallSite(C), P, Size); + return getModRefInfo(C, Location(P, Size)); } /// getModRefInfo (for invokes) - Return whether information about whether - /// a particular invoke modifies or reads the memory specified by the - /// pointer. + /// a particular invoke modifies or reads the specified memory location. + ModRefResult getModRefInfo(const InvokeInst *I, + const Location &Loc) { + return getModRefInfo(ImmutableCallSite(I), Loc); + } + + /// getModRefInfo (for invokes) - A convenience wrapper. ModRefResult getModRefInfo(const InvokeInst *I, const Value *P, unsigned Size) { - return getModRefInfo(ImmutableCallSite(I), P, Size); + return getModRefInfo(I, Location(P, Size)); } /// getModRefInfo (for loads) - Return whether information about whether - /// a particular load modifies or reads the memory specified by the - /// pointer. - ModRefResult getModRefInfo(const LoadInst *L, const Value *P, unsigned Size); + /// a particular load modifies or reads the specified memory location. + ModRefResult getModRefInfo(const LoadInst *L, const Location &Loc); + + /// getModRefInfo (for loads) - A convenience wrapper. + ModRefResult getModRefInfo(const LoadInst *L, const Value *P, unsigned Size) { + return getModRefInfo(L, Location(P, Size)); + } /// getModRefInfo (for stores) - Return whether information about whether - /// a particular store modifies or reads the memory specified by the - /// pointer. - ModRefResult getModRefInfo(const StoreInst *S, const Value *P, unsigned Size); + /// a particular store modifies or reads the specified memory location. + ModRefResult getModRefInfo(const StoreInst *S, const Location &Loc); + + /// getModRefInfo (for stores) - A convenience wrapper. + ModRefResult getModRefInfo(const StoreInst *S, const Value *P, unsigned Size) { + return getModRefInfo(S, Location(P, Size)); + } /// getModRefInfo (for va_args) - Return whether information about whether - /// a particular va_arg modifies or reads the memory specified by the - /// pointer. - ModRefResult getModRefInfo(const VAArgInst* I, const Value* P, unsigned Size); + /// a particular va_arg modifies or reads the specified memory location. + ModRefResult getModRefInfo(const VAArgInst* I, const Location &Loc); + + /// getModRefInfo (for va_args) - A convenience wrapper. + ModRefResult getModRefInfo(const VAArgInst* I, const Value* P, unsigned Size) { + return getModRefInfo(I, Location(P, Size)); + } /// getModRefInfo - Return information about whether two call sites may refer /// to the same set of memory locations. See @@ -278,100 +340,30 @@ public: ImmutableCallSite CS2); //===--------------------------------------------------------------------===// - /// Dependence queries. - /// - - /// DependenceResult - These are the return values for getDependence queries. - /// They are defined in terms of "memory", but they are also used to model - /// other side effects, such as I/O and volatility. - enum DependenceResult { - /// ReadThenRead - The instructions are ReadThenReadSome and the second - /// instruction reads from exactly the same memory read from by the first. - ReadThenRead, - - /// ReadThenReadSome - The instructions are Independent, both are read-only, - /// and the second instruction reads from a subset of the memory read from - /// by the first. - ReadThenReadSome, - - /// Independent - Neither instruction reads from or writes to memory written - /// to by the other. All enum values lower than this one are special cases - /// of Indepenent. - Independent, - - /// WriteThenRead - The instructions are WriteThenReadSome and the second - /// instruction reads from exactly the same memory written by the first. - WriteThenRead, - - /// WriteThenReadSome - The first instruction is write-only, the second - /// instruction is read-only, and the second only reads from memory - /// written to by the first. - WriteThenReadSome, - - /// ReadThenWrite - The first instruction is read-only, the second - /// instruction is write-only, and the second wrotes to exactly the - /// same memory read from by the first. - ReadThenWrite, - - /// WriteThenWrite - The instructions are WriteThenWriteSome, and the - /// second instruction writes to exactly the same memory written to by - /// the first. - WriteThenWrite, - - /// WriteSomeThenWrite - Both instructions are write-only, and the second - /// instruction writes to a superset of the memory written to by the first. - WriteSomeThenWrite, - - /// Unknown - The relationship between the instructions cannot be - /// determined or does not fit into any of the cases defined here. - Unknown - }; - - /// DependenceQueryFlags - Flags for refining dependence queries. - enum DependenceQueryFlags { - Default = 0, - IgnoreLoads = 1, - IgnoreStores = 2 - }; - - /// getDependence - Determine the dependence relationship between the - /// instructions. This does not include "register" dependencies; it just - /// considers memory references and other side effects. - /// WARNING: This is an experimental interface. - DependenceResult getDependence(const Instruction *First, - const Instruction *Second) { - return getDependence(First, 0, Default, Second, 0, Default); - } - - /// getDependence - Determine the dependence relationship between the - /// instructions. This does not include "register" dependencies; it just - /// considers memory references and other side effects. This overload - /// has additional parameters to allow phi-translated addresses to be - /// specified, and additional flags to refine the query. - /// WARNING: This is an experimental interface. - virtual DependenceResult getDependence(const Instruction *First, - const Value *FirstPHITranslatedAddr, - DependenceQueryFlags FirstFlags, - const Instruction *Second, - const Value *SecondPHITranslatedAddr, - DependenceQueryFlags SecondFlags); - - //===--------------------------------------------------------------------===// /// Higher level methods for querying mod/ref information. /// /// canBasicBlockModify - Return true if it is possible for execution of the /// specified basic block to modify the value pointed to by Ptr. - /// - bool canBasicBlockModify(const BasicBlock &BB, const Value *P, unsigned Size); + bool canBasicBlockModify(const BasicBlock &BB, const Location &Loc); + + /// canBasicBlockModify - A convenience wrapper. + bool canBasicBlockModify(const BasicBlock &BB, const Value *P, unsigned Size){ + return canBasicBlockModify(BB, Location(P, Size)); + } /// canInstructionRangeModify - Return true if it is possible for the /// execution of the specified instructions to modify the value pointed to by /// Ptr. The instructions to consider are all of the instructions in the /// range of [I1,I2] INCLUSIVE. I1 and I2 must be in the same basic block. - /// bool canInstructionRangeModify(const Instruction &I1, const Instruction &I2, - const Value *Ptr, unsigned Size); + const Location &Loc); + + /// canInstructionRangeModify - A convenience wrapper. + bool canInstructionRangeModify(const Instruction &I1, const Instruction &I2, + const Value *Ptr, unsigned Size) { + return canInstructionRangeModify(I1, I2, Location(Ptr, Size)); + } //===--------------------------------------------------------------------===// /// Methods that clients should call when they transform the program to allow @@ -401,17 +393,6 @@ public: copyValue(Old, New); deleteValue(Old); } - -protected: - /// getDependenceViaModRefInfo - Helper function for implementing getDependence - /// in implementations which already have getModRefInfo implementations. - DependenceResult getDependenceViaModRefInfo(const Instruction *First, - const Value *FirstPHITranslatedAddr, - DependenceQueryFlags FirstFlags, - const Instruction *Second, - const Value *SecondPHITranslatedAddr, - DependenceQueryFlags SecondFlags); - }; /// isNoAliasCall - Return true if this pointer is returned by a noalias diff --git a/include/llvm/Analysis/LibCallAliasAnalysis.h b/include/llvm/Analysis/LibCallAliasAnalysis.h index c9adf3f36a..7d7782ab7c 100644 --- a/include/llvm/Analysis/LibCallAliasAnalysis.h +++ b/include/llvm/Analysis/LibCallAliasAnalysis.h @@ -36,7 +36,7 @@ namespace llvm { ~LibCallAliasAnalysis(); ModRefResult getModRefInfo(ImmutableCallSite CS, - const Value *P, unsigned Size); + const Location &Loc); ModRefResult getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2) { @@ -64,7 +64,7 @@ namespace llvm { private: ModRefResult AnalyzeLibCallDetails(const LibCallFunctionInfo *FI, ImmutableCallSite CS, - const Value *P, unsigned Size); + const Location &Loc); }; } // End of llvm namespace diff --git a/include/llvm/Analysis/LibCallSemantics.h b/include/llvm/Analysis/LibCallSemantics.h index 31d7cc56ce..f5a9e96cbd 100644 --- a/include/llvm/Analysis/LibCallSemantics.h +++ b/include/llvm/Analysis/LibCallSemantics.h @@ -48,7 +48,7 @@ namespace llvm { Yes, No, Unknown }; LocResult (*isLocation)(ImmutableCallSite CS, - const Value *Ptr, unsigned Size); + const AliasAnalysis::Location &Loc); }; /// LibCallFunctionInfo - Each record in the array of FunctionInfo structs diff --git a/include/llvm/LLVMContext.h b/include/llvm/LLVMContext.h index 8abf277772..e5b77777d9 100644 --- a/include/llvm/LLVMContext.h +++ b/include/llvm/LLVMContext.h @@ -37,7 +37,8 @@ public: // Pinned metadata names, which always have the same value. This is a // compile-time performance optimization, not a correctness optimization. enum { - MD_dbg = 0 // "dbg" + MD_dbg = 0, // "dbg" + MD_tbaa = 1 // "tbaa" }; /// getMDKindID - Return a unique non-zero ID for the specified metadata kind. diff --git a/lib/Analysis/AliasAnalysis.cpp b/lib/Analysis/AliasAnalysis.cpp index 93597cab22..b9cd5a6920 100644 --- a/lib/Analysis/AliasAnalysis.cpp +++ b/lib/Analysis/AliasAnalysis.cpp @@ -30,6 +30,7 @@ #include "llvm/Function.h" #include "llvm/IntrinsicInst.h" #include "llvm/Instructions.h" +#include "llvm/LLVMContext.h" #include "llvm/Type.h" #include "llvm/Target/TargetData.h" using namespace llvm; @@ -43,15 +44,14 @@ char AliasAnalysis::ID = 0; //===----------------------------------------------------------------------===// AliasAnalysis::AliasResult -AliasAnalysis::alias(const Value *V1, unsigned V1Size, - const Value *V2, unsigned V2Size) { +AliasAnalysis::alias(const Location &LocA, const Location &LocB) { assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!"); - return AA->alias(V1, V1Size, V2, V2Size); + return AA->alias(LocA, LocB); } -bool AliasAnalysis::pointsToConstantMemory(const Value *P) { +bool AliasAnalysis::pointsToConstantMemory(const Location &Loc) { assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!"); - return AA->pointsToConstantMemory(P); + return AA->pointsToConstantMemory(Loc); } void AliasAnalysis::deleteValue(Value *V) { @@ -66,7 +66,7 @@ void AliasAnalysis::copyValue(Value *From, Value *To) { AliasAnalysis::ModRefResult AliasAnalysis::getModRefInfo(ImmutableCallSite CS, - const Value *P, unsigned Size) { + const Location &Loc) { // Don't assert AA because BasicAA calls us in order to make use of the // logic here. @@ -81,7 +81,7 @@ AliasAnalysis::getModRefInfo(ImmutableCallSite CS, bool doesAlias = false; for (ImmutableCallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end(); AI != AE; ++AI) - if (!isNoAlias(*AI, ~0U, P, Size)) { + if (!isNoAlias(Location(*AI), Loc)) { doesAlias = true; break; } @@ -90,9 +90,9 @@ AliasAnalysis::getModRefInfo(ImmutableCallSite CS, return NoModRef; } - // If P points to a constant memory location, the call definitely could not + // If Loc is a constant memory location, the call definitely could not // modify the memory location. - if ((Mask & Mod) && pointsToConstantMemory(P)) + if ((Mask & Mod) && pointsToConstantMemory(Loc)) Mask = ModRefResult(Mask & ~Mod); // If this is BasicAA, don't forward. @@ -100,7 +100,7 @@ AliasAnalysis::getModRefInfo(ImmutableCallSite CS, // Otherwise, fall back to the next AA in the chain. But we can merge // in any mask we've managed to compute. - return ModRefResult(AA->getModRefInfo(CS, P, Size) & Mask); + return ModRefResult(AA->getModRefInfo(CS, Loc) & Mask); } AliasAnalysis::ModRefResult @@ -188,31 +188,22 @@ AliasAnalysis::getModRefBehavior(const Function *F) { return AA->getModRefBehavior(F); } -AliasAnalysis::DependenceResult -AliasAnalysis::getDependence(const Instruction *First, - const Value *FirstPHITranslatedAddr, - DependenceQueryFlags FirstFlags, - const Instruction *Second, - const Value *SecondPHITranslatedAddr, - DependenceQueryFlags SecondFlags) { - assert(AA && "AA didn't call InitializeAliasAnalyais in its run method!"); - return AA->getDependence(First, FirstPHITranslatedAddr, FirstFlags, - Second, SecondPHITranslatedAddr, SecondFlags); -} - //===----------------------------------------------------------------------===// // AliasAnalysis non-virtual helper method implementation //===----------------------------------------------------------------------===// AliasAnalysis::ModRefResult -AliasAnalysis::getModRefInfo(const LoadInst *L, const Value *P, unsigned Size) { +AliasAnalysis::getModRefInfo(const LoadInst *L, const Location &Loc) { // Be conservative in the face of volatile. if (L->isVolatile()) return ModRef; // If the load address doesn't alias the given address, it doesn't read // or write the specified memory. - if (!alias(L->getOperand(0), getTypeStoreSize(L->getType()), P, Size)) + if (!alias(Location(L->getOperand(0), + getTypeStoreSize(L->getType()), + L->getMetadata(LLVMContext::MD_tbaa)), + Loc)) return NoModRef; // Otherwise, a load just reads. @@ -220,20 +211,22 @@ AliasAnalysis::getModRefInfo(const LoadInst *L, const Value *P, unsigned Size) { } AliasAnalysis::ModRefResult -AliasAnalysis::getModRefInfo(const StoreInst *S, const Value *P, unsigned Size) { +AliasAnalysis::getModRefInfo(const StoreInst *S, const Location &Loc) { // Be conservative in the face of volatile. if (S->isVolatile()) return ModRef; // If the store address cannot alias the pointer in question, then the // specified memory cannot be modified by the store. - if (!alias(S->getOperand(1), - getTypeStoreSize(S->getOperand(0)->getType()), P, Size)) + if (!alias(Location(S->getOperand(1), + getTypeStoreSize(S->getOperand(0)->getType()), + S->getMetadata(LLVMContext::MD_tbaa)), + Loc)) return NoModRef; // If the pointer is a pointer to constant memory, then it could not have been // modified by this store. - if (pointsToConstantMemory(P)) + if (pointsToConstantMemory(Loc)) return NoModRef; // Otherwise, a store just writes. @@ -241,240 +234,24 @@ AliasAnalysis::getModRefInfo(const StoreInst *S, const Value *P, unsigned Size) } AliasAnalysis::ModRefResult -AliasAnalysis::getModRefInfo(const VAArgInst *V, const Value *P, unsigned Size) { +AliasAnalysis::getModRefInfo(const VAArgInst *V, const Location &Loc) { // If the va_arg address cannot alias the pointer in question, then the // specified memory cannot be accessed by the va_arg. - if (!alias(V->getOperand(0), UnknownSize, P, Size)) + if (!alias(Location(V->getOperand(0), + UnknownSize, + V->getMetadata(LLVMContext::MD_tbaa)), + Loc)) return NoModRef; // If the pointer is a pointer to constant memory, then it could not have been // modified by this va_arg. - if (pointsToConstantMemory(P)) + if (pointsToConstantMemory(Loc)) return NoModRef; // Otherwise, a va_arg reads and writes. return ModRef; } -AliasAnalysis::DependenceResult -AliasAnalysis::getDependenceViaModRefInfo(const Instruction *First, - const Value *FirstPHITranslatedAddr, - DependenceQueryFlags FirstFlags, - const Instruction *Second, - const Value *SecondPHITranslatedAddr, - DependenceQueryFlags SecondFlags) { - if (const LoadInst *L = dyn_cast<LoadInst>(First)) { - // Be over-conservative with volatile for now. - if (L->isVolatile()) - return Unknown; - - // If we don't have a phi-translated address, use the actual one. - if (!FirstPHITranslatedAddr) - FirstPHITranslatedAddr = L->getPointerOperand(); - - // Forward this query to getModRefInfo. - switch (getModRefInfo(Second, - FirstPHITranslatedAddr, - getTypeStoreSize(L->getType()))) { - case NoModRef: - // Second doesn't reference First's memory, so they're independent. - return Independent; - - case Ref: - // Second only reads from the memory read from by First. If it - // also writes to any other memory, be conservative. - if (Second->mayWriteToMemory()) - return Unknown; - - // If it's loading the same size from the same address, we can - // give a more precise result. - if (const LoadInst *SecondL = dyn_cast<LoadInst>(Second)) { - // If we don't have a phi-translated address, use the actual one. - if (!SecondPHITranslatedAddr) - SecondPHITranslatedAddr = SecondL->getPointerOperand(); - - unsigned LSize = getTypeStoreSize(L->getType()); - unsigned SecondLSize = getTypeStoreSize(SecondL->getType()); - if (alias(FirstPHITranslatedAddr, LSize, - SecondPHITranslatedAddr, SecondLSize) == - MustAlias) { - // If the loads are the same size, it's ReadThenRead. - if (LSize == SecondLSize) - return ReadThenRead; - - // If the second load is smaller, it's only ReadThenReadSome. - if (LSize > SecondLSize) - return ReadThenReadSome; - } - } - - // Otherwise it's just two loads. - return Independent; - - case Mod: - // Second only writes to the memory read from by First. If it - // also reads from any other memory, be conservative. - if (Second->mayReadFromMemory()) - return Unknown; - - // If it's storing the same size to the same address, we can - // give a more precise result. - if (const StoreInst *SecondS = dyn_cast<StoreInst>(Second)) { - // If we don't have a phi-translated address, use the actual one. - if (!SecondPHITranslatedAddr) - SecondPHITranslatedAddr = SecondS->getPointerOperand(); - - unsigned LSize = getTypeStoreSize(L->getType()); - unsigned SecondSSize = getTypeStoreSize(SecondS->getType()); - if (alias(FirstPHITranslatedAddr, LSize, - SecondPHITranslatedAddr, SecondSSize) == - MustAlias) { - // If the load and the store are the same size, it's ReadThenWrite. - if (LSize == SecondSSize) - return ReadThenWrite; - } - } - - // Otherwise we don't know if it could be writing to other memory. - return Unknown; - - case ModRef: - // Second reads and writes to the memory read from by First. - // We don't have a way to express that. - return Unknown; - } - - } else if (const StoreInst *S = dyn_cast<StoreInst>(First)) { - // Be over-conservative with volatile for now. - if (S->isVolatile()) - return Unknown; - - // If we don't have a phi-translated address, use the actual one. - if (!FirstPHITranslatedAddr) - FirstPHITranslatedAddr = S->getPointerOperand(); - - // Forward this query to getModRefInfo. - switch (getModRefInfo(Second, - FirstPHITranslatedAddr, - getTypeStoreSize(S->getValueOperand()->getType()))) { - case NoModRef: - // Second doesn't reference First's memory, so they're independent. - return Independent; - - case Ref: - // Second only reads from the memory written to by First. If it - // also writes to any other memory, be conservative. - if (Second->mayWriteToMemory()) - return Unknown; - - // If it's loading the same size from the same address, we can - // give a more precise result. - if (const LoadInst *SecondL = dyn_cast<LoadInst>(Second)) { - // If we don't have a phi-translated address, use the actual one. - if (!SecondPHITranslatedAddr) - SecondPHITranslatedAddr = SecondL->getPointerOperand(); - - unsigned SSize = getTypeStoreSize(S->getValueOperand()->getType()); - unsigned SecondLSize = getTypeStoreSize(SecondL->getType()); - if (alias(FirstPHITranslatedAddr, SSize, - SecondPHITranslatedAddr, SecondLSize) == - MustAlias) { - // If the store and the load are the same size, it's WriteThenRead. - if (SSize == SecondLSize) - return WriteThenRead; - - // If the load is smaller, it's only WriteThenReadSome. - if (SSize > SecondLSize) - return WriteThenReadSome; - } - } - - // Otherwise we don't know if it could be reading from other memory. - return Unknown; - - case Mod: - // Second only writes to the memory written to by First. If it - // also reads from any other memory, be conservative. - if (Second->mayReadFromMemory()) - return Unknown; - - // If it's storing the same size to the same address, we can - // give a more precise result. - if (const StoreInst *SecondS = dyn_cast<StoreInst>(Second)) { - // If we don't have a phi-translated address, use the actual one. - if (!SecondPHITranslatedAddr) - SecondPHITranslatedAddr = SecondS->getPointerOperand(); - - unsigned SSize = getTypeStoreSize(S->getValueOperand()->getType()); - unsigned SecondSSize = getTypeStoreSize(SecondS->getType()); - if (alias(FirstPHITranslatedAddr, SSize, - SecondPHITranslatedAddr, SecondSSize) == - MustAlias) { - // If the stores are the same size, it's WriteThenWrite. - if (SSize == SecondSSize) - return WriteThenWrite; - - // If the second store is larger, it's only WriteSomeThenWrite. - if (SSize < SecondSSize) - return WriteSomeThenWrite; - } - } - - // Otherwise we don't know if it could be writing to other memory. - return Unknown; - - case ModRef: - // Second reads and writes to the memory written to by First. - // We don't have a way to express that. - return Unknown; - } - - } else if (const VAArgInst *V = dyn_cast<VAArgInst>(First)) { - // If we don't have a phi-translated address, use the actual one. - if (!FirstPHITranslatedAddr) - FirstPHITranslatedAddr = V->getPointerOperand(); - - // Forward this query to getModRefInfo. - if (getModRefInfo(Second, FirstPHITranslatedAddr, UnknownSize) == NoModRef) - // Second doesn't reference First's memory, so they're independent. - return Independent; - - } else if (ImmutableCallSite FirstCS = cast<Value>(First)) { - assert(!FirstPHITranslatedAddr && - !SecondPHITranslatedAddr && - "PHI translation with calls not supported yet!"); - - // If both instructions are calls/invokes we can use the two-callsite - // form of getModRefInfo. - if (ImmutableCallSite SecondCS = cast<Value>(Second)) - // getModRefInfo's arguments are backwards from intuition. - switch (getModRefInfo(SecondCS, FirstCS)) { - case NoModRef: - // Second doesn't reference First's memory, so they're independent. - return Independent; - - case Ref: - // If they're both read-only, there's no dependence. - if (FirstCS.onlyReadsMemory() && SecondCS.onlyReadsMemory()) - return Independent; - - // Otherwise it's not obvious what we can do here. - return Unknown; - - case Mod: - // It's not obvious what we can do here. - return Unknown; - - case ModRef: - // I know, right? - return Unknown; - } - } - - // For anything else, be conservative. - return Unknown; -} - AliasAnalysis::ModRefBehavior AliasAnalysis::getIntrinsicModRefBehavior(unsigned iid) { #define GET_INTRINSIC_MODREF_BEHAVIOR @@ -514,8 +291,8 @@ unsigned AliasAnalysis::getTypeStoreSize(const Type *Ty) { /// specified basic block to modify the value pointed to by Ptr. /// bool AliasAnalysis::canBasicBlockModify(const BasicBlock &BB, - const Value *Ptr, unsigned Size) { - return canInstructionRangeModify(BB.front(), BB.back(), Ptr, Size); + const Location &Loc) { + return canInstructionRangeModify(BB.front(), BB.back(), Loc); } /// canInstructionRangeModify - Return true if it is possible for the execution @@ -525,7 +302,7 @@ bool AliasAnalysis::canBasicBlockModify(const BasicBlock &BB, /// bool AliasAnalysis::canInstructionRangeModify(const Instruction &I1, const Instruction &I2, - const Value *Ptr, unsigned Size) { + const Location &Loc) { assert(I1.getParent() == I2.getParent() && "Instructions not in same basic block!"); BasicBlock::const_iterator I = &I1; @@ -533,7 +310,7 @@ bool AliasAnalysis::canInstructionRangeModify(const Instruction &I1, ++E; // Convert from inclusive to exclusive range. for (; I != E; ++I) // Check every instruction in range - if (getModRefInfo(I, Ptr, Size) & Mod) + if (getModRefInfo(I, Loc) & Mod) return true; return false; } diff --git a/lib/Analysis/AliasAnalysisCounter.cpp b/lib/Analysis/AliasAnalysisCounter.cpp index b17804186a..48f7a9f223 100644 --- a/lib/Analysis/AliasAnalysisCounter.cpp +++ b/lib/Analysis/AliasAnalysisCounter.cpp @@ -94,17 +94,16 @@ namespace { } // FIXME: We could count these too... - bool pointsToConstantMemory(const Value *P) { - return getAnalysis<AliasAnalysis>().pointsToConstantMemory(P); + bool pointsToConstantMemory(const Location &Loc) { + return getAnalysis<AliasAnalysis>().pointsToConstantMemory(Loc); } // Forwarding functions: just delegate to a real AA implementation, counting // the number of responses... - AliasResult alias(const Value *V1, unsigned V1Size, |