TR::Instruction * TR_X86SystemLinkage::savePreservedRegisters(TR::Instruction *cursor) { // For IA32, if disableShrinkWrapping, usePushForPreservedRegs will be true; otherwise false; // For X64, shrinkWraping is always on, and usePushForPreservedRegs always false; // TR_ASSERT(!getProperties().getUsesPushesForPreservedRegs(), "assertion failure"); TR::ResolvedMethodSymbol *bodySymbol = comp()->getJittedMethodSymbol(); const int32_t localSize = getProperties().getOffsetToFirstLocal() - bodySymbol->getLocalMappingCursor(); const int32_t pointerSize = getProperties().getPointerSize(); int32_t offsetCursor = -localSize + getProperties().getOffsetToFirstLocal() - pointerSize; if (_properties.getUsesPushesForPreservedRegs()) { for (int32_t pindex = _properties.getMaxRegistersPreservedInPrologue()-1; pindex >= 0; pindex--) { TR::RealRegister::RegNum idx = _properties.getPreservedRegister((uint32_t)pindex); TR::RealRegister *reg = machine()->getX86RealRegister(idx); if (reg->getHasBeenAssignedInMethod() && reg->getState() != TR::RealRegister::Locked) { cursor = new (trHeapMemory()) TR::X86RegInstruction(cursor, PUSHReg, reg, cg()); } } } else { TR_BitVector *p = cg()->getPreservedRegsInPrologue(); for (int32_t pindex = getProperties().getMaxRegistersPreservedInPrologue()-1; pindex >= 0; pindex--) { TR::RealRegister::RegNum idx = _properties.getPreservedRegister((uint32_t)pindex); TR::RealRegister *reg = machine()->getX86RealRegister(getProperties().getPreservedRegister((uint32_t)pindex)); if(reg->getHasBeenAssignedInMethod() && reg->getState() != TR::RealRegister::Locked) { if (!p || p->get(idx)) { cursor = generateMemRegInstruction( cursor, movOpcodes[MemReg][fullRegisterMovType(reg)], generateX86MemoryReference(machine()->getX86RealRegister(TR::RealRegister::vfp), offsetCursor, cg()), reg, cg() ); } offsetCursor -= pointerSize; } } } return cursor; }
bool TR_DominatorVerifier::isExpensiveAlgorithmCorrect(TR_DominatorsChk &expensiveAlgorithm) { int32_t i,j; _nodesSeenOnEveryPath = new (trStackMemory()) TR_BitVector(_numBlocks,trMemory(), stackAlloc); _nodesSeenOnCurrentPath = new (trStackMemory()) TR_BitVector(_numBlocks,trMemory(), stackAlloc); _dominatorsChkInfo = expensiveAlgorithm.getDominatorsChkInfo(); for (i = 2; i < _numBlocks-1; i++) { TR_BitVector *bucket = _dominatorsChkInfo[i]._tmpbucket; for (j = 0; j < _numBlocks-1; j++) { if (bucket->get(j)) // dominator according to algorithm { // Initializing these BitVectors before checking // dominators for the next block. // The last bit is not changed for either bit vector - is that what // was intended? // _nodesSeenOnEveryPath->setAll(_numBlocks-1); int32_t lastBit = _nodesSeenOnCurrentPath->get(_numBlocks-1); _nodesSeenOnCurrentPath->empty(); if (lastBit) _nodesSeenOnCurrentPath->set(_numBlocks-1); if ( ! dominates(_dominatorsChkInfo[j+1]._block,_dominatorsChkInfo[i]._block) ) // dominator according to the CFG { if (debug("traceVER")) { dumpOptDetails(comp(), " Dominator info for expensive algorithm is incorrect \n"); dumpOptDetails(comp(), " Dominator of [%p] is [%p] as per the algorithm\n", _dominatorsChkInfo[i]._block, _dominatorsChkInfo[j+1]._block); dumpOptDetails(comp(), " But [%p] is not an the dominator of [%p] as per the Control Flow Graph", _dominatorsChkInfo[j+1]._block, _dominatorsChkInfo[i]._block); } return false; } } } } return true; }
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 }