void TR_ForwardReachabilityWithoutExceptionEdges::propagateInputs(blocknum_t blockNum, int32_t depth, blocknum_t *stack, blocknum_t *depth_map, TR_BitVector *closure) { TR::Block *block = getBlock(blockNum); for (auto edge = block->getPredecessors().begin(); edge != block->getPredecessors().end(); ++edge) { TR::Block *inputBlock = toBlock((*edge)->getFrom()); propagateOneInput(inputBlock->getNumber(), blockNum, depth, stack, depth_map, closure); } }
void TR_LocalAnalysis::initializeBlocks(TR::Block *block, TR::BitVector &blocksSeen) { _info[block->getNumber()]._block = block; blocksSeen[block->getNumber()] = true; TR::Block *next; for (auto nextEdge = block->getSuccessors().begin(); nextEdge != block->getSuccessors().end(); ++nextEdge) { next = toBlock((*nextEdge)->getTo()); if (!blocksSeen.ValueAt(next->getNumber())) initializeBlocks(next, blocksSeen); } for (auto nextEdge = block->getExceptionSuccessors().begin(); nextEdge != block->getExceptionSuccessors().end(); ++nextEdge) { next = toBlock((*nextEdge)->getTo()); if (!blocksSeen.ValueAt(next->getNumber())) initializeBlocks(next, blocksSeen); } }
void TR_BackwardReachability::propagateInputs(blocknum_t blockNum, int32_t depth, blocknum_t *stack, blocknum_t *depth_map, TR_BitVector *closure) { TR::Block *block = getBlock(blockNum); TR_SuccessorIterator bi(block); for (TR::CFGEdge *edge = bi.getFirst(); edge != NULL; edge = bi.getNext()) { TR::Block *inputBlock = toBlock(edge->getTo()); propagateOneInput(inputBlock->getNumber(), blockNum, depth, stack, depth_map, closure); } }
// Visits the Predecessors of the dominated block recursively. // void TR_DominatorVerifier::compareWithPredsOf(TR::Block *dominator, TR::Block *dominated) { dominated->setVisitCount(_visitCount); _nodesSeenOnCurrentPath->set(_dominators->_dfNumbers[dominator->getNumber()]); if (dominator == dominated) return; for (auto pred = dominated->getPredecessors().begin(); pred != dominated->getPredecessors().end(); ++pred) { if (toBlock((*pred)->getFrom())->getVisitCount() != _visitCount) compareWithPredsOf(dominator, toBlock((*pred)->getFrom())); } for (auto pred = dominated->getExceptionPredecessors().begin(); pred != dominated->getExceptionPredecessors().end(); ++pred) { if (toBlock((*pred)->getFrom())->getVisitCount() != _visitCount) compareWithPredsOf(dominator, toBlock((*pred)->getFrom())); } }
// Returns true if the dominator block dominates the dominated block // as per the Control Flow Graph. Examines each (backward) control // flow path from the dominated block to the dominator block. Intersection // of the nodes seen along each of the backward control flow paths (until // the dominator block) from the dominated block must be a singleton set, // containing only the dominator block. // bool TR_DominatorVerifier::dominates(TR::Block *dominator, TR::Block *dominated) { for (auto pred = dominated->getPredecessors().begin(); pred != dominated->getPredecessors().end(); ++pred) { _visitCount = comp()->incVisitCount(); compareWithPredsOf(dominator, toBlock((*pred)->getFrom())); *_nodesSeenOnEveryPath &= *_nodesSeenOnCurrentPath; // Reset all bits except the last - is this what is intended? int32_t lastBit = _nodesSeenOnCurrentPath->get(_numBlocks-1); _nodesSeenOnCurrentPath->empty(); if (lastBit) _nodesSeenOnCurrentPath->set(_numBlocks-1); } for (auto pred = dominated->getExceptionPredecessors().begin(); pred != dominated->getExceptionPredecessors().end(); ++pred) { _visitCount = comp()->incVisitCount(); compareWithPredsOf(dominator, toBlock((*pred)->getFrom())); *_nodesSeenOnEveryPath &= *_nodesSeenOnCurrentPath; _nodesSeenOnCurrentPath->empty(); } for (int32_t i=0;i<_numBlocks-1;i++) { if (i==_dominators->_dfNumbers[dominator->getNumber()]) { if (!_nodesSeenOnEveryPath->get(i)) return false; } else { if (_nodesSeenOnEveryPath->get(i)) return false; } } return true; }
void TR_LocalAnalysis::initializeLocalAnalysis(bool isSparse, bool lock) { _info = (TR_LocalAnalysisInfo::LAInfo*) trMemory()->allocateStackMemory(_lainfo._numBlocks*sizeof(TR_LocalAnalysisInfo::LAInfo)); memset(_info, 0, _lainfo._numBlocks*sizeof(TR_LocalAnalysisInfo::LAInfo)); TR::BitVector blocksSeen(comp()->allocator()); initializeBlocks(toBlock(comp()->getFlowGraph()->getStart()), blocksSeen); int32_t i; for (i = 0; i < _lainfo._numBlocks; i++) { _info[i]._analysisInfo = allocateContainer(getNumNodes()); _info[i]._downwardExposedAnalysisInfo = allocateContainer(getNumNodes()); _info[i]._downwardExposedStoreAnalysisInfo = allocateContainer(getNumNodes()); } }
TR::Block * TR_ExpressionsSimplification::findPredecessorBlock(TR::CFGNode *entryNode) { if (!(entryNode->getPredecessors().size() == 2)) return 0; TR::Block *block = 0; for (auto edge = entryNode->getPredecessors().begin(); edge != entryNode->getPredecessors().end(); ++edge) { if ((*edge)->getFrom()->getSuccessors().size() == 1) { block = toBlock((*edge)->getFrom()); if (block->getStructureOf()->isLoopInvariantBlock()) break; else block = 0; } } //traceMsg(comp(), "Commoned code will be put in block_%d\n", block->getNumber()); return block; }
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_Latestness::TR_Latestness(TR::Compilation *comp, TR::Optimizer *optimizer, TR_Structure *rootStructure, bool trace) : TR_BackwardIntersectionBitVectorAnalysis(comp, comp->getFlowGraph(), optimizer, trace) { _delayedness = new (comp->allocator()) TR_Delayedness(comp, optimizer, rootStructure, trace); _supportedNodesAsArray = _delayedness->_supportedNodesAsArray; if (trace) traceMsg(comp, "Starting Latestness\n"); TR::CFG *cfg = comp->getFlowGraph(); _numberOfNodes = cfg->getNextNodeNumber(); TR_ASSERT(_numberOfNodes > 0, "Latestness, node numbers not assigned"); _numberOfBits = getNumberOfBits(); _inSetInfo = (ContainerType **)trMemory()->allocateStackMemory(_numberOfNodes*sizeof(ContainerType *)); for (int32_t i=0;i<_numberOfNodes;i++) allocateContainer(_inSetInfo+i); // Allocate temp bit vectors from block info, since it is local to this analysis ContainerType *intersection, *negation; allocateBlockInfoContainer(&intersection); allocateBlockInfoContainer(&negation); TR::CFGNode *nextNode; for (nextNode = cfg->getFirstNode(); nextNode; nextNode = nextNode->getNext()) { TR_BlockStructure *blockStructure = (toBlock(nextNode))->getStructureOf(); if ((blockStructure == NULL) || (blockStructure->getBlock()->getSuccessors().empty() && blockStructure->getBlock()->getExceptionSuccessors().empty())) continue; /////analyzeTreeTopsInBlockStructure(blockStructure); /////analysisInfo->_containsExceptionTreeTop = _containsExceptionTreeTop; initializeInfo(intersection); for (auto succ = nextNode->getSuccessors().begin(); succ != nextNode->getSuccessors().end(); ++succ) { TR::CFGNode *succBlock = (*succ)->getTo(); compose(intersection, _delayedness->_inSetInfo[succBlock->getNumber()]); } /////if (getAnalysisInfo(blockStructure)->_containsExceptionTreeTop) { for (auto succ = nextNode->getExceptionSuccessors().begin(); succ != nextNode->getExceptionSuccessors().end(); ++succ) { TR::CFGNode *succBlock = (*succ)->getTo(); compose(intersection, _delayedness->_inSetInfo[succBlock->getNumber()]); } } negation->setAll(_numberOfBits); *negation -= *intersection; copyFromInto(negation, _inSetInfo[blockStructure->getNumber()]); *(_inSetInfo[blockStructure->getNumber()]) |= *(_delayedness->_earliestness->_globalAnticipatability->_localAnticipatability.getDownwardExposedAnalysisInfo(blockStructure->getBlock()->getNumber())); *(_inSetInfo[blockStructure->getNumber()]) &= *(_delayedness->_inSetInfo[blockStructure->getNumber()]); if (trace) { traceMsg(comp, "\nIn Set of Block : %d\n", blockStructure->getNumber()); _inSetInfo[blockStructure->getNumber()]->print(comp); } } if (trace) traceMsg(comp, "\nEnding Latestness\n"); // Null out info that will not be used by callers _delayedness->_inSetInfo = NULL; _blockAnalysisInfo = NULL; }
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; } }