[llvm] 6aa672f - [IR] Take operand bundles into account for call argument readonly/writeonly

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 1 01:38:27 PDT 2022


Author: Nikita Popov
Date: 2022-11-01T09:30:03+01:00
New Revision: 6aa672f14197e84520671de4ce3fcc724bbfe8d9

URL: https://github.com/llvm/llvm-project/commit/6aa672f14197e84520671de4ce3fcc724bbfe8d9
DIFF: https://github.com/llvm/llvm-project/commit/6aa672f14197e84520671de4ce3fcc724bbfe8d9.diff

LOG: [IR] Take operand bundles into account for call argument readonly/writeonly

We currently only take operand bundle effects into account when
querying the function-level memory attributes. However, I believe
that we also need to do the same for parameter attributes. For
example, a call with deopt bundle to a function with readnone
parameter attribute cannot treat that parameter as readnone,
because the deopt bundle may read it.

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

Added: 
    

Modified: 
    llvm/lib/IR/Instructions.cpp
    llvm/test/Analysis/BasicAA/deoptimize.ll
    llvm/test/Transforms/FunctionAttrs/readattrs.ll
    llvm/test/Transforms/FunctionAttrs/writeonly.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
index f3bcd5322f6a5..8682a938d78c4 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -344,9 +344,25 @@ bool CallBase::paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const {
 
   if (Attrs.hasParamAttr(ArgNo, Kind))
     return true;
-  if (const Function *F = getCalledFunction())
-    return F->getAttributes().hasParamAttr(ArgNo, Kind);
-  return false;
+
+  const Function *F = getCalledFunction();
+  if (!F)
+    return false;
+
+  if (!F->getAttributes().hasParamAttr(ArgNo, Kind))
+    return false;
+
+  // Take into account mod/ref by operand bundles.
+  switch (Kind) {
+  case Attribute::ReadNone:
+    return !hasReadingOperandBundles() && !hasClobberingOperandBundles();
+  case Attribute::ReadOnly:
+    return !hasClobberingOperandBundles();
+  case Attribute::WriteOnly:
+    return !hasReadingOperandBundles();
+  default:
+    return true;
+  }
 }
 
 bool CallBase::hasFnAttrOnCalledFunction(Attribute::AttrKind Kind) const {

diff  --git a/llvm/test/Analysis/BasicAA/deoptimize.ll b/llvm/test/Analysis/BasicAA/deoptimize.ll
index b8f9f970627b1..6836cc4621e4e 100644
--- a/llvm/test/Analysis/BasicAA/deoptimize.ll
+++ b/llvm/test/Analysis/BasicAA/deoptimize.ll
@@ -21,7 +21,7 @@ define void @test1(i8* %p) {
 ; Check that global G1 is reported as Ref by memcpy/memmove calls.
 define i32 @test_memcpy_with_deopt() {
 ; CHECK-LABEL: Function: test_memcpy_with_deopt:
-; CHECK: Just Mod:  Ptr: i8* %A	<->  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %A, i8* %B, i64 -1, i1 false) [ "deopt"() ]
+; CHECK: Both ModRef:  Ptr: i8* %A	<->  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %A, i8* %B, i64 -1, i1 false) [ "deopt"() ]
 ; CHECK: Just Ref:  Ptr: i8* %B	<->  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %A, i8* %B, i64 -1, i1 false) [ "deopt"() ]
 ; CHECK: Just Ref:  Ptr: i32* @G1	<->  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %A, i8* %B, i64 -1, i1 false) [ "deopt"() ]
 
@@ -40,7 +40,7 @@ define i32 @test_memcpy_with_deopt() {
 
 define i32 @test_memmove_with_deopt() {
 ; CHECK-LABEL: Function: test_memmove_with_deopt:
-; CHECK: Just Mod:  Ptr: i8* %A	<->  call void @llvm.memmove.p0i8.p0i8.i64(i8* %A, i8* %B, i64 -1, i1 false) [ "deopt"() ]
+; CHECK: Both ModRef:  Ptr: i8* %A	<->  call void @llvm.memmove.p0i8.p0i8.i64(i8* %A, i8* %B, i64 -1, i1 false) [ "deopt"() ]
 ; CHECK: Just Ref:  Ptr: i8* %B	<->  call void @llvm.memmove.p0i8.p0i8.i64(i8* %A, i8* %B, i64 -1, i1 false) [ "deopt"() ]
 ; CHECK: Just Ref:  Ptr: i32* @G1	<->  call void @llvm.memmove.p0i8.p0i8.i64(i8* %A, i8* %B, i64 -1, i1 false) [ "deopt"() ]
 

diff  --git a/llvm/test/Transforms/FunctionAttrs/readattrs.ll b/llvm/test/Transforms/FunctionAttrs/readattrs.ll
index a982832fa37dd..1833d8b561ccf 100644
--- a/llvm/test/Transforms/FunctionAttrs/readattrs.ll
+++ b/llvm/test/Transforms/FunctionAttrs/readattrs.ll
@@ -326,9 +326,10 @@ exit:
 declare void @readnone_param(ptr nocapture readnone %p)
 declare void @readonly_param(ptr nocapture readonly %p)
 
+; FIXME: While this can't be readnone, this could be readonly.
 define void @op_bundle_readnone_deopt(ptr %p) {
 ; CHECK-LABEL: define {{[^@]+}}@op_bundle_readnone_deopt
-; CHECK-SAME: (ptr nocapture readnone [[P:%.*]]) {
+; CHECK-SAME: (ptr nocapture [[P:%.*]]) {
 ; CHECK-NEXT:    call void @readnone_param(ptr [[P]]) [ "deopt"() ]
 ; CHECK-NEXT:    ret void
 ;
@@ -338,7 +339,7 @@ define void @op_bundle_readnone_deopt(ptr %p) {
 
 define void @op_bundle_readnone_unknown(ptr %p) {
 ; CHECK-LABEL: define {{[^@]+}}@op_bundle_readnone_unknown
-; CHECK-SAME: (ptr nocapture readnone [[P:%.*]]) {
+; CHECK-SAME: (ptr nocapture [[P:%.*]]) {
 ; CHECK-NEXT:    call void @readnone_param(ptr [[P]]) [ "unknown"() ]
 ; CHECK-NEXT:    ret void
 ;
@@ -358,7 +359,7 @@ define void @op_bundle_readonly_deopt(ptr %p) {
 
 define void @op_bundle_readonly_unknown(ptr %p) {
 ; CHECK-LABEL: define {{[^@]+}}@op_bundle_readonly_unknown
-; CHECK-SAME: (ptr nocapture readonly [[P:%.*]]) {
+; CHECK-SAME: (ptr nocapture [[P:%.*]]) {
 ; CHECK-NEXT:    call void @readonly_param(ptr [[P]]) [ "unknown"() ]
 ; CHECK-NEXT:    ret void
 ;

diff  --git a/llvm/test/Transforms/FunctionAttrs/writeonly.ll b/llvm/test/Transforms/FunctionAttrs/writeonly.ll
index e4d1347ff9f2b..40ca265990487 100644
--- a/llvm/test/Transforms/FunctionAttrs/writeonly.ll
+++ b/llvm/test/Transforms/FunctionAttrs/writeonly.ll
@@ -180,7 +180,7 @@ define void @direct3b(ptr %p) {
 
 define void @direct3c(ptr %p) {
 ; CHECK-LABEL: define {{[^@]+}}@direct3c
-; CHECK-SAME: (ptr nocapture writeonly [[P:%.*]]) {
+; CHECK-SAME: (ptr nocapture [[P:%.*]]) {
 ; CHECK-NEXT:    call void @direct3_callee(ptr [[P]]) [ "may-read"() ]
 ; CHECK-NEXT:    ret void
 ;


        


More information about the llvm-commits mailing list