static void removeGlRegDep(TR::Node * parent, TR_GlobalRegisterNumber registerNum, TR::Block *containingBlock, TR::Optimization *opt) { if (parent->getNumChildren() == 0) return; TR_ASSERT(parent->getNumChildren() > 0, "expected TR::GlRegDeps %p", parent); TR::Node * predGlRegDeps = parent->getLastChild(); if (predGlRegDeps->getOpCodeValue() != TR::GlRegDeps) // could be already removed return; TR_ASSERT(predGlRegDeps->getOpCodeValue() == TR::GlRegDeps, "expected TR::GlRegDeps"); for (int32_t i = predGlRegDeps->getNumChildren() - 1; i >= 0; --i) if (predGlRegDeps->getChild(i)->getGlobalRegisterNumber() == registerNum) { dumpOptDetails(opt->comp(), "%sRemove GlRegDep : %p\n", opt->optDetailString(), predGlRegDeps->getChild(i)); TR::Node *removedChild = predGlRegDeps->removeChild(i); if (removedChild->getReferenceCount() <= 1) { // The only remaining parent is the RegStore. Another pass of // deadTrees may be able to eliminate that. // opt->requestOpt(OMR::deadTreesElimination, true, containingBlock); } break; } if (predGlRegDeps->getNumChildren() == 0) parent->removeLastChild(); }
void TR::DeadTreesElimination::prePerformOnBlocks() { _cannotBeEliminated = false; _delayedRegStores = false; _targetTrees.deleteAll(); // Walk through all the blocks to remove trivial dead trees of the form // treetop // => node // The problem with these trees is in the scenario where the earlier use // of 'node' is also dead. However, our analysis won't find that because // the reference count is > 1. vcount_t visitCount = comp()->incOrResetVisitCount(); for (TR::TreeTop *tt = comp()->getStartTree(); tt != 0; tt = tt->getNextTreeTop()) { bool removed = false; TR::Node *node = tt->getNode(); if (node->getOpCodeValue() == TR::treetop && node->getFirstChild()->getVisitCount() == visitCount && performTransformation(comp(), "%sRemove trivial dead tree: %p\n", optDetailString(), node)) { TR::TransformUtil::removeTree(comp(), tt); removed = true; } else { if (node->getOpCode().isCheck() && node->getFirstChild()->getOpCode().isCall() && node->getFirstChild()->getReferenceCount() == 1 && node->getFirstChild()->getSymbolReference()->getSymbol()->isResolvedMethod() && node->getFirstChild()->getSymbolReference()->getSymbol()->castToResolvedMethodSymbol()->isSideEffectFree() && performTransformation(comp(), "%sRemove dead check of side-effect free call: %p\n", optDetailString(), node)) { TR::TransformUtil::removeTree(comp(), tt); removed = true; } } if (removed && tt->getNextTreeTop()->getNode()->getOpCodeValue() == TR::Goto && tt->getPrevTreeTop()->getNode()->getOpCodeValue() == TR::BBStart && !tt->getPrevTreeTop()->getNode()->getBlock()->isExtensionOfPreviousBlock()) { requestOpt(OMR::redundantGotoElimination, tt->getEnclosingBlock()); } if (node->getVisitCount() >= visitCount) continue; TR::TransformUtil::recursivelySetNodeVisitCount(tt->getNode(), visitCount); } // If the last use of an iRegLoad has been removed, then remove the node from // the BBStart and remove the corresponding dependency node from each of the block's // predecessors. // while (1) { bool glRegDepRemoved = false; for (TR::Block * b = comp()->getStartBlock(); b; b = b->getNextBlock()) { TR::TreeTop * startTT = b->getEntry(); TR::Node * startNode = startTT->getNode(); if (startNode->getNumChildren() > 0 && !debug("disableEliminationOfGlRegDeps")) { TR::Node * glRegDeps = startNode->getFirstChild(); TR_ASSERT(glRegDeps->getOpCodeValue() == TR::GlRegDeps, "expected TR::GlRegDeps"); for (int32_t i = glRegDeps->getNumChildren() - 1; i >= 0; --i) { TR::Node * dep = glRegDeps->getChild(i); if (dep->getReferenceCount() == 1 && (!dep->getOpCode().isFloatingPoint() || cg()->getSupportsJavaFloatSemantics()) && performTransformation(comp(), "%sRemove GlRegDep : %p\n", optDetailString(), glRegDeps->getChild(i))) { glRegDeps->removeChild(i); glRegDepRemoved = true; TR_GlobalRegisterNumber registerNum = dep->getGlobalRegisterNumber(); for (auto e = b->getPredecessors().begin(); e != b->getPredecessors().end(); ++e) { TR::Block * pred = toBlock((*e)->getFrom()); if (pred == comp()->getFlowGraph()->getStart()) continue; TR::Node * parent = pred->getLastRealTreeTop()->getNode(); if ( parent->getOpCode().isJumpWithMultipleTargets() && parent->getOpCode().hasBranchChildren()) { for (int32_t j = parent->getCaseIndexUpperBound() - 1; j > 0; --j) { TR::Node * caseNode = parent->getChild(j); TR_ASSERT(caseNode->getOpCode().isCase() || caseNode->getOpCodeValue() == TR::branch, "having problems navigating a switch"); if (caseNode->getBranchDestination() == startTT && caseNode->getNumChildren() > 0 && 0) // can't do this now that all glRegDeps are hung off the default branch removeGlRegDep(caseNode, registerNum, pred, this); } } else if (!parent->getOpCode().isReturn() && parent->getOpCodeValue() != TR::igoto && !( parent->getOpCode().isJumpWithMultipleTargets() && parent->getOpCode().hasBranchChildren()) && !(parent->getOpCodeValue()==TR::treetop && parent->getFirstChild()->getOpCode().isCall() && parent->getFirstChild()->getOpCode().isIndirect())) { if (pred->getNextBlock() == b) parent = pred->getExit()->getNode(); removeGlRegDep(parent, registerNum, pred, this); } } } } if (glRegDeps->getNumChildren() == 0) startNode->removeChild(0); } } if (!glRegDepRemoved) break; } }