void LinearScan::allocRegs(Trace* trace) { if (RuntimeOption::EvalHHIREnableCoalescing) { // <coalesce> doesn't need instruction numbering. coalesce(trace); } numberInstructions(trace); collectNatives(trace); computePreColoringHint(); initFreeList(); allocRegsToTraceAux(trace); // Renumber instructions, because we added spills and reloads. numberInstructions(trace); if (RuntimeOption::EvalHHIREnableRematerialization && m_slots.size() > 0) { // Don't bother rematerializing the trace if it has no Spill/Reload. if (RuntimeOption::EvalDumpIR > 5) { std::cout << "--------- HHIR before rematerialization ---------\n"; trace->print(std::cout, false); std::cout << "-------------------------------------------------\n"; } rematerialize(trace); } // assignSpillLoc needs next natives in order to decide whether we // can use MMX registers. collectNatives(trace); // Make sure rsp is 16-aligned. uint32 numSpillLocs = assignSpillLoc(trace); if (numSpillLocs % 2) { ++numSpillLocs; } assert(NumPreAllocatedSpillLocs % 2 == 0); if (numSpillLocs > 0) { preAllocSpillLoc(trace, numSpillLocs); if (numSpillLocs > (uint32)NumPreAllocatedSpillLocs) { /* * We only insert AllocSpill and FreeSpill when the pre-allocated * spill locations are not enough. * * AllocSpill and FreeSpill take the number of extra spill locations * besides the pre-allocated ones. * * TODO(#2044051) AllocSpill/FreeSpill are currently disabled * due to bugs. */ PUNT(LinearScan_AllocSpill); insertAllocFreeSpill(trace, numSpillLocs - NumPreAllocatedSpillLocs); } } numberInstructions(trace); // record the live out register set at each instruction LinearScan::computeLiveOutRegs(trace); }
void LinearScan::allocRegsToTraceAux(Trace* trace) { IRInstruction::List& instructionList = trace->getInstructionList(); IRInstruction::Iterator it; for (it = instructionList.begin(); it != instructionList.end(); it++) { IRInstruction* inst = *it; allocRegToInstruction(trace, it); if (RuntimeOption::EvalDumpIR > 3) { std::cout << "--- allocated to instruction: "; inst->print(std::cout); std::cout << "\n"; } if (inst->isControlFlowInstruction()) { // This instruction may transfer control to another trace // If this is the last instruction in the trace that can branch // to this target trace, then allocate registers to the target // trace, effectively linearizing the target trace after inst. LabelInstruction* label = inst->getLabel(); if (label != NULL && label->getId() == inst->getId() + 1) { allocRegsToTraceAux(label->getTrace()); } } } // Insert spill instructions. // Reload instructions are already added in <allocRegsToTrace>. for (it = instructionList.begin(); it != instructionList.end(); ) { IRInstruction::Iterator next = it; ++next; IRInstruction* inst = *it; if (inst->getOpcode() != Reload) { // Reloaded SSATmps needn't be spilled again. if (SSATmp* dst = inst->getDst()) { int32 slotId = dst->getSpillSlot(); if (slotId != -1) { // If this instruction is marked to be spilled, // add a spill right afterwards. IRInstruction* spillInst = m_slots[slotId].m_slotTmp->getInstruction(); instructionList.insert(next, spillInst); spillInst->setParent(trace); } } } it = next; } }