summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/Scalar/JumpThreading.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/Scalar/JumpThreading.cpp')
-rw-r--r--llvm/lib/Transforms/Scalar/JumpThreading.cpp27
1 files changed, 27 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/Scalar/JumpThreading.cpp b/llvm/lib/Transforms/Scalar/JumpThreading.cpp
index 08eb95a1a3d..5d193c54282 100644
--- a/llvm/lib/Transforms/Scalar/JumpThreading.cpp
+++ b/llvm/lib/Transforms/Scalar/JumpThreading.cpp
@@ -1289,6 +1289,33 @@ bool JumpThreadingPass::ProcessThreadableEdges(Value *Cond, BasicBlock *BB,
if (PredToDestList.empty())
return false;
+ // If all the predecessors go to a single known successor, we want to fold,
+ // not thread. By doing so, we do not need to duplicate the current block and
+ // also miss potential opportunities in case we don't/can't duplicate.
+ if (OnlyDest && OnlyDest != MultipleDestSentinel) {
+ if (PredToDestList.size() ==
+ (size_t)std::distance(pred_begin(BB), pred_end(BB))) {
+ for (BasicBlock *SuccBB : successors(BB)) {
+ if (SuccBB != OnlyDest)
+ SuccBB->removePredecessor(BB, true); // This is unreachable successor.
+ }
+
+ // Finally update the terminator.
+ TerminatorInst *Term = BB->getTerminator();
+ BranchInst::Create(OnlyDest, Term);
+ Term->eraseFromParent();
+
+ // If the condition is now dead due to the removal of the old terminator,
+ // erase it.
+ auto *CondInst = dyn_cast<Instruction>(Cond);
+ if (CondInst && CondInst->use_empty())
+ CondInst->eraseFromParent();
+ // FIXME: in case this instruction is defined in the current BB and it
+ // resolves to a single value from all predecessors, we can do RAUW.
+ return true;
+ }
+ }
+
// Determine which is the most common successor. If we have many inputs and
// this block is a switch, we want to start by threading the batch that goes
// to the most popular destination first. If we only know about one
OpenPOWER on IntegriCloud