diff --git a/include/llvm/Analysis/AliasAnalysis.h b/include/llvm/Analysis/AliasAnalysis.h index 42094167052..0aff4f2c9d2 100644 --- a/include/llvm/Analysis/AliasAnalysis.h +++ b/include/llvm/Analysis/AliasAnalysis.h @@ -186,40 +186,57 @@ public: }; }; - /// getModRefBehavior - Return the behavior of the specified function if - /// called from the specified call site. The call site may be null in which - /// case the most generic behavior of this function should be returned. - virtual ModRefBehavior getModRefBehavior(Function *F, CallSite CS, - std::vector *Info = 0); + /// getModRefBehavior - Return the behavior when calling the given call site. + ModRefBehavior getModRefBehavior(CallSite CS, + std::vector *Info = 0); - /// doesNotAccessMemory - If the specified function is known to never read or - /// write memory, return true. If the function only reads from known-constant - /// memory, it is also legal to return true. Functions that unwind the stack - /// are not legal for this predicate. + /// getModRefBehavior - Return the behavior when calling the given function. + /// For use when the call site is not known. + ModRefBehavior getModRefBehavior(Function *F, + std::vector *Info = 0); + + /// doesNotAccessMemory - If the specified call is known to never read or + /// write memory, return true. If the call only reads from known-constant + /// memory, it is also legal to return true. Calls that unwind the stack + /// are legal for this predicate. /// - /// Many optimizations (such as CSE and LICM) can be performed on calls to it, - /// without worrying about aliasing properties, and many functions have this - /// property (e.g. 'sin' and 'cos'). + /// Many optimizations (such as CSE and LICM) can be performed on such calls + /// without worrying about aliasing properties, and many calls have this + /// property (e.g. calls to 'sin' and 'cos'). /// /// This property corresponds to the GCC 'const' attribute. /// - bool doesNotAccessMemory(Function *F) { - return getModRefBehavior(F, CallSite()) == DoesNotAccessMemory; + bool doesNotAccessMemory(CallSite CS) { + return getModRefBehavior(CS) == DoesNotAccessMemory; } - /// onlyReadsMemory - If the specified function is known to only read from - /// non-volatile memory (or not access memory at all), return true. Functions - /// that unwind the stack are not legal for this predicate. + /// doesNotAccessMemory - If the specified function is known to never read or + /// write memory, return true. For use when the call site is not known. + /// + bool doesNotAccessMemory(Function *F) { + return getModRefBehavior(F) == DoesNotAccessMemory; + } + + /// onlyReadsMemory - If the specified call is known to only read from + /// non-volatile memory (or not access memory at all), return true. Calls + /// that unwind the stack are legal for this predicate. /// /// This property allows many common optimizations to be performed in the /// absence of interfering store instructions, such as CSE of strlen calls. /// /// This property corresponds to the GCC 'pure' attribute. /// + bool onlyReadsMemory(CallSite CS) { + ModRefBehavior MRB = getModRefBehavior(CS); + return MRB == DoesNotAccessMemory || MRB == OnlyReadsMemory; + } + + /// onlyReadsMemory - If the specified function is known to only read from + /// non-volatile memory (or not access memory at all), return true. For use + /// when the call site is not known. + /// bool onlyReadsMemory(Function *F) { - /// FIXME: If the analysis returns more precise info, we can reduce it to - /// this. - ModRefBehavior MRB = getModRefBehavior(F, CallSite()); + ModRefBehavior MRB = getModRefBehavior(F); return MRB == DoesNotAccessMemory || MRB == OnlyReadsMemory; } @@ -250,6 +267,14 @@ public: /// virtual bool hasNoModRefInfoForCalls() const; +protected: + /// getModRefBehavior - Return the behavior of the specified function if + /// called from the specified call site. The call site may be null in which + /// case the most generic behavior of this function should be returned. + virtual ModRefBehavior getModRefBehavior(Function *F, CallSite CS, + std::vector *Info = 0); + +public: /// Convenience functions... ModRefResult getModRefInfo(LoadInst *L, Value *P, unsigned Size); ModRefResult getModRefInfo(StoreInst *S, Value *P, unsigned Size); diff --git a/lib/Analysis/AliasAnalysis.cpp b/lib/Analysis/AliasAnalysis.cpp index 2a3ac5ae17c..9e1ae2a0d20 100644 --- a/lib/Analysis/AliasAnalysis.cpp +++ b/lib/Analysis/AliasAnalysis.cpp @@ -27,6 +27,7 @@ #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Pass.h" #include "llvm/BasicBlock.h" +#include "llvm/Function.h" #include "llvm/Instructions.h" #include "llvm/Type.h" #include "llvm/Target/TargetData.h" @@ -112,16 +113,40 @@ AliasAnalysis::getModRefInfo(StoreInst *S, Value *P, unsigned Size) { return pointsToConstantMemory(P) ? NoModRef : Mod; } +AliasAnalysis::ModRefBehavior +AliasAnalysis::getModRefBehavior(CallSite CS, + std::vector *Info) { + if (CS.paramHasAttr(0, ParamAttr::ReadNone)) + // Can't do better than this. + return DoesNotAccessMemory; + ModRefBehavior MRB = UnknownModRefBehavior; + if (Function *F = CS.getCalledFunction()) + MRB = getModRefBehavior(F, CS, Info); + if (MRB != DoesNotAccessMemory && CS.paramHasAttr(0, ParamAttr::ReadOnly)) + return OnlyReadsMemory; + return MRB; +} + +AliasAnalysis::ModRefBehavior +AliasAnalysis::getModRefBehavior(Function *F, + std::vector *Info) { + if (F->paramHasAttr(0, ParamAttr::ReadNone)) + // Can't do better than this. + return DoesNotAccessMemory; + ModRefBehavior MRB = getModRefBehavior(F, CallSite(), Info); + if (MRB != DoesNotAccessMemory && F->paramHasAttr(0, ParamAttr::ReadOnly)) + return OnlyReadsMemory; + return MRB; +} + AliasAnalysis::ModRefResult AliasAnalysis::getModRefInfo(CallSite CS, Value *P, unsigned Size) { ModRefResult Mask = ModRef; - if (Function *F = CS.getCalledFunction()) { - ModRefBehavior MRB = getModRefBehavior(F, CallSite()); - if (MRB == OnlyReadsMemory) - Mask = Ref; - else if (MRB == DoesNotAccessMemory) - return NoModRef; - } + ModRefBehavior MRB = getModRefBehavior(CS); + if (MRB == OnlyReadsMemory) + Mask = Ref; + else if (MRB == DoesNotAccessMemory) + return NoModRef; if (!AA) return Mask; diff --git a/lib/Analysis/AliasAnalysisCounter.cpp b/lib/Analysis/AliasAnalysisCounter.cpp index eea2c9904d1..2fccff1b729 100644 --- a/lib/Analysis/AliasAnalysisCounter.cpp +++ b/lib/Analysis/AliasAnalysisCounter.cpp @@ -89,9 +89,15 @@ namespace { bool pointsToConstantMemory(const Value *P) { return getAnalysis().pointsToConstantMemory(P); } + bool doesNotAccessMemory(CallSite CS) { + return getAnalysis().doesNotAccessMemory(CS); + } bool doesNotAccessMemory(Function *F) { return getAnalysis().doesNotAccessMemory(F); } + bool onlyReadsMemory(CallSite CS) { + return getAnalysis().onlyReadsMemory(CS); + } bool onlyReadsMemory(Function *F) { return getAnalysis().onlyReadsMemory(F); } diff --git a/lib/Analysis/AliasSetTracker.cpp b/lib/Analysis/AliasSetTracker.cpp index fcdd1b33999..1b20c7aebf3 100644 --- a/lib/Analysis/AliasSetTracker.cpp +++ b/lib/Analysis/AliasSetTracker.cpp @@ -114,15 +114,13 @@ void AliasSet::addPointer(AliasSetTracker &AST, HashNodePair &Entry, void AliasSet::addCallSite(CallSite CS, AliasAnalysis &AA) { CallSites.push_back(CS); - if (Function *F = CS.getCalledFunction()) { - AliasAnalysis::ModRefBehavior Behavior = AA.getModRefBehavior(F, CS); - if (Behavior == AliasAnalysis::DoesNotAccessMemory) - return; - else if (Behavior == AliasAnalysis::OnlyReadsMemory) { - AliasTy = MayAlias; - AccessTy |= Refs; - return; - } + AliasAnalysis::ModRefBehavior Behavior = AA.getModRefBehavior(CS); + if (Behavior == AliasAnalysis::DoesNotAccessMemory) + return; + else if (Behavior == AliasAnalysis::OnlyReadsMemory) { + AliasTy = MayAlias; + AccessTy |= Refs; + return; } // FIXME: This should use mod/ref information to make this not suck so bad @@ -166,9 +164,8 @@ bool AliasSet::aliasesPointer(const Value *Ptr, unsigned Size, } bool AliasSet::aliasesCallSite(CallSite CS, AliasAnalysis &AA) const { - if (Function *F = CS.getCalledFunction()) - if (AA.doesNotAccessMemory(F)) - return false; + if (AA.doesNotAccessMemory(CS)) + return false; if (AA.hasNoModRefInfoForCalls()) return true; @@ -297,9 +294,8 @@ bool AliasSetTracker::add(FreeInst *FI) { bool AliasSetTracker::add(CallSite CS) { - if (Function *F = CS.getCalledFunction()) - if (AA.doesNotAccessMemory(F)) - return true; // doesn't alias anything + if (AA.doesNotAccessMemory(CS)) + return true; // doesn't alias anything AliasSet *AS = findAliasSetForCallSite(CS); if (!AS) { @@ -419,9 +415,8 @@ bool AliasSetTracker::remove(FreeInst *FI) { } bool AliasSetTracker::remove(CallSite CS) { - if (Function *F = CS.getCalledFunction()) - if (AA.doesNotAccessMemory(F)) - return false; // doesn't alias anything + if (AA.doesNotAccessMemory(CS)) + return false; // doesn't alias anything AliasSet *AS = findAliasSetForCallSite(CS); if (!AS) return false; @@ -455,13 +450,10 @@ void AliasSetTracker::deleteValue(Value *PtrVal) { // If this is a call instruction, remove the callsite from the appropriate // AliasSet. CallSite CS = CallSite::get(PtrVal); - if (CS.getInstruction()) { - Function *F = CS.getCalledFunction(); - if (!F || !AA.doesNotAccessMemory(F)) { + if (CS.getInstruction()) + if (!AA.doesNotAccessMemory(CS)) if (AliasSet *AS = findAliasSetForCallSite(CS)) AS->removeCallSite(CS); - } - } // First, look up the PointerRec for this pointer. hash_map::iterator I = PointerMap.find(PtrVal); diff --git a/lib/Analysis/BasicAliasAnalysis.cpp b/lib/Analysis/BasicAliasAnalysis.cpp index 575e9218eaa..5ec9afaec98 100644 --- a/lib/Analysis/BasicAliasAnalysis.cpp +++ b/lib/Analysis/BasicAliasAnalysis.cpp @@ -839,11 +839,6 @@ BasicAliasAnalysis::getModRefBehavior(Function *F, CallSite CS, return UnknownModRefBehavior; } - if (F->paramHasAttr(0, ParamAttr::ReadNone)) - return DoesNotAccessMemory; - if (F->paramHasAttr(0, ParamAttr::ReadOnly)) - return OnlyReadsMemory; - return UnknownModRefBehavior; } diff --git a/lib/Analysis/IPA/GlobalsModRef.cpp b/lib/Analysis/IPA/GlobalsModRef.cpp index dce4a1ee8a0..9e943dde5d0 100644 --- a/lib/Analysis/IPA/GlobalsModRef.cpp +++ b/lib/Analysis/IPA/GlobalsModRef.cpp @@ -394,7 +394,7 @@ void GlobalsModRef::AnalyzeSCC(std::vector &SCC) { // Okay, if we can't say anything about it, maybe some other alias // analysis can. ModRefBehavior MRB = - AliasAnalysis::getModRefBehavior(Callee, CallSite()); + AliasAnalysis::getModRefBehavior(Callee); if (MRB != DoesNotAccessMemory) { // FIXME: could make this more aggressive for functions that just // read memory. We should just say they read all globals. diff --git a/lib/Analysis/LoadValueNumbering.cpp b/lib/Analysis/LoadValueNumbering.cpp index 3af92bc11cb..67d4dd22bba 100644 --- a/lib/Analysis/LoadValueNumbering.cpp +++ b/lib/Analysis/LoadValueNumbering.cpp @@ -148,7 +148,7 @@ void LoadVN::getCallEqualNumberNodes(CallInst *CI, Function *CF = CI->getCalledFunction(); if (CF == 0) return; // Indirect call. AliasAnalysis &AA = getAnalysis(); - AliasAnalysis::ModRefBehavior MRB = AA.getModRefBehavior(CF, CI); + AliasAnalysis::ModRefBehavior MRB = AA.getModRefBehavior(CI); if (MRB != AliasAnalysis::DoesNotAccessMemory && MRB != AliasAnalysis::OnlyReadsMemory) return; // Nothing we can do for now. @@ -227,8 +227,7 @@ void LoadVN::getCallEqualNumberNodes(CallInst *CI, CantEqual = true; break; } else if (CallInst *CI = dyn_cast(I)) { - if (CI->getCalledFunction() == 0 || - !AA.onlyReadsMemory(CI->getCalledFunction())) { + if (!AA.onlyReadsMemory(CI)) { CantEqual = true; break; } diff --git a/lib/Analysis/MemoryDependenceAnalysis.cpp b/lib/Analysis/MemoryDependenceAnalysis.cpp index dd567aac95d..8c5f216f539 100644 --- a/lib/Analysis/MemoryDependenceAnalysis.cpp +++ b/lib/Analysis/MemoryDependenceAnalysis.cpp @@ -94,11 +94,9 @@ Instruction* MemoryDependenceAnalysis::getCallSiteDependency(CallSite C, // FreeInsts erase the entire structure pointerSize = ~0UL; - } else if (CallSite::get(QI).getInstruction() != 0 && - cast(QI)->getCalledFunction()) { + } else if (isa(QI)) { AliasAnalysis::ModRefBehavior result = - AA.getModRefBehavior(cast(QI)->getCalledFunction(), - CallSite::get(QI)); + AA.getModRefBehavior(CallSite::get(QI)); if (result != AliasAnalysis::DoesNotAccessMemory && result != AliasAnalysis::OnlyReadsMemory) { if (!start && !block) { diff --git a/lib/Transforms/Scalar/ADCE.cpp b/lib/Transforms/Scalar/ADCE.cpp index e3bd3623ce2..7f373342100 100644 --- a/lib/Transforms/Scalar/ADCE.cpp +++ b/lib/Transforms/Scalar/ADCE.cpp @@ -198,8 +198,7 @@ bool ADCE::doADCE() { for (BasicBlock::iterator II = BB->begin(), EI = BB->end(); II != EI; ) { Instruction *I = II++; if (CallInst *CI = dyn_cast(I)) { - Function *F = CI->getCalledFunction(); - if (F && AA.onlyReadsMemory(F)) { + if (AA.onlyReadsMemory(CI)) { if (CI->use_empty()) { BB->getInstList().erase(CI); ++NumCallRemoved; diff --git a/lib/Transforms/Scalar/DeadStoreElimination.cpp b/lib/Transforms/Scalar/DeadStoreElimination.cpp index b19077f1fcc..8e69d9ad689 100644 --- a/lib/Transforms/Scalar/DeadStoreElimination.cpp +++ b/lib/Transforms/Scalar/DeadStoreElimination.cpp @@ -306,8 +306,7 @@ bool DSE::handleEndBlock(BasicBlock& BB, // If this call does not access memory, it can't // be undeadifying any of our pointers. CallSite CS = CallSite::get(BBI); - if (CS.getCalledFunction() && - AA.doesNotAccessMemory(CS.getCalledFunction())) + if (AA.doesNotAccessMemory(CS)) continue; unsigned modRef = 0; diff --git a/lib/Transforms/Scalar/GVN.cpp b/lib/Transforms/Scalar/GVN.cpp index 7799befb3c2..c3d59854c65 100644 --- a/lib/Transforms/Scalar/GVN.cpp +++ b/lib/Transforms/Scalar/GVN.cpp @@ -341,8 +341,7 @@ Expression::ExpressionOpcode uint32_t ValueTable::hash_operand(Value* v) { if (CallInst* CI = dyn_cast(v)) - if (CI->getCalledFunction() && - !AA->doesNotAccessMemory(CI->getCalledFunction())) + if (!AA->doesNotAccessMemory(CI)) return nextValueNumber++; return lookup_or_add(v); @@ -485,9 +484,7 @@ uint32_t ValueTable::lookup_or_add(Value* V) { return VI->second; if (CallInst* C = dyn_cast(V)) { - if (C->getCalledFunction() && - (AA->doesNotAccessMemory(C->getCalledFunction()) || - AA->onlyReadsMemory(C->getCalledFunction()))) { + if (AA->onlyReadsMemory(C)) { // includes doesNotAccessMemory Expression e = create_expression(C); DenseMap::iterator EI = expressionNumbering.find(e); @@ -1051,8 +1048,7 @@ bool GVN::processInstruction(Instruction* I, if (CallInst* CI = dyn_cast(I)) { AliasAnalysis& AA = getAnalysis(); - if (CI->getCalledFunction() && - !AA.doesNotAccessMemory(CI->getCalledFunction())) { + if (!AA.doesNotAccessMemory(CI)) { MemoryDependenceAnalysis& MD = getAnalysis(); if (cast(repl)->getParent() != CI->getParent() || MD.getDependency(CI) != MD.getDependency(cast(repl))) { diff --git a/lib/Transforms/Scalar/LICM.cpp b/lib/Transforms/Scalar/LICM.cpp index c86b4639489..0c8cb4d0273 100644 --- a/lib/Transforms/Scalar/LICM.cpp +++ b/lib/Transforms/Scalar/LICM.cpp @@ -375,24 +375,22 @@ bool LICM::canSinkOrHoistInst(Instruction &I) { return !pointerInvalidatedByLoop(LI->getOperand(0), Size); } else if (CallInst *CI = dyn_cast(&I)) { // Handle obvious cases efficiently. - if (Function *Callee = CI->getCalledFunction()) { - AliasAnalysis::ModRefBehavior Behavior =AA->getModRefBehavior(Callee, CI); - if (Behavior == AliasAnalysis::DoesNotAccessMemory) - return true; - else if (Behavior == AliasAnalysis::OnlyReadsMemory) { - // If this call only reads from memory and there are no writes to memory - // in the loop, we can hoist or sink the call as appropriate. - bool FoundMod = false; - for (AliasSetTracker::iterator I = CurAST->begin(), E = CurAST->end(); - I != E; ++I) { - AliasSet &AS = *I; - if (!AS.isForwardingAliasSet() && AS.isMod()) { - FoundMod = true; - break; - } + AliasAnalysis::ModRefBehavior Behavior = AA->getModRefBehavior(CI); + if (Behavior == AliasAnalysis::DoesNotAccessMemory) + return true; + else if (Behavior == AliasAnalysis::OnlyReadsMemory) { + // If this call only reads from memory and there are no writes to memory + // in the loop, we can hoist or sink the call as appropriate. + bool FoundMod = false; + for (AliasSetTracker::iterator I = CurAST->begin(), E = CurAST->end(); + I != E; ++I) { + AliasSet &AS = *I; + if (!AS.isForwardingAliasSet() && AS.isMod()) { + FoundMod = true; + break; } - if (!FoundMod) return true; } + if (!FoundMod) return true; } // FIXME: This should use mod/ref information to see if we can hoist or sink