[llvm] 5b37768 - [FunctionAttrs] Account for memory effects of inalloca/preallocated

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 13 01:20:30 PDT 2022


Author: Nikita Popov
Date: 2022-10-13T10:20:17+02:00
New Revision: 5b3776842f8e14b70199c0f76773b2af1cf32d34

URL: https://github.com/llvm/llvm-project/commit/5b3776842f8e14b70199c0f76773b2af1cf32d34
DIFF: https://github.com/llvm/llvm-project/commit/5b3776842f8e14b70199c0f76773b2af1cf32d34.diff

LOG: [FunctionAttrs] Account for memory effects of inalloca/preallocated

The code for inferring memory attributes on arguments claims that
inalloca/preallocated arguments are always clobbered:
https://github.com/llvm/llvm-project/blob/d71ad4108056d685f48407447095d8d92fd7685d/llvm/lib/Transforms/IPO/FunctionAttrs.cpp#L640-L642

However, we would still infer memory attributes for the whole
function without taking this into account, so we could still end
up inferring readnone for the function. This adds an argument
clobber if there are any inalloca/preallocated arguments.

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

Added: 
    

Modified: 
    llvm/lib/Transforms/IPO/FunctionAttrs.cpp
    llvm/test/Transforms/FunctionAttrs/readattrs.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
index 22ff83b2a2211..055cb14c3114c 100644
--- a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
+++ b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
@@ -133,13 +133,18 @@ checkFunctionMemoryAccess(Function &F, bool ThisBody, AAResults &AAR,
   if (!ThisBody)
     return OrigMRB;
 
-  // Scan the function body for instructions that may read or write memory.
   FunctionModRefBehavior MRB = FunctionModRefBehavior::none();
+  // Inalloca and preallocated arguments are always clobbered by the call.
+  if (F.getAttributes().hasAttrSomewhere(Attribute::InAlloca) ||
+      F.getAttributes().hasAttrSomewhere(Attribute::Preallocated))
+    MRB |= FunctionModRefBehavior::argMemOnly(ModRefInfo::ModRef);
+
   // Returns true if Ptr is not based on a function argument.
   auto IsArgumentOrAlloca = [](const Value *Ptr) {
     const Value *UO = getUnderlyingObject(Ptr);
     return isa<Argument>(UO) || isa<AllocaInst>(UO);
   };
+  // Scan the function body for instructions that may read or write memory.
   for (Instruction &I : instructions(F)) {
     // Some instructions can be ignored even if they read or write memory.
     // Detect these now, skipping to the next instruction if one is found.

diff  --git a/llvm/test/Transforms/FunctionAttrs/readattrs.ll b/llvm/test/Transforms/FunctionAttrs/readattrs.ll
index 798378ee05070..63c27831fe006 100644
--- a/llvm/test/Transforms/FunctionAttrs/readattrs.ll
+++ b/llvm/test/Transforms/FunctionAttrs/readattrs.ll
@@ -81,9 +81,9 @@ define void @test6_2(i8** %p, i8* %q) {
 
 ; inalloca parameters are always considered written
 define void @test7_1(i32* inalloca(i32) %a) {
-; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn
+; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse nosync nounwind willreturn
 ; CHECK-LABEL: define {{[^@]+}}@test7_1
-; CHECK-SAME: (i32* nocapture inalloca(i32) [[A:%.*]]) #[[ATTR1]] {
+; CHECK-SAME: (i32* nocapture inalloca(i32) [[A:%.*]]) #[[ATTR5:[0-9]+]] {
 ; CHECK-NEXT:    ret void
 ;
   ret void
@@ -91,9 +91,9 @@ define void @test7_1(i32* inalloca(i32) %a) {
 
 ; preallocated parameters are always considered written
 define void @test7_2(i32* preallocated(i32) %a) {
-; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn
+; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse nosync nounwind willreturn
 ; CHECK-LABEL: define {{[^@]+}}@test7_2
-; CHECK-SAME: (i32* nocapture preallocated(i32) [[A:%.*]]) #[[ATTR1]] {
+; CHECK-SAME: (i32* nocapture preallocated(i32) [[A:%.*]]) #[[ATTR5]] {
 ; CHECK-NEXT:    ret void
 ;
   ret void
@@ -130,7 +130,7 @@ declare void @llvm.masked.scatter.v4i32.v4p0i32(<4 x i32>%val, <4 x i32*>, i32,
 define void @test9(<4 x i32*> %ptrs, <4 x i32>%val) {
 ; CHECK: Function Attrs: mustprogress nofree nosync nounwind willreturn writeonly
 ; CHECK-LABEL: define {{[^@]+}}@test9
-; CHECK-SAME: (<4 x i32*> [[PTRS:%.*]], <4 x i32> [[VAL:%.*]]) #[[ATTR6:[0-9]+]] {
+; CHECK-SAME: (<4 x i32*> [[PTRS:%.*]], <4 x i32> [[VAL:%.*]]) #[[ATTR7:[0-9]+]] {
 ; CHECK-NEXT:    call void @llvm.masked.scatter.v4i32.v4p0i32(<4 x i32> [[VAL]], <4 x i32*> [[PTRS]], i32 4, <4 x i1> <i1 true, i1 false, i1 true, i1 false>)
 ; CHECK-NEXT:    ret void
 ;
@@ -142,7 +142,7 @@ declare <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*>, i32, <4 x i1>, <
 define <4 x i32> @test10(<4 x i32*> %ptrs) {
 ; CHECK: Function Attrs: mustprogress nofree nosync nounwind readonly willreturn
 ; CHECK-LABEL: define {{[^@]+}}@test10
-; CHECK-SAME: (<4 x i32*> [[PTRS:%.*]]) #[[ATTR8:[0-9]+]] {
+; CHECK-SAME: (<4 x i32*> [[PTRS:%.*]]) #[[ATTR9:[0-9]+]] {
 ; CHECK-NEXT:    [[RES:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> [[PTRS]], i32 4, <4 x i1> <i1 true, i1 false, i1 true, i1 false>, <4 x i32> undef)
 ; CHECK-NEXT:    ret <4 x i32> [[RES]]
 ;
@@ -154,7 +154,7 @@ declare <4 x i32> @test11_1(<4 x i32*>) argmemonly nounwind readonly
 define <4 x i32> @test11_2(<4 x i32*> %ptrs) {
 ; CHECK: Function Attrs: argmemonly nofree nounwind readonly
 ; CHECK-LABEL: define {{[^@]+}}@test11_2
-; CHECK-SAME: (<4 x i32*> [[PTRS:%.*]]) #[[ATTR10:[0-9]+]] {
+; CHECK-SAME: (<4 x i32*> [[PTRS:%.*]]) #[[ATTR11:[0-9]+]] {
 ; CHECK-NEXT:    [[RES:%.*]] = call <4 x i32> @test11_1(<4 x i32*> [[PTRS]])
 ; CHECK-NEXT:    ret <4 x i32> [[RES]]
 ;
@@ -166,7 +166,7 @@ declare <4 x i32> @test12_1(<4 x i32*>) argmemonly nounwind
 define <4 x i32> @test12_2(<4 x i32*> %ptrs) {
 ; CHECK: Function Attrs: argmemonly nounwind
 ; CHECK-LABEL: define {{[^@]+}}@test12_2
-; CHECK-SAME: (<4 x i32*> [[PTRS:%.*]]) #[[ATTR11:[0-9]+]] {
+; CHECK-SAME: (<4 x i32*> [[PTRS:%.*]]) #[[ATTR12:[0-9]+]] {
 ; CHECK-NEXT:    [[RES:%.*]] = call <4 x i32> @test12_1(<4 x i32*> [[PTRS]])
 ; CHECK-NEXT:    ret <4 x i32> [[RES]]
 ;
@@ -177,7 +177,7 @@ define <4 x i32> @test12_2(<4 x i32*> %ptrs) {
 define i32 @volatile_load(i32* %p) {
 ; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse nounwind willreturn
 ; CHECK-LABEL: define {{[^@]+}}@volatile_load
-; CHECK-SAME: (i32* [[P:%.*]]) #[[ATTR12:[0-9]+]] {
+; CHECK-SAME: (i32* [[P:%.*]]) #[[ATTR13:[0-9]+]] {
 ; CHECK-NEXT:    [[LOAD:%.*]] = load volatile i32, i32* [[P]], align 4
 ; CHECK-NEXT:    ret i32 [[LOAD]]
 ;


        


More information about the llvm-commits mailing list