From b7efa6c22777539be1e63a76988ed030cf264599 Mon Sep 17 00:00:00 2001 From: James Molloy Date: Wed, 31 Aug 2016 12:33:48 +0000 Subject: [SimplifyCFG] Fix bootstrap failure after r280220 We check that a sinking candidate is used by only one PHI node during our legality checks. However for instructions that are used by other sinking candidates our heuristic is less conservative. This can result in a candidate actually being illegal when we come to sink it because of how we sunk a predecessor. Do the used-by-only-one-PHI checks again during sinking to ensure we don't crash. llvm-svn: 280228 --- llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) (limited to 'llvm/lib/Transforms/Utils/SimplifyCFG.cpp') diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp index 3de6c6069a8..537bc7678c6 100644 --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -1444,7 +1444,7 @@ static bool canSinkInstructions( // Assuming canSinkLastInstruction(Blocks) has returned true, sink the last // instruction of every block in Blocks to their common successor, commoning // into one instruction. -static void sinkLastInstruction(ArrayRef Blocks) { +static bool sinkLastInstruction(ArrayRef Blocks) { auto *BBEnd = Blocks[0]->getTerminator()->getSuccessor(0); // canSinkLastInstruction returning true guarantees that every block has at @@ -1453,9 +1453,22 @@ static void sinkLastInstruction(ArrayRef Blocks) { for (auto *BB : Blocks) Insts.push_back(BB->getTerminator()->getPrevNode()); - // We don't need to do any checking here; canSinkLastInstruction should have - // done it all for us. + // The only checking we need to do now is that all users of all instructions + // are the same PHI node. canSinkLastInstruction should have checked this but + // it is slightly over-aggressive - it gets confused by commutative instructions + // so double-check it here. Instruction *I0 = Insts.front(); + if (!isa(I0)) { + auto *PNUse = dyn_cast(*I0->user_begin()); + if (!all_of(Insts, [&PNUse](const Instruction *I) -> bool { + auto *U = cast(*I->user_begin()); + return U == PNUse || U->getParent() == I->getParent(); + })) + return false; + } + + // We don't need to do any more checking here; canSinkLastInstruction should + // have done it all for us. SmallVector NewOperands; for (unsigned O = 0, E = I0->getNumOperands(); O != E; ++O) { // This check is different to that in canSinkLastInstruction. There, we @@ -1507,6 +1520,8 @@ static void sinkLastInstruction(ArrayRef Blocks) { for (auto *I : Insts) if (I != I0) I->eraseFromParent(); + + return true; } namespace { @@ -1639,7 +1654,7 @@ static bool SinkThenElseCodeToEnd(BranchInst *BI1) { LockstepReverseIterator LRI(UnconditionalPreds); while (LRI.isValid() && canSinkInstructions(*LRI, PHIOperands)) { - DEBUG(dbgs() << "SINK: instruction can be sunk: " << (*LRI)[0] << "\n"); + DEBUG(dbgs() << "SINK: instruction can be sunk: " << *(*LRI)[0] << "\n"); InstructionsToSink.insert((*LRI).begin(), (*LRI).end()); ++ScanIdx; --LRI; @@ -1698,7 +1713,8 @@ static bool SinkThenElseCodeToEnd(BranchInst *BI1) { break; } - sinkLastInstruction(UnconditionalPreds); + if (!sinkLastInstruction(UnconditionalPreds)) + return Changed; NumSinkCommons++; Changed = true; } -- cgit v1.2.3