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 */ 013 package org.jikesrvm.compilers.opt.ir; 014 015 import org.jikesrvm.ArchitectureSpecificOpt.PhysicalRegisterSet; 016 import org.jikesrvm.compilers.opt.ir.operand.RegisterOperand; 017 018 /** 019 * Represents a symbolic or physical register. 020 * Registers are shared among all Operands -- for a given register 021 * pool, there is only one instance of an Register with each number. 022 * 023 * @see RegisterOperand 024 * @see org.jikesrvm.ArchitectureSpecificOpt.RegisterPool 025 */ 026 public final class Register { 027 028 /** 029 * Index number relative to register pool. 030 */ 031 public final int number; 032 033 /** 034 * Encoding of register properties & scratch bits 035 */ 036 private int flags; 037 038 private static final int LOCAL = 0x00001; /* local variable */ 039 private static final int SPAN_BASIC_BLOCK = 0x00002; /* live on a basic block boundary */ 040 private static final int SSA = 0x00004; /* only one assignment to this register */ 041 private static final int SEEN_USE = 0x00008; /* seen use */ 042 private static final int PHYSICAL = 0x00010; /* physical (real) register - not symbolic */ 043 044 /* register type for both physical and symbolic */ 045 private static final int TYPE_SHIFT = 6; /* # bits to shift */ 046 private static final int ADDRESS = 0x00040; /* address */ 047 private static final int INTEGER = 0x00080; /* integer */ 048 private static final int FLOAT = 0x00100; /* floating-point single precision */ 049 private static final int DOUBLE = 0x00200; /* floating-point double precision */ 050 private static final int CONDITION = 0x00400; /* condition: PPC,x86*/ 051 private static final int LONG = 0x00800; /* long (two ints)*/ 052 private static final int VALIDATION = 0x01000; /* validation pseudo-register */ 053 054 /* this for physical register only */ 055 private static final int VOLATILE = 0x02000; 056 private static final int NON_VOLATILE = 0x04000; 057 058 /* used with live analysis */ 059 private static final int EXCLUDE_LIVEANAL = 0x08000; /* reg is excluded from live analysis */ 060 061 /* used by the register allocator */ 062 private static final int SPILLED = 0x10000; /* spilled into a memory location */ 063 private static final int TOUCHED = 0x20000; /* register touched */ 064 private static final int ALLOCATED = 0x40000; /* allocated to some register */ 065 private static final int PINNED = 0x80000; /* pinned, unavailable for allocation */ 066 067 /* derived constants to be exported */ 068 private static final int TYPE_MASK = (ADDRESS | INTEGER | FLOAT | DOUBLE | CONDITION | LONG | VALIDATION); 069 public static final int ADDRESS_TYPE = ADDRESS >>> TYPE_SHIFT; 070 public static final int INTEGER_TYPE = INTEGER >>> TYPE_SHIFT; 071 public static final int FLOAT_TYPE = FLOAT >>> TYPE_SHIFT; 072 public static final int DOUBLE_TYPE = DOUBLE >>> TYPE_SHIFT; 073 public static final int CONDITION_TYPE = CONDITION >>> TYPE_SHIFT; 074 public static final int LONG_TYPE = LONG >>> TYPE_SHIFT; 075 public static final int VALIDATION_TYPE = VALIDATION >>> TYPE_SHIFT; 076 077 public boolean isTemp() { return (flags & LOCAL) == 0; } 078 079 public boolean isLocal() { return (flags & LOCAL) != 0; } 080 081 public boolean spansBasicBlock() { return (flags & SPAN_BASIC_BLOCK) != 0; } 082 083 public boolean isSSA() { return (flags & SSA) != 0; } 084 085 public boolean seenUse() { return (flags & SEEN_USE) != 0; } 086 087 public boolean isPhysical() { return (flags & PHYSICAL) != 0; } 088 089 public boolean isSymbolic() { return (flags & PHYSICAL) == 0; } 090 091 public boolean isAddress() { return (flags & ADDRESS) != 0; } 092 093 public boolean isInteger() { return (flags & INTEGER) != 0; } 094 095 public boolean isLong() { return (flags & LONG) != 0; } 096 097 public boolean isNatural() { return (flags & (INTEGER | LONG | ADDRESS)) != 0; } 098 099 public boolean isFloat() { return (flags & FLOAT) != 0; } 100 101 public boolean isDouble() { return (flags & DOUBLE) != 0; } 102 103 public boolean isFloatingPoint() { return (flags & (FLOAT | DOUBLE)) != 0; } 104 105 public boolean isCondition() { return (flags & CONDITION) != 0; } 106 107 public boolean isValidation() { return (flags & VALIDATION) != 0; } 108 109 public boolean isExcludedLiveA() { return (flags & EXCLUDE_LIVEANAL) != 0; } 110 111 public int getType() { return (flags & TYPE_MASK) >>> TYPE_SHIFT; } 112 113 public boolean isVolatile() { return (flags & VOLATILE) != 0; } 114 115 public boolean isNonVolatile() { return (flags & NON_VOLATILE) != 0; } 116 117 public void setLocal() { flags |= LOCAL; } 118 119 public void setSpansBasicBlock() { flags |= SPAN_BASIC_BLOCK; } 120 121 public void setSSA() { flags |= SSA; } 122 123 public void setSeenUse() { flags |= SEEN_USE; } 124 125 public void setPhysical() { flags |= PHYSICAL; } 126 127 public void setAddress() { flags |= ADDRESS; } 128 129 public void setInteger() { flags |= INTEGER; } 130 131 public void setFloat() { flags |= FLOAT; } 132 133 public void setDouble() { flags |= DOUBLE; } 134 135 public void setLong() { flags |= LONG; } 136 137 public void setCondition() { flags = (flags & ~TYPE_MASK) | CONDITION; } 138 139 public void setValidation() { flags |= VALIDATION; } 140 141 public void setExcludedLiveA() { flags |= EXCLUDE_LIVEANAL; } 142 143 public void setVolatile() { flags |= VOLATILE; } 144 145 public void setNonVolatile() { flags |= NON_VOLATILE; } 146 147 public void putSSA(boolean a) { 148 if (a) { 149 setSSA(); 150 } else { 151 clearSSA(); 152 } 153 } 154 155 public void putSpansBasicBlock(boolean a) { 156 if (a) { 157 setSpansBasicBlock(); 158 } else { 159 clearSpansBasicBlock(); 160 } 161 } 162 163 public void clearLocal() { flags &= ~LOCAL; } 164 165 public void clearSpansBasicBlock() { flags &= ~SPAN_BASIC_BLOCK; } 166 167 public void clearSSA() { flags &= ~SSA; } 168 169 public void clearSeenUse() { flags &= ~SEEN_USE; } 170 171 public void clearPhysical() { flags &= ~PHYSICAL; } 172 173 public void clearAddress() { flags &= ~ADDRESS; } 174 175 public void clearInteger() { flags &= ~INTEGER; } 176 177 public void clearFloat() { flags &= ~FLOAT; } 178 179 public void clearDouble() { flags &= ~DOUBLE; } 180 181 public void clearLong() { flags &= ~LONG; } 182 183 public void clearCondition() { flags &= ~CONDITION; } 184 185 public void clearType() { flags &= ~TYPE_MASK; } 186 187 public void clearValidation() { flags &= ~VALIDATION; } 188 189 public Object scratchObject; 190 191 /** 192 * Used in dependence graph construction. 193 */ 194 public void setdNode(org.jikesrvm.compilers.opt.depgraph.DepGraphNode a) { 195 scratchObject = a; 196 } 197 198 public org.jikesrvm.compilers.opt.depgraph.DepGraphNode dNode() { 199 return (org.jikesrvm.compilers.opt.depgraph.DepGraphNode) scratchObject; 200 } 201 202 /** 203 * Used to store register lists. 204 * Computed on demand by IR.computeDU(). 205 */ 206 public RegisterOperand defList, useList; 207 208 /** 209 * This accessor is only valid when register lists are valid 210 */ 211 public Instruction getFirstDef() { 212 if (defList == null) { 213 return null; 214 } else { 215 return defList.instruction; 216 } 217 } 218 219 /** 220 * The number of uses; used by flow-insensitive optimizations 221 */ 222 public int useCount; 223 224 /** 225 * A field optimizations can use as they choose 226 */ 227 public int scratch; 228 229 public Register(int Number) { 230 number = Number; 231 } 232 233 public int getNumber() { 234 int start = PhysicalRegisterSet.getSize(); 235 return number - start; 236 } 237 238 /** 239 * Returns the string representation of this register. 240 */ 241 @Override 242 public String toString() { 243 if (isPhysical()) { 244 return PhysicalRegisterSet.getName(number); 245 } 246 247 // Set s to descriptive letter for register type 248 String s = isLocal() ? "l" : "t"; 249 s = s + getNumber() + (spansBasicBlock() ? "p" : "") + (isSSA() ? "s" : "") + typeName(); 250 return s; 251 } 252 253 public String typeName() { 254 String s = ""; 255 if (isCondition()) s += "c"; 256 if (isAddress()) s += "a"; 257 if (isInteger()) s += "i"; 258 if (isDouble()) s += "d"; 259 if (isFloat()) s += "f"; 260 if (isLong()) s += "l"; 261 if (isValidation()) s += "v"; 262 if (s == null) s = "_"; 263 return s; 264 } 265 266 /* used by the register allocator */ 267 public Register mapsToRegister; 268 269 public void clearAllocationFlags() { 270 flags &= ~(PINNED | TOUCHED | ALLOCATED | SPILLED); 271 } 272 273 public void pinRegister() { 274 flags |= PINNED | TOUCHED; 275 } 276 277 public void reserveRegister() { 278 flags |= PINNED; 279 } 280 281 public void touchRegister() { 282 flags |= TOUCHED; 283 } 284 285 public void allocateRegister() { 286 flags = (flags & ~SPILLED) | (ALLOCATED | TOUCHED); 287 } 288 289 public void allocateRegister(Register reg) { 290 flags = (flags & ~SPILLED) | (ALLOCATED | TOUCHED); 291 mapsToRegister = reg; 292 } 293 294 public void allocateToRegister(Register reg) { 295 this.allocateRegister(reg); 296 reg.allocateRegister(this); 297 } 298 299 public void deallocateRegister() { 300 flags &= ~ALLOCATED; 301 mapsToRegister = null; 302 } 303 304 public void freeRegister() { 305 deallocateRegister(); 306 Register symbReg = mapsToRegister; 307 if (symbReg != null) { 308 symbReg.clearSpill(); 309 } 310 } 311 312 public void spillRegister() { 313 flags = (flags & ~ALLOCATED) | SPILLED; 314 } 315 316 public void clearSpill() { 317 flags &= ~SPILLED; 318 } 319 320 public void unpinRegister() { 321 flags &= ~PINNED; 322 } 323 324 public boolean isTouched() { 325 return (flags & TOUCHED) != 0; 326 } 327 328 public boolean isAllocated() { 329 return (flags & ALLOCATED) != 0; 330 } 331 332 public boolean isSpilled() { 333 return (flags & SPILLED) != 0; 334 } 335 336 public boolean isPinned() { 337 return (flags & PINNED) != 0; 338 } 339 340 public boolean isAvailable() { 341 return (flags & (ALLOCATED | PINNED)) == 0; 342 } 343 344 public Register getRegisterAllocated() { 345 return mapsToRegister; 346 } 347 348 public int getSpillAllocated() { 349 return scratch; 350 } 351 352 @Override 353 public int hashCode() { 354 return number; 355 } 356 357 /* inlined behavior of DoublyLinkedListElement */ Register next, prev; 358 359 public Register getNext() { return next; } 360 361 void setNext(Register e) { next = e; } 362 363 public Register getPrev() { return prev; } 364 365 public void linkWithNext(Register Next) { 366 next = Next; 367 Next.prev = this; 368 } 369 370 void append(Register l) { 371 next = l; 372 l.prev = this; 373 } 374 375 Register remove() { 376 Register Prev = prev, Next = next; 377 if (Prev != null) Prev.next = Next; 378 if (Next != null) Next.prev = Prev; 379 return Next; 380 } 381 /* end of inlined behavior */ 382 }