/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/eclipse-1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.jikesrvm.compilers.opt.regalloc; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import org.jikesrvm.compilers.opt.ir.BasicBlock; import org.jikesrvm.compilers.opt.ir.GenericPhysicalRegisterSet; import org.jikesrvm.compilers.opt.ir.IR; import org.jikesrvm.compilers.opt.ir.Instruction; import org.jikesrvm.compilers.opt.ir.Register; /** * The register allocator currently caches a bunch of state in the IR; * This class provides accessors to this state. * <ul> * <li>TODO: Consider caching the state in a lookaside structure. * <li>TODO: Currently, the physical registers are STATIC! fix this. * </ul> */ public class RegisterAllocatorState { private final int[] spills; private final CompoundInterval[] intervals; private Map<Instruction, Integer> depthFirstNumbers; RegisterAllocatorState(int registerCount) { spills = new int[registerCount]; intervals = new CompoundInterval[registerCount]; } /** * Resets the physical register info. * * @param ir the IR whose info is to be reset */ void resetPhysicalRegisters(IR ir) { GenericPhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet(); for (Enumeration<Register> e = phys.enumerateAll(); e.hasMoreElements();) { Register reg = e.nextElement(); reg.deallocateRegister(); reg.mapsToRegister = null; // mapping from real to symbolic reg.defList = null; reg.useList = null; setSpill(reg, 0); } } void setSpill(Register reg, int spill) { reg.spillRegister(); spills[reg.number] = spill; } public int getSpill(Register reg) { return spills[reg.number]; } /** * Records that register A and register B are associated with each other * in a bijection.<p> * * The register allocator uses this state to indicate that a symbolic * register is presently allocated to a physical register. * * @param A first register * @param B second register */ void mapOneToOne(Register A, Register B) { Register aFriend = getMapping(A); Register bFriend = getMapping(B); if (aFriend != null) { aFriend.mapsToRegister = null; } if (bFriend != null) { bFriend.mapsToRegister = null; } A.mapsToRegister = B; B.mapsToRegister = A; } /** * @param r a register * @return the register currently mapped 1-to-1 to r */ Register getMapping(Register r) { return r.mapsToRegister; } /** * Clears any 1-to-1 mapping for a register. * * @param r the register whose mapping is to be cleared */ void clearOneToOne(Register r) { if (r != null) { Register s = getMapping(r); if (s != null) { s.mapsToRegister = null; } r.mapsToRegister = null; } } /** * Returns the interval associated with the passed register. * @param reg the register * @return the live interval or {@code null} */ CompoundInterval getInterval(Register reg) { return intervals[reg.number]; } /** * Initializes data structures for depth first numbering. * @param instructionCount an estimate of the total number of instructions. */ void initializeDepthFirstNumbering(int instructionCount) { int noRehashCapacity = (int) (instructionCount * 1.5f); depthFirstNumbers = new HashMap<Instruction, Integer>(noRehashCapacity); } /** * Associates the passed live interval with the passed register. * * @param reg the register * @param interval the live interval */ void setInterval(Register reg, CompoundInterval interval) { intervals[reg.number] = interval; } /** * Associates the passed dfn number with the instruction * @param inst the instruction * @param dfn the dfn number */ void setDFN(Instruction inst, int dfn) { depthFirstNumbers.put(inst, Integer.valueOf(dfn)); } /** * returns the dfn associated with the passed instruction * @param inst the instruction * @return the associated dfn */ public int getDFN(Instruction inst) { return depthFirstNumbers.get(inst); } /** * Prints the DFN numbers associated with each instruction. * * @param ir the IR that contains the instructions */ void printDfns(IR ir) { System.out.println("DFNS: **** " + ir.getMethod() + "****"); for (Instruction inst = ir.firstInstructionInCodeOrder(); inst != null; inst = inst.nextInstructionInCodeOrder()) { System.out.println(getDFN(inst) + " " + inst); } } /** * @param live the live interval * @param bb the basic block for the live interval * @return the Depth-first-number of the beginning of the live interval. If the * interval is open-ended, the dfn for the beginning of the basic block will * be returned instead. */ int getDfnBegin(LiveIntervalElement live, BasicBlock bb) { Instruction begin = live.getBegin(); int dfnBegin; if (begin != null) { dfnBegin = getDFN(begin); } else { dfnBegin = getDFN(bb.firstInstruction()); } return dfnBegin; } /** * @param live the live interval * @param bb the basic block for the live interval * @return the Depth-first-number of the end of the live interval. If the * interval is open-ended, the dfn for the end of the basic block will * be returned instead. */ int getDfnEnd(LiveIntervalElement live, BasicBlock bb) { Instruction end = live.getEnd(); int dfnEnd; if (end != null) { dfnEnd = getDFN(end); } else { dfnEnd = getDFN(bb.lastInstruction()); } return dfnEnd; } }