changeset 16138:f315b1c0a590

Introduce InstructionValueProcedure.
author Josef Eisl <josef.eisl@jku.at>
date Wed, 18 Jun 2014 14:21:10 +0200
parents 0eb8270ae69d
children b7a1ece4f07b 7109baa7b9eb
files graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRFrameState.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValue.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java
diffstat 11 files changed, 337 insertions(+), 154 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java	Wed Jun 04 14:52:17 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java	Wed Jun 18 14:21:10 2014 +0200
@@ -80,18 +80,20 @@
             }
         }
 
-        private void collectStats(final LIRInstruction instr) {
-            instr.forEachOutput(new ValueProcedure() {
+        private ValueProcedure collectStatsProc = new ValueProcedure() {
 
-                @Override
-                public Value doValue(Value value) {
-                    if (ValueUtil.isRegister(value)) {
-                        final Register reg = ValueUtil.asRegister(value);
-                        registers.add(reg);
-                    }
-                    return value;
+            @Override
+            public Value doValue(Value value) {
+                if (ValueUtil.isRegister(value)) {
+                    final Register reg = ValueUtil.asRegister(value);
+                    registers.add(reg);
                 }
-            });
+                return value;
+            }
+        };
+
+        private void collectStats(final LIRInstruction instr) {
+            instr.forEachOutput(collectStatsProc);
 
             if (instr instanceof MoveOp) {
                 MoveOp move = (MoveOp) instr;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Wed Jun 04 14:52:17 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Wed Jun 18 14:21:10 2014 +0200
@@ -41,6 +41,7 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
 import com.oracle.graal.lir.LIRInstruction.StateProcedure;
@@ -1123,6 +1124,70 @@
     void buildIntervals() {
 
         try (Indent indent = Debug.logAndIndent("build intervals")) {
+            InstructionValueProcedure outputProc = new InstructionValueProcedure() {
+
+                @Override
+                public Value doValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
+                    if (isVariableOrRegister(operand)) {
+                        addDef((AllocatableValue) operand, op, registerPriorityOfOutputOperand(op), operand.getLIRKind());
+                        addRegisterHint(op, operand, mode, flags, true);
+                    }
+                    return operand;
+                }
+            };
+
+            InstructionValueProcedure tempProc = new InstructionValueProcedure() {
+
+                @Override
+                public Value doValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
+                    if (isVariableOrRegister(operand)) {
+                        addTemp((AllocatableValue) operand, op.id(), RegisterPriority.MustHaveRegister, operand.getLIRKind());
+                        addRegisterHint(op, operand, mode, flags, false);
+                    }
+                    return operand;
+                }
+            };
+
+            InstructionValueProcedure aliveProc = new InstructionValueProcedure() {
+
+                @Override
+                public Value doValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
+                    if (isVariableOrRegister(operand)) {
+                        RegisterPriority p = registerPriorityOfInputOperand(flags);
+                        final int opId = op.id();
+                        final int blockFrom = getFirstLirInstructionId((blockForId(opId)));
+                        addUse((AllocatableValue) operand, blockFrom, opId + 1, p, operand.getLIRKind());
+                        addRegisterHint(op, operand, mode, flags, false);
+                    }
+                    return operand;
+                }
+            };
+
+            InstructionValueProcedure inputProc = new InstructionValueProcedure() {
+
+                @Override
+                public Value doValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
+                    if (isVariableOrRegister(operand)) {
+                        final int opId = op.id();
+                        final int blockFrom = getFirstLirInstructionId((blockForId(opId)));
+                        RegisterPriority p = registerPriorityOfInputOperand(flags);
+                        addUse((AllocatableValue) operand, blockFrom, opId, p, operand.getLIRKind());
+                        addRegisterHint(op, operand, mode, flags, false);
+                    }
+                    return operand;
+                }
+            };
+
+            InstructionValueProcedure stateProc = new InstructionValueProcedure() {
+
+                @Override
+                public Value doValue(LIRInstruction op, Value operand) {
+                    final int opId = op.id();
+                    final int blockFrom = getFirstLirInstructionId((blockForId(opId)));
+                    addUse((AllocatableValue) operand, blockFrom, opId + 1, RegisterPriority.None, operand.getLIRKind());
+                    return operand;
+                }
+            };
 
             // create a list with all caller-save registers (cpu, fpu, xmm)
             Register[] callerSaveRegs = frameMap.registerConfig.getCallerSaveRegisters();
@@ -1177,66 +1242,17 @@
                                 Debug.log("operation destroys all caller-save registers");
                             }
 
-                            op.forEachOutput(new ValueProcedure() {
-
-                                @Override
-                                public Value doValue(Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
-                                    if (isVariableOrRegister(operand)) {
-                                        addDef((AllocatableValue) operand, op, registerPriorityOfOutputOperand(op), operand.getLIRKind());
-                                        addRegisterHint(op, operand, mode, flags, true);
-                                    }
-                                    return operand;
-                                }
-                            });
-                            op.forEachTemp(new ValueProcedure() {
-
-                                @Override
-                                public Value doValue(Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
-                                    if (isVariableOrRegister(operand)) {
-                                        addTemp((AllocatableValue) operand, opId, RegisterPriority.MustHaveRegister, operand.getLIRKind());
-                                        addRegisterHint(op, operand, mode, flags, false);
-                                    }
-                                    return operand;
-                                }
-                            });
-                            op.forEachAlive(new ValueProcedure() {
-
-                                @Override
-                                public Value doValue(Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
-                                    if (isVariableOrRegister(operand)) {
-                                        RegisterPriority p = registerPriorityOfInputOperand(flags);
-                                        addUse((AllocatableValue) operand, blockFrom, opId + 1, p, operand.getLIRKind());
-                                        addRegisterHint(op, operand, mode, flags, false);
-                                    }
-                                    return operand;
-                                }
-                            });
-                            op.forEachInput(new ValueProcedure() {
-
-                                @Override
-                                public Value doValue(Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
-                                    if (isVariableOrRegister(operand)) {
-                                        RegisterPriority p = registerPriorityOfInputOperand(flags);
-                                        addUse((AllocatableValue) operand, blockFrom, opId, p, operand.getLIRKind());
-                                        addRegisterHint(op, operand, mode, flags, false);
-                                    }
-                                    return operand;
-                                }
-                            });
+                            op.forEachOutput(outputProc);
+                            op.forEachTemp(tempProc);
+                            op.forEachAlive(aliveProc);
+                            op.forEachInput(inputProc);
 
                             // Add uses of live locals from interpreter's point of view for proper
                             // debug information generation
                             // Treat these operands as temp values (if the live range is extended
                             // to a call site, the value would be in a register at
                             // the call otherwise)
-                            op.forEachState(new ValueProcedure() {
-
-                                @Override
-                                public Value doValue(Value operand) {
-                                    addUse((AllocatableValue) operand, blockFrom, opId + 1, RegisterPriority.None, operand.getLIRKind());
-                                    return operand;
-                                }
-                            });
+                            op.forEachState(stateProc);
 
                             // special steps for some instructions (especially moves)
                             handleMethodArguments(op);
@@ -1682,42 +1698,44 @@
         return attributes(asRegister(operand)).isCallerSave();
     }
 
+    private InstructionValueProcedure debugInfoProc = new InstructionValueProcedure() {
+
+        @Override
+        public Value doValue(LIRInstruction op, Value operand) {
+            int tempOpId = op.id();
+            OperandMode mode = OperandMode.USE;
+            AbstractBlock<?> block = blockForId(tempOpId);
+            if (block.getSuccessorCount() == 1 && tempOpId == getLastLirInstructionId(block)) {
+                // generating debug information for the last instruction of a block.
+                // if this instruction is a branch, spill moves are inserted before this branch
+                // and so the wrong operand would be returned (spill moves at block boundaries
+                // are not
+                // considered in the live ranges of intervals)
+                // Solution: use the first opId of the branch target block instead.
+                final LIRInstruction instr = ir.getLIRforBlock(block).get(ir.getLIRforBlock(block).size() - 1);
+                if (instr instanceof StandardOp.JumpOp) {
+                    if (blockData.get(block).liveOut.get(operandNumber(operand))) {
+                        tempOpId = getFirstLirInstructionId(block.getSuccessors().iterator().next());
+                        mode = OperandMode.DEF;
+                    }
+                }
+            }
+
+            // Get current location of operand
+            // The operand must be live because debug information is considered when building
+            // the intervals
+            // if the interval is not live, colorLirOperand will cause an assert on failure
+            Value result = colorLirOperand((Variable) operand, tempOpId, mode);
+            assert !hasCall(tempOpId) || isStackSlot(result) || isConstant(result) || !isCallerSave(result) : "cannot have caller-save register operands at calls";
+            return result;
+        }
+    };
+
     private void computeDebugInfo(IntervalWalker iw, final LIRInstruction op, LIRFrameState info) {
         info.initDebugInfo(frameMap, !op.destroysCallerSavedRegisters() || !callKillsRegisters);
         markFrameLocations(iw, op, info);
 
-        info.forEachState(new ValueProcedure() {
-
-            @Override
-            public Value doValue(Value operand) {
-                int tempOpId = op.id();
-                OperandMode mode = OperandMode.USE;
-                AbstractBlock<?> block = blockForId(tempOpId);
-                if (block.getSuccessorCount() == 1 && tempOpId == getLastLirInstructionId(block)) {
-                    // generating debug information for the last instruction of a block.
-                    // if this instruction is a branch, spill moves are inserted before this branch
-                    // and so the wrong operand would be returned (spill moves at block boundaries
-                    // are not
-                    // considered in the live ranges of intervals)
-                    // Solution: use the first opId of the branch target block instead.
-                    final LIRInstruction instr = ir.getLIRforBlock(block).get(ir.getLIRforBlock(block).size() - 1);
-                    if (instr instanceof StandardOp.JumpOp) {
-                        if (blockData.get(block).liveOut.get(operandNumber(operand))) {
-                            tempOpId = getFirstLirInstructionId(block.getSuccessors().iterator().next());
-                            mode = OperandMode.DEF;
-                        }
-                    }
-                }
-
-                // Get current location of operand
-                // The operand must be live because debug information is considered when building
-                // the intervals
-                // if the interval is not live, colorLirOperand will cause an assert on failure
-                Value result = colorLirOperand((Variable) operand, tempOpId, mode);
-                assert !hasCall(tempOpId) || isStackSlot(result) || isConstant(result) || !isCallerSave(result) : "cannot have caller-save register operands at calls";
-                return result;
-            }
-        });
+        info.forEachState(op, debugInfoProc);
         info.finish(op, frameMap);
     }
 
@@ -1725,6 +1743,17 @@
         int numInst = instructions.size();
         boolean hasDead = false;
 
+        InstructionValueProcedure assignProc = new InstructionValueProcedure() {
+
+            @Override
+            public Value doValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
+                if (isVariable(operand)) {
+                    return colorLirOperand((Variable) operand, op.id(), mode);
+                }
+                return operand;
+            }
+        };
+
         for (int j = 0; j < numInst; j++) {
             final LIRInstruction op = instructions.get(j);
             if (op == null) { // this can happen when spill-moves are removed in eliminateSpillMoves
@@ -1749,17 +1778,6 @@
                 }
             }
 
-            ValueProcedure assignProc = new ValueProcedure() {
-
-                @Override
-                public Value doValue(Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
-                    if (isVariable(operand)) {
-                        return colorLirOperand((Variable) operand, op.id(), mode);
-                    }
-                    return operand;
-                }
-            };
-
             op.forEachInput(assignProc);
             op.forEachAlive(assignProc);
             op.forEachTemp(assignProc);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java	Wed Jun 04 14:52:17 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/RegisterVerifier.java	Wed Jun 18 14:21:10 2014 +0200
@@ -32,9 +32,9 @@
 import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
-import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
 import com.oracle.graal.phases.util.*;
 
 /**
@@ -187,6 +187,38 @@
     }
 
     void processOperations(List<LIRInstruction> ops, final Interval[] inputState) {
+        InstructionValueProcedure useProc = new InstructionValueProcedure() {
+
+            @Override
+            public Value doValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
+                if (LinearScan.isVariableOrRegister(operand) && allocator.isProcessed(operand)) {
+                    Interval interval = intervalAt(operand);
+                    if (op.id() != -1) {
+                        interval = interval.getSplitChildAtOpId(op.id(), mode, allocator);
+                    }
+
+                    assert checkState(inputState, interval.location(), interval.splitParent());
+                }
+                return operand;
+            }
+        };
+
+        InstructionValueProcedure defProc = new InstructionValueProcedure() {
+
+            @Override
+            public Value doValue(LIRInstruction op, Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
+                if (LinearScan.isVariableOrRegister(operand) && allocator.isProcessed(operand)) {
+                    Interval interval = intervalAt(operand);
+                    if (op.id() != -1) {
+                        interval = interval.getSplitChildAtOpId(op.id(), mode, allocator);
+                    }
+
+                    statePut(inputState, interval.location(), interval.splitParent());
+                }
+                return operand;
+            }
+        };
+
         // visit all instructions of the block
         for (int i = 0; i < ops.size(); i++) {
             final LIRInstruction op = ops.get(i);
@@ -195,38 +227,6 @@
                 Debug.log("%s", op.toStringWithIdPrefix());
             }
 
-            ValueProcedure useProc = new ValueProcedure() {
-
-                @Override
-                public Value doValue(Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
-                    if (LinearScan.isVariableOrRegister(operand) && allocator.isProcessed(operand)) {
-                        Interval interval = intervalAt(operand);
-                        if (op.id() != -1) {
-                            interval = interval.getSplitChildAtOpId(op.id(), mode, allocator);
-                        }
-
-                        assert checkState(inputState, interval.location(), interval.splitParent());
-                    }
-                    return operand;
-                }
-            };
-
-            ValueProcedure defProc = new ValueProcedure() {
-
-                @Override
-                public Value doValue(Value operand, OperandMode mode, EnumSet<OperandFlag> flags) {
-                    if (LinearScan.isVariableOrRegister(operand) && allocator.isProcessed(operand)) {
-                        Interval interval = intervalAt(operand);
-                        if (op.id() != -1) {
-                            interval = interval.getSplitChildAtOpId(op.id(), mode, allocator);
-                        }
-
-                        statePut(inputState, interval.location(), interval.splitParent());
-                    }
-                    return operand;
-                }
-            };
-
             // check if input operands are correct
             op.forEachInput(useProc);
             // invalidate all caller save registers at calls
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRFrameState.java	Wed Jun 04 14:52:17 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRFrameState.java	Wed Jun 18 14:21:10 2014 +0200
@@ -26,6 +26,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
 import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
 
@@ -50,4 +51,17 @@
             return super.processValue(proc, value);
         }
     }
+
+    @Override
+    protected Value processValue(LIRInstruction inst, InstructionValueProcedure proc, Value value) {
+        if (value instanceof HotSpotMonitorValue) {
+            HotSpotMonitorValue monitor = (HotSpotMonitorValue) value;
+            if (processed(monitor.getOwner())) {
+                monitor.setOwner(proc.doValue(inst, monitor.getOwner(), OperandMode.ALIVE, STATE_FLAGS));
+            }
+            return value;
+        } else {
+            return super.processValue(inst, proc, value);
+        }
+    }
 }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValue.java	Wed Jun 04 14:52:17 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValue.java	Wed Jun 18 14:21:10 2014 +0200
@@ -26,6 +26,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.debug.*;
+import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
 import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
@@ -58,6 +59,10 @@
         valueClass.forEachComponent(this, mode, proc);
     }
 
+    public final void forEachComponent(LIRInstruction inst, OperandMode mode, InstructionValueProcedure proc) {
+        valueClass.forEachComponent(inst, this, mode, proc);
+    }
+
     @Override
     public String toString() {
         return valueClass.toString(this);
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java	Wed Jun 04 14:52:17 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java	Wed Jun 18 14:21:10 2014 +0200
@@ -27,6 +27,7 @@
 
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.lir.CompositeValue.Component;
+import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
 import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
@@ -143,6 +144,10 @@
         forEach(obj, directComponentCount, componentOffsets, mode, componentFlags, proc);
     }
 
+    public final void forEachComponent(LIRInstruction inst, CompositeValue obj, OperandMode mode, InstructionValueProcedure proc) {
+        forEach(inst, obj, directComponentCount, componentOffsets, mode, componentFlags, proc);
+    }
+
     public String toString(CompositeValue obj) {
         StringBuilder result = new StringBuilder();
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java	Wed Jun 04 14:52:17 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java	Wed Jun 18 14:21:10 2014 +0200
@@ -28,6 +28,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
 import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
@@ -60,7 +61,7 @@
 
     /**
      * Iterates the frame state and calls the {@link ValueProcedure} for every variable.
-     * 
+     *
      * @param proc The procedure called for variables.
      */
     public void forEachState(ValueProcedure proc) {
@@ -75,6 +76,22 @@
     }
 
     /**
+     * Iterates the frame state and calls the {@link InstructionValueProcedure} for every variable.
+     *
+     * @param proc The procedure called for variables.
+     */
+    public void forEachState(LIRInstruction inst, InstructionValueProcedure proc) {
+        for (BytecodeFrame cur = topFrame; cur != null; cur = cur.caller()) {
+            processValues(inst, cur.values, proc);
+        }
+        if (virtualObjects != null) {
+            for (VirtualObject obj : virtualObjects) {
+                processValues(inst, obj.getValues(), proc);
+            }
+        }
+    }
+
+    /**
      * We filter out constant and illegal values ourself before calling the procedure, so
      * {@link OperandFlag#CONST} and {@link OperandFlag#ILLEGAL} need not be set.
      */
@@ -94,6 +111,20 @@
         return value;
     }
 
+    protected void processValues(LIRInstruction inst, Value[] values, InstructionValueProcedure proc) {
+        for (int i = 0; i < values.length; i++) {
+            Value value = values[i];
+            values[i] = processValue(inst, proc, value);
+        }
+    }
+
+    protected Value processValue(LIRInstruction inst, InstructionValueProcedure proc, Value value) {
+        if (processed(value)) {
+            return proc.doValue(inst, value, OperandMode.ALIVE, STATE_FLAGS);
+        }
+        return value;
+    }
+
     protected boolean processed(Value value) {
         if (isIllegal(value)) {
             // Ignore dead local variables.
@@ -111,7 +142,7 @@
 
     /**
      * Called by the register allocator before {@link #markLocation} to initialize the frame state.
-     * 
+     *
      * @param frameMap The frame map.
      * @param canHaveRegisters True if there can be any register map entries.
      */
@@ -123,7 +154,7 @@
      * Called by the register allocator to mark the specified location as a reference in the
      * reference map of the debug information. The tracked location can be a {@link RegisterValue}
      * or a {@link StackSlot}. Note that a {@link Constant} is automatically tracked.
-     * 
+     *
      * @param location The location to be added to the reference map.
      * @param frameMap The frame map.
      */
@@ -133,7 +164,7 @@
 
     /**
      * Called by the register allocator after all locations are marked.
-     * 
+     *
      * @param op The instruction to which this frame state belongs.
      * @param frameMap The frame map.
      */
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Wed Jun 04 14:52:17 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Wed Jun 18 14:21:10 2014 +0200
@@ -51,7 +51,7 @@
         /**
          * 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.
          */
@@ -62,7 +62,7 @@
         /**
          * 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.
@@ -73,6 +73,38 @@
         }
     }
 
+    /**
+     * Similar to {@link ValueProcedure} but with an {@link LIRInstruction} parameter.
+     */
+    public abstract static class InstructionValueProcedure {
+
+        /**
+         * Iterator method to be overwritten. This version of the iterator does not take additional
+         * parameters to keep the signature short.
+         *
+         * @param instruction The current instruction.
+         * @param value The value that is iterated.
+         * @return The new value to replace the value that was passed in.
+         */
+        protected Value doValue(LIRInstruction instruction, Value value) {
+            throw GraalInternalError.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 instruction The current instruction.
+         * @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 Value doValue(LIRInstruction instruction, Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
+            return doValue(instruction, value);
+        }
+    }
+
     public abstract static class StateProcedure {
 
         protected abstract void doState(LIRFrameState state);
@@ -275,6 +307,26 @@
         instructionClass.forEachState(this, proc);
     }
 
+    public final void forEachInput(InstructionValueProcedure proc) {
+        instructionClass.forEachUse(this, proc);
+    }
+
+    public final void forEachAlive(InstructionValueProcedure proc) {
+        instructionClass.forEachAlive(this, proc);
+    }
+
+    public final void forEachTemp(InstructionValueProcedure proc) {
+        instructionClass.forEachTemp(this, proc);
+    }
+
+    public final void forEachOutput(InstructionValueProcedure proc) {
+        instructionClass.forEachDef(this, proc);
+    }
+
+    public final void forEachState(InstructionValueProcedure proc) {
+        instructionClass.forEachState(this, proc);
+    }
+
     public final void forEachState(StateProcedure proc) {
         instructionClass.forEachState(this, proc);
     }
@@ -286,7 +338,7 @@
      * 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
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java	Wed Jun 04 14:52:17 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java	Wed Jun 18 14:21:10 2014 +0200
@@ -28,6 +28,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
 import com.oracle.graal.lir.LIRInstruction.StateProcedure;
@@ -278,6 +279,22 @@
         forEach(obj, directDefCount, defOffsets, OperandMode.DEF, defFlags, proc);
     }
 
+    public final void forEachUse(LIRInstruction obj, InstructionValueProcedure proc) {
+        forEach(obj, obj, directUseCount, useOffsets, OperandMode.USE, useFlags, proc);
+    }
+
+    public final void forEachAlive(LIRInstruction obj, InstructionValueProcedure proc) {
+        forEach(obj, obj, directAliveCount, aliveOffsets, OperandMode.ALIVE, aliveFlags, proc);
+    }
+
+    public final void forEachTemp(LIRInstruction obj, InstructionValueProcedure proc) {
+        forEach(obj, obj, directTempCount, tempOffsets, OperandMode.TEMP, tempFlags, proc);
+    }
+
+    public final void forEachDef(LIRInstruction obj, InstructionValueProcedure proc) {
+        forEach(obj, obj, directDefCount, defOffsets, OperandMode.DEF, defFlags, proc);
+    }
+
     public final void forEachState(LIRInstruction obj, ValueProcedure proc) {
         for (int i = 0; i < stateOffsets.length; i++) {
             LIRFrameState state = getState(obj, stateOffsets[i]);
@@ -287,6 +304,15 @@
         }
     }
 
+    public final void forEachState(LIRInstruction obj, InstructionValueProcedure proc) {
+        for (int i = 0; i < stateOffsets.length; i++) {
+            LIRFrameState state = getState(obj, stateOffsets[i]);
+            if (state != null) {
+                state.forEachState(obj, proc);
+            }
+        }
+    }
+
     public final void forEachState(LIRInstruction obj, StateProcedure proc) {
         for (int i = 0; i < stateOffsets.length; i++) {
             LIRFrameState state = getState(obj, stateOffsets[i]);
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java	Wed Jun 04 14:52:17 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java	Wed Jun 18 14:21:10 2014 +0200
@@ -32,6 +32,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
 import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
@@ -146,6 +147,33 @@
         }
     }
 
+    protected static void forEach(LIRInstruction inst, Object obj, int directCount, long[] offsets, OperandMode mode, EnumSet<OperandFlag>[] flags, InstructionValueProcedure proc) {
+        for (int i = 0; i < offsets.length; i++) {
+            assert LIRInstruction.ALLOWED_FLAGS.get(mode).containsAll(flags[i]);
+
+            if (i < directCount) {
+                Value value = getValue(obj, offsets[i]);
+                if (value instanceof CompositeValue) {
+                    CompositeValue composite = (CompositeValue) value;
+                    composite.forEachComponent(inst, mode, proc);
+                } else {
+                    setValue(obj, offsets[i], proc.doValue(inst, value, mode, flags[i]));
+                }
+            } else {
+                Value[] values = getValueArray(obj, offsets[i]);
+                for (int j = 0; j < values.length; j++) {
+                    Value value = values[j];
+                    if (value instanceof CompositeValue) {
+                        CompositeValue composite = (CompositeValue) value;
+                        composite.forEachComponent(inst, mode, proc);
+                    } else {
+                        values[j] = proc.doValue(inst, value, mode, flags[i]);
+                    }
+                }
+            }
+        }
+    }
+
     protected static Value getValue(Object obj, long offset) {
         return (Value) unsafe.getObject(obj, offset);
     }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java	Wed Jun 04 14:52:17 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java	Wed Jun 18 14:21:10 2014 +0200
@@ -32,6 +32,7 @@
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.cfg.*;
 import com.oracle.graal.debug.*;
+import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
 import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
@@ -62,14 +63,15 @@
         return isRegister(value) && frameMap.registerConfig.getAttributesMap()[asRegister(value).number].isAllocatable();
     }
 
-    public static boolean verify(final LIRInstruction op) {
-        ValueProcedure allowedProc = new ValueProcedure() {
+    private static InstructionValueProcedure allowedProc = new InstructionValueProcedure() {
 
-            @Override
-            public Value doValue(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
-                return allowed(op, value, mode, flags);
-            }
-        };
+        @Override
+        public Value doValue(LIRInstruction op, Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
+            return allowed(op, value, mode, flags);
+        }
+    };
+
+    public static boolean verify(final LIRInstruction op) {
 
         op.forEachInput(allowedProc);
         op.forEachAlive(allowedProc);