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    }