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; }
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; }
TR_GlobalRegisterNumber OMR::X86::I386::CodeGenerator::pickRegister( TR_RegisterCandidate *rc, TR::Block **allBlocks, TR_BitVector &availableRegisters, TR_GlobalRegisterNumber &highRegisterNumber, TR_LinkHead<TR_RegisterCandidate> *candidates) { if (!self()->comp()->getOption(TR_DisableRegisterPressureSimulation)) { if (self()->comp()->getOption(TR_AssignEveryGlobalRegister)) { // This is not really necessary except for testing purposes. // Conceptually, the common pickRegister code should be free to make // its choices based only on performance considerations, and shouldn't // need to worry about correctness. When SupportsVMThreadGRA is not set, // it is incorrect to choose the VMThread register. Therefore we mask // it out here. // // Having said that, the common code *does* already mask out the // VMThread register for convenience, so under normal circumstances, // this code is redundant. It is only necessary when // TR_AssignEveryGlobalRegister is set. // availableRegisters -= *self()->getGlobalRegisters(TR_vmThreadSpill, self()->comp()->getMethodSymbol()->getLinkageConvention()); } return OMR::CodeGenerator::pickRegister(rc, allBlocks, availableRegisters, highRegisterNumber, candidates); } if ((rc->getSymbol()->getDataType() == TR::Float) || (rc->getSymbol()->getDataType() == TR::Double)) { if (availableRegisters.get(7)) return 7; if (availableRegisters.get(8)) return 8; if (availableRegisters.get(9)) return 9; if (availableRegisters.get(10)) return 10; if (availableRegisters.get(11)) return 11; if (availableRegisters.get(12)) return 12; return -1; } if (!_assignedGlobalRegisters) _assignedGlobalRegisters = new (self()->trStackMemory()) TR_BitVector(self()->comp()->getSymRefCount(), self()->trMemory(), stackAlloc, growable); if (availableRegisters.get(5)) return 5; // esi if (availableRegisters.get(2)) return 2; // ecx static char *dontUseEBXasGPR = feGetEnv("dontUseEBXasGPR"); if (!dontUseEBXasGPR && availableRegisters.get(1)) return 1; #ifdef J9_PROJECT_SPECIFIC TR::RecognizedMethod rm = self()->comp()->getMethodSymbol()->getRecognizedMethod(); if (rm == TR::java_util_HashtableHashEnumerator_hasMoreElements) { if (availableRegisters.get(4)) return 4; // edi if (availableRegisters.get(3)) return 3; // edx } else #endif { int32_t numExtraRegs = 0; int32_t maxRegisterPressure = 0; vcount_t visitCount = self()->comp()->incVisitCount(); TR_BitVectorIterator bvi(rc->getBlocksLiveOnEntry()); int32_t maxFrequency = 0; while (bvi.hasMoreElements()) { int32_t liveBlockNum = bvi.getNextElement(); TR::Block *block = allBlocks[liveBlockNum]; if (block->getFrequency() > maxFrequency) maxFrequency = block->getFrequency(); } int32_t maxStaticFrequency = 0; if (maxFrequency == 0) { bvi.setBitVector(rc->getBlocksLiveOnEntry()); while (bvi.hasMoreElements()) { int32_t liveBlockNum = bvi.getNextElement(); TR::Block *block = allBlocks[liveBlockNum]; TR_BlockStructure *blockStructure = block->getStructureOf(); int32_t blockWeight = 1; if (blockStructure && !block->isCold()) { blockStructure->calculateFrequencyOfExecution(&blockWeight); if (blockWeight > maxStaticFrequency) maxStaticFrequency = blockWeight; } } } bool assigningEDX = false; if (!availableRegisters.get(4) && availableRegisters.get(3)) assigningEDX = true; bool vmThreadUsed = false; bvi.setBitVector(rc->getBlocksLiveOnEntry()); while (bvi.hasMoreElements()) { int32_t liveBlockNum = bvi.getNextElement(); TR::Block *block = allBlocks[liveBlockNum]; _assignedGlobalRegisters->empty(); int32_t numAssignedGlobalRegs = 0; TR_RegisterCandidate *prev; for (prev = candidates->getFirst(); prev; prev = prev->getNext()) { bool gprCandidate = true; if ((prev->getSymbol()->getDataType() == TR::Float) || (prev->getSymbol()->getDataType() == TR::Double)) gprCandidate = false; if (gprCandidate && prev->getBlocksLiveOnEntry().get(liveBlockNum)) { numAssignedGlobalRegs++; if (prev->getDataType() == TR::Int64) numAssignedGlobalRegs++; _assignedGlobalRegisters->set(prev->getSymbolReference()->getReferenceNumber()); } } maxRegisterPressure = self()->estimateRegisterPressure(block, visitCount, maxStaticFrequency, maxFrequency, vmThreadUsed, numAssignedGlobalRegs, _assignedGlobalRegisters, rc->getSymbolReference(), assigningEDX); if (maxRegisterPressure >= self()->getMaximumNumbersOfAssignableGPRs()) break; } // Determine if we can spare any extra registers for this candidate without spilling // in any hot (critical) blocks // if (maxRegisterPressure < self()->getMaximumNumbersOfAssignableGPRs()) numExtraRegs = self()->getMaximumNumbersOfAssignableGPRs() - maxRegisterPressure; //dumpOptDetails("For global register candidate %d reg pressure is %d maxRegs %d numExtraRegs %d\n", rc->getSymbolReference()->getReferenceNumber(), maxRegisterPressure, comp()->cg()->getMaximumNumbersOfAssignableGPRs(), numExtraRegs); if (numExtraRegs > 0) { if (availableRegisters.get(4)) return 4; // edi if (availableRegisters.get(3)) return 3; // edx } } return -1; // -1 ==> don't use a global register }