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 }