#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Pass.h"
#include "llvm/BasicBlock.h"
#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;
INITIALIZE_ANALYSIS_GROUP(AliasAnalysis, "Alias Analysis", NoAA)
char AliasAnalysis::ID = 0;
AliasAnalysis::AliasResult
AliasAnalysis::alias(const Location &LocA, const Location &LocB) {
assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
return AA->alias(LocA, LocB);
}
bool AliasAnalysis::pointsToConstantMemory(const Location &Loc) {
assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
return AA->pointsToConstantMemory(Loc);
}
void AliasAnalysis::deleteValue(Value *V) {
assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
AA->deleteValue(V);
}
void AliasAnalysis::copyValue(Value *From, Value *To) {
assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
AA->copyValue(From, To);
}
AliasAnalysis::ModRefResult
AliasAnalysis::getModRefInfo(ImmutableCallSite CS,
const Location &Loc) {
assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
ModRefBehavior MRB = getModRefBehavior(CS);
if (MRB == DoesNotAccessMemory)
return NoModRef;
ModRefResult Mask = ModRef;
if (MRB == OnlyReadsMemory)
Mask = Ref;
else if (MRB == AliasAnalysis::AccessesArguments) {
bool doesAlias = false;
for (ImmutableCallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end();
AI != AE; ++AI)
if (!isNoAlias(Location(*AI), Loc)) {
doesAlias = true;
break;
}
if (!doesAlias)
return NoModRef;
}
if ((Mask & Mod) && pointsToConstantMemory(Loc))
Mask = ModRefResult(Mask & ~Mod);
if (!AA) return Mask;
return ModRefResult(AA->getModRefInfo(CS, Loc) & Mask);
}
AliasAnalysis::ModRefResult
AliasAnalysis::getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2) {
assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
ModRefBehavior CS1B = getModRefBehavior(CS1);
if (CS1B == DoesNotAccessMemory) return NoModRef;
ModRefBehavior CS2B = getModRefBehavior(CS2);
if (CS2B == DoesNotAccessMemory) return NoModRef;
if (CS1B == OnlyReadsMemory && CS2B == OnlyReadsMemory)
return NoModRef;
AliasAnalysis::ModRefResult Mask = ModRef;
if (CS1B == OnlyReadsMemory)
Mask = ModRefResult(Mask & Ref);
if (CS2B == AccessesArguments) {
AliasAnalysis::ModRefResult R = NoModRef;
for (ImmutableCallSite::arg_iterator
I = CS2.arg_begin(), E = CS2.arg_end(); I != E; ++I) {
R = ModRefResult((R | getModRefInfo(CS1, *I, UnknownSize)) & Mask);
if (R == Mask)
break;
}
return R;
}
if (CS1B == AccessesArguments) {
AliasAnalysis::ModRefResult R = NoModRef;
for (ImmutableCallSite::arg_iterator
I = CS1.arg_begin(), E = CS1.arg_end(); I != E; ++I)
if (getModRefInfo(CS2, *I, UnknownSize) != NoModRef) {
R = Mask;
break;
}
if (R == NoModRef)
return R;
}
if (!AA) return Mask;
return ModRefResult(AA->getModRefInfo(CS1, CS2) & Mask);
}
AliasAnalysis::ModRefBehavior
AliasAnalysis::getModRefBehavior(ImmutableCallSite CS) {
assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
ModRefBehavior Min = UnknownModRefBehavior;
if (const Function *F = CS.getCalledFunction())
Min = getModRefBehavior(F);
if (!AA) return Min;
return std::min(AA->getModRefBehavior(CS), Min);
}
AliasAnalysis::ModRefBehavior
AliasAnalysis::getModRefBehavior(const Function *F) {
assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
return AA->getModRefBehavior(F);
}
AliasAnalysis::ModRefResult
AliasAnalysis::getModRefInfo(const LoadInst *L, const Location &Loc) {
if (L->isVolatile())
return ModRef;
if (!alias(Location(L->getOperand(0),
getTypeStoreSize(L->getType()),
L->getMetadata(LLVMContext::MD_tbaa)),
Loc))
return NoModRef;
return Ref;
}
AliasAnalysis::ModRefResult
AliasAnalysis::getModRefInfo(const StoreInst *S, const Location &Loc) {
if (S->isVolatile())
return ModRef;
if (!alias(Location(S->getOperand(1),
getTypeStoreSize(S->getOperand(0)->getType()),
S->getMetadata(LLVMContext::MD_tbaa)),
Loc))
return NoModRef;
if (pointsToConstantMemory(Loc))
return NoModRef;
return Mod;
}
AliasAnalysis::ModRefResult
AliasAnalysis::getModRefInfo(const VAArgInst *V, const Location &Loc) {
if (!alias(Location(V->getOperand(0),
UnknownSize,
V->getMetadata(LLVMContext::MD_tbaa)),
Loc))
return NoModRef;
if (pointsToConstantMemory(Loc))
return NoModRef;
return ModRef;
}
AliasAnalysis::ModRefBehavior
AliasAnalysis::getIntrinsicModRefBehavior(unsigned iid) {
#define GET_INTRINSIC_MODREF_BEHAVIOR
#include "llvm/Intrinsics.gen"
#undef GET_INTRINSIC_MODREF_BEHAVIOR
}
AliasAnalysis::~AliasAnalysis() {}
void AliasAnalysis::InitializeAliasAnalysis(Pass *P) {
TD = P->getAnalysisIfAvailable<TargetData>();
AA = &P->getAnalysis<AliasAnalysis>();
}
void AliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<AliasAnalysis>(); }
uint64_t AliasAnalysis::getTypeStoreSize(const Type *Ty) {
return TD ? TD->getTypeStoreSize(Ty) : UnknownSize;
}
bool AliasAnalysis::canBasicBlockModify(const BasicBlock &BB,
const Location &Loc) {
return canInstructionRangeModify(BB.front(), BB.back(), Loc);
}
bool AliasAnalysis::canInstructionRangeModify(const Instruction &I1,
const Instruction &I2,
const Location &Loc) {
assert(I1.getParent() == I2.getParent() &&
"Instructions not in same basic block!");
BasicBlock::const_iterator I = &I1;
BasicBlock::const_iterator E = &I2;
++E;
for (; I != E; ++I) if (getModRefInfo(I, Loc) & Mod)
return true;
return false;
}
bool llvm::isNoAliasCall(const Value *V) {
if (isa<CallInst>(V) || isa<InvokeInst>(V))
return ImmutableCallSite(cast<Instruction>(V))
.paramHasAttr(0, Attribute::NoAlias);
return false;
}
bool llvm::isIdentifiedObject(const Value *V) {
if (isa<AllocaInst>(V))
return true;
if (isa<GlobalValue>(V) && !isa<GlobalAlias>(V))
return true;
if (isNoAliasCall(V))
return true;
if (const Argument *A = dyn_cast<Argument>(V))
return A->hasNoAliasAttr() || A->hasByValAttr();
return false;
}