<div dir="ltr">We are seeing assertion failures while building Chromium related to this change:<div><a href="https://build.chromium.org/p/chromium.fyi/builders/ClangToTLinuxASan/builds/4019/steps/compile/logs/stdio">https://build.chromium.org/p/chromium.fyi/builders/ClangToTLinuxASan/builds/4019/steps/compile/logs/stdio</a><br></div><div><br></div><div>The uses related to lifetime start / end make me suspect this change, as well as TryToSimplifyUncondBranchFromEmptyBlock, so I'm going to speculatively revert for now while I look for a test case.</div><div><br></div><div><div>FAILED: obj/base/files/base.file_posix.o </div><div>...</div><div>While deleting: i8* %</div><div>Use still stuck around after Def is destroyed:  call void @llvm.lifetime.end(i64 4, i8* <badref>) #11, !dbg !129</div><div>Use still stuck around after Def is destroyed:  call void @llvm.lifetime.end(i64 4, i8* <badref>) #11, !dbg !129</div><div>clang-3.9: /b/build/slave/ClangToTLinuxASan/build/src/third_party/llvm/lib/IR/Value.cpp:85: virtual llvm::Value::~Value(): Assertion `use_empty() && "Uses remain when a value is destroyed!"' failed.</div><div>0  clang-3.9       0x0000000001a1c945 llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 37</div><div>1  clang-3.9       0x0000000001a1a6d6 llvm::sys::RunSignalHandlers() + 54</div><div>2  clang-3.9       0x0000000001a1a901</div><div>3  libpthread.so.0 0x00007f753c5c2cb0</div><div>4  libc.so.6       0x00007f753b7ff0d5 gsignal + 53</div><div>5  libc.so.6       0x00007f753b80283b abort + 379</div><div>6  libc.so.6       0x00007f753b7f7d9e</div><div>7  libc.so.6       0x00007f753b7f7e42</div><div>8  clang-3.9       0x00000000016d6d0f</div><div>9  clang-3.9       0x0000000001679437</div><div>10 clang-3.9       0x00000000016161fc llvm::BasicBlock::~BasicBlock() + 140</div><div>11 clang-3.9       0x00000000016163b9 llvm::BasicBlock::~BasicBlock() + 9</div><div>12 clang-3.9       0x0000000001616722 llvm::BasicBlock::eraseFromParent() + 114</div><div>13 clang-3.9       0x0000000001a6b0d3 llvm::TryToSimplifyUncondBranchFromEmptyBlock(llvm::BasicBlock*) + 3923</div><div>14 clang-3.9       0x0000000001ab74ea llvm::SimplifyCFG(llvm::BasicBlock*, llvm::TargetTransformInfo const&, unsigned int, llvm::AssumptionCache*, llvm::SmallPtrSetImpl<llvm::BasicBlock*>*) + 7914</div><div>15 clang-3.9       0x0000000001994c2d</div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, May 2, 2016 at 10:22 AM, Hans Wennborg via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: hans<br>
Date: Mon May  2 12:22:54 2016<br>
New Revision: 268254<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=268254&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=268254&view=rev</a><br>
Log:<br>
[SimplifyCFG] Extend TryToSimplifyUncondBranchFromEmptyBlock for empty block including lifetime intrinsics<br>
<br>
Make it possible that TryToSimplifyUncondBranchFromEmptyBlock merges empty<br>
basic block including lifetime intrinsics as well as phi nodes and<br>
unconditional branch into its successor or predecessor(s).<br>
<br>
If successor of empty block has single predecessor, all contents including<br>
lifetime intrinsics are sinked into the successor. Otherwise, they are<br>
hoisted into its predecessor(s) and then merged into the predecessor(s).<br>
<br>
Patch by Josh Yoon <<a href="mailto:josh.yoon@samsung.com">josh.yoon@samsung.com</a>>!<br>
<br>
Differential Revision: <a href="http://reviews.llvm.org/D19257" rel="noreferrer" target="_blank">http://reviews.llvm.org/D19257</a><br>
<br>
Modified:<br>
    llvm/trunk/include/llvm/IR/BasicBlock.h<br>
    llvm/trunk/lib/IR/BasicBlock.cpp<br>
    llvm/trunk/lib/Transforms/Utils/Local.cpp<br>
    llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp<br>
    llvm/trunk/test/Transforms/SimplifyCFG/lifetime.ll<br>
<br>
Modified: llvm/trunk/include/llvm/IR/BasicBlock.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/BasicBlock.h?rev=268254&r1=268253&r2=268254&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/BasicBlock.h?rev=268254&r1=268253&r2=268254&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/IR/BasicBlock.h (original)<br>
+++ llvm/trunk/include/llvm/IR/BasicBlock.h Mon May  2 12:22:54 2016<br>
@@ -152,6 +152,15 @@ public:<br>
     return const_cast<BasicBlock*>(this)->getFirstNonPHIOrDbgOrLifetime();<br>
   }<br>
<br>
+  /// \brief Returns a pointer to the first instruction in this block that is<br>
+  /// not a PHINode, a debug intrinsic, a lifetime intrinsic, or a bitcast<br>
+  /// instruction coupled with the following lifetime intrinsic.<br>
+  Instruction *getFirstNonPHIOrDbgOrLifetimeOrBitCast();<br>
+  const Instruction *getFirstNonPHIOrDbgOrLifetimeOrBitCast() const {<br>
+    return const_cast<BasicBlock *>(this)<br>
+        ->getFirstNonPHIOrDbgOrLifetimeOrBitCast();<br>
+  }<br>
+<br>
   /// \brief Returns an iterator to the first instruction in this block that is<br>
   /// suitable for inserting a non-PHI instruction.<br>
   ///<br>
<br>
Modified: llvm/trunk/lib/IR/BasicBlock.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/BasicBlock.cpp?rev=268254&r1=268253&r2=268254&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/BasicBlock.cpp?rev=268254&r1=268253&r2=268254&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/IR/BasicBlock.cpp (original)<br>
+++ llvm/trunk/lib/IR/BasicBlock.cpp Mon May  2 12:22:54 2016<br>
@@ -206,6 +206,30 @@ Instruction* BasicBlock::getFirstNonPHIO<br>
   return nullptr;<br>
 }<br>
<br>
+Instruction *BasicBlock::getFirstNonPHIOrDbgOrLifetimeOrBitCast() {<br>
+  for (Instruction &I : *this) {<br>
+    if (isa<PHINode>(I) || isa<DbgInfoIntrinsic>(I))<br>
+      continue;<br>
+<br>
+    if (auto *II = dyn_cast<IntrinsicInst>(&I))<br>
+      if (II->getIntrinsicID() == Intrinsic::lifetime_start ||<br>
+          II->getIntrinsicID() == Intrinsic::lifetime_end)<br>
+        continue;<br>
+<br>
+    if (auto *BCI = dyn_cast<BitCastInst>(&I)) {<br>
+      if (auto *II = dyn_cast<IntrinsicInst>(++I.getIterator())) {<br>
+        if ((II->getIntrinsicID() == Intrinsic::lifetime_start ||<br>
+             II->getIntrinsicID() == Intrinsic::lifetime_end) &&<br>
+            II->getOperand(1) == BCI) {<br>
+          continue;<br>
+        }<br>
+      }<br>
+    }<br>
+    return &I;<br>
+  }<br>
+  return nullptr;<br>
+}<br>
+<br>
 BasicBlock::iterator BasicBlock::getFirstInsertionPt() {<br>
   Instruction *FirstNonPHI = getFirstNonPHI();<br>
   if (!FirstNonPHI)<br>
<br>
Modified: llvm/trunk/lib/Transforms/Utils/Local.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/Local.cpp?rev=268254&r1=268253&r2=268254&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/Local.cpp?rev=268254&r1=268253&r2=268254&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/Utils/Local.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Utils/Local.cpp Mon May  2 12:22:54 2016<br>
@@ -800,6 +800,55 @@ static void redirectValuesFromPredecesso<br>
   replaceUndefValuesInPhi(PN, IncomingValues);<br>
 }<br>
<br>
+/// Return true if BB has lifetime.end intrinsic.<br>
+///<br>
+static bool hasLifetime(BasicBlock *BB) {<br>
+  for (auto &I : *BB) {<br>
+    if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I)) {<br>
+      if (II->getIntrinsicID() == Intrinsic::lifetime_end ||<br>
+          II->getIntrinsicID() == Intrinsic::lifetime_start) {<br>
+        return true;<br>
+      }<br>
+    }<br>
+  }<br>
+  return false;<br>
+}<br>
+<br>
+/// hoistLifetimeFromEmptyBlockToPred - Hoist lifetime.end intrinsics and<br>
+/// related bitcast instructions from BB to predecessors of BB.<br>
+///<br>
+static bool hoistLifetimeFromEmptyBlockToPred(BasicBlock *BB) {<br>
+  // Check to see if all Preds have single successor and if not, we cannot<br>
+  // hoist lifetime intrinsics because it would change semantics.<br>
+  for (auto Pred : predecessors(BB))<br>
+    if (!Pred->getSingleSuccessor())<br>
+      return false;<br>
+<br>
+  // Hoist all lifetime.end intrinsics and related bitcast instrunctions<br>
+  // in BB to Preds.<br>
+  for (auto &I : *BB) {<br>
+    if (auto *II = dyn_cast<IntrinsicInst>(&I)) {<br>
+      if (II->getIntrinsicID() == Intrinsic::lifetime_end ||<br>
+          II->getIntrinsicID() == Intrinsic::lifetime_start) {<br>
+        for (auto Pred : predecessors(BB)) {<br>
+          Instruction *NewII = I.clone();<br>
+          NewII->insertBefore(Pred->getTerminator());<br>
+<br>
+          if (I.getIterator() != BB->begin()) {<br>
+            if (auto BC = dyn_cast<BitCastInst>(--I.getIterator())) {<br>
+              assert(BC == I.getOperand(1));<br>
+              auto NewBC = BC->clone();<br>
+              NewBC->insertBefore(NewII);<br>
+              NewII->setOperand(1, NewBC);<br>
+            }<br>
+          }<br>
+        }<br>
+      }<br>
+    }<br>
+  }<br>
+  return true;<br>
+}<br>
+<br>
 /// TryToSimplifyUncondBranchFromEmptyBlock - BB is known to contain an<br>
 /// unconditional branch, and contains no instructions other than PHI nodes,<br>
 /// potential side-effect free intrinsics and the branch.  If possible,<br>
@@ -813,74 +862,118 @@ bool llvm::TryToSimplifyUncondBranchFrom<br>
   BasicBlock *Succ = cast<BranchInst>(BB->getTerminator())->getSuccessor(0);<br>
   if (BB == Succ) return false;<br>
<br>
-  // Check to see if merging these blocks would cause conflicts for any of the<br>
-  // phi nodes in BB or Succ. If not, we can safely merge.<br>
-  if (!CanPropagatePredecessorsForPHIs(BB, Succ)) return false;<br>
-<br>
-  // Check for cases where Succ has multiple predecessors and a PHI node in BB<br>
-  // has uses which will not disappear when the PHI nodes are merged.  It is<br>
-  // possible to handle such cases, but difficult: it requires checking whether<br>
-  // BB dominates Succ, which is non-trivial to calculate in the case where<br>
-  // Succ has multiple predecessors.  Also, it requires checking whether<br>
-  // constructing the necessary self-referential PHI node doesn't introduce any<br>
-  // conflicts; this isn't too difficult, but the previous code for doing this<br>
-  // was incorrect.<br>
-  //<br>
-  // Note that if this check finds a live use, BB dominates Succ, so BB is<br>
-  // something like a loop pre-header (or rarely, a part of an irreducible CFG);<br>
-  // folding the branch isn't profitable in that case anyway.<br>
-  if (!Succ->getSinglePredecessor()) {<br>
-    BasicBlock::iterator BBI = BB->begin();<br>
-    while (isa<PHINode>(*BBI)) {<br>
-      for (Use &U : BBI->uses()) {<br>
-        if (PHINode* PN = dyn_cast<PHINode>(U.getUser())) {<br>
-          if (PN->getIncomingBlock(U) != BB)<br>
-            return false;<br>
-        } else {<br>
-          return false;<br>
-        }<br>
+  // If BB has lifetime.end intrinsics, simplify BB under more constraints.<br>
+  if (hasLifetime(BB)) {<br>
+    // Check to see if BB and its predecessors and successors have PHI.<br>
+    if (isa<PHINode>(BB->begin()))<br>
+      return false;<br>
+<br>
+    for (auto Pred : predecessors(BB))<br>
+      if (isa<PHINode>(Pred->begin()))<br>
+        return false;<br>
+<br>
+    for (auto Succ : successors(BB))<br>
+      if (isa<PHINode>(Succ->begin()))<br>
+        return false;<br>
+<br>
+    if (Succ->getSinglePredecessor()) {<br>
+      // BB is the only predecessor of Succ, so Succ will end up with exactly<br>
+      // the same predecessors BB had.<br>
+<br>
+      // Copy over any debug or lifetime instruction.<br>
+      BB->getTerminator()->eraseFromParent();<br>
+      Succ->getInstList().splice(Succ->getFirstNonPHI()->getIterator(),<br>
+                                 BB->getInstList());<br>
+<br>
+    } else {<br>
+      // Unless BB is the only predecessor of Succ, hoist lifetime intrinsics<br>
+      // to predecessors of BB and simplify BB.<br>
+      if (!hoistLifetimeFromEmptyBlockToPred(BB)) {<br>
+        return false;<br>
       }<br>
-      ++BBI;<br>
     }<br>
-  }<br>
<br>
-  DEBUG(dbgs() << "Killing Trivial BB: \n" << *BB);<br>
+    DEBUG(dbgs() << "Killing Trivial BB: \n" << *BB);<br>
<br>
-  if (isa<PHINode>(Succ->begin())) {<br>
-    // If there is more than one pred of succ, and there are PHI nodes in<br>
-    // the successor, then we need to add incoming edges for the PHI nodes<br>
+    // Everything that jumped to BB now goes to Succ.<br>
+    BB->replaceAllUsesWith(Succ);<br>
+    if (!Succ->hasName())<br>
+      Succ->takeName(BB);<br>
+    BB->eraseFromParent(); // Delete the old basic block.<br>
+    return true;<br>
+  } else {<br>
+    // Check to see if merging these blocks would cause conflicts for any of the<br>
+    // phi nodes in BB or Succ. If not, we can safely merge.<br>
+    if (!CanPropagatePredecessorsForPHIs(BB, Succ))<br>
+      return false;<br>
+<br>
+    // Check for cases where Succ has multiple predecessors and a PHI node in BB<br>
+    // has uses which will not disappear when the PHI nodes are merged.  It is<br>
+    // possible to handle such cases, but difficult: it requires checking<br>
+    // whether BB dominates Succ, which is non-trivial to calculate in the<br>
+    // case where Succ has multiple predecessors.  Also, it requires checking<br>
+    // whether constructing the necessary self-referential PHI node doesn't<br>
+    // introduce any conflicts; this isn't too difficult, but the previous code<br>
+    // for doing this was incorrect.<br>
     //<br>
-    const PredBlockVector BBPreds(pred_begin(BB), pred_end(BB));<br>
+    // Note that if this check finds a live use, BB dominates Succ, so BB is<br>
+    // something like a loop pre-header (or rarely, a part of an irreducible<br>
+    // CFG);<br>
+    // folding the branch isn't profitable in that case anyway.<br>
+    if (!Succ->getSinglePredecessor()) {<br>
+      BasicBlock::iterator BBI = BB->begin();<br>
+      while (isa<PHINode>(*BBI)) {<br>
+        for (Use &U : BBI->uses()) {<br>
+          if (PHINode *PN = dyn_cast<PHINode>(U.getUser())) {<br>
+            if (PN->getIncomingBlock(U) != BB)<br>
+              return false;<br>
+          } else {<br>
+            return false;<br>
+          }<br>
+        }<br>
+        ++BBI;<br>
+      }<br>
+    }<br>
+<br>
+    DEBUG(dbgs() << "Killing Trivial BB: \n" << *BB);<br>
<br>
-    // Loop over all of the PHI nodes in the successor of BB.<br>
-    for (BasicBlock::iterator I = Succ->begin(); isa<PHINode>(I); ++I) {<br>
-      PHINode *PN = cast<PHINode>(I);<br>
+    if (isa<PHINode>(Succ->begin())) {<br>
+      // If there is more than one pred of succ, and there are PHI nodes in<br>
+      // the successor, then we need to add incoming edges for the PHI nodes<br>
+      //<br>
+      const PredBlockVector BBPreds(pred_begin(BB), pred_end(BB));<br>
+<br>
+      // Loop over all of the PHI nodes in the successor of BB.<br>
+      for (BasicBlock::iterator I = Succ->begin(); isa<PHINode>(I); ++I) {<br>
+        PHINode *PN = cast<PHINode>(I);<br>
<br>
-      redirectValuesFromPredecessorsToPhi(BB, BBPreds, PN);<br>
+        redirectValuesFromPredecessorsToPhi(BB, BBPreds, PN);<br>
+      }<br>
     }<br>
-  }<br>
<br>
-  if (Succ->getSinglePredecessor()) {<br>
-    // BB is the only predecessor of Succ, so Succ will end up with exactly<br>
-    // the same predecessors BB had.<br>
-<br>
-    // Copy over any phi, debug or lifetime instruction.<br>
-    BB->getTerminator()->eraseFromParent();<br>
-    Succ->getInstList().splice(Succ->getFirstNonPHI()->getIterator(),<br>
-                               BB->getInstList());<br>
-  } else {<br>
-    while (PHINode *PN = dyn_cast<PHINode>(&BB->front())) {<br>
-      // We explicitly check for such uses in CanPropagatePredecessorsForPHIs.<br>
-      assert(PN->use_empty() && "There shouldn't be any uses here!");<br>
-      PN->eraseFromParent();<br>
+    if (Succ->getSinglePredecessor()) {<br>
+      // BB is the only predecessor of Succ, so Succ will end up with exactly<br>
+      // the same predecessors BB had.<br>
+<br>
+      // Copy over any phi, debug or lifetime instruction.<br>
+      BB->getTerminator()->eraseFromParent();<br>
+      Succ->getInstList().splice(Succ->getFirstNonPHI()->getIterator(),<br>
+                                 BB->getInstList());<br>
+    } else {<br>
+      while (PHINode *PN = dyn_cast<PHINode>(&BB->front())) {<br>
+        // We explicitly check for such uses in CanPropagatePredecessorsForPHIs.<br>
+        assert(PN->use_empty() && "There shouldn't be any uses here!");<br>
+        PN->eraseFromParent();<br>
+      }<br>
     }<br>
-  }<br>
<br>
-  // Everything that jumped to BB now goes to Succ.<br>
-  BB->replaceAllUsesWith(Succ);<br>
-  if (!Succ->hasName()) Succ->takeName(BB);<br>
-  BB->eraseFromParent();              // Delete the old basic block.<br>
-  return true;<br>
+    // Everything that jumped to BB now goes to Succ.<br>
+    BB->replaceAllUsesWith(Succ);<br>
+    if (!Succ->hasName())<br>
+      Succ->takeName(BB);<br>
+    BB->eraseFromParent(); // Delete the old basic block.<br>
+    return true;<br>
+  }<br>
 }<br>
<br>
 /// EliminateDuplicatePHINodes - Check for and eliminate duplicate PHI<br>
<br>
Modified: llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp?rev=268254&r1=268253&r2=268254&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp?rev=268254&r1=268253&r2=268254&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp Mon May  2 12:22:54 2016<br>
@@ -5056,14 +5056,15 @@ bool SimplifyCFGOpt::SimplifyUncondBranc<br>
<br>
   if (SinkCommon && SinkThenElseCodeToEnd(BI))<br>
     return true;<br>
-<br>
-  // If the Terminator is the only non-phi instruction, simplify the block.<br>
-  // if LoopHeader is provided, check if the block is a loop header<br>
+  // If the Terminator is the only non-phi instruction except for bitcast<br>
+  // instruction coupled with the following lifetime intrinsic, simplify the<br>
+  // block. If LoopHeader is provided, check if the block is a loop header<br>
   // (This is for early invocations before loop simplify and vectorization<br>
   // to keep canonical loop forms for nested loops.<br>
   // These blocks can be eliminated when the pass is invoked later<br>
   // in the back-end.)<br>
-  BasicBlock::iterator I = BB->getFirstNonPHIOrDbg()->getIterator();<br>
+  BasicBlock::iterator I =<br>
+      BB->getFirstNonPHIOrDbgOrLifetimeOrBitCast()->getIterator();<br>
   if (I->isTerminator() && BB != &BB->getParent()->getEntryBlock() &&<br>
       (!LoopHeaders || !LoopHeaders->count(BB)) &&<br>
       TryToSimplifyUncondBranchFromEmptyBlock(BB))<br>
<br>
Modified: llvm/trunk/test/Transforms/SimplifyCFG/lifetime.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/lifetime.ll?rev=268254&r1=268253&r2=268254&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/lifetime.ll?rev=268254&r1=268253&r2=268254&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Transforms/SimplifyCFG/lifetime.ll (original)<br>
+++ llvm/trunk/test/Transforms/SimplifyCFG/lifetime.ll Mon May  2 12:22:54 2016<br>
@@ -1,6 +1,9 @@<br>
 ; RUN: opt < %s -simplifycfg -S | FileCheck %s<br>
<br>
 ; Test that a lifetime intrinsic isn't removed because that would change semantics<br>
+; This case is that predecessor(s) of the target empty block (bb0) has multiple<br>
+; successors (bb0 and bb1) and its successor has multiple predecessors (entry and<br>
+; bb0).<br>
<br>
 ; CHECK: foo<br>
 ; CHECK: entry:<br>
@@ -27,3 +30,232 @@ declare void @f()<br>
 declare void @llvm.lifetime.start(i64, i8* nocapture) nounwind<br>
<br>
 declare void @llvm.lifetime.end(i64, i8* nocapture) nounwind<br>
+<br>
+; Test that empty block including lifetime intrinsic and not related bitcast<br>
+; instruction cannot be removed. It is because the block is not empty.<br>
+<br>
+; CHECK-LABEL: coo<br>
+; CHECK-LABEL: entry:<br>
+; CHECK-LABEL: if.then:<br>
+; CHECK-LABEL: if.else:<br>
+; CHECK-LABEL: if.end:<br>
+; CHECK-LABEL: bb:<br>
+; CHECK: ret<br>
+<br>
+define void @coo(i1 %x, i1 %y) {<br>
+entry:<br>
+  %a = alloca i8, align 4<br>
+  %b = alloca i32, align 4<br>
+  br label %while.cond<br>
+<br>
+while.cond:                                       ; preds = %if.end, %entry<br>
+  br i1 %y, label %while.body, label %bb<br>
+<br>
+while.body:                                       ; preds = %while.cond<br>
+  call void @llvm.lifetime.start(i64 4, i8* %a)<br>
+  %c = load i8, i8* %a, align 4<br>
+  br i1 %x, label %if.then, label %if.else<br>
+<br>
+if.then:                                          ; preds = %while.body<br>
+  %d = add i8 %c, 1<br>
+  br label %if.end<br>
+<br>
+if.else:                                          ; preds = %while.body<br>
+  %e = sub i8 %c, 1<br>
+  br label %if.end<br>
+<br>
+if.end:                                           ; preds = %if.else, %if.then<br>
+  %f = bitcast i32* %b to i8*<br>
+  call void @llvm.lifetime.end(i64 4, i8* %a)<br>
+  br label %while.cond<br>
+<br>
+bb:                                               ; preds = %while.cond<br>
+  ret void<br>
+}<br>
+<br>
+; Test that empty block including lifetime intrinsic can be removed.<br>
+; Lifetime.end intrinsic is moved to predecessors because successor has<br>
+; multiple predecessors.<br>
+<br>
+; CHECK-LABEL: soo<br>
+; CHECK-LABEL: entry:<br>
+; CHECK-LABEL: if.then:<br>
+; CHECK-NEXT: %e<br>
+; CHECK-NEXT: call void @llvm.lifetime.end<br>
+; CHECK-LABEL: if.else:<br>
+; CHECK-NEXT: %g<br>
+; CHECK-NEXT: call void @llvm.lifetime.end<br>
+; CHECK-NEXT: br label %while.cond<br>
+; CHECK-NOT: if.end:<br>
+; CHECK: ret<br>
+<br>
+define void @soo(i1 %x, i1 %y) {<br>
+entry:<br>
+  %a = alloca i8, align 4<br>
+  br label %while.cond<br>
+<br>
+while.cond:                                       ; preds = %if.end, %entry<br>
+  br i1 %y, label %while.body, label %bb<br>
+<br>
+while.body:                                       ; preds = %while.cond<br>
+  call void @llvm.lifetime.start(i64 4, i8* %a)<br>
+  %d = load i8, i8* %a, align 4<br>
+  br i1 %x, label %if.then, label %if.else<br>
+<br>
+if.then:                                          ; preds = %while.body<br>
+  %e = add i8 %d, 1<br>
+  br label %if.end<br>
+<br>
+if.else:                                          ; preds = %while.body<br>
+  %g = sub i8 %d, 1<br>
+  br label %if.end<br>
+<br>
+if.end:                                           ; preds = %if.else, %if.then<br>
+  call void @llvm.lifetime.end(i64 4, i8* %a)<br>
+  br label %while.cond<br>
+<br>
+bb:                                               ; preds = %while.cond<br>
+  ret void<br>
+}<br>
+<br>
+; Test that empty block including lifetime intrinsic and related bitcast<br>
+; instruction can be removed. Lifetime.end intrinsic and related bitcast<br>
+; instruction are moved to predecessors because successor has multiple<br>
+; predecessors.<br>
+<br>
+; CHECK-LABEL: boo<br>
+; CHECK-LABEL: entry:<br>
+; CHECK-LABEL: if.then:<br>
+; CHECK-NEXT: %e<br>
+; CHECK-NEXT: %[[T:[^ ]+]] = bitcast<br>
+; CHECK-NEXT: call void @llvm.lifetime.end(i64 4, i8* %[[T]])<br>
+; CHECK-LABEL: if.else:<br>
+; CHECK-NEXT: %g<br>
+; CHECK-NEXT: %[[B:[^ ]+]] = bitcast<br>
+; CHECK-NEXT: call void @llvm.lifetime.end(i64 4, i8* %[[B]])<br>
+; CHECK-NEXT: br label %while.cond<br>
+; CHECK-NOT: if.end:<br>
+; CHECK: ret<br>
+<br>
+define void @boo(i1 %x, i1 %y) {<br>
+entry:<br>
+  %a = alloca i32, align 4<br>
+  br label %while.cond<br>
+<br>
+while.cond:                                       ; preds = %if.end, %entry<br>
+  br i1 %y, label %while.body, label %bb<br>
+<br>
+while.body:                                       ; preds = %while.cond<br>
+  %b = bitcast i32* %a to i8*<br>
+  call void @llvm.lifetime.start(i64 4, i8* %b)<br>
+  %d = load i32, i32* %a, align 4<br>
+  br i1 %x, label %if.then, label %if.else<br>
+<br>
+if.then:                                          ; preds = %while.body<br>
+  %e = add i32 %d, 1<br>
+  br label %if.end<br>
+<br>
+if.else:                                          ; preds = %while.body<br>
+  %g = sub i32 %d, 1<br>
+  br label %if.end<br>
+<br>
+if.end:                                           ; preds = %if.else, %if.then<br>
+  %c = bitcast i32* %a to i8*<br>
+  call void @llvm.lifetime.end(i64 4, i8* %c)<br>
+  br label %while.cond<br>
+<br>
+bb:                                               ; preds = %while.cond<br>
+  ret void<br>
+}<br>
+<br>
+; Test that empty block including lifetime intrinsic can be removed.<br>
+; Lifetime.start intrinsic is moved to predecessors because successor has<br>
+; multiple predecessors.<br>
+<br>
+; CHECK-LABEL: koo<br>
+; CHECK-LABEL: entry:<br>
+; CHECK-LABEL: if.then:<br>
+; CHECK-NEXT: call void @f<br>
+; CHECK-NEXT: call void @llvm.lifetime.start<br>
+; CHECK-LABEL: if.else:<br>
+; CHECK-NEXT: call void @g<br>
+; CHECK-NEXT: call void @llvm.lifetime.start<br>
+; CHECK-NEXT: br label %bb<br>
+; CHECK-NOT: if.end:<br>
+; CHECK: ret<br>
+<br>
+define void @koo(i1 %x, i1 %y, i1 %z) {<br>
+entry:<br>
+  %a = alloca i8, align 4<br>
+  br i1 %z, label %bb, label %bb0<br>
+<br>
+bb0:                                              ; preds = %entry<br>
+  br i1 %x, label %if.then, label %if.else<br>
+<br>
+if.then:                                          ; preds = %bb0<br>
+  call void @f()<br>
+  br label %if.end<br>
+<br>
+if.else:                                          ; preds = %bb0<br>
+  call void @g()<br>
+  br label %if.end<br>
+<br>
+if.end:                                           ; preds = %if.else, %if.then<br>
+  call void @llvm.lifetime.start(i64 4, i8* %a)<br>
+  br label %bb<br>
+<br>
+bb:                                               ; preds = %if.end, %entry<br>
+  %d = load i8, i8* %a, align 4<br>
+  call void @llvm.lifetime.end(i64 4, i8* %a)<br>
+  ret void<br>
+}<br>
+<br>
+declare void @g()<br>
+<br>
+; Test that empty block including lifetime intrinsic and related bitcast<br>
+; instruction can be removed. Lifetime.start intrinsic and related bitcast<br>
+; instruction are moved to predecessors because successor has multiple<br>
+; predecessors.<br>
+<br>
+<br>
+; CHECK-LABEL: goo<br>
+; CHECK-LABEL: entry:<br>
+; CHECK-LABEL: if.then:<br>
+; CHECK-NEXT: call void @f<br>
+; CHECK-NEXT: %[[T:[^ ]+]] = bitcast<br>
+; CHECK-NEXT: call void @llvm.lifetime.start(i64 4, i8* %[[T]])<br>
+; CHECK-LABEL: if.else:<br>
+; CHECK-NEXT: call void @g<br>
+; CHECK-NEXT: %[[B:[^ ]+]] = bitcast<br>
+; CHECK-NEXT: call void @llvm.lifetime.start(i64 4, i8* %[[B]])<br>
+; CHECK-NEXT: br label %bb<br>
+; CHECK-NOT: if.end:<br>
+; CHECK: ret<br>
+<br>
+define void @goo(i1 %x, i1 %y, i1 %z) {<br>
+entry:<br>
+  %a = alloca i32, align 4<br>
+  br i1 %z, label %bb, label %bb0<br>
+<br>
+bb0:                                              ; preds = %entry<br>
+  br i1 %x, label %if.then, label %if.else<br>
+<br>
+if.then:                                          ; preds = %bb0<br>
+  call void @f()<br>
+  br label %if.end<br>
+<br>
+if.else:                                          ; preds = %bb0<br>
+  call void @g()<br>
+  br label %if.end<br>
+<br>
+if.end:                                           ; preds = %if.else, %if.then<br>
+  %b = bitcast i32* %a to i8*<br>
+  call void @llvm.lifetime.start(i64 4, i8* %b)<br>
+  br label %bb<br>
+<br>
+bb:                                               ; preds = %if.end, %entry<br>
+  %d = load i32, i32* %a, align 4<br>
+  %c = bitcast i32* %a to i8*<br>
+  call void @llvm.lifetime.end(i64 4, i8* %c)<br>
+  ret void<br>
+}<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>