diff --git a/compiler/optimizer/LocalOpts.cpp b/compiler/optimizer/LocalOpts.cpp index 9a60f5c27a0..af91b827f95 100644 --- a/compiler/optimizer/LocalOpts.cpp +++ b/compiler/optimizer/LocalOpts.cpp @@ -6695,6 +6695,15 @@ TR::Block *TR_BlockSplitter::splitBlock(TR::Block *pred, TR_LinkHeadAndTailappend(TR::TreeTop::create(comp(), TR::Node::create(lastRealNode, TR::Goto, 0, nextTree))); cfg->addEdge(cloneEnd, newBlock); cfg->addEdge(newBlock, nextTree->getNode()->getBlock()); + // The branch target may be the fall-through path. If so, since we're redirecting the fall-through path to a goto block + // and removing the single edge that represents both the fall-through and branch paths, we should also redirect the branch + // to the goto block. + if (lastRealNode->getBranchDestination()->getNode()->getBlock()->getNumber() == nextTree->getNode()->getBlock()->getNumber()) + { + if (trace()) + traceMsg(comp(), " Redirecting branch %d->%d to %d\n", cloneEnd->getNumber(), nextTree->getNode()->getBlock()->getNumber(), newBlock->getNumber()); + lastRealNode->setBranchDestination(newBlock->getEntry()); + } cfg->removeEdge(cloneEnd, nextTree->getNode()->getBlock()); if (trace()) diff --git a/compiler/optimizer/OMRSimplifierHelpers.cpp b/compiler/optimizer/OMRSimplifierHelpers.cpp index eb4a158bb10..5c45d4fe654 100644 --- a/compiler/optimizer/OMRSimplifierHelpers.cpp +++ b/compiler/optimizer/OMRSimplifierHelpers.cpp @@ -440,6 +440,26 @@ bool branchToFollowingBlock(TR::Node * node, TR::Block * block, TR::Compilation return true; } +bool fallthroughGoesToBranchBlock(TR::Node *node, TR::Block *block, TR::Compilation *comp) + { + TR::Block *fallthroughBlock = block->getNextBlock(); + if (fallthroughBlock == NULL || + !fallthroughBlock->isGotoBlock(comp) || + fallthroughBlock->getPredecessors().size() > 1 || + fallthroughBlock->getExceptionPredecessors().size() > 0 || + fallthroughBlock->getFirstRealTreeTop()->getNode()->getBranchDestination() != node->getBranchDestination()) + return false; + + // If this is an extended basic block there may be real nodes after the + // conditional branch. In this case the conditional branch must remain. + // + TR::TreeTop * treeTop = block->getLastRealTreeTop(); + if (treeTop->getNode() != node) + return false; + + return true; + } + // If the first child is a constant but the second isn't, swap them. // void makeConstantTheRightChild(TR::Node * node, TR::Node * & firstChild, TR::Node * & secondChild, TR::Simplifier * s) @@ -695,6 +715,20 @@ TR::Node *removeIfToFollowingBlock(TR::Node * node, TR::Block * block, TR::Simpl return NULL; } } + if (fallthroughGoesToBranchBlock(node, block, s->comp())) + { + // Immediately following block goes to branch block. The branch can (later) be removed + // + static bool disable = feGetEnv("TR_disableSimplifyIfFallthroughGoto") != NULL; + if (!disable) + { + if (performTransformation(s->comp(), "%sMaking %s [" POINTER_PRINTF_FORMAT "] unconditional to following block\n", s->optDetailString(), node->getOpCode().getName(), node)) + { + s->conditionalToUnconditional(node, block, false); + s->requestOpt(OMR::redundantGotoElimination, true, block); + } + } + } return node; } diff --git a/compiler/optimizer/OMRSimplifierHelpers.hpp b/compiler/optimizer/OMRSimplifierHelpers.hpp index f5d06064ef6..6b8a0aed96c 100644 --- a/compiler/optimizer/OMRSimplifierHelpers.hpp +++ b/compiler/optimizer/OMRSimplifierHelpers.hpp @@ -173,6 +173,7 @@ void orderChildren(TR::Node * node, TR::Node * & firstChild, TR::Node * & second TR::Node *foldRedundantAND(TR::Node * node, TR::ILOpCodes andOpCode, TR::ILOpCodes constOpCode, int64_t andVal, TR::Simplifier * s); TR::Node* tryFoldAndWidened(TR::Simplifier* simplifier, TR::Node* node); bool branchToFollowingBlock(TR::Node * node, TR::Block * block, TR::Compilation *comp); +bool fallthroughGoesToBranchBlock(TR::Node *node, TR::Block *block, TR::Compilation *comp); void makeConstantTheRightChild(TR::Node * node, TR::Node * & firstChild, TR::Node * & secondChild, TR::Simplifier * s); void makeConstantTheRightChildAndSetOpcode(TR::Node * node, TR::Node * & firstChild, TR::Node * & secondChild, TR::Simplifier * s); TR::Node *replaceChild(int32_t childIndex, TR::Node* node, TR::Node* newChild, TR::Simplifier* s);