mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-26 05:00:26 +00:00
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
This commit is contained in:
parent
fe3ac088ee
commit
b2143b6247
@ -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 Value *V1, unsigned V1Size,
|
||||
const Value *V2, unsigned V2Size) {
|
||||
return alias(V1, V1Size, V2, V2Size) == NoAlias;
|
||||
bool isNoAlias(const Location &LocA, const Location &LocB) {
|
||||
return alias(LocA, LocB) == NoAlias;
|
||||
}
|
||||
|
||||
/// pointsToConstantMemory - If the specified pointer is known to point into
|
||||
/// constant global memory, return true. This allows disambiguation of store
|
||||
/// isNoAlias - A convenience wrapper.
|
||||
bool isNoAlias(const Value *V1, unsigned V1Size,
|
||||
const Value *V2, unsigned V2Size) {
|
||||
return isNoAlias(Location(V1, V1Size), Location(V2, V2Size));
|
||||
}
|
||||
|
||||
/// 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
|
||||
@ -277,101 +339,31 @@ public:
|
||||
virtual ModRefResult getModRefInfo(ImmutableCallSite CS1,
|
||||
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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
const Value *V2, unsigned V2Size);
|
||||
AliasResult alias(const Location &LocA, const Location &LocB);
|
||||
|
||||
ModRefResult getModRefInfo(ImmutableCallSite CS,
|
||||
const Value *P, unsigned Size);
|
||||
const Location &Loc);
|
||||
ModRefResult getModRefInfo(ImmutableCallSite CS1,
|
||||
ImmutableCallSite CS2) {
|
||||
return AliasAnalysis::getModRefInfo(CS1,CS2);
|
||||
@ -121,9 +120,8 @@ ModulePass *llvm::createAliasAnalysisCounterPass() {
|
||||
}
|
||||
|
||||
AliasAnalysis::AliasResult
|
||||
AliasAnalysisCounter::alias(const Value *V1, unsigned V1Size,
|
||||
const Value *V2, unsigned V2Size) {
|
||||
AliasResult R = getAnalysis<AliasAnalysis>().alias(V1, V1Size, V2, V2Size);
|
||||
AliasAnalysisCounter::alias(const Location &LocA, const Location &LocB) {
|
||||
AliasResult R = getAnalysis<AliasAnalysis>().alias(LocA, LocB);
|
||||
|
||||
const char *AliasString;
|
||||
switch (R) {
|
||||
@ -135,11 +133,11 @@ AliasAnalysisCounter::alias(const Value *V1, unsigned V1Size,
|
||||
|
||||
if (PrintAll || (PrintAllFailures && R == MayAlias)) {
|
||||
errs() << AliasString << ":\t";
|
||||
errs() << "[" << V1Size << "B] ";
|
||||
WriteAsOperand(errs(), V1, true, M);
|
||||
errs() << "[" << LocA.Size << "B] ";
|
||||
WriteAsOperand(errs(), LocA.Ptr, true, M);
|
||||
errs() << ", ";
|
||||
errs() << "[" << V2Size << "B] ";
|
||||
WriteAsOperand(errs(), V2, true, M);
|
||||
errs() << "[" << LocB.Size << "B] ";
|
||||
WriteAsOperand(errs(), LocB.Ptr, true, M);
|
||||
errs() << "\n";
|
||||
}
|
||||
|
||||
@ -148,8 +146,8 @@ AliasAnalysisCounter::alias(const Value *V1, unsigned V1Size,
|
||||
|
||||
AliasAnalysis::ModRefResult
|
||||
AliasAnalysisCounter::getModRefInfo(ImmutableCallSite CS,
|
||||
const Value *P, unsigned Size) {
|
||||
ModRefResult R = getAnalysis<AliasAnalysis>().getModRefInfo(CS, P, Size);
|
||||
const Location &Loc) {
|
||||
ModRefResult R = getAnalysis<AliasAnalysis>().getModRefInfo(CS, Loc);
|
||||
|
||||
const char *MRString;
|
||||
switch (R) {
|
||||
@ -162,8 +160,8 @@ AliasAnalysisCounter::getModRefInfo(ImmutableCallSite CS,
|
||||
|
||||
if (PrintAll || (PrintAllFailures && R == ModRef)) {
|
||||
errs() << MRString << ": Ptr: ";
|
||||
errs() << "[" << Size << "B] ";
|
||||
WriteAsOperand(errs(), P, true, M);
|
||||
errs() << "[" << Loc.Size << "B] ";
|
||||
WriteAsOperand(errs(), Loc.Ptr, true, M);
|
||||
errs() << "\t<->" << *CS.getInstruction() << '\n';
|
||||
}
|
||||
return R;
|
||||
|
@ -92,17 +92,18 @@ namespace {
|
||||
//------------------------------------------------
|
||||
// Implement the AliasAnalysis API
|
||||
//
|
||||
AliasResult alias(const Value *V1, unsigned V1Size,
|
||||
const Value *V2, unsigned V2Size) {
|
||||
assert(Vals.find(V1) != Vals.end() && "Never seen value in AA before");
|
||||
assert(Vals.find(V2) != Vals.end() && "Never seen value in AA before");
|
||||
return AliasAnalysis::alias(V1, V1Size, V2, V2Size);
|
||||
AliasResult alias(const Location &LocA, const Location &LocB) {
|
||||
assert(Vals.find(LocA.Ptr) != Vals.end() &&
|
||||
"Never seen value in AA before");
|
||||
assert(Vals.find(LocB.Ptr) != Vals.end() &&
|
||||
"Never seen value in AA before");
|
||||
return AliasAnalysis::alias(LocA, LocB);
|
||||
}
|
||||
|
||||
ModRefResult getModRefInfo(ImmutableCallSite CS,
|
||||
const Value *P, unsigned Size) {
|
||||
assert(Vals.find(P) != Vals.end() && "Never seen value in AA before");
|
||||
return AliasAnalysis::getModRefInfo(CS, P, Size);
|
||||
const Location &Loc) {
|
||||
assert(Vals.find(Loc.Ptr) != Vals.end() && "Never seen value in AA before");
|
||||
return AliasAnalysis::getModRefInfo(CS, Loc);
|
||||
}
|
||||
|
||||
ModRefResult getModRefInfo(ImmutableCallSite CS1,
|
||||
@ -110,9 +111,9 @@ namespace {
|
||||
return AliasAnalysis::getModRefInfo(CS1,CS2);
|
||||
}
|
||||
|
||||
bool pointsToConstantMemory(const Value *P) {
|
||||
assert(Vals.find(P) != Vals.end() && "Never seen value in AA before");
|
||||
return AliasAnalysis::pointsToConstantMemory(P);
|
||||
bool pointsToConstantMemory(const Location &Loc) {
|
||||
assert(Vals.find(Loc.Ptr) != Vals.end() && "Never seen value in AA before");
|
||||
return AliasAnalysis::pointsToConstantMemory(Loc);
|
||||
}
|
||||
|
||||
virtual void deleteValue(Value *V) {
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "llvm/GlobalVariable.h"
|
||||
#include "llvm/Instructions.h"
|
||||
#include "llvm/IntrinsicInst.h"
|
||||
#include "llvm/LLVMContext.h"
|
||||
#include "llvm/Operator.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Analysis/CaptureTracking.h"
|
||||
@ -149,8 +150,7 @@ namespace {
|
||||
TD = getAnalysisIfAvailable<TargetData>();
|
||||
}
|
||||
|
||||
virtual AliasResult alias(const Value *V1, unsigned V1Size,
|
||||
const Value *V2, unsigned V2Size) {
|
||||
virtual AliasResult alias(const Location &LocA, const Location &LocB) {
|
||||
return MayAlias;
|
||||
}
|
||||
|
||||
@ -161,9 +161,9 @@ namespace {
|
||||
return UnknownModRefBehavior;
|
||||
}
|
||||
|
||||
virtual bool pointsToConstantMemory(const Value *P) { return false; }
|
||||
virtual bool pointsToConstantMemory(const Location &Loc) { return false; }
|
||||
virtual ModRefResult getModRefInfo(ImmutableCallSite CS,
|
||||
const Value *P, unsigned Size) {
|
||||
const Location &Loc) {
|
||||
return ModRef;
|
||||
}
|
||||
virtual ModRefResult getModRefInfo(ImmutableCallSite CS1,
|
||||
@ -171,15 +171,6 @@ namespace {
|
||||
return ModRef;
|
||||
}
|
||||
|
||||
virtual DependenceResult getDependence(const Instruction *First,
|
||||
const Value *FirstPHITranslatedAddr,
|
||||
DependenceQueryFlags FirstFlags,
|
||||
const Instruction *Second,
|
||||
const Value *SecondPHITranslatedAddr,
|
||||
DependenceQueryFlags SecondFlags) {
|
||||
return Unknown;
|
||||
}
|
||||
|
||||
virtual void deleteValue(Value *V) {}
|
||||
virtual void copyValue(Value *From, Value *To) {}
|
||||
|
||||
@ -501,18 +492,18 @@ namespace {
|
||||
static char ID; // Class identification, replacement for typeinfo
|
||||
BasicAliasAnalysis() : NoAA(ID) {}
|
||||
|
||||
virtual AliasResult alias(const Value *V1, unsigned V1Size,
|
||||
const Value *V2, unsigned V2Size) {
|
||||
virtual AliasResult alias(const Location &LocA,
|
||||
const Location &LocB) {
|
||||
assert(Visited.empty() && "Visited must be cleared after use!");
|
||||
assert(notDifferentParent(V1, V2) &&
|
||||
assert(notDifferentParent(LocA.Ptr, LocB.Ptr) &&
|
||||
"BasicAliasAnalysis doesn't support interprocedural queries.");
|
||||
AliasResult Alias = aliasCheck(V1, V1Size, V2, V2Size);
|
||||
AliasResult Alias = aliasCheck(LocA.Ptr, LocA.Size, LocB.Ptr, LocB.Size);
|
||||
Visited.clear();
|
||||
return Alias;
|
||||
}
|
||||
|
||||
virtual ModRefResult getModRefInfo(ImmutableCallSite CS,
|
||||
const Value *P, unsigned Size);
|
||||
const Location &Loc);
|
||||
|
||||
virtual ModRefResult getModRefInfo(ImmutableCallSite CS1,
|
||||
ImmutableCallSite CS2) {
|
||||
@ -522,7 +513,7 @@ namespace {
|
||||
|
||||
/// pointsToConstantMemory - Chase pointers until we find a (constant
|
||||
/// global) or not.
|
||||
virtual bool pointsToConstantMemory(const Value *P);
|
||||
virtual bool pointsToConstantMemory(const Location &Loc);
|
||||
|
||||
/// getModRefBehavior - Return the behavior when calling the given
|
||||
/// call site.
|
||||
@ -532,13 +523,6 @@ namespace {
|
||||
/// For use when the call site is not known.
|
||||
virtual ModRefBehavior getModRefBehavior(const Function *F);
|
||||
|
||||
virtual DependenceResult getDependence(const Instruction *First,
|
||||
const Value *FirstPHITranslatedAddr,
|
||||
DependenceQueryFlags FirstFlags,
|
||||
const Instruction *Second,
|
||||
const Value *SecondPHITranslatedAddr,
|
||||
DependenceQueryFlags SecondFlags);
|
||||
|
||||
/// getAdjustedAnalysisPointer - This method is used when a pass implements
|
||||
/// an analysis interface through multiple inheritance. If needed, it
|
||||
/// should override this to adjust the this pointer as needed for the
|
||||
@ -586,15 +570,15 @@ ImmutablePass *llvm::createBasicAliasAnalysisPass() {
|
||||
|
||||
/// pointsToConstantMemory - Chase pointers until we find a (constant
|
||||
/// global) or not.
|
||||
bool BasicAliasAnalysis::pointsToConstantMemory(const Value *P) {
|
||||
bool BasicAliasAnalysis::pointsToConstantMemory(const Location &Loc) {
|
||||
if (const GlobalVariable *GV =
|
||||
dyn_cast<GlobalVariable>(P->getUnderlyingObject()))
|
||||
dyn_cast<GlobalVariable>(Loc.Ptr->getUnderlyingObject()))
|
||||
// Note: this doesn't require GV to be "ODR" because it isn't legal for a
|
||||
// global to be marked constant in some modules and non-constant in others.
|
||||
// GV may even be a declaration, not a definition.
|
||||
return GV->isConstant();
|
||||
|
||||
return NoAA::pointsToConstantMemory(P);
|
||||
return NoAA::pointsToConstantMemory(Loc);
|
||||
}
|
||||
|
||||
/// getModRefBehavior - Return the behavior when calling the given call site.
|
||||
@ -636,13 +620,13 @@ BasicAliasAnalysis::getModRefBehavior(const Function *F) {
|
||||
/// simple "address taken" analysis on local objects.
|
||||
AliasAnalysis::ModRefResult
|
||||
BasicAliasAnalysis::getModRefInfo(ImmutableCallSite CS,
|
||||
const Value *P, unsigned Size) {
|
||||
assert(notDifferentParent(CS.getInstruction(), P) &&
|
||||
const Location &Loc) {
|
||||
assert(notDifferentParent(CS.getInstruction(), Loc.Ptr) &&
|
||||
"AliasAnalysis query involving multiple functions!");
|
||||
|
||||
const Value *Object = P->getUnderlyingObject();
|
||||
const Value *Object = Loc.Ptr->getUnderlyingObject();
|
||||
|
||||
// If this is a tail call and P points to a stack location, we know that
|
||||
// If this is a tail call and Loc.Ptr points to a stack location, we know that
|
||||
// the tail call cannot access or modify the local stack.
|
||||
// We cannot exclude byval arguments here; these belong to the caller of
|
||||
// the current function not to the current function, and a tail callee
|
||||
@ -666,11 +650,11 @@ BasicAliasAnalysis::getModRefInfo(ImmutableCallSite CS,
|
||||
!CS.paramHasAttr(ArgNo+1, Attribute::NoCapture))
|
||||
continue;
|
||||
|
||||
// If this is a no-capture pointer argument, see if we can tell that it
|
||||
// If this is a no-capture pointer argument, see if we can tell that it
|
||||
// is impossible to alias the pointer we're checking. If not, we have to
|
||||
// assume that the call could touch the pointer, even though it doesn't
|
||||
// escape.
|
||||
if (!isNoAlias(cast<Value>(CI), UnknownSize, P, UnknownSize)) {
|
||||
if (!isNoAlias(Location(cast<Value>(CI)), Loc)) {
|
||||
PassedAsArg = true;
|
||||
break;
|
||||
}
|
||||
@ -692,8 +676,8 @@ BasicAliasAnalysis::getModRefInfo(ImmutableCallSite CS,
|
||||
Len = LenCI->getZExtValue();
|
||||
Value *Dest = II->getArgOperand(0);
|
||||
Value *Src = II->getArgOperand(1);
|
||||
if (isNoAlias(Dest, Len, P, Size)) {
|
||||
if (isNoAlias(Src, Len, P, Size))
|
||||
if (isNoAlias(Location(Dest, Len), Loc)) {
|
||||
if (isNoAlias(Location(Src, Len), Loc))
|
||||
return NoModRef;
|
||||
return Ref;
|
||||
}
|
||||
@ -705,7 +689,7 @@ BasicAliasAnalysis::getModRefInfo(ImmutableCallSite CS,
|
||||
if (ConstantInt *LenCI = dyn_cast<ConstantInt>(II->getArgOperand(2))) {
|
||||
unsigned Len = LenCI->getZExtValue();
|
||||
Value *Dest = II->getArgOperand(0);
|
||||
if (isNoAlias(Dest, Len, P, Size))
|
||||
if (isNoAlias(Location(Dest, Len), Loc))
|
||||
return NoModRef;
|
||||
}
|
||||
break;
|
||||
@ -724,7 +708,8 @@ BasicAliasAnalysis::getModRefInfo(ImmutableCallSite CS,
|
||||
if (TD) {
|
||||
Value *Op1 = II->getArgOperand(0);
|
||||
unsigned Op1Size = TD->getTypeStoreSize(Op1->getType());
|
||||
if (isNoAlias(Op1, Op1Size, P, Size))
|
||||
MDNode *Tag = II->getMetadata(LLVMContext::MD_tbaa);
|
||||
if (isNoAlias(Location(Op1, Op1Size, Tag), Loc))
|
||||
return NoModRef;
|
||||
}
|
||||
break;
|
||||
@ -733,33 +718,27 @@ BasicAliasAnalysis::getModRefInfo(ImmutableCallSite CS,
|
||||
case Intrinsic::invariant_start: {
|
||||
unsigned PtrSize =
|
||||
cast<ConstantInt>(II->getArgOperand(0))->getZExtValue();
|
||||
if (isNoAlias(II->getArgOperand(1), PtrSize, P, Size))
|
||||
if (isNoAlias(Location(II->getArgOperand(1),
|
||||
PtrSize,
|
||||
II->getMetadata(LLVMContext::MD_tbaa)),
|
||||
Loc))
|
||||
return NoModRef;
|
||||
break;
|
||||
}
|
||||
case Intrinsic::invariant_end: {
|
||||
unsigned PtrSize =
|
||||
cast<ConstantInt>(II->getArgOperand(1))->getZExtValue();
|
||||
if (isNoAlias(II->getArgOperand(2), PtrSize, P, Size))
|
||||
if (isNoAlias(Location(II->getArgOperand(2),
|
||||
PtrSize,
|
||||
II->getMetadata(LLVMContext::MD_tbaa)),
|
||||
Loc))
|
||||
return NoModRef;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// The AliasAnalysis base class has some smarts, lets use them.
|
||||
return AliasAnalysis::getModRefInfo(CS, P, Size);
|
||||
}
|
||||
|
||||
AliasAnalysis::DependenceResult
|
||||
BasicAliasAnalysis::getDependence(const Instruction *First,
|
||||
const Value *FirstPHITranslatedAddr,
|
||||
DependenceQueryFlags FirstFlags,
|
||||
const Instruction *Second,
|
||||
const Value *SecondPHITranslatedAddr,
|
||||
DependenceQueryFlags SecondFlags) {
|
||||
// We don't have anything special to say yet.
|
||||
return getDependenceViaModRefInfo(First, FirstPHITranslatedAddr, FirstFlags,
|
||||
Second, SecondPHITranslatedAddr, SecondFlags);
|
||||
return AliasAnalysis::getModRefInfo(CS, Loc);
|
||||
}
|
||||
|
||||
/// aliasGEP - Provide a bunch of ad-hoc rules to disambiguate a GEP instruction
|
||||
@ -1103,7 +1082,7 @@ BasicAliasAnalysis::aliasCheck(const Value *V1, unsigned V1Size,
|
||||
if (const SelectInst *S1 = dyn_cast<SelectInst>(V1))
|
||||
return aliasSelect(S1, V1Size, V2, V2Size);
|
||||
|
||||
return NoAA::alias(V1, V1Size, V2, V2Size);
|
||||
return NoAA::alias(Location(V1, V1Size), Location(V2, V2Size));
|
||||
}
|
||||
|
||||
// Make sure that anything that uses AliasAnalysis pulls in this file.
|
||||
|
@ -106,10 +106,9 @@ namespace {
|
||||
//------------------------------------------------
|
||||
// Implement the AliasAnalysis API
|
||||
//
|
||||
AliasResult alias(const Value *V1, unsigned V1Size,
|
||||
const Value *V2, unsigned V2Size);
|
||||
AliasResult alias(const Location &LocA, const Location &LocB);
|
||||
ModRefResult getModRefInfo(ImmutableCallSite CS,
|
||||
const Value *P, unsigned Size);
|
||||
const Location &Loc);
|
||||
ModRefResult getModRefInfo(ImmutableCallSite CS1,
|
||||
ImmutableCallSite CS2) {
|
||||
return AliasAnalysis::getModRefInfo(CS1, CS2);
|
||||
@ -476,11 +475,11 @@ void GlobalsModRef::AnalyzeCallGraph(CallGraph &CG, Module &M) {
|
||||
/// other is some random pointer, we know there cannot be an alias, because the
|
||||
/// address of the global isn't taken.
|
||||
AliasAnalysis::AliasResult
|
||||
GlobalsModRef::alias(const Value *V1, unsigned V1Size,
|
||||
const Value *V2, unsigned V2Size) {
|
||||
GlobalsModRef::alias(const Location &LocA,
|
||||
const Location &LocB) {
|
||||
// Get the base object these pointers point to.
|
||||
const Value *UV1 = V1->getUnderlyingObject();
|
||||
const Value *UV2 = V2->getUnderlyingObject();
|
||||
const Value *UV1 = LocA.Ptr->getUnderlyingObject();
|
||||
const Value *UV2 = LocB.Ptr->getUnderlyingObject();
|
||||
|
||||
// If either of the underlying values is a global, they may be non-addr-taken
|
||||
// globals, which we can answer queries about.
|
||||
@ -528,17 +527,18 @@ GlobalsModRef::alias(const Value *V1, unsigned V1Size,
|
||||
if ((GV1 || GV2) && GV1 != GV2)
|
||||
return NoAlias;
|
||||
|
||||
return AliasAnalysis::alias(V1, V1Size, V2, V2Size);
|
||||
return AliasAnalysis::alias(LocA, LocB);
|
||||
}
|
||||
|
||||
AliasAnalysis::ModRefResult
|
||||
GlobalsModRef::getModRefInfo(ImmutableCallSite CS,
|
||||
const Value *P, unsigned Size) {
|
||||
const Location &Loc) {
|
||||
unsigned Known = ModRef;
|
||||
|
||||
// If we are asking for mod/ref info of a direct call with a pointer to a
|
||||
// global we are tracking, return information if we have it.
|
||||
if (const GlobalValue *GV = dyn_cast<GlobalValue>(P->getUnderlyingObject()))
|
||||
if (const GlobalValue *GV =
|
||||
dyn_cast<GlobalValue>(Loc.Ptr->getUnderlyingObject()))
|
||||
if (GV->hasLocalLinkage())
|
||||
if (const Function *F = CS.getCalledFunction())
|
||||
if (NonAddressTakenGlobals.count(GV))
|
||||
@ -547,7 +547,7 @@ GlobalsModRef::getModRefInfo(ImmutableCallSite CS,
|
||||
|
||||
if (Known == NoModRef)
|
||||
return NoModRef; // No need to query other mod/ref analyses
|
||||
return ModRefResult(Known & AliasAnalysis::getModRefInfo(CS, P, Size));
|
||||
return ModRefResult(Known & AliasAnalysis::getModRefInfo(CS, Loc));
|
||||
}
|
||||
|
||||
|
||||
|
@ -43,8 +43,8 @@ void LibCallAliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
/// vs the specified pointer/size.
|
||||
AliasAnalysis::ModRefResult
|
||||
LibCallAliasAnalysis::AnalyzeLibCallDetails(const LibCallFunctionInfo *FI,
|
||||
ImmutableCallSite CS, const Value *P,
|
||||
unsigned Size) {
|
||||
ImmutableCallSite CS,
|
||||
const Location &Loc) {
|
||||
// If we have a function, check to see what kind of mod/ref effects it
|
||||
// has. Start by including any info globally known about the function.
|
||||
AliasAnalysis::ModRefResult MRInfo = FI->UniversalBehavior;
|
||||
@ -64,9 +64,9 @@ LibCallAliasAnalysis::AnalyzeLibCallDetails(const LibCallFunctionInfo *FI,
|
||||
if (FI->DetailsType == LibCallFunctionInfo::DoesNot) {
|
||||
// Find out if the pointer refers to a known location.
|
||||
for (unsigned i = 0; Details[i].LocationID != ~0U; ++i) {
|
||||
const LibCallLocationInfo &Loc =
|
||||
const LibCallLocationInfo &LocInfo =
|
||||
LCI->getLocationInfo(Details[i].LocationID);
|
||||
LibCallLocationInfo::LocResult Res = Loc.isLocation(CS, P, Size);
|
||||
LibCallLocationInfo::LocResult Res = LocInfo.isLocation(CS, Loc);
|
||||
if (Res != LibCallLocationInfo::Yes) continue;
|
||||
|
||||
// If we find a match against a location that we 'do not' interact with,
|
||||
@ -85,9 +85,9 @@ LibCallAliasAnalysis::AnalyzeLibCallDetails(const LibCallFunctionInfo *FI,
|
||||
// Find out if the pointer refers to a known location.
|
||||
bool NoneMatch = true;
|
||||
for (unsigned i = 0; Details[i].LocationID != ~0U; ++i) {
|
||||
const LibCallLocationInfo &Loc =
|
||||
const LibCallLocationInfo &LocInfo =
|
||||
LCI->getLocationInfo(Details[i].LocationID);
|
||||
LibCallLocationInfo::LocResult Res = Loc.isLocation(CS, P, Size);
|
||||
LibCallLocationInfo::LocResult Res = LocInfo.isLocation(CS, Loc);
|
||||
if (Res == LibCallLocationInfo::No) continue;
|
||||
|
||||
// If we don't know if this pointer points to the location, then we have to
|
||||
@ -118,7 +118,7 @@ LibCallAliasAnalysis::AnalyzeLibCallDetails(const LibCallFunctionInfo *FI,
|
||||
//
|
||||
AliasAnalysis::ModRefResult
|
||||
LibCallAliasAnalysis::getModRefInfo(ImmutableCallSite CS,
|
||||
const Value *P, unsigned Size) {
|
||||
const Location &Loc) {
|
||||
ModRefResult MRInfo = ModRef;
|
||||
|
||||
// If this is a direct call to a function that LCI knows about, get the
|
||||
@ -126,12 +126,12 @@ LibCallAliasAnalysis::getModRefInfo(ImmutableCallSite CS,
|
||||
if (LCI) {
|
||||
if (const Function *F = CS.getCalledFunction()) {
|
||||
if (const LibCallFunctionInfo *FI = LCI->getFunctionInfo(F)) {
|
||||
MRInfo = ModRefResult(MRInfo & AnalyzeLibCallDetails(FI, CS, P, Size));
|
||||
MRInfo = ModRefResult(MRInfo & AnalyzeLibCallDetails(FI, CS, Loc));
|
||||
if (MRInfo == NoModRef) return NoModRef;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The AliasAnalysis base class has some smarts, lets use them.
|
||||
return (ModRefResult)(MRInfo | AliasAnalysis::getModRefInfo(CS, P, Size));
|
||||
return (ModRefResult)(MRInfo | AliasAnalysis::getModRefInfo(CS, Loc));
|
||||
}
|
||||
|
@ -49,8 +49,7 @@ namespace {
|
||||
private:
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
virtual bool runOnFunction(Function &F);
|
||||
virtual AliasResult alias(const Value *V1, unsigned V1Size,
|
||||
const Value *V2, unsigned V2Size);
|
||||
virtual AliasResult alias(const Location &LocA, const Location &LocB);
|
||||
|
||||
Value *GetBaseValue(const SCEV *S);
|
||||
};
|
||||
@ -101,17 +100,17 @@ ScalarEvolutionAliasAnalysis::GetBaseValue(const SCEV *S) {
|
||||
}
|
||||
|
||||
AliasAnalysis::AliasResult
|
||||
ScalarEvolutionAliasAnalysis::alias(const Value *A, unsigned ASize,
|
||||
const Value *B, unsigned BSize) {
|
||||
ScalarEvolutionAliasAnalysis::alias(const Location &LocA,
|
||||
const Location &LocB) {
|
||||
// If either of the memory references is empty, it doesn't matter what the
|
||||
// pointer values are. This allows the code below to ignore this special
|
||||
// case.
|
||||
if (ASize == 0 || BSize == 0)
|
||||
if (LocA.Size == 0 || LocB.Size == 0)
|
||||
return NoAlias;
|
||||
|
||||
// This is ScalarEvolutionAliasAnalysis. Get the SCEVs!
|
||||
const SCEV *AS = SE->getSCEV(const_cast<Value *>(A));
|
||||
const SCEV *BS = SE->getSCEV(const_cast<Value *>(B));
|
||||
const SCEV *AS = SE->getSCEV(const_cast<Value *>(LocA.Ptr));
|
||||
const SCEV *BS = SE->getSCEV(const_cast<Value *>(LocB.Ptr));
|
||||
|
||||
// If they evaluate to the same expression, it's a MustAlias.
|
||||
if (AS == BS) return MustAlias;
|
||||
@ -121,8 +120,8 @@ ScalarEvolutionAliasAnalysis::alias(const Value *A, unsigned ASize,
|
||||
if (SE->getEffectiveSCEVType(AS->getType()) ==
|
||||
SE->getEffectiveSCEVType(BS->getType())) {
|
||||
unsigned BitWidth = SE->getTypeSizeInBits(AS->getType());
|
||||
APInt ASizeInt(BitWidth, ASize);
|
||||
APInt BSizeInt(BitWidth, BSize);
|
||||
APInt ASizeInt(BitWidth, LocA.Size);
|
||||
APInt BSizeInt(BitWidth, LocB.Size);
|
||||
|
||||
// Compute the difference between the two pointers.
|
||||
const SCEV *BA = SE->getMinusSCEV(BS, AS);
|
||||
@ -154,11 +153,15 @@ ScalarEvolutionAliasAnalysis::alias(const Value *A, unsigned ASize,
|
||||
// inttoptr and ptrtoint operators.
|
||||
Value *AO = GetBaseValue(AS);
|
||||
Value *BO = GetBaseValue(BS);
|
||||
if ((AO && AO != A) || (BO && BO != B))
|
||||
if (alias(AO ? AO : A, AO ? UnknownSize : ASize,
|
||||
BO ? BO : B, BO ? UnknownSize : BSize) == NoAlias)
|
||||
if ((AO && AO != LocA.Ptr) || (BO && BO != LocB.Ptr))
|
||||
if (alias(Location(AO ? AO : LocA.Ptr,
|
||||
AO ? +UnknownSize : LocA.Size,
|
||||
AO ? 0 : LocA.TBAATag),
|
||||
Location(BO ? BO : LocB.Ptr,
|
||||
BO ? +UnknownSize : LocB.Size,
|
||||
BO ? 0 : LocB.TBAATag)) == NoAlias)
|
||||
return NoAlias;
|
||||
|
||||
// Forward the query to the next analysis.
|
||||
return AliasAnalysis::alias(A, ASize, B, BSize);
|
||||
return AliasAnalysis::alias(LocA, LocB);
|
||||
}
|
||||
|
@ -96,9 +96,8 @@ namespace {
|
||||
|
||||
private:
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
virtual AliasResult alias(const Value *V1, unsigned V1Size,
|
||||
const Value *V2, unsigned V2Size);
|
||||
virtual bool pointsToConstantMemory(const Value *P);
|
||||
virtual AliasResult alias(const Location &LocA, const Location &LocB);
|
||||
virtual bool pointsToConstantMemory(const Location &Loc);
|
||||
};
|
||||
} // End of anonymous namespace
|
||||
|
||||
@ -118,12 +117,12 @@ TypeBasedAliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
}
|
||||
|
||||
AliasAnalysis::AliasResult
|
||||
TypeBasedAliasAnalysis::alias(const Value *A, unsigned ASize,
|
||||
const Value *B, unsigned BSize) {
|
||||
TypeBasedAliasAnalysis::alias(const Location &LocA,
|
||||
const Location &LocB) {
|
||||
// Currently, metadata can only be attached to Instructions.
|
||||
const Instruction *AI = dyn_cast<Instruction>(A);
|
||||
const Instruction *AI = dyn_cast<Instruction>(LocA.Ptr);
|
||||
if (!AI) return MayAlias;
|
||||
const Instruction *BI = dyn_cast<Instruction>(B);
|
||||
const Instruction *BI = dyn_cast<Instruction>(LocB.Ptr);
|
||||
if (!BI) return MayAlias;
|
||||
|
||||
// Get the attached MDNodes. If either value lacks a tbaa MDNode, we must
|
||||
@ -175,9 +174,9 @@ TypeBasedAliasAnalysis::alias(const Value *A, unsigned ASize,
|
||||
return MayAlias;
|
||||
}
|
||||
|
||||
bool TypeBasedAliasAnalysis::pointsToConstantMemory(const Value *P) {
|
||||
bool TypeBasedAliasAnalysis::pointsToConstantMemory(const Location &Loc) {
|
||||
// Currently, metadata can only be attached to Instructions.
|
||||
const Instruction *I = dyn_cast<Instruction>(P);
|
||||
const Instruction *I = dyn_cast<Instruction>(Loc.Ptr);
|
||||
if (!I) return false;
|
||||
|
||||
MDNode *M =
|
||||
|
@ -28,9 +28,16 @@ LLVMContext& llvm::getGlobalContext() {
|
||||
}
|
||||
|
||||
LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) {
|
||||
// Create the first metadata kind, which is always 'dbg'.
|
||||
// Create the fixed metadata kinds. This is done in the same order as the
|
||||
// MD_* enum values so that they correspond.
|
||||
|
||||
// Create the 'dbg' metadata kind.
|
||||
unsigned DbgID = getMDKindID("dbg");
|
||||
assert(DbgID == MD_dbg && "dbg kind id drifted"); (void)DbgID;
|
||||
|
||||
// Create the 'tbaa' metadata kind.
|
||||
unsigned TBAAID = getMDKindID("tbaa");
|
||||
assert(TBAAID == MD_tbaa && "tbaa kind id drifted"); (void)TBAAID;
|
||||
}
|
||||
LLVMContext::~LLVMContext() { delete pImpl; }
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user