TypeBasedAliasAnalysis.cpp [plain text]
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Constants.h"
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/Metadata.h"
#include "llvm/Pass.h"
#include "llvm/Support/CommandLine.h"
using namespace llvm;
static cl::opt<bool> EnableTBAA("enable-tbaa", cl::init(true));
namespace {
class TBAANode {
const MDNode *Node;
public:
TBAANode() : Node(0) {}
explicit TBAANode(const MDNode *N) : Node(N) {}
const MDNode *getNode() const { return Node; }
TBAANode getParent() const {
if (Node->getNumOperands() < 2)
return TBAANode();
MDNode *P = dyn_cast_or_null<MDNode>(Node->getOperand(1));
if (!P)
return TBAANode();
return TBAANode(P);
}
bool TypeIsImmutable() const {
if (Node->getNumOperands() < 3)
return false;
ConstantInt *CI = dyn_cast<ConstantInt>(Node->getOperand(2));
if (!CI)
return false;
return CI->getValue()[0];
}
};
}
namespace {
class TypeBasedAliasAnalysis : public ImmutablePass,
public AliasAnalysis {
public:
static char ID; TypeBasedAliasAnalysis() : ImmutablePass(ID) {
initializeTypeBasedAliasAnalysisPass(*PassRegistry::getPassRegistry());
}
virtual void initializePass() {
InitializeAliasAnalysis(this);
}
virtual void *getAdjustedAnalysisPointer(const void *PI) {
if (PI == &AliasAnalysis::ID)
return (AliasAnalysis*)this;
return this;
}
bool Aliases(const MDNode *A, const MDNode *B) const;
private:
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
virtual AliasResult alias(const Location &LocA, const Location &LocB);
virtual bool pointsToConstantMemory(const Location &Loc, bool OrLocal);
virtual ModRefBehavior getModRefBehavior(ImmutableCallSite CS);
virtual ModRefBehavior getModRefBehavior(const Function *F);
virtual ModRefResult getModRefInfo(ImmutableCallSite CS,
const Location &Loc);
virtual ModRefResult getModRefInfo(ImmutableCallSite CS1,
ImmutableCallSite CS2);
};
}
char TypeBasedAliasAnalysis::ID = 0;
INITIALIZE_AG_PASS(TypeBasedAliasAnalysis, AliasAnalysis, "tbaa",
"Type-Based Alias Analysis", false, true, false)
ImmutablePass *llvm::createTypeBasedAliasAnalysisPass() {
return new TypeBasedAliasAnalysis();
}
void
TypeBasedAliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
AliasAnalysis::getAnalysisUsage(AU);
}
bool
TypeBasedAliasAnalysis::Aliases(const MDNode *A,
const MDNode *B) const {
TBAANode RootA, RootB;
for (TBAANode T(A); ; ) {
if (T.getNode() == B)
return true;
RootA = T;
T = T.getParent();
if (!T.getNode())
break;
}
for (TBAANode T(B); ; ) {
if (T.getNode() == A)
return true;
RootB = T;
T = T.getParent();
if (!T.getNode())
break;
}
if (RootA.getNode() != RootB.getNode())
return true;
return false;
}
AliasAnalysis::AliasResult
TypeBasedAliasAnalysis::alias(const Location &LocA,
const Location &LocB) {
if (!EnableTBAA)
return AliasAnalysis::alias(LocA, LocB);
const MDNode *AM = LocA.TBAATag;
if (!AM) return AliasAnalysis::alias(LocA, LocB);
const MDNode *BM = LocB.TBAATag;
if (!BM) return AliasAnalysis::alias(LocA, LocB);
if (Aliases(AM, BM))
return AliasAnalysis::alias(LocA, LocB);
return NoAlias;
}
bool TypeBasedAliasAnalysis::pointsToConstantMemory(const Location &Loc,
bool OrLocal) {
if (!EnableTBAA)
return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal);
const MDNode *M = Loc.TBAATag;
if (!M) return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal);
if (TBAANode(M).TypeIsImmutable())
return true;
return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal);
}
AliasAnalysis::ModRefBehavior
TypeBasedAliasAnalysis::getModRefBehavior(ImmutableCallSite CS) {
if (!EnableTBAA)
return AliasAnalysis::getModRefBehavior(CS);
ModRefBehavior Min = UnknownModRefBehavior;
if (const MDNode *M = CS.getInstruction()->getMetadata(LLVMContext::MD_tbaa))
if (TBAANode(M).TypeIsImmutable())
Min = OnlyReadsMemory;
return ModRefBehavior(AliasAnalysis::getModRefBehavior(CS) & Min);
}
AliasAnalysis::ModRefBehavior
TypeBasedAliasAnalysis::getModRefBehavior(const Function *F) {
return AliasAnalysis::getModRefBehavior(F);
}
AliasAnalysis::ModRefResult
TypeBasedAliasAnalysis::getModRefInfo(ImmutableCallSite CS,
const Location &Loc) {
if (!EnableTBAA)
return AliasAnalysis::getModRefInfo(CS, Loc);
if (const MDNode *L = Loc.TBAATag)
if (const MDNode *M =
CS.getInstruction()->getMetadata(LLVMContext::MD_tbaa))
if (!Aliases(L, M))
return NoModRef;
return AliasAnalysis::getModRefInfo(CS, Loc);
}
AliasAnalysis::ModRefResult
TypeBasedAliasAnalysis::getModRefInfo(ImmutableCallSite CS1,
ImmutableCallSite CS2) {
if (!EnableTBAA)
return AliasAnalysis::getModRefInfo(CS1, CS2);
if (const MDNode *M1 =
CS1.getInstruction()->getMetadata(LLVMContext::MD_tbaa))
if (const MDNode *M2 =
CS2.getInstruction()->getMetadata(LLVMContext::MD_tbaa))
if (!Aliases(M1, M2))
return NoModRef;
return AliasAnalysis::getModRefInfo(CS1, CS2);
}