001/* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013package org.jikesrvm.compilers.opt.regalloc; 014 015import java.util.Enumeration; 016import java.util.HashMap; 017import java.util.Map; 018 019import org.jikesrvm.compilers.opt.ir.BasicBlock; 020import org.jikesrvm.compilers.opt.ir.GenericPhysicalRegisterSet; 021import org.jikesrvm.compilers.opt.ir.IR; 022import org.jikesrvm.compilers.opt.ir.Instruction; 023import org.jikesrvm.compilers.opt.ir.Register; 024 025/** 026 * The register allocator currently caches a bunch of state in the IR; 027 * This class provides accessors to this state. 028 * <ul> 029 * <li>TODO: Consider caching the state in a lookaside structure. 030 * <li>TODO: Currently, the physical registers are STATIC! fix this. 031 * </ul> 032 */ 033public class RegisterAllocatorState { 034 035 private final int[] spills; 036 037 private final CompoundInterval[] intervals; 038 039 private Map<Instruction, Integer> depthFirstNumbers; 040 041 RegisterAllocatorState(int registerCount) { 042 spills = new int[registerCount]; 043 intervals = new CompoundInterval[registerCount]; 044 } 045 046 /** 047 * Resets the physical register info. 048 * 049 * @param ir the IR whose info is to be reset 050 */ 051 void resetPhysicalRegisters(IR ir) { 052 GenericPhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet(); 053 for (Enumeration<Register> e = phys.enumerateAll(); e.hasMoreElements();) { 054 Register reg = e.nextElement(); 055 reg.deallocateRegister(); 056 reg.mapsToRegister = null; // mapping from real to symbolic 057 reg.defList = null; 058 reg.useList = null; 059 setSpill(reg, 0); 060 } 061 } 062 063 void setSpill(Register reg, int spill) { 064 reg.spillRegister(); 065 spills[reg.number] = spill; 066 } 067 068 public int getSpill(Register reg) { 069 return spills[reg.number]; 070 } 071 072 /** 073 * Records that register A and register B are associated with each other 074 * in a bijection.<p> 075 * 076 * The register allocator uses this state to indicate that a symbolic 077 * register is presently allocated to a physical register. 078 * 079 * @param A first register 080 * @param B second register 081 */ 082 void mapOneToOne(Register A, Register B) { 083 Register aFriend = getMapping(A); 084 Register bFriend = getMapping(B); 085 if (aFriend != null) { 086 aFriend.mapsToRegister = null; 087 } 088 if (bFriend != null) { 089 bFriend.mapsToRegister = null; 090 } 091 A.mapsToRegister = B; 092 B.mapsToRegister = A; 093 } 094 095 /** 096 * @param r a register 097 * @return the register currently mapped 1-to-1 to r 098 */ 099 Register getMapping(Register r) { 100 return r.mapsToRegister; 101 } 102 103 /** 104 * Clears any 1-to-1 mapping for a register. 105 * 106 * @param r the register whose mapping is to be cleared 107 */ 108 void clearOneToOne(Register r) { 109 if (r != null) { 110 Register s = getMapping(r); 111 if (s != null) { 112 s.mapsToRegister = null; 113 } 114 r.mapsToRegister = null; 115 } 116 } 117 118 /** 119 * Returns the interval associated with the passed register. 120 * @param reg the register 121 * @return the live interval or {@code null} 122 */ 123 CompoundInterval getInterval(Register reg) { 124 return intervals[reg.number]; 125 } 126 127 /** 128 * Initializes data structures for depth first numbering. 129 * @param instructionCount an estimate of the total number of instructions. 130 */ 131 void initializeDepthFirstNumbering(int instructionCount) { 132 int noRehashCapacity = (int) (instructionCount * 1.5f); 133 depthFirstNumbers = new HashMap<Instruction, Integer>(noRehashCapacity); 134 } 135 136 /** 137 * Associates the passed live interval with the passed register. 138 * 139 * @param reg the register 140 * @param interval the live interval 141 */ 142 void setInterval(Register reg, CompoundInterval interval) { 143 intervals[reg.number] = interval; 144 } 145 146 /** 147 * Associates the passed dfn number with the instruction 148 * @param inst the instruction 149 * @param dfn the dfn number 150 */ 151 void setDFN(Instruction inst, int dfn) { 152 depthFirstNumbers.put(inst, Integer.valueOf(dfn)); 153 } 154 155 /** 156 * returns the dfn associated with the passed instruction 157 * @param inst the instruction 158 * @return the associated dfn 159 */ 160 public int getDFN(Instruction inst) { 161 return depthFirstNumbers.get(inst); 162 } 163 164 /** 165 * Prints the DFN numbers associated with each instruction. 166 * 167 * @param ir the IR that contains the instructions 168 */ 169 void printDfns(IR ir) { 170 System.out.println("DFNS: **** " + ir.getMethod() + "****"); 171 for (Instruction inst = ir.firstInstructionInCodeOrder(); inst != null; inst = 172 inst.nextInstructionInCodeOrder()) { 173 System.out.println(getDFN(inst) + " " + inst); 174 } 175 } 176 177 /** 178 * @param live the live interval 179 * @param bb the basic block for the live interval 180 * @return the Depth-first-number of the beginning of the live interval. If the 181 * interval is open-ended, the dfn for the beginning of the basic block will 182 * be returned instead. 183 */ 184 int getDfnBegin(LiveIntervalElement live, BasicBlock bb) { 185 Instruction begin = live.getBegin(); 186 int dfnBegin; 187 if (begin != null) { 188 dfnBegin = getDFN(begin); 189 } else { 190 dfnBegin = getDFN(bb.firstInstruction()); 191 } 192 return dfnBegin; 193 } 194 195 /** 196 * @param live the live interval 197 * @param bb the basic block for the live interval 198 * @return the Depth-first-number of the end of the live interval. If the 199 * interval is open-ended, the dfn for the end of the basic block will 200 * be returned instead. 201 */ 202 int getDfnEnd(LiveIntervalElement live, BasicBlock bb) { 203 Instruction end = live.getEnd(); 204 int dfnEnd; 205 if (end != null) { 206 dfnEnd = getDFN(end); 207 } else { 208 dfnEnd = getDFN(bb.lastInstruction()); 209 } 210 return dfnEnd; 211 } 212 213}