Mercurial > hg > truffle
diff graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRInstruction.java @ 4245:75c620f90ab9
Support stack-operands and register hints in new register allocator API
author | Christian Wimmer <Christian.Wimmer@Oracle.com> |
---|---|
date | Sat, 07 Jan 2012 16:04:22 -0800 |
parents | 4e86f3befd65 |
children | 9ce8594bedaf |
line wrap: on
line diff
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRInstruction.java Fri Jan 06 15:35:52 2012 +0100 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRInstruction.java Sat Jan 07 16:04:22 2012 -0800 @@ -22,6 +22,8 @@ */ package com.oracle.max.graal.compiler.lir; +import java.util.*; + import com.oracle.max.cri.ci.*; import com.oracle.max.graal.compiler.asm.*; import com.oracle.max.graal.compiler.util.*; @@ -33,19 +35,34 @@ public static final CiValue[] NO_OPERANDS = {}; - public static final OperandMode[] OPERAND_MODES = OperandMode.values(); - /** - * Iterator interface for iterating over a list of values. + * Iterator for iterating over a list of values. Subclasses must overwrite one of the doValue methods. + * Clients of the class must only call the doValue method that takes additional parameters. */ - public interface ValueProcedure { + public abstract static class ValueProcedure { /** - * The iterator method. + * Iterator method to be overwritten. This version of the iterator does not take additional parameters + * to keep the signature short. * * @param value The value that is iterated. * @return The new value to replace the value that was passed in. */ - CiValue doValue(CiValue value); + protected CiValue doValue(CiValue value) { + throw Util.shouldNotReachHere("One of the doValue() methods must be overwritten"); + } + + /** + * Iterator method to be overwritten. This version of the iterator gets additional parameters about the + * processed value. + * + * @param value The value that is iterated. + * @param mode The operand mode for the value. + * @param flags A set of flags for the value. + * @return The new value to replace the value that was passed in. + */ + public CiValue doValue(CiValue value, OperandMode mode, EnumSet<OperandFlag> flags) { + return doValue(value); + } } @@ -82,6 +99,37 @@ } /** + * Flags for an operand. + */ + public enum OperandFlag { + /** + * The value can be a {@link CiRegisterValue}. + */ + Register, + + /** + * The value can be a {@link CiStackSlot}. + */ + Stack, + + /** + * The value can be a {@link CiConstant}. + */ + Constant, + + /** + * The value can be {@link CiValue#IllegalValue}. + */ + Illegal, + + /** + * The register allocator should try to assign a certain register to improve code quality. + * Use {@link LIRInstruction#forEachRegisterHint} to access the register hints. + */ + RegisterHint, + } + + /** * The opcode of this instruction. */ public final LIROpcode code; @@ -152,7 +200,7 @@ * @param index the index of the operand requested. * @return the {@code index}'th input operand. */ - public final CiValue input(int index) { + protected final CiValue input(int index) { return inputs[index]; } @@ -162,7 +210,7 @@ * @param index the index of the operand requested. * @return the {@code index}'th alive operand. */ - public final CiValue alive(int index) { + protected final CiValue alive(int index) { return alives[index]; } @@ -172,7 +220,7 @@ * @param index the index of the operand requested. * @return the {@code index}'th temp operand. */ - public final CiValue temp(int index) { + protected final CiValue temp(int index) { return temps[index]; } @@ -181,7 +229,7 @@ * * @return return the result operand */ - public final CiValue output(int index) { + protected final CiValue output(int index) { return outputs[index]; } @@ -196,62 +244,26 @@ return inputs.length > 0 || alives.length > 0 || temps.length > 0 || outputs.length > 0 || info != null || hasCall(); } - public final int operandCount(OperandMode mode) { - switch (mode) { - case Output: return outputs.length; - case Input: return inputs.length; - case Alive: return alives.length; - case Temp: return temps.length; - default: throw Util.shouldNotReachHere(); - } - } - - public final CiValue operandAt(OperandMode mode, int index) { - assert index < operandCount(mode); - switch (mode) { - case Output: return outputs[index]; - case Input: return inputs[index]; - case Alive: return alives[index]; - case Temp: return temps[index]; - default: throw Util.shouldNotReachHere(); - } - } - - public final void setOperandAt(OperandMode mode, int index, CiValue location) { - assert index < operandCount(mode); - assert location.kind != CiKind.Illegal; - assert operandAt(mode, index).kind == location.kind; - switch (mode) { - case Output: outputs[index] = location; break; - case Input: inputs[index] = location; break; - case Alive: alives[index] = location; break; - case Temp: temps[index] = location; break; - default: throw Util.shouldNotReachHere(); + private void forEach(CiValue[] values, OperandMode mode, ValueProcedure proc) { + for (int i = 0; i < values.length; i++) { + values[i] = proc.doValue(values[i], mode, flagsFor(mode, i)); } } public final void forEachInput(ValueProcedure proc) { - for (int i = 0; i < inputs.length; i++) { - inputs[i] = proc.doValue(inputs[i]); - } + forEach(inputs, OperandMode.Input, proc); } public final void forEachAlive(ValueProcedure proc) { - for (int i = 0; i < alives.length; i++) { - alives[i] = proc.doValue(alives[i]); - } + forEach(alives, OperandMode.Alive, proc); } public final void forEachTemp(ValueProcedure proc) { - for (int i = 0; i < temps.length; i++) { - temps[i] = proc.doValue(temps[i]); - } + forEach(temps, OperandMode.Temp, proc); } public final void forEachOutput(ValueProcedure proc) { - for (int i = 0; i < outputs.length; i++) { - outputs[i] = proc.doValue(outputs[i]); - } + forEach(outputs, OperandMode.Output, proc); } public final void forEachState(ValueProcedure proc) { @@ -275,22 +287,46 @@ } /** - * Used by the register allocator. The result operand of this instruction should get - * the same register assigned as the returned operand. - * @return The register hint for the output operand, or null if no register hint should be defined. + * Iterates all register hints for the specified value, i.e., all preferred candidates for the register to be + * assigned to the value. + * <br> + * Subclasses can override this method. The default implementation processes all Input operands as the hints for + * an Output operand, and all Output operands as the hints for an Input operand. + * + * @param value The value the hints are needed for. + * @param mode The operand mode of the value. + * @param proc The procedure invoked for all the hints. If the procedure returns a non-null value, the iteration is stopped + * and the value is returned by this method, i.e., clients can stop the iteration once a suitable hint has been found. + * @return The non-null value returned by the procedure, or null. */ - public CiValue registerHint() { + public CiValue forEachRegisterHint(CiValue value, OperandMode mode, ValueProcedure proc) { + CiValue[] hints; + if (mode == OperandMode.Input) { + hints = outputs; + } else if (mode == OperandMode.Output) { + hints = inputs; + } else { + return null; + } + + for (int i = 0; i < hints.length; i++) { + CiValue result = proc.doValue(hints[i], null, null); + if (result != null) { + return result; + } + } return null; } /** - * Used by the register allocator to decide whether an input operand can be assigned a stack slot. - * Subclasses should override this method when an input can be memory. - * @param index The index of the operand in {@link #inputs}. - * @return true if the input operand with the given index can be assigned a stack slot. + * Used by the register allocator to decide which kind of location can be assigned to the operand. + * @param mode The kind of operand. + * @param index The index of the operand. + * @return The flags for the operand. */ - public boolean inputCanBeMemory(int index) { - return false; + // TODO this method will go away when we have named operands, the flags will be specified as annotations instead. + protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) { + return EnumSet.of(OperandFlag.Register); }