diff options
| -rw-r--r-- | llvm/include/llvm/Analysis/CFLAliasAnalysis.h | 10 | ||||
| -rw-r--r-- | llvm/lib/Analysis/CFLAliasAnalysis.cpp | 71 | ||||
| -rw-r--r-- | llvm/test/Analysis/CFLAliasAnalysis/interproc-ret-arg.ll | 2 |
3 files changed, 83 insertions, 0 deletions
diff --git a/llvm/include/llvm/Analysis/CFLAliasAnalysis.h b/llvm/include/llvm/Analysis/CFLAliasAnalysis.h index 17290c8c78e..02cc8fbfe7f 100644 --- a/llvm/include/llvm/Analysis/CFLAliasAnalysis.h +++ b/llvm/include/llvm/Analysis/CFLAliasAnalysis.h @@ -73,6 +73,16 @@ public: return QueryResult; } + /// Get the location associated with a pointer argument of a callsite. + ModRefInfo getArgModRefInfo(ImmutableCallSite CS, unsigned ArgIdx); + + /// Returns the behavior when calling the given call site. + FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS); + + /// Returns the behavior when calling the given function. For use when the + /// call site is not known. + FunctionModRefBehavior getModRefBehavior(const Function *F); + private: struct FunctionHandle final : public CallbackVH { FunctionHandle(Function *Fn, CFLAAResult *Result) diff --git a/llvm/lib/Analysis/CFLAliasAnalysis.cpp b/llvm/lib/Analysis/CFLAliasAnalysis.cpp index e2ace96edf7..b480fc01340 100644 --- a/llvm/lib/Analysis/CFLAliasAnalysis.cpp +++ b/llvm/lib/Analysis/CFLAliasAnalysis.cpp @@ -1047,6 +1047,77 @@ AliasResult CFLAAResult::query(const MemoryLocation &LocA, return NoAlias; } +ModRefInfo CFLAAResult::getArgModRefInfo(ImmutableCallSite CS, + unsigned ArgIdx) { + if (auto CalledFunc = CS.getCalledFunction()) { + auto &MaybeInfo = ensureCached(const_cast<Function *>(CalledFunc)); + if (!MaybeInfo.hasValue()) + return MRI_ModRef; + auto &RetParamAttributes = MaybeInfo->getRetParamAttributes(); + auto &RetParamRelations = MaybeInfo->getRetParamRelations(); + + bool ArgAttributeIsWritten = + std::any_of(RetParamAttributes.begin(), RetParamAttributes.end(), + [ArgIdx](const ExternalAttribute &ExtAttr) { + return ExtAttr.IValue.Index == ArgIdx + 1; + }); + bool ArgIsAccessed = + std::any_of(RetParamRelations.begin(), RetParamRelations.end(), + [ArgIdx](const ExternalRelation &ExtRelation) { + return ExtRelation.To.Index == ArgIdx + 1 || + ExtRelation.From.Index == ArgIdx + 1; + }); + + return (!ArgIsAccessed && !ArgAttributeIsWritten) ? MRI_NoModRef + : MRI_ModRef; + } + + return MRI_ModRef; +} + +FunctionModRefBehavior CFLAAResult::getModRefBehavior(ImmutableCallSite CS) { + // If we know the callee, try analyzing it + if (auto CalledFunc = CS.getCalledFunction()) + return getModRefBehavior(CalledFunc); + + // Otherwise, be conservative + return FMRB_UnknownModRefBehavior; +} + +FunctionModRefBehavior CFLAAResult::getModRefBehavior(const Function *F) { + assert(F != nullptr); + + // TODO: Remove the const_cast + auto &MaybeInfo = ensureCached(const_cast<Function *>(F)); + if (!MaybeInfo.hasValue()) + return FMRB_UnknownModRefBehavior; + auto &RetParamAttributes = MaybeInfo->getRetParamAttributes(); + auto &RetParamRelations = MaybeInfo->getRetParamRelations(); + + // First, if any argument is marked Escpaed, Unknown or Global, anything may + // happen to them and thus we can't draw any conclusion. + if (!RetParamAttributes.empty()) + return FMRB_UnknownModRefBehavior; + + // Currently we don't (and can't) distinguish reads from writes in + // RetParamRelations. All we can say is whether there may be memory access or + // not. + if (RetParamRelations.empty()) + return FMRB_DoesNotAccessMemory; + + // Check if something beyond argmem gets touched. + bool AccessArgMemoryOnly = + std::all_of(RetParamRelations.begin(), RetParamRelations.end(), + [](const ExternalRelation &ExtRelation) { + // Both DerefLevels has to be 0, since we don't know which + // one is a read and which is a write. + return ExtRelation.From.DerefLevel == 0 && + ExtRelation.To.DerefLevel == 0; + }); + return AccessArgMemoryOnly ? FMRB_OnlyAccessesArgumentPointees + : FMRB_UnknownModRefBehavior; +} + char CFLAA::PassID; CFLAAResult CFLAA::run(Function &F, AnalysisManager<Function> &AM) { diff --git a/llvm/test/Analysis/CFLAliasAnalysis/interproc-ret-arg.ll b/llvm/test/Analysis/CFLAliasAnalysis/interproc-ret-arg.ll index 46d213b0e99..af6d8c0c90a 100644 --- a/llvm/test/Analysis/CFLAliasAnalysis/interproc-ret-arg.ll +++ b/llvm/test/Analysis/CFLAliasAnalysis/interproc-ret-arg.ll @@ -11,6 +11,8 @@ define i32* @return_arg_callee(i32* %arg1, i32* %arg2) { ; CHECK: NoAlias: i32* %a, i32* %b ; CHECK: MayAlias: i32* %a, i32* %c ; CHECK: NoAlias: i32* %b, i32* %c + +; CHECK: NoModRef: Ptr: i32* %b <-> %c = call i32* @return_arg_callee(i32* %a, i32* %b) define void @test_return_arg() { %a = alloca i32, align 4 %b = alloca i32, align 4 |

