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}