Teach InstCombine that lifetime intrincs aren't a real user on the result of a
authorNick Lewycky <nicholas@mxc.ca>
Tue, 2 Aug 2011 22:08:01 +0000 (22:08 +0000)
committerNick Lewycky <nicholas@mxc.ca>
Tue, 2 Aug 2011 22:08:01 +0000 (22:08 +0000)
malloc call.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@136732 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/InstCombine/InstructionCombining.cpp
test/Transforms/InstCombine/malloc-free-delete.ll

index b4a2e2a1d22287ab37f21e94648ec63627161760..5b763c0b07a485ee975a9edd4c03f5f86aaa6ac5 100644 (file)
@@ -1043,7 +1043,10 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) {
 
 
 
-static bool IsOnlyNullComparedAndFreed(const Value &V) {
+static bool IsOnlyNullComparedAndFreed(const Value &V, int Depth = 0) {
+  if (Depth == 8)
+    return false;
+
   for (Value::const_use_iterator UI = V.use_begin(), UE = V.use_end();
        UI != UE; ++UI) {
     const User *U = *UI;
@@ -1052,6 +1055,20 @@ static bool IsOnlyNullComparedAndFreed(const Value &V) {
     if (const ICmpInst *ICI = dyn_cast<ICmpInst>(U))
       if (ICI->isEquality() && isa<ConstantPointerNull>(ICI->getOperand(1)))
         continue;
+    if (const BitCastInst *BCI = dyn_cast<BitCastInst>(U)) {
+      if (IsOnlyNullComparedAndFreed(*BCI, Depth+1))
+        continue;
+    }
+    if (const GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(U)) {
+      if (GEPI->hasAllZeroIndices() &&
+          IsOnlyNullComparedAndFreed(*GEPI, Depth+1))
+        continue;
+    }
+    if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(U)) {
+      if (II->getIntrinsicID() == Intrinsic::lifetime_start ||
+          II->getIntrinsicID() == Intrinsic::lifetime_end)
+        continue;
+    }
     return false;
   }
   return true;
@@ -1064,22 +1081,29 @@ Instruction *InstCombiner::visitMalloc(Instruction &MI) {
   if (IsOnlyNullComparedAndFreed(MI)) {
     for (Value::use_iterator UI = MI.use_begin(), UE = MI.use_end();
          UI != UE;) {
-      // We can assume that every remaining use is a free call or an icmp eq/ne
-      // to null, so the cast is safe.
+      // All the users permitted by IsOnlyNullComparedAndFreed are Instructions.
       Instruction *I = cast<Instruction>(*UI);
 
       // Early increment here, as we're about to get rid of the user.
       ++UI;
 
-      if (isFreeCall(I)) {
-        EraseInstFromFunction(*cast<CallInst>(I));
-        continue;
+      if (CallInst *CI = isFreeCall(I)) {
+        if (CI != I)
+          EraseInstFromFunction(*CI);
+        EraseInstFromFunction(*I);
+      } else if (ICmpInst *C = dyn_cast<ICmpInst>(I)) {
+        ReplaceInstUsesWith(*C,
+                            ConstantInt::get(Type::getInt1Ty(C->getContext()),
+                                             C->isFalseWhenEqual()));
+        EraseInstFromFunction(*C);
+      } else if (I->getType()->isVoidTy()) {
+        // An all-zero GEP or a bitcast.
+        ReplaceInstUsesWith(*I, UndefValue::get(I->getType()));
+        EraseInstFromFunction(*I);
+      } else {
+        // A lifetime intrinsic.
+        EraseInstFromFunction(*I);
       }
-      // Again, the cast is safe.
-      ICmpInst *C = cast<ICmpInst>(I);
-      ReplaceInstUsesWith(*C, ConstantInt::get(Type::getInt1Ty(C->getContext()),
-                                               C->isFalseWhenEqual()));
-      EraseInstFromFunction(*C);
     }
     return EraseInstFromFunction(MI);
   }
index 8455300c98cad13536bbf45beff09fc5d1f5fdba..a35e7b646a489c1c119a2c222b51f8e342065c5d 100644 (file)
@@ -12,7 +12,7 @@ define i32 @main(i32 %argc, i8** %argv) {
 ; CHECK: ret i32 0
 }
 
-declare i8* @malloc(i32)
+declare noalias i8* @malloc(i32)
 declare void @free(i8*)
 
 define i1 @foo() {
@@ -23,3 +23,15 @@ define i1 @foo() {
   call void @free(i8* %m)
   ret i1 %z
 }
+
+declare void @llvm.lifetime.start(i64, i8*)
+declare void @llvm.lifetime.end(i64, i8*)
+
+define void @test3() {
+; CHECK: @test3
+; CHECK-NEXT: ret void
+  %a = call noalias i8* @malloc(i32 10)
+  call void @llvm.lifetime.start(i64 10, i8* %a)
+  call void @llvm.lifetime.end(i64 10, i8* %a)
+  ret void
+}