TR::Register *IA32LinkageUtils::pushFloatArg( TR::Node *child, TR::CodeGenerator *cg) { TR::Register *pushRegister; if (child->getRegister() == NULL) { if (child->getOpCodeValue() == TR::fconst) { int32_t value = child->getFloatBits(); TR_X86OpCodes pushOp; if (value >= -128 && value <= 127) { pushOp = PUSHImms; } else { pushOp = PUSHImm4; } generateImmInstruction(pushOp, child, value, cg); cg->decReferenceCount(child); return NULL; } else if (child->getReferenceCount() == 1) { if (child->getOpCode().isLoad()) { TR::MemoryReference *tempMR = generateX86MemoryReference(child, cg); generateMemInstruction(PUSHMem, child, tempMR, cg); tempMR->decNodeReferenceCounts(cg); cg->decReferenceCount(child); return NULL; } else if (child->getOpCodeValue() == TR::ibits2f) { pushRegister = pushIntegerWordArg(child->getFirstChild(), cg); cg->decReferenceCount(child); return pushRegister; } } } pushRegister = cg->evaluate(child); TR::RealRegister *espReal = cg->machine()->getRealRegister(TR::RealRegister::esp); generateRegImmInstruction(SUB4RegImms, child, espReal, 4, cg); if (cg->useSSEForSinglePrecision() && pushRegister->getKind() == TR_FPR) generateMemRegInstruction(MOVSSMemReg, child, generateX86MemoryReference(espReal, 0, cg), pushRegister, cg); else generateFPMemRegInstruction(FSTMemReg, child, generateX86MemoryReference(espReal, 0, cg), pushRegister, cg); cg->decReferenceCount(child); return pushRegister; }
void TR_S390BinaryAnalyser::genericAnalyser(TR::Node * root, TR::InstOpCode::Mnemonic regToRegOpCode, TR::InstOpCode::Mnemonic memToRegOpCode, TR::InstOpCode::Mnemonic copyOpCode) { TR::Node * firstChild; TR::Node * secondChild; firstChild = root->getFirstChild(); secondChild = root->getSecondChild(); TR::Register * firstRegister = firstChild->getRegister(); TR::Register * secondRegister = secondChild->getRegister(); TR::Compilation *comp = TR::comp(); TR::SymbolReference * firstReference = firstChild->getOpCode().hasSymbolReference() ? firstChild->getSymbolReference() : NULL; TR::SymbolReference * secondReference = secondChild->getOpCode().hasSymbolReference() ? secondChild->getSymbolReference() : NULL; setInputs(firstChild, firstRegister, secondChild, secondRegister, false, false, comp, (cg()->isAddressOfStaticSymRefWithLockedReg(firstReference) || cg()->isAddressOfPrivateStaticSymRefWithLockedReg(firstReference)), (cg()->isAddressOfStaticSymRefWithLockedReg(secondReference) || cg()->isAddressOfPrivateStaticSymRefWithLockedReg(secondReference))); /* * Check if SH or CH can be used to evaluate this integer subtract/compare node. * The second operand of SH/CH is a 16-bit number from memory. And using * these directly can save a load instruction. */ bool is16BitMemory2Operand = false; if (secondChild->getOpCodeValue() == TR::s2i && secondChild->getFirstChild()->getOpCodeValue() == TR::sloadi && secondChild->isSingleRefUnevaluated() && secondChild->getFirstChild()->isSingleRefUnevaluated()) { bool supported = true; if (memToRegOpCode == TR::InstOpCode::S) { memToRegOpCode = TR::InstOpCode::SH; } else if (memToRegOpCode == TR::InstOpCode::C) { memToRegOpCode = TR::InstOpCode::CH; } else { supported = false; } if (supported) { setMem2(); is16BitMemory2Operand = true; } } if (getEvalChild1()) { firstRegister = cg()->evaluate(firstChild); } if (getEvalChild2()) { secondRegister = cg()->evaluate(secondChild); } remapInputs(firstChild, firstRegister, secondChild, secondRegister); if (getCopyReg1()) { TR::Register * thirdReg; bool done = false; if (firstRegister->getKind() == TR_GPR64) { thirdReg = cg()->allocate64bitRegister(); } else if (firstRegister->getKind() == TR_VRF) { TR_ASSERT(false,"VRF: genericAnalyser unimplemented"); } else if (firstRegister->getKind() != TR_FPR && firstRegister->getKind() != TR_VRF) { thirdReg = cg()->allocateRegister(); } else { thirdReg = cg()->allocateRegister(TR_FPR); } if (cg()->getS390ProcessorInfo()->supportsArch(TR_S390ProcessorInfo::TR_z196)) { if (getBinaryReg3Reg2() || secondRegister != NULL) { if (regToRegOpCode == TR::InstOpCode::SR) { generateRRRInstruction(cg(), TR::InstOpCode::SRK, root, thirdReg, firstRegister, secondRegister); done = true; } else if (regToRegOpCode == TR::InstOpCode::SLR) { generateRRRInstruction(cg(), TR::InstOpCode::SLRK, root, thirdReg, firstRegister, secondRegister); done = true; } else if (regToRegOpCode == TR::InstOpCode::SGR) { generateRRRInstruction(cg(), TR::InstOpCode::SGRK, root, thirdReg, firstRegister, secondRegister); done = true; } else if (regToRegOpCode == TR::InstOpCode::SLGR) { generateRRRInstruction(cg(), TR::InstOpCode::SLGRK, root, thirdReg, firstRegister, secondRegister); done = true; } } } if (!done) { generateRRInstruction(cg(), copyOpCode, root, thirdReg, firstRegister); if (getBinaryReg3Reg2() || (secondRegister != NULL)) { generateRRInstruction(cg(), regToRegOpCode, root, thirdReg, secondRegister); } else { TR::Node* loadBaseAddr = is16BitMemory2Operand ? secondChild->getFirstChild() : secondChild; TR::MemoryReference * tempMR = generateS390MemoryReference(loadBaseAddr, cg()); //floating-point arithmatics don't have RXY format instructions, so no long displacement if (secondChild->getOpCode().isFloatingPoint()) { tempMR->enforce4KDisplacementLimit(secondChild, cg(), NULL); } generateRXInstruction(cg(), memToRegOpCode, root, thirdReg, tempMR); tempMR->stopUsingMemRefRegister(cg()); if (is16BitMemory2Operand) { cg()->decReferenceCount(secondChild->getFirstChild()); } } } root->setRegister(thirdReg); } else if (getBinaryReg1Reg2()) { generateRRInstruction(cg(), regToRegOpCode, root, firstRegister, secondRegister); root->setRegister(firstRegister); } else // assert getBinaryReg1Mem2() == true { TR_ASSERT( !getInvalid(), "TR_S390BinaryAnalyser::invalid case\n"); TR::MemoryReference * tempMR = generateS390MemoryReference(is16BitMemory2Operand ? secondChild->getFirstChild() : secondChild, cg()); //floating-point arithmatics don't have RXY format instructions, so no long displacement if (secondChild->getOpCode().isFloatingPoint()) { tempMR->enforce4KDisplacementLimit(secondChild, cg(), NULL); } generateRXInstruction(cg(), memToRegOpCode, root, firstRegister, tempMR); tempMR->stopUsingMemRefRegister(cg()); if (is16BitMemory2Operand) cg()->decReferenceCount(secondChild->getFirstChild()); root->setRegister(firstRegister); } cg()->decReferenceCount(firstChild); cg()->decReferenceCount(secondChild); return; }
rcount_t OMR::CodeGenerator::decReferenceCount(TR::Node * node) { TR::Register *reg = node->getRegister(); // restricted registers go dead when ref count==2 because // their ref count was inced in prepareNodeForInstructionSelection if ((node->getReferenceCount() == 1) && reg && self()->getLiveRegisters(reg->getKind())) { TR_ASSERT(reg->isLive() || (diagnostic("\n*** Error: Register %s for node " "[%s] died prematurely\n", reg->getRegisterName(self()->comp()), node->getName(self()->comp()->getDebug())), 0), "Node %s register should be live",self()->getDebug()->getName(node)); TR_LiveRegisterInfo *liveRegister = reg->getLiveRegisterInfo(); TR::Register *pair = reg->getRegisterPair(); if (pair) { pair->getHighOrder()->getLiveRegisterInfo()->decNodeCount(); pair->getLowOrder()->getLiveRegisterInfo()->decNodeCount(); } if (liveRegister && liveRegister->decNodeCount() == 0) { // The register is now dead // self()->getLiveRegisters(reg->getKind())->registerIsDead(reg); } } #ifdef J9_PROJECT_SPECIFIC #if defined(TR_TARGET_S390) if (reg && reg->getOpaquePseudoRegister()) { TR_OpaquePseudoRegister *pseudoReg = reg->getOpaquePseudoRegister(); TR_StorageReference *storageReference = pseudoReg->getStorageReference(); TR_ASSERT(storageReference,"the pseudoReg should have a non-null storage reference\n"); storageReference->decrementTemporaryReferenceCount(); if (node->getReferenceCount() == 1) { storageReference->decOwningRegisterCount(); if (self()->traceBCDCodeGen()) traceMsg(self()->comp(),"\tdecrement owningRegisterCount %d->%d on ref #%d (%s) for reg %s as %s (%p) refCount == 1 (going to 0)\n", storageReference->getOwningRegisterCount()+1, storageReference->getOwningRegisterCount(), storageReference->getReferenceNumber(), self()->getDebug()->getName(storageReference->getSymbol()), self()->getDebug()->getName(reg), node->getOpCode().getName(), node); } } else if (node->getOpCode().hasSymbolReference() && node->getSymbolReference() && node->getSymbolReference()->isTempVariableSizeSymRef()) { TR_ASSERT(false,"tempMemSlots should only be attached to pseudoRegisters and not node %p\n",node); } #endif #endif rcount_t count = node->decReferenceCount(); if (self()->comp()->getOptions()->getTraceCGOption(TR_TraceCGEvaluation)) { self()->getDebug()->printNodeEvaluation(node, "-- ", reg); } return count; }
void TR_PPCRegisterDependencyGroup::assignRegisters(TR::Instruction *currentInstruction, TR_RegisterKinds kindToBeAssigned, uint32_t numberOfRegisters, TR::CodeGenerator *cg) { // *this swipeable for debugging purposes TR::Machine *machine = cg->machine(); TR::Register *virtReg; TR::RealRegister::RegNum dependentRegNum; TR::RealRegister *dependentRealReg, *assignedRegister, *realReg; int i, j; TR::Compilation *comp = cg->comp(); int num_gprs = 0; int num_fprs = 0; int num_vrfs = 0; // Use to do lookups using real register numbers TR_PPCRegisterDependencyMap map(_dependencies, numberOfRegisters); if (!comp->getOption(TR_DisableOOL)) { for (i = 0; i< numberOfRegisters; i++) { virtReg = _dependencies[i].getRegister(); dependentRegNum = _dependencies[i].getRealRegister(); if (dependentRegNum == TR::RealRegister::SpilledReg) { TR_ASSERT(virtReg->getBackingStorage(),"should have a backing store if dependentRegNum == spillRegIndex()\n"); if (virtReg->getAssignedRealRegister()) { // this happens when the register was first spilled in main line path then was reverse spilled // and assigned to a real register in OOL path. We protected the backing store when doing // the reverse spill so we could re-spill to the same slot now traceMsg (comp,"\nOOL: Found register spilled in main line and re-assigned inside OOL"); TR::Node *currentNode = currentInstruction->getNode(); TR::RealRegister *assignedReg = toRealRegister(virtReg->getAssignedRegister()); TR::MemoryReference *tempMR = new (cg->trHeapMemory()) TR::MemoryReference(currentNode, (TR::SymbolReference*)virtReg->getBackingStorage()->getSymbolReference(), sizeof(uintptr_t), cg); TR::InstOpCode::Mnemonic opCode; TR_RegisterKinds rk = virtReg->getKind(); switch (rk) { case TR_GPR: opCode =TR::InstOpCode::Op_load; break; case TR_FPR: opCode = virtReg->isSinglePrecision() ? TR::InstOpCode::lfs : TR::InstOpCode::lfd; break; default: TR_ASSERT(0, "\nRegister kind not supported in OOL spill\n"); break; } TR::Instruction *inst = generateTrg1MemInstruction(cg, opCode, currentNode, assignedReg, tempMR, currentInstruction); assignedReg->setAssignedRegister(NULL); virtReg->setAssignedRegister(NULL); assignedReg->setState(TR::RealRegister::Free); if (comp->getDebug()) cg->traceRegisterAssignment("Generate reload of virt %s due to spillRegIndex dep at inst %p\n",comp->getDebug()->getName(virtReg),currentInstruction); cg->traceRAInstruction(inst); } if (!(std::find(cg->getSpilledRegisterList()->begin(), cg->getSpilledRegisterList()->end(), virtReg) != cg->getSpilledRegisterList()->end())) cg->getSpilledRegisterList()->push_front(virtReg); } // we also need to free up all locked backing storage if we are exiting the OOL during backwards RA assignment else if (currentInstruction->isLabel() && virtReg->getAssignedRealRegister()) { TR::PPCLabelInstruction *labelInstr = (TR::PPCLabelInstruction *)currentInstruction; TR_BackingStore * location = virtReg->getBackingStorage(); TR_RegisterKinds rk = virtReg->getKind(); int32_t dataSize; if (labelInstr->getLabelSymbol()->isStartOfColdInstructionStream() && location) { traceMsg (comp,"\nOOL: Releasing backing storage (%p)\n", location); if (rk == TR_GPR) dataSize = TR::Compiler->om.sizeofReferenceAddress(); else dataSize = 8; location->setMaxSpillDepth(0); cg->freeSpill(location,dataSize,0); virtReg->setBackingStorage(NULL); } } } } for (i = 0; i < numberOfRegisters; i++) { map.addDependency(_dependencies[i], i); virtReg = _dependencies[i].getRegister(); dependentRegNum = _dependencies[i].getRealRegister(); if (dependentRegNum != TR::RealRegister::SpilledReg) { if (virtReg->getKind() == TR_GPR) num_gprs++; else if (virtReg->getKind() == TR_FPR) num_fprs++; else if (virtReg->getKind() == TR_VRF) num_vrfs++; } } #ifdef DEBUG int locked_gprs = 0; int locked_fprs = 0; int locked_vrfs = 0; // count up how many registers are locked for each type for(i = TR::RealRegister::FirstGPR; i <= TR::RealRegister::LastGPR; i++) { realReg = machine->getPPCRealRegister((TR::RealRegister::RegNum)i); if (realReg->getState() == TR::RealRegister::Locked) locked_gprs++; } for(i = TR::RealRegister::FirstFPR; i <= TR::RealRegister::LastFPR; i++) { realReg = machine->getPPCRealRegister((TR::RealRegister::RegNum)i); if (realReg->getState() == TR::RealRegister::Locked) locked_fprs++; } for(i = TR::RealRegister::FirstVRF; i <= TR::RealRegister::LastVRF; i++) { realReg = machine->getPPCRealRegister((TR::RealRegister::RegNum)i); if (realReg->getState() == TR::RealRegister::Locked) locked_vrfs++; } TR_ASSERT( locked_gprs == machine->getNumberOfLockedRegisters(TR_GPR),"Inconsistent number of locked GPRs"); TR_ASSERT( locked_fprs == machine->getNumberOfLockedRegisters(TR_FPR),"Inconsistent number of locked FPRs"); TR_ASSERT( locked_vrfs == machine->getNumberOfLockedRegisters(TR_VRF), "Inconsistent number of locked VRFs"); #endif // To handle circular dependencies, we block a real register if (1) it is already assigned to a correct // virtual register and (2) if it is assigned to one register in the list but is required by another. // However, if all available registers are requested, we do not block in case (2) to avoid all registers // being blocked. bool block_gprs = true; bool block_fprs = true; bool block_vrfs = true; TR_ASSERT(num_gprs <= (TR::RealRegister::LastGPR - TR::RealRegister::FirstGPR + 1 - machine->getNumberOfLockedRegisters(TR_GPR)), "Too many GPR dependencies, unable to assign" ); TR_ASSERT(num_fprs <= (TR::RealRegister::LastFPR - TR::RealRegister::FirstFPR + 1 - machine->getNumberOfLockedRegisters(TR_FPR)), "Too many FPR dependencies, unable to assign" ); TR_ASSERT(num_vrfs <= (TR::RealRegister::LastVRF - TR::RealRegister::FirstVRF + 1 - machine->getNumberOfLockedRegisters(TR_VRF)), "Too many VRF dependencies, unable to assign" ); if (num_gprs == (TR::RealRegister::LastGPR - TR::RealRegister::FirstGPR + 1 - machine->getNumberOfLockedRegisters(TR_GPR))) block_gprs = false; if (num_fprs == (TR::RealRegister::LastFPR - TR::RealRegister::FirstFPR + 1 - machine->getNumberOfLockedRegisters(TR_FPR))) block_fprs = false; if (num_vrfs == (TR::RealRegister::LastVRF - TR::RealRegister::FirstVRF + 1 - machine->getNumberOfLockedRegisters(TR_VRF))) block_vrfs = false; for (i = 0; i < numberOfRegisters; i++) { virtReg = _dependencies[i].getRegister(); if (virtReg->getAssignedRealRegister()!=NULL) { if (_dependencies[i].getRealRegister() == TR::RealRegister::NoReg) { virtReg->block(); } else { TR::RealRegister::RegNum assignedRegNum; assignedRegNum = toRealRegister(virtReg->getAssignedRealRegister())->getRegisterNumber(); // always block if required register and assigned register match; // block if assigned register is required by other dependency but only if // any spare registers are left to avoid blocking all existing registers if (_dependencies[i].getRealRegister() == assignedRegNum || (map.getDependencyWithTarget(assignedRegNum) && ((virtReg->getKind() != TR_GPR || block_gprs) && (virtReg->getKind() != TR_FPR || block_fprs) && (virtReg->getKind() != TR_VRF || block_vrfs)))) { virtReg->block(); } } } } // Assign all virtual regs that depend on a specific real reg that is free for (i = 0; i < numberOfRegisters; i++) { virtReg = _dependencies[i].getRegister(); dependentRegNum = _dependencies[i].getRealRegister(); dependentRealReg = machine->getPPCRealRegister(dependentRegNum); if (dependentRegNum != TR::RealRegister::NoReg && dependentRegNum != TR::RealRegister::SpilledReg && dependentRealReg->getState() == TR::RealRegister::Free) { assignFreeRegisters(currentInstruction, &_dependencies[i], map, cg); } } // Assign all virtual regs that depend on a specfic real reg that is not free for (i = 0; i < numberOfRegisters; i++) { virtReg = _dependencies[i].getRegister(); assignedRegister = NULL; if (virtReg->getAssignedRealRegister() != NULL) { assignedRegister = toRealRegister(virtReg->getAssignedRealRegister()); } dependentRegNum = _dependencies[i].getRealRegister(); dependentRealReg = machine->getPPCRealRegister(dependentRegNum); if (dependentRegNum != TR::RealRegister::NoReg && dependentRegNum != TR::RealRegister::SpilledReg && dependentRealReg != assignedRegister) { bool depsBlocked = false; switch (_dependencies[i].getRegister()->getKind()) { case TR_GPR: depsBlocked = block_gprs; break; case TR_FPR: depsBlocked = block_fprs; break; case TR_VRF: depsBlocked = block_vrfs; break; } assignContendedRegisters(currentInstruction, &_dependencies[i], map, depsBlocked, cg); } } // Assign all virtual regs that depend on NoReg but exclude gr0 for (i=0; i<numberOfRegisters; i++) { if (_dependencies[i].getRealRegister() == TR::RealRegister::NoReg && _dependencies[i].getExcludeGPR0()) { TR::RealRegister *realOne; virtReg = _dependencies[i].getRegister(); realOne = virtReg->getAssignedRealRegister(); if (realOne!=NULL && toRealRegister(realOne)->getRegisterNumber()==TR::RealRegister::gr0) { if ((assignedRegister = machine->findBestFreeRegister(currentInstruction, virtReg->getKind(), true, false, virtReg)) == NULL) { assignedRegister = machine->freeBestRegister(currentInstruction, virtReg, NULL, true); } machine->coerceRegisterAssignment(currentInstruction, virtReg, assignedRegister->getRegisterNumber()); } else if (realOne == NULL) { machine->assignOneRegister(currentInstruction, virtReg, true); } virtReg->block(); } } // Assign all virtual regs that depend on NoReg for (i=0; i<numberOfRegisters; i++) { if (_dependencies[i].getRealRegister() == TR::RealRegister::NoReg && !_dependencies[i].getExcludeGPR0()) { TR::RealRegister *realOne; virtReg = _dependencies[i].getRegister(); realOne = virtReg->getAssignedRealRegister(); if (!realOne) { machine->assignOneRegister(currentInstruction, virtReg, false); } virtReg->block(); } } unblockRegisters(numberOfRegisters); for (i = 0; i < numberOfRegisters; i++) { TR::Register *dependentRegister = getRegisterDependency(i)->getRegister(); // dependentRegister->getAssignedRegister() is NULL if the reg has already been spilled due to a spilledReg dep if (comp->getOption(TR_DisableOOL) || (!(cg->isOutOfLineColdPath()) && !(cg->isOutOfLineHotPath()))) { TR_ASSERT(dependentRegister->getAssignedRegister(), "assignedRegister can not be NULL"); } if (dependentRegister->getAssignedRegister()) { TR::RealRegister *assignedRegister = dependentRegister->getAssignedRegister()->getRealRegister(); if (getRegisterDependency(i)->getRealRegister() == TR::RealRegister::NoReg) getRegisterDependency(i)->setRealRegister(toRealRegister(assignedRegister)->getRegisterNumber()); machine->decFutureUseCountAndUnlatch(dependentRegister); } } }
static void assignContendedRegisters(TR::Instruction *currentInstruction, TR::RegisterDependency *dep, TR_PPCRegisterDependencyMap& map, bool depsBlocked, TR::CodeGenerator *cg) { // *this swipeable for debugging purposes TR::Machine *machine = cg->machine(); dep = findDependencyChainHead(dep, map); TR::Register *virtReg = dep->getRegister(); TR::RealRegister::RegNum targetRegNum = dep->getRealRegister(); TR::RealRegister *targetReg = machine->getPPCRealRegister(targetRegNum); TR::RealRegister *assignedReg = virtReg->getAssignedRealRegister() ? toRealRegister(virtReg->getAssignedRealRegister()) : NULL; // Chain of length 1 if (!assignedReg || !map.getDependencyWithTarget(assignedReg->getRegisterNumber())) { machine->coerceRegisterAssignment(currentInstruction, virtReg, targetRegNum); virtReg->block(); return; } // Chain of length 2, handled here instead of below to get 3*xor exchange on GPRs if (map.getDependencyWithTarget(assignedReg->getRegisterNumber()) == map.getDependencyWithAssigned(targetRegNum)) { TR::Register *targetVirtReg = targetReg->getAssignedRegister(); machine->coerceRegisterAssignment(currentInstruction, virtReg, targetRegNum); virtReg->block(); targetVirtReg->block(); return; } // Grab a spare reg in order to free the target of the first dep // At this point the first dep's target could be blocked, assigned, or NoReg // If it's blocked or assigned we allocate a spare and assign the target's virtual to it // If it's NoReg, the spare reg will be used as the first dep's actual target TR::RealRegister *spareReg = machine->findBestFreeRegister(currentInstruction, virtReg->getKind(), targetRegNum == TR::RealRegister::NoReg ? dep->getExcludeGPR0() : false, false, targetRegNum == TR::RealRegister::NoReg ? virtReg : targetReg->getAssignedRegister()); bool haveFreeSpare = spareReg != NULL; if (!spareReg) { // If the regs in this dep group are not blocked we need to make sure we don't spill a reg that's in the middle of the chain if (!depsBlocked) { if (targetRegNum == TR::RealRegister::NoReg) spareReg = machine->freeBestRegister(currentInstruction, map.getDependencyWithTarget(assignedReg->getRegisterNumber())->getRegister(), assignedReg, false); else spareReg = machine->freeBestRegister(currentInstruction, virtReg, targetReg, false); } else { if (targetRegNum == TR::RealRegister::NoReg) spareReg = machine->freeBestRegister(currentInstruction, virtReg, NULL, dep->getExcludeGPR0()); else spareReg = machine->freeBestRegister(currentInstruction, targetReg->getAssignedRegister(), NULL, false); } } if (targetRegNum != TR::RealRegister::NoReg && spareReg != targetReg) { machine->coerceRegisterAssignment(currentInstruction, targetReg->getAssignedRegister(), spareReg->getRegisterNumber()); } TR_ASSERT(targetRegNum == TR::RealRegister::NoReg || targetReg->getState() == TR::RealRegister::Free, "Expecting free target register"); if (depsBlocked || targetRegNum != TR::RealRegister::NoReg || haveFreeSpare) { machine->coerceRegisterAssignment(currentInstruction, virtReg, targetRegNum == TR::RealRegister::NoReg ? spareReg->getRegisterNumber() : targetRegNum); virtReg->block(); } dep = map.getDependencyWithTarget(assignedReg->getRegisterNumber()); while (dep) { virtReg = dep->getRegister(); targetRegNum = dep->getRealRegister(); targetReg = machine->getPPCRealRegister(targetRegNum); assignedReg = virtReg->getAssignedRealRegister() ? toRealRegister(virtReg->getAssignedRealRegister()) : NULL; TR_ASSERT(targetReg->getState() == TR::RealRegister::Free || targetReg == spareReg, "Expecting free target register or target to have been filled to free spare register"); machine->coerceRegisterAssignment(currentInstruction, virtReg, targetRegNum); virtReg->block(); dep = assignedReg ? map.getDependencyWithTarget(assignedReg->getRegisterNumber()) : NULL; } }
OMR::Power::RegisterDependencyConditions::RegisterDependencyConditions( TR::CodeGenerator *cg, TR::Node *node, uint32_t extranum, TR::Instruction **cursorPtr) { List<TR::Register> regList(cg->trMemory()); TR::Instruction *iCursor = (cursorPtr==NULL)?NULL:*cursorPtr; int32_t totalNum = node->getNumChildren() + extranum; int32_t i; cg->comp()->incVisitCount(); int32_t numLongs = 0; // // Pre-compute how many longs are global register candidates // for (i = 0; i < node->getNumChildren(); ++i) { TR::Node *child = node->getChild(i); TR::Register *reg = child->getRegister(); if (reg!=NULL /* && reg->getKind()==TR_GPR */) { if (child->getHighGlobalRegisterNumber() > -1) numLongs++; } } totalNum = totalNum + numLongs; _preConditions = new (totalNum, cg->trMemory()) TR_PPCRegisterDependencyGroup; _postConditions = new (totalNum, cg->trMemory()) TR_PPCRegisterDependencyGroup; _numPreConditions = totalNum; _addCursorForPre = 0; _numPostConditions = totalNum; _addCursorForPost = 0; // First, handle dependencies that match current association for (i=0; i<node->getNumChildren(); i++) { TR::Node *child = node->getChild(i); TR::Register *reg = child->getRegister(); TR::Register *highReg = NULL; TR::RealRegister::RegNum regNum = (TR::RealRegister::RegNum)cg->getGlobalRegister(child->getGlobalRegisterNumber()); TR::RealRegister::RegNum highRegNum; if (child->getHighGlobalRegisterNumber() > -1) { highRegNum = (TR::RealRegister::RegNum)cg->getGlobalRegister(child->getHighGlobalRegisterNumber()); TR::RegisterPair *regPair = reg->getRegisterPair(); TR_ASSERT(regPair, "assertion failure"); highReg = regPair->getHighOrder(); reg = regPair->getLowOrder(); if (highReg->getAssociation() != highRegNum || reg->getAssociation() != regNum) continue; } else if (reg->getAssociation() != regNum) continue; TR_ASSERT(!regList.find(reg) && (!highReg || !regList.find(highReg)), "Should not happen\n"); addPreCondition(reg, regNum); addPostCondition(reg, regNum); regList.add(reg); if (highReg) { addPreCondition(highReg, highRegNum); addPostCondition(highReg, highRegNum); regList.add(highReg); } } // Second pass to handle dependencies for which association does not exist // or does not match for (i=0; i<node->getNumChildren(); i++) { TR::Node *child = node->getChild(i); TR::Register *reg = child->getRegister(); TR::Register *highReg = NULL; TR::Register *copyReg = NULL; TR::Register *highCopyReg = NULL; TR::RealRegister::RegNum regNum = (TR::RealRegister::RegNum)cg->getGlobalRegister(child->getGlobalRegisterNumber()); TR::RealRegister::RegNum highRegNum; if (child->getHighGlobalRegisterNumber() > -1) { highRegNum = (TR::RealRegister::RegNum)cg->getGlobalRegister(child->getHighGlobalRegisterNumber()); TR::RegisterPair *regPair = reg->getRegisterPair(); TR_ASSERT(regPair, "assertion failure"); highReg = regPair->getHighOrder(); reg = regPair->getLowOrder(); if (highReg->getAssociation() == highRegNum && reg->getAssociation() == regNum) continue; } else if (reg->getAssociation() == regNum) continue; if (regList.find(reg) || (highReg && regList.find(highReg))) { TR::InstOpCode::Mnemonic opCode; TR_RegisterKinds kind = reg->getKind(); switch (kind) { case TR_GPR: opCode = TR::InstOpCode::mr; break; case TR_FPR: opCode = TR::InstOpCode::fmr; break; case TR_VRF: opCode = TR::InstOpCode::vor; //TR_ASSERT(0, "VMX not fully supported."); break; case TR_VSX_VECTOR: opCode = TR::InstOpCode::xxlor; break; case TR_CCR: opCode = TR::InstOpCode::mcrf; break; default: TR_ASSERT(0, "Invalid register kind."); } if (regList.find(reg)) { bool containsInternalPointer = false; if (reg->getPinningArrayPointer()) containsInternalPointer = true; copyReg = (reg->containsCollectedReference() && !containsInternalPointer) ? cg->allocateCollectedReferenceRegister() : cg->allocateRegister(kind); if (containsInternalPointer) { copyReg->setContainsInternalPointer(); copyReg->setPinningArrayPointer(reg->getPinningArrayPointer()); } if (opCode == TR::InstOpCode::vor || opCode == TR::InstOpCode::xxlor) iCursor = generateTrg1Src2Instruction(cg, opCode, node, copyReg, reg, reg, iCursor); else iCursor = generateTrg1Src1Instruction(cg, opCode, node, copyReg, reg, iCursor); reg = copyReg; } if (highReg && regList.find(highReg)) { bool containsInternalPointer = false; if (highReg->getPinningArrayPointer()) containsInternalPointer = true; highCopyReg = (highReg->containsCollectedReference() && !containsInternalPointer) ? cg->allocateCollectedReferenceRegister() : cg->allocateRegister(kind); if (containsInternalPointer) { highCopyReg->setContainsInternalPointer(); highCopyReg->setPinningArrayPointer(highReg->getPinningArrayPointer()); } if (opCode == TR::InstOpCode::vor || opCode == TR::InstOpCode::xxlor) iCursor = generateTrg1Src2Instruction(cg, opCode, node, highCopyReg, highReg, highReg, iCursor); else iCursor = generateTrg1Src1Instruction(cg, opCode, node, highCopyReg, highReg, iCursor); highReg = highCopyReg; } } addPreCondition(reg, regNum); addPostCondition(reg, regNum); if (copyReg != NULL) cg->stopUsingRegister(copyReg); else regList.add(reg); if (highReg) { addPreCondition(highReg, highRegNum); addPostCondition(highReg, highRegNum); if (highCopyReg != NULL) cg->stopUsingRegister(highCopyReg); else regList.add(highReg); } } if (iCursor!=NULL && cursorPtr!=NULL) *cursorPtr = iCursor; }
TR::Register *IA32LinkageUtils::pushDoubleArg( TR::Node *child, TR::CodeGenerator *cg) { TR::Register *pushRegister; if (child->getRegister() == NULL) { if (child->getOpCodeValue() == TR::dconst) { TR_X86OpCodes pushOp; int32_t highValue = child->getLongIntHigh(); if (highValue >= -128 && highValue <= 127) { pushOp = PUSHImms; } else { pushOp = PUSHImm4; } generateImmInstruction(pushOp, child, highValue, cg); int32_t lowValue = child->getLongIntLow(); if (lowValue >= -128 && lowValue <= 127) { pushOp = PUSHImms; } else { pushOp = PUSHImm4; } generateImmInstruction(pushOp, child, lowValue, cg); cg->decReferenceCount(child); return NULL; } else if (child->getReferenceCount() == 1) { if (child->getOpCode().isLoad()) { TR::MemoryReference *lowMR = generateX86MemoryReference(child, cg); generateMemInstruction(PUSHMem, child, generateX86MemoryReference(*lowMR, 4, cg), cg); generateMemInstruction(PUSHMem, child, lowMR, cg); lowMR->decNodeReferenceCounts(cg); cg->decReferenceCount(child); return NULL; } else if (child->getOpCodeValue() == TR::lbits2d) { pushRegister = pushLongArg(child->getFirstChild(), cg); cg->decReferenceCount(child); return pushRegister; } } } pushRegister = cg->evaluate(child); TR::RealRegister *espReal = cg->machine()->getRealRegister(TR::RealRegister::esp); generateRegImmInstruction(SUB4RegImms, child, espReal, 8, cg); if (cg->useSSEForSinglePrecision() && pushRegister->getKind() == TR_FPR) generateMemRegInstruction(MOVSDMemReg, child, generateX86MemoryReference(espReal, 0, cg), pushRegister, cg); else generateFPMemRegInstruction(DSTMemReg, child, generateX86MemoryReference(espReal, 0, cg), pushRegister, cg); cg->decReferenceCount(child); return pushRegister; }
void TR_ARMRegisterDependencyGroup::assignRegisters(TR::Instruction *currentInstruction, TR_RegisterKinds kindToBeAssigned, uint32_t numberOfRegisters, TR::CodeGenerator *cg) { TR::Compilation *comp = cg->comp(); TR::Machine *machine = cg->machine(); TR::Register *virtReg; TR::RealRegister::RegNum dependentRegNum; TR::RealRegister *dependentRealReg, *assignedRegister; uint32_t i, j; bool changed; if (!comp->getOption(TR_DisableOOL)) { for (i = 0; i< numberOfRegisters; i++) { virtReg = dependencies[i].getRegister(); dependentRegNum = dependencies[i].getRealRegister(); if (dependentRegNum == TR::RealRegister::SpilledReg) { TR_ASSERT(virtReg->getBackingStorage(),"should have a backing store if dependentRegNum == spillRegIndex()\n"); if (virtReg->getAssignedRealRegister()) { // this happens when the register was first spilled in main line path then was reverse spilled // and assigned to a real register in OOL path. We protected the backing store when doing // the reverse spill so we could re-spill to the same slot now traceMsg (comp,"\nOOL: Found register spilled in main line and re-assigned inside OOL"); TR::Node *currentNode = currentInstruction->getNode(); TR::RealRegister *assignedReg = toRealRegister(virtReg->getAssignedRegister()); TR::MemoryReference *tempMR = new (cg->trHeapMemory()) TR::MemoryReference(currentNode, (TR::SymbolReference*)virtReg->getBackingStorage()->getSymbolReference(), sizeof(uintptr_t), cg); TR_ARMOpCodes opCode; TR_RegisterKinds rk = virtReg->getKind(); switch (rk) { case TR_GPR: opCode = ARMOp_ldr; break; case TR_FPR: opCode = virtReg->isSinglePrecision() ? ARMOp_ldfs : ARMOp_ldfd; break; default: TR_ASSERT(0, "\nRegister kind not supported in OOL spill\n"); break; } TR::Instruction *inst = generateTrg1MemInstruction(cg, opCode, currentNode, assignedReg, tempMR, currentInstruction); assignedReg->setAssignedRegister(NULL); virtReg->setAssignedRegister(NULL); assignedReg->setState(TR::RealRegister::Free); if (comp->getDebug()) cg->traceRegisterAssignment("Generate reload of virt %s due to spillRegIndex dep at inst %p\n", cg->comp()->getDebug()->getName(virtReg),currentInstruction); cg->traceRAInstruction(inst); } if (!(std::find(cg->getSpilledRegisterList()->begin(), cg->getSpilledRegisterList()->end(), virtReg) != cg->getSpilledRegisterList()->end())) cg->getSpilledRegisterList()->push_front(virtReg); } // we also need to free up all locked backing storage if we are exiting the OOL during backwards RA assignment else if (currentInstruction->isLabel() && virtReg->getAssignedRealRegister()) { TR::ARMLabelInstruction *labelInstr = (TR::ARMLabelInstruction *)currentInstruction; TR_BackingStore *location = virtReg->getBackingStorage(); TR_RegisterKinds rk = virtReg->getKind(); int32_t dataSize; if (labelInstr->getLabelSymbol()->isStartOfColdInstructionStream() && location) { traceMsg (comp,"\nOOL: Releasing backing storage (%p)\n", location); if (rk == TR_GPR) dataSize = TR::Compiler->om.sizeofReferenceAddress(); else dataSize = 8; location->setMaxSpillDepth(0); cg->freeSpill(location,dataSize,0); virtReg->setBackingStorage(NULL); } } } } for (i = 0; i < numberOfRegisters; i++) { virtReg = dependencies[i].getRegister(); if (virtReg->getAssignedRealRegister()!=NULL) { if (dependencies[i].getRealRegister() == TR::RealRegister::NoReg) { virtReg->block(); } else { dependentRegNum = toRealRegister(virtReg->getAssignedRealRegister())->getRegisterNumber(); for (j=0; j<numberOfRegisters; j++) { if (dependentRegNum == dependencies[j].getRealRegister()) { virtReg->block(); break; } } } } } do { changed = false; for (i = 0; i < numberOfRegisters; i++) { virtReg = dependencies[i].getRegister(); dependentRegNum = dependencies[i].getRealRegister(); dependentRealReg = machine->getRealRegister(dependentRegNum); if (dependentRegNum != TR::RealRegister::NoReg && dependentRegNum != TR::RealRegister::SpilledReg && dependentRealReg->getState() == TR::RealRegister::Free) { machine->coerceRegisterAssignment(currentInstruction, virtReg, dependentRegNum); virtReg->block(); changed = true; } } } while (changed == true); do { changed = false; for (i = 0; i < numberOfRegisters; i++) { virtReg = dependencies[i].getRegister(); assignedRegister = NULL; if (virtReg->getAssignedRealRegister() != NULL) { assignedRegister = toRealRegister(virtReg->getAssignedRealRegister()); } dependentRegNum = dependencies[i].getRealRegister(); dependentRealReg = machine->getRealRegister(dependentRegNum); if (dependentRegNum != TR::RealRegister::NoReg && dependentRegNum != TR::RealRegister::SpilledReg && dependentRealReg != assignedRegister) { machine->coerceRegisterAssignment(currentInstruction, virtReg, dependentRegNum); virtReg->block(); changed = true; } } } while (changed == true); for (i=0; i<numberOfRegisters; i++) { if (dependencies[i].getRealRegister() == TR::RealRegister::NoReg) { bool excludeGPR0 = dependencies[i].getExcludeGPR0()?true:false; TR::RealRegister *realOne; virtReg = dependencies[i].getRegister(); realOne = virtReg->getAssignedRealRegister(); if (realOne!=NULL && excludeGPR0 && toRealRegister(realOne)->getRegisterNumber()==TR::RealRegister::gr0) { if ((assignedRegister = machine->findBestFreeRegister(virtReg->getKind(), true)) == NULL) { assignedRegister = machine->freeBestRegister(currentInstruction, virtReg->getKind(), NULL, true); } machine->coerceRegisterAssignment(currentInstruction, virtReg, assignedRegister->getRegisterNumber()); } else if (realOne == NULL) { if (virtReg->getTotalUseCount() == virtReg->getFutureUseCount()) { if ((assignedRegister = machine->findBestFreeRegister(virtReg->getKind(), excludeGPR0, true)) == NULL) { assignedRegister = machine->freeBestRegister(currentInstruction, virtReg->getKind(), NULL, excludeGPR0); } } else { assignedRegister = machine->reverseSpillState(currentInstruction, virtReg, NULL, excludeGPR0); } virtReg->setAssignedRegister(assignedRegister); assignedRegister->setAssignedRegister(virtReg); assignedRegister->setState(TR::RealRegister::Assigned); virtReg->block(); } } } unblockRegisters(numberOfRegisters); for (i = 0; i < numberOfRegisters; i++) { TR::Register *dependentRegister = getRegisterDependency(i)->getRegister(); if (dependentRegister->getAssignedRegister()) { TR::RealRegister *assignedRegister = dependentRegister->getAssignedRegister()->getRealRegister(); if (getRegisterDependency(i)->getRealRegister() == TR::RealRegister::NoReg) getRegisterDependency(i)->setRealRegister(toRealRegister(assignedRegister)->getRegisterNumber()); if (dependentRegister->decFutureUseCount() == 0) { dependentRegister->setAssignedRegister(NULL); assignedRegister->setAssignedRegister(NULL); assignedRegister->setState(TR::RealRegister::Unlatched); // Was setting to Free } } } }