diff options
author | George Burgess IV <george.burgess.iv@gmail.com> | 2016-06-30 02:11:26 +0000 |
---|---|---|
committer | George Burgess IV <george.burgess.iv@gmail.com> | 2016-06-30 02:11:26 +0000 |
commit | d86e38e1dbe318f5efed215ccf4ef22965591bf2 (patch) | |
tree | d2a3a7d6d5038dd9c44b6efb589d5b7c48a86cc6 | |
parent | 48e7cbdf41d7f54c2e75b2c1d16b5b75af4f6e69 (diff) | |
download | bcm5719-llvm-d86e38e1dbe318f5efed215ccf4ef22965591bf2.tar.gz bcm5719-llvm-d86e38e1dbe318f5efed215ccf4ef22965591bf2.zip |
[CFLAA] Add support for ModRef queries.
This patch makes CFLAA answer some ModRef queries. Because we don't
distinguish between reading/writing when making StratifiedSets, we're
unable to offer any of the readonly-related answers.
Patch by Jia Chen.
Differential Revision: http://reviews.llvm.org/D21858
llvm-svn: 274197
-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 |