[llvm] r276939 - [CFLAA] Add getModRefBehavior to CFLAnders.

George Burgess IV via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 27 16:07:08 PDT 2016


Author: gbiv
Date: Wed Jul 27 18:07:07 2016
New Revision: 276939

URL: http://llvm.org/viewvc/llvm-project?rev=276939&view=rev
Log:
[CFLAA] Add getModRefBehavior to CFLAnders.

This patch lets CFLAnders respond to mod-ref queries. It also includes
a small bugfix to CFLSteens.

Patch by Jia Chen.

Differential Revision: https://reviews.llvm.org/D22823

Modified:
    llvm/trunk/include/llvm/Analysis/CFLAndersAliasAnalysis.h
    llvm/trunk/lib/Analysis/CFLAndersAliasAnalysis.cpp
    llvm/trunk/lib/Analysis/CFLSteensAliasAnalysis.cpp
    llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/interproc-ret-arg.ll
    llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/interproc-ret-deref-arg-multilevel.ll
    llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/interproc-ret-deref-arg.ll
    llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/interproc-ret-ref-arg-multilevel.ll
    llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/interproc-ret-ref-arg.ll
    llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/interproc-store-arg.ll

Modified: llvm/trunk/include/llvm/Analysis/CFLAndersAliasAnalysis.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/CFLAndersAliasAnalysis.h?rev=276939&r1=276938&r2=276939&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/CFLAndersAliasAnalysis.h (original)
+++ llvm/trunk/include/llvm/Analysis/CFLAndersAliasAnalysis.h Wed Jul 27 18:07:07 2016
@@ -53,6 +53,16 @@ public:
   AliasResult query(const MemoryLocation &, const MemoryLocation &);
   AliasResult alias(const MemoryLocation &, const MemoryLocation &);
 
+  /// 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, CFLAndersAAResult *Result)

Modified: llvm/trunk/lib/Analysis/CFLAndersAliasAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CFLAndersAliasAnalysis.cpp?rev=276939&r1=276938&r2=276939&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/CFLAndersAliasAnalysis.cpp (original)
+++ llvm/trunk/lib/Analysis/CFLAndersAliasAnalysis.cpp Wed Jul 27 18:07:07 2016
@@ -859,6 +859,112 @@ AliasResult CFLAndersAAResult::alias(con
   return QueryResult;
 }
 
+ModRefInfo CFLAndersAAResult::getArgModRefInfo(ImmutableCallSite CS,
+                                               unsigned ArgIdx) {
+  if (auto CalledFunc = CS.getCalledFunction()) {
+    if (!CalledFunc->hasExactDefinition())
+      return MRI_ModRef;
+
+    auto &MaybeInfo = ensureCached(*CalledFunc);
+    if (!MaybeInfo.hasValue())
+      return MRI_ModRef;
+    auto &RetParamAttributes = MaybeInfo->getAliasSummary().RetParamAttributes;
+    auto &RetParamRelations = MaybeInfo->getAliasSummary().RetParamRelations;
+
+    bool ArgAttributeIsWritten =
+        any_of(RetParamAttributes, [ArgIdx](const ExternalAttribute &ExtAttr) {
+          return ExtAttr.IValue.Index == ArgIdx + 1;
+        });
+
+    // If the argument is unknown, escaped, or alias global, be conservative.
+    // FIXME: Do we really need to be conservative for AttrGlobal?
+    if (ArgAttributeIsWritten)
+      return MRI_ModRef;
+
+    bool ArgIsRead = any_of(RetParamRelations,
+                            [ArgIdx](const ExternalRelation &ExtRelation) {
+                              return ExtRelation.From.Index == ArgIdx + 1;
+                            });
+
+    bool ArgIsWritten = any_of(RetParamRelations,
+                               [ArgIdx](const ExternalRelation &ExtRelation) {
+                                 return ExtRelation.To.Index == ArgIdx + 1;
+                               });
+
+    if (ArgIsRead)
+      return ArgIsWritten ? MRI_ModRef : MRI_Ref;
+    return ArgIsWritten ? MRI_Mod : MRI_NoModRef;
+  }
+
+  return MRI_ModRef;
+}
+
+FunctionModRefBehavior
+CFLAndersAAResult::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 CFLAndersAAResult::getModRefBehavior(const Function *F) {
+  assert(F != nullptr);
+
+  // We cannot process external functions
+  if (!F->hasExactDefinition())
+    return FMRB_UnknownModRefBehavior;
+
+  auto &MaybeInfo = ensureCached(*F);
+  if (!MaybeInfo.hasValue())
+    return FMRB_UnknownModRefBehavior;
+  auto &RetParamAttributes = MaybeInfo->getAliasSummary().RetParamAttributes;
+  auto &RetParamRelations = MaybeInfo->getAliasSummary().RetParamRelations;
+
+  // First, if any argument is marked Escpaed, Unknown or Global, anything may
+  // happen to them and thus we can't draw any conclusion.
+  // FIXME: Do we really need to be conservative for AttrGlobal?
+  if (!RetParamAttributes.empty())
+    return FMRB_UnknownModRefBehavior;
+
+  // Check if memory gets touched.
+  bool MemIsRead =
+      any_of(RetParamRelations, [](const ExternalRelation &ExtRelation) {
+        return ExtRelation.From.DerefLevel > 0;
+      });
+  bool MemIsWritten =
+      any_of(RetParamRelations, [](const ExternalRelation &ExtRelation) {
+        return ExtRelation.To.DerefLevel > 0;
+      });
+  if (!MemIsRead && !MemIsWritten)
+    return FMRB_DoesNotAccessMemory;
+
+  // Check if only argmem gets touched.
+  bool ArgMemIsAccessed =
+      all_of(RetParamRelations, [](const ExternalRelation &ExtRelation) {
+        return ExtRelation.From.Index > 0 && ExtRelation.From.DerefLevel <= 1 &&
+               ExtRelation.To.Index > 0 && ExtRelation.To.DerefLevel <= 1;
+      });
+  if (ArgMemIsAccessed)
+    return FMRB_OnlyAccessesArgumentPointees;
+
+  if (!MemIsWritten) {
+    // Check if something beyond argmem gets read.
+    bool ArgMemReadOnly =
+        all_of(RetParamRelations, [](const ExternalRelation &ExtRelation) {
+          return ExtRelation.From.Index > 0 && ExtRelation.From.DerefLevel <= 1;
+        });
+    return ArgMemReadOnly ? FMRB_OnlyReadsArgumentPointees
+                          : FMRB_OnlyReadsMemory;
+  }
+
+  if (!MemIsRead)
+    return FMRB_DoesNotReadMemory;
+
+  return FMRB_UnknownModRefBehavior;
+}
+
 char CFLAndersAA::PassID;
 
 CFLAndersAAResult CFLAndersAA::run(Function &F, AnalysisManager<Function> &AM) {

Modified: llvm/trunk/lib/Analysis/CFLSteensAliasAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CFLSteensAliasAnalysis.cpp?rev=276939&r1=276938&r2=276939&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/CFLSteensAliasAnalysis.cpp (original)
+++ llvm/trunk/lib/Analysis/CFLSteensAliasAnalysis.cpp Wed Jul 27 18:07:07 2016
@@ -344,6 +344,9 @@ AliasResult CFLSteensAAResult::query(con
 ModRefInfo CFLSteensAAResult::getArgModRefInfo(ImmutableCallSite CS,
                                                unsigned ArgIdx) {
   if (auto CalledFunc = CS.getCalledFunction()) {
+    if (!CalledFunc->hasExactDefinition())
+      return MRI_ModRef;
+
     auto &MaybeInfo = ensureCached(const_cast<Function *>(CalledFunc));
     if (!MaybeInfo.hasValue())
       return MRI_ModRef;
@@ -382,6 +385,10 @@ CFLSteensAAResult::getModRefBehavior(Imm
 FunctionModRefBehavior CFLSteensAAResult::getModRefBehavior(const Function *F) {
   assert(F != nullptr);
 
+  // We cannot process external functions
+  if (!F->hasExactDefinition())
+    return FMRB_UnknownModRefBehavior;
+
   // TODO: Remove the const_cast
   auto &MaybeInfo = ensureCached(const_cast<Function *>(F));
   if (!MaybeInfo.hasValue())
@@ -397,18 +404,21 @@ FunctionModRefBehavior CFLSteensAAResult
   // 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())
+  bool AccessNoMemory =
+      all_of(RetParamRelations, [](const ExternalRelation &ExtRelation) {
+        return ExtRelation.From.DerefLevel == 0 &&
+               ExtRelation.To.DerefLevel == 0;
+      });
+  if (AccessNoMemory)
     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;
-                  });
+      all_of(RetParamRelations, [](const ExternalRelation &ExtRelation) {
+        return ExtRelation.From.Index > 0 && ExtRelation.To.Index > 0 &&
+               ExtRelation.From.DerefLevel <= 1 &&
+               ExtRelation.To.DerefLevel <= 1;
+      });
   return AccessArgMemoryOnly ? FMRB_OnlyAccessesArgumentPointees
                              : FMRB_UnknownModRefBehavior;
 }

Modified: llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/interproc-ret-arg.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/interproc-ret-arg.ll?rev=276939&r1=276938&r2=276939&view=diff
==============================================================================
--- llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/interproc-ret-arg.ll (original)
+++ llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/interproc-ret-arg.ll Wed Jul 27 18:07:07 2016
@@ -11,6 +11,10 @@ define i32* @return_arg_callee(i32* %arg
 ; CHECK: NoAlias: i32* %a, i32* %b
 ; CHECK: MayAlias: i32* %a, i32* %c
 ; CHECK: NoAlias: i32* %b, i32* %c
+
+; CHECK: NoModRef: Ptr: i32* %a <-> %c = call i32* @return_arg_callee(i32* %a, i32* %b)
+; CHECK: NoModRef: Ptr: i32* %b <-> %c = call i32* @return_arg_callee(i32* %a, i32* %b)
+; CHECK: NoModRef: Ptr: i32* %c <-> %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

Modified: llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/interproc-ret-deref-arg-multilevel.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/interproc-ret-deref-arg-multilevel.ll?rev=276939&r1=276938&r2=276939&view=diff
==============================================================================
--- llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/interproc-ret-deref-arg-multilevel.ll (original)
+++ llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/interproc-ret-deref-arg-multilevel.ll Wed Jul 27 18:07:07 2016
@@ -28,6 +28,11 @@ define i32* @return_deref_arg_multilevel
 ; CHECK: MayAlias: i32* %c, i32* %lp
 ; CHECK: NoAlias: i32* %lp, i32** %lpp
 ; CHECK: MayAlias: i32* %lp, i32* %lpp_deref
+
+; CHECK: Just Ref: Ptr: i32** %p <-> %c = call i32* @return_deref_arg_multilevel_callee(i32*** %pp)
+; CHECK: Just Ref: Ptr: i32*** %pp <-> %c = call i32* @return_deref_arg_multilevel_callee(i32*** %pp)
+; CHECK: Just Ref: Ptr: i32** %lpp <-> %c = call i32* @return_deref_arg_multilevel_callee(i32*** %pp)
+
 define void @test_return_deref_arg_multilevel() {
   %a = alloca i32, align 4
   %b = alloca i32, align 4

Modified: llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/interproc-ret-deref-arg.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/interproc-ret-deref-arg.ll?rev=276939&r1=276938&r2=276939&view=diff
==============================================================================
--- llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/interproc-ret-deref-arg.ll (original)
+++ llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/interproc-ret-deref-arg.ll Wed Jul 27 18:07:07 2016
@@ -16,6 +16,12 @@ define i32* @return_deref_arg_callee(i32
 ; CHECK: NoAlias: i32* %b, i32* %lp
 ; CHECK: NoAlias: i32* %lp, i32** %p
 ; CHECK: MayAlias: i32* %c, i32* %lp
+
+; CHECK: NoModRef: Ptr: i32* %a <-> %c = call i32* @return_deref_arg_callee(i32** %p)
+; CHECK: NoModRef: Ptr: i32* %b <-> %c = call i32* @return_deref_arg_callee(i32** %p)
+; CHECK: Just Ref: Ptr: i32** %p <-> %c = call i32* @return_deref_arg_callee(i32** %p)
+; CHECK: NoModRef: Ptr: i32* %c <-> %c = call i32* @return_deref_arg_callee(i32** %p)
+; CHECK: NoModRef: Ptr: i32* %lp <-> %c = call i32* @return_deref_arg_callee(i32** %p)
 define void @test_return_deref_arg() {
   %a = alloca i32, align 4
   %b = alloca i32, align 4

Modified: llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/interproc-ret-ref-arg-multilevel.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/interproc-ret-ref-arg-multilevel.ll?rev=276939&r1=276938&r2=276939&view=diff
==============================================================================
--- llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/interproc-ret-ref-arg-multilevel.ll (original)
+++ llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/interproc-ret-ref-arg-multilevel.ll Wed Jul 27 18:07:07 2016
@@ -30,6 +30,9 @@ define i32*** @return_ref_arg_multilevel
 ; CHECK: MayAlias: i32* %lb_deref, i32* %lp
 ; CHECK: NoAlias: i32* %lp, i32** %lpp
 ; CHECK: MayAlias: i32* %lp, i32* %lpp_deref
+
+; CHECK: Just Mod: Ptr: i32*** %b <-> %b = call i32*** @return_ref_arg_multilevel_callee(i32* %a)
+; CHECK: Just Mod: Ptr: i32** %lb <-> %b = call i32*** @return_ref_arg_multilevel_callee(i32* %a)
 define void @test_return_ref_arg_multilevel() {
   %a = alloca i32, align 4
   %p = alloca i32*, align 8

Modified: llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/interproc-ret-ref-arg.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/interproc-ret-ref-arg.ll?rev=276939&r1=276938&r2=276939&view=diff
==============================================================================
--- llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/interproc-ret-ref-arg.ll (original)
+++ llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/interproc-ret-ref-arg.ll Wed Jul 27 18:07:07 2016
@@ -20,6 +20,8 @@ define i32** @return_ref_arg_callee(i32*
 ; CHECK: NoAlias: i32* %lp, i32** %p
 ; CHECK: NoAlias: i32* %lp, i32** %b
 ; CHECK: MayAlias: i32* %lb, i32* %lp
+
+; CHECK: Just Mod: Ptr: i32** %b <-> %b = call i32** @return_ref_arg_callee(i32* %a)
 define void @test_return_ref_arg() {
   %a = alloca i32, align 4
   %p = alloca i32*, align 8

Modified: llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/interproc-store-arg.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/interproc-store-arg.ll?rev=276939&r1=276938&r2=276939&view=diff
==============================================================================
--- llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/interproc-store-arg.ll (original)
+++ llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/interproc-store-arg.ll Wed Jul 27 18:07:07 2016
@@ -17,6 +17,11 @@ define void @store_arg_callee(i32** %arg
 ; CHECK: NoAlias: i32* %a, i32* %lq
 ; CHECK: MayAlias: i32* %b, i32* %lq
 ; CHECK: MayAlias: i32* %lp, i32* %lq
+
+; CHECK: NoModRef: Ptr: i32* %a <-> call void @store_arg_callee(i32** %p, i32* %b)
+; CHECK: Just Ref: Ptr: i32* %b <-> call void @store_arg_callee(i32** %p, i32* %b)
+; CHECK: Just Mod: Ptr: i32** %p  <-> call void @store_arg_callee(i32** %p, i32* %b)
+; CHECK: NoModRef: Ptr: i32** %q  <-> call void @store_arg_callee(i32** %p, i32* %b)
 define void @test_store_arg() {
   %a = alloca i32, align 4
   %b = alloca i32, align 4




More information about the llvm-commits mailing list