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