reames created this revision.
reames added reviewers: jdoerfert, anna, aeubanks, modimo, sstefan1.
Herald added subscribers: jeroen.dobbelaere, ormris, kerbowa, bollu, hiraditya, 
sbc100, nhaehnle, jvesely, mcrosier.
reames requested review of this revision.
Herald added subscribers: cfe-commits, aheejin.
Herald added projects: clang, LLVM.

This builds on the code from D114963 <https://reviews.llvm.org/D114963>, and 
extends it to handle calls both direct and indirect.  I ended up deciding to do 
this in the current code structure (before a cleanup) so that the cornercases 
were a bit more obvious.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D115003

Files:
  clang/test/CodeGen/arm-vfp16-arguments.c
  clang/test/CodeGenCXX/wasm-args-returns.cpp
  clang/test/CodeGenOpenCL/amdgpu-abi-struct-coerce.cl
  llvm/lib/Transforms/IPO/FunctionAttrs.cpp
  llvm/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll
  llvm/test/Other/cgscc-devirt-iteration.ll
  llvm/test/Transforms/FunctionAttrs/nocapture.ll
  llvm/test/Transforms/FunctionAttrs/norecurse.ll
  llvm/test/Transforms/FunctionAttrs/writeonly.ll

Index: llvm/test/Transforms/FunctionAttrs/writeonly.ll
===================================================================
--- llvm/test/Transforms/FunctionAttrs/writeonly.ll
+++ llvm/test/Transforms/FunctionAttrs/writeonly.ll
@@ -69,7 +69,7 @@
 
 declare void @direct2_callee(i8* %p) writeonly
 
-; CHECK: define void @direct2(i8* %p)
+; CHECK: define void @direct2(i8* writeonly %p)
 define void @direct2(i8* %p) {
   call void @direct2_callee(i8* %p)
   ret void
@@ -77,7 +77,7 @@
 
 declare void @direct3_callee(i8* writeonly %p)
 
-; CHECK: define void @direct3(i8* %p)
+; CHECK: define void @direct3(i8* writeonly %p)
 define void @direct3(i8* %p) {
   call void @direct3_callee(i8* %p)
   ret void
@@ -95,7 +95,7 @@
   ret void
 }
 
-; CHECK: define void @fptr_test3(i8* %p, void (i8*)* nocapture %f)
+; CHECK: define void @fptr_test3(i8* writeonly %p, void (i8*)* nocapture %f)
 define void @fptr_test3(i8* %p, void (i8*)* %f) {
   call void %f(i8* %p) writeonly
   ret void
Index: llvm/test/Transforms/FunctionAttrs/norecurse.ll
===================================================================
--- llvm/test/Transforms/FunctionAttrs/norecurse.ll
+++ llvm/test/Transforms/FunctionAttrs/norecurse.ll
@@ -50,7 +50,7 @@
 ; CHECK: Function Attrs
 ; CHECK-SAME: nounwind
 ; CHECK-NOT: norecurse
-; CHECK-NEXT: define void @intrinsic(i8* nocapture %dest, i8* nocapture readonly %src, i32 %len)
+; CHECK-NEXT: define void @intrinsic(i8* nocapture writeonly %dest, i8* nocapture readonly %src, i32 %len)
 define void @intrinsic(i8* %dest, i8* %src, i32 %len) {
   call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 false)
   ret void
Index: llvm/test/Transforms/FunctionAttrs/nocapture.ll
===================================================================
--- llvm/test/Transforms/FunctionAttrs/nocapture.ll
+++ llvm/test/Transforms/FunctionAttrs/nocapture.ll
@@ -15,7 +15,7 @@
 	ret void
 }
 
-; FNATTR: define void @c3(i32* %q)
+; FNATTR: define void @c3(i32* writeonly %q)
 define void @c3(i32* %q) {
 	call void @c2(i32* %q)
 	ret void
@@ -156,7 +156,7 @@
   ret void
 }
 
-; FNATTR: define i8* @test1_2(i8* nocapture readnone %x1_2, i8* returned %y1_2, i1 %c)
+; FNATTR: define i8* @test1_2(i8* nocapture readnone %x1_2, i8* returned writeonly %y1_2, i1 %c)
 define i8* @test1_2(i8* %x1_2, i8* %y1_2, i1 %c) {
   br i1 %c, label %t, label %f
 t:
Index: llvm/test/Other/cgscc-devirt-iteration.ll
===================================================================
--- llvm/test/Other/cgscc-devirt-iteration.ll
+++ llvm/test/Other/cgscc-devirt-iteration.ll
@@ -112,7 +112,7 @@
 ; CHECK-NOT: read
 ; CHECK-SAME: noinline
 ; BEFORE-LABEL: define void @test3(i8* %src, i8* %dest, i64 %size)
-; AFTER-LABEL: define void @test3(i8* nocapture readonly %src, i8* nocapture %dest, i64 %size)
+; AFTER-LABEL: define void @test3(i8* nocapture readonly %src, i8* nocapture writeonly %dest, i64 %size)
   %fptr = alloca i8* (i8*, i8*, i64)*
   store i8* (i8*, i8*, i64)* @memcpy, i8* (i8*, i8*, i64)** %fptr
   %f = load i8* (i8*, i8*, i64)*, i8* (i8*, i8*, i64)** %fptr
Index: llvm/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll
===================================================================
--- llvm/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll
+++ llvm/test/Analysis/TypeBasedAliasAnalysis/functionattrs.ll
@@ -49,7 +49,7 @@
   ret void
 }
 
-; CHECK: define void @test2_no(i8* nocapture %p, i8* nocapture readonly %q, i64 %n) #5 {
+; CHECK: define void @test2_no(i8* nocapture writeonly %p, i8* nocapture readonly %q, i64 %n) #5 {
 define void @test2_no(i8* %p, i8* %q, i64 %n) nounwind {
   call void @llvm.memcpy.p0i8.p0i8.i64(i8* %p, i8* %q, i64 %n, i1 false), !tbaa !2
   ret void
Index: llvm/lib/Transforms/IPO/FunctionAttrs.cpp
===================================================================
--- llvm/lib/Transforms/IPO/FunctionAttrs.cpp
+++ llvm/lib/Transforms/IPO/FunctionAttrs.cpp
@@ -713,6 +713,10 @@
           IsRead = true;
           AddUsersToWorklistIfCapturing();
           continue;
+        } else if (!CB.isCallee(U) && CB.hasFnAttr(Attribute::WriteOnly)) {
+          IsWrite = true;
+          AddUsersToWorklistIfCapturing();
+          continue;
         }
         return Attribute::None;
       }
@@ -749,10 +753,14 @@
         // The accessors used on call site here do the right thing for calls and
         // invokes with operand bundles.
 
-        if (!CB.onlyReadsMemory() && !CB.onlyReadsMemory(UseIndex))
-          return Attribute::None;
-        if (!CB.doesNotAccessMemory(UseIndex))
+        if (CB.doesNotAccessMemory(UseIndex)) { /* nop */ }
+        else if (CB.onlyReadsMemory() || CB.onlyReadsMemory(UseIndex))
           IsRead = true;
+        else if (CB.hasFnAttr(Attribute::WriteOnly) ||
+                 CB.dataOperandHasImpliedAttr(UseIndex, Attribute::WriteOnly))
+          IsWrite = true;
+        else
+          return Attribute::None;
       }
 
       AddUsersToWorklistIfCapturing();
Index: clang/test/CodeGenOpenCL/amdgpu-abi-struct-coerce.cl
===================================================================
--- clang/test/CodeGenOpenCL/amdgpu-abi-struct-coerce.cl
+++ clang/test/CodeGenOpenCL/amdgpu-abi-struct-coerce.cl
@@ -403,14 +403,14 @@
   return s;
 }
 
-// CHECK: define{{.*}} void @func_ret_struct_arr32(%struct.struct_arr32 addrspace(5)* noalias nocapture sret(%struct.struct_arr32) align 4 %agg.result)
+// CHECK: define{{.*}} void @func_ret_struct_arr32(%struct.struct_arr32 addrspace(5)* noalias nocapture writeonly sret(%struct.struct_arr32) align 4 %agg.result)
 struct_arr32 func_ret_struct_arr32()
 {
   struct_arr32 s = { 0 };
   return s;
 }
 
-// CHECK: define{{.*}} void @func_ret_struct_arr33(%struct.struct_arr33 addrspace(5)* noalias nocapture sret(%struct.struct_arr33) align 4 %agg.result)
+// CHECK: define{{.*}} void @func_ret_struct_arr33(%struct.struct_arr33 addrspace(5)* noalias nocapture writeonly sret(%struct.struct_arr33) align 4 %agg.result)
 struct_arr33 func_ret_struct_arr33()
 {
   struct_arr33 s = { 0 };
@@ -468,7 +468,7 @@
 // CHECK: define{{.*}} void @func_large_struct_padding_arg_direct(i8 %arg.coerce0, i32 %arg.coerce1, i8 %arg.coerce2, i32 %arg.coerce3, i8 %arg.coerce4, i8 %arg.coerce5, i16 %arg.coerce6, i16 %arg.coerce7, [3 x i8] %arg.coerce8, i64 %arg.coerce9, i32 %arg.coerce10, i8 %arg.coerce11, i32 %arg.coerce12, i16 %arg.coerce13, i8 %arg.coerce14)
 void func_large_struct_padding_arg_direct(large_struct_padding arg) { }
 
-// CHECK: define{{.*}} void @func_large_struct_padding_arg_store(%struct.large_struct_padding addrspace(1)* nocapture %out, %struct.large_struct_padding addrspace(5)* nocapture readonly byval(%struct.large_struct_padding) align 8 %arg)
+// CHECK: define{{.*}} void @func_large_struct_padding_arg_store(%struct.large_struct_padding addrspace(1)* nocapture writeonly %out, %struct.large_struct_padding addrspace(5)* nocapture readonly byval(%struct.large_struct_padding) align 8 %arg)
 void func_large_struct_padding_arg_store(global large_struct_padding* out, large_struct_padding arg) {
   *out = arg;
 }
Index: clang/test/CodeGenCXX/wasm-args-returns.cpp
===================================================================
--- clang/test/CodeGenCXX/wasm-args-returns.cpp
+++ clang/test/CodeGenCXX/wasm-args-returns.cpp
@@ -30,7 +30,7 @@
   double d, e;
 };
 test(two_fields);
-// CHECK: define void @_Z7forward10two_fields(%struct.two_fields* noalias nocapture sret(%struct.two_fields) align 8 %{{.*}}, %struct.two_fields* nocapture readonly byval(%struct.two_fields) align 8 %{{.*}})
+// CHECK: define void @_Z7forward10two_fields(%struct.two_fields* noalias nocapture writeonly sret(%struct.two_fields) align 8 %{{.*}}, %struct.two_fields* nocapture readonly byval(%struct.two_fields) align 8 %{{.*}})
 //
 // CHECK: define void @_Z15test_two_fieldsv()
 // CHECK: %[[tmp:.*]] = alloca %struct.two_fields, align 8
Index: clang/test/CodeGen/arm-vfp16-arguments.c
===================================================================
--- clang/test/CodeGen/arm-vfp16-arguments.c
+++ clang/test/CodeGen/arm-vfp16-arguments.c
@@ -71,6 +71,6 @@
 
 hfa_t ghfa;
 hfa_t test_ret_hfa(void) { return ghfa; }
-// CHECK-SOFT: define{{.*}} void @test_ret_hfa(%struct.hfa_t* noalias nocapture sret(%struct.hfa_t) align 8 %agg.result)
+// CHECK-SOFT: define{{.*}} void @test_ret_hfa(%struct.hfa_t* noalias nocapture writeonly sret(%struct.hfa_t) align 8 %agg.result)
 // CHECK-HARD: define{{.*}} arm_aapcs_vfpcc [2 x <2 x i32>] @test_ret_hfa()
 // CHECK-FULL: define{{.*}} arm_aapcs_vfpcc %struct.hfa_t @test_ret_hfa()
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D115003: [funcattrs]... Philip Reames via Phabricator via cfe-commits

Reply via email to