[llvm] f65f566 - Re-commit: Mark values as trivially dead when their only use is a start or end lifetime intrinsic.

via llvm-commits llvm-commits at lists.llvm.org
Fri May 8 12:24:21 PDT 2020


Author: zoecarver
Date: 2020-05-08T12:24:10-07:00
New Revision: f65f566aeb799f35f48c5c9bbc54b05bafec4f08

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

LOG: Re-commit: Mark values as trivially dead when their only use is a start or end lifetime intrinsic.

Summary:
If the only use of a value is a start or end lifetime intrinsic then mark the intrinsic as trivially dead. This should allow for that value to then be removed as well.

Currently, this only works for allocas, globals, and arguments.

Subscribers: hiraditya, llvm-commits

Tags: #llvm

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

Added: 
    

Modified: 
    llvm/lib/Transforms/Utils/Local.cpp
    llvm/test/Analysis/BasicAA/modref.ll
    llvm/test/Transforms/Attributor/memory_locations.ll
    llvm/test/Transforms/DCE/basic.ll
    llvm/test/Transforms/DeadStoreElimination/lifetime.ll
    llvm/test/Transforms/InstCombine/vararg.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp
index 265d6d9337d9..6d6e74c9d759 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -403,9 +403,22 @@ bool llvm::wouldInstructionBeTriviallyDead(Instruction *I,
         II->getIntrinsicID() == Intrinsic::launder_invariant_group)
       return true;
 
-    // Lifetime intrinsics are dead when their right-hand is undef.
-    if (II->isLifetimeStartOrEnd())
-      return isa<UndefValue>(II->getArgOperand(1));
+    if (II->isLifetimeStartOrEnd()) {
+      auto *Arg = II->getArgOperand(1);
+      // Lifetime intrinsics are dead when their right-hand is undef.
+      if (isa<UndefValue>(Arg))
+        return true;
+      // If the right-hand is an alloc, global, or argument and the only uses
+      // are lifetime intrinsics then the intrinsics are dead.
+      if (isa<AllocaInst>(Arg) || isa<GlobalValue>(Arg) || isa<Argument>(Arg))
+        return llvm::all_of(Arg->uses(), [](Use &Use) {
+          if (IntrinsicInst *IntrinsicUse =
+                  dyn_cast<IntrinsicInst>(Use.getUser()))
+            return IntrinsicUse->isLifetimeStartOrEnd();
+          return false;
+        });
+      return false;
+    }
 
     // Assumptions are dead if their condition is trivially true.  Guards on
     // true are operationally no-ops.  In the future we can consider more

diff  --git a/llvm/test/Analysis/BasicAA/modref.ll b/llvm/test/Analysis/BasicAA/modref.ll
index a364a81a4e05..eb18f913fb9d 100644
--- a/llvm/test/Analysis/BasicAA/modref.ll
+++ b/llvm/test/Analysis/BasicAA/modref.ll
@@ -80,7 +80,6 @@ define void @test3a(i8* %P, i8 %X) {
 
   %P2 = getelementptr i8, i8* %P, i32 2
   store i8 %Y, i8* %P2
-; CHECK-NEXT: call void @llvm.lifetime.end
   call void @llvm.lifetime.end.p0i8(i64 10, i8* %P)
   ret void
 ; CHECK-NEXT: ret void

diff  --git a/llvm/test/Transforms/Attributor/memory_locations.ll b/llvm/test/Transforms/Attributor/memory_locations.ll
index 1f0983047f70..6ca5cddd94d1 100644
--- a/llvm/test/Transforms/Attributor/memory_locations.ll
+++ b/llvm/test/Transforms/Attributor/memory_locations.ll
@@ -386,11 +386,11 @@ define void @callerD2() {
   store i8 0, i8* %unknown
   ret void
 }
-; CHECK: Function Attrs: argmemonly nounwind willreturn
+
+; CHECK: Function Attrs: nofree {{(norecurse )?}}nosync nounwind readnone willreturn
 define void @callerE(i8* %arg) {
 ; CHECK-LABEL: define {{[^@]+}}@callerE
-; CHECK-SAME: (i8* nocapture [[ARG:%.*]])
-; CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 4, i8* nocapture [[ARG]])
+; CHECK-SAME: (i8* nocapture nofree readnone [[ARG:%.*]])
 ; CHECK-NEXT:    ret void
 ;
   call void @llvm.lifetime.start.p0i8(i64 4, i8* %arg)

diff  --git a/llvm/test/Transforms/DCE/basic.ll b/llvm/test/Transforms/DCE/basic.ll
index 6282ac78e75e..0f70300ec0f9 100644
--- a/llvm/test/Transforms/DCE/basic.ll
+++ b/llvm/test/Transforms/DCE/basic.ll
@@ -11,5 +11,63 @@ define void @test() {
   ret void
 }
 
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) nounwind
+declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) nounwind
+
+; CHECK-LABEL: @test_lifetime_alloca
+define i32 @test_lifetime_alloca() {
+; Check that lifetime intrinsics are removed along with the pointer.
+; CHECK-NEXT: @llvm.dbg.value
+; CHECK-NEXT: ret i32 0
+; CHECK-NOT: llvm.lifetime.start
+; CHECK-NOT: llvm.lifetime.end
+  %i = alloca i8, align 4
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %i)
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %i)
+  ret i32 0
+}
+
+; CHECK-LABEL: @test_lifetime_arg
+define i32 @test_lifetime_arg(i8*) {
+; Check that lifetime intrinsics are removed along with the pointer.
+; CHECK-NEXT: llvm.dbg.value
+; CHECK-NEXT: ret i32 0
+; CHECK-NOT: llvm.lifetime.start
+; CHECK-NOT: llvm.lifetime.end
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %0)
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %0)
+  ret i32 0
+}
+
+ at glob = global i8 1
+
+; CHECK-LABEL: @test_lifetime_global
+define i32 @test_lifetime_global() {
+; Check that lifetime intrinsics are removed along with the pointer.
+; CHECK-NEXT: llvm.dbg.value
+; CHECK-NEXT: ret i32 0
+; CHECK-NOT: llvm.lifetime.start
+; CHECK-NOT: llvm.lifetime.end
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* @glob)
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* @glob)
+  ret i32 0
+}
+
+; CHECK-LABEL: @test_lifetime_bitcast
+define i32 @test_lifetime_bitcast(i32*) {
+; Check that lifetime intrinsics are NOT removed when the pointer is a bitcast.
+; It's not uncommon for two bitcasts to be made: one for lifetime, one for use.
+; TODO: Support the above case.
+; CHECK-NEXT: bitcast
+; CHECK-NEXT: llvm.dbg.value
+; CHECK-NEXT: llvm.lifetime.start
+; CHECK-NEXT: llvm.lifetime.end
+; CHECK-NEXT: ret i32 0
+  %2 = bitcast i32* %0 to i8*
+  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %2)
+  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %2)
+  ret i32 0
+}
+
 ; CHECK: [[add]] = !DILocalVariable
 ; CHECK: [[sub]] = !DILocalVariable

diff  --git a/llvm/test/Transforms/DeadStoreElimination/lifetime.ll b/llvm/test/Transforms/DeadStoreElimination/lifetime.ll
index 28a164cd8b50..c0cc2109c202 100644
--- a/llvm/test/Transforms/DeadStoreElimination/lifetime.ll
+++ b/llvm/test/Transforms/DeadStoreElimination/lifetime.ll
@@ -12,7 +12,7 @@ define void @test1() {
 
   store i8 0, i8* %A  ;; Written to by memset
   call void @llvm.lifetime.end.p0i8(i64 1, i8* %A)
-; CHECK: lifetime.end
+; CHECK-NOT: lifetime.end
 
   call void @llvm.memset.p0i8.i8(i8* %A, i8 0, i8 -1, i1 false)
 ; CHECK-NOT: memset
@@ -26,11 +26,9 @@ define void @test2(i32* %P) {
   %Q = getelementptr i32, i32* %P, i32 1
   %R = bitcast i32* %Q to i8*
   call void @llvm.lifetime.start.p0i8(i64 4, i8* %R)
-; CHECK: lifetime.start
   store i32 0, i32* %Q  ;; This store is dead.
 ; CHECK-NOT: store
   call void @llvm.lifetime.end.p0i8(i64 4, i8* %R)
-; CHECK: lifetime.end
   ret void
 }
 

diff  --git a/llvm/test/Transforms/InstCombine/vararg.ll b/llvm/test/Transforms/InstCombine/vararg.ll
index 8fc9aafcdefc..dd605fcc5c41 100644
--- a/llvm/test/Transforms/InstCombine/vararg.ll
+++ b/llvm/test/Transforms/InstCombine/vararg.ll
@@ -1,4 +1,4 @@
-; RUN: opt < %s -instcombine -instcombine-infinite-loop-threshold=2 -S | FileCheck %s
+; RUN: opt < %s -instcombine -instcombine-infinite-loop-threshold=3 -S | FileCheck %s
 
 %struct.__va_list = type { i8*, i8*, i8*, i32, i32 }
 


        


More information about the llvm-commits mailing list