[llvm] r296617 - [BasicAA] Take attributes into account when requesting modref info for a call site

Igor Laevsky via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 1 05:19:52 PST 2017


Author: igor.laevsky
Date: Wed Mar  1 07:19:51 2017
New Revision: 296617

URL: http://llvm.org/viewvc/llvm-project?rev=296617&view=rev
Log:
[BasicAA] Take attributes into account when requesting modref info for a call site

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


Added:
    llvm/trunk/test/Analysis/BasicAA/call-attrs.ll
Modified:
    llvm/trunk/include/llvm/IR/CallSite.h
    llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp
    llvm/trunk/test/Transforms/NewGVN/readattrs.ll

Modified: llvm/trunk/include/llvm/IR/CallSite.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/CallSite.h?rev=296617&r1=296616&r2=296617&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/CallSite.h (original)
+++ llvm/trunk/include/llvm/IR/CallSite.h Wed Mar  1 07:19:51 2017
@@ -583,6 +583,11 @@ public:
            dataOperandHasImpliedAttr(OpNo + 1, Attribute::ReadNone);
   }
 
+  bool doesNotReadMemory(unsigned OpNo) const {
+    return dataOperandHasImpliedAttr(OpNo + 1, Attribute::WriteOnly) ||
+           dataOperandHasImpliedAttr(OpNo + 1, Attribute::ReadNone);
+  }
+
   /// Return true if the return value is known to be not null.
   /// This may be because it has the nonnull attribute, or because at least
   /// one byte is dereferenceable and the pointer is in addrspace(0).

Modified: llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp?rev=296617&r1=296616&r2=296617&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp (original)
+++ llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp Wed Mar  1 07:19:51 2017
@@ -749,7 +749,11 @@ ModRefInfo BasicAAResult::getModRefInfo(
   // as an argument, and itself doesn't capture it.
   if (!isa<Constant>(Object) && CS.getInstruction() != Object &&
       isNonEscapingLocalObject(Object)) {
-    bool PassedAsArg = false;
+
+    // Optimistically assume that call doesn't touch Object and check this
+    // assumption in the following loop.
+    ModRefInfo Result = MRI_NoModRef;
+
     unsigned OperandNo = 0;
     for (auto CI = CS.data_operands_begin(), CE = CS.data_operands_end();
          CI != CE; ++CI, ++OperandNo) {
@@ -761,20 +765,38 @@ ModRefInfo BasicAAResult::getModRefInfo(
            OperandNo < CS.getNumArgOperands() && !CS.isByValArgument(OperandNo)))
         continue;
 
+      // Call doesn't access memory through this operand, so we don't care
+      // if it aliases with Object.
+      if (CS.doesNotAccessMemory(OperandNo))
+        continue;
+
       // If this is a no-capture pointer argument, see if we can tell that it
-      // is impossible to alias the pointer we're checking.  If not, we have to
-      // assume that the call could touch the pointer, even though it doesn't
-      // escape.
+      // is impossible to alias the pointer we're checking.
       AliasResult AR =
           getBestAAResults().alias(MemoryLocation(*CI), MemoryLocation(Object));
-      if (AR) {
-        PassedAsArg = true;
-        break;
+
+      // Operand doesnt alias 'Object', continue looking for other aliases
+      if (AR == NoAlias)
+        continue;
+      // Operand aliases 'Object', but call doesn't modify it. Strengthen
+      // initial assumption and keep looking in case if there are more aliases.
+      if (CS.onlyReadsMemory(OperandNo)) {
+        Result = static_cast<ModRefInfo>(Result | MRI_Ref);
+        continue;
+      }
+      // Operand aliases 'Object' but call only writes into it.
+      if (CS.doesNotReadMemory(OperandNo)) {
+        Result = static_cast<ModRefInfo>(Result | MRI_Mod);
+        continue;
       }
+      // This operand aliases 'Object' and call reads and writes into it.
+      Result = MRI_ModRef;
+      break;
     }
 
-    if (!PassedAsArg)
-      return MRI_NoModRef;
+    // Early return if we improved mod ref information
+    if (Result != MRI_ModRef)
+      return Result;
   }
 
   // If the CallSite is to malloc or calloc, we can assume that it doesn't

Added: llvm/trunk/test/Analysis/BasicAA/call-attrs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/BasicAA/call-attrs.ll?rev=296617&view=auto
==============================================================================
--- llvm/trunk/test/Analysis/BasicAA/call-attrs.ll (added)
+++ llvm/trunk/test/Analysis/BasicAA/call-attrs.ll Wed Mar  1 07:19:51 2017
@@ -0,0 +1,42 @@
+; RUN: opt < %s -basicaa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
+
+declare void @readonly_attr(i8* readonly nocapture)
+declare void @writeonly_attr(i8* writeonly nocapture)
+declare void @readnone_attr(i8* readnone nocapture)
+
+declare void @readonly_func(i8* nocapture) readonly
+declare void @writeonly_func(i8* nocapture) writeonly
+declare void @readnone_func(i8* nocapture) readnone
+
+declare void @read_write(i8* writeonly nocapture, i8* readonly nocapture, i8* readnone nocapture)
+
+declare void @func()
+
+define void @test(i8* noalias %p) {
+entry:
+  call void @readonly_attr(i8* %p)
+  call void @readonly_func(i8* %p)
+
+  call void @writeonly_attr(i8* %p)
+  call void @writeonly_func(i8* %p)
+
+  call void @readnone_attr(i8* %p)
+  call void @readnone_func(i8* %p)
+
+  call void @read_write(i8* %p, i8* %p, i8* %p)
+
+  call void @func() ["deopt" (i8* %p)]
+  call void @writeonly_attr(i8* %p) ["deopt" (i8* %p)]
+
+  ret void
+}
+
+; CHECK:  Just Ref:  Ptr: i8* %p	<->  call void @readonly_attr(i8* %p)
+; CHECK:  Just Ref:  Ptr: i8* %p	<->  call void @readonly_func(i8* %p)
+; CHECK:  Just Mod:  Ptr: i8* %p	<->  call void @writeonly_attr(i8* %p)
+; CHECK:  Just Mod:  Ptr: i8* %p	<->  call void @writeonly_func(i8* %p)
+; CHECK:  NoModRef:  Ptr: i8* %p	<->  call void @readnone_attr(i8* %p)
+; CHECK:  NoModRef:  Ptr: i8* %p	<->  call void @readnone_func(i8* %p)
+; CHECK:  Both ModRef:  Ptr: i8* %p	<->  call void @read_write(i8* %p, i8* %p, i8* %p)
+; CHECK:  Just Ref:  Ptr: i8* %p	<->  call void @func() [ "deopt"(i8* %p) ]
+; CHECK:  Both ModRef:  Ptr: i8* %p	<->  call void @writeonly_attr(i8* %p) [ "deopt"(i8* %p) ]

Modified: llvm/trunk/test/Transforms/NewGVN/readattrs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/NewGVN/readattrs.ll?rev=296617&r1=296616&r2=296617&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/NewGVN/readattrs.ll (original)
+++ llvm/trunk/test/Transforms/NewGVN/readattrs.ll Wed Mar  1 07:19:51 2017
@@ -1,4 +1,3 @@
-; XFAIL: *
 ; RUN: opt -newgvn -S -o - < %s | FileCheck %s
 
 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"




More information about the llvm-commits mailing list