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      public String toString() {
242        if (isPhysical()) {
243          return PhysicalRegisterSet.getName(number);
244        }
245    
246        // Set s to descriptive letter for register type
247        String s = isLocal() ? "l" : "t";
248        s = s + getNumber() + (spansBasicBlock() ? "p" : "") + (isSSA() ? "s" : "") + typeName();
249        return s;
250      }
251    
252      public String typeName() {
253        String s = "";
254        if (isCondition()) s += "c";
255        if (isAddress()) s += "a";
256        if (isInteger()) s += "i";
257        if (isDouble()) s += "d";
258        if (isFloat()) s += "f";
259        if (isLong()) s += "l";
260        if (isValidation()) s += "v";
261        if (s == null) s = "_";
262        return s;
263      }
264    
265      /* used by the register allocator */
266      public Register mapsToRegister;
267    
268      public void clearAllocationFlags() {
269        flags &= ~(PINNED | TOUCHED | ALLOCATED | SPILLED);
270      }
271    
272      public void pinRegister() {
273        flags |= PINNED | TOUCHED;
274      }
275    
276      public void reserveRegister() {
277        flags |= PINNED;
278      }
279    
280      public void touchRegister() {
281        flags |= TOUCHED;
282      }
283    
284      public void allocateRegister() {
285        flags = (flags & ~SPILLED) | (ALLOCATED | TOUCHED);
286      }
287    
288      public void allocateRegister(Register reg) {
289        flags = (flags & ~SPILLED) | (ALLOCATED | TOUCHED);
290        mapsToRegister = reg;
291      }
292    
293      public void allocateToRegister(Register reg) {
294        this.allocateRegister(reg);
295        reg.allocateRegister(this);
296      }
297    
298      public void deallocateRegister() {
299        flags &= ~ALLOCATED;
300        mapsToRegister = null;
301      }
302    
303      public void freeRegister() {
304        deallocateRegister();
305        Register symbReg = mapsToRegister;
306        if (symbReg != null) {
307          symbReg.clearSpill();
308        }
309      }
310    
311      public void spillRegister() {
312        flags = (flags & ~ALLOCATED) | SPILLED;
313      }
314    
315      public void clearSpill() {
316        flags &= ~SPILLED;
317      }
318    
319      public void unpinRegister() {
320        flags &= ~PINNED;
321      }
322    
323      public boolean isTouched() {
324        return (flags & TOUCHED) != 0;
325      }
326    
327      public boolean isAllocated() {
328        return (flags & ALLOCATED) != 0;
329      }
330    
331      public boolean isSpilled() {
332        return (flags & SPILLED) != 0;
333      }
334    
335      public boolean isPinned() {
336        return (flags & PINNED) != 0;
337      }
338    
339      public boolean isAvailable() {
340        return (flags & (ALLOCATED | PINNED)) == 0;
341      }
342    
343      public Register getRegisterAllocated() {
344        return mapsToRegister;
345      }
346    
347      public int getSpillAllocated() {
348        return scratch;
349      }
350    
351      public int hashCode() {
352        return number;
353      }
354    
355      /* inlined behavior of DoublyLinkedListElement */ Register next, prev;
356    
357      public Register getNext() { return next; }
358    
359      void setNext(Register e) { next = e; }
360    
361      public Register getPrev() { return prev; }
362    
363      public void linkWithNext(Register Next) {
364        next = Next;
365        Next.prev = this;
366      }
367    
368      void append(Register l) {
369        next = l;
370        l.prev = this;
371      }
372    
373      Register remove() {
374        Register Prev = prev, Next = next;
375        if (Prev != null) Prev.next = Next;
376        if (Next != null) Next.prev = Prev;
377        return Next;
378      }
379      /* end of inlined behavior */
380    }