diff --git a/include/llvm/Analysis/AliasAnalysis.h b/include/llvm/Analysis/AliasAnalysis.h index 1b38baf48c5..c938e887940 100644 --- a/include/llvm/Analysis/AliasAnalysis.h +++ b/include/llvm/Analysis/AliasAnalysis.h @@ -187,12 +187,12 @@ public: }; /// getModRefBehavior - Return the behavior when calling the given call site. - ModRefBehavior getModRefBehavior(CallSite CS, + virtual ModRefBehavior getModRefBehavior(CallSite CS, std::vector *Info = 0); /// getModRefBehavior - Return the behavior when calling the given function. /// For use when the call site is not known. - ModRefBehavior getModRefBehavior(Function *F, + virtual ModRefBehavior getModRefBehavior(Function *F, std::vector *Info = 0); /// doesNotAccessMemory - If the specified call is known to never read or @@ -267,13 +267,6 @@ 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); diff --git a/lib/Analysis/AliasAnalysis.cpp b/lib/Analysis/AliasAnalysis.cpp index 3e46fccc58d..3d1b20bba7a 100644 --- a/lib/Analysis/AliasAnalysis.cpp +++ b/lib/Analysis/AliasAnalysis.cpp @@ -59,13 +59,6 @@ bool AliasAnalysis::pointsToConstantMemory(const Value *P) { return AA->pointsToConstantMemory(P); } -AliasAnalysis::ModRefBehavior -AliasAnalysis::getModRefBehavior(Function *F, CallSite CS, - std::vector *Info) { - assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!"); - return AA->getModRefBehavior(F, CS, Info); -} - bool AliasAnalysis::hasNoModRefInfoForCalls() const { assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!"); return AA->hasNoModRefInfoForCalls(); @@ -115,33 +108,10 @@ AliasAnalysis::getModRefInfo(StoreInst *S, Value *P, unsigned Size) { AliasAnalysis::ModRefBehavior AliasAnalysis::getModRefBehavior(CallSite CS, std::vector *Info) { - if (IntrinsicInst* II = dyn_cast(CS.getInstruction())) { - switch (II->getIntrinsicID()) { - case Intrinsic::atomic_cmp_swap: - case Intrinsic::atomic_load_add: - case Intrinsic::atomic_load_and: - case Intrinsic::atomic_load_max: - case Intrinsic::atomic_load_min: - case Intrinsic::atomic_load_nand: - case Intrinsic::atomic_load_or: - case Intrinsic::atomic_load_sub: - case Intrinsic::atomic_load_umax: - case Intrinsic::atomic_load_umin: - case Intrinsic::atomic_load_xor: - case Intrinsic::atomic_swap: - // CAS and related intrinsics only access their arguments. - return AliasAnalysis::AccessesArguments; - default: - break; - } - } - if (CS.doesNotAccessMemory()) // Can't do better than this. return DoesNotAccessMemory; - ModRefBehavior MRB = UnknownModRefBehavior; - if (Function *F = CS.getCalledFunction()) - MRB = getModRefBehavior(F, CS, Info); + ModRefBehavior MRB = getModRefBehavior(CS.getCalledFunction(), Info); if (MRB != DoesNotAccessMemory && CS.onlyReadsMemory()) return OnlyReadsMemory; return MRB; @@ -150,34 +120,10 @@ AliasAnalysis::getModRefBehavior(CallSite CS, AliasAnalysis::ModRefBehavior AliasAnalysis::getModRefBehavior(Function *F, std::vector *Info) { - if (F->isIntrinsic()) { - switch (F->getIntrinsicID()) { - case Intrinsic::atomic_cmp_swap: - case Intrinsic::atomic_load_add: - case Intrinsic::atomic_load_and: - case Intrinsic::atomic_load_max: - case Intrinsic::atomic_load_min: - case Intrinsic::atomic_load_nand: - case Intrinsic::atomic_load_or: - case Intrinsic::atomic_load_sub: - case Intrinsic::atomic_load_umax: - case Intrinsic::atomic_load_umin: - case Intrinsic::atomic_load_xor: - case Intrinsic::atomic_swap: - // CAS and related intrinsics only access their arguments. - return AliasAnalysis::AccessesArguments; - default: - break; - } - } - if (F->doesNotAccessMemory()) // Can't do better than this. return DoesNotAccessMemory; - ModRefBehavior MRB = getModRefBehavior(F, CallSite(), Info); - if (MRB != DoesNotAccessMemory && F->onlyReadsMemory()) - return OnlyReadsMemory; - return MRB; + return UnknownModRefBehavior; } AliasAnalysis::ModRefResult @@ -188,6 +134,18 @@ AliasAnalysis::getModRefInfo(CallSite CS, Value *P, unsigned Size) { Mask = Ref; else if (MRB == DoesNotAccessMemory) return NoModRef; + else if (MRB == AliasAnalysis::AccessesArguments) { + bool doesAlias = false; + for (CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end(); + AI != AE; ++AI) + if (alias(*AI, ~0U, P, Size) != NoAlias) { + doesAlias = true; + break; + } + + if (!doesAlias) + return NoModRef; + } if (!AA) return Mask; diff --git a/lib/Analysis/AliasDebugger.cpp b/lib/Analysis/AliasDebugger.cpp index 0bbd739351f..1e82621e020 100644 --- a/lib/Analysis/AliasDebugger.cpp +++ b/lib/Analysis/AliasDebugger.cpp @@ -102,15 +102,6 @@ namespace { return AliasAnalysis::pointsToConstantMemory(P); } - /// 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) { - assert(Vals.find(F) != Vals.end() && "Never seen value in AA before"); - return AliasAnalysis::getModRefBehavior(F, CS, Info); - } - virtual void deleteValue(Value *V) { assert(Vals.find(V) != Vals.end() && "Never seen value in AA before"); AliasAnalysis::deleteValue(V); diff --git a/lib/Analysis/BasicAliasAnalysis.cpp b/lib/Analysis/BasicAliasAnalysis.cpp index 317e9d9e2e7..1b26dc421ce 100644 --- a/lib/Analysis/BasicAliasAnalysis.cpp +++ b/lib/Analysis/BasicAliasAnalysis.cpp @@ -155,11 +155,6 @@ namespace { return MayAlias; } - virtual ModRefBehavior getModRefBehavior(Function *F, CallSite CS, - std::vector *Info) { - return UnknownModRefBehavior; - } - virtual void getArgumentAccesses(Function *F, CallSite CS, std::vector &Info) { assert(0 && "This method may not be called on this function!"); @@ -207,6 +202,12 @@ namespace { ModRefResult getModRefInfo(CallSite CS, Value *P, unsigned Size); ModRefResult getModRefInfo(CallSite CS1, CallSite CS2); + virtual ModRefBehavior getModRefBehavior(CallSite CS, + std::vector *Info = 0); + + virtual ModRefBehavior getModRefBehavior(Function *F, + std::vector *Info = 0); + /// hasNoModRefInfoForCalls - We can provide mod/ref information against /// non-escaping allocations. virtual bool hasNoModRefInfoForCalls() const { return false; } @@ -249,6 +250,52 @@ bool BasicAliasAnalysis::pointsToConstantMemory(const Value *P) { return false; } + +static bool isAtomicRMW(Function* F) { + if (!F) return false; + if (F->isIntrinsic()) { + switch (F->getIntrinsicID()) { + case Intrinsic::atomic_cmp_swap: + case Intrinsic::atomic_load_add: + case Intrinsic::atomic_load_and: + case Intrinsic::atomic_load_max: + case Intrinsic::atomic_load_min: + case Intrinsic::atomic_load_nand: + case Intrinsic::atomic_load_or: + case Intrinsic::atomic_load_sub: + case Intrinsic::atomic_load_umax: + case Intrinsic::atomic_load_umin: + case Intrinsic::atomic_load_xor: + case Intrinsic::atomic_swap: + return true; + default: + return false; + } + } + + return false; +} + +AliasAnalysis::ModRefBehavior +BasicAliasAnalysis::getModRefBehavior(CallSite CS, + std::vector *Info) { + if (isAtomicRMW(CS.getCalledFunction())) + // CAS and related intrinsics only access their arguments. + return AliasAnalysis::AccessesArguments; + + return AliasAnalysis::getModRefBehavior(CS, Info); +} + +AliasAnalysis::ModRefBehavior +BasicAliasAnalysis::getModRefBehavior(Function *F, + std::vector *Info) { + if (isAtomicRMW(F)) + // CAS and related intrinsics only access their arguments. + return AliasAnalysis::AccessesArguments; + + return AliasAnalysis::getModRefBehavior(F, Info); +} + // getModRefInfo - Check to see if the specified callsite can clobber the // specified memory object. Since we only look at local properties of this // function, we really can't say much about this query. We do, however, use @@ -256,22 +303,6 @@ bool BasicAliasAnalysis::pointsToConstantMemory(const Value *P) { // AliasAnalysis::ModRefResult BasicAliasAnalysis::getModRefInfo(CallSite CS, Value *P, unsigned Size) { - // If the function only accesses its arguments, it suffices to check that - // P does not alias any of those arguments. - if (AliasAnalysis::getModRefBehavior(CS, 0) == - AliasAnalysis::AccessesArguments) { - bool doesAlias = false; - for (CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end(); - AI != AE; ++AI) - if (alias(*AI, ~0U, P, Size) != NoAlias) { - doesAlias = true; - break; - } - - if (!doesAlias) - return NoModRef; - } - if (!isa(P)) { const Value *Object = P->getUnderlyingObject(); diff --git a/lib/Analysis/IPA/GlobalsModRef.cpp b/lib/Analysis/IPA/GlobalsModRef.cpp index a795ca675fe..2e9884aa01b 100644 --- a/lib/Analysis/IPA/GlobalsModRef.cpp +++ b/lib/Analysis/IPA/GlobalsModRef.cpp @@ -117,7 +117,7 @@ namespace { /// 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, + ModRefBehavior getModRefBehavior(Function *F, std::vector *Info) { if (FunctionRecord *FR = getFunctionInfo(F)) { if (FR->FunctionEffect == 0) @@ -125,7 +125,23 @@ namespace { else if ((FR->FunctionEffect & Mod) == 0) return OnlyReadsMemory; } - return AliasAnalysis::getModRefBehavior(F, CS, Info); + return AliasAnalysis::getModRefBehavior(F, Info); + } + + /// 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. + ModRefBehavior getModRefBehavior(CallSite CS, + std::vector *Info) { + Function* F = CS.getCalledFunction(); + if (!F) return AliasAnalysis::getModRefBehavior(CS, Info); + if (FunctionRecord *FR = getFunctionInfo(F)) { + if (FR->FunctionEffect == 0) + return DoesNotAccessMemory; + else if ((FR->FunctionEffect & Mod) == 0) + return OnlyReadsMemory; + } + return AliasAnalysis::getModRefBehavior(CS, Info); } virtual void deleteValue(Value *V);