int32_t TR_CatchBlockRemover::perform() { TR::CFG *cfg = comp()->getFlowGraph(); if (cfg == NULL) { if (trace()) traceMsg(comp(), "Can't do Catch Block Removal, no CFG\n"); return 0; } if (trace()) traceMsg(comp(), "Starting Catch Block Removal\n"); bool thereMayBeRemovableCatchBlocks = false; { TR::StackMemoryRegion stackMemoryRegion(*trMemory()); TR::Block *block; ListIterator<TR::CFGEdge> edgeIterator; // Go through all blocks that have exception successors and see if any of them // are not reached. Mark each of these edges with a visit count so they can // be identified later. // vcount_t visitCount = comp()->incOrResetVisitCount(); TR::CFGNode *cfgNode; for (cfgNode = cfg->getFirstNode(); cfgNode; cfgNode = cfgNode->getNext()) { if (cfgNode->getExceptionSuccessors().empty()) continue; block = toBlock(cfgNode); uint32_t reachedExceptions = 0; TR::TreeTop *treeTop; for (treeTop = block->getEntry(); treeTop != block->getExit(); treeTop = treeTop->getNextTreeTop()) { reachedExceptions |= treeTop->getNode()->exceptionsRaised(); if (treeTop->getNode()->getOpCodeValue() == TR::monexitfence) // for live monitor metadata reachedExceptions |= TR::Block::CanCatchMonitorExit; } if (reachedExceptions & TR::Block::CanCatchUserThrows) continue; for (auto edge = block->getExceptionSuccessors().begin(); edge != block->getExceptionSuccessors().end();) { TR::CFGEdge * current = *(edge++); TR::Block *catchBlock = toBlock(current->getTo()); if (catchBlock->isOSRCodeBlock() || catchBlock->isOSRCatchBlock()) continue; if (!reachedExceptions && performTransformation(comp(), "%sRemove redundant exception edge from block_%d at [%p] to catch block_%d at [%p]\n", optDetailString(), block->getNumber(), block, catchBlock->getNumber(), catchBlock)) { cfg->removeEdge(block, catchBlock); thereMayBeRemovableCatchBlocks = true; } else { if (!catchBlock->canCatchExceptions(reachedExceptions)) { current->setVisitCount(visitCount); thereMayBeRemovableCatchBlocks = true; } } } } bool edgesRemoved = false; // Now look to see if there are any catch blocks for which all exception // predecessors have the visit count set. If so, the block is unreachable and // can be removed. // If only some of the exception predecessors are marked, these edges are // left in place to identify the try/catch structure properly. // while (thereMayBeRemovableCatchBlocks) { thereMayBeRemovableCatchBlocks = false; for (cfgNode = cfg->getFirstNode(); cfgNode; cfgNode = cfgNode->getNext()) { if (cfgNode->getExceptionPredecessors().empty()) continue; auto edgeIt = cfgNode->getExceptionPredecessors().begin(); for (; edgeIt != cfgNode->getExceptionPredecessors().end(); ++edgeIt) { if ((*edgeIt)->getVisitCount() != visitCount) break; } if (edgeIt == cfgNode->getExceptionPredecessors().end() && performTransformation(comp(), "%sRemove redundant catch block_%d at [%p]\n", optDetailString(), cfgNode->getNumber(), cfgNode)) { while (!cfgNode->getExceptionPredecessors().empty()) { cfg->removeEdge(cfgNode->getExceptionPredecessors().front()); } edgesRemoved = true; thereMayBeRemovableCatchBlocks = true; } } } // Any transformations invalidate use/def and value number information // if (edgesRemoved) { optimizer()->setUseDefInfo(NULL); optimizer()->setValueNumberInfo(NULL); requestOpt(OMR::treeSimplification, true); } } // scope of the stack memory region if (trace()) traceMsg(comp(), "\nEnding Catch Block Removal\n"); return 1; // actual cost }
TR::TreeTop * OMR::Simplifier::simplifyExtendedBlock(TR::TreeTop * treeTop) { TR::Block * block = 0; _containingStructure = NULL; _blockRemoved = false; for (; treeTop; treeTop = treeTop->getNextTreeTop()) { TR::Node * node = treeTop->getNode(); TR_ASSERT(node->getOpCodeValue() == TR::BBStart, "Simplification, expected BBStart treetop"); TR::Block * b = node->getBlock(); if (block && !b->isExtensionOfPreviousBlock()) break; if (b->isOSRCodeBlock() || b->isOSRCatchBlock()) { b->setHasBeenVisited(); treeTop = b->getExit(); continue; } #ifdef DEBUG if (block != b) b->setHasBeenVisited(); #endif if (!block && _reassociate && comp()->getFlowGraph()->getStructure() != NULL // [99391] getStructureOf() only valid if structure isn't invalidated ) { // b is first block in the extended block TR_BlockStructure *blockStructure = b->getStructureOf(); if(blockStructure) { TR_Structure *parent = blockStructure->getParent(); while (parent) { TR_RegionStructure *region = parent->asRegion(); if (region->isNaturalLoop() /* || region->containsInternalCycles() */) { _containingStructure = region; break; } parent = parent->getParent(); } } } block = b; if (trace()) traceMsg(comp(), "simplifying block_%d\n", block->getNumber()); _performLowerTreeSimplifier=NULL; _performLowerTreeNode=NULL; simplify(block); if(_performLowerTreeSimplifier) { _performLowerTreeNode = postWalkLowerTreeSimplifier(_performLowerTreeSimplifier, _performLowerTreeNode, block, (TR::Simplifier *) this); _performLowerTreeSimplifier->setNode(_performLowerTreeNode); } // If the block itself was removed from the CFG during simplification, find // the next 'legitimate' block to be simplified // //if (comp()->getFlowGraph()->getRemovedNodes().find(block)) if(block->nodeIsRemoved()) { TR::TreeTop * tt = findNextLegalTreeTop(comp(), block); // in certain cases the removed block might be the last one we haven't // visited and therefore we won't be able to find a treetop to continue // in such cases we exit the loop // treeTop = tt ? tt->getPrevTreeTop() : 0; if (!treeTop) break; } else { treeTop = block->getExit(); } } // now remove any unreachable blocks // if (_blockRemoved) { // if the next block to be processed has been removed, // find the next valid block to process // if (treeTop) { TR::Block *b = treeTop->getNode()->getBlock(); //if (comp()->getFlowGraph()->getRemovedNodes().find(b)) if(b->nodeIsRemoved()) treeTop = findNextLegalTreeTop(comp(), b); } } return treeTop; }