[llvm] r245542 - [DSE] Enable removal of lifetime intrinsics in terminating blocks

Bjorn Steinbrink via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 20 01:25:28 PDT 2015


Author: bsteinbr
Date: Thu Aug 20 03:25:28 2015
New Revision: 245542

URL: http://llvm.org/viewvc/llvm-project?rev=245542&view=rev
Log:
[DSE] Enable removal of lifetime intrinsics in terminating blocks

Usually DSE is not supposed to remove lifetime intrinsics, but it's
actually ok to remove them for dead objects in terminating blocks,
because they convey no extra information there. Until we hit a lifetime
start that cannot be removed, that is. Because from that point on the
lifetime intrinsics become interesting again, e.g. for stack coloring.

Reviewers: reames

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D11710

Modified:
    llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp
    llvm/trunk/test/Transforms/DeadStoreElimination/lifetime.ll

Modified: llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp?rev=245542&r1=245541&r2=245542&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp Thu Aug 20 03:25:28 2015
@@ -788,15 +788,33 @@ bool DSE::handleEndBlock(BasicBlock &BB)
 
   const DataLayout &DL = BB.getModule()->getDataLayout();
 
+  // becomes false once lifetime intrinsics are observable or useful for stack
+  // coloring
+  bool canRemoveLifetimeIntrinsics = true;
+
   // Scan the basic block backwards
   for (BasicBlock::iterator BBI = BB.end(); BBI != BB.begin(); ){
     --BBI;
 
-    // If we find a store, check to see if it points into a dead stack value.
-    if (hasMemoryWrite(BBI, *TLI) && isRemovable(BBI)) {
+    Value *V = nullptr;
+    if (canRemoveLifetimeIntrinsics)
+      if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(BBI))
+        switch (II->getIntrinsicID()) {
+          default: break;
+          case Intrinsic::lifetime_start:
+          case Intrinsic::lifetime_end:
+            V = II->getArgOperand(1);
+            break;
+        }
+
+    if (!V && hasMemoryWrite(BBI, *TLI) && isRemovable(BBI))
+      V = getStoredPointerOperand(BBI);
+
+    // If we found a store, check to see if it points into a dead stack value.
+    if (V) {
       // See through pointer-to-pointer bitcasts
       SmallVector<Value *, 4> Pointers;
-      GetUnderlyingObjects(getStoredPointerOperand(BBI), Pointers, DL);
+      GetUnderlyingObjects(V, Pointers, DL);
 
       // Stores to stack values are valid candidates for removal.
       bool AllDead = true;
@@ -844,6 +862,15 @@ bool DSE::handleEndBlock(BasicBlock &BB)
       continue;
     }
 
+    if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(BBI))
+      if (II->getIntrinsicID() == Intrinsic::lifetime_start) {
+        // We found a lifetime start for a live object, which we could not
+        // remove. So we must stop removing lifetime intrinsics from this block
+        // because they're useful for stack coloring again
+        canRemoveLifetimeIntrinsics = false;
+        continue;
+      }
+
     if (auto CS = CallSite(BBI)) {
       // Remove allocation function calls from the list of dead stack objects; 
       // there can't be any references before the definition.

Modified: llvm/trunk/test/Transforms/DeadStoreElimination/lifetime.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/DeadStoreElimination/lifetime.ll?rev=245542&r1=245541&r2=245542&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/DeadStoreElimination/lifetime.ll (original)
+++ llvm/trunk/test/Transforms/DeadStoreElimination/lifetime.ll Thu Aug 20 03:25:28 2015
@@ -5,14 +5,16 @@ target datalayout = "E-p:64:64:64-a0:0:8
 declare void @llvm.lifetime.start(i64, i8* nocapture) nounwind
 declare void @llvm.lifetime.end(i64, i8* nocapture) nounwind
 declare void @llvm.memset.p0i8.i8(i8* nocapture, i8, i8, i32, i1) nounwind
+declare void @callee(i8*)
 
 define void @test1() {
 ; CHECK-LABEL: @test1(
   %A = alloca i8
 
   store i8 0, i8* %A  ;; Written to by memset
+; CHECK-NOT: store
   call void @llvm.lifetime.end(i64 1, i8* %A)
-; CHECK: lifetime.end
+; CHECK-NOT: lifetime.end
 
   call void @llvm.memset.p0i8.i8(i8* %A, i8 0, i8 -1, i32 0, i1 false)
 ; CHECK-NOT: memset
@@ -22,7 +24,7 @@ define void @test1() {
 }
 
 define void @test2(i32* %P) {
-; CHECK: test2
+; CHECK-LABEL: test2
   %Q = getelementptr i32, i32* %P, i32 1
   %R = bitcast i32* %Q to i8*
   call void @llvm.lifetime.start(i64 4, i8* %R)
@@ -34,4 +36,51 @@ define void @test2(i32* %P) {
   ret void
 }
 
+define void @test3(i8*) {
+; CHECK-LABEL: test3
+  %a = alloca i8
+  call void @llvm.lifetime.start(i64 1, i8* %a)
+; CHECK-NOT: lifetime.start
+  call void @llvm.lifetime.end(i64 1, i8* %a)
+; CHECK-NOT: lifetime.end
+  call void @llvm.lifetime.start(i64 1, i8* undef)
+; CHECK-NOT: lifetime.start
+  call void @llvm.lifetime.end(i64 1, i8* undef)
+; CHECK-NOT: lifetime.end
+  ret void
+}
+
+define void @test4(i8*) {
+; CHECK-LABEL: test4
+  %a = alloca i8
+  call void @llvm.lifetime.start(i64 1, i8* %a)
+; CHECK: lifetime.start
+  call void @llvm.lifetime.end(i64 1, i8* %a)
+; CHECK: lifetime.end
+  call void @llvm.lifetime.start(i64 1, i8* %0)
+; CHECK: lifetime.start
+  call void @llvm.lifetime.end(i64 1, i8* %0)
+; CHECK: lifetime.end
+  call void @llvm.lifetime.start(i64 1, i8* %a)
+; CHECK-NOT: lifetime.start
+  call void @llvm.lifetime.end(i64 1, i8* %a)
+; CHECK-NOT: lifetime.end
+  ret void
+}
 
+define void @test5() {
+; CHECK-LABEL: test5
+  %a = alloca i8
+  %b = alloca i8
+  call void @llvm.lifetime.start(i64 1, i8* %a)
+; CHECK: lifetime.start
+  call void @llvm.lifetime.end(i64 1, i8* %a)
+; CHECK: lifetime.end
+  call void @llvm.lifetime.start(i64 1, i8* %b)
+; CHECK: lifetime.start
+  call void @callee(i8* %b)
+; CHECK: call void @callee
+  call void @llvm.lifetime.end(i64 1, i8* %b)
+; CHECK-NOT: lifetime.end
+  ret void
+}




More information about the llvm-commits mailing list