[PATCH] D118242: [AA] Make use of sret being invisible on unwind

Nikita Popov via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 26 05:36:28 PST 2022


nikic created this revision.
Herald added subscribers: jeroen.dobbelaere, asbirlea, hiraditya.
nikic requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

This implements the LangRef change from D116998 <https://reviews.llvm.org/D116998>. DSE, MemCpyOpt and LICM can now perform optimizations on sret arguments in the presence of unwinding.

Depends on D116998 <https://reviews.llvm.org/D116998>.


https://reviews.llvm.org/D118242

Files:
  llvm/lib/Analysis/AliasAnalysis.cpp
  llvm/test/Transforms/DeadStoreElimination/simple.ll
  llvm/test/Transforms/LICM/scalar-promote-unwind.ll
  llvm/test/Transforms/MemCpyOpt/callslot_throw.ll


Index: llvm/test/Transforms/MemCpyOpt/callslot_throw.ll
===================================================================
--- llvm/test/Transforms/MemCpyOpt/callslot_throw.ll
+++ llvm/test/Transforms/MemCpyOpt/callslot_throw.ll
@@ -56,14 +56,12 @@
   ret void
 }
 
-; TODO: With updated semantics, sret could also be invisible on unwind.
+; sret argument is not visible on unwind.
 define void @test_sret(i32* nocapture noalias dereferenceable(4) sret(i32) %x) {
 ; CHECK-LABEL: @test_sret(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[T:%.*]] = alloca i32, align 4
-; CHECK-NEXT:    call void @may_throw(i32* nonnull [[T]])
-; CHECK-NEXT:    [[LOAD:%.*]] = load i32, i32* [[T]], align 4
-; CHECK-NEXT:    store i32 [[LOAD]], i32* [[X:%.*]], align 4
+; CHECK-NEXT:    call void @may_throw(i32* nonnull [[X:%.*]])
 ; CHECK-NEXT:    ret void
 ;
 entry:
Index: llvm/test/Transforms/LICM/scalar-promote-unwind.ll
===================================================================
--- llvm/test/Transforms/LICM/scalar-promote-unwind.ll
+++ llvm/test/Transforms/LICM/scalar-promote-unwind.ll
@@ -146,16 +146,16 @@
   ret void
 }
 
-; TODO: sret could be specified to not be accessed on unwind either.
+; sret is not visible on unwind.
 define void @test_sret(i32* noalias sret(i32) %a, i1 zeroext %y) uwtable {
 ; CHECK-LABEL: @test_sret(
 ; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[A_PROMOTED:%.*]] = load i32, i32* [[A:%.*]], align 4
 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
 ; CHECK:       for.body:
-; CHECK-NEXT:    [[I_03:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
-; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* [[A:%.*]], align 4
-; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[TMP0]], 1
-; CHECK-NEXT:    store i32 [[ADD]], i32* [[A]], align 4
+; CHECK-NEXT:    [[ADD1:%.*]] = phi i32 [ [[A_PROMOTED]], [[ENTRY:%.*]] ], [ [[ADD:%.*]], [[FOR_INC:%.*]] ]
+; CHECK-NEXT:    [[I_03:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC:%.*]], [[FOR_INC]] ]
+; CHECK-NEXT:    [[ADD]] = add nsw i32 [[ADD1]], 1
 ; CHECK-NEXT:    br i1 [[Y:%.*]], label [[IF_THEN:%.*]], label [[FOR_INC]]
 ; CHECK:       if.then:
 ; CHECK-NEXT:    tail call void @f()
@@ -165,6 +165,8 @@
 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 10000
 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]]
 ; CHECK:       for.cond.cleanup:
+; CHECK-NEXT:    [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_INC]] ]
+; CHECK-NEXT:    store i32 [[ADD_LCSSA]], i32* [[A]], align 4
 ; CHECK-NEXT:    ret void
 ;
 entry:
Index: llvm/test/Transforms/DeadStoreElimination/simple.ll
===================================================================
--- llvm/test/Transforms/DeadStoreElimination/simple.ll
+++ llvm/test/Transforms/DeadStoreElimination/simple.ll
@@ -532,13 +532,12 @@
   store i32 0, i32* %p
   ret void
 }
-; Same as previous case, but with an sret argument.
-; TODO: The first store could be eliminated if sret is not visible on unwind.
+; Same as previous case, but with an sret argument, which is not visible on
+; unwind.
 define void @test34_sret(i32* noalias sret(i32) %p) {
 ; CHECK-LABEL: @test34_sret(
-; CHECK-NEXT:    store i32 1, i32* [[P:%.*]], align 4
 ; CHECK-NEXT:    call void @unknown_func()
-; CHECK-NEXT:    store i32 0, i32* [[P]], align 4
+; CHECK-NEXT:    store i32 0, i32* [[P:%.*]], align 4
 ; CHECK-NEXT:    ret void
 ;
   store i32 1, i32* %p
Index: llvm/lib/Analysis/AliasAnalysis.cpp
===================================================================
--- llvm/lib/Analysis/AliasAnalysis.cpp
+++ llvm/lib/Analysis/AliasAnalysis.cpp
@@ -996,9 +996,9 @@
   if (isa<AllocaInst>(Object))
     return true;
 
-  // Byval goes out of scope on unwind.
+  // Byval goes out of scope on unwind, sret is poisoned on unwind.
   if (auto *A = dyn_cast<Argument>(Object))
-    return A->hasByValAttr();
+    return A->hasByValAttr() || A->hasStructRetAttr();
 
   // A noalias return is not accessible from any other code. If the pointer
   // does not escape prior to the unwind, then the caller cannot access the


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D118242.403233.patch
Type: text/x-patch
Size: 4068 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20220126/297110b9/attachment.bin>


More information about the llvm-commits mailing list