summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeorge Burgess IV <george.burgess.iv@gmail.com>2016-06-30 02:11:26 +0000
committerGeorge Burgess IV <george.burgess.iv@gmail.com>2016-06-30 02:11:26 +0000
commitd86e38e1dbe318f5efed215ccf4ef22965591bf2 (patch)
treed2a3a7d6d5038dd9c44b6efb589d5b7c48a86cc6
parent48e7cbdf41d7f54c2e75b2c1d16b5b75af4f6e69 (diff)
downloadbcm5719-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.h10
-rw-r--r--llvm/lib/Analysis/CFLAliasAnalysis.cpp71
-rw-r--r--llvm/test/Analysis/CFLAliasAnalysis/interproc-ret-arg.ll2
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
OpenPOWER on IntegriCloud