Remove interprocedural-basic-aa and associated code. The AliasAnalysis

interface needs implementations to be consistent, so any code which
wants to support different semantics must use a different interface.
It's not currently worthwhile to add a new interface for this new
concept.

Document that AliasAnalysis doesn't support cross-function queries.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@107776 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Dan Gohman
2010-07-07 14:27:09 +00:00
parent 46151f1764
commit 9e86f4364b
8 changed files with 338 additions and 1959 deletions

View File

@@ -117,6 +117,11 @@ as the actual <tt>call</tt> or <tt>invoke</tt> instructions that performs the
call. The <tt>AliasAnalysis</tt> interface also exposes some helper methods call. The <tt>AliasAnalysis</tt> interface also exposes some helper methods
which allow you to get mod/ref information for arbitrary instructions.</p> which allow you to get mod/ref information for arbitrary instructions.</p>
<p>All <tt>AliasAnalysis</tt> interfaces require that in queries involving
multiple values, values which are not
<a href="LangRef.html#constants">constants</a> are all defined within the
same function.</p>
</div> </div>
<!-- ======================================================================= --> <!-- ======================================================================= -->
@@ -181,9 +186,13 @@ that the accesses alias.</p>
</div> </div>
<div class="doc_text"> <div class="doc_text">
The <tt>alias</tt> method is the primary interface used to determine whether or <p>The <tt>alias</tt> method is the primary interface used to determine whether
not two memory objects alias each other. It takes two memory objects as input or not two memory objects alias each other. It takes two memory objects as
and returns MustAlias, MayAlias, or NoAlias as appropriate. input and returns MustAlias, MayAlias, or NoAlias as appropriate.</p>
<p>Like all <tt>AliasAnalysis</tt> interfaces, the <tt>alias</tt> method requires
that either the two pointer values be defined within the same function, or at
least one of the values is a <a href="LangRef.html#constants">constant</a>.</p>
</div> </div>
<!-- _______________________________________________________________________ --> <!-- _______________________________________________________________________ -->
@@ -202,10 +211,8 @@ the other -- in this case, there is a dependence, but it's mediated by the free
and reallocation.</p> and reallocation.</p>
<p>As an exception to this is with the <p>As an exception to this is with the
<a href="LangRef.html#noalias"><tt>noalias</tt></a> keyword. AliasAnalysis <a href="LangRef.html#noalias"><tt>noalias</tt></a> keyword; the "irrelevant"
implementations may choose to respect the <tt>noalias</tt> keyword and ignore dependencies are ignored.</p>
the "irrelevant" dependencies, provided their clients do not need to be aware
of these dependencies for correctness.</p>
<p>The MayAlias response is used whenever the two pointers might refer to the <p>The MayAlias response is used whenever the two pointers might refer to the
same object. If the two memory objects overlap, but do not start at the same same object. If the two memory objects overlap, but do not start at the same

View File

@@ -323,10 +323,10 @@ bool isNoAliasCall(const Value *V);
/// identifiable object. This returns true for: /// identifiable object. This returns true for:
/// Global Variables and Functions (but not Global Aliases) /// Global Variables and Functions (but not Global Aliases)
/// Allocas and Mallocs /// Allocas and Mallocs
/// ByVal and NoAlias Arguments, if Interprocedural is false /// ByVal and NoAlias Arguments
/// NoAlias returns, if Interprocedural is false /// NoAlias returns
/// ///
bool isIdentifiedObject(const Value *V, bool Interprocedural = false); bool isIdentifiedObject(const Value *V);
} // End llvm namespace } // End llvm namespace

View File

@@ -51,13 +51,6 @@ namespace llvm {
// //
FunctionPass *createAAEvalPass(); FunctionPass *createAAEvalPass();
//===--------------------------------------------------------------------===//
//
// createInterproceduralAAEvalPass - This pass implements a simple
// N^2 interprocedural alias analysis accuracy evaluator.
//
Pass *createInterproceduralAAEvalPass();
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
// //
// createNoAAPass - This pass implements a "I don't know" alias analysis. // createNoAAPass - This pass implements a "I don't know" alias analysis.
@@ -67,21 +60,10 @@ namespace llvm {
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
// //
// createBasicAliasAnalysisPass - This pass implements the default alias // createBasicAliasAnalysisPass - This pass implements the default alias
// analysis. This analysis respects the noalias attribute, so it is not // analysis.
// suitable for some interprocedural uses (see the discussion of noalias
// in AliasAnalysis.html for details).
// //
ImmutablePass *createBasicAliasAnalysisPass(); ImmutablePass *createBasicAliasAnalysisPass();
//===--------------------------------------------------------------------===//
//
// createInterproceduralBasicAliasAnalysisPass - This pass is similar to
// baiscaa, except that it properly supports queries to values which live
// in different functions. Unlike the regular BasicAliasAnalysis, this
// implementation does not respect the noalias attribute.
//
ImmutablePass *createInterproceduralBasicAliasAnalysisPass();
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
// //
/// createLibCallAliasAnalysisPass - Create an alias analysis pass that knows /// createLibCallAliasAnalysisPass - Create an alias analysis pass that knows

View File

@@ -229,20 +229,18 @@ bool llvm::isNoAliasCall(const Value *V) {
/// identifiable object. This returns true for: /// identifiable object. This returns true for:
/// Global Variables and Functions (but not Global Aliases) /// Global Variables and Functions (but not Global Aliases)
/// Allocas and Mallocs /// Allocas and Mallocs
/// ByVal and NoAlias Arguments, if Interprocedural is false /// ByVal and NoAlias Arguments
/// NoAlias returns, if Interprocedural is false /// NoAlias returns
/// ///
bool llvm::isIdentifiedObject(const Value *V, bool Interprocedural) { bool llvm::isIdentifiedObject(const Value *V) {
if (isa<AllocaInst>(V)) if (isa<AllocaInst>(V))
return true; return true;
if (isa<GlobalValue>(V) && !isa<GlobalAlias>(V)) if (isa<GlobalValue>(V) && !isa<GlobalAlias>(V))
return true; return true;
if (!Interprocedural) {
if (isNoAliasCall(V)) if (isNoAliasCall(V))
return true; return true;
if (const Argument *A = dyn_cast<Argument>(V)) if (const Argument *A = dyn_cast<Argument>(V))
return A->hasNoAliasAttr() || A->hasByValAttr(); return A->hasNoAliasAttr() || A->hasByValAttr();
}
return false; return false;
} }

View File

@@ -21,7 +21,6 @@
#include "llvm/DerivedTypes.h" #include "llvm/DerivedTypes.h"
#include "llvm/Function.h" #include "llvm/Function.h"
#include "llvm/Instructions.h" #include "llvm/Instructions.h"
#include "llvm/Module.h"
#include "llvm/Pass.h" #include "llvm/Pass.h"
#include "llvm/Analysis/Passes.h" #include "llvm/Analysis/Passes.h"
#include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/AliasAnalysis.h"
@@ -45,21 +44,20 @@ static cl::opt<bool> PrintRef("print-ref", cl::ReallyHidden);
static cl::opt<bool> PrintModRef("print-modref", cl::ReallyHidden); static cl::opt<bool> PrintModRef("print-modref", cl::ReallyHidden);
namespace { namespace {
/// AAEval - Base class for exhaustive alias analysis evaluators. class AAEval : public FunctionPass {
class AAEval {
protected:
unsigned NoAlias, MayAlias, MustAlias; unsigned NoAlias, MayAlias, MustAlias;
unsigned NoModRef, Mod, Ref, ModRef; unsigned NoModRef, Mod, Ref, ModRef;
SetVector<Value *> Pointers; public:
SetVector<CallSite> CallSites; static char ID; // Pass identification, replacement for typeid
AAEval() : FunctionPass(&ID) {}
void getAnalysisUsage(AnalysisUsage &AU) const { virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<AliasAnalysis>(); AU.addRequired<AliasAnalysis>();
AU.setPreservesAll(); AU.setPreservesAll();
} }
void doInitialization(Module &M) { bool doInitialization(Module &M) {
NoAlias = MayAlias = MustAlias = 0; NoAlias = MayAlias = MustAlias = 0;
NoModRef = Mod = Ref = ModRef = 0; NoModRef = Mod = Ref = ModRef = 0;
@@ -67,85 +65,19 @@ namespace {
PrintNoAlias = PrintMayAlias = PrintMustAlias = true; PrintNoAlias = PrintMayAlias = PrintMustAlias = true;
PrintNoModRef = PrintMod = PrintRef = PrintModRef = true; PrintNoModRef = PrintMod = PrintRef = PrintModRef = true;
} }
}
void runOnFunction(Function &F);
void evaluate(AliasAnalysis *AA, Module *M);
void doFinalization(Module &M);
};
class FunctionAAEval : public FunctionPass, AAEval {
public:
static char ID; // Pass identification, replacement for typeid
FunctionAAEval() : FunctionPass(&ID) {}
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
return AAEval::getAnalysisUsage(AU);
}
virtual bool doInitialization(Module &M) {
AAEval::doInitialization(M);
return false; return false;
} }
virtual bool runOnFunction(Function &F) { bool runOnFunction(Function &F);
AAEval::runOnFunction(F); bool doFinalization(Module &M);
if (PrintNoAlias || PrintMayAlias || PrintMustAlias ||
PrintNoModRef || PrintMod || PrintRef || PrintModRef)
errs() << "Function: " << F.getName() << ": " << Pointers.size()
<< " pointers, " << CallSites.size() << " call sites\n";
AAEval::evaluate(&getAnalysis<AliasAnalysis>(), F.getParent());
return false;
}
virtual bool doFinalization(Module &M) {
AAEval::doFinalization(M);
return false;
}
};
class InterproceduralAAEval : public ModulePass, AAEval {
public:
static char ID; // Pass identification, replacement for typeid
InterproceduralAAEval() : ModulePass(&ID) {}
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
return AAEval::getAnalysisUsage(AU);
}
virtual bool runOnModule(Module &M) {
AAEval::doInitialization(M);
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
AAEval::runOnFunction(*I);
if (PrintNoAlias || PrintMayAlias || PrintMustAlias ||
PrintNoModRef || PrintMod || PrintRef || PrintModRef)
errs() << "Module: " << Pointers.size()
<< " pointers, " << CallSites.size() << " call sites\n";
AAEval::evaluate(&getAnalysis<AliasAnalysis>(), &M);
AAEval::doFinalization(M);
return false;
}
}; };
} }
char FunctionAAEval::ID = 0; char AAEval::ID = 0;
static RegisterPass<FunctionAAEval> static RegisterPass<AAEval>
X("aa-eval", "Exhaustive Alias Analysis Precision Evaluator", false, true); X("aa-eval", "Exhaustive Alias Analysis Precision Evaluator", false, true);
FunctionPass *llvm::createAAEvalPass() { return new FunctionAAEval(); } FunctionPass *llvm::createAAEvalPass() { return new AAEval(); }
char InterproceduralAAEval::ID = 0;
static RegisterPass<InterproceduralAAEval>
Y("interprocedural-aa-eval",
"Exhaustive Interprocedural Alias Analysis Precision Evaluator", false, true);
Pass *llvm::createInterproceduralAAEvalPass() {
return new InterproceduralAAEval();
}
static void PrintResults(const char *Msg, bool P, const Value *V1, static void PrintResults(const char *Msg, bool P, const Value *V1,
const Value *V2, const Module *M) { const Value *V2, const Module *M) {
@@ -180,7 +112,12 @@ static inline bool isInterestingPointer(Value *V) {
&& !isa<ConstantPointerNull>(V); && !isa<ConstantPointerNull>(V);
} }
void AAEval::runOnFunction(Function &F) { bool AAEval::runOnFunction(Function &F) {
AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
SetVector<Value *> Pointers;
SetVector<CallSite> CallSites;
for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I)
if (I->getType()->isPointerTy()) // Add all pointer arguments. if (I->getType()->isPointerTy()) // Add all pointer arguments.
Pointers.insert(I); Pointers.insert(I);
@@ -210,31 +147,33 @@ void AAEval::runOnFunction(Function &F) {
if (CS.getInstruction()) CallSites.insert(CS); if (CS.getInstruction()) CallSites.insert(CS);
} }
}
void AAEval::evaluate(AliasAnalysis *AA, Module *M) { if (PrintNoAlias || PrintMayAlias || PrintMustAlias ||
PrintNoModRef || PrintMod || PrintRef || PrintModRef)
errs() << "Function: " << F.getName() << ": " << Pointers.size()
<< " pointers, " << CallSites.size() << " call sites\n";
// iterate over the worklist, and run the full (n^2)/2 disambiguations // iterate over the worklist, and run the full (n^2)/2 disambiguations
for (SetVector<Value *>::iterator I1 = Pointers.begin(), E = Pointers.end(); for (SetVector<Value *>::iterator I1 = Pointers.begin(), E = Pointers.end();
I1 != E; ++I1) { I1 != E; ++I1) {
unsigned I1Size = ~0u; unsigned I1Size = ~0u;
const Type *I1ElTy = cast<PointerType>((*I1)->getType())->getElementType(); const Type *I1ElTy = cast<PointerType>((*I1)->getType())->getElementType();
if (I1ElTy->isSized()) I1Size = AA->getTypeStoreSize(I1ElTy); if (I1ElTy->isSized()) I1Size = AA.getTypeStoreSize(I1ElTy);
for (SetVector<Value *>::iterator I2 = Pointers.begin(); I2 != I1; ++I2) { for (SetVector<Value *>::iterator I2 = Pointers.begin(); I2 != I1; ++I2) {
unsigned I2Size = ~0u; unsigned I2Size = ~0u;
const Type *I2ElTy =cast<PointerType>((*I2)->getType())->getElementType(); const Type *I2ElTy =cast<PointerType>((*I2)->getType())->getElementType();
if (I2ElTy->isSized()) I2Size = AA->getTypeStoreSize(I2ElTy); if (I2ElTy->isSized()) I2Size = AA.getTypeStoreSize(I2ElTy);
switch (AA->alias(*I1, I1Size, *I2, I2Size)) { switch (AA.alias(*I1, I1Size, *I2, I2Size)) {
case AliasAnalysis::NoAlias: case AliasAnalysis::NoAlias:
PrintResults("NoAlias", PrintNoAlias, *I1, *I2, M); PrintResults("NoAlias", PrintNoAlias, *I1, *I2, F.getParent());
++NoAlias; break; ++NoAlias; break;
case AliasAnalysis::MayAlias: case AliasAnalysis::MayAlias:
PrintResults("MayAlias", PrintMayAlias, *I1, *I2, M); PrintResults("MayAlias", PrintMayAlias, *I1, *I2, F.getParent());
++MayAlias; break; ++MayAlias; break;
case AliasAnalysis::MustAlias: case AliasAnalysis::MustAlias:
PrintResults("MustAlias", PrintMustAlias, *I1, *I2, M); PrintResults("MustAlias", PrintMustAlias, *I1, *I2, F.getParent());
++MustAlias; break; ++MustAlias; break;
default: default:
errs() << "Unknown alias query result!\n"; errs() << "Unknown alias query result!\n";
@@ -251,20 +190,20 @@ void AAEval::evaluate(AliasAnalysis *AA, Module *M) {
V != Ve; ++V) { V != Ve; ++V) {
unsigned Size = ~0u; unsigned Size = ~0u;
const Type *ElTy = cast<PointerType>((*V)->getType())->getElementType(); const Type *ElTy = cast<PointerType>((*V)->getType())->getElementType();
if (ElTy->isSized()) Size = AA->getTypeStoreSize(ElTy); if (ElTy->isSized()) Size = AA.getTypeStoreSize(ElTy);
switch (AA->getModRefInfo(*C, *V, Size)) { switch (AA.getModRefInfo(*C, *V, Size)) {
case AliasAnalysis::NoModRef: case AliasAnalysis::NoModRef:
PrintModRefResults("NoModRef", PrintNoModRef, I, *V, M); PrintModRefResults("NoModRef", PrintNoModRef, I, *V, F.getParent());
++NoModRef; break; ++NoModRef; break;
case AliasAnalysis::Mod: case AliasAnalysis::Mod:
PrintModRefResults(" Mod", PrintMod, I, *V, M); PrintModRefResults(" Mod", PrintMod, I, *V, F.getParent());
++Mod; break; ++Mod; break;
case AliasAnalysis::Ref: case AliasAnalysis::Ref:
PrintModRefResults(" Ref", PrintRef, I, *V, M); PrintModRefResults(" Ref", PrintRef, I, *V, F.getParent());
++Ref; break; ++Ref; break;
case AliasAnalysis::ModRef: case AliasAnalysis::ModRef:
PrintModRefResults(" ModRef", PrintModRef, I, *V, M); PrintModRefResults(" ModRef", PrintModRef, I, *V, F.getParent());
++ModRef; break; ++ModRef; break;
default: default:
errs() << "Unknown alias query result!\n"; errs() << "Unknown alias query result!\n";
@@ -272,8 +211,7 @@ void AAEval::evaluate(AliasAnalysis *AA, Module *M) {
} }
} }
Pointers.clear(); return false;
CallSites.clear();
} }
static void PrintPercent(unsigned Num, unsigned Sum) { static void PrintPercent(unsigned Num, unsigned Sum) {
@@ -281,7 +219,7 @@ static void PrintPercent(unsigned Num, unsigned Sum) {
<< ((Num*1000ULL/Sum) % 10) << "%)\n"; << ((Num*1000ULL/Sum) % 10) << "%)\n";
} }
void AAEval::doFinalization(Module &M) { bool AAEval::doFinalization(Module &M) {
unsigned AliasSum = NoAlias + MayAlias + MustAlias; unsigned AliasSum = NoAlias + MayAlias + MustAlias;
errs() << "===== Alias Analysis Evaluator Report =====\n"; errs() << "===== Alias Analysis Evaluator Report =====\n";
if (AliasSum == 0) { if (AliasSum == 0) {
@@ -317,4 +255,6 @@ void AAEval::doFinalization(Module &M) {
<< NoModRef*100/ModRefSum << "%/" << Mod*100/ModRefSum << "%/" << NoModRef*100/ModRefSum << "%/" << Mod*100/ModRefSum << "%/"
<< Ref*100/ModRefSum << "%/" << ModRef*100/ModRefSum << "%\n"; << Ref*100/ModRefSum << "%/" << ModRef*100/ModRefSum << "%\n";
} }
return false;
} }

View File

@@ -194,6 +194,7 @@ ImmutablePass *llvm::createNoAAPass() { return new NoAA(); }
// BasicAliasAnalysis Pass // BasicAliasAnalysis Pass
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#ifndef NDEBUG
static const Function *getParent(const Value *V) { static const Function *getParent(const Value *V) {
if (const Instruction *inst = dyn_cast<Instruction>(V)) if (const Instruction *inst = dyn_cast<Instruction>(V))
return inst->getParent()->getParent(); return inst->getParent()->getParent();
@@ -204,15 +205,6 @@ static const Function *getParent(const Value *V) {
return NULL; return NULL;
} }
static bool sameParent(const Value *O1, const Value *O2) {
const Function *F1 = getParent(O1);
const Function *F2 = getParent(O2);
return F1 && F1 == F2;
}
#ifdef XDEBUG
static bool notDifferentParent(const Value *O1, const Value *O2) { static bool notDifferentParent(const Value *O1, const Value *O2) {
const Function *F1 = getParent(O1); const Function *F1 = getParent(O1);
@@ -227,25 +219,14 @@ namespace {
/// Because it doesn't chain to a previous alias analysis (like -no-aa), it /// Because it doesn't chain to a previous alias analysis (like -no-aa), it
/// derives from the NoAA class. /// derives from the NoAA class.
struct BasicAliasAnalysis : public NoAA { struct BasicAliasAnalysis : public NoAA {
/// Interprocedural - Flag for "interprocedural" mode, where we must
/// support queries of values which live in different functions.
bool Interprocedural;
static char ID; // Class identification, replacement for typeinfo static char ID; // Class identification, replacement for typeinfo
BasicAliasAnalysis() BasicAliasAnalysis() : NoAA(&ID) {}
: NoAA(&ID), Interprocedural(false) {}
BasicAliasAnalysis(void *PID, bool interprocedural)
: NoAA(PID), Interprocedural(interprocedural) {}
AliasResult alias(const Value *V1, unsigned V1Size, AliasResult alias(const Value *V1, unsigned V1Size,
const Value *V2, unsigned V2Size) { const Value *V2, unsigned V2Size) {
assert(Visited.empty() && "Visited must be cleared after use!"); assert(Visited.empty() && "Visited must be cleared after use!");
#ifdef XDEBUG assert(notDifferentParent(V1, V2) &&
assert((Interprocedural || notDifferentParent(V1, V2)) && "BasicAliasAnalysis doesn't support interprocedural queries.");
"BasicAliasAnalysis (-basicaa) doesn't support interprocedural "
"queries; use InterproceduralAliasAnalysis "
"(-interprocedural-basic-aa) instead.");
#endif
AliasResult Alias = aliasCheck(V1, V1Size, V2, V2Size); AliasResult Alias = aliasCheck(V1, V1Size, V2, V2Size);
Visited.clear(); Visited.clear();
return Alias; return Alias;
@@ -324,6 +305,9 @@ bool BasicAliasAnalysis::pointsToConstantMemory(const Value *P) {
/// simple "address taken" analysis on local objects. /// simple "address taken" analysis on local objects.
AliasAnalysis::ModRefResult AliasAnalysis::ModRefResult
BasicAliasAnalysis::getModRefInfo(CallSite CS, Value *P, unsigned Size) { BasicAliasAnalysis::getModRefInfo(CallSite CS, Value *P, unsigned Size) {
assert(notDifferentParent(CS.getInstruction(), P) &&
"AliasAnalysis query involving multiple functions!");
const Value *Object = P->getUnderlyingObject(); const Value *Object = P->getUnderlyingObject();
// If this is a tail call and P points to a stack location, we know that // If this is a tail call and P points to a stack location, we know that
@@ -336,16 +320,10 @@ BasicAliasAnalysis::getModRefInfo(CallSite CS, Value *P, unsigned Size) {
if (CI->isTailCall()) if (CI->isTailCall())
return NoModRef; return NoModRef;
// If we can identify an object and it's known to be within the
// same function as the call, we can ignore interprocedural concerns.
bool EffectivelyInterprocedural =
Interprocedural && !sameParent(Object, CS.getInstruction());
// If the pointer is to a locally allocated object that does not escape, // If the pointer is to a locally allocated object that does not escape,
// then the call can not mod/ref the pointer unless the call takes the pointer // then the call can not mod/ref the pointer unless the call takes the pointer
// as an argument, and itself doesn't capture it. // as an argument, and itself doesn't capture it.
if (!isa<Constant>(Object) && CS.getInstruction() != Object && if (!isa<Constant>(Object) && CS.getInstruction() != Object &&
!EffectivelyInterprocedural &&
isNonEscapingLocalObject(Object)) { isNonEscapingLocalObject(Object)) {
bool PassedAsArg = false; bool PassedAsArg = false;
unsigned ArgNo = 0; unsigned ArgNo = 0;
@@ -765,36 +743,25 @@ BasicAliasAnalysis::aliasCheck(const Value *V1, unsigned V1Size,
if (CPN->getType()->getAddressSpace() == 0) if (CPN->getType()->getAddressSpace() == 0)
return NoAlias; return NoAlias;
// If we can identify two objects and they're known to be within the
// same function, we can ignore interprocedural concerns.
bool EffectivelyInterprocedural =
Interprocedural && !sameParent(O1, O2);
if (O1 != O2) { if (O1 != O2) {
// If V1/V2 point to two different objects we know that we have no alias. // If V1/V2 point to two different objects we know that we have no alias.
if (isIdentifiedObject(O1, EffectivelyInterprocedural) && if (isIdentifiedObject(O1) && isIdentifiedObject(O2))
isIdentifiedObject(O2, EffectivelyInterprocedural))
return NoAlias; return NoAlias;
// Constant pointers can't alias with non-const isIdentifiedObject objects. // Constant pointers can't alias with non-const isIdentifiedObject objects.
if ((isa<Constant>(O1) && if ((isa<Constant>(O1) && isIdentifiedObject(O2) && !isa<Constant>(O2)) ||
isIdentifiedObject(O2, EffectivelyInterprocedural) && (isa<Constant>(O2) && isIdentifiedObject(O1) && !isa<Constant>(O1)))
!isa<Constant>(O2)) ||
(isa<Constant>(O2) &&
isIdentifiedObject(O1, EffectivelyInterprocedural) &&
!isa<Constant>(O1)))
return NoAlias; return NoAlias;
// Arguments can't alias with local allocations or noalias calls // Arguments can't alias with local allocations or noalias calls
// in the same function. // in the same function.
if (!EffectivelyInterprocedural && if (((isa<Argument>(O1) && (isa<AllocaInst>(O2) || isNoAliasCall(O2))) ||
((isa<Argument>(O1) && (isa<AllocaInst>(O2) || isNoAliasCall(O2))) ||
(isa<Argument>(O2) && (isa<AllocaInst>(O1) || isNoAliasCall(O1))))) (isa<Argument>(O2) && (isa<AllocaInst>(O1) || isNoAliasCall(O1)))))
return NoAlias; return NoAlias;
// Most objects can't alias null. // Most objects can't alias null.
if ((isa<ConstantPointerNull>(V2) && isKnownNonNull(O1)) || if ((isa<ConstantPointerNull>(O2) && isKnownNonNull(O1)) ||
(isa<ConstantPointerNull>(V1) && isKnownNonNull(O2))) (isa<ConstantPointerNull>(O1) && isKnownNonNull(O2)))
return NoAlias; return NoAlias;
} }
@@ -814,7 +781,7 @@ BasicAliasAnalysis::aliasCheck(const Value *V1, unsigned V1Size,
// temporary store the nocapture argument's value in a temporary memory // temporary store the nocapture argument's value in a temporary memory
// location if that memory location doesn't escape. Or it may pass a // location if that memory location doesn't escape. Or it may pass a
// nocapture value to other functions as long as they don't capture it. // nocapture value to other functions as long as they don't capture it.
if (O1 != O2 && !EffectivelyInterprocedural) { if (O1 != O2) {
if (isEscapeSource(O1) && isNonEscapingLocalObject(O2)) if (isEscapeSource(O1) && isNonEscapingLocalObject(O2))
return NoAlias; return NoAlias;
if (isEscapeSource(O2) && isNonEscapingLocalObject(O1)) if (isEscapeSource(O2) && isNonEscapingLocalObject(O1))
@@ -850,33 +817,3 @@ BasicAliasAnalysis::aliasCheck(const Value *V1, unsigned V1Size,
// Make sure that anything that uses AliasAnalysis pulls in this file. // Make sure that anything that uses AliasAnalysis pulls in this file.
DEFINING_FILE_FOR(BasicAliasAnalysis) DEFINING_FILE_FOR(BasicAliasAnalysis)
//===----------------------------------------------------------------------===//
// InterproceduralBasicAliasAnalysis Pass
//===----------------------------------------------------------------------===//
namespace {
/// InterproceduralBasicAliasAnalysis - This is similar to basicaa, except
/// that it properly supports queries to values which live in different
/// functions.
///
/// Note that we don't currently take this to the extreme, analyzing all
/// call sites of a function to answer a query about an Argument.
///
struct InterproceduralBasicAliasAnalysis : public BasicAliasAnalysis {
static char ID; // Class identification, replacement for typeinfo
InterproceduralBasicAliasAnalysis() : BasicAliasAnalysis(&ID, true) {}
};
}
// Register this pass...
char InterproceduralBasicAliasAnalysis::ID = 0;
static RegisterPass<InterproceduralBasicAliasAnalysis>
W("interprocedural-basic-aa", "Interprocedural Basic Alias Analysis", false, true);
// Declare that we implement the AliasAnalysis interface
static RegisterAnalysisGroup<AliasAnalysis> Z(W);
ImmutablePass *llvm::createInterproceduralBasicAliasAnalysisPass() {
return new InterproceduralBasicAliasAnalysis();
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,73 +0,0 @@
; RUN: opt -interprocedural-basic-aa -interprocedural-aa-eval -print-all-alias-modref-info -disable-output < %s |& FileCheck %s
; The noalias attribute is not safe in an interprocedural context.
; CHECK: MayAlias: i8* %p, i8* %q
define void @t0(i8* noalias %p) {
store i8 0, i8* %p
ret void
}
define void @t1(i8* noalias %q) {
store i8 0, i8* %q
ret void
}
; An alloca can alias an argument in a different function.
; CHECK: MayAlias: i32* %r, i32* %s
define void @s0(i32* %r) {
store i32 0, i32* %r
ret void
}
define void @s1() {
%s = alloca i32, i32 10
store i32 0, i32* %s
call void @s0(i32* %s)
ret void
}
; An alloca does not alias an argument in the same function.
; CHECK: NoAlias: i64* %t, i64* %u
; CHECK: NoAlias: i64* %a, i64* %u
; CHECK: NoAlias: i64* %a, i64* %t
; CHECK: MayAlias: i64* %u, i64* %v
; CHECK: MayAlias: i64* %t, i64* %v
; CHECK: NoAlias: i64* %a, i64* %v
; CHECK: MayAlias: i64* %b, i64* %u
; CHECK: MayAlias: i64* %b, i64* %t
; CHECK: MayAlias: i64* %b, i64* %v
declare i64* @r0_callee(i64*)
define i64* @r0(i64* %u) {
%t = alloca i64, i32 10
%a = alloca i64, i32 10
%v = call i64* @r0_callee(i64* %t)
%b = call i64* @r0_callee(i64* %t)
store i64 0, i64* %t
store i64 0, i64* %u
store i64 0, i64* %v
store i64 0, i64* %a
store i64 0, i64* %b
ret i64* %t
}
; The noalias attribute is safe when both arguments belong to the same function
; even in an interprocedural context.
; CHECK: NoAlias: i8* %w, i8* %x
define void @q0(i8* noalias %w, i8* noalias %x) {
store i8 0, i8* %w
store i8 0, i8* %x
call void @q0(i8* noalias %x, i8* noalias %w)
unreachable
}
; The noalias attribute is not necessarily safe in an interprocedural context.
; CHECK: MayAlias: double* %y, double* @G
@G = external global double
define void @p0(double* noalias %y) {
store double 0.0, double* %y
store double 0.0, double* @G
unreachable
}