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