comparison graal/Compiler/src/com/sun/c1x/ir/Value.java @ 2507:9ec15d6914ca

Pull over of compiler from maxine repository.
author Thomas Wuerthinger <thomas@wuerthinger.net>
date Wed, 27 Apr 2011 11:43:22 +0200
parents
children
comparison
equal deleted inserted replaced
2506:4a3bf8a5bf41 2507:9ec15d6914ca
1 /*
2 * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23 package com.sun.c1x.ir;
24
25 import static com.sun.c1x.ir.Value.Flag.*;
26
27 import com.sun.c1x.*;
28 import com.sun.c1x.debug.*;
29 import com.sun.c1x.opt.*;
30 import com.sun.cri.ci.*;
31 import com.sun.cri.ri.*;
32
33 /**
34 * This class represents a value within the HIR graph, including local variables, phis, and
35 * all other instructions.
36 *
37 * @author Ben L. Titzer
38 */
39 public abstract class Value {
40 /**
41 * An enumeration of flags on values.
42 */
43 public enum Flag {
44 NonNull, // this value is non-null
45
46 NoNullCheck, // does not require null check
47 NoStoreCheck, // does not require store check
48 NoBoundsCheck, // does not require bounds check
49 NoZeroCheck, // divide or modulus cannot cause exception
50
51 NoReadBarrier, // does not require read barrier
52 NoWriteBarrier, // does not require write barrier
53 NoDivSpecialCase, // divide or modulus cannot be special case of MIN_INT / -1
54 DirectCompare,
55 IsLoaded, // field or method is resolved and class is loaded and initialized
56 IsStatic, // field or method access is static
57 IsSafepoint, // branch is backward (safepoint)
58 IsStrictFP,
59 PreservesState, // intrinsic preserves state
60 UnorderedIsTrue,
61 NeedsPatching,
62 LiveValue, // live because value is used
63 LiveDeopt, // live for deoptimization
64 LiveControl, // live for control dependencies
65 LiveSideEffect, // live for possible side-effects only
66 LiveStore, // instruction is a store
67 PhiDead, // phi is illegal because local is dead
68 PhiCannotSimplify, // phi cannot be simplified
69 PhiVisited, // phi has been visited during simplification
70
71 ResultIsUnique; // the result of this instruction is guaranteed to be unique (e.g. a new object)
72
73 public final int mask = 1 << ordinal();
74 }
75
76 private static final int LIVE_FLAGS = Flag.LiveValue.mask |
77 Flag.LiveDeopt.mask |
78 Flag.LiveControl.mask |
79 Flag.LiveSideEffect.mask;
80 /**
81 * The kind of this value. This is {@link CiKind#Void} for instructions that produce no value.
82 * This kind is guaranteed to be a {@linkplain CiKind#stackKind() stack kind}.
83 */
84 public final CiKind kind;
85
86 /**
87 * Unique identifier for this value. This field's value is lazily initialized by {@link #id()}.
88 */
89 private int id;
90
91 /**
92 * A mask of {@linkplain Flag flags} denoting extra properties of this value.
93 */
94 private int flags;
95
96 protected CiValue operand = CiValue.IllegalValue;
97
98 /**
99 * A cache for analysis information. Every optimization must reset this field to {@code null} once it has completed.
100 */
101 public Object optInfo;
102
103 /**
104 * Used by {@link InstructionSubstituter}.
105 */
106 public Value subst;
107
108 public abstract BlockBegin block();
109
110 /**
111 * Creates a new value with the specified kind.
112 * @param kind the type of this value
113 */
114 public Value(CiKind kind) {
115 assert kind == kind.stackKind() : kind + " != " + kind.stackKind();
116 this.kind = kind;
117 }
118
119 /**
120 * Checks whether this instruction is live (i.e. code should be generated for it).
121 * This is computed in a dedicated pass by {@link LivenessMarker}.
122 * An instruction is live because its value is needed by another live instruction,
123 * because its value is needed for deoptimization, or the program is control dependent
124 * upon it.
125 * @return {@code true} if this instruction should be considered live
126 */
127 public final boolean isLive() {
128 return C1XOptions.PinAllInstructions || (flags & LIVE_FLAGS) != 0;
129 }
130
131 /**
132 * Clears all liveness flags.
133 */
134 public final void clearLive() {
135 flags = flags & ~LIVE_FLAGS;
136 }
137
138 /**
139 * Gets the instruction that should be substituted for this one. Note that this
140 * method is recursive; if the substituted instruction has a substitution, then
141 * the final substituted instruction will be returned. If there is no substitution
142 * for this instruction, {@code this} will be returned.
143 * @return the substitution for this instruction
144 */
145 public final Value subst() {
146 if (subst == null) {
147 return this;
148 }
149 return subst.subst();
150 }
151
152 /**
153 * Checks whether this instruction has a substitute.
154 * @return {@code true} if this instruction has a substitution.
155 */
156 public final boolean hasSubst() {
157 return subst != null;
158 }
159
160 /**
161 * Eliminates a given runtime check for this instruction.
162 *
163 * @param flag the flag representing the (elimination of the) runtime check
164 */
165 public final void clearRuntimeCheck(Flag flag) {
166 if (!checkFlag(flag)) {
167 setFlag(flag);
168 runtimeCheckCleared();
169 if (flag == NoNullCheck) {
170 C1XMetrics.NullCheckEliminations++;
171 } else if (flag == NoBoundsCheck) {
172 C1XMetrics.BoundsChecksElminations++;
173 } else if (flag == NoStoreCheck) {
174 C1XMetrics.StoreCheckEliminations++;
175 } else if (flag != NoZeroCheck) {
176 throw new InternalError("Unknown runtime check: " + flag);
177 }
178 }
179 }
180
181
182 /**
183 * Clear any internal state related to null checks, because a null check
184 * for this instruction is redundant. The state cleared may depend
185 * on the type of this instruction
186 */
187 public final void eliminateNullCheck() {
188 clearRuntimeCheck(NoNullCheck);
189 }
190
191 /**
192 * Notifies this instruction that a runtime check has been
193 * eliminated or made redundant.
194 */
195 protected void runtimeCheckCleared() {
196 }
197
198 /**
199 * Check whether this instruction has the specified flag set.
200 * @param flag the flag to test
201 * @return {@code true} if this instruction has the flag
202 */
203 public final boolean checkFlag(Flag flag) {
204 return (flags & flag.mask) != 0;
205 }
206
207 /**
208 * Set a flag on this instruction.
209 * @param flag the flag to set
210 */
211 public final void setFlag(Flag flag) {
212 flags |= flag.mask;
213 }
214
215 /**
216 * Clear a flag on this instruction.
217 * @param flag the flag to set
218 */
219 public final void clearFlag(Flag flag) {
220 flags &= ~flag.mask;
221 }
222
223 /**
224 * Set or clear a flag on this instruction.
225 * @param flag the flag to set
226 * @param val if {@code true}, set the flag, otherwise clear it
227 */
228 public final void setFlag(Flag flag, boolean val) {
229 if (val) {
230 setFlag(flag);
231 } else {
232 clearFlag(flag);
233 }
234 }
235
236 /**
237 * Initialize a flag on this instruction. Assumes the flag is not initially set,
238 * e.g. in the constructor of an instruction.
239 * @param flag the flag to set
240 * @param val if {@code true}, set the flag, otherwise do nothing
241 */
242 public final void initFlag(Flag flag, boolean val) {
243 if (val) {
244 setFlag(flag);
245 }
246 }
247
248 /**
249 * Checks whether this instruction produces a value which is guaranteed to be non-null.
250 * @return {@code true} if this instruction's value is not null
251 */
252 public final boolean isNonNull() {
253 return checkFlag(Flag.NonNull);
254 }
255
256 /**
257 * Checks whether this instruction needs a null check.
258 * @return {@code true} if this instruction needs a null check
259 */
260 public final boolean needsNullCheck() {
261 return !checkFlag(Flag.NoNullCheck);
262 }
263
264 /**
265 * Checks whether this value is a constant (i.e. it is of type {@link Constant}.
266 * @return {@code true} if this value is a constant
267 */
268 public final boolean isConstant() {
269 return this instanceof Constant;
270 }
271
272 /**
273 * Checks whether this value represents the null constant.
274 * @return {@code true} if this value represents the null constant
275 */
276 public final boolean isNullConstant() {
277 return this instanceof Constant && ((Constant) this).value.isNull();
278 }
279
280 /**
281 * Checks whether this instruction "is illegal"--i.e. it represents a dead
282 * phi or an instruction which does not produce a value.
283 * @return {@code true} if this instruction is illegal as an input value to another instruction
284 */
285 public final boolean isIllegal() {
286 return checkFlag(Flag.PhiDead);
287 }
288
289 /**
290 * Convert this value to a constant if it is a constant, otherwise return null.
291 * @return the {@link CiConstant} represented by this value if it is a constant; {@code null}
292 * otherwise
293 */
294 public final CiConstant asConstant() {
295 if (this instanceof Constant) {
296 return ((Constant) this).value;
297 }
298 return null;
299 }
300
301 /**
302 * Gets the LIR operand associated with this instruction.
303 * @return the LIR operand for this instruction
304 */
305 public final CiValue operand() {
306 return operand;
307 }
308
309 /**
310 * Sets the LIR operand associated with this instruction.
311 * @param operand the operand to associate with this instruction
312 */
313 public final void setOperand(CiValue operand) {
314 assert this.operand.isIllegal() : "operand cannot be set twice";
315 assert operand != null && operand.isLegal() : "operand must be legal";
316 assert operand.kind.stackKind() == this.kind;
317 this.operand = operand;
318 }
319
320 /**
321 * Clears the LIR operand associated with this instruction.
322 */
323 public final void clearOperand() {
324 this.operand = CiValue.IllegalValue;
325 }
326
327 /**
328 * Computes the exact type of the result of this instruction, if possible.
329 * @return the exact type of the result of this instruction, if it is known; {@code null} otherwise
330 */
331 public RiType exactType() {
332 return null; // default: unknown exact type
333 }
334
335 /**
336 * Computes the declared type of the result of this instruction, if possible.
337 * @return the declared type of the result of this instruction, if it is known; {@code null} otherwise
338 */
339 public RiType declaredType() {
340 return null; // default: unknown declared type
341 }
342
343 /**
344 * Apply the specified closure to all the input values of this instruction.
345 * @param closure the closure to apply
346 */
347 public void inputValuesDo(ValueClosure closure) {
348 // default: do nothing.
349 }
350
351 @Override
352 public String toString() {
353 StringBuilder builder = new StringBuilder();
354 builder.append(getClass().getSimpleName());
355 builder.append(" #");
356 builder.append(id());
357 if (this instanceof Instruction) {
358 builder.append(" @ ");
359 builder.append(((Instruction) this).bci());
360 }
361 builder.append(" [").append(flagsToString()).append("]");
362 return builder.toString();
363 }
364
365 public String flagsToString() {
366 StringBuilder sb = new StringBuilder();
367 for (Flag f : Flag.values()) {
368 if (checkFlag(f)) {
369 if (sb.length() != 0) {
370 sb.append(' ');
371 }
372 sb.append(f.name());
373 }
374 }
375 return sb.toString();
376 }
377
378 public final boolean isDeadPhi() {
379 return checkFlag(Flag.PhiDead);
380 }
381
382 /**
383 * This method supports the visitor pattern by accepting a visitor and calling the
384 * appropriate {@code visit()} method.
385 *
386 * @param v the visitor to accept
387 */
388 public abstract void accept(ValueVisitor v);
389
390 public abstract void print(LogStream out);
391
392 /**
393 * This method returns a unique identification number for this value. The number returned is unique
394 * only to the compilation that produced this node and is computed lazily by using the current compilation
395 * for the current thread. Thus the first access is a hash lookup using {@link java.lang.ThreadLocal} and
396 * should not be considered fast. Because of the potentially slow first access, use of this ID should be
397 * restricted to debugging output.
398 * @return a unique ID for this value
399 */
400 public int id() {
401 if (id == 0) {
402 C1XMetrics.UniqueValueIdsAssigned++;
403 id = C1XCompilation.compilation().nextID();
404 }
405 return id;
406 }
407 }