Teach DSE to eliminate useless trampolines.
authorDuncan Sands <baldrick@free.fr>
Tue, 10 Nov 2009 13:49:50 +0000 (13:49 +0000)
committerDuncan Sands <baldrick@free.fr>
Tue, 10 Nov 2009 13:49:50 +0000 (13:49 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@86683 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/DeadStoreElimination.cpp
test/Transforms/DeadStoreElimination/2009-11-10-Trampoline.ll [new file with mode: 0644]

index 4dd0e91f9089326f34c04495b20f8fe082d5373b..ae25d38718df4bd0742623fea124adea6e704f0a 100644 (file)
@@ -87,13 +87,13 @@ static bool doesClobberMemory(Instruction *I) {
     switch (II->getIntrinsicID()) {
     default: return false;
     case Intrinsic::memset: case Intrinsic::memmove: case Intrinsic::memcpy:
-    case Intrinsic::lifetime_end: return true;
+    case Intrinsic::init_trampoline: case Intrinsic::lifetime_end: return true;
     }
   }
   return false;
 }
 
-/// isElidable - If the memory this instruction and the memory it writes to is
+/// isElidable - If the value of this instruction and the memory it writes to is
 /// unused, may we delete this instrtction?
 static bool isElidable(Instruction *I) {
   assert(doesClobberMemory(I));
@@ -111,8 +111,15 @@ static Value *getPointerOperand(Instruction *I) {
     return SI->getPointerOperand();
   if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(I))
     return MI->getOperand(1);
-  assert(cast<IntrinsicInst>(I)->getIntrinsicID() == Intrinsic::lifetime_end);
-  return cast<IntrinsicInst>(I)->getOperand(2);
+  IntrinsicInst *II = cast<IntrinsicInst>(I);
+  switch (II->getIntrinsicID()) {
+    default:
+      assert(false && "Unexpected intrinsic!");
+    case Intrinsic::init_trampoline:
+      return II->getOperand(1);
+    case Intrinsic::lifetime_end:
+      return II->getOperand(2);
+  }
 }
 
 /// getStoreSize - Return the length in bytes of the write by the clobbering
@@ -129,8 +136,14 @@ static unsigned getStoreSize(Instruction *I, const TargetData *TD) {
     Len = MI->getLength();
   } else {
     IntrinsicInst *II = cast<IntrinsicInst>(I);
-    assert(II->getIntrinsicID() == Intrinsic::lifetime_end);
-    Len = II->getOperand(0);
+    switch (II->getIntrinsicID()) {
+      default:
+        assert(false && "Unexpected intrinsic!");
+      case Intrinsic::init_trampoline:
+        return -1u;
+      case Intrinsic::lifetime_end:
+        Len = II->getOperand(0);
+    }
   }
   if (ConstantInt *LenCI = dyn_cast<ConstantInt>(Len))
     if (!LenCI->isAllOnesValue())
diff --git a/test/Transforms/DeadStoreElimination/2009-11-10-Trampoline.ll b/test/Transforms/DeadStoreElimination/2009-11-10-Trampoline.ll
new file mode 100644 (file)
index 0000000..9a943b4
--- /dev/null
@@ -0,0 +1,16 @@
+; RUN: opt -S -dse < %s | FileCheck %s
+
+declare i8* @llvm.init.trampoline(i8*, i8*, i8*)
+
+declare void @f()
+
+define void @unused_trampoline() {
+; CHECK: @unused_trampoline
+       %storage = alloca [10 x i8], align 16           ; <[10 x i8]*> [#uses=1]
+; CHECK-NOT: alloca
+       %cast = getelementptr [10 x i8]* %storage, i32 0, i32 0         ; <i8*> [#uses=1]
+       %tramp = call i8* @llvm.init.trampoline( i8* %cast, i8* bitcast (void ()* @f to i8*), i8* null )                ; <i8*> [#uses=1]
+; CHECK-NOT: trampoline
+       ret void
+; CHECK: ret void
+}