Author: baldrick Date: Sat Dec 1 01:51:45 2007 New Revision: 44487 URL: http://llvm.org/viewvc/llvm-project?rev=44487&view=rev Log: Integrate the readonly/readnone logic more deeply into alias analysis. This meant updating the API which now has versions of the getModRefBehavior, doesNotAccessMemory and onlyReadsMemory methods which take a callsite parameter. These should be used unless the callsite is not known, since in general they can do a better job than the versions that take a function. Also, users should no longer call the version of getModRefBehavior that takes both a function and a callsite. To reduce the chance of misuse it is now protected.
Modified: llvm/trunk/include/llvm/Analysis/AliasAnalysis.h llvm/trunk/lib/Analysis/AliasAnalysis.cpp llvm/trunk/lib/Analysis/AliasAnalysisCounter.cpp llvm/trunk/lib/Analysis/AliasSetTracker.cpp llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp llvm/trunk/lib/Analysis/IPA/GlobalsModRef.cpp llvm/trunk/lib/Analysis/LoadValueNumbering.cpp llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp llvm/trunk/lib/Transforms/Scalar/ADCE.cpp llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp llvm/trunk/lib/Transforms/Scalar/GVN.cpp llvm/trunk/lib/Transforms/Scalar/LICM.cpp Modified: llvm/trunk/include/llvm/Analysis/AliasAnalysis.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/AliasAnalysis.h?rev=44487&r1=44486&r2=44487&view=diff ============================================================================== --- llvm/trunk/include/llvm/Analysis/AliasAnalysis.h (original) +++ llvm/trunk/include/llvm/Analysis/AliasAnalysis.h Sat Dec 1 01:51:45 2007 @@ -186,40 +186,57 @@ }; }; - /// 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<PointerAccessInfo> *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. - /// - /// 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'). + /// getModRefBehavior - Return the behavior when calling the given call site. + ModRefBehavior getModRefBehavior(CallSite CS, + std::vector<PointerAccessInfo> *Info = 0); + + /// getModRefBehavior - Return the behavior when calling the given function. + /// For use when the call site is not known. + ModRefBehavior getModRefBehavior(Function *F, + std::vector<PointerAccessInfo> *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 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(CallSite CS) { + return getModRefBehavior(CS) == DoesNotAccessMemory; + } + + /// 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, CallSite()) == DoesNotAccessMemory; + return getModRefBehavior(F) == 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. + /// 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 @@ /// 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<PointerAccessInfo> *Info = 0); + +public: /// Convenience functions... ModRefResult getModRefInfo(LoadInst *L, Value *P, unsigned Size); ModRefResult getModRefInfo(StoreInst *S, Value *P, unsigned Size); Modified: llvm/trunk/lib/Analysis/AliasAnalysis.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/AliasAnalysis.cpp?rev=44487&r1=44486&r2=44487&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/AliasAnalysis.cpp (original) +++ llvm/trunk/lib/Analysis/AliasAnalysis.cpp Sat Dec 1 01:51:45 2007 @@ -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 @@ return pointsToConstantMemory(P) ? NoModRef : Mod; } +AliasAnalysis::ModRefBehavior +AliasAnalysis::getModRefBehavior(CallSite CS, + std::vector<PointerAccessInfo> *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<PointerAccessInfo> *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; Modified: llvm/trunk/lib/Analysis/AliasAnalysisCounter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/AliasAnalysisCounter.cpp?rev=44487&r1=44486&r2=44487&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/AliasAnalysisCounter.cpp (original) +++ llvm/trunk/lib/Analysis/AliasAnalysisCounter.cpp Sat Dec 1 01:51:45 2007 @@ -89,9 +89,15 @@ bool pointsToConstantMemory(const Value *P) { return getAnalysis<AliasAnalysis>().pointsToConstantMemory(P); } + bool doesNotAccessMemory(CallSite CS) { + return getAnalysis<AliasAnalysis>().doesNotAccessMemory(CS); + } bool doesNotAccessMemory(Function *F) { return getAnalysis<AliasAnalysis>().doesNotAccessMemory(F); } + bool onlyReadsMemory(CallSite CS) { + return getAnalysis<AliasAnalysis>().onlyReadsMemory(CS); + } bool onlyReadsMemory(Function *F) { return getAnalysis<AliasAnalysis>().onlyReadsMemory(F); } Modified: llvm/trunk/lib/Analysis/AliasSetTracker.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/AliasSetTracker.cpp?rev=44487&r1=44486&r2=44487&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/AliasSetTracker.cpp (original) +++ llvm/trunk/lib/Analysis/AliasSetTracker.cpp Sat Dec 1 01:51:45 2007 @@ -114,15 +114,13 @@ 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::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(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(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 @@ // 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<Value*, AliasSet::PointerRec>::iterator I = PointerMap.find(PtrVal); Modified: llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp?rev=44487&r1=44486&r2=44487&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp (original) +++ llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp Sat Dec 1 01:51:45 2007 @@ -839,11 +839,6 @@ return UnknownModRefBehavior; } - if (F->paramHasAttr(0, ParamAttr::ReadNone)) - return DoesNotAccessMemory; - if (F->paramHasAttr(0, ParamAttr::ReadOnly)) - return OnlyReadsMemory; - return UnknownModRefBehavior; } Modified: llvm/trunk/lib/Analysis/IPA/GlobalsModRef.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/IPA/GlobalsModRef.cpp?rev=44487&r1=44486&r2=44487&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/IPA/GlobalsModRef.cpp (original) +++ llvm/trunk/lib/Analysis/IPA/GlobalsModRef.cpp Sat Dec 1 01:51:45 2007 @@ -394,7 +394,7 @@ // 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. Modified: llvm/trunk/lib/Analysis/LoadValueNumbering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/LoadValueNumbering.cpp?rev=44487&r1=44486&r2=44487&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/LoadValueNumbering.cpp (original) +++ llvm/trunk/lib/Analysis/LoadValueNumbering.cpp Sat Dec 1 01:51:45 2007 @@ -148,7 +148,7 @@ Function *CF = CI->getCalledFunction(); if (CF == 0) return; // Indirect call. AliasAnalysis &AA = getAnalysis<AliasAnalysis>(); - 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 @@ CantEqual = true; break; } else if (CallInst *CI = dyn_cast<CallInst>(I)) { - if (CI->getCalledFunction() == 0 || - !AA.onlyReadsMemory(CI->getCalledFunction())) { + if (!AA.onlyReadsMemory(CI)) { CantEqual = true; break; } Modified: llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp?rev=44487&r1=44486&r2=44487&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp (original) +++ llvm/trunk/lib/Analysis/MemoryDependenceAnalysis.cpp Sat Dec 1 01:51:45 2007 @@ -94,11 +94,9 @@ // FreeInsts erase the entire structure pointerSize = ~0UL; - } else if (CallSite::get(QI).getInstruction() != 0 && - cast<CallInst>(QI)->getCalledFunction()) { + } else if (isa<CallInst>(QI)) { AliasAnalysis::ModRefBehavior result = - AA.getModRefBehavior(cast<CallInst>(QI)->getCalledFunction(), - CallSite::get(QI)); + AA.getModRefBehavior(CallSite::get(QI)); if (result != AliasAnalysis::DoesNotAccessMemory && result != AliasAnalysis::OnlyReadsMemory) { if (!start && !block) { Modified: llvm/trunk/lib/Transforms/Scalar/ADCE.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/ADCE.cpp?rev=44487&r1=44486&r2=44487&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/ADCE.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/ADCE.cpp Sat Dec 1 01:51:45 2007 @@ -198,8 +198,7 @@ for (BasicBlock::iterator II = BB->begin(), EI = BB->end(); II != EI; ) { Instruction *I = II++; if (CallInst *CI = dyn_cast<CallInst>(I)) { - Function *F = CI->getCalledFunction(); - if (F && AA.onlyReadsMemory(F)) { + if (AA.onlyReadsMemory(CI)) { if (CI->use_empty()) { BB->getInstList().erase(CI); ++NumCallRemoved; Modified: llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp?rev=44487&r1=44486&r2=44487&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp Sat Dec 1 01:51:45 2007 @@ -306,8 +306,7 @@ // 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; Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/GVN.cpp?rev=44487&r1=44486&r2=44487&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/GVN.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/GVN.cpp Sat Dec 1 01:51:45 2007 @@ -341,8 +341,7 @@ uint32_t ValueTable::hash_operand(Value* v) { if (CallInst* CI = dyn_cast<CallInst>(v)) - if (CI->getCalledFunction() && - !AA->doesNotAccessMemory(CI->getCalledFunction())) + if (!AA->doesNotAccessMemory(CI)) return nextValueNumber++; return lookup_or_add(v); @@ -485,9 +484,7 @@ return VI->second; if (CallInst* C = dyn_cast<CallInst>(V)) { - if (C->getCalledFunction() && - (AA->doesNotAccessMemory(C->getCalledFunction()) || - AA->onlyReadsMemory(C->getCalledFunction()))) { + if (AA->onlyReadsMemory(C)) { // includes doesNotAccessMemory Expression e = create_expression(C); DenseMap<Expression, uint32_t>::iterator EI = expressionNumbering.find(e); @@ -1051,8 +1048,7 @@ if (CallInst* CI = dyn_cast<CallInst>(I)) { AliasAnalysis& AA = getAnalysis<AliasAnalysis>(); - if (CI->getCalledFunction() && - !AA.doesNotAccessMemory(CI->getCalledFunction())) { + if (!AA.doesNotAccessMemory(CI)) { MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>(); if (cast<Instruction>(repl)->getParent() != CI->getParent() || MD.getDependency(CI) != MD.getDependency(cast<CallInst>(repl))) { Modified: llvm/trunk/lib/Transforms/Scalar/LICM.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LICM.cpp?rev=44487&r1=44486&r2=44487&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/LICM.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/LICM.cpp Sat Dec 1 01:51:45 2007 @@ -375,24 +375,22 @@ return !pointerInvalidatedByLoop(LI->getOperand(0), Size); } else if (CallInst *CI = dyn_cast<CallInst>(&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 _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits