<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Thanks for reverting this. I think it also caused some LTO failures on green dragon, although I was still trying to reproduce them to make sure.<div class=""><br class=""></div><div class="">More detail is here (<a href="http://lab.llvm.org:8080/green/job/clang-stage2-configure-Rlto_build/8797/consoleFull" class="">http://lab.llvm.org:8080/green/job/clang-stage2-configure-Rlto_build/8797/consoleFull</a>), but were you seeing something like the following?</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><div class="">While deleting: i8* %</div></div><div class=""><div class="">Use still stuck around after Def is destroyed: call void @llvm.lifetime.end(i64 24, i8* nonnull <badref>) #3, !dbg !4862</div></div><div class=""><div class="">Use still stuck around after Def is destroyed: %.pre194 = load i8, i8* <badref>, align 8, !dbg !4799, !tbaa !4501</div></div><div class=""><div class="">Use still stuck around after Def is destroyed: call void @llvm.memset.p0i8.i64(i8* <badref>, i8 0, i64 24, i32 8, i1 false) #3, !dbg !4783, !alias.scope !4791</div></div><div class=""><br class="Apple-interchange-newline"></div><div class="">Assertion failed: (use_empty() && "Uses remain when a value is destroyed!"), function ~Value, file /Users/buildslave/jenkins/sharedspace/phase1@2/llvm/lib/IR/Value.cpp, line 85.</div></blockquote><div class=""><br class=""></div>Cheers,<div class="">Pete<br class=""><div class=""><div><blockquote type="cite" class=""><div class="">On May 2, 2016, at 12:43 PM, Reid Kleckner via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org" class="">llvm-commits@lists.llvm.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="">Author: rnk<br class="">Date: Mon May 2 14:43:22 2016<br class="">New Revision: 268288<br class=""><br class="">URL: <a href="http://llvm.org/viewvc/llvm-project?rev=268288&view=rev" class="">http://llvm.org/viewvc/llvm-project?rev=268288&view=rev</a><br class="">Log:<br class="">Revert "[SimplifyCFG] Extend TryToSimplifyUncondBranchFromEmptyBlock for empty block including lifetime intrinsics"<br class=""><br class="">This reverts commit r268254.<br class=""><br class="">This change causes assertion failures while building Chromium. Reduced<br class="">test case coming soon.<br class=""><br class="">Modified:<br class=""> llvm/trunk/include/llvm/IR/BasicBlock.h<br class=""> llvm/trunk/lib/IR/BasicBlock.cpp<br class=""> llvm/trunk/lib/Transforms/Utils/Local.cpp<br class=""> llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp<br class=""> llvm/trunk/test/Transforms/SimplifyCFG/lifetime.ll<br class=""><br class="">Modified: llvm/trunk/include/llvm/IR/BasicBlock.h<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/BasicBlock.h?rev=268288&r1=268287&r2=268288&view=diff" class="">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/BasicBlock.h?rev=268288&r1=268287&r2=268288&view=diff</a><br class="">==============================================================================<br class="">--- llvm/trunk/include/llvm/IR/BasicBlock.h (original)<br class="">+++ llvm/trunk/include/llvm/IR/BasicBlock.h Mon May 2 14:43:22 2016<br class="">@@ -152,15 +152,6 @@ public:<br class=""> return const_cast<BasicBlock*>(this)->getFirstNonPHIOrDbgOrLifetime();<br class=""> }<br class=""><br class="">- /// \brief Returns a pointer to the first instruction in this block that is<br class="">- /// not a PHINode, a debug intrinsic, a lifetime intrinsic, or a bitcast<br class="">- /// instruction coupled with the following lifetime intrinsic.<br class="">- Instruction *getFirstNonPHIOrDbgOrLifetimeOrBitCast();<br class="">- const Instruction *getFirstNonPHIOrDbgOrLifetimeOrBitCast() const {<br class="">- return const_cast<BasicBlock *>(this)<br class="">- ->getFirstNonPHIOrDbgOrLifetimeOrBitCast();<br class="">- }<br class="">-<br class=""> /// \brief Returns an iterator to the first instruction in this block that is<br class=""> /// suitable for inserting a non-PHI instruction.<br class=""> ///<br class=""><br class="">Modified: llvm/trunk/lib/IR/BasicBlock.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/BasicBlock.cpp?rev=268288&r1=268287&r2=268288&view=diff" class="">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/BasicBlock.cpp?rev=268288&r1=268287&r2=268288&view=diff</a><br class="">==============================================================================<br class="">--- llvm/trunk/lib/IR/BasicBlock.cpp (original)<br class="">+++ llvm/trunk/lib/IR/BasicBlock.cpp Mon May 2 14:43:22 2016<br class="">@@ -206,30 +206,6 @@ Instruction* BasicBlock::getFirstNonPHIO<br class=""> return nullptr;<br class=""> }<br class=""><br class="">-Instruction *BasicBlock::getFirstNonPHIOrDbgOrLifetimeOrBitCast() {<br class="">- for (Instruction &I : *this) {<br class="">- if (isa<PHINode>(I) || isa<DbgInfoIntrinsic>(I))<br class="">- continue;<br class="">-<br class="">- if (auto *II = dyn_cast<IntrinsicInst>(&I))<br class="">- if (II->getIntrinsicID() == Intrinsic::lifetime_start ||<br class="">- II->getIntrinsicID() == Intrinsic::lifetime_end)<br class="">- continue;<br class="">-<br class="">- if (auto *BCI = dyn_cast<BitCastInst>(&I)) {<br class="">- if (auto *II = dyn_cast<IntrinsicInst>(++I.getIterator())) {<br class="">- if ((II->getIntrinsicID() == Intrinsic::lifetime_start ||<br class="">- II->getIntrinsicID() == Intrinsic::lifetime_end) &&<br class="">- II->getOperand(1) == BCI) {<br class="">- continue;<br class="">- }<br class="">- }<br class="">- }<br class="">- return &I;<br class="">- }<br class="">- return nullptr;<br class="">-}<br class="">-<br class=""> BasicBlock::iterator BasicBlock::getFirstInsertionPt() {<br class=""> Instruction *FirstNonPHI = getFirstNonPHI();<br class=""> if (!FirstNonPHI)<br class=""><br class="">Modified: llvm/trunk/lib/Transforms/Utils/Local.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/Local.cpp?rev=268288&r1=268287&r2=268288&view=diff" class="">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/Local.cpp?rev=268288&r1=268287&r2=268288&view=diff</a><br class="">==============================================================================<br class="">--- llvm/trunk/lib/Transforms/Utils/Local.cpp (original)<br class="">+++ llvm/trunk/lib/Transforms/Utils/Local.cpp Mon May 2 14:43:22 2016<br class="">@@ -800,55 +800,6 @@ static void redirectValuesFromPredecesso<br class=""> replaceUndefValuesInPhi(PN, IncomingValues);<br class=""> }<br class=""><br class="">-/// Return true if BB has lifetime.end intrinsic.<br class="">-///<br class="">-static bool hasLifetime(BasicBlock *BB) {<br class="">- for (auto &I : *BB) {<br class="">- if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I)) {<br class="">- if (II->getIntrinsicID() == Intrinsic::lifetime_end ||<br class="">- II->getIntrinsicID() == Intrinsic::lifetime_start) {<br class="">- return true;<br class="">- }<br class="">- }<br class="">- }<br class="">- return false;<br class="">-}<br class="">-<br class="">-/// hoistLifetimeFromEmptyBlockToPred - Hoist lifetime.end intrinsics and<br class="">-/// related bitcast instructions from BB to predecessors of BB.<br class="">-///<br class="">-static bool hoistLifetimeFromEmptyBlockToPred(BasicBlock *BB) {<br class="">- // Check to see if all Preds have single successor and if not, we cannot<br class="">- // hoist lifetime intrinsics because it would change semantics.<br class="">- for (auto Pred : predecessors(BB))<br class="">- if (!Pred->getSingleSuccessor())<br class="">- return false;<br class="">-<br class="">- // Hoist all lifetime.end intrinsics and related bitcast instrunctions<br class="">- // in BB to Preds.<br class="">- for (auto &I : *BB) {<br class="">- if (auto *II = dyn_cast<IntrinsicInst>(&I)) {<br class="">- if (II->getIntrinsicID() == Intrinsic::lifetime_end ||<br class="">- II->getIntrinsicID() == Intrinsic::lifetime_start) {<br class="">- for (auto Pred : predecessors(BB)) {<br class="">- Instruction *NewII = I.clone();<br class="">- NewII->insertBefore(Pred->getTerminator());<br class="">-<br class="">- if (I.getIterator() != BB->begin()) {<br class="">- if (auto BC = dyn_cast<BitCastInst>(--I.getIterator())) {<br class="">- assert(BC == I.getOperand(1));<br class="">- auto NewBC = BC->clone();<br class="">- NewBC->insertBefore(NewII);<br class="">- NewII->setOperand(1, NewBC);<br class="">- }<br class="">- }<br class="">- }<br class="">- }<br class="">- }<br class="">- }<br class="">- return true;<br class="">-}<br class="">-<br class=""> /// TryToSimplifyUncondBranchFromEmptyBlock - BB is known to contain an<br class=""> /// unconditional branch, and contains no instructions other than PHI nodes,<br class=""> /// potential side-effect free intrinsics and the branch. If possible,<br class="">@@ -862,118 +813,74 @@ bool llvm::TryToSimplifyUncondBranchFrom<br class=""> BasicBlock *Succ = cast<BranchInst>(BB->getTerminator())->getSuccessor(0);<br class=""> if (BB == Succ) return false;<br class=""><br class="">- // If BB has lifetime.end intrinsics, simplify BB under more constraints.<br class="">- if (hasLifetime(BB)) {<br class="">- // Check to see if BB and its predecessors and successors have PHI.<br class="">- if (isa<PHINode>(BB->begin()))<br class="">- return false;<br class="">-<br class="">- for (auto Pred : predecessors(BB))<br class="">- if (isa<PHINode>(Pred->begin()))<br class="">- return false;<br class="">-<br class="">- for (auto Succ : successors(BB))<br class="">- if (isa<PHINode>(Succ->begin()))<br class="">- return false;<br class="">-<br class="">- if (Succ->getSinglePredecessor()) {<br class="">- // BB is the only predecessor of Succ, so Succ will end up with exactly<br class="">- // the same predecessors BB had.<br class="">-<br class="">- // Copy over any debug or lifetime instruction.<br class="">- BB->getTerminator()->eraseFromParent();<br class="">- Succ->getInstList().splice(Succ->getFirstNonPHI()->getIterator(),<br class="">- BB->getInstList());<br class="">-<br class="">- } else {<br class="">- // Unless BB is the only predecessor of Succ, hoist lifetime intrinsics<br class="">- // to predecessors of BB and simplify BB.<br class="">- if (!hoistLifetimeFromEmptyBlockToPred(BB)) {<br class="">- return false;<br class="">- }<br class="">- }<br class="">-<br class="">- DEBUG(dbgs() << "Killing Trivial BB: \n" << *BB);<br class="">-<br class="">- // Everything that jumped to BB now goes to Succ.<br class="">- BB->replaceAllUsesWith(Succ);<br class="">- if (!Succ->hasName())<br class="">- Succ->takeName(BB);<br class="">- BB->eraseFromParent(); // Delete the old basic block.<br class="">- return true;<br class="">- } else {<br class="">- // Check to see if merging these blocks would cause conflicts for any of the<br class="">- // phi nodes in BB or Succ. If not, we can safely merge.<br class="">- if (!CanPropagatePredecessorsForPHIs(BB, Succ))<br class="">- return false;<br class="">-<br class="">- // Check for cases where Succ has multiple predecessors and a PHI node in BB<br class="">- // has uses which will not disappear when the PHI nodes are merged. It is<br class="">- // possible to handle such cases, but difficult: it requires checking<br class="">- // whether BB dominates Succ, which is non-trivial to calculate in the<br class="">- // case where Succ has multiple predecessors. Also, it requires checking<br class="">- // whether constructing the necessary self-referential PHI node doesn't<br class="">- // introduce any conflicts; this isn't too difficult, but the previous code<br class="">- // for doing this was incorrect.<br class="">- //<br class="">- // Note that if this check finds a live use, BB dominates Succ, so BB is<br class="">- // something like a loop pre-header (or rarely, a part of an irreducible<br class="">- // CFG);<br class="">- // folding the branch isn't profitable in that case anyway.<br class="">- if (!Succ->getSinglePredecessor()) {<br class="">- BasicBlock::iterator BBI = BB->begin();<br class="">- while (isa<PHINode>(*BBI)) {<br class="">- for (Use &U : BBI->uses()) {<br class="">- if (PHINode *PN = dyn_cast<PHINode>(U.getUser())) {<br class="">- if (PN->getIncomingBlock(U) != BB)<br class="">- return false;<br class="">- } else {<br class="">+ // Check to see if merging these blocks would cause conflicts for any of the<br class="">+ // phi nodes in BB or Succ. If not, we can safely merge.<br class="">+ if (!CanPropagatePredecessorsForPHIs(BB, Succ)) return false;<br class="">+<br class="">+ // Check for cases where Succ has multiple predecessors and a PHI node in BB<br class="">+ // has uses which will not disappear when the PHI nodes are merged. It is<br class="">+ // possible to handle such cases, but difficult: it requires checking whether<br class="">+ // BB dominates Succ, which is non-trivial to calculate in the case where<br class="">+ // Succ has multiple predecessors. Also, it requires checking whether<br class="">+ // constructing the necessary self-referential PHI node doesn't introduce any<br class="">+ // conflicts; this isn't too difficult, but the previous code for doing this<br class="">+ // was incorrect.<br class="">+ //<br class="">+ // Note that if this check finds a live use, BB dominates Succ, so BB is<br class="">+ // something like a loop pre-header (or rarely, a part of an irreducible CFG);<br class="">+ // folding the branch isn't profitable in that case anyway.<br class="">+ if (!Succ->getSinglePredecessor()) {<br class="">+ BasicBlock::iterator BBI = BB->begin();<br class="">+ while (isa<PHINode>(*BBI)) {<br class="">+ for (Use &U : BBI->uses()) {<br class="">+ if (PHINode* PN = dyn_cast<PHINode>(U.getUser())) {<br class="">+ if (PN->getIncomingBlock(U) != BB)<br class=""> return false;<br class="">- }<br class="">+ } else {<br class="">+ return false;<br class=""> }<br class="">- ++BBI;<br class=""> }<br class="">+ ++BBI;<br class=""> }<br class="">+ }<br class=""><br class="">- DEBUG(dbgs() << "Killing Trivial BB: \n" << *BB);<br class="">+ DEBUG(dbgs() << "Killing Trivial BB: \n" << *BB);<br class=""><br class="">- if (isa<PHINode>(Succ->begin())) {<br class="">- // If there is more than one pred of succ, and there are PHI nodes in<br class="">- // the successor, then we need to add incoming edges for the PHI nodes<br class="">- //<br class="">- const PredBlockVector BBPreds(pred_begin(BB), pred_end(BB));<br class="">-<br class="">- // Loop over all of the PHI nodes in the successor of BB.<br class="">- for (BasicBlock::iterator I = Succ->begin(); isa<PHINode>(I); ++I) {<br class="">- PHINode *PN = cast<PHINode>(I);<br class="">+ if (isa<PHINode>(Succ->begin())) {<br class="">+ // If there is more than one pred of succ, and there are PHI nodes in<br class="">+ // the successor, then we need to add incoming edges for the PHI nodes<br class="">+ //<br class="">+ const PredBlockVector BBPreds(pred_begin(BB), pred_end(BB));<br class=""><br class="">- redirectValuesFromPredecessorsToPhi(BB, BBPreds, PN);<br class="">- }<br class="">- }<br class="">+ // Loop over all of the PHI nodes in the successor of BB.<br class="">+ for (BasicBlock::iterator I = Succ->begin(); isa<PHINode>(I); ++I) {<br class="">+ PHINode *PN = cast<PHINode>(I);<br class=""><br class="">- if (Succ->getSinglePredecessor()) {<br class="">- // BB is the only predecessor of Succ, so Succ will end up with exactly<br class="">- // the same predecessors BB had.<br class="">-<br class="">- // Copy over any phi, debug or lifetime instruction.<br class="">- BB->getTerminator()->eraseFromParent();<br class="">- Succ->getInstList().splice(Succ->getFirstNonPHI()->getIterator(),<br class="">- BB->getInstList());<br class="">- } else {<br class="">- while (PHINode *PN = dyn_cast<PHINode>(&BB->front())) {<br class="">- // We explicitly check for such uses in CanPropagatePredecessorsForPHIs.<br class="">- assert(PN->use_empty() && "There shouldn't be any uses here!");<br class="">- PN->eraseFromParent();<br class="">- }<br class="">+ redirectValuesFromPredecessorsToPhi(BB, BBPreds, PN);<br class=""> }<br class="">+ }<br class=""><br class="">- // Everything that jumped to BB now goes to Succ.<br class="">- BB->replaceAllUsesWith(Succ);<br class="">- if (!Succ->hasName())<br class="">- Succ->takeName(BB);<br class="">- BB->eraseFromParent(); // Delete the old basic block.<br class="">- return true;<br class="">+ if (Succ->getSinglePredecessor()) {<br class="">+ // BB is the only predecessor of Succ, so Succ will end up with exactly<br class="">+ // the same predecessors BB had.<br class="">+<br class="">+ // Copy over any phi, debug or lifetime instruction.<br class="">+ BB->getTerminator()->eraseFromParent();<br class="">+ Succ->getInstList().splice(Succ->getFirstNonPHI()->getIterator(),<br class="">+ BB->getInstList());<br class="">+ } else {<br class="">+ while (PHINode *PN = dyn_cast<PHINode>(&BB->front())) {<br class="">+ // We explicitly check for such uses in CanPropagatePredecessorsForPHIs.<br class="">+ assert(PN->use_empty() && "There shouldn't be any uses here!");<br class="">+ PN->eraseFromParent();<br class="">+ }<br class=""> }<br class="">+<br class="">+ // Everything that jumped to BB now goes to Succ.<br class="">+ BB->replaceAllUsesWith(Succ);<br class="">+ if (!Succ->hasName()) Succ->takeName(BB);<br class="">+ BB->eraseFromParent(); // Delete the old basic block.<br class="">+ return true;<br class=""> }<br class=""><br class=""> /// EliminateDuplicatePHINodes - Check for and eliminate duplicate PHI<br class=""><br class="">Modified: llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp?rev=268288&r1=268287&r2=268288&view=diff" class="">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp?rev=268288&r1=268287&r2=268288&view=diff</a><br class="">==============================================================================<br class="">--- llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp (original)<br class="">+++ llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp Mon May 2 14:43:22 2016<br class="">@@ -5056,15 +5056,14 @@ bool SimplifyCFGOpt::SimplifyUncondBranc<br class=""><br class=""> if (SinkCommon && SinkThenElseCodeToEnd(BI))<br class=""> return true;<br class="">- // If the Terminator is the only non-phi instruction except for bitcast<br class="">- // instruction coupled with the following lifetime intrinsic, simplify the<br class="">- // block. If LoopHeader is provided, check if the block is a loop header<br class="">+<br class="">+ // If the Terminator is the only non-phi instruction, simplify the block.<br class="">+ // if LoopHeader is provided, check if the block is a loop header<br class=""> // (This is for early invocations before loop simplify and vectorization<br class=""> // to keep canonical loop forms for nested loops.<br class=""> // These blocks can be eliminated when the pass is invoked later<br class=""> // in the back-end.)<br class="">- BasicBlock::iterator I =<br class="">- BB->getFirstNonPHIOrDbgOrLifetimeOrBitCast()->getIterator();<br class="">+ BasicBlock::iterator I = BB->getFirstNonPHIOrDbg()->getIterator();<br class=""> if (I->isTerminator() && BB != &BB->getParent()->getEntryBlock() &&<br class=""> (!LoopHeaders || !LoopHeaders->count(BB)) &&<br class=""> TryToSimplifyUncondBranchFromEmptyBlock(BB))<br class=""><br class="">Modified: llvm/trunk/test/Transforms/SimplifyCFG/lifetime.ll<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/lifetime.ll?rev=268288&r1=268287&r2=268288&view=diff" class="">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/lifetime.ll?rev=268288&r1=268287&r2=268288&view=diff</a><br class="">==============================================================================<br class="">--- llvm/trunk/test/Transforms/SimplifyCFG/lifetime.ll (original)<br class="">+++ llvm/trunk/test/Transforms/SimplifyCFG/lifetime.ll Mon May 2 14:43:22 2016<br class="">@@ -1,9 +1,6 @@<br class=""> ; RUN: opt < %s -simplifycfg -S | FileCheck %s<br class=""><br class=""> ; Test that a lifetime intrinsic isn't removed because that would change semantics<br class="">-; This case is that predecessor(s) of the target empty block (bb0) has multiple<br class="">-; successors (bb0 and bb1) and its successor has multiple predecessors (entry and<br class="">-; bb0).<br class=""><br class=""> ; CHECK: foo<br class=""> ; CHECK: entry:<br class="">@@ -30,232 +27,3 @@ declare void @f()<br class=""> declare void @llvm.lifetime.start(i64, i8* nocapture) nounwind<br class=""><br class=""> declare void @llvm.lifetime.end(i64, i8* nocapture) nounwind<br class="">-<br class="">-; Test that empty block including lifetime intrinsic and not related bitcast<br class="">-; instruction cannot be removed. It is because the block is not empty.<br class="">- <br class="">-; CHECK-LABEL: coo<br class="">-; CHECK-LABEL: entry:<br class="">-; CHECK-LABEL: if.then:<br class="">-; CHECK-LABEL: if.else:<br class="">-; CHECK-LABEL: if.end:<br class="">-; CHECK-LABEL: bb:<br class="">-; CHECK: ret<br class="">-<br class="">-define void @coo(i1 %x, i1 %y) {<br class="">-entry:<br class="">- %a = alloca i8, align 4<br class="">- %b = alloca i32, align 4<br class="">- br label %while.cond<br class="">-<br class="">-while.cond: ; preds = %if.end, %entry<br class="">- br i1 %y, label %while.body, label %bb<br class="">-<br class="">-while.body: ; preds = %while.cond<br class="">- call void @llvm.lifetime.start(i64 4, i8* %a)<br class="">- %c = load i8, i8* %a, align 4<br class="">- br i1 %x, label %if.then, label %if.else<br class="">-<br class="">-if.then: ; preds = %while.body<br class="">- %d = add i8 %c, 1<br class="">- br label %if.end<br class="">-<br class="">-if.else: ; preds = %while.body<br class="">- %e = sub i8 %c, 1<br class="">- br label %if.end<br class="">-<br class="">-if.end: ; preds = %if.else, %if.then<br class="">- %f = bitcast i32* %b to i8*<br class="">- call void @llvm.lifetime.end(i64 4, i8* %a)<br class="">- br label %while.cond<br class="">-<br class="">-bb: ; preds = %while.cond<br class="">- ret void<br class="">-}<br class="">-<br class="">-; Test that empty block including lifetime intrinsic can be removed.<br class="">-; Lifetime.end intrinsic is moved to predecessors because successor has <br class="">-; multiple predecessors.<br class="">-<br class="">-; CHECK-LABEL: soo<br class="">-; CHECK-LABEL: entry:<br class="">-; CHECK-LABEL: if.then:<br class="">-; CHECK-NEXT: %e<br class="">-; CHECK-NEXT: call void @llvm.lifetime.end<br class="">-; CHECK-LABEL: if.else:<br class="">-; CHECK-NEXT: %g<br class="">-; CHECK-NEXT: call void @llvm.lifetime.end<br class="">-; CHECK-NEXT: br label %while.cond<br class="">-; CHECK-NOT: if.end:<br class="">-; CHECK: ret<br class="">-<br class="">-define void @soo(i1 %x, i1 %y) {<br class="">-entry:<br class="">- %a = alloca i8, align 4<br class="">- br label %while.cond<br class="">-<br class="">-while.cond: ; preds = %if.end, %entry<br class="">- br i1 %y, label %while.body, label %bb<br class="">-<br class="">-while.body: ; preds = %while.cond<br class="">- call void @llvm.lifetime.start(i64 4, i8* %a)<br class="">- %d = load i8, i8* %a, align 4<br class="">- br i1 %x, label %if.then, label %if.else<br class="">-<br class="">-if.then: ; preds = %while.body<br class="">- %e = add i8 %d, 1<br class="">- br label %if.end<br class="">-<br class="">-if.else: ; preds = %while.body<br class="">- %g = sub i8 %d, 1<br class="">- br label %if.end<br class="">-<br class="">-if.end: ; preds = %if.else, %if.then<br class="">- call void @llvm.lifetime.end(i64 4, i8* %a)<br class="">- br label %while.cond<br class="">-<br class="">-bb: ; preds = %while.cond<br class="">- ret void<br class="">-}<br class="">-<br class="">-; Test that empty block including lifetime intrinsic and related bitcast<br class="">-; instruction can be removed. Lifetime.end intrinsic and related bitcast <br class="">-; instruction are moved to predecessors because successor has multiple<br class="">-; predecessors.<br class="">-<br class="">-; CHECK-LABEL: boo<br class="">-; CHECK-LABEL: entry:<br class="">-; CHECK-LABEL: if.then:<br class="">-; CHECK-NEXT: %e<br class="">-; CHECK-NEXT: %[[T:[^ ]+]] = bitcast<br class="">-; CHECK-NEXT: call void @llvm.lifetime.end(i64 4, i8* %[[T]])<br class="">-; CHECK-LABEL: if.else:<br class="">-; CHECK-NEXT: %g<br class="">-; CHECK-NEXT: %[[B:[^ ]+]] = bitcast<br class="">-; CHECK-NEXT: call void @llvm.lifetime.end(i64 4, i8* %[[B]])<br class="">-; CHECK-NEXT: br label %while.cond<br class="">-; CHECK-NOT: if.end:<br class="">-; CHECK: ret<br class="">-<br class="">-define void @boo(i1 %x, i1 %y) {<br class="">-entry:<br class="">- %a = alloca i32, align 4<br class="">- br label %while.cond<br class="">-<br class="">-while.cond: ; preds = %if.end, %entry<br class="">- br i1 %y, label %while.body, label %bb<br class="">-<br class="">-while.body: ; preds = %while.cond<br class="">- %b = bitcast i32* %a to i8*<br class="">- call void @llvm.lifetime.start(i64 4, i8* %b)<br class="">- %d = load i32, i32* %a, align 4<br class="">- br i1 %x, label %if.then, label %if.else<br class="">-<br class="">-if.then: ; preds = %while.body<br class="">- %e = add i32 %d, 1<br class="">- br label %if.end<br class="">-<br class="">-if.else: ; preds = %while.body<br class="">- %g = sub i32 %d, 1<br class="">- br label %if.end<br class="">-<br class="">-if.end: ; preds = %if.else, %if.then<br class="">- %c = bitcast i32* %a to i8*<br class="">- call void @llvm.lifetime.end(i64 4, i8* %c)<br class="">- br label %while.cond<br class="">-<br class="">-bb: ; preds = %while.cond<br class="">- ret void<br class="">-}<br class="">-<br class="">-; Test that empty block including lifetime intrinsic can be removed.<br class="">-; Lifetime.start intrinsic is moved to predecessors because successor has <br class="">-; multiple predecessors.<br class="">-<br class="">-; CHECK-LABEL: koo<br class="">-; CHECK-LABEL: entry:<br class="">-; CHECK-LABEL: if.then:<br class="">-; CHECK-NEXT: call void @f<br class="">-; CHECK-NEXT: call void @llvm.lifetime.start<br class="">-; CHECK-LABEL: if.else:<br class="">-; CHECK-NEXT: call void @g<br class="">-; CHECK-NEXT: call void @llvm.lifetime.start<br class="">-; CHECK-NEXT: br label %bb<br class="">-; CHECK-NOT: if.end:<br class="">-; CHECK: ret<br class="">-<br class="">-define void @koo(i1 %x, i1 %y, i1 %z) {<br class="">-entry:<br class="">- %a = alloca i8, align 4<br class="">- br i1 %z, label %bb, label %bb0<br class="">-<br class="">-bb0: ; preds = %entry<br class="">- br i1 %x, label %if.then, label %if.else<br class="">-<br class="">-if.then: ; preds = %bb0<br class="">- call void @f()<br class="">- br label %if.end<br class="">-<br class="">-if.else: ; preds = %bb0<br class="">- call void @g()<br class="">- br label %if.end<br class="">-<br class="">-if.end: ; preds = %if.else, %if.then<br class="">- call void @llvm.lifetime.start(i64 4, i8* %a)<br class="">- br label %bb<br class="">-<br class="">-bb: ; preds = %if.end, %entry<br class="">- %d = load i8, i8* %a, align 4<br class="">- call void @llvm.lifetime.end(i64 4, i8* %a)<br class="">- ret void<br class="">-}<br class="">-<br class="">-declare void @g()<br class="">-<br class="">-; Test that empty block including lifetime intrinsic and related bitcast<br class="">-; instruction can be removed. Lifetime.start intrinsic and related bitcast <br class="">-; instruction are moved to predecessors because successor has multiple<br class="">-; predecessors.<br class="">-<br class="">-<br class="">-; CHECK-LABEL: goo<br class="">-; CHECK-LABEL: entry:<br class="">-; CHECK-LABEL: if.then:<br class="">-; CHECK-NEXT: call void @f<br class="">-; CHECK-NEXT: %[[T:[^ ]+]] = bitcast<br class="">-; CHECK-NEXT: call void @llvm.lifetime.start(i64 4, i8* %[[T]])<br class="">-; CHECK-LABEL: if.else:<br class="">-; CHECK-NEXT: call void @g<br class="">-; CHECK-NEXT: %[[B:[^ ]+]] = bitcast<br class="">-; CHECK-NEXT: call void @llvm.lifetime.start(i64 4, i8* %[[B]])<br class="">-; CHECK-NEXT: br label %bb<br class="">-; CHECK-NOT: if.end:<br class="">-; CHECK: ret<br class="">-<br class="">-define void @goo(i1 %x, i1 %y, i1 %z) {<br class="">-entry:<br class="">- %a = alloca i32, align 4<br class="">- br i1 %z, label %bb, label %bb0<br class="">-<br class="">-bb0: ; preds = %entry<br class="">- br i1 %x, label %if.then, label %if.else<br class="">-<br class="">-if.then: ; preds = %bb0<br class="">- call void @f()<br class="">- br label %if.end<br class="">-<br class="">-if.else: ; preds = %bb0<br class="">- call void @g()<br class="">- br label %if.end<br class="">-<br class="">-if.end: ; preds = %if.else, %if.then<br class="">- %b = bitcast i32* %a to i8*<br class="">- call void @llvm.lifetime.start(i64 4, i8* %b)<br class="">- br label %bb<br class="">-<br class="">-bb: ; preds = %if.end, %entry<br class="">- %d = load i32, i32* %a, align 4<br class="">- %c = bitcast i32* %a to i8*<br class="">- call void @llvm.lifetime.end(i64 4, i8* %c)<br class="">- ret void<br class="">-}<br class=""><br class=""><br class="">_______________________________________________<br class="">llvm-commits mailing list<br class=""><a href="mailto:llvm-commits@lists.llvm.org" class="">llvm-commits@lists.llvm.org</a><br class="">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits<br class=""></div></div></blockquote></div><br class=""></div></div></body></html>