[PATCH] D73426: [Attributor] Derive memory location attributes (argmemonly, ...)

Robert Cox via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 13 18:56:34 PDT 2021


rcox2 added inline comments.
Herald added subscribers: ormris, okura, kuter.
Herald added a reviewer: homerdin.


================
Comment at: llvm/include/llvm/Transforms/IPO/Attributor.h:2603
+  bool isAssumedReadNone() const {
+    return isAssumed(NO_LOCATIONS) | isAssumedStackOnly();
+  }
----------------
Hi Johannes, 

We have a question about the intended behavior of the attributor on functions with byval arguments.
Consider the following input (t1.ll) 

{code}
%struct._vec = type { float, float, float }

define void @caller() {
  %x = alloca %struct._vec, align 4
  %y = getelementptr inbounds %struct._vec, %struct._vec* %x, i32 0, i32 1
  store float 42.0, float* %y
  %v = call float @callee(%struct._vec* %x)
  ret float %v
}

define float @callee(%struct._vec* byval(%struct._vec) %x) {
  %y = getelementptr inbounds %struct._vec, %struct._vec* %x, i32 0, i32 1
  %v = load float, float* %y
  ret float %v
}
{code}

If I run this through the attributor with:
opt -passes='module(attributor)' -S t1.ll
I get:

{code}
%struct._vec = type { float, float, float }

; Function Attrs: nofree nosync nounwind readnone willreturn
define float @caller() #0 {
  %x = alloca %struct._vec, align 4
  %y = getelementptr inbounds %struct._vec, %struct._vec* %x, i32 0, i32 1
  store float 4.200000e+01, float* %y, align 4
  %v = call float @callee(%struct._vec* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(12) %x) #0
  ret float %v
}

; Function Attrs: nofree nosync nounwind readnone willreturn
define float @callee(%struct._vec* noalias nocapture nofree nonnull readonly byval(%struct._vec) align 4 dereferenceable(12) %x) #0 {
  %y = getelementptr inbounds %struct._vec, %struct._vec* %x, i32 0, i32 1
  %v = load float, float* %y, align 4
  ret float %v
}

attributes #0 = { nofree nosync nounwind readnone willreturn }
{code}

The key point is that the @callee is marked 'readnone' rather than 'readonly'. 

Adding the dse pass:
opt -passes='module(attributor),dse' -S t1.ll 

%struct._vec = type { float, float, float }
{code}

; Function Attrs: nofree nosync nounwind readnone willreturn
define float @caller() #0 {
  %x = alloca %struct._vec, align 4
  %v = call float @callee(%struct._vec* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(12) %x) #0
  ret float %v
}

; Function Attrs: nofree nosync nounwind readnone willreturn
define float @callee(%struct._vec* noalias nocapture nofree nonnull readonly byval(%struct._vec) align 4 dereferenceable(12) %x) #0 {
  %y = getelementptr inbounds %struct._vec, %struct._vec* %x, i32 0, i32 1
  %v = load float, float* %y, align 4
  ret float %v
}

attributes #0 = { nofree nosync nounwind readnone willreturn }
{code}

With a loss of the store in the caller. So, is this a bug in the attributor, because it is marking the callee "readnone"? Or is it a bug in dse, because it thinks that 'readnone' with a byval arg menas it can eleiminate the store in the caller? 


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D73426/new/

https://reviews.llvm.org/D73426



More information about the llvm-commits mailing list