void TR::ARMSystemLinkage::createEpilogue(TR::Instruction *cursor) { TR::CodeGenerator *codeGen = cg(); const TR::ARMLinkageProperties& properties = getProperties(); TR::Machine *machine = codeGen->machine(); TR::Node *lastNode = cursor->getNode(); TR::ResolvedMethodSymbol* bodySymbol = comp()->getJittedMethodSymbol(); TR::RealRegister *stackPtr = machine->getRealRegister(properties.getStackPointerRegister()); // restore link register (r14) auto *stackSlot = new (trHeapMemory()) TR::MemoryReference(stackPtr, bodySymbol->getLocalMappingCursor(), codeGen); cursor = generateMemSrc1Instruction(cg(), ARMOp_ldr, lastNode, stackSlot, machine->getRealRegister(TR::RealRegister::gr14), cursor); // restore all preserved registers for (int r = TR::RealRegister::gr4; r <= TR::RealRegister::gr11; ++r) { auto *stackSlot = new (trHeapMemory()) TR::MemoryReference(stackPtr, (TR::RealRegister::gr11 - r + 1)*4 + bodySymbol->getLocalMappingCursor(), codeGen); cursor = generateMemSrc1Instruction(cg(), ARMOp_ldr, lastNode, stackSlot, machine->getRealRegister((TR::RealRegister::RegNum)r), cursor); } // remove space for preserved registers auto frameSize = codeGen->getFrameSizeInBytes(); cursor = generateTrg1Src1ImmInstruction(codeGen, ARMOp_add, lastNode, stackPtr, stackPtr, frameSize, 0, cursor); // return using `mov r15, r14` TR::RealRegister *gr14 = machine->getRealRegister(TR::RealRegister::gr14); TR::RealRegister *gr15 = machine->getRealRegister(TR::RealRegister::gr15); cursor = generateTrg1Src1Instruction(codeGen, ARMOp_mov, lastNode, gr15, gr14, cursor); }
void TR::ARM64Trg1Src2Instruction::assignRegisters(TR_RegisterKinds kindToBeAssigned) { TR::Machine *machine = cg()->machine(); TR::Register *target1Virtual = getTargetRegister(); TR::Register *source1Virtual = getSource1Register(); TR::Register *source2Virtual = getSource2Register(); if (getDependencyConditions()) getDependencyConditions()->assignPostConditionRegisters(this, kindToBeAssigned, cg()); source1Virtual->block(); target1Virtual->block(); TR::RealRegister *assignedSource2Register = machine->assignOneRegister(this, source2Virtual); target1Virtual->unblock(); source1Virtual->unblock(); source2Virtual->block(); target1Virtual->block(); TR::RealRegister *assignedSource1Register = machine->assignOneRegister(this, source1Virtual); target1Virtual->unblock(); source2Virtual->unblock(); source2Virtual->block(); source1Virtual->block(); TR::RealRegister *assignedTarget1Register = machine->assignOneRegister(this, target1Virtual); source1Virtual->unblock(); source2Virtual->unblock(); if (getDependencyConditions()) getDependencyConditions()->assignPreConditionRegisters(this->getPrev(), kindToBeAssigned, cg()); setTargetRegister(assignedTarget1Register); setSource1Register(assignedSource1Register); setSource2Register(assignedSource2Register); }
void TR::ARM64MemSrc1Instruction::assignRegisters(TR_RegisterKinds kindToBeAssigned) { TR::Machine *machine = cg()->machine(); TR::MemoryReference *mref = getMemoryReference(); TR::Register *sourceVirtual = getSource1Register(); if (getDependencyConditions()) getDependencyConditions()->assignPostConditionRegisters(this, kindToBeAssigned, cg()); sourceVirtual->block(); mref->assignRegisters(this, cg()); sourceVirtual->unblock(); mref->blockRegisters(); TR::RealRegister *assignedRegister = sourceVirtual->getAssignedRealRegister(); if (assignedRegister == NULL) { assignedRegister = machine->assignOneRegister(this, sourceVirtual); } mref->unblockRegisters(); setSource1Register(assignedRegister); if (getDependencyConditions()) getDependencyConditions()->assignPreConditionRegisters(this->getPrev(), kindToBeAssigned, cg()); }
void TR::ARM64Trg1Instruction::assignRegisters(TR_RegisterKinds kindToBeAssigned) { if (getDependencyConditions()) getDependencyConditions()->assignPostConditionRegisters(this, kindToBeAssigned, cg()); TR::Machine *machine = cg()->machine(); TR::Register *targetVirtual = getTargetRegister(); setTargetRegister(machine->assignOneRegister(this, targetVirtual)); if (getDependencyConditions()) getDependencyConditions()->assignPreConditionRegisters(this->getPrev(), kindToBeAssigned, cg()); }
TR::MemoryReference *OMR::Power::Linkage::getOutgoingArgumentMemRef(int32_t argSize, TR::Register *argReg, TR::InstOpCode::Mnemonic opCode, TR::PPCMemoryArgument &memArg, uint32_t length) { TR::Machine *machine = self()->machine(); const TR::PPCLinkageProperties& properties = self()->getProperties(); TR::MemoryReference *result = new (self()->trHeapMemory()) TR::MemoryReference(machine->getRealRegister(properties.getNormalStackPointerRegister()), argSize+properties.getOffsetToFirstParm(), length, self()->cg()); memArg.argRegister = argReg; memArg.argMemory = result; memArg.opCode = opCode; return(result); }
void TR::ARM64SystemLinkage::createEpilogue(TR::Instruction *cursor) { TR::CodeGenerator *codeGen = cg(); const TR::ARM64LinkageProperties& properties = getProperties(); TR::Machine *machine = codeGen->machine(); TR::Node *lastNode = cursor->getNode(); TR::ResolvedMethodSymbol *bodySymbol = comp()->getJittedMethodSymbol(); TR::RealRegister *sp = machine->getRealRegister(properties.getStackPointerRegister()); // restore callee-saved registers uint32_t offset = bodySymbol->getLocalMappingCursor() + 8; // +8 for LR for (int r = TR::RealRegister::x19; r <= TR::RealRegister::x28; r++) { TR::RealRegister *rr = machine->getRealRegister((TR::RealRegister::RegNum)r); if (rr->getHasBeenAssignedInMethod()) { TR::MemoryReference *stackSlot = new (trHeapMemory()) TR::MemoryReference(sp, offset, codeGen); cursor = generateTrg1MemInstruction(cg(), TR::InstOpCode::ldrimmx, lastNode, rr, stackSlot, cursor); offset += 8; } } for (int r = TR::RealRegister::v8; r <= TR::RealRegister::v15; r++) { TR::RealRegister *rr = machine->getRealRegister((TR::RealRegister::RegNum)r); if (rr->getHasBeenAssignedInMethod()) { TR::MemoryReference *stackSlot = new (trHeapMemory()) TR::MemoryReference(sp, offset, codeGen); cursor = generateTrg1MemInstruction(cg(), TR::InstOpCode::vldrimmd, lastNode, rr, stackSlot, cursor); offset += 8; } } // restore link register (x30) TR::RealRegister *lr = machine->getRealRegister(TR::RealRegister::lr); TR::MemoryReference *stackSlot = new (trHeapMemory()) TR::MemoryReference(sp, bodySymbol->getLocalMappingCursor(), codeGen); cursor = generateTrg1MemInstruction(cg(), TR::InstOpCode::ldrimmx, lastNode, lr, stackSlot, cursor); // remove space for preserved registers uint32_t frameSize = codeGen->getFrameSizeInBytes(); if (constantIsUnsignedImm12(frameSize)) { cursor = generateTrg1Src1ImmInstruction(codeGen, TR::InstOpCode::addimmx, lastNode, sp, sp, frameSize, cursor); } else { TR_ASSERT(false, "Not implemented yet."); } // return cursor = generateRegBranchInstruction(codeGen, TR::InstOpCode::ret, lastNode, lr, cursor); }
void TR::ARM64SystemLinkage::initARM64RealRegisterLinkage() { TR::Machine *machine = cg()->machine(); TR::RealRegister *reg; int icount; reg = machine->getRealRegister(TR::RealRegister::RegNum::x16); // IP0 reg->setState(TR::RealRegister::Locked); reg->setAssignedRegister(reg); reg = machine->getRealRegister(TR::RealRegister::RegNum::x17); // IP1 reg->setState(TR::RealRegister::Locked); reg->setAssignedRegister(reg); reg = machine->getRealRegister(TR::RealRegister::RegNum::x29); // FP reg->setState(TR::RealRegister::Locked); reg->setAssignedRegister(reg); reg = machine->getRealRegister(TR::RealRegister::RegNum::x30); // LR reg->setState(TR::RealRegister::Locked); reg->setAssignedRegister(reg); reg = machine->getRealRegister(TR::RealRegister::RegNum::sp); // SP reg->setState(TR::RealRegister::Locked); reg->setAssignedRegister(reg); reg = machine->getRealRegister(TR::RealRegister::RegNum::xzr); // zero reg->setState(TR::RealRegister::Locked); reg->setAssignedRegister(reg); // assign "maximum" weight to registers x0-x15 for (icount = TR::RealRegister::x0; icount <= TR::RealRegister::x15; icount++) machine->getRealRegister((TR::RealRegister::RegNum)icount)->setWeight(0xf000); // assign "maximum" weight to registers x18-x28 for (icount = TR::RealRegister::x18; icount <= TR::RealRegister::x28; icount++) machine->getRealRegister((TR::RealRegister::RegNum)icount)->setWeight(0xf000); // assign "maximum" weight to registers v0-v31 for (icount = TR::RealRegister::v0; icount <= TR::RealRegister::v31; icount++) machine->getRealRegister((TR::RealRegister::RegNum)icount)->setWeight(0xf000); }
static void assignFreeRegisters(TR::Instruction *currentInstruction, TR::RegisterDependency *dep, TR_PPCRegisterDependencyMap& map, TR::CodeGenerator *cg) { // *this swipeable for debugging purposes TR::Machine *machine = cg->machine(); // Assign a chain of dependencies where the head of the chain depends on a free reg while (dep) { TR_ASSERT(machine->getPPCRealRegister(dep->getRealRegister())->getState() == TR::RealRegister::Free, "Expecting free target register"); TR::RealRegister *assignedReg = dep->getRegister()->getAssignedRealRegister() ? toRealRegister(dep->getRegister()->getAssignedRealRegister()) : NULL; machine->coerceRegisterAssignment(currentInstruction, dep->getRegister(), dep->getRealRegister()); dep->getRegister()->block(); dep = assignedReg ? map.getDependencyWithTarget(assignedReg->getRegisterNumber()) : NULL; } }
void TR::ARM64Trg1MemInstruction::assignRegisters(TR_RegisterKinds kindToBeAssigned) { TR::Machine *machine = cg()->machine(); TR::MemoryReference *mref = getMemoryReference(); TR::Register *targetVirtual = getTargetRegister(); if (getDependencyConditions()) getDependencyConditions()->assignPostConditionRegisters(this, kindToBeAssigned, cg()); mref->blockRegisters(); setTargetRegister(machine->assignOneRegister(this, targetVirtual)); mref->unblockRegisters(); targetVirtual->block(); mref->assignRegisters(this, cg()); targetVirtual->unblock(); if (getDependencyConditions()) getDependencyConditions()->assignPreConditionRegisters(this->getPrev(), kindToBeAssigned, cg()); }
void TR::ARMSystemLinkage::initARMRealRegisterLinkage() { TR::Machine *machine = cg()->machine(); // make r15 (PC) unavailable for RA TR::RealRegister *reg = machine->getRealRegister(TR::RealRegister::gr15); reg->setState(TR::RealRegister::Locked); reg->setAssignedRegister(reg); // make r14 (LR) unavailable for RA reg = machine->getRealRegister(TR::RealRegister::gr14); reg->setState(TR::RealRegister::Locked); reg->setAssignedRegister(reg); // make r13 (SP) unavailable for RA reg = machine->getRealRegister(TR::RealRegister::gr13); reg->setState(TR::RealRegister::Locked); reg->setAssignedRegister(reg); // make r12 (IP) unavailable for RA reg = machine->getRealRegister(TR::RealRegister::gr12); reg->setState(TR::RealRegister::Locked); reg->setAssignedRegister(reg); // make r9 unavailable for RA (just in case, because it's meaning is platform defined) reg = machine->getRealRegister(TR::RealRegister::gr9); reg->setState(TR::RealRegister::Locked); reg->setAssignedRegister(reg); /* * Note: we can assign the same weight to all registers because loads/stores * can be done on multiple registers simultaneously. */ // assign "maximum" weight to registers r0-r8 for (int32_t r = TR::RealRegister::gr0; r <= TR::RealRegister::gr8; ++r) { machine->getRealRegister(static_cast<TR::RealRegister::RegNum>(r))->setWeight(0xf000); } // assign "maximum" weight to registers r10-r12 for (int32_t r = TR::RealRegister::gr10; r <= TR::RealRegister::gr12; ++r) { machine->getRealRegister(static_cast<TR::RealRegister::RegNum>(r))->setWeight(0xf000); } }
void OMR::Power::RegisterDependencyConditions::bookKeepingRegisterUses(TR::Instruction *instr, TR::CodeGenerator *cg) { // *this swipeable for debugging purposes TR::Register *virtReg; TR::RealRegister::RegNum regNum; TR::RegisterDependencyConditions *assoc; int numAssoc = 0; if (instr->getOpCodeValue() == TR::InstOpCode::assocreg) return; // Don't track associations or emit assocregs in outlined code // Register assigner can save/restore associations across outlined sections properly, however no such mechanism exists for instruction selection // so we don't want these associations to clobber the associations that were set in main line code, which are more important // TODO: Fix this by saving/restoring the associations in swapInstructionListsWithCompilation() bool isOOL = cg->getIsInOOLSection(); TR::Machine *machine = cg->machine(); assoc = !isOOL ? new (cg->trHeapMemory()) TR::RegisterDependencyConditions(0,_addCursorForPre, cg->trMemory()) : 0; for (int i = 0; i < _addCursorForPre; i++) { virtReg = _preConditions->getRegisterDependency(i)->getRegister(); regNum = _preConditions->getRegisterDependency(i)->getRealRegister(); if (!isOOL) { // Add to the association condition when the association is changed // from one virtual register to another if (machine->getVirtualAssociatedWithReal(regNum) != virtReg && machine->getVirtualAssociatedWithReal(regNum) != 0) { assoc->addPostCondition(machine->getVirtualAssociatedWithReal(regNum), regNum); numAssoc++; } // Keep track of the virtual register map to real registers! machine->setVirtualAssociatedWithReal(regNum, virtReg); } instr->useRegister(virtReg); if (!isOOL) { cg->setRealRegisterAssociation(virtReg, regNum); if (_preConditions->getRegisterDependency(i)->getExcludeGPR0()) cg->addRealRegisterInterference(virtReg, TR::RealRegister::gr0); } } if (numAssoc > 0) { // Emit an AssocRegs instruction to track the previous association assoc->setNumPostConditions(numAssoc, cg->trMemory()); generateDepInstruction(cg, TR::InstOpCode::assocreg, instr->getNode(), assoc, instr->getPrev()); } for (int j = 0; j < _addCursorForPost; j++) { virtReg = _postConditions->getRegisterDependency(j)->getRegister(); regNum = _postConditions->getRegisterDependency(j)->getRealRegister(); instr->useRegister(virtReg); if (!isOOL) { cg->setRealRegisterAssociation(virtReg, regNum); if (_postConditions->getRegisterDependency(j)->getExcludeGPR0()) cg->addRealRegisterInterference(virtReg, TR::RealRegister::gr0); } } }
void OMR::X86::Instruction::assignRegisters(TR_RegisterKinds kindsToBeAssigned) { if (!self()->getDependencyConditions()) { // Fast path when there are no dependency conditions. // return; } if (self()->getOpCodeValue() != ASSOCREGS) { self()->aboutToAssignRegDeps(); if ((self()->cg()->getAssignmentDirection() == self()->cg()->Backward)) { self()->getDependencyConditions()->assignPostConditionRegisters(self(), kindsToBeAssigned, self()->cg()); self()->getDependencyConditions()->assignPreConditionRegisters(self(), kindsToBeAssigned, self()->cg()); } else { self()->getDependencyConditions()->assignPreConditionRegisters(self()->getPrev(), kindsToBeAssigned, self()->cg()); self()->getDependencyConditions()->assignPostConditionRegisters(self(), kindsToBeAssigned, self()->cg()); } } else if ((self()->getOpCodeValue() == ASSOCREGS) && self()->cg()->enableRegisterAssociations()) { if (kindsToBeAssigned & TR_GPR_Mask) { TR::Machine *machine = self()->cg()->machine(); // First traverse the existing associations and remove them // so that they don't interfere with the new ones // for (int i = TR::RealRegister::FirstGPR; i <= TR::RealRegister::LastAssignableGPR; ++i) { // Skip non-assignable registers // if (machine->getX86RealRegister((TR::RealRegister::RegNum)i)->getState() == TR::RealRegister::Locked) continue; TR::Register *virtReg = machine->getVirtualAssociatedWithReal((TR::RealRegister::RegNum)i); if (virtReg) { virtReg->setAssociation(TR::RealRegister::NoReg); } } // Next loop through and set up the new associations (both on the machine // and by associating the virtual registers with their real dependencies) // TR_X86RegisterDependencyGroup *depGroup = self()->getDependencyConditions()->getPostConditions(); for (int j = 0; j < self()->getDependencyConditions()->getNumPostConditions(); ++j) { TR::RegisterDependency *dep = depGroup->getRegisterDependency(j); machine->setVirtualAssociatedWithReal(dep->getRealRegister(), dep->getRegister()); } machine->setGPRWeightsFromAssociations(); } } }
void TR_Debug::print(TR::FILE *pOutFile, TR::AMD64FPConversionSnippet * snippet) { if (pOutFile == NULL) return; uint8_t *bufferPos = snippet->getSnippetLabel()->getCodeLocation(); printSnippetLabel(pOutFile, snippet->getSnippetLabel(), bufferPos, getName(snippet)); TR::Machine *machine = _cg->machine(); TR::RealRegister *sourceRegister = toRealRegister(snippet->getConvertInstruction()->getSourceRegister()); TR::RealRegister *targetRegister = toRealRegister(snippet->getConvertInstruction()->getTargetRegister()); uint8_t sreg = sourceRegister->getRegisterNumber(); uint8_t treg = targetRegister->getRegisterNumber(); TR::ILOpCodes opCode = snippet->getConvertInstruction()->getNode()->getOpCodeValue(); TR_RegisterSizes size = TR_DoubleWordReg; if (treg != TR::RealRegister::eax) { int instrSize = IS_REX(*bufferPos)? 3 : 2; printPrefix(pOutFile, NULL, bufferPos, instrSize); trfprintf(pOutFile, "mov \t"); print(pOutFile, targetRegister, size); trfprintf(pOutFile, ", "); print(pOutFile, machine->getX86RealRegister(TR::RealRegister::eax), size); trfprintf(pOutFile, "\t%s preserve helper return reg", commentString()); bufferPos += instrSize; } if (sreg != TR::RealRegister::xmm0) { printPrefix(pOutFile, NULL, bufferPos, 4); trfprintf(pOutFile, "sub \trsp, 8"); printPrefix(pOutFile, NULL, bufferPos, 5); trfprintf(pOutFile, "movsd\t[rsp], xmm0\t%s save xmm0", commentString()); bufferPos += 9; int instrSize = IS_REX(*bufferPos)? 5 : 4; printPrefix(pOutFile, NULL, bufferPos, instrSize); trfprintf(pOutFile, "movsd\txmm0, "); print(pOutFile, sourceRegister, TR_QuadWordReg); trfprintf(pOutFile, "\t%s load parameter", commentString()); bufferPos += instrSize; } printPrefix(pOutFile, NULL, bufferPos, 5); trfprintf(pOutFile, "call\t%s", getName(snippet->getHelperSymRef())); bufferPos += 5; if (sreg != TR::RealRegister::xmm0) { printPrefix(pOutFile, NULL, bufferPos, 5); trfprintf(pOutFile, "movsd\txmm0, [rsp]\t%s restore xmm0", commentString()); printPrefix(pOutFile, NULL, bufferPos, 4); trfprintf(pOutFile, "add \trsp, 8"); bufferPos += 9; } if (treg != TR::RealRegister::eax) { int instrSize = IS_REX(*bufferPos)? 2 : 1; printPrefix(pOutFile, NULL, bufferPos, instrSize); trfprintf(pOutFile, "xchg\t"); print(pOutFile, targetRegister, size); trfprintf(pOutFile, ", "); print(pOutFile, machine->getX86RealRegister(TR::RealRegister::eax), size); trfprintf(pOutFile, "\t%s restore result reg & put result in target reg", commentString()); bufferPos += instrSize; } printRestartJump(pOutFile, snippet, bufferPos); }
void TR::ARMSystemLinkage::createPrologue(TR::Instruction *cursor) { TR::CodeGenerator *codeGen = cg(); const TR::ARMLinkageProperties& properties = getProperties(); TR::Machine *machine = codeGen->machine(); TR::ResolvedMethodSymbol* bodySymbol = comp()->getJittedMethodSymbol(); TR::Node *firstNode = comp()->getStartTree()->getNode(); TR::RealRegister *stackPtr = machine->getRealRegister(properties.getStackPointerRegister()); // Entry breakpoint // if (comp()->getOption(TR_EntryBreakPoints)) { cursor = new (trHeapMemory()) TR::Instruction(cursor, ARMOp_bad, firstNode, cg()); } // allocate stack space auto frameSize = codeGen->getFrameSizeInBytes(); cursor = generateTrg1Src1ImmInstruction(codeGen, ARMOp_sub, firstNode, stackPtr, stackPtr, frameSize, 0, cursor); // spill argument registers auto nextIntArgReg = 0; auto nextFltArgReg = 0; ListIterator<TR::ParameterSymbol> parameterIterator(&bodySymbol->getParameterList()); for (TR::ParameterSymbol *parameter = parameterIterator.getFirst(); parameter!=NULL && (nextIntArgReg < getProperties().getNumIntArgRegs() || nextFltArgReg < getProperties().getNumFloatArgRegs()); parameter=parameterIterator.getNext()) { auto *stackSlot = new (trHeapMemory()) TR::MemoryReference(stackPtr, parameter->getParameterOffset(), codeGen); switch (parameter->getDataType()) { case TR::Int8: case TR::Int16: case TR::Int32: case TR::Address: if (nextIntArgReg < getProperties().getNumIntArgRegs()) { cursor = generateMemSrc1Instruction(cg(), ARMOp_str, firstNode, stackSlot, machine->getRealRegister((TR::RealRegister::RegNum)(TR::RealRegister::gr0 + nextIntArgReg)), cursor); nextIntArgReg++; } else { nextIntArgReg = getProperties().getNumIntArgRegs() + 1; } break; case TR::Int64: nextIntArgReg += nextIntArgReg & 0x1; // round to next even number if (nextIntArgReg + 1 < getProperties().getNumIntArgRegs()) { cursor = generateMemSrc1Instruction(cg(), ARMOp_str, firstNode, stackSlot, machine->getRealRegister((TR::RealRegister::RegNum)(TR::RealRegister::gr0 + nextIntArgReg)), cursor); stackSlot = new (trHeapMemory()) TR::MemoryReference(stackPtr, parameter->getParameterOffset() + 4, codeGen); cursor = generateMemSrc1Instruction(cg(), ARMOp_str, firstNode, stackSlot, machine->getRealRegister((TR::RealRegister::RegNum)(TR::RealRegister::gr0 + nextIntArgReg + 1)), cursor); nextIntArgReg += 2; } else { nextIntArgReg = getProperties().getNumIntArgRegs() + 1; } break; case TR::Float: comp()->failCompilation<UnsupportedParameterType>("Compiling methods with a single precision floating point parameter is not supported"); break; case TR::Double: if (nextFltArgReg < getProperties().getNumFloatArgRegs()) { cursor = generateMemSrc1Instruction(cg(), ARMOp_fstd, firstNode, stackSlot, machine->getRealRegister((TR::RealRegister::RegNum)(TR::RealRegister::fp0 + nextFltArgReg)), cursor); nextFltArgReg += 1; } else { nextFltArgReg = getProperties().getNumFloatArgRegs() + 1; } break; case TR::Aggregate: TR_ASSERT(false, "Function parameters of aggregate types are not currently supported on ARM."); } } // save all preserved registers for (int r = TR::RealRegister::gr4; r <= TR::RealRegister::gr11; ++r) { auto *stackSlot = new (trHeapMemory()) TR::MemoryReference(stackPtr, (TR::RealRegister::gr11 - r + 1)*4 + bodySymbol->getLocalMappingCursor(), codeGen); cursor = generateMemSrc1Instruction(cg(), ARMOp_str, firstNode, stackSlot, machine->getRealRegister((TR::RealRegister::RegNum)r), cursor); } // save link register (r14) auto *stackSlot = new (trHeapMemory()) TR::MemoryReference(stackPtr, bodySymbol->getLocalMappingCursor(), codeGen); cursor = generateMemSrc1Instruction(cg(), ARMOp_str, firstNode, stackSlot, machine->getRealRegister(TR::RealRegister::gr14), cursor); }
TR::Instruction *OMR::Power::Linkage::flushArguments(TR::Instruction *cursor) { TR::Machine *machine = self()->machine(); TR::RealRegister *stackPtr = self()->cg()->getStackPointerRegister(); TR::ResolvedMethodSymbol *bodySymbol = self()->comp()->getJittedMethodSymbol(); ListIterator<TR::ParameterSymbol> paramIterator(&(bodySymbol->getParameterList())); TR::ParameterSymbol *paramCursor = paramIterator.getFirst(); TR::Node *firstNode = self()->comp()->getStartTree()->getNode(); int32_t numIntArgs = 0, numFloatArgs = 0; const TR::PPCLinkageProperties& properties = self()->getProperties(); while ( (paramCursor!=NULL) && ( (numIntArgs < properties.getNumIntArgRegs()) || (numFloatArgs < properties.getNumFloatArgRegs()) ) ) { TR::RealRegister *argRegister; int32_t offset = paramCursor->getParameterOffset(); // If parm is referenced or required to be on stack (i.e. FSD), we have to flush. bool hasToStoreToStack = paramCursor->isReferencedParameter() || paramCursor->isParmHasToBeOnStack(); switch (paramCursor->getDataType()) { case TR::Int8: case TR::Int16: case TR::Int32: if (hasToStoreToStack && numIntArgs<properties.getNumIntArgRegs()) { argRegister = machine->getRealRegister(properties.getIntegerArgumentRegister(numIntArgs)); cursor = generateMemSrc1Instruction(self()->cg(), TR::InstOpCode::stw, firstNode, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, 4, self()->cg()), argRegister, cursor); } numIntArgs++; break; case TR::Address: if (numIntArgs<properties.getNumIntArgRegs()) { argRegister = machine->getRealRegister(properties.getIntegerArgumentRegister(numIntArgs)); cursor = generateMemSrc1Instruction(self()->cg(),TR::InstOpCode::Op_st, firstNode, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, TR::Compiler->om.sizeofReferenceAddress(), self()->cg()), argRegister, cursor); } numIntArgs++; break; case TR::Int64: if (hasToStoreToStack && numIntArgs<properties.getNumIntArgRegs()) { argRegister = machine->getRealRegister(properties.getIntegerArgumentRegister(numIntArgs)); if (TR::Compiler->target.is64Bit()) cursor = generateMemSrc1Instruction(self()->cg(),TR::InstOpCode::Op_st, firstNode, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, 8, self()->cg()), argRegister, cursor); else { cursor = generateMemSrc1Instruction(self()->cg(), TR::InstOpCode::stw, firstNode, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, 4, self()->cg()), argRegister, cursor); if (numIntArgs < properties.getNumIntArgRegs()-1) { argRegister = machine->getRealRegister(properties.getIntegerArgumentRegister(numIntArgs+1)); cursor = generateMemSrc1Instruction(self()->cg(), TR::InstOpCode::stw, firstNode, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset+4, 4, self()->cg()), argRegister, cursor); } } } if (TR::Compiler->target.is64Bit()) numIntArgs++; else numIntArgs+=2; break; case TR::Float: if (hasToStoreToStack && numFloatArgs<properties.getNumFloatArgRegs()) { argRegister = machine->getRealRegister(properties.getFloatArgumentRegister(numFloatArgs)); cursor = generateMemSrc1Instruction(self()->cg(), TR::InstOpCode::stfs, firstNode, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, 4, self()->cg()), argRegister, cursor); } numFloatArgs++; break; case TR::Double: if (hasToStoreToStack && numFloatArgs<properties.getNumFloatArgRegs()) { argRegister = machine->getRealRegister(properties.getFloatArgumentRegister(numFloatArgs)); cursor = generateMemSrc1Instruction(self()->cg(), TR::InstOpCode::stfd, firstNode, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, 8, self()->cg()), argRegister, cursor); } numFloatArgs++; break; } paramCursor = paramIterator.getNext(); } return(cursor); }
TR::Instruction *OMR::Power::Linkage::loadUpArguments(TR::Instruction *cursor) { if (!self()->cg()->buildInterpreterEntryPoint()) // would be better to use a different linkage for this purpose return cursor; TR::Machine *machine = self()->machine(); TR::RealRegister *stackPtr = self()->cg()->getStackPointerRegister(); TR::ResolvedMethodSymbol *bodySymbol = self()->comp()->getJittedMethodSymbol(); ListIterator<TR::ParameterSymbol> paramIterator(&(bodySymbol->getParameterList())); TR::ParameterSymbol *paramCursor = paramIterator.getFirst(); TR::Node *firstNode = self()->comp()->getStartTree()->getNode(); int32_t numIntArgs = 0, numFloatArgs = 0; const TR::PPCLinkageProperties& properties = self()->getProperties(); while ( (paramCursor!=NULL) && ( (numIntArgs < properties.getNumIntArgRegs()) || (numFloatArgs < properties.getNumFloatArgRegs()) ) ) { TR::RealRegister *argRegister; int32_t offset = paramCursor->getParameterOffset(); bool hasToLoadFromStack = paramCursor->isReferencedParameter() || paramCursor->isParmHasToBeOnStack(); switch (paramCursor->getDataType()) { case TR::Int8: case TR::Int16: case TR::Int32: if (hasToLoadFromStack && numIntArgs<properties.getNumIntArgRegs()) { argRegister = machine->getRealRegister(properties.getIntegerArgumentRegister(numIntArgs)); cursor = generateTrg1MemInstruction(self()->cg(), TR::InstOpCode::lwz, firstNode, argRegister, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, 4, self()->cg()), cursor); } numIntArgs++; break; case TR::Address: if (numIntArgs<properties.getNumIntArgRegs()) { argRegister = machine->getRealRegister(properties.getIntegerArgumentRegister(numIntArgs)); cursor = generateTrg1MemInstruction(self()->cg(),TR::InstOpCode::Op_load, firstNode, argRegister, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, TR::Compiler->om.sizeofReferenceAddress(), self()->cg()), cursor); } numIntArgs++; break; case TR::Int64: if (hasToLoadFromStack && numIntArgs<properties.getNumIntArgRegs()) { argRegister = machine->getRealRegister(properties.getIntegerArgumentRegister(numIntArgs)); if (TR::Compiler->target.is64Bit()) cursor = generateTrg1MemInstruction(self()->cg(), TR::InstOpCode::ld, firstNode, argRegister, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, 8, self()->cg()), cursor); else { cursor = generateTrg1MemInstruction(self()->cg(), TR::InstOpCode::lwz, firstNode, argRegister, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, 4, self()->cg()), cursor); if (numIntArgs < properties.getNumIntArgRegs()-1) { argRegister = machine->getRealRegister(properties.getIntegerArgumentRegister(numIntArgs+1)); cursor = generateTrg1MemInstruction(self()->cg(), TR::InstOpCode::lwz, firstNode, argRegister, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset+4, 4, self()->cg()), cursor); } } } if (TR::Compiler->target.is64Bit()) numIntArgs++; else numIntArgs+=2; break; case TR::Float: if (hasToLoadFromStack && numFloatArgs<properties.getNumFloatArgRegs()) { argRegister = machine->getRealRegister(properties.getFloatArgumentRegister(numFloatArgs)); cursor = generateTrg1MemInstruction(self()->cg(), TR::InstOpCode::lfs, firstNode, argRegister, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, 4, self()->cg()), cursor); } numFloatArgs++; break; case TR::Double: if (hasToLoadFromStack && numFloatArgs<properties.getNumFloatArgRegs()) { argRegister = machine->getRealRegister(properties.getFloatArgumentRegister(numFloatArgs)); cursor = generateTrg1MemInstruction(self()->cg(), TR::InstOpCode::lfd, firstNode, argRegister, new (self()->trHeapMemory()) TR::MemoryReference(stackPtr, offset, 8, self()->cg()), cursor); } numFloatArgs++; break; } paramCursor = paramIterator.getNext(); } return(cursor); }
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; } }
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); } } }
void TR::ARM64SystemLinkage::createPrologue(TR::Instruction *cursor, List<TR::ParameterSymbol> &parmList) { TR::CodeGenerator *codeGen = cg(); TR::Machine *machine = codeGen->machine(); TR::ResolvedMethodSymbol *bodySymbol = comp()->getJittedMethodSymbol(); const TR::ARM64LinkageProperties& properties = getProperties(); TR::RealRegister *sp = machine->getRealRegister(properties.getStackPointerRegister()); TR::Node *firstNode = comp()->getStartTree()->getNode(); // allocate stack space uint32_t frameSize = (uint32_t)codeGen->getFrameSizeInBytes(); if (constantIsUnsignedImm12(frameSize)) { cursor = generateTrg1Src1ImmInstruction(codeGen, TR::InstOpCode::subimmx, firstNode, sp, sp, frameSize, cursor); } else { TR_UNIMPLEMENTED(); } // save link register (x30) if (machine->getLinkRegisterKilled()) { TR::MemoryReference *stackSlot = new (trHeapMemory()) TR::MemoryReference(sp, 0, codeGen); cursor = generateMemSrc1Instruction(cg(), TR::InstOpCode::strimmx, firstNode, stackSlot, machine->getRealRegister(TR::RealRegister::x30), cursor); } // spill argument registers int32_t nextIntArgReg = 0; int32_t nextFltArgReg = 0; ListIterator<TR::ParameterSymbol> parameterIterator(&parmList); for (TR::ParameterSymbol *parameter = parameterIterator.getFirst(); parameter != NULL && (nextIntArgReg < getProperties().getNumIntArgRegs() || nextFltArgReg < getProperties().getNumFloatArgRegs()); parameter = parameterIterator.getNext()) { TR::MemoryReference *stackSlot = new (trHeapMemory()) TR::MemoryReference(sp, parameter->getParameterOffset(), codeGen); TR::InstOpCode::Mnemonic op; switch (parameter->getDataType()) { case TR::Int8: case TR::Int16: case TR::Int32: case TR::Int64: case TR::Address: if (nextIntArgReg < getProperties().getNumIntArgRegs()) { op = (parameter->getSize() == 8) ? TR::InstOpCode::strimmx : TR::InstOpCode::strimmw; cursor = generateMemSrc1Instruction(cg(), op, firstNode, stackSlot, machine->getRealRegister((TR::RealRegister::RegNum)(TR::RealRegister::x0 + nextIntArgReg)), cursor); nextIntArgReg++; } else { nextIntArgReg = getProperties().getNumIntArgRegs() + 1; } break; case TR::Float: case TR::Double: if (nextFltArgReg < getProperties().getNumFloatArgRegs()) { op = (parameter->getSize() == 8) ? TR::InstOpCode::vstrimmd : TR::InstOpCode::vstrimms; cursor = generateMemSrc1Instruction(cg(), op, firstNode, stackSlot, machine->getRealRegister((TR::RealRegister::RegNum)(TR::RealRegister::v0 + nextFltArgReg)), cursor); nextFltArgReg++; } else { nextFltArgReg = getProperties().getNumFloatArgRegs() + 1; } break; case TR::Aggregate: TR_ASSERT(false, "Function parameters of aggregate types are not currently supported on AArch64."); break; default: TR_ASSERT(false, "Unknown parameter type."); } } // save callee-saved registers uint32_t offset = bodySymbol->getLocalMappingCursor(); for (int r = TR::RealRegister::x19; r <= TR::RealRegister::x28; r++) { TR::RealRegister *rr = machine->getRealRegister((TR::RealRegister::RegNum)r); if (rr->getHasBeenAssignedInMethod()) { TR::MemoryReference *stackSlot = new (trHeapMemory()) TR::MemoryReference(sp, offset, codeGen); cursor = generateMemSrc1Instruction(cg(), TR::InstOpCode::strimmx, firstNode, stackSlot, rr, cursor); offset += 8; } } for (int r = TR::RealRegister::v8; r <= TR::RealRegister::v15; r++) { TR::RealRegister *rr = machine->getRealRegister((TR::RealRegister::RegNum)r); if (rr->getHasBeenAssignedInMethod()) { TR::MemoryReference *stackSlot = new (trHeapMemory()) TR::MemoryReference(sp, offset, codeGen); cursor = generateMemSrc1Instruction(cg(), TR::InstOpCode::vstrimmd, firstNode, stackSlot, rr, cursor); offset += 8; } } }
void TR::ARM64SystemLinkage::mapStack(TR::ResolvedMethodSymbol *method) { TR::Machine *machine = cg()->machine(); uint32_t stackIndex = 0; ListIterator<TR::AutomaticSymbol> automaticIterator(&method->getAutomaticList()); TR::AutomaticSymbol *localCursor = automaticIterator.getFirst(); stackIndex = 8; // [sp+0] is for link register // map non-long/double automatics while (localCursor != NULL) { if (localCursor->getGCMapIndex() < 0 && localCursor->getDataType() != TR::Int64 && localCursor->getDataType() != TR::Double) { localCursor->setOffset(stackIndex); stackIndex += (localCursor->getSize() + 3) & (~3); } localCursor = automaticIterator.getNext(); } stackIndex += (stackIndex & 0x4) ? 4 : 0; // align to 8 bytes automaticIterator.reset(); localCursor = automaticIterator.getFirst(); // map long/double automatics while (localCursor != NULL) { if (localCursor->getDataType() == TR::Int64 || localCursor->getDataType() == TR::Double) { localCursor->setOffset(stackIndex); stackIndex += (localCursor->getSize() + 7) & (~7); } localCursor = automaticIterator.getNext(); } method->setLocalMappingCursor(stackIndex); // allocate space for preserved registers (x19-x28, v8-v15) for (int r = TR::RealRegister::x19; r <= TR::RealRegister::x28; r++) { TR::RealRegister *rr = machine->getRealRegister((TR::RealRegister::RegNum)r); if (rr->getHasBeenAssignedInMethod()) { stackIndex += 8; } } for (int r = TR::RealRegister::v8; r <= TR::RealRegister::v15; r++) { TR::RealRegister *rr = machine->getRealRegister((TR::RealRegister::RegNum)r); if (rr->getHasBeenAssignedInMethod()) { stackIndex += 8; } } /* * Because the rest of the code generator currently expects **all** arguments * to be passed on the stack, arguments passed in registers must be spilled * in the callee frame. To map the arguments correctly, we use two loops. The * first maps the arguments that will come in registers onto the callee stack. * At the end of this loop, the `stackIndex` is the the size of the frame. * The second loop then maps the remaining arguments onto the caller frame. */ int32_t nextIntArgReg = 0; int32_t nextFltArgReg = 0; ListIterator<TR::ParameterSymbol> parameterIterator(&method->getParameterList()); for (TR::ParameterSymbol *parameter = parameterIterator.getFirst(); parameter != NULL && (nextIntArgReg < getProperties().getNumIntArgRegs() || nextFltArgReg < getProperties().getNumFloatArgRegs()); parameter = parameterIterator.getNext()) { switch (parameter->getDataType()) { case TR::Int8: case TR::Int16: case TR::Int32: case TR::Int64: case TR::Address: if (nextIntArgReg < getProperties().getNumIntArgRegs()) { nextIntArgReg++; mapSingleParameter(parameter, stackIndex, true); } else { nextIntArgReg = getProperties().getNumIntArgRegs() + 1; } break; case TR::Float: case TR::Double: if (nextFltArgReg < getProperties().getNumFloatArgRegs()) { nextFltArgReg++; mapSingleParameter(parameter, stackIndex, true); } else { nextFltArgReg = getProperties().getNumFloatArgRegs() + 1; } break; case TR::Aggregate: TR_ASSERT(false, "Function parameters of aggregate types are not currently supported on AArch64."); break; default: TR_ASSERT(false, "Unknown parameter type."); } } // save the stack frame size, aligned to 16 bytes stackIndex = (stackIndex + 15) & (~15); cg()->setFrameSizeInBytes(stackIndex); nextIntArgReg = 0; nextFltArgReg = 0; parameterIterator.reset(); for (TR::ParameterSymbol *parameter = parameterIterator.getFirst(); parameter != NULL && (nextIntArgReg < getProperties().getNumIntArgRegs() || nextFltArgReg < getProperties().getNumFloatArgRegs()); parameter = parameterIterator.getNext()) { switch (parameter->getDataType()) { case TR::Int8: case TR::Int16: case TR::Int32: case TR::Int64: case TR::Address: if (nextIntArgReg < getProperties().getNumIntArgRegs()) { nextIntArgReg++; } else { mapSingleParameter(parameter, stackIndex, false); } break; case TR::Float: case TR::Double: if (nextFltArgReg < getProperties().getNumFloatArgRegs()) { nextFltArgReg++; } else { mapSingleParameter(parameter, stackIndex, false); } break; case TR::Aggregate: TR_ASSERT(false, "Function parameters of aggregate types are not currently supported on AArch64."); break; default: TR_ASSERT(false, "Unknown parameter type."); } } }
uint8_t * TR::S390CallSnippet::S390flushArgumentsToStack(uint8_t * buffer, TR::Node * callNode, int32_t argSize, TR::CodeGenerator * cg) { int32_t intArgNum = 0, floatArgNum = 0, offset; TR::Machine *machine = cg->machine(); TR::Linkage * linkage = cg->getLinkage(callNode->getSymbol()->castToMethodSymbol()->getLinkageConvention()); int32_t argStart = callNode->getFirstArgumentIndex(); bool rightToLeft = linkage->getRightToLeft() && //we want the arguments for induceOSR to be passed from left to right as in any other non-helper call !callNode->getSymbolReference()->isOSRInductionHelper(); if (rightToLeft) { offset = linkage->getOffsetToFirstParm(); } else { offset = argSize + linkage->getOffsetToFirstParm(); } for (int32_t i = argStart; i < callNode->getNumChildren(); i++) { TR::Node * child = callNode->getChild(i); switch (child->getDataType()) { case TR::Int8: case TR::Int16: case TR::Int32: if (!rightToLeft) { offset -= TR::Compiler->target.is64Bit() ? 8 : 4; } if (intArgNum < linkage->getNumIntegerArgumentRegisters()) { buffer = storeArgumentItem(TR::InstOpCode::ST, buffer, machine->getRealRegister(linkage->getIntegerArgumentRegister(intArgNum)), offset, cg); } intArgNum++; if (rightToLeft) { offset += TR::Compiler->target.is64Bit() ? 8 : 4; } break; case TR::Address: if (!rightToLeft) { offset -= TR::Compiler->target.is64Bit() ? 8 : 4; } if (intArgNum < linkage->getNumIntegerArgumentRegisters()) { buffer = storeArgumentItem(TR::InstOpCode::getStoreOpCode(), buffer, machine->getRealRegister(linkage->getIntegerArgumentRegister(intArgNum)), offset, cg); } intArgNum++; if (rightToLeft) { offset += TR::Compiler->target.is64Bit() ? 8 : 4; } break; case TR::Int64: if (!rightToLeft) { offset -= (TR::Compiler->target.is64Bit() ? 16 : 8); } if (intArgNum < linkage->getNumIntegerArgumentRegisters()) { if (TR::Compiler->target.is64Bit()) { buffer = storeArgumentItem(TR::InstOpCode::STG, buffer, machine->getRealRegister(linkage->getIntegerArgumentRegister(intArgNum)), offset, cg); } else { buffer = storeArgumentItem(TR::InstOpCode::ST, buffer, machine->getRealRegister(linkage->getIntegerArgumentRegister(intArgNum)), offset, cg); if (intArgNum < linkage->getNumIntegerArgumentRegisters() - 1) { buffer = storeArgumentItem(TR::InstOpCode::ST, buffer, machine->getRealRegister(linkage->getIntegerArgumentRegister(intArgNum + 1)), offset + 4, cg); } } } intArgNum += TR::Compiler->target.is64Bit() ? 1 : 2; if (rightToLeft) { offset += TR::Compiler->target.is64Bit() ? 16 : 8; } break; case TR::Float: if (!rightToLeft) { offset -= TR::Compiler->target.is64Bit() ? 8 : 4; } if (floatArgNum < linkage->getNumFloatArgumentRegisters()) { buffer = storeArgumentItem(TR::InstOpCode::STE, buffer, machine->getRealRegister(linkage->getFloatArgumentRegister(floatArgNum)), offset, cg); } floatArgNum++; if (rightToLeft) { offset += TR::Compiler->target.is64Bit() ? 8 : 4; } break; case TR::Double: if (!rightToLeft) { offset -= TR::Compiler->target.is64Bit() ? 16 : 8; } if (floatArgNum < linkage->getNumFloatArgumentRegisters()) { buffer = storeArgumentItem(TR::InstOpCode::STD, buffer, machine->getRealRegister(linkage->getFloatArgumentRegister(floatArgNum)), offset, cg); } floatArgNum++; if (rightToLeft) { offset += TR::Compiler->target.is64Bit() ? 16 : 8; } break; } } return buffer; }
// Copies parameters from where they enter the method (either on stack or in a // linkage register) to their "home location" where the method body will expect // to find them (either on stack or in a global register). // TR::Instruction * TR::X86SystemLinkage::copyParametersToHomeLocation(TR::Instruction *cursor) { TR::Machine *machine = cg()->machine(); TR::RealRegister *framePointer = machine->getX86RealRegister(TR::RealRegister::vfp); TR::ResolvedMethodSymbol *bodySymbol = comp()->getJittedMethodSymbol(); ListIterator<TR::ParameterSymbol> paramIterator(&(bodySymbol->getParameterList())); TR::ParameterSymbol *paramCursor; const TR::RealRegister::RegNum noReg = TR::RealRegister::NoReg; TR_ASSERT(noReg == 0, "noReg must be zero so zero-initializing movStatus will work"); TR::MovStatus movStatus[TR::RealRegister::NumRegisters] = {{(TR::RealRegister::RegNum)0,(TR::RealRegister::RegNum)0,(TR_MovDataTypes)0}}; // We must always do the stores first, then the reg-reg copies, then the // loads, so that we never clobber a register we will need later. However, // the logic is simpler if we do the loads and stores in the same loop. // Therefore, we maintain a separate instruction cursor for the loads. // // We defer the initialization of loadCursor until we generate the first // load. Otherwise, if we happen to generate some stores first, then the // store cursor would get ahead of the loadCursor, and the instructions // would end up in the wrong order despite our efforts. // TR::Instruction *loadCursor = NULL; // Phase 1: generate RegMem and MemReg movs, and collect information about // the required RegReg movs. // for (paramCursor = paramIterator.getFirst(); paramCursor != NULL; paramCursor = paramIterator.getNext()) { int8_t lri = paramCursor->getLinkageRegisterIndex(); // How the parameter enters the method TR::RealRegister::RegNum ai // Where method body expects to find it = (TR::RealRegister::RegNum)paramCursor->getAllocatedIndex(); int32_t offset = paramCursor->getParameterOffset(); // Location of the parameter's stack slot TR_MovDataTypes movDataType = paramMovType(paramCursor); // What sort of MOV instruction does it need? // Copy the parameter to wherever it should be // if (lri == NOT_LINKAGE) // It's on the stack { if (ai == NOT_ASSIGNED) // It only needs to be on the stack { // Nothing to do } else // Method body expects it to be in the ai register { if (loadCursor == NULL) loadCursor = cursor; if (debug("traceCopyParametersToHomeLocation")) diagnostic("copyParametersToHomeLocation: Loading %d\n", ai); // ai := stack loadCursor = generateRegMemInstruction( loadCursor, TR::Linkage::movOpcodes(RegMem, movDataType), machine->getX86RealRegister(ai), generateX86MemoryReference(framePointer, offset, cg()), cg() ); } } else // It's in a linkage register { TR::RealRegister::RegNum sourceIndex = getProperties().getArgumentRegister(lri, isFloat(movDataType)); // Copy to the stack if necessary // if (ai == NOT_ASSIGNED || hasToBeOnStack(paramCursor)) { if (comp()->getOption(TR_TraceCG)) traceMsg(comp(), "copyToHomeLocation param %p, linkage reg index %d, allocated index %d, parameter offset %d, hasToBeOnStack %d, parm->isParmHasToBeOnStack() %d.\n", paramCursor, lri, ai, offset, hasToBeOnStack(paramCursor), paramCursor->isParmHasToBeOnStack()); if (debug("traceCopyParametersToHomeLocation")) diagnostic("copyParametersToHomeLocation: Storing %d\n", sourceIndex); // stack := lri cursor = generateMemRegInstruction( cursor, TR::Linkage::movOpcodes(MemReg, movDataType), generateX86MemoryReference(framePointer, offset, cg()), machine->getX86RealRegister(sourceIndex), cg() ); } // Copy to the ai register if necessary // if (ai != NOT_ASSIGNED && ai != sourceIndex) { // This parameter needs a RegReg move. We don't know yet whether // we need the value in the target register, so for now we just // remember that we need to do this and keep going. // TR_ASSERT(movStatus[ai ].sourceReg == noReg, "Each target reg must have only one source"); TR_ASSERT(movStatus[sourceIndex].targetReg == noReg, "Each source reg must have only one target"); if (debug("traceCopyParametersToHomeLocation")) diagnostic("copyParametersToHomeLocation: Planning to move %d to %d\n", sourceIndex, ai); movStatus[ai].sourceReg = sourceIndex; movStatus[sourceIndex].targetReg = ai; movStatus[sourceIndex].outgoingDataType = movDataType; } if (debug("traceCopyParametersToHomeLocation") && ai == sourceIndex) { diagnostic("copyParametersToHomeLocation: Parameter #%d already in register %d\n", lri, ai); } } } // Phase 2: Iterate through the parameters again to insert the RegReg moves. // for (paramCursor = paramIterator.getFirst(); paramCursor != NULL; paramCursor = paramIterator.getNext()) { if (paramCursor->getLinkageRegisterIndex() == NOT_LINKAGE) continue; const TR::RealRegister::RegNum paramReg = getProperties().getArgumentRegister(paramCursor->getLinkageRegisterIndex(), isFloat(paramMovType(paramCursor))); if (movStatus[paramReg].targetReg == 0) { // This parameter does not need to be copied anywhere if (debug("traceCopyParametersToHomeLocation")) diagnostic("copyParametersToHomeLocation: Not moving %d\n", paramReg); } else { if (debug("traceCopyParametersToHomeLocation")) diagnostic("copyParametersToHomeLocation: Preparing to move %d\n", paramReg); // If a mov's target register is the source for another mov, we need // to do that other mov first. The idea is to find the end point of // the chain of movs starting with paramReg and ending with a // register whose current value is not needed; then do that chain of // movs in reverse order. // TR_ASSERT(noReg == 0, "noReg must be zero (not %d) for zero-filled initialization to work", noReg); TR::RealRegister::RegNum regCursor; // Find the last target in the chain // regCursor = movStatus[paramReg].targetReg; while(movStatus[regCursor].targetReg != noReg) { // Haven't found the end yet regCursor = movStatus[regCursor].targetReg; TR_ASSERT(regCursor != paramReg, "Can't yet handle cyclic dependencies"); // TODO:AMD64 Use scratch register to break cycles // A properly-written pickRegister should never // cause cycles to occur in the first place. However, we may want // to consider adding cycle-breaking logic so that (1) pickRegister // has more flexibility, and (2) we're more robust against // otherwise harmless bugs in pickRegister. } // Work our way backward along the chain, generating all the necessary movs // while(movStatus[regCursor].sourceReg != noReg) { TR::RealRegister::RegNum source = movStatus[regCursor].sourceReg; if (debug("traceCopyParametersToHomeLocation")) diagnostic("copyParametersToHomeLocation: Moving %d to %d\n", source, regCursor); // regCursor := regCursor.sourceReg cursor = generateRegRegInstruction( cursor, TR::Linkage::movOpcodes(RegReg, movStatus[source].outgoingDataType), machine->getX86RealRegister(regCursor), machine->getX86RealRegister(source), cg() ); // Update movStatus as we go so we don't generate redundant movs movStatus[regCursor].sourceReg = noReg; movStatus[source ].targetReg = noReg; // Continue with the next register in the chain regCursor = source; } } } // Return the last instruction we inserted, whether or not it was a load. // return loadCursor? loadCursor : cursor; }
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 } } } }