changeset 5733:141b15521a39

use annotated fields for operands of LIR instructions
author Christian Wimmer <christian.wimmer@oracle.com>
date Fri, 29 Jun 2012 18:33:48 -0700
parents e1d5c642d022
children dba56a3344ba
files graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/simple/AssignRegisters.java graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/simple/LinearScanAllocator.java graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/simple/SpillAllAllocator.java graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/util/IntervalPrinter.java graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/util/RegisterVerifier.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/ControlFlowOptimizer.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/EdgeMoveOptimizer.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.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/LinearScanWalker.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64DeoptimizationStub.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64XirOp.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/counters/MethodEntryCounters.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64NewInstanceStubCallOp.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64VerifyOopStubCallOp.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64SafepointOp.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64TailcallOp.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64LIRInstruction.java graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRDebugInfo.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/LIRVerifier.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRXirInstruction.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/MathIntrinsicNode.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/target/amd64/AMD64MathIntrinsicOp.java
diffstat 42 files changed, 1389 insertions(+), 1279 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/simple/AssignRegisters.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/simple/AssignRegisters.java	Fri Jun 29 18:33:48 2012 -0700
@@ -49,6 +49,7 @@
         ValueProcedure useProc =          new ValueProcedure() { @Override public Value doValue(Value value) { return use(value); } };
         ValueProcedure defProc =          new ValueProcedure() { @Override public Value doValue(Value value) { return def(value); } };
         ValueProcedure setReferenceProc = new ValueProcedure() { @Override public Value doValue(Value value) { return setReference(value); } };
+        StateProcedure finishProc =       new StateProcedure() { @Override public void doState(LIRFrameState state) { state.finish((BitSet) (curRegisterRefMap.clone()), (BitSet) (curFrameRefMap.clone()), frameMap); } };
 
         Debug.log("==== start assign registers ====");
         for (int i = lir.linearScanOrder().size() - 1; i >= 0; i--) {
@@ -70,17 +71,8 @@
                 op.forEachState(useProc);
                 op.forEachAlive(useProc);
 
-                if (op.info != null) {
-                    Debug.log("    registerRefMap: %s  frameRefMap: %s", curRegisterRefMap, curFrameRefMap);
-                    op.info.finish((BitSet) (curRegisterRefMap.clone()), (BitSet) (curFrameRefMap.clone()), frameMap);
-
-                    if (op instanceof LIRXirInstruction) {
-                        LIRXirInstruction xir = (LIRXirInstruction) op;
-                        if (xir.infoAfter != null) {
-                            xir.infoAfter.finish((BitSet) (curRegisterRefMap.clone()), (BitSet) (curFrameRefMap.clone()), frameMap);
-                        }
-                    }
-                }
+                // Build the reference map for the GC.
+                op.forEachState(finishProc);
 
                 // Process input operands after assigning the reference map, so that input operands that are used
                 // for the last time at this instruction are not part of the reference map.
--- a/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/simple/LinearScanAllocator.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/simple/LinearScanAllocator.java	Fri Jun 29 18:33:48 2012 -0700
@@ -341,20 +341,20 @@
     }
 
     private Value use(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
-        assert mode == OperandMode.Input || mode == OperandMode.Alive;
+        assert mode == OperandMode.USE || mode == OperandMode.ALIVE;
         if (isVariable(value)) {
             // State values are not recorded beforehand because it does not matter if they are spilled. Still, it is necessary to record them as used now.
             recordUse(value);
 
             Location curLoc = curLocations.get(asVariable(value));
-            if (isStackSlot(curLoc.location) && flags.contains(OperandFlag.Stack)) {
+            if (isStackSlot(curLoc.location) && flags.contains(OperandFlag.STACK)) {
                 Debug.log("    use %s %s: use current stack slot %s", mode, value, curLoc.location);
                 return curLoc;
             }
             if (isRegister(curLoc.location)) {
                 int regNum = asRegister(curLoc.location).number;
                 assert curInRegisterState[regNum] == curLoc;
-                if (mode == OperandMode.Input || curOutRegisterState[regNum] == curLoc) {
+                if (mode == OperandMode.USE || curOutRegisterState[regNum] == curLoc) {
                     Debug.log("    use %s %s: use current register %s", mode, value, curLoc.location);
                     return curLoc;
                 }
@@ -373,10 +373,10 @@
         return value;
     }
 
-    private static final EnumSet<OperandFlag> SPILL_FLAGS = EnumSet.of(OperandFlag.Register, OperandFlag.Stack);
+    private static final EnumSet<OperandFlag> SPILL_FLAGS = EnumSet.of(OperandFlag.REG, OperandFlag.STACK);
 
     private Value def(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
-        assert mode == OperandMode.Temp || mode == OperandMode.Output;
+        assert mode == OperandMode.TEMP || mode == OperandMode.DEF;
         if (isVariable(value)) {
             Debug.log("    def %s %s", mode, value);
             assert curLocations.get(asVariable(value)) == null;
@@ -396,7 +396,7 @@
             if (in != null && in != out && isLocation(in) && curLocations.get(asLocation(in).variable) == in) {
                 Debug.log("    %s was evicted by %s, need to allocate new location", in, out);
                 Location oldLoc = asLocation(in);
-                Location newLoc = allocateRegister(oldLoc.variable, OperandMode.Alive, SPILL_FLAGS);
+                Location newLoc = allocateRegister(oldLoc.variable, OperandMode.ALIVE, SPILL_FLAGS);
                 assert oldLoc != newLoc;
                 moveResolver.add(oldLoc, newLoc);
             }
@@ -417,7 +417,7 @@
                 Value phiInput = phiInputs[i];
 
                 if (isVariable(phiDefinition)) {
-                    Location hintResult = processRegisterHint(asVariable(phiDefinition), OperandMode.Output, phiInput);
+                    Location hintResult = processRegisterHint(asVariable(phiDefinition), OperandMode.DEF, phiInput);
                     if (hintResult != null) {
                         phiDefinitions[i] = hintResult;
                     }
@@ -444,7 +444,7 @@
     }
 
     private Location allocateRegister(final Variable variable, final OperandMode mode, EnumSet<OperandFlag> flags) {
-        if (flags.contains(OperandFlag.RegisterHint)) {
+        if (flags.contains(OperandFlag.HINT)) {
             Value hintResult = curOp.forEachRegisterHint(variable, mode, new ValueProcedure() {
                 @Override
                 public Value doValue(Value registerHint) {
@@ -476,7 +476,7 @@
             }
         }
 
-        if (flags.contains(OperandFlag.Stack) && betterSpillCandidate(curLocations.get(variable), bestSpillCandidate)) {
+        if (flags.contains(OperandFlag.STACK) && betterSpillCandidate(curLocations.get(variable), bestSpillCandidate)) {
             return selectSpillSlot(variable);
         }
 
@@ -509,11 +509,11 @@
 
     private boolean isFree(Register reg, OperandMode mode) {
         switch (mode) {
-            case Input:  return curInRegisterState[reg.number] == null;
-            case Alive:  return curInRegisterState[reg.number] == null && curOutRegisterState[reg.number] == null;
-            case Temp:   return curOutRegisterState[reg.number] == null;
-            case Output: return curOutRegisterState[reg.number] == null;
-            default:     throw GraalInternalError.shouldNotReachHere();
+            case USE: return curInRegisterState[reg.number] == null;
+            case ALIVE: return curInRegisterState[reg.number] == null && curOutRegisterState[reg.number] == null;
+            case TEMP: return curOutRegisterState[reg.number] == null;
+            case DEF: return curOutRegisterState[reg.number] == null;
+            default: throw GraalInternalError.shouldNotReachHere();
         }
     }
 
@@ -552,7 +552,7 @@
         assert isFree(reg, mode);
 
         Location loc = new Location(variable, reg.asValue(variable.kind));
-        if (mode == OperandMode.Input || mode == OperandMode.Alive) {
+        if (mode == OperandMode.USE || mode == OperandMode.ALIVE) {
             curInRegisterState[reg.number] = loc;
         }
         curOutRegisterState[reg.number] = loc;
--- a/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/simple/SpillAllAllocator.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/simple/SpillAllAllocator.java	Fri Jun 29 18:33:48 2012 -0700
@@ -290,8 +290,8 @@
     }
 
     private Value load(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
-        assert mode == OperandMode.Input || mode == OperandMode.Alive;
-        if (flags.contains(OperandFlag.Stack)) {
+        assert mode == OperandMode.USE || mode == OperandMode.ALIVE;
+        if (flags.contains(OperandFlag.STACK)) {
             return useSlot(value);
         }
         if (isVariable(value)) {
@@ -301,7 +301,7 @@
                 // This variable has already been processed before.
                 Debug.log("      found location %s", regLoc);
             } else {
-                regLoc = allocateRegister(asVariable(value), curInRegisterState, mode == OperandMode.Alive ? curOutRegisterState : null, mode, flags);
+                regLoc = allocateRegister(asVariable(value), curInRegisterState, mode == OperandMode.ALIVE ? curOutRegisterState : null, mode, flags);
                 Location stackLoc = curStackLocations.get(asVariable(value));
                 assert stackLoc != null;
                 moveResolver.add(stackLoc, regLoc);
@@ -314,15 +314,15 @@
     }
 
     private Value spill(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
-        assert mode == OperandMode.Temp || mode == OperandMode.Output;
-        if (flags.contains(OperandFlag.Stack)) {
+        assert mode == OperandMode.TEMP || mode == OperandMode.DEF;
+        if (flags.contains(OperandFlag.STACK)) {
             return defSlot(value);
         }
         if (isVariable(value)) {
             Debug.log("    spill %s", value);
             assert curStackLocations.get(asVariable(value)) == null;
             Location regLoc = allocateRegister(asVariable(value), null, curOutRegisterState, mode, flags);
-            if (mode == OperandMode.Output) {
+            if (mode == OperandMode.DEF) {
                 Location stackLoc = new Location(asVariable(value), frameMap.allocateSpillSlot(value.kind));
                 curStackLocations.put(stackLoc);
                 moveResolver.add(regLoc, stackLoc);
@@ -360,7 +360,7 @@
     }
 
     private Location allocateRegister(final Variable variable, final Object[] inRegisterState, final Object[] outRegisterState, OperandMode mode, EnumSet<OperandFlag> flags) {
-        if (flags.contains(OperandFlag.RegisterHint)) {
+        if (flags.contains(OperandFlag.HINT)) {
             Value result = curInstruction.forEachRegisterHint(variable, mode, new ValueProcedure() {
                 @Override
                 public Value doValue(Value registerHint) {
--- a/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/util/IntervalPrinter.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/util/IntervalPrinter.java	Fri Jun 29 18:33:48 2012 -0700
@@ -167,7 +167,7 @@
                 if (op.hasCall()) {
                     intervals.get("call").ranges.add(new Range(curOpId, curOpId + 1));
                 }
-                if (op.info != null) {
+                if (op.hasState()) {
                     intervals.get("st").ranges.add(new Range(curOpId, curOpId + 1));
                 }
             }
@@ -228,7 +228,7 @@
     private String useKind(EnumSet<OperandFlag> flags) {
         if (curUseKind != null) {
             return curUseKind;
-        } else if (flags.contains(OperandFlag.Stack)) {
+        } else if (flags.contains(OperandFlag.STACK)) {
             return "S";
         } else {
             return "M";
@@ -242,7 +242,7 @@
                 interval.uses.add(new UsePosition(curOpId, useKind(flags)));
             }
             if (interval.lastTo == 0) {
-                interval.lastTo = curOpId + (mode == OperandMode.Alive ? 1 : 0);
+                interval.lastTo = curOpId + (mode == OperandMode.ALIVE ? 1 : 0);
             }
         }
         return value;
--- a/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/util/RegisterVerifier.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/util/RegisterVerifier.java	Fri Jun 29 18:33:48 2012 -0700
@@ -189,7 +189,7 @@
     private Value use(Value value, EnumSet<OperandFlag> flags) {
         if (!isConstant(value) && value != Value.IllegalValue && !isIgnoredRegister(value)) {
             Value actual = curInputState.get(key(value));
-            if (actual == null && flags.contains(OperandFlag.Uninitialized)) {
+            if (actual == null && flags.contains(OperandFlag.UNINITIALIZED)) {
                 // OK, since uninitialized values are allowed explicitly.
             } else if (value != actual) {
                 Debug.log("Error in register allocation: %s != %s for key %s", value, actual, key(value));
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/ControlFlowOptimizer.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/ControlFlowOptimizer.java	Fri Jun 29 18:33:48 2012 -0700
@@ -106,7 +106,7 @@
 
         // block must have exactly one successor
 
-        return instructions.size() == 2 && instructions.get(instructions.size() - 1).info == null;
+        return instructions.size() == 2 && !instructions.get(instructions.size() - 1).hasState();
     }
 
     private void deleteEmptyBlocks(List<Block> code) {
@@ -159,7 +159,7 @@
             if (lastOp instanceof StandardOp.JumpOp) {
                 StandardOp.JumpOp lastJump = (StandardOp.JumpOp) lastOp;
 
-                if (lastOp.info == null) {
+                if (!lastOp.hasState()) {
                     if (lastJump.destination().label() == ((StandardOp.LabelOp) code.get(i + 1).lir.get(0)).getLabel()) {
                         // delete last branch instruction
                         Util.truncate(instructions, instructions.size() - 1);
@@ -169,7 +169,7 @@
                         if (prevOp instanceof StandardOp.BranchOp) {
                             StandardOp.BranchOp prevBranch = (StandardOp.BranchOp) prevOp;
 
-                            if (prevBranch.destination().label() == ((StandardOp.LabelOp) code.get(i + 1).lir.get(0)).getLabel() && prevOp.info == null) {
+                            if (prevBranch.destination().label() == ((StandardOp.LabelOp) code.get(i + 1).lir.get(0)).getLabel() && !prevOp.hasState()) {
                                 // eliminate a conditional branch to the immediate successor
                                 prevBranch.negate(lastJump.destination());
                                 Util.truncate(instructions, instructions.size() - 1);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/EdgeMoveOptimizer.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/EdgeMoveOptimizer.java	Fri Jun 29 18:33:48 2012 -0700
@@ -79,8 +79,7 @@
 
     /**
      * Determines if two operations are both {@linkplain MoveOp moves}
-     * that have the same {@linkplain MoveOp#getInput() source} and {@linkplain MoveOp#getResult() destination}
-     * operands and they have the same {@linkplain LIRInstruction#info debug info}.
+     * that have the same {@linkplain MoveOp#getInput() source} and {@linkplain MoveOp#getResult() destination} operands.
      *
      * @param op1 the first instruction to compare
      * @param op2 the second instruction to compare
@@ -138,7 +137,7 @@
             assert pred.suxAt(0) == block : "invalid control flow";
             assert predInstructions.get(predInstructions.size() - 1) instanceof StandardOp.JumpOp : "block must end with unconditional jump";
 
-            if (predInstructions.get(predInstructions.size() - 1).info != null) {
+            if (predInstructions.get(predInstructions.size() - 1).hasState()) {
                 // can not optimize instructions that have debug info
                 return;
             }
@@ -195,13 +194,13 @@
 
         assert instructions.get(instructions.size() - 1) instanceof StandardOp.JumpOp : "block must end with unconditional jump";
 
-        if (instructions.get(instructions.size() - 1).info != null) {
+        if (instructions.get(instructions.size() - 1).hasState()) {
             // cannot optimize instructions when debug info is needed
             return;
         }
 
         LIRInstruction branch = instructions.get(instructions.size() - 2);
-        if (!(branch instanceof StandardOp.BranchOp) || branch.info != null) {
+        if (!(branch instanceof StandardOp.BranchOp) || branch.hasState()) {
             // not a valid case for optimization
             // currently, only blocks that end with two branches (conditional branch followed
             // by unconditional branch) are optimized
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java	Fri Jun 29 18:33:48 2012 -0700
@@ -759,7 +759,7 @@
             int len = splitChildren.size();
 
             // in outputMode, the end of the interval (opId == cur.to()) is not valid
-            int toOffset = (mode == LIRInstruction.OperandMode.Output ? 0 : 1);
+            int toOffset = (mode == LIRInstruction.OperandMode.DEF ? 0 : 1);
 
             int i;
             for (i = 0; i < len; i++) {
@@ -905,7 +905,7 @@
     }
 
     void addUsePos(int pos, RegisterPriority registerPriority) {
-        assert covers(pos, LIRInstruction.OperandMode.Input) : "use position not covered by live range";
+        assert covers(pos, LIRInstruction.OperandMode.USE) : "use position not covered by live range";
 
         // do not add use positions for precolored intervals because they are never used
         if (registerPriority != RegisterPriority.None && isVariable(operand)) {
@@ -1063,7 +1063,7 @@
         if (cur != Range.EndMarker) {
             assert cur.to != cur.next.from : "ranges not separated";
 
-            if (mode == LIRInstruction.OperandMode.Output) {
+            if (mode == LIRInstruction.OperandMode.DEF) {
                 return cur.from <= opId && opId < cur.to;
             } else {
                 return cur.from <= opId && opId <= cur.to;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java	Fri Jun 29 18:33:48 2012 -0700
@@ -22,11 +22,12 @@
  */
 package com.oracle.graal.compiler.alloc;
 
-import static com.oracle.graal.alloc.util.LocationUtil.*;
 import static com.oracle.graal.api.code.CodeUtil.*;
+import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRValueUtil.*;
+
 import java.util.*;
 
-import com.oracle.max.criutils.*;
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.*;
@@ -38,9 +39,13 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.LIRInstruction.*;
-import com.oracle.graal.lir.StandardOp.*;
+import com.oracle.graal.lir.LIRInstruction.OperandFlag;
+import com.oracle.graal.lir.LIRInstruction.OperandMode;
+import com.oracle.graal.lir.LIRInstruction.StateProcedure;
+import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
+import com.oracle.graal.lir.StandardOp.MoveOp;
 import com.oracle.graal.lir.cfg.*;
+import com.oracle.max.criutils.*;
 
 /**
  * An implementation of the linear scan register allocator algorithm described
@@ -867,16 +872,13 @@
                         TTY.println("  used in block B%d", block.getId());
                         for (LIRInstruction ins : block.lir) {
                             TTY.println(ins.id() + ": " + ins.toString());
-                            LIRDebugInfo info = ins.info;
-                            if (info != null) {
-                                info.forEachState(new ValueProcedure() {
-                                    @Override
-                                    public Value doValue(Value liveStateOperand) {
-                                        TTY.println("   operand=" + liveStateOperand);
-                                        return liveStateOperand;
-                                    }
-                                });
-                            }
+                            ins.forEachState(new ValueProcedure() {
+                                @Override
+                                public Value doValue(Value liveStateOperand) {
+                                    TTY.println("   operand=" + liveStateOperand);
+                                    return liveStateOperand;
+                                }
+                            });
                         }
                     }
                     if (blockData.get(block).liveKill.get(operandNum)) {
@@ -1032,7 +1034,7 @@
      * Determines the priority which with an instruction's input operand will be allocated a register.
      */
     static RegisterPriority registerPriorityOfInputOperand(EnumSet<OperandFlag> flags) {
-        if (flags.contains(OperandFlag.Stack)) {
+        if (flags.contains(OperandFlag.STACK)) {
             return RegisterPriority.ShouldHaveRegister;
         }
         // all other operands require a register
@@ -1068,7 +1070,7 @@
     }
 
     void addRegisterHint(final LIRInstruction op, final Value targetValue, OperandMode mode, EnumSet<OperandFlag> flags) {
-        if (flags.contains(OperandFlag.RegisterHint) && isVariableOrRegister(targetValue)) {
+        if (flags.contains(OperandFlag.HINT) && isVariableOrRegister(targetValue)) {
 
             op.forEachRegisterHint(targetValue, mode, new ValueProcedure() {
                 @Override
@@ -1401,21 +1403,21 @@
         assert isVariable(operand) : "register number out of bounds";
         assert intervalFor(operand) != null : "no interval found";
 
-        return splitChildAtOpId(intervalFor(operand), block.getFirstLirInstructionId(), LIRInstruction.OperandMode.Output);
+        return splitChildAtOpId(intervalFor(operand), block.getFirstLirInstructionId(), LIRInstruction.OperandMode.DEF);
     }
 
     Interval intervalAtBlockEnd(Block block, Value operand) {
         assert isVariable(operand) : "register number out of bounds";
         assert intervalFor(operand) != null : "no interval found";
 
-        return splitChildAtOpId(intervalFor(operand), block.getLastLirInstructionId() + 1, LIRInstruction.OperandMode.Output);
+        return splitChildAtOpId(intervalFor(operand), block.getLastLirInstructionId() + 1, LIRInstruction.OperandMode.DEF);
     }
 
     Interval intervalAtOpId(Value operand, int opId) {
         assert isVariable(operand) : "register number out of bounds";
         assert intervalFor(operand) != null : "no interval found";
 
-        return splitChildAtOpId(intervalFor(operand), opId, LIRInstruction.OperandMode.Input);
+        return splitChildAtOpId(intervalFor(operand), opId, LIRInstruction.OperandMode.USE);
     }
 
     void resolveCollectMappings(Block fromBlock, Block toBlock, MoveResolver moveResolver) {
@@ -1697,20 +1699,7 @@
     }
 
 
-    private void computeDebugInfo(IntervalWalker iw, LIRInstruction op) {
-        assert iw != null : "interval walker needed for debug information";
-        computeDebugInfo(iw, op, op.info);
-
-        if (op instanceof LIRXirInstruction) {
-            LIRXirInstruction xir = (LIRXirInstruction) op;
-            if (xir.infoAfter != null) {
-                computeDebugInfo(iw, op, xir.infoAfter);
-            }
-        }
-    }
-
-
-    private void computeDebugInfo(IntervalWalker iw, final LIRInstruction op, LIRDebugInfo info) {
+    private void computeDebugInfo(IntervalWalker iw, final LIRInstruction op, LIRFrameState info) {
         BitSet registerRefMap = op.hasCall() ? null : frameMap.initRegisterRefMap();
         BitSet frameRefMap = frameMap.initFrameRefMap();
         computeOopMap(iw, op, registerRefMap, frameRefMap);
@@ -1719,7 +1708,7 @@
             @Override
             public Value doValue(Value operand) {
                 int tempOpId = op.id();
-                OperandMode mode = OperandMode.Input;
+                OperandMode mode = OperandMode.USE;
                 Block block = blockForId(tempOpId);
                 if (block.numberOfSux() == 1 && tempOpId == block.getLastLirInstructionId()) {
                     // generating debug information for the last instruction of a block.
@@ -1731,7 +1720,7 @@
                     if (instr instanceof StandardOp.JumpOp) {
                         if (blockData.get(block).liveOut.get(operandNumber(operand))) {
                             tempOpId = block.suxAt(0).getFirstLirInstructionId();
-                            mode = OperandMode.Output;
+                            mode = OperandMode.DEF;
                         }
                     }
                 }
@@ -1748,7 +1737,7 @@
         info.finish(registerRefMap, frameRefMap, frameMap);
     }
 
-    private void assignLocations(List<LIRInstruction> instructions, IntervalWalker iw) {
+    private void assignLocations(List<LIRInstruction> instructions, final IntervalWalker iw) {
         int numInst = instructions.size();
         boolean hasDead = false;
 
@@ -1774,10 +1763,13 @@
             op.forEachTemp(assignProc);
             op.forEachOutput(assignProc);
 
-            if (op.info != null) {
-                // compute reference map and debug information
-                computeDebugInfo(iw, op);
-            }
+            // compute reference map and debug information
+            op.forEachState(new StateProcedure() {
+                @Override
+                protected void doState(LIRFrameState state) {
+                    computeDebugInfo(iw, op, state);
+                }
+            });
 
             // remove useless moves
             if (op instanceof MoveOp) {
@@ -2049,7 +2041,7 @@
             for (int j = 0; j < instructions.size(); j++) {
                 LIRInstruction op = instructions.get(j);
 
-                if (op.info != null) {
+                if (op.hasState()) {
                     iw.walkBefore(op.id());
                     boolean checkLive = true;
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScanWalker.java	Fri Jun 29 18:33:48 2012 -0700
@@ -867,8 +867,8 @@
             return;
         }
 
-        Interval beginHint = registerHint.getSplitChildAtOpId(beginPos, LIRInstruction.OperandMode.Input, allocator);
-        Interval endHint = registerHint.getSplitChildAtOpId(endPos, LIRInstruction.OperandMode.Output, allocator);
+        Interval beginHint = registerHint.getSplitChildAtOpId(beginPos, LIRInstruction.OperandMode.USE, allocator);
+        Interval endHint = registerHint.getSplitChildAtOpId(endPos, LIRInstruction.OperandMode.DEF, allocator);
         if (beginHint == endHint || beginHint.to() != beginPos || endHint.from() != endPos) {
             // registerHint must be split : otherwise the re-writing of use positions does not work
             return;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Fri Jun 29 18:33:48 2012 -0700
@@ -44,7 +44,7 @@
 
     private HashMap<VirtualObjectNode, VirtualObject> virtualObjects = new HashMap<>();
 
-    public LIRDebugInfo build(FrameState topState, LockScope locks, List<StackSlot> pointerSlots, LabelRef exceptionEdge, long leafGraphId) {
+    public LIRFrameState build(FrameState topState, LockScope locks, List<StackSlot> pointerSlots, LabelRef exceptionEdge, long leafGraphId) {
         assert virtualObjects.size() == 0;
         BytecodeFrame frame = computeFrameForState(topState, locks, leafGraphId);
 
@@ -94,7 +94,7 @@
             virtualObjects.clear();
         }
 
-        return new LIRDebugInfo(frame, virtualObjectsArray, pointerSlots, exceptionEdge);
+        return new LIRFrameState(frame, virtualObjectsArray, pointerSlots, exceptionEdge);
     }
 
     private BytecodeFrame computeFrameForState(FrameState state, LockScope locks, long leafGraphId) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Fri Jun 29 18:33:48 2012 -0700
@@ -261,21 +261,21 @@
         return LabelRef.forSuccessor(currentBlock, suxIndex);
     }
 
-    public LIRDebugInfo state() {
+    public LIRFrameState state() {
         assert lastState != null : "must have state before instruction";
         return stateFor(lastState, -1);
     }
 
-    public LIRDebugInfo state(long leafGraphId) {
+    public LIRFrameState state(long leafGraphId) {
         assert lastState != null : "must have state before instruction";
         return stateFor(lastState, leafGraphId);
     }
 
-    public LIRDebugInfo stateFor(FrameState state, long leafGraphId) {
+    public LIRFrameState stateFor(FrameState state, long leafGraphId) {
         return stateFor(state, null, null, leafGraphId);
     }
 
-    public LIRDebugInfo stateFor(FrameState state, List<StackSlot> pointerSlots, LabelRef exceptionEdge, long leafGraphId) {
+    public LIRFrameState stateFor(FrameState state, List<StackSlot> pointerSlots, LabelRef exceptionEdge, long leafGraphId) {
         return debugInfoBuilder.build(state, curLocks, pointerSlots, exceptionEdge, leafGraphId);
     }
 
@@ -552,11 +552,11 @@
         XirArgument obj = toXirArgument(x.object());
         XirArgument lockAddress = lockData == null ? null : toXirArgument(emitLea(lockData));
 
-        LIRDebugInfo stateBefore = state();
+        LIRFrameState stateBefore = state();
         // The state before the monitor enter is used for null checks, so it must not contain the newly locked object.
         curLocks = new LockScope(curLocks, x.stateAfter().inliningIdentifier(), x, lockData);
         // The state after the monitor enter is used for deoptimization, after the monitor has blocked, so it must contain the newly locked object.
-        LIRDebugInfo stateAfter = stateFor(x.stateAfter(), -1);
+        LIRFrameState stateAfter = stateFor(x.stateAfter(), -1);
 
         XirSnippet snippet = xir.genMonitorEnter(site(x, x.object()), obj, lockAddress);
         emitXir(snippet, x, stateBefore, stateAfter, true, null, null);
@@ -576,7 +576,7 @@
         XirArgument obj = toXirArgument(x.object());
         XirArgument lockAddress = lockData == null ? null : toXirArgument(emitLea(lockData));
 
-        LIRDebugInfo stateBefore = state();
+        LIRFrameState stateBefore = state();
         curLocks = curLocks.outer;
 
         XirSnippet snippet = xir.genMonitorExit(site(x, x.object()), obj, lockAddress);
@@ -698,7 +698,7 @@
             // False constants are handled within emitBranch.
         } else {
             // Fall back to a normal branch.
-            LIRDebugInfo info = state(leafGraphId);
+            LIRFrameState info = state(leafGraphId);
             LabelRef stubEntry = createDeoptStub(action, deoptReason, info, comp);
             if (negated) {
                 emitBranch(comp, stubEntry, null, info);
@@ -710,7 +710,7 @@
 
     protected abstract void emitNullCheckGuard(ValueNode object, long leafGraphId);
 
-    public void emitBranch(BooleanNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRDebugInfo info) {
+    public void emitBranch(BooleanNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRFrameState info) {
         if (node instanceof IsNullNode) {
             emitNullCheckBranch((IsNullNode) node, trueSuccessor, falseSuccessor, info);
         } else if (node instanceof CompareNode) {
@@ -726,7 +726,7 @@
         }
     }
 
-    private void emitNullCheckBranch(IsNullNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRDebugInfo info) {
+    private void emitNullCheckBranch(IsNullNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRFrameState info) {
         if (falseSuccessor != null) {
             emitBranch(operand(node.object()), Constant.NULL_OBJECT, Condition.NE, false, falseSuccessor, info);
             if (trueSuccessor != null) {
@@ -737,7 +737,7 @@
         }
     }
 
-    public void emitCompareBranch(CompareNode compare, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock, LIRDebugInfo info) {
+    public void emitCompareBranch(CompareNode compare, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock, LIRFrameState info) {
         if (falseSuccessorBlock != null) {
             emitBranch(operand(compare.x()), operand(compare.y()), compare.condition().negate(), !compare.unorderedIsTrue(), falseSuccessorBlock, info);
             if (trueSuccessorBlock != null) {
@@ -748,20 +748,20 @@
         }
     }
 
-    private void emitInstanceOfBranch(InstanceOfNode x, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRDebugInfo info) {
+    private void emitInstanceOfBranch(InstanceOfNode x, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRFrameState info) {
         XirArgument obj = toXirArgument(x.object());
         XirSnippet snippet = xir.genInstanceOf(site(x, x.object()), obj, toXirArgument(x.targetClassInstruction()), x.targetClass(), x.profile());
         emitXir(snippet, x, info, null, false, trueSuccessor, falseSuccessor);
     }
 
-    public void emitConstantBranch(boolean value, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock, LIRDebugInfo info) {
+    public void emitConstantBranch(boolean value, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock, LIRFrameState info) {
         LabelRef block = value ? trueSuccessorBlock : falseSuccessorBlock;
         if (block != null) {
             emitJump(block, info);
         }
     }
 
-    public void emitTypeBranch(IsTypeNode x, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRDebugInfo info) {
+    public void emitTypeBranch(IsTypeNode x, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRFrameState info) {
         XirArgument thisClass = toXirArgument(x.objectClass());
         XirArgument otherClass = toXirArgument(x.type().getEncoding(Representation.ObjectHub));
         XirSnippet snippet = xir.genTypeBranch(site(x), thisClass, otherClass, x.type());
@@ -814,8 +814,8 @@
 
 
     public abstract void emitLabel(Label label, boolean align);
-    public abstract void emitJump(LabelRef label, LIRDebugInfo info);
-    public abstract void emitBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRDebugInfo info);
+    public abstract void emitJump(LabelRef label, LIRFrameState info);
+    public abstract void emitBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRFrameState info);
     public abstract Variable emitCMove(Value leftVal, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue);
 
     protected FrameState stateBeforeCallWithArguments(FrameState stateAfter, MethodCallTargetNode call, int bci) {
@@ -882,7 +882,7 @@
         if (!target().invokeSnippetAfterArguments) {
             // This is the version currently necessary for Maxine: since the invokeinterface-snippet uses a division, it
             // destroys rdx, which is also used to pass a parameter.  Therefore, the snippet must be before the parameters are assigned to their locations.
-            LIRDebugInfo addrInfo = stateFor(stateBeforeCallWithArguments(x.stateAfter(), callTarget, x.bci()), x.leafGraphId());
+            LIRFrameState addrInfo = stateFor(stateBeforeCallWithArguments(x.stateAfter(), callTarget, x.bci()), x.leafGraphId());
             destinationAddress = emitXir(snippet, x.node(), addrInfo, false);
         }
 
@@ -895,11 +895,11 @@
 
         if (target().invokeSnippetAfterArguments) {
             // This is the version currently active for HotSpot.
-            LIRDebugInfo addrInfo = stateFor(stateBeforeCallWithArguments(x.stateAfter(), callTarget, x.bci()), null, null, x.leafGraphId());
+            LIRFrameState addrInfo = stateFor(stateBeforeCallWithArguments(x.stateAfter(), callTarget, x.bci()), null, null, x.leafGraphId());
             destinationAddress = emitXir(snippet, x.node(), addrInfo, false);
         }
 
-        LIRDebugInfo callInfo = stateFor(x.stateDuring(), null, x instanceof InvokeWithExceptionNode ? getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge()) : null, x.leafGraphId());
+        LIRFrameState callInfo = stateFor(x.stateDuring(), null, x instanceof InvokeWithExceptionNode ? getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge()) : null, x.leafGraphId());
         emitCall(targetMethod, resultOperand, argList, destinationAddress, callInfo, snippet.marks);
 
         if (isLegal(resultOperand)) {
@@ -907,7 +907,7 @@
         }
     }
 
-    protected abstract void emitCall(Object targetMethod, Value result, List<Value> arguments, Value targetAddress, LIRDebugInfo info, Map<XirMark, Mark> marks);
+    protected abstract void emitCall(Object targetMethod, Value result, List<Value> arguments, Value targetAddress, LIRFrameState info, Map<XirMark, Mark> marks);
 
 
     private static Value toStackKind(Value value) {
@@ -942,11 +942,11 @@
     }
 
 
-    protected abstract LabelRef createDeoptStub(DeoptimizationAction action, DeoptimizationReason reason, LIRDebugInfo info, Object deoptInfo);
+    protected abstract LabelRef createDeoptStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info, Object deoptInfo);
 
     @Override
     public Variable emitCall(@SuppressWarnings("hiding") Object target, Kind result, Kind[] arguments, boolean canTrap, Value... args) {
-        LIRDebugInfo info = canTrap ? state() : null;
+        LIRFrameState info = canTrap ? state() : null;
 
         Value physReg = resultOperandFor(result);
 
@@ -984,7 +984,7 @@
         frameMap.callsMethod(cc, RuntimeCall);
         List<Value> argList = visitInvokeArguments(cc, x.arguments());
 
-        LIRDebugInfo info = null;
+        LIRFrameState info = null;
         FrameState stateAfter = x.stateAfter();
         if (stateAfter != null) {
             // (cwimmer) I made the code that modifies the operand stack conditional. My scenario: runtime calls to, e.g.,
@@ -1192,11 +1192,11 @@
         return variable;
     }
 
-    protected Value emitXir(XirSnippet snippet, ValueNode x, LIRDebugInfo info, boolean setInstructionResult) {
+    protected Value emitXir(XirSnippet snippet, ValueNode x, LIRFrameState info, boolean setInstructionResult) {
         return emitXir(snippet, x, info, null, setInstructionResult, null, null);
     }
 
-    protected Value emitXir(XirSnippet snippet, ValueNode instruction, LIRDebugInfo info, LIRDebugInfo infoAfter, boolean setInstructionResult, LabelRef trueSuccessor, LabelRef falseSuccessor) {
+    protected Value emitXir(XirSnippet snippet, ValueNode instruction, LIRFrameState info, LIRFrameState infoAfter, boolean setInstructionResult, LabelRef trueSuccessor, LabelRef falseSuccessor) {
         if (GraalOptions.PrintXirTemplates) {
             TTY.println("Emit XIR template " + snippet.template.name);
         }
@@ -1304,9 +1304,9 @@
     }
 
     protected abstract void emitXir(XirSnippet snippet, Value[] operands, Value outputOperand, Value[] inputs, Value[] temps, int[] inputOperandIndices, int[] tempOperandIndices, int outputOperandIndex,
-                    LIRDebugInfo info, LIRDebugInfo infoAfter, LabelRef trueSuccessor, LabelRef falseSuccessor);
+                    LIRFrameState info, LIRFrameState infoAfter, LabelRef trueSuccessor, LabelRef falseSuccessor);
 
-    protected final Value callRuntime(RuntimeCall runtimeCall, LIRDebugInfo info, Value... args) {
+    protected final Value callRuntime(RuntimeCall runtimeCall, LIRFrameState info, Value... args) {
         // get a result register
         Kind result = runtimeCall.resultKind;
         Kind[] arguments = runtimeCall.arguments;
@@ -1336,7 +1336,7 @@
         return physReg;
     }
 
-    protected final Variable callRuntimeWithResult(RuntimeCall runtimeCall, LIRDebugInfo info, Value... args) {
+    protected final Variable callRuntimeWithResult(RuntimeCall runtimeCall, LIRFrameState info, Value... args) {
         Value location = callRuntime(runtimeCall, info, args);
         return emitMove(location);
     }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64DeoptimizationStub.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64DeoptimizationStub.java	Fri Jun 29 18:33:48 2012 -0700
@@ -35,12 +35,12 @@
 
 public class AMD64DeoptimizationStub extends AMD64Code {
     public final Label label = new Label();
-    public final LIRDebugInfo info;
+    public final LIRFrameState info;
     public final DeoptimizationAction action;
     public final DeoptimizationReason reason;
     public final Object deoptInfo;
 
-    public AMD64DeoptimizationStub(DeoptimizationAction action, DeoptimizationReason reason, LIRDebugInfo info, Object deoptInfo) {
+    public AMD64DeoptimizationStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info, Object deoptInfo) {
         this.action = action;
         this.reason = reason;
         this.info = info;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64LIRGenerator.java	Fri Jun 29 18:33:48 2012 -0700
@@ -213,12 +213,12 @@
     }
 
     @Override
-    public void emitJump(LabelRef label, LIRDebugInfo info) {
+    public void emitJump(LabelRef label, LIRFrameState info) {
         append(new JumpOp(label, info));
     }
 
     @Override
-    public void emitBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRDebugInfo info) {
+    public void emitBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRFrameState info) {
         boolean mirrored = emitCompare(left, right);
         Condition finalCondition = mirrored ? cond.mirror() : cond;
         switch (left.kind.stackKind()) {
@@ -520,7 +520,7 @@
 
     @Override
     public void emitDeoptimizeOnOverflow(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo) {
-        LIRDebugInfo info = state();
+        LIRFrameState info = state();
         LabelRef stubEntry = createDeoptStub(action, reason, info, deoptInfo);
         append(new BranchOp(ConditionFlag.overflow, stubEntry, info));
     }
@@ -528,7 +528,7 @@
 
     @Override
     public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo, long leafGraphId) {
-        LIRDebugInfo info = state(leafGraphId);
+        LIRFrameState info = state(leafGraphId);
         LabelRef stubEntry = createDeoptStub(action, reason, info, deoptInfo);
         append(new JumpOp(stubEntry, info));
     }
@@ -542,7 +542,7 @@
     }
 
     @Override
-    protected void emitCall(Object targetMethod, Value result, List<Value> arguments, Value targetAddress, LIRDebugInfo info, Map<XirMark, Mark> marks) {
+    protected void emitCall(Object targetMethod, Value result, List<Value> arguments, Value targetAddress, LIRFrameState info, Map<XirMark, Mark> marks) {
         if (isConstant(targetAddress)) {
             append(new DirectCallOp(targetMethod, result, arguments.toArray(new Value[arguments.size()]), info, marks));
         } else {
@@ -557,7 +557,7 @@
 
     @Override
     protected void emitXir(XirSnippet snippet, Value[] operands, Value outputOperand, Value[] inputs, Value[] temps, int[] inputOperandIndices, int[] tempOperandIndices, int outputOperandIndex,
-                    LIRDebugInfo info, LIRDebugInfo infoAfter, LabelRef trueSuccessor, LabelRef falseSuccessor) {
+                    LIRFrameState info, LIRFrameState infoAfter, LabelRef trueSuccessor, LabelRef falseSuccessor) {
         append(new AMD64XirOp(snippet, operands, outputOperand, inputs, temps, inputOperandIndices, tempOperandIndices, outputOperandIndex, info, infoAfter, trueSuccessor, falseSuccessor));
     }
 
@@ -565,7 +565,7 @@
     protected void emitSequentialSwitch(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key) {
         // Making a copy of the switch value is necessary because jump table destroys the input value
         if (key.kind == Kind.Int) {
-            append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key));
+            append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, Value.IllegalValue));
         } else {
             assert key.kind == Kind.Object;
             append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, newVariable(Kind.Object)));
@@ -585,7 +585,7 @@
     }
 
     @Override
-    protected LabelRef createDeoptStub(DeoptimizationAction action, DeoptimizationReason reason, LIRDebugInfo info, Object deoptInfo) {
+    protected LabelRef createDeoptStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info, Object deoptInfo) {
         assert info.topFrame.getBCI() >= 0 : "invalid bci for deopt framestate";
         AMD64DeoptimizationStub stub = new AMD64DeoptimizationStub(action, reason, info, deoptInfo);
         lir.stubs.add(stub);
@@ -595,7 +595,7 @@
     @Override
     protected void emitNullCheckGuard(ValueNode object, long leafGraphId) {
         Variable value = load(operand(object));
-        LIRDebugInfo info = state(leafGraphId);
+        LIRFrameState info = state(leafGraphId);
         append(new NullCheckOp(value, info));
     }
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64XirOp.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/amd64/AMD64XirOp.java	Fri Jun 29 18:33:48 2012 -0700
@@ -46,8 +46,8 @@
 
 public class AMD64XirOp extends LIRXirInstruction {
     public AMD64XirOp(XirSnippet snippet, Value[] operands, Value outputOperand, Value[] inputs, Value[] temps, int[] inputOperandIndices, int[] tempOperandIndices, int outputOperandIndex,
-                        LIRDebugInfo info, LIRDebugInfo infoAfter, LabelRef trueSuccessor, LabelRef falseSuccessor) {
-        super("XIR", snippet, operands, outputOperand, inputs, temps, inputOperandIndices, tempOperandIndices, outputOperandIndex, info, infoAfter, trueSuccessor, falseSuccessor);
+                        LIRFrameState info, LIRFrameState infoAfter, LabelRef trueSuccessor, LabelRef falseSuccessor) {
+        super(snippet, operands, outputOperand, inputs, temps, inputOperandIndices, tempOperandIndices, outputOperandIndex, info, infoAfter, trueSuccessor, falseSuccessor);
     }
 
     @Override
@@ -165,7 +165,7 @@
                     Value pointer = operands[inst.x().index];
                     RegisterValue register = assureInRegister(tasm, masm, pointer);
 
-                    AMD64Move.load(tasm, masm, result, new Address(inst.kind, register), (Boolean) inst.extra ? info : null);
+                    AMD64Move.load(tasm, masm, result, new Address(inst.kind, register), (Boolean) inst.extra ? state : null);
                     break;
                 }
 
@@ -174,7 +174,7 @@
                     Value pointer = operands[inst.x().index];
                     assert isRegister(pointer);
 
-                    AMD64Move.store(tasm, masm, new Address(inst.kind, pointer), value, (Boolean) inst.extra ? info : null);
+                    AMD64Move.store(tasm, masm, new Address(inst.kind, pointer), value, (Boolean) inst.extra ? state : null);
                     break;
                 }
 
@@ -201,7 +201,7 @@
                         src = new Address(inst.kind, pointer, index, scale, displacement);
                     }
 
-                    AMD64Move.load(tasm, masm, result, src, canTrap ? info : null);
+                    AMD64Move.load(tasm, masm, result, src, canTrap ? state : null);
                     break;
                 }
 
@@ -245,7 +245,7 @@
                         dst = new Address(inst.kind, pointer, index, scale, displacement);
                     }
 
-                    AMD64Move.store(tasm, masm, dst, value, canTrap ? info : null);
+                    AMD64Move.store(tasm, masm, dst, value, canTrap ? state : null);
                     break;
                 }
 
@@ -271,8 +271,8 @@
                     RegisterValue pointerRegister = assureInRegister(tasm, masm, exchangedAddress);
                     Address addr = new Address(tasm.target.wordKind, pointerRegister);
 
-                    if ((Boolean) inst.extra && info != null) {
-                        tasm.recordImplicitException(masm.codeBuffer.position(), info);
+                    if ((Boolean) inst.extra && state != null) {
+                        tasm.recordImplicitException(masm.codeBuffer.position(), state);
                     }
                     masm.cmpxchgq(asRegister(exchangedVal), addr);
 
@@ -294,7 +294,7 @@
                     }
 
                     RuntimeCallInformation runtimeCallInformation = (RuntimeCallInformation) inst.extra;
-                    AMD64Call.directCall(tasm, masm, runtimeCallInformation.target, (runtimeCallInformation.useInfoAfter) ? infoAfter : info);
+                    AMD64Call.directCall(tasm, masm, runtimeCallInformation.target, (runtimeCallInformation.useInfoAfter) ? stateAfter : state);
 
                     if (inst.result != null && inst.result.kind != Kind.Illegal && inst.result.kind != Kind.Void) {
                         Register returnRegister = tasm.frameMap.registerConfig.getReturnRegister(inst.result.kind);
@@ -386,12 +386,12 @@
                     break;
                 }
                 case Safepoint: {
-                    assert info != null : "Must have debug info in order to create a safepoint.";
-                    tasm.recordSafepoint(masm.codeBuffer.position(), info);
+                    assert state != null : "Must have debug info in order to create a safepoint.";
+                    tasm.recordSafepoint(masm.codeBuffer.position(), state);
                     break;
                 }
                 case NullCheck: {
-                    tasm.recordImplicitException(masm.codeBuffer.position(), info);
+                    tasm.recordImplicitException(masm.codeBuffer.position(), state);
                     Value pointer = operands[inst.x().index];
                     masm.nullCheck(asRegister(pointer));
                     break;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/counters/MethodEntryCounters.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/counters/MethodEntryCounters.java	Fri Jun 29 18:33:48 2012 -0700
@@ -32,9 +32,8 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.gen.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.max.asm.*;
@@ -42,7 +41,6 @@
 import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag;
 import com.oracle.max.criutils.*;
 
-
 public class MethodEntryCounters {
     protected static final class Counter implements Comparable<Counter> {
         protected static ArrayList<Counter> counters = new ArrayList<>();
@@ -64,23 +62,24 @@
     }
 
 
+    @Opcode("ENTRY_COUNTER")
     protected static class AMD64MethodEntryOp extends AMD64LIRInstruction {
+        @Temp protected Value counterArr;
+        @Temp protected Value callerPc;
+
         protected static int codeSize;
 
         protected final Counter counter;
 
         protected AMD64MethodEntryOp(Counter counter, Value counterArr, Value callerPc) {
-            super("ENTRY_COUNTER", LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, new Value[] {counterArr, callerPc});
             this.counter = counter;
+            this.counterArr = counterArr;
+            this.callerPc = callerPc;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
             int start = masm.codeBuffer.position();
-
-            Value counterArr = temp(0);
-            Value callerPc = temp(1);
-
             int off = Unsafe.getUnsafe().arrayBaseOffset(long[].class);
             int scale = Unsafe.getUnsafe().arrayIndexScale(long[].class);
 
@@ -114,16 +113,6 @@
             assert codeSize == 0 || codeSize == size;
             codeSize = size;
         }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Temp && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            } else if (mode == OperandMode.Temp && index == 1) {
-                return EnumSet.of(OperandFlag.Register);
-            }
-            throw GraalInternalError.shouldNotReachHere();
-        }
     }
 
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java	Fri Jun 29 18:33:48 2012 -0700
@@ -62,7 +62,7 @@
     public void generate(LIRGenerator gen) {
         Variable result = gen.newVariable(Kind.Object);
         gen.emitMove(gen.operand(hub), AMD64.rdx.asValue(Kind.Object));
-        LIRDebugInfo info = gen.state();
+        LIRFrameState info = gen.state();
         AMD64NewInstanceStubCallOp op = new AMD64NewInstanceStubCallOp(result, AMD64.rdx.asValue(Kind.Object), info);
         gen.append(op);
         gen.setResult(this, result);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java	Fri Jun 29 18:33:48 2012 -0700
@@ -72,6 +72,6 @@
 
         Value entry = gen.emitLoad(new Address(Kind.Long, gen.operand(target), config.nmethodEntryOffset), false);
 
-        gen.append(new AMD64TailcallOp(argList, entry, cc.locations));
+        gen.append(new AMD64TailcallOp(argList, entry));
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java	Fri Jun 29 18:33:48 2012 -0700
@@ -45,7 +45,7 @@
 
     @Override
     public void generate(LIRGenerator gen) {
-        LIRDebugInfo info = gen.state();
+        LIRFrameState info = gen.state();
         AMD64VerifyOopStubCallOp op = new AMD64VerifyOopStubCallOp(gen.operand(object), info);
         gen.append(op);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64NewInstanceStubCallOp.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64NewInstanceStubCallOp.java	Fri Jun 29 18:33:48 2012 -0700
@@ -24,48 +24,45 @@
 
 import static com.oracle.graal.api.code.ValueUtil.*;
 
-import java.util.*;
-
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.max.asm.target.amd64.*;
+import com.oracle.graal.lir.LIRInstruction.Opcode;
 
 /**
  * LIR instruction for calling HotSpot's {@code new_instance} stub. This stub is declared in c1_Runtime1.hpp
  * and implemented in Runtime1::generate_code_for() which is located in c1_Runtime1_x86.cpp.
  */
+@Opcode("NEW_INSTANCE")
 public class AMD64NewInstanceStubCallOp extends AMD64LIRInstruction {
-    public AMD64NewInstanceStubCallOp(Value result, Value hub, LIRDebugInfo info) {
-        super("NEW_INSTANCE", new Value[] {result}, info, new Value[] {hub}, NO_OPERANDS, new Value[]{AMD64.rax.asValue(Kind.Object)});
+    @Def protected Value result;
+    @Use protected Value hub;
+    @Temp protected Value temp;
+    @State protected LIRFrameState state;
+
+    public AMD64NewInstanceStubCallOp(Value result, Value hub, LIRFrameState state) {
+        this.result = result;
+        this.hub = hub;
+        this.temp = AMD64.rax.asValue(Kind.Object);
+        this.state = state;
     }
 
     @Override
     public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-        Value result = output(0);
-        Value hub = input(0);
-
         // rdx: (in) hub
         // rax: (out) result
-        assert asRegister(hub) == AMD64.rdx;
-        AMD64Call.directCall(tasm, masm, HotSpotGraalRuntime.getInstance().getConfig().newInstanceStub, info);
+        AMD64Call.directCall(tasm, masm, HotSpotGraalRuntime.getInstance().getConfig().newInstanceStub, state);
         if (asRegister(result) != AMD64.rax) {
             masm.movq(asRegister(result), AMD64.rax);
         }
     }
 
     @Override
-    protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-        if (mode == OperandMode.Input) {
-            return EnumSet.of(OperandFlag.Register);
-        } else if (mode == OperandMode.Output) {
-            return EnumSet.of(OperandFlag.Register);
-        } else if (mode == OperandMode.Temp) {
-            return EnumSet.of(OperandFlag.Register);
-        }
-        throw GraalInternalError.shouldNotReachHere();
+    protected void verify() {
+        super.verify();
+        assert asRegister(hub) == AMD64.rdx;
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64VerifyOopStubCallOp.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64VerifyOopStubCallOp.java	Fri Jun 29 18:33:48 2012 -0700
@@ -24,13 +24,10 @@
 
 import static com.oracle.graal.api.code.ValueUtil.*;
 
-import java.util.*;
-
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.max.asm.target.amd64.*;
@@ -38,30 +35,26 @@
 /**
  * A call to HotSpot's object pointer verification stub.
  */
+@Opcode("VERIFY_OOP")
 public class AMD64VerifyOopStubCallOp extends AMD64LIRInstruction {
-    public AMD64VerifyOopStubCallOp(Value object, LIRDebugInfo info) {
-        super("VERIFY_OOP", LIRInstruction.NO_OPERANDS, info, new Value[] {object}, NO_OPERANDS, NO_OPERANDS);
+    @Use protected Value object;
+    @State protected LIRFrameState state;
+
+    public AMD64VerifyOopStubCallOp(Value object, LIRFrameState state) {
+        this.object = object;
+        this.state = state;
     }
 
     @Override
     public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-        Register object = asRegister(input(0));
         // r13: (in) object
-        if (object != AMD64.r13) {
+        if (asRegister(object) != AMD64.r13) {
             masm.push(AMD64.r13);
-            masm.movq(AMD64.r13, object);
+            masm.movq(AMD64.r13, asRegister(object));
         }
-        AMD64Call.directCall(tasm, masm, HotSpotGraalRuntime.getInstance().getConfig().verifyOopStub, info);
-        if (object != AMD64.r13) {
+        AMD64Call.directCall(tasm, masm, HotSpotGraalRuntime.getInstance().getConfig().verifyOopStub, state);
+        if (asRegister(object) != AMD64.r13) {
             masm.pop(AMD64.r13);
         }
     }
-
-    @Override
-    protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-        if (mode == OperandMode.Input) {
-            return EnumSet.of(OperandFlag.Register);
-        }
-        throw GraalInternalError.shouldNotReachHere();
-    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64SafepointOp.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64SafepointOp.java	Fri Jun 29 18:33:48 2012 -0700
@@ -25,12 +25,10 @@
 import static com.oracle.graal.hotspot.meta.HotSpotXirGenerator.*;
 import static com.oracle.max.asm.target.amd64.AMD64.*;
 
-import java.util.*;
-
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.max.asm.target.amd64.*;
@@ -38,12 +36,14 @@
 /**
  * Emits a safepoint poll.
  */
+@Opcode("SAFEPOINT")
 public class AMD64SafepointOp extends AMD64LIRInstruction {
+    @State protected LIRFrameState state;
 
     private final HotSpotVMConfig config;
 
-    public AMD64SafepointOp(LIRDebugInfo info, HotSpotVMConfig config) {
-        super("SAFEPOINT", LIRInstruction.NO_OPERANDS, info, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+    public AMD64SafepointOp(LIRFrameState state, HotSpotVMConfig config) {
+        this.state = state;
         this.config = config;
     }
 
@@ -54,17 +54,12 @@
         if (config.isPollingPageFar) {
             asm.movq(scratch, config.safepointPollingAddress);
             tasm.recordMark(MARK_POLL_FAR);
-            tasm.recordSafepoint(pos, info);
+            tasm.recordSafepoint(pos, state);
             asm.movq(scratch, new Address(tasm.target.wordKind, scratch.asValue()));
         } else {
             tasm.recordMark(MARK_POLL_NEAR);
-            tasm.recordSafepoint(pos, info);
+            tasm.recordSafepoint(pos, state);
             asm.movq(scratch, new Address(tasm.target.wordKind, rip.asValue()));
         }
     }
-
-    @Override
-    protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-        throw GraalInternalError.shouldNotReachHere();
-    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64TailcallOp.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64TailcallOp.java	Fri Jun 29 18:33:48 2012 -0700
@@ -26,33 +26,23 @@
 
 import java.util.*;
 
-import com.oracle.max.asm.target.amd64.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.Opcode;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.max.asm.target.amd64.*;
 
 /**
  * Performs a hard-coded tail call to the specified target, which normally should be an RiCompiledCode instance.
  */
+@Opcode("TAILCALL")
 public class AMD64TailcallOp extends AMD64LIRInstruction {
-
-    public AMD64TailcallOp(List<Value> parameters, Value target, Value[] callingConvention) {
-        super("TAILCALL", LIRInstruction.NO_OPERANDS, null, toArray(parameters, target), LIRInstruction.NO_OPERANDS, callingConvention.clone());
-        assert inputs.length == temps.length + 1;
+    @Use protected Value target;
+    @Alive protected Value[] parameters;
 
-        for (int i = 0; i < temps.length; i++) {
-            assert isRegister(temps[i]) : "too many parameters for tail call";
-            assert sameRegister(temps[i], inputs[i]) : "inputs do not match calling convention";
-        }
-    }
-
-    private static Value[] toArray(List<Value> parameters, Value target) {
-        Value[] result = new Value[parameters.size() + 1];
-        parameters.toArray(result);
-        result[parameters.size()] = target;
-        return result;
+    public AMD64TailcallOp(List<Value> parameters, Value target) {
+        this.target = target;
+        this.parameters = parameters.toArray(new Value[parameters.size()]);
     }
 
     @Override
@@ -61,17 +51,7 @@
         masm.leave();
 
         // jump to the target method
-        masm.jmp(asRegister(inputs[inputs.length - 1]));
+        masm.jmp(asRegister(target));
         masm.ensureUniquePC();
     }
-
-    @Override
-    protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-        if (mode == OperandMode.Input) {
-            return EnumSet.of(OperandFlag.Register);
-        } else if (mode == OperandMode.Temp) {
-            return EnumSet.of(OperandFlag.Register);
-        }
-        throw GraalInternalError.shouldNotReachHere();
-    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/HotSpotAMD64Backend.java	Fri Jun 29 18:33:48 2012 -0700
@@ -61,7 +61,7 @@
 
             @Override
             public void visitSafepointNode(SafepointNode i) {
-                LIRDebugInfo info = state();
+                LIRFrameState info = state();
                 append(new AMD64SafepointOp(info, ((HotSpotRuntime) runtime).config));
             }
 
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java	Fri Jun 29 18:33:48 2012 -0700
@@ -23,16 +23,15 @@
 package com.oracle.graal.lir.amd64;
 
 import static com.oracle.graal.api.code.ValueUtil.*;
-
-import java.util.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
-import com.oracle.max.asm.*;
-import com.oracle.max.asm.target.amd64.*;
-import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.max.asm.*;
+import com.oracle.max.asm.target.amd64.*;
+import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag;
 
 public enum AMD64Arithmetic {
     IADD, ISUB, IMUL, IDIV, IREM, IUDIV, IUREM, IAND, IOR, IXOR, ISHL, ISHR, IUSHR,
@@ -48,254 +47,183 @@
 
 
     public static class Op1Reg extends AMD64LIRInstruction {
-        public Op1Reg(AMD64Arithmetic opcode, Value result, Value x) {
-            super(opcode, new Value[] {result}, null, new Value[] {x}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
-        }
-
-        @Override
-        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            Value result = output(0);
-            Value x = input(0);
-
-            emit(tasm, masm, (AMD64Arithmetic) code, result, x, null);
-        }
+        @Opcode private final AMD64Arithmetic opcode;
+        @Def({REG, HINT}) protected Value result;
+        @Use({REG}) protected Value x;
 
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            } else if (mode == OperandMode.Output && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            }
-            throw GraalInternalError.shouldNotReachHere();
-        }
-    }
-
-    public static class Op1Stack extends AMD64LIRInstruction {
-        public Op1Stack(AMD64Arithmetic opcode, Value result, Value x) {
-            super(opcode, new Value[] {result}, null, new Value[] {x}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+        public Op1Reg(AMD64Arithmetic opcode, Value result, Value x) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            Value result = output(0);
-            Value x = input(0);
-
-            AMD64Move.move(tasm, masm, result, x);
-            emit(tasm, masm, (AMD64Arithmetic) code, result);
-        }
-
-        @Override
-        public EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
-            } else if (mode == OperandMode.Output && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint);
-            }
-            throw GraalInternalError.shouldNotReachHere();
+            emit(tasm, masm, opcode, result, x, null);
         }
     }
 
-    public static class Op2Stack extends AMD64LIRInstruction {
-        public Op2Stack(AMD64Arithmetic opcode, Value result, Value x, Value y) {
-            super(opcode, new Value[] {result}, null, new Value[] {x}, new Value[] {y}, LIRInstruction.NO_OPERANDS);
+    public static class Op1Stack extends AMD64LIRInstruction {
+        @Opcode private final AMD64Arithmetic opcode;
+        @Def({REG, HINT}) protected Value result;
+        @Use({REG, STACK, CONST}) protected Value x;
+
+        public Op1Stack(AMD64Arithmetic opcode, Value result, Value x) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            Value result = output(0);
-            Value x = input(0);
-            Value y = alive(0);
-
             AMD64Move.move(tasm, masm, result, x);
-            emit(tasm, masm, (AMD64Arithmetic) code, result, y, null);
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
-            } else if (mode == OperandMode.Alive && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
-            } else if (mode == OperandMode.Output && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint);
-            }
-            throw GraalInternalError.shouldNotReachHere();
-        }
-
-        @Override
-        public void verify() {
-            Value result = output(0);
-            Value x = input(0);
-            Value y = alive(0);
-
-            super.verify();
-            assert differentRegisters(result, y) || sameRegister(x, y);
-            verifyKind((AMD64Arithmetic) code, result, x, y);
+            emit(tasm, masm, opcode, result);
         }
     }
 
-    public static class Op2Reg extends AMD64LIRInstruction {
-        public Op2Reg(AMD64Arithmetic opcode, Value result, Value x, Value y) {
-            super(opcode, new Value[] {result}, null, new Value[] {x}, new Value[] {y}, LIRInstruction.NO_OPERANDS);
+    public static class Op2Stack extends AMD64LIRInstruction {
+        @Opcode private final AMD64Arithmetic opcode;
+        @Def({REG, HINT}) protected Value result;
+        @Use({REG, STACK, CONST}) protected Value x;
+        @Alive({REG, STACK, CONST}) protected Value y;
+
+        public Op2Stack(AMD64Arithmetic opcode, Value result, Value x, Value y) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+            this.y = y;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            Value result = output(0);
-            Value x = input(0);
-            Value y = alive(0);
-
             AMD64Move.move(tasm, masm, result, x);
-            emit(tasm, masm, (AMD64Arithmetic) code, result, y, null);
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
-            } else if (mode == OperandMode.Alive && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Constant);
-            } else if (mode == OperandMode.Output && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint);
-            }
-            throw GraalInternalError.shouldNotReachHere();
+            emit(tasm, masm, opcode, result, y, null);
         }
 
         @Override
         public void verify() {
-            Value result = output(0);
-            Value x = input(0);
-            Value y = alive(0);
-
             super.verify();
             assert differentRegisters(result, y) || sameRegister(x, y);
-            verifyKind((AMD64Arithmetic) code, result, x, y);
+            verifyKind(opcode, result, x, y);
+        }
+    }
+
+    public static class Op2Reg extends AMD64LIRInstruction {
+        @Opcode private final AMD64Arithmetic opcode;
+        @Def({REG, HINT}) protected Value result;
+        @Use({REG, STACK, CONST}) protected Value x;
+        @Alive({REG, CONST}) protected Value y;
+
+        public Op2Reg(AMD64Arithmetic opcode, Value result, Value x, Value y) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+            this.y = y;
+        }
+
+        @Override
+        public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
+            AMD64Move.move(tasm, masm, result, x);
+            emit(tasm, masm, opcode, result, y, null);
+        }
+
+        @Override
+        public void verify() {
+            super.verify();
+            assert differentRegisters(result, y) || sameRegister(x, y);
+            verifyKind(opcode, result, x, y);
         }
     }
 
     public static class Op2RegCommutative extends AMD64LIRInstruction {
+        @Opcode private final AMD64Arithmetic opcode;
+        @Def({REG, HINT}) protected Value result;
+        @Use({REG, STACK, CONST}) protected Value x;
+        @Use({REG, CONST}) protected Value y;
+
         public Op2RegCommutative(AMD64Arithmetic opcode, Value result, Value x, Value y) {
-            super(opcode, new Value[] {result}, null, new Value[] {x, y}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+            this.y = y;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            Value result = output(0);
-            Value x = input(0);
-            Value y = input(1);
-
             if (sameRegister(result, y)) {
-                emit(tasm, masm, (AMD64Arithmetic) code, result, x, null);
+                emit(tasm, masm, opcode, result, x, null);
             } else {
                 AMD64Move.move(tasm, masm, result, x);
-                emit(tasm, masm, (AMD64Arithmetic) code, result, y, null);
+                emit(tasm, masm, opcode, result, y, null);
             }
         }
 
         @Override
-        public EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
-            } else if (mode == OperandMode.Input && index == 1) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Constant);
-            } else if (mode == OperandMode.Output && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint);
-            }
-            throw GraalInternalError.shouldNotReachHere();
-        }
-
-        @Override
         protected void verify() {
-            Value result = output(0);
-            Value x = input(0);
-            Value y = input(1);
-
             super.verify();
-            verifyKind((AMD64Arithmetic) code, result, x, y);
+            verifyKind(opcode, result, x, y);
         }
     }
 
     public static class ShiftOp extends AMD64LIRInstruction {
+        @Opcode private final AMD64Arithmetic opcode;
+        @Def({REG, HINT}) protected Value result;
+        @Use({REG, STACK, CONST}) protected Value x;
+        @Alive({REG, CONST}) protected Value y;
+
         public ShiftOp(AMD64Arithmetic opcode, Value result, Value x, Value y) {
-            super(opcode, new Value[] {result}, null, new Value[] {x}, new Value[] {y}, LIRInstruction.NO_OPERANDS);
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+            this.y = y;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            Value result = output(0);
-            Value x = input(0);
-            Value y = alive(0);
-
             AMD64Move.move(tasm, masm, result, x);
-            emit(tasm, masm, (AMD64Arithmetic) code, result, y, null);
-        }
-
-        @Override
-        public EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
-            } else if (mode == OperandMode.Alive && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Constant);
-            } else if (mode == OperandMode.Output && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint);
-            }
-            throw GraalInternalError.shouldNotReachHere();
+            emit(tasm, masm, opcode, result, y, null);
         }
 
         @Override
         public void verify() {
-            Value result = output(0);
-            Value x = input(0);
-            Value y = alive(0);
-
             super.verify();
             assert isConstant(y) || asRegister(y) == AMD64.rcx;
             assert differentRegisters(result, y) || sameRegister(x, y);
-            verifyKind((AMD64Arithmetic) code, result, x, x);
+            verifyKind(opcode, result, x, x);
             assert y.kind.stackKind() == Kind.Int;
         }
     }
 
     public static class DivOp extends AMD64LIRInstruction {
-        public DivOp(AMD64Arithmetic opcode, Value result, Value x, Value y, LIRDebugInfo info) {
-            super(opcode, new Value[] {result}, info, new Value[] {x}, new Value[] {y}, new Value[] {asRegister(result) == AMD64.rax ? AMD64.rdx.asValue(result.kind) : AMD64.rax.asValue(result.kind)});
+        @Opcode private final AMD64Arithmetic opcode;
+        @Def protected Value result;
+        @Use protected Value x;
+        @Alive protected Value y;
+        @Temp protected Value temp;
+        @State protected LIRFrameState state;
+
+        public DivOp(AMD64Arithmetic opcode, Value result, Value x, Value y, LIRFrameState state) {
+            this.opcode = opcode;
+            this.result = result;
+            this.x = x;
+            this.y = y;
+            this.temp = asRegister(result) == AMD64.rax ? AMD64.rdx.asValue(result.kind) : AMD64.rax.asValue(result.kind);
+            this.state = state;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            Value result = output(0);
-            Value y = alive(0);
-
-            emit(tasm, masm, (AMD64Arithmetic) code, result, y, info);
-        }
-
-        @Override
-        public EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            } else if (mode == OperandMode.Alive && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            } else if (mode == OperandMode.Temp && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            } else if (mode == OperandMode.Output && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            }
-            throw GraalInternalError.shouldNotReachHere();
+            emit(tasm, masm, opcode, result, y, state);
         }
 
         @Override
         protected void verify() {
-            Value result = output(0);
-            Value x = input(0);
-            Value y = alive(0);
-
             super.verify();
             // left input in rax, right input in any register but rax and rdx, result quotient in rax, result remainder in rdx
             assert asRegister(x) == AMD64.rax;
             assert differentRegisters(y, AMD64.rax.asValue(), AMD64.rdx.asValue());
             assert (name().endsWith("DIV") && asRegister(result) == AMD64.rax) || (name().endsWith("REM") && asRegister(result) == AMD64.rdx);
-            verifyKind((AMD64Arithmetic) code, result, x, y);
+            verifyKind(opcode, result, x, y);
         }
     }
 
@@ -313,7 +241,7 @@
         }
     }
 
-    public static void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AMD64Arithmetic opcode, Value dst, Value src, LIRDebugInfo info) {
+    public static void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AMD64Arithmetic opcode, Value dst, Value src, LIRFrameState info) {
         int exceptionOffset = -1;
         if (isRegister(src)) {
             switch (opcode) {
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java	Fri Jun 29 18:33:48 2012 -0700
@@ -23,27 +23,35 @@
 package com.oracle.graal.lir.amd64;
 
 import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
 import java.util.*;
 
+import com.oracle.graal.api.code.CompilationResult.Mark;
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.asm.*;
 import com.oracle.max.asm.target.amd64.*;
 import com.oracle.max.cri.xir.CiXirAssembler.XirMark;
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.CompilationResult.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.asm.*;
 
 public class AMD64Call {
 
+    @Opcode("CALL_DIRECT")
     public static class DirectCallOp extends AMD64LIRInstruction implements StandardOp.CallOp {
-        private final Object targetMethod;
-        private final Map<XirMark, Mark> marks;
+        @Def({REG, ILLEGAL}) protected Value result;
+        @Use({REG, STACK}) protected Value[] parameters;
+        @State protected LIRFrameState state;
 
-        public DirectCallOp(Object targetMethod, Value result, Value[] parameters, LIRDebugInfo info, Map<XirMark, Mark> marks) {
-            super("CALL_DIRECT", new Value[] {result}, info, parameters, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+        protected final Object targetMethod;
+        protected final Map<XirMark, Mark> marks;
+
+        public DirectCallOp(Object targetMethod, Value result, Value[] parameters, LIRFrameState state, Map<XirMark, Mark> marks) {
             this.targetMethod = targetMethod;
+            this.result = result;
+            this.parameters = parameters;
+            this.state = state;
             this.marks = marks;
         }
 
@@ -53,57 +61,36 @@
             if (marks != null) {
                 marks.put(XirMark.CALLSITE, tasm.recordMark(null, new Mark[0]));
             }
-            directCall(tasm, masm, targetMethod, info);
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack);
-            } else if (mode == OperandMode.Output) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Illegal);
-            }
-            throw GraalInternalError.shouldNotReachHere();
+            directCall(tasm, masm, targetMethod, state);
         }
     }
 
+    @Opcode("CALL_INDIRECT")
     public static class IndirectCallOp extends AMD64LIRInstruction implements StandardOp.CallOp {
+        @Def({REG, ILLEGAL}) protected Value result;
+        @Use({REG, STACK}) protected Value[] parameters;
+        @Use({REG}) protected Value targetAddress;
+        @State protected LIRFrameState state;
+
         private final Object targetMethod;
         private final Map<XirMark, Mark> marks;
 
-        private static Value[] concat(Value[] parameters, Value targetAddress) {
-            Value[] result = Arrays.copyOf(parameters, parameters.length + 1);
-            result[result.length - 1] = targetAddress;
-            return result;
-        }
-
-        public IndirectCallOp(Object targetMethod, Value result, Value[] parameters, Value targetAddress, LIRDebugInfo info, Map<XirMark, Mark> marks) {
-            super("CALL_INDIRECT", new Value[] {result}, info, concat(parameters, targetAddress), LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+        public IndirectCallOp(Object targetMethod, Value result, Value[] parameters, Value targetAddress, LIRFrameState state, Map<XirMark, Mark> marks) {
             this.targetMethod = targetMethod;
+            this.result = result;
+            this.parameters = parameters;
+            this.targetAddress = targetAddress;
+            this.state = state;
             this.marks = marks;
         }
 
-        private Value targetAddress() {
-            return input(inputs.length - 1);
-        }
-
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
             callAlignment(tasm, masm);
             if (marks != null) {
                 marks.put(XirMark.CALLSITE, tasm.recordMark(null, new Mark[0]));
             }
-            indirectCall(tasm, masm, asRegister(targetAddress()), targetMethod, info);
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack);
-            } else if (mode == OperandMode.Output) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Illegal);
-            }
-            throw GraalInternalError.shouldNotReachHere();
+            indirectCall(tasm, masm, asRegister(targetAddress), targetMethod, state);
         }
     }
 
@@ -117,7 +104,7 @@
         }
     }
 
-    public static void directCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Object target, LIRDebugInfo info) {
+    public static void directCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Object target, LIRFrameState info) {
         int before = masm.codeBuffer.position();
         if (target instanceof RuntimeCall) {
             long maxOffset = tasm.runtime.getMaxCallTargetOffset((RuntimeCall) target);
@@ -148,7 +135,7 @@
         masm.ensureUniquePC();
     }
 
-    public static void indirectCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Register dst, Object target, LIRDebugInfo info) {
+    public static void indirectCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Register dst, Object target, LIRFrameState info) {
         int before = masm.codeBuffer.position();
         masm.call(dst);
         int after = masm.codeBuffer.position();
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java	Fri Jun 29 18:33:48 2012 -0700
@@ -23,45 +23,34 @@
 package com.oracle.graal.lir.amd64;
 
 import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
-import java.util.*;
-
-import com.oracle.max.asm.target.amd64.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.max.asm.target.amd64.*;
 
 public enum AMD64Compare {
     ICMP, LCMP, ACMP, FCMP, DCMP;
 
     public static class CompareOp extends AMD64LIRInstruction {
+        @Opcode private final AMD64Compare opcode;
+        @Use({REG}) protected Value x;
+        @Use({REG, STACK, CONST}) protected Value y;
+
         public CompareOp(AMD64Compare opcode, Value x, Value y) {
-            super(opcode, LIRInstruction.NO_OPERANDS, null, new Value[] {x, y}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+            this.opcode = opcode;
+            this.x = x;
+            this.y = y;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            Value x = input(0);
-            Value y = input(1);
-            emit(tasm, masm, (AMD64Compare) code, x, y);
-        }
-
-        @Override
-        public EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            } else if (mode == OperandMode.Input && index == 1) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
-            }
-            throw GraalInternalError.shouldNotReachHere();
+            emit(tasm, masm, opcode, x, y);
         }
 
         @Override
         protected void verify() {
-            Value x = input(0);
-            Value y = input(1);
-
             super.verify();
             assert (name().startsWith("I") && x.kind == Kind.Int && y.kind.stackKind() == Kind.Int)
                 || (name().startsWith("I") && x.kind == Kind.Jsr && y.kind == Kind.Jsr)
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java	Fri Jun 29 18:33:48 2012 -0700
@@ -23,27 +23,29 @@
 package com.oracle.graal.lir.amd64;
 
 import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
-import java.util.*;
-
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.code.Address.Scale;
+import com.oracle.graal.api.code.CompilationResult.JumpTable;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.*;
+import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.StandardOp.FallThroughOp;
+import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.nodes.calc.*;
 import com.oracle.max.asm.*;
 import com.oracle.max.asm.target.amd64.*;
 import com.oracle.max.asm.target.amd64.AMD64Assembler.ConditionFlag;
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.Address.*;
-import com.oracle.graal.api.code.CompilationResult.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.StandardOp.FallThroughOp;
-import com.oracle.graal.lir.asm.*;
-import com.oracle.graal.nodes.calc.*;
 
 public class AMD64ControlFlow {
 
     public static class ReturnOp extends AMD64LIRInstruction {
-        public ReturnOp(Value input) {
-            super("RETURN", LIRInstruction.NO_OPERANDS, null, new Value[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+        @Use({REG, ILLEGAL}) protected Value x;
+
+        public ReturnOp(Value x) {
+            this.x = x;
         }
 
         @Override
@@ -53,29 +55,22 @@
             }
             masm.ret(0);
         }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Illegal);
-            }
-            throw GraalInternalError.shouldNotReachHere();
-        }
     }
 
 
     public static class BranchOp extends AMD64LIRInstruction implements StandardOp.BranchOp {
         protected ConditionFlag condition;
         protected LabelRef destination;
+        @State protected LIRFrameState state;
 
-        public BranchOp(Condition condition, LabelRef destination, LIRDebugInfo info) {
+        public BranchOp(Condition condition, LabelRef destination, LIRFrameState info) {
             this(intCond(condition), destination, info);
         }
 
-        public BranchOp(ConditionFlag condition, LabelRef destination, LIRDebugInfo info) {
-            super("BRANCH", LIRInstruction.NO_OPERANDS, info, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+        public BranchOp(ConditionFlag condition, LabelRef destination, LIRFrameState state) {
             this.condition = condition;
             this.destination = destination;
+            this.state = state;
         }
 
         @Override
@@ -93,23 +88,13 @@
             destination = newDestination;
             condition = condition.negate();
         }
-
-        @Override
-        public String operationString() {
-            return condition.operator + " [" + destination + "]";
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            throw GraalInternalError.shouldNotReachHere();
-        }
     }
 
 
     public static class FloatBranchOp extends BranchOp {
         protected boolean unorderedIsTrue;
 
-        public FloatBranchOp(Condition condition, boolean unorderedIsTrue, LabelRef destination, LIRDebugInfo info) {
+        public FloatBranchOp(Condition condition, boolean unorderedIsTrue, LabelRef destination, LIRFrameState info) {
             super(floatCond(condition), destination, info);
             this.unorderedIsTrue = unorderedIsTrue;
         }
@@ -124,11 +109,6 @@
             super.negate(newDestination);
             unorderedIsTrue = !unorderedIsTrue;
         }
-
-        @Override
-        public String operationString() {
-            return condition.operator + " [" + destination + "]" + (unorderedIsTrue ? " unorderedIsTrue" : " unorderedIsFalse");
-        }
     }
 
 
@@ -136,58 +116,41 @@
         private final int lowKey;
         private final LabelRef defaultTarget;
         private final LabelRef[] targets;
+        @Alive protected Value index;
+        @Temp protected Value scratch;
 
         public TableSwitchOp(final int lowKey, final LabelRef defaultTarget, final LabelRef[] targets, Variable index, Variable scratch) {
-            super("TABLE_SWITCH", LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, new Value[] {index}, new Value[] {scratch});
             this.lowKey = lowKey;
             this.defaultTarget = defaultTarget;
             this.targets = targets;
+            this.index = index;
+            this.scratch = scratch;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            tableswitch(tasm, masm, lowKey, defaultTarget, targets, asIntReg(alive(0)), asLongReg(temp(0)));
-        }
-
-        @Override
-        public String operationString() {
-            StringBuilder buf = new StringBuilder(super.operationString());
-            buf.append("\ndefault: [").append(defaultTarget).append(']');
-            int key = lowKey;
-            for (LabelRef l : targets) {
-                buf.append("\ncase ").append(key).append(": [").append(l).append(']');
-                key++;
-            }
-            return buf.toString();
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Alive && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            } else if (mode == OperandMode.Temp && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            }
-            throw GraalInternalError.shouldNotReachHere();
+            tableswitch(tasm, masm, lowKey, defaultTarget, targets, asIntReg(index), asLongReg(scratch));
         }
     }
 
     public static class SequentialSwitchOp extends AMD64LIRInstruction implements FallThroughOp {
-        private final Constant[] keyConstants;
+        @Use({CONST}) protected Constant[] keyConstants;
         private final LabelRef[] keyTargets;
         private LabelRef defaultTarget;
+        @Alive({REG}) protected Value key;
+        @Temp({REG, ILLEGAL}) protected Value scratch;
 
-        public SequentialSwitchOp(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value... temp) {
-            super("SEQUENTIAL_SWITCH", LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, new Value[] {key}, temp);
+        public SequentialSwitchOp(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch) {
             assert keyConstants.length == keyTargets.length;
             this.keyConstants = keyConstants;
             this.keyTargets = keyTargets;
             this.defaultTarget = defaultTarget;
+            this.key = key;
+            this.scratch = scratch;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            Value key = alive(0);
             if (key.kind == Kind.Int) {
                 Register intKey = asIntReg(key);
                 for (int i = 0; i < keyConstants.length; i++) {
@@ -196,7 +159,7 @@
                 }
             } else if (key.kind == Kind.Object) {
                 Register intKey = asObjectReg(key);
-                Register temp = asObjectReg(temp(0));
+                Register temp = asObjectReg(scratch);
                 for (int i = 0; i < keyConstants.length; i++) {
                     AMD64Move.move(tasm, masm, temp.asValue(Kind.Object), keyConstants[i]);
                     masm.cmpptr(intKey, temp);
@@ -213,26 +176,6 @@
         }
 
         @Override
-        public String operationString() {
-            StringBuilder buf = new StringBuilder(super.operationString());
-            buf.append("\ndefault: [").append(defaultTarget).append(']');
-            for (int i = 0; i < keyConstants.length; i++) {
-                buf.append("\ncase ").append(keyConstants[i]).append(": [").append(keyTargets[i]).append("]");
-            }
-            return buf.toString();
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Alive && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            } else if (mode == OperandMode.Temp && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            }
-            throw GraalInternalError.shouldNotReachHere();
-        }
-
-        @Override
         public LabelRef fallThroughTarget() {
             return defaultTarget;
         }
@@ -248,37 +191,34 @@
         private LabelRef defaultTarget;
         private final int[] lowKeys;
         private final int[] highKeys;
+        @Alive protected Value key;
 
         public SwitchRangesOp(int[] lowKeys, int[] highKeys, LabelRef[] keyTargets, LabelRef defaultTarget, Value key) {
-            super("SWITCH_RANGES", LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, new Value[] {key}, LIRInstruction.NO_OPERANDS);
-            assert lowKeys.length == keyTargets.length;
-            assert highKeys.length == keyTargets.length;
-            assert key.kind == Kind.Int;
             this.lowKeys = lowKeys;
             this.highKeys = highKeys;
             this.keyTargets = keyTargets;
             this.defaultTarget = defaultTarget;
+            this.key = key;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            Register key = asIntReg(alive(0));
             for (int i = 0; i < lowKeys.length; i++) {
                 int lowKey = lowKeys[i];
                 int highKey = highKeys[i];
                 if (lowKey == highKey) {
-                    masm.cmpl(key, lowKey);
+                    masm.cmpl(asIntReg(key), lowKey);
                     masm.jcc(ConditionFlag.equal, keyTargets[i].label());
                 } else if (lowKey + 1 == highKey) {
-                    masm.cmpl(key, lowKey);
+                    masm.cmpl(asIntReg(key), lowKey);
                     masm.jcc(ConditionFlag.equal, keyTargets[i].label());
-                    masm.cmpl(key, highKey);
+                    masm.cmpl(asIntReg(key), highKey);
                     masm.jcc(ConditionFlag.equal, keyTargets[i].label());
                 } else {
                     Label skip = new Label();
-                    masm.cmpl(key, lowKey);
+                    masm.cmpl(asIntReg(key), lowKey);
                     masm.jcc(ConditionFlag.less, skip);
-                    masm.cmpl(key, highKey);
+                    masm.cmpl(asIntReg(key), highKey);
                     masm.jcc(ConditionFlag.lessEqual, keyTargets[i].label());
                     masm.bind(skip);
                 }
@@ -291,23 +231,11 @@
         }
 
         @Override
-        public String operationString() {
-            StringBuilder buf = new StringBuilder(super.operationString());
-            buf.append("\ndefault: [").append(defaultTarget).append(']');
-            for (int i = 0; i < lowKeys.length; i++) {
-                buf.append("\ncase ").append(lowKeys[i]).append(" - ").append(highKeys[i]).append(": [").append(keyTargets[i]).append("]");
-            }
-            return buf.toString();
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Alive && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            } else if (mode == OperandMode.Temp && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            }
-            throw GraalInternalError.shouldNotReachHere();
+        protected void verify() {
+            super.verify();
+            assert lowKeys.length == keyTargets.length;
+            assert highKeys.length == keyTargets.length;
+            assert key.kind == Kind.Int;
         }
 
         @Override
@@ -322,68 +250,46 @@
     }
 
 
+    @Opcode("CMOVE")
     public static class CondMoveOp extends AMD64LIRInstruction {
+        @Def({REG, HINT}) protected Value result;
+        @Alive({REG}) protected Value trueValue;
+        @Use({REG, STACK, CONST}) protected Value falseValue;
         private final ConditionFlag condition;
 
         public CondMoveOp(Variable result, Condition condition, Variable trueValue, Value falseValue) {
-            super("CMOVE", new Value[] {result}, null, new Value[] {falseValue}, new Value[] {trueValue}, LIRInstruction.NO_OPERANDS);
+            this.result = result;
             this.condition = intCond(condition);
+            this.trueValue = trueValue;
+            this.falseValue = falseValue;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            cmove(tasm, masm, output(0), false, condition, false, alive(0), input(0));
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
-            } else if (mode == OperandMode.Alive && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            } else if (mode == OperandMode.Output && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint);
-            }
-            throw GraalInternalError.shouldNotReachHere();
-        }
-
-        @Override
-        public String operationString() {
-            return condition.toString() + " " + super.operationString();
+            cmove(tasm, masm, result, false, condition, false, trueValue, falseValue);
         }
     }
 
 
+    @Opcode("CMOVE")
     public static class FloatCondMoveOp extends AMD64LIRInstruction {
+        @Def({REG}) protected Value result;
+        @Alive({REG}) protected Value trueValue;
+        @Alive({REG}) protected Value falseValue;
         private final ConditionFlag condition;
         private final boolean unorderedIsTrue;
 
         public FloatCondMoveOp(Variable result, Condition condition, boolean unorderedIsTrue, Variable trueValue, Variable falseValue) {
-            super("FLOAT_CMOVE", new Value[] {result}, null, LIRInstruction.NO_OPERANDS, new Value[] {trueValue, falseValue}, LIRInstruction.NO_OPERANDS);
+            this.result = result;
             this.condition = floatCond(condition);
             this.unorderedIsTrue = unorderedIsTrue;
+            this.trueValue = trueValue;
+            this.falseValue = falseValue;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            cmove(tasm, masm, output(0), true, condition, unorderedIsTrue, alive(0), alive(1));
-        }
-
-        @Override
-        public String operationString() {
-            return condition.toString() + " unordered=" + unorderedIsTrue + " " + super.operationString();
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Alive && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            } else if (mode == OperandMode.Alive && index == 1) {
-                return EnumSet.of(OperandFlag.Register);
-            } else if (mode == OperandMode.Output && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            }
-            throw GraalInternalError.shouldNotReachHere();
+            cmove(tasm, masm, result, true, condition, unorderedIsTrue, trueValue, falseValue);
         }
     }
 
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64LIRInstruction.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64LIRInstruction.java	Fri Jun 29 18:33:48 2012 -0700
@@ -22,20 +22,14 @@
  */
 package com.oracle.graal.lir.amd64;
 
-import com.oracle.max.asm.target.amd64.*;
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.max.asm.target.amd64.*;
 
 /**
  * Convenience class to provide AMD64MacroAssembler for the {@link #emitCode} method.
  */
 public abstract class AMD64LIRInstruction extends LIRInstruction {
-
-    public AMD64LIRInstruction(Object opcode, Value[] outputs, LIRDebugInfo info, Value[] inputs, Value[] alives, Value[] temps) {
-        super(opcode, outputs, info, inputs, alives, temps);
-    }
-
     @Override
     public final void emitCode(TargetMethodAssembler tasm) {
         emitCode(tasm, (AMD64MacroAssembler) tasm.asm);
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java	Fri Jun 29 18:33:48 2012 -0700
@@ -23,25 +23,30 @@
 package com.oracle.graal.lir.amd64;
 
 import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 import static java.lang.Double.*;
 import static java.lang.Float.*;
 
-import java.util.*;
-
-import com.oracle.max.asm.*;
-import com.oracle.max.asm.target.amd64.*;
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.StandardOp.*;
+import com.oracle.graal.lir.LIRInstruction.Opcode;
+import com.oracle.graal.lir.StandardOp.MoveOp;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.max.asm.*;
+import com.oracle.max.asm.target.amd64.*;
 
 public class AMD64Move {
 
+    @Opcode("MOVE")
     public static class SpillMoveOp extends AMD64LIRInstruction implements MoveOp {
+        @Def({REG, STACK}) protected Value result;
+        @Use({REG, STACK, CONST}) protected Value input;
+
         public SpillMoveOp(Value result, Value input) {
-            super("MOVE", new Value[] {result}, null, new Value[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+            this.result = result;
+            this.input = input;
         }
 
         @Override
@@ -51,28 +56,23 @@
 
         @Override
         public Value getInput() {
-            return input(0);
+            return input;
         }
         @Override
         public Value getResult() {
-            return output(0);
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
-            } else if (mode == OperandMode.Output && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack);
-            }
-            throw GraalInternalError.shouldNotReachHere();
+            return result;
         }
     }
 
 
+    @Opcode("MOVE")
     public static class MoveToRegOp extends AMD64LIRInstruction implements MoveOp {
+        @Def({REG, HINT}) protected Value result;
+        @Use({REG, STACK, CONST}) protected Value input;
+
         public MoveToRegOp(Value result, Value input) {
-            super("MOVE", new Value[] {result}, null, new Value[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+            this.result = result;
+            this.input = input;
         }
 
         @Override
@@ -82,28 +82,23 @@
 
         @Override
         public Value getInput() {
-            return input(0);
+            return input;
         }
         @Override
         public Value getResult() {
-            return output(0);
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
-            } else if (mode == OperandMode.Output && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.RegisterHint);
-            }
-            throw GraalInternalError.shouldNotReachHere();
+            return result;
         }
     }
 
 
+    @Opcode("MOVE")
     public static class MoveFromRegOp extends AMD64LIRInstruction implements MoveOp {
+        @Def({REG, STACK}) protected Value result;
+        @Use({REG, CONST, HINT}) protected Value input;
+
         public MoveFromRegOp(Value result, Value input) {
-            super("MOVE", new Value[] {result}, null, new Value[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+            this.result = result;
+            this.input = input;
         }
 
         @Override
@@ -113,87 +108,63 @@
 
         @Override
         public Value getInput() {
-            return input(0);
+            return input;
         }
         @Override
         public Value getResult() {
-            return output(0);
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Constant, OperandFlag.RegisterHint);
-            } else if (mode == OperandMode.Output && index == 0) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack);
-            }
-            throw GraalInternalError.shouldNotReachHere();
+            return result;
         }
     }
 
 
     public static class LoadOp extends AMD64LIRInstruction {
-        public LoadOp(Value result, Value address, LIRDebugInfo info) {
-            super("LOAD", new Value[] {result}, info, new Value[] {address}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+        @Def({REG}) protected Value result;
+        @Use({ADDR}) protected Value address;
+        @State protected LIRFrameState state;
+
+        public LoadOp(Value result, Value address, LIRFrameState state) {
+            this.result = result;
+            this.address = address;
+            this.state = state;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            load(tasm, masm, output(0), (Address) input(0), info);
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Address);
-            } else if (mode == OperandMode.Output && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            }
-            throw GraalInternalError.shouldNotReachHere();
+            load(tasm, masm, result, (Address) address, state);
         }
     }
 
 
     public static class StoreOp extends AMD64LIRInstruction {
-        public StoreOp(Value address, Value input, LIRDebugInfo info) {
-            super("STORE", LIRInstruction.NO_OPERANDS, info, new Value[] {address, input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+        @Use({ADDR}) protected Value address;
+        @Use({REG, CONST}) protected Value input;
+        @State protected LIRFrameState state;
+
+        public StoreOp(Value address, Value input, LIRFrameState state) {
+            this.address = address;
+            this.input = input;
+            this.state = state;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            store(tasm, masm, (Address) input(0), input(1), info);
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Address);
-            } else if (mode == OperandMode.Input && index == 1) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Constant);
-            }
-            throw GraalInternalError.shouldNotReachHere();
+            store(tasm, masm, (Address) address, input, state);
         }
     }
 
 
     public static class LeaOp extends AMD64LIRInstruction {
+        @Def({REG}) protected Value result;
+        @Use({ADDR, STACK, UNINITIALIZED}) protected Value address;
+
         public LeaOp(Value result, Value address) {
-            super("LEA", new Value[] {result}, null, new Value[] {address}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+            this.result = result;
+            this.address = address;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            masm.leaq(asLongReg(output(0)), tasm.asAddress(input(0)));
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Address, OperandFlag.Stack, OperandFlag.Uninitialized);
-            } else if (mode == OperandMode.Output && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            }
-            throw GraalInternalError.shouldNotReachHere();
+            masm.leaq(asLongReg(result), tasm.asAddress(address));
         }
     }
 
@@ -202,7 +173,6 @@
         private final int barriers;
 
         public MembarOp(final int barriers) {
-            super("MEMBAR", LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
             this.barriers = barriers;
         }
 
@@ -210,57 +180,43 @@
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
             masm.membar(barriers);
         }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            throw GraalInternalError.shouldNotReachHere();
-        }
     }
 
 
     public static class NullCheckOp extends AMD64LIRInstruction {
-        public NullCheckOp(Variable input, LIRDebugInfo info) {
-            super("NULL_CHECK", LIRInstruction.NO_OPERANDS, info, new Value[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+        @Use protected Value input;
+        @State protected LIRFrameState state;
+
+        public NullCheckOp(Variable input, LIRFrameState state) {
+            this.input = input;
+            this.state = state;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            tasm.recordImplicitException(masm.codeBuffer.position(), info);
-            masm.nullCheck(asRegister(input(0)));
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            }
-            throw GraalInternalError.shouldNotReachHere();
+            tasm.recordImplicitException(masm.codeBuffer.position(), state);
+            masm.nullCheck(asRegister(input));
         }
     }
 
 
+    @Opcode("CAS")
     public static class CompareAndSwapOp extends AMD64LIRInstruction {
+        @Def protected Value result;
+        @Use({ADDR}) protected Value address;
+        @Use protected Value cmpValue;
+        @Use protected Value newValue;
+
         public CompareAndSwapOp(Value result, Address address, Value cmpValue, Value newValue) {
-            super("CAS", new Value[] {result}, null, new Value[] {address, cmpValue, newValue}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+            this.result = result;
+            this.address = address;
+            this.cmpValue = cmpValue;
+            this.newValue = newValue;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-            compareAndSwap(tasm, masm, output(0), asAddress(input(0)), input(1), input(2));
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Input && index == 0) {
-                return EnumSet.of(OperandFlag.Address);
-            } else if (mode == OperandMode.Input && index == 1) {
-                return EnumSet.of(OperandFlag.Register);
-            } else if (mode == OperandMode.Input && index == 2) {
-                return EnumSet.of(OperandFlag.Register);
-            } else if (mode == OperandMode.Output && index == 0) {
-                return EnumSet.of(OperandFlag.Register);
-            }
-            throw GraalInternalError.shouldNotReachHere();
+            compareAndSwap(tasm, masm, result, (Address) address, cmpValue, newValue);
         }
     }
 
@@ -404,7 +360,7 @@
     }
 
 
-    public static void load(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value result, Address loadAddr, LIRDebugInfo info) {
+    public static void load(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value result, Address loadAddr, LIRFrameState info) {
         if (info != null) {
             tasm.recordImplicitException(masm.codeBuffer.position(), info);
         }
@@ -422,7 +378,7 @@
         }
     }
 
-    public static void store(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Address storeAddr, Value input, LIRDebugInfo info) {
+    public static void store(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Address storeAddr, Value input, LIRFrameState info) {
         if (info != null) {
             tasm.recordImplicitException(masm.codeBuffer.position(), info);
         }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Fri Jun 29 18:33:48 2012 -0700
@@ -108,7 +108,7 @@
     public boolean hasDebugInfo() {
         for (Block b : linearScanOrder()) {
             for (LIRInstruction op : b.lir) {
-                if (op.info != null) {
+                if (op.hasState()) {
                     return true;
                 }
             }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRDebugInfo.java	Thu Jun 28 17:39:06 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,129 +0,0 @@
-/*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.lir;
-
-import static com.oracle.graal.api.code.ValueUtil.*;
-
-import java.util.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.lir.LIRInstruction.OperandFlag;
-import com.oracle.graal.lir.LIRInstruction.OperandMode;
-import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
-
-/**
- * This class represents garbage collection and deoptimization information attached to a LIR instruction.
- */
-public class LIRDebugInfo {
-    public final BytecodeFrame topFrame;
-    private final VirtualObject[] virtualObjects;
-    private final List<StackSlot> pointerSlots;
-    public final LabelRef exceptionEdge;
-    private DebugInfo debugInfo;
-
-    public LIRDebugInfo(BytecodeFrame topFrame, VirtualObject[] virtualObjects, List<StackSlot> pointerSlots, LabelRef exceptionEdge) {
-        this.topFrame = topFrame;
-        this.virtualObjects = virtualObjects;
-        this.pointerSlots = pointerSlots;
-        this.exceptionEdge = exceptionEdge;
-    }
-
-    public boolean hasDebugInfo() {
-        return debugInfo != null;
-    }
-
-    public DebugInfo debugInfo() {
-        assert debugInfo != null : "debug info not allocated yet";
-        return debugInfo;
-    }
-
-    /**
-     * Iterates the frame state and calls the {@link ValueProcedure} for every variable.
-     *
-     * @param proc The procedure called for variables.
-     */
-    public void forEachState(ValueProcedure proc) {
-        for (BytecodeFrame cur = topFrame; cur != null; cur = cur.caller()) {
-            processValues(cur.values, proc);
-        }
-        if (virtualObjects != null) {
-            for (VirtualObject obj : virtualObjects) {
-                processValues(obj.values(), proc);
-            }
-        }
-    }
-
-    /**
-     * We filter out constant and illegal values ourself before calling the procedure, so {@link OperandFlag#Constant} and {@link OperandFlag#Illegal} need not be set.
-     */
-    private static final EnumSet<OperandFlag> STATE_FLAGS = EnumSet.of(OperandFlag.Register, OperandFlag.Stack);
-
-    private void processValues(Value[] values, ValueProcedure proc) {
-        for (int i = 0; i < values.length; i++) {
-            Value value = values[i];
-            if (value instanceof MonitorValue) {
-                MonitorValue monitor = (MonitorValue) value;
-                if (processed(monitor.getOwner())) {
-                    monitor.setOwner(proc.doValue(monitor.getOwner(), OperandMode.Alive, STATE_FLAGS));
-                }
-
-            } else if (processed(value)) {
-                values[i] = proc.doValue(value, OperandMode.Alive, STATE_FLAGS);
-            }
-        }
-    }
-
-    private boolean processed(Value value) {
-        if (isIllegal(value)) {
-            // Ignore dead local variables.
-            return false;
-        } else if (isConstant(value)) {
-            // Ignore constants, the register allocator does not need to see them.
-            return false;
-        } else if (isVirtualObject(value)) {
-            assert Arrays.asList(virtualObjects).contains(value);
-            return false;
-        } else {
-            return true;
-        }
-    }
-
-
-    public void finish(BitSet registerRefMap, BitSet frameRefMap, FrameMap frameMap) {
-        debugInfo = new DebugInfo(topFrame, registerRefMap, frameRefMap);
-
-        // Add additional stack slots for outgoing method parameters.
-        if (pointerSlots != null) {
-            for (StackSlot v : pointerSlots) {
-                frameMap.setReference(v, registerRefMap, frameRefMap);
-            }
-        }
-    }
-
-
-    @Override
-    public String toString() {
-        return debugInfo != null ? debugInfo.toString() : topFrame.toString();
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java	Fri Jun 29 18:33:48 2012 -0700
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir;
+
+import static com.oracle.graal.api.code.ValueUtil.*;
+
+import java.util.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.lir.LIRInstruction.OperandFlag;
+import com.oracle.graal.lir.LIRInstruction.OperandMode;
+import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
+
+/**
+ * This class represents garbage collection and deoptimization information attached to a LIR instruction.
+ */
+public class LIRFrameState {
+    public final BytecodeFrame topFrame;
+    private final VirtualObject[] virtualObjects;
+    private final List<StackSlot> pointerSlots;
+    public final LabelRef exceptionEdge;
+    private DebugInfo debugInfo;
+
+    public LIRFrameState(BytecodeFrame topFrame, VirtualObject[] virtualObjects, List<StackSlot> pointerSlots, LabelRef exceptionEdge) {
+        this.topFrame = topFrame;
+        this.virtualObjects = virtualObjects;
+        this.pointerSlots = pointerSlots;
+        this.exceptionEdge = exceptionEdge;
+    }
+
+    public boolean hasDebugInfo() {
+        return debugInfo != null;
+    }
+
+    public DebugInfo debugInfo() {
+        assert debugInfo != null : "debug info not allocated yet";
+        return debugInfo;
+    }
+
+    /**
+     * Iterates the frame state and calls the {@link ValueProcedure} for every variable.
+     *
+     * @param proc The procedure called for variables.
+     */
+    public void forEachState(ValueProcedure proc) {
+        for (BytecodeFrame cur = topFrame; cur != null; cur = cur.caller()) {
+            processValues(cur.values, proc);
+        }
+        if (virtualObjects != null) {
+            for (VirtualObject obj : virtualObjects) {
+                processValues(obj.values(), 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.
+     */
+    private static final EnumSet<OperandFlag> STATE_FLAGS = EnumSet.of(OperandFlag.REG, OperandFlag.STACK);
+
+    private void processValues(Value[] values, ValueProcedure proc) {
+        for (int i = 0; i < values.length; i++) {
+            Value value = values[i];
+            if (value instanceof MonitorValue) {
+                MonitorValue monitor = (MonitorValue) value;
+                if (processed(monitor.getOwner())) {
+                    monitor.setOwner(proc.doValue(monitor.getOwner(), OperandMode.ALIVE, STATE_FLAGS));
+                }
+
+            } else if (processed(value)) {
+                values[i] = proc.doValue(value, OperandMode.ALIVE, STATE_FLAGS);
+            }
+        }
+    }
+
+    private boolean processed(Value value) {
+        if (isIllegal(value)) {
+            // Ignore dead local variables.
+            return false;
+        } else if (isConstant(value)) {
+            // Ignore constants, the register allocator does not need to see them.
+            return false;
+        } else if (isVirtualObject(value)) {
+            assert Arrays.asList(virtualObjects).contains(value);
+            return false;
+        } else {
+            return true;
+        }
+    }
+
+
+    public void finish(BitSet registerRefMap, BitSet frameRefMap, FrameMap frameMap) {
+        debugInfo = new DebugInfo(topFrame, registerRefMap, frameRefMap);
+
+        // Add additional stack slots for outgoing method parameters.
+        if (pointerSlots != null) {
+            for (StackSlot v : pointerSlots) {
+                frameMap.setReference(v, registerRefMap, frameRefMap);
+            }
+        }
+    }
+
+
+    @Override
+    public String toString() {
+        return debugInfo != null ? debugInfo.toString() : topFrame.toString();
+    }
+}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Fri Jun 29 18:33:48 2012 -0700
@@ -22,8 +22,10 @@
  */
 package com.oracle.graal.lir;
 
-import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandMode.*;
 
+import java.lang.annotation.*;
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
@@ -69,6 +71,11 @@
     }
 
 
+    public abstract static class StateProcedure {
+        protected abstract void doState(LIRFrameState state);
+    }
+
+
     /**
      * Constants denoting how a LIR instruction uses an operand.
      */
@@ -79,28 +86,64 @@
          * to a Temp or Output operand. The value can be used again after the instruction, so the instruction must not
          * modify the register.
          */
-        Input,
+        USE,
 
         /**
          * The value must have been defined before. It is alive before the instruction and throughout the instruction. A
          * register assigned to it cannot be assigned to a Temp or Output operand. The value can be used again after the
          * instruction, so the instruction must not modify the register.
          */
-        Alive,
+        ALIVE,
 
         /**
          * The value must not have been defined before, and must not be used after the instruction. The instruction can
          * do whatever it wants with the register assigned to it (or not use it at all).
          */
-        Temp,
+        TEMP,
 
         /**
          * The value must not have been defined before. The instruction has to assign a value to the register. The
          * value can (and most likely will) be used after the instruction.
          */
-        Output,
+        DEF,
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.FIELD)
+    public static @interface Use {
+        OperandFlag[] value() default REG;
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.FIELD)
+    public static @interface Alive {
+        OperandFlag[] value() default REG;
     }
 
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.FIELD)
+    public static @interface Temp {
+        OperandFlag[] value() default REG;
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.FIELD)
+    public static @interface Def {
+        OperandFlag[] value() default REG;
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.FIELD)
+    public static @interface State {
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.TYPE, ElementType.FIELD})
+    public static @interface Opcode {
+        String value() default "";
+    }
+
+
     /**
      * Flags for an operand.
      */
@@ -108,83 +151,61 @@
         /**
          * The value can be a {@link RegisterValue}.
          */
-        Register,
+        REG,
 
         /**
          * The value can be a {@link StackSlot}.
          */
-        Stack,
+        STACK,
 
         /**
          * The value can be a {@link Address}.
          */
-        Address,
+        ADDR,
 
         /**
          * The value can be a {@link Constant}.
          */
-        Constant,
+        CONST,
 
         /**
          * The value can be {@link Value#IllegalValue}.
          */
-        Illegal,
+        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,
+        HINT,
 
         /**
          * The value can be uninitialized, e.g., a stack slot that has not written to before. This is only
          * used to avoid false positives in verification code.
          */
-        Uninitialized,
+        UNINITIALIZED,
     }
 
+
     /**
      * For validity checking of the operand flags defined by instruction subclasses.
      */
-    private static final EnumMap<OperandMode, EnumSet<OperandFlag>> ALLOWED_FLAGS;
+    protected static final EnumMap<OperandMode, EnumSet<OperandFlag>> ALLOWED_FLAGS;
 
     static {
         ALLOWED_FLAGS = new EnumMap<>(OperandMode.class);
-        ALLOWED_FLAGS.put(OperandMode.Input,  EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Address, OperandFlag.Constant, OperandFlag.Illegal, OperandFlag.RegisterHint, OperandFlag.Uninitialized));
-        ALLOWED_FLAGS.put(OperandMode.Alive,  EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Address, OperandFlag.Constant, OperandFlag.Illegal, OperandFlag.RegisterHint, OperandFlag.Uninitialized));
-        ALLOWED_FLAGS.put(OperandMode.Temp,   EnumSet.of(OperandFlag.Register, OperandFlag.Constant, OperandFlag.Illegal, OperandFlag.RegisterHint));
-        ALLOWED_FLAGS.put(OperandMode.Output, EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Illegal, OperandFlag.RegisterHint));
+        ALLOWED_FLAGS.put(USE, EnumSet.of(REG, STACK, ADDR, CONST, ILLEGAL, HINT, UNINITIALIZED));
+        ALLOWED_FLAGS.put(ALIVE, EnumSet.of(REG, STACK, ADDR, CONST, ILLEGAL, HINT, UNINITIALIZED));
+        ALLOWED_FLAGS.put(TEMP,  EnumSet.of(REG, CONST, ILLEGAL, HINT));
+        ALLOWED_FLAGS.put(DEF, EnumSet.of(REG, STACK, ILLEGAL, HINT));
     }
 
     /**
-     * The opcode of this instruction.
-     */
-    protected final Object code;
-
-    /**
-     * The output operands for this instruction (modified by the register allocator).
+     * The flags of the base and index value of an address.
      */
-    protected Value[] outputs;
-
-    /**
-     * The input operands for this instruction (modified by the register allocator).
-     */
-    protected Value[] inputs;
+    protected static final EnumSet<OperandFlag> ADDRESS_FLAGS = EnumSet.of(REG, ILLEGAL);
 
-    /**
-     * The alive operands for this instruction (modified by the register allocator).
-     */
-    protected Value[] alives;
-
-    /**
-     * The temp operands for this instruction (modified by the register allocator).
-     */
-    protected Value[] temps;
-
-    /**
-     * Used to emit debug information.
-     */
-    public final LIRDebugInfo info;
+    private final LIRInstructionClass instructionClass;
 
     /**
      * Instruction id for register allocation.
@@ -192,22 +213,11 @@
     private int id;
 
     /**
-     * Constructs a new LIR instruction that has input and temp operands.
-     *
-     * @param opcode the opcode of the new instruction
-     * @param outputs the operands that holds the operation results of this instruction.
-     * @param info the {@link LIRDebugInfo} info that is to be preserved for the instruction. This will be {@code null} when no debug info is required for the instruction.
-     * @param inputs the input operands for the instruction.
-     * @param temps the temp operands for the instruction.
+     * Constructs a new LIR instruction.
      */
-    public LIRInstruction(Object opcode, Value[] outputs, LIRDebugInfo info, Value[] inputs, Value[] alives, Value[] temps) {
-        this.code = opcode;
-        this.outputs = outputs;
-        this.inputs = inputs;
-        this.alives = alives;
-        this.temps = temps;
-        this.info = info;
-        this.id = -1;
+    public LIRInstruction() {
+        instructionClass = LIRInstructionClass.get(getClass());
+        id = -1;
     }
 
     public abstract void emitCode(TargetMethodAssembler tasm);
@@ -222,100 +232,18 @@
     }
 
     /**
-     * Gets an input operand of this instruction.
-     *
-     * @param index the index of the operand requested.
-     * @return the {@code index}'th input operand.
-     */
-    protected final Value input(int index) {
-        return inputs[index];
-    }
-
-    /**
-     * Gets an alive operand of this instruction.
-     *
-     * @param index the index of the operand requested.
-     * @return the {@code index}'th alive operand.
-     */
-    protected final Value alive(int index) {
-        return alives[index];
-    }
-
-    /**
-     * Gets a temp operand of this instruction.
-     *
-     * @param index the index of the operand requested.
-     * @return the {@code index}'th temp operand.
-     */
-    protected final Value temp(int index) {
-        return temps[index];
-    }
-
-    /**
-     * Gets the result operand for this instruction.
-     *
-     * @return return the result operand
-     */
-    protected final Value output(int index) {
-        return outputs[index];
-    }
-
-    /**
      * Gets the instruction name.
      */
-    public String name() {
-        return code.toString();
+    public final String name() {
+        return instructionClass.getOpcode(this);
     }
 
-    public boolean hasOperands() {
-        return inputs.length > 0 || alives.length > 0 || temps.length > 0 || outputs.length > 0 || info != null || hasCall();
-    }
-
-    private static final EnumSet<OperandFlag> ADDRESS_FLAGS = EnumSet.of(OperandFlag.Register, OperandFlag.Illegal);
-
-    private void forEach(Value[] values, OperandMode mode, ValueProcedure proc) {
-        for (int i = 0; i < values.length; i++) {
-            assert ALLOWED_FLAGS.get(mode).containsAll(flagsFor(mode, i));
-
-            Value value = values[i];
-            if (isAddress(value)) {
-                assert flagsFor(mode, i).contains(OperandFlag.Address);
-                Address address = asAddress(value);
-                address.setBase(proc.doValue(address.getBase(), mode, ADDRESS_FLAGS));
-                address.setIndex(proc.doValue(address.getIndex(), mode, ADDRESS_FLAGS));
-            } else {
-                values[i] = proc.doValue(values[i], mode, flagsFor(mode, i));
-            }
-        }
+    public final boolean hasOperands() {
+        return instructionClass.hasOperands() || hasState() || hasCall();
     }
 
-    public final void forEachInput(ValueProcedure proc) {
-        forEach(inputs, OperandMode.Input, proc);
-    }
-
-    public final void forEachAlive(ValueProcedure proc) {
-        forEach(alives, OperandMode.Alive, proc);
-    }
-
-    public final void forEachTemp(ValueProcedure proc) {
-        forEach(temps, OperandMode.Temp, proc);
-    }
-
-    public final void forEachOutput(ValueProcedure proc) {
-        forEach(outputs, OperandMode.Output, proc);
-    }
-
-    public final void forEachState(ValueProcedure proc) {
-        if (info != null) {
-            info.forEachState(proc);
-
-            if (this instanceof LIRXirInstruction) {
-                LIRXirInstruction xir = (LIRXirInstruction) this;
-                if (xir.infoAfter != null) {
-                    xir.infoAfter.forEachState(proc);
-                }
-            }
-        }
+    public final boolean hasState() {
+        return instructionClass.hasState(this);
     }
 
     /**
@@ -325,6 +253,31 @@
         return this instanceof StandardOp.CallOp;
     }
 
+
+    public final void forEachInput(ValueProcedure proc) {
+        instructionClass.forEachUse(this, proc);
+    }
+
+    public final void forEachAlive(ValueProcedure proc) {
+        instructionClass.forEachAlive(this, proc);
+    }
+
+    public final void forEachTemp(ValueProcedure proc) {
+        instructionClass.forEachTemp(this, proc);
+    }
+
+    public final void forEachOutput(ValueProcedure proc) {
+        instructionClass.forEachDef(this, proc);
+    }
+
+    public final void forEachState(ValueProcedure proc) {
+        instructionClass.forEachState(this, proc);
+    }
+
+    public final void forEachState(StateProcedure proc) {
+        instructionClass.forEachState(this, proc);
+    }
+
     /**
      * Iterates all register hints for the specified value, i.e., all preferred candidates for the register to be
      * assigned to the value.
@@ -339,32 +292,9 @@
      * @return The non-null value returned by the procedure, or null.
      */
     public Value forEachRegisterHint(Value value, OperandMode mode, ValueProcedure proc) {
-        Value[] 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++) {
-            Value result = proc.doValue(hints[i], null, null);
-            if (result != null) {
-                return result;
-            }
-        }
-        return null;
+        return instructionClass.forEachRegisterHint(this, mode, proc);
     }
 
-    /**
-     * 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.
-     */
-    // TODO (cwimmer) this method will go away when we have named operands, the flags will be specified as annotations instead.
-    protected abstract EnumSet<OperandFlag> flagsFor(OperandMode mode, int index);
 
     protected void verify() {
     }
@@ -377,72 +307,8 @@
         return "     " + toString();
     }
 
-    /**
-     * Gets the operation performed by this instruction in terms of its operands as a string.
-     */
-    public String operationString() {
-        StringBuilder buf = new StringBuilder();
-        String sep = "";
-        if (outputs.length > 1) {
-            buf.append("(");
-        }
-        for (Value output : outputs) {
-            buf.append(sep).append(output);
-            sep = ", ";
-        }
-        if (outputs.length > 1) {
-            buf.append(")");
-        }
-        if (outputs.length > 0) {
-            buf.append(" = ");
-        }
-
-        if (inputs.length + alives.length != 1) {
-            buf.append("(");
-        }
-        sep = "";
-        for (Value input : inputs) {
-            buf.append(sep).append(input);
-            sep = ", ";
-        }
-        for (Value input : alives) {
-            buf.append(sep).append(input).append(" ~");
-            sep = ", ";
-        }
-        if (inputs.length + alives.length != 1) {
-            buf.append(")");
-        }
-
-        if (temps.length > 0) {
-            buf.append(" [");
-        }
-        sep = "";
-        for (Value temp : temps) {
-            buf.append(sep).append(temp);
-            sep = ", ";
-        }
-        if (temps.length > 0) {
-            buf.append("]");
-        }
-        return buf.toString();
-    }
-
-    protected void appendDebugInfo(StringBuilder buf) {
-        if (info != null) {
-            buf.append(" [bci:");
-            String sep = "";
-            for (BytecodeFrame cur = info.topFrame; cur != null; cur = cur.caller()) {
-                buf.append(sep).append(cur.getBCI());
-                sep = ",";
-            }
-            buf.append("]");
-        }
-    }
-
     @Override
     public String toString() {
-        StringBuilder buf = new StringBuilder(name()).append(' ').append(operationString());
-        appendDebugInfo(buf);
-        return buf.toString();
+        return instructionClass.toString(this);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java	Fri Jun 29 18:33:48 2012 -0700
@@ -0,0 +1,608 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir;
+import static com.oracle.graal.api.code.ValueUtil.*;
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.Map.Entry;
+import java.util.concurrent.*;
+
+import sun.misc.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.LIRInstruction.OperandFlag;
+import com.oracle.graal.lir.LIRInstruction.OperandMode;
+import com.oracle.graal.lir.LIRInstruction.StateProcedure;
+import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
+
+public class LIRInstructionClass {
+    // TODO(cwimmer) factor out the common methods of this class and NodeClass into a base class.
+
+    /**
+     * Interface used by {@link LIRInstructionClass#rescanAllFieldOffsets(CalcOffset)} to determine the offset (in bytes) of a field.
+     */
+    public interface CalcOffset {
+        long getOffset(Field field);
+    }
+
+    private static final Unsafe unsafe = getUnsafe();
+
+    private static Unsafe getUnsafe() {
+        try {
+            // this will only fail if graal is not part of the boot class path
+            return Unsafe.getUnsafe();
+        } catch (SecurityException e) {
+            // nothing to do
+        }
+        try {
+            Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
+            theUnsafeInstance.setAccessible(true);
+            return (Unsafe) theUnsafeInstance.get(Unsafe.class);
+        } catch (Exception e) {
+            // currently we rely on being able to use Unsafe...
+            throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e);
+        }
+    }
+
+    static class DefaultCalcOffset implements CalcOffset {
+        @Override
+        public long getOffset(Field field) {
+            return unsafe.objectFieldOffset(field);
+        }
+    }
+
+    private static final Class<?> INSTRUCTION_CLASS = LIRInstruction.class;
+    private static final Class<?> VALUE_CLASS = Value.class;
+    private static final Class<?> VALUE_ARRAY_CLASS = Value[].class;
+    private static final Class<?> STATE_CLASS = LIRFrameState.class;
+
+
+    private static final ConcurrentHashMap<Class< ? >, LIRInstructionClass> classes = new ConcurrentHashMap<>();
+
+    private final Class< ? > clazz;
+    private final int directUseCount;
+    private final long[] useOffsets;
+    private final EnumSet<OperandFlag>[] useFlags;
+    private final int directAliveCount;
+    private final long[] aliveOffsets;
+    private final EnumSet<OperandFlag>[] aliveFlags;
+    private final int directTempCount;
+    private final long[] tempOffsets;
+    private final EnumSet<OperandFlag>[] tempFlags;
+    private final int directDefCount;
+    private final long[] defOffsets;
+    private final EnumSet<OperandFlag>[] defFlags;
+
+    private final long[] stateOffsets;
+    private final long[] dataOffsets;
+
+    private final Map<Long, String> fieldNames;
+    private final Map<Long, Class<?>> fieldTypes;
+
+    private String opcodeConstant;
+    private long opcodeOffset;
+
+    @SuppressWarnings("unchecked")
+    public LIRInstructionClass(Class<?> clazz) {
+        assert INSTRUCTION_CLASS.isAssignableFrom(clazz);
+        this.clazz = clazz;
+
+        FieldScanner scanner = new FieldScanner(new DefaultCalcOffset());
+        scanner.scan(clazz);
+
+        OperandModeAnnotation mode = scanner.valueAnnotations.get(LIRInstruction.Use.class);
+        directUseCount = mode.scalarOffsets.size();
+        useOffsets = sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets);
+        useFlags = arrayUsingSortedOffsets(mode.flags, useOffsets, new EnumSet[useOffsets.length]);
+
+        mode = scanner.valueAnnotations.get(LIRInstruction.Alive.class);
+        directAliveCount = mode.scalarOffsets.size();
+        aliveOffsets = sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets);
+        aliveFlags = arrayUsingSortedOffsets(mode.flags, aliveOffsets, new EnumSet[aliveOffsets.length]);
+
+        mode = scanner.valueAnnotations.get(LIRInstruction.Temp.class);
+        directTempCount = mode.scalarOffsets.size();
+        tempOffsets = sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets);
+        tempFlags = arrayUsingSortedOffsets(mode.flags, tempOffsets, new EnumSet[tempOffsets.length]);
+
+        mode = scanner.valueAnnotations.get(LIRInstruction.Def.class);
+        directDefCount = mode.scalarOffsets.size();
+        defOffsets = sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets);
+        defFlags = arrayUsingSortedOffsets(mode.flags, defOffsets, new EnumSet[defOffsets.length]);
+
+        stateOffsets = sortedLongCopy(scanner.stateOffsets);
+        dataOffsets = sortedLongCopy(scanner.dataOffsets);
+
+        fieldNames = scanner.fieldNames;
+        fieldTypes = scanner.fieldTypes;
+
+        opcodeConstant = scanner.opcodeConstant;
+        opcodeOffset = scanner.opcodeOffset;
+    }
+
+    public static void rescanAllFieldOffsets(CalcOffset calc) {
+        for (LIRInstructionClass nodeClass : classes.values()) {
+            nodeClass.rescanFieldOffsets(calc);
+        }
+    }
+
+    private void rescanFieldOffsets(CalcOffset calc) {
+        FieldScanner scanner = new FieldScanner(calc);
+        scanner.scan(clazz);
+
+        OperandModeAnnotation mode = scanner.valueAnnotations.get(LIRInstruction.Use.class);
+        copyInto(useOffsets, sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets));
+        mode = scanner.valueAnnotations.get(LIRInstruction.Alive.class);
+        copyInto(aliveOffsets, sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets));
+        mode = scanner.valueAnnotations.get(LIRInstruction.Temp.class);
+        copyInto(tempOffsets, sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets));
+        mode = scanner.valueAnnotations.get(LIRInstruction.Def.class);
+        copyInto(defOffsets, sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets));
+
+        copyInto(stateOffsets, sortedLongCopy(scanner.stateOffsets));
+        copyInto(dataOffsets, sortedLongCopy(scanner.dataOffsets));
+
+        fieldNames.clear();
+        fieldNames.putAll(scanner.fieldNames);
+        fieldTypes.clear();
+        fieldTypes.putAll(scanner.fieldTypes);
+
+        opcodeConstant = scanner.opcodeConstant;
+        opcodeOffset = scanner.opcodeOffset;
+    }
+
+    private static void copyInto(long[] dest, long[] src) {
+        assert dest.length == src.length;
+        for (int i = 0; i < dest.length; i++) {
+            dest[i] = src[i];
+        }
+    }
+
+    public static final LIRInstructionClass get(Class<?> c) {
+        LIRInstructionClass clazz = classes.get(c);
+        if (clazz != null) {
+            return clazz;
+        }
+
+        // We can have a race of multiple threads creating the LIRInstructionClass at the same time.
+        // However, only one will be put into the map, and this is the one returned by all threads.
+        clazz = new LIRInstructionClass(c);
+        LIRInstructionClass oldClazz = classes.putIfAbsent(c, clazz);
+        if (oldClazz != null) {
+            return oldClazz;
+        } else {
+            return clazz;
+        }
+    }
+
+
+    private static class OperandModeAnnotation {
+        public final ArrayList<Long> scalarOffsets = new ArrayList<>();
+        public final ArrayList<Long> arrayOffsets = new ArrayList<>();
+        public final Map<Long, EnumSet<OperandFlag>> flags = new HashMap<>();
+    }
+
+    private static class FieldScanner {
+        public final CalcOffset calc;
+
+        public final Map<Class<? extends Annotation>, OperandModeAnnotation> valueAnnotations;
+        public final ArrayList<Long> stateOffsets = new ArrayList<>();
+        public final ArrayList<Long> dataOffsets = new ArrayList<>();
+
+        public final Map<Long, String> fieldNames = new HashMap<>();
+        public final Map<Long, Class<?>> fieldTypes = new HashMap<>();
+
+        private String opcodeConstant;
+        private long opcodeOffset;
+
+        public FieldScanner(CalcOffset calc) {
+            this.calc = calc;
+
+            valueAnnotations = new HashMap<>();
+            valueAnnotations.put(LIRInstruction.Use.class, new OperandModeAnnotation()); //LIRInstruction.Use.class));
+            valueAnnotations.put(LIRInstruction.Alive.class, new OperandModeAnnotation()); //LIRInstruction.Alive.class));
+            valueAnnotations.put(LIRInstruction.Temp.class, new OperandModeAnnotation()); //LIRInstruction.Temp.class));
+            valueAnnotations.put(LIRInstruction.Def.class, new OperandModeAnnotation()); //LIRInstruction.Def.class));
+        }
+
+        private OperandModeAnnotation getOperandModeAnnotation(Field field) {
+            OperandModeAnnotation result = null;
+            for (Entry<Class<? extends Annotation>, OperandModeAnnotation> entry  : valueAnnotations.entrySet()) {
+                Annotation annotation = field.getAnnotation(entry.getKey());
+                if (annotation != null) {
+                    assert result == null : "Field has two operand mode annotations: " + field;
+                    result = entry.getValue();
+                }
+            }
+            return result;
+        }
+
+        private static EnumSet<OperandFlag> getFlags(Field field) {
+            EnumSet<OperandFlag> result = EnumSet.noneOf(OperandFlag.class);
+            // Unfortunately, annotations cannot have class hierarchies or implement interfaces, so we have to duplicate the code for every operand mode.
+            // Unfortunately, annotations cannot have an EnumSet property, so we have to convert from arrays to EnumSet manually.
+            if (field.isAnnotationPresent(LIRInstruction.Use.class)) {
+                result.addAll(Arrays.asList(field.getAnnotation(LIRInstruction.Use.class).value()));
+            } else if (field.isAnnotationPresent(LIRInstruction.Alive.class)) {
+                result.addAll(Arrays.asList(field.getAnnotation(LIRInstruction.Alive.class).value()));
+            } else if (field.isAnnotationPresent(LIRInstruction.Temp.class)) {
+                result.addAll(Arrays.asList(field.getAnnotation(LIRInstruction.Temp.class).value()));
+            } else if (field.isAnnotationPresent(LIRInstruction.Def.class)) {
+                result.addAll(Arrays.asList(field.getAnnotation(LIRInstruction.Def.class).value()));
+            } else {
+                GraalInternalError.shouldNotReachHere();
+            }
+            return result;
+        }
+
+        public void scan(Class<?> clazz) {
+            if (clazz.getAnnotation(LIRInstruction.Opcode.class) != null) {
+                opcodeConstant = clazz.getAnnotation(LIRInstruction.Opcode.class).value();
+            }
+            opcodeOffset = -1;
+
+            Class<?> currentClazz = clazz;
+            do {
+                for (Field field : currentClazz.getDeclaredFields()) {
+                    if (Modifier.isStatic(field.getModifiers())) {
+                        continue;
+                    }
+
+                    Class< ? > type = field.getType();
+                    long offset = calc.getOffset(field);
+
+                    if (VALUE_CLASS.isAssignableFrom(type)) {
+                        assert Modifier.isProtected(field.getModifiers()) && !Modifier.isFinal(field.getModifiers()) : "Value field must not be declared final or private because it is modified by register allocator: " + field;
+                        OperandModeAnnotation annotation = getOperandModeAnnotation(field);
+                        assert annotation != null : "Field must have operand mode annotation: " + field;
+                        annotation.scalarOffsets.add(offset);
+                        annotation.flags.put(offset, getFlags(field));
+                    } else if (VALUE_ARRAY_CLASS.isAssignableFrom(type)) {
+                        OperandModeAnnotation annotation = getOperandModeAnnotation(field);
+                        assert annotation != null : "Field must have operand mode annotation: " + field;
+                        annotation.arrayOffsets.add(offset);
+                        annotation.flags.put(offset, getFlags(field));
+                    } else if (STATE_CLASS.isAssignableFrom(type)) {
+                        assert getOperandModeAnnotation(field) == null : "Field must not have operand mode annotation: " + field;
+                        assert field.getAnnotation(LIRInstruction.State.class) != null : "Field must have state annotation: " + field;
+                        stateOffsets.add(offset);
+                    } else {
+                        assert getOperandModeAnnotation(field) == null : "Field must not have operand mode annotation: " + field;
+                        assert field.getAnnotation(LIRInstruction.State.class) == null : "Field must not have state annotation: " + field;
+                        dataOffsets.add(offset);
+                    }
+                    fieldNames.put(offset, field.getName());
+                    fieldTypes.put(offset, type);
+
+                    if (field.getAnnotation(LIRInstruction.Opcode.class) != null) {
+                        assert opcodeConstant == null && opcodeOffset == -1 : "Can have only one Opcode definition: " + clazz;
+                        opcodeOffset = offset;
+                    }
+                }
+                currentClazz = currentClazz.getSuperclass();
+            } while (currentClazz != LIRInstruction.class);
+
+            if (opcodeConstant == null && opcodeOffset == -1) {
+                opcodeConstant = clazz.getSimpleName();
+                if (opcodeConstant.endsWith("Op")) {
+                    opcodeConstant = opcodeConstant.substring(0, opcodeConstant.length() - 2);
+                }
+            }
+        }
+    }
+
+    private static <T> T[] arrayUsingSortedOffsets(Map<Long, T> map, long[] sortedOffsets, T[] result) {
+        for (int i = 0; i < sortedOffsets.length; i++) {
+            result[i] = map.get(sortedOffsets[i]);
+        }
+        return result;
+    }
+
+    private static long[] sortedLongCopy(ArrayList<Long> list1) {
+        Collections.sort(list1);
+        long[] result = new long[list1.size()];
+        for (int i = 0; i < list1.size(); i++) {
+            result[i] = list1.get(i);
+        }
+        return result;
+    }
+
+    private static long[] sortedLongCopy(ArrayList<Long> list1, ArrayList<Long> list2) {
+        Collections.sort(list1);
+        Collections.sort(list2);
+        long[] result = new long[list1.size() + list2.size()];
+        for (int i = 0; i < list1.size(); i++) {
+            result[i] = list1.get(i);
+        }
+        for (int i = 0; i < list2.size(); i++) {
+            result[list1.size() + i] = list2.get(i);
+        }
+        return result;
+    }
+
+
+    @Override
+    public String toString() {
+        StringBuilder str = new StringBuilder();
+        str.append(getClass().getSimpleName()).append(" ").append(clazz.getSimpleName()).append(" use[");
+        for (int i = 0; i < useOffsets.length; i++) {
+            str.append(i == 0 ? "" : ", ").append(useOffsets[i]);
+        }
+        str.append("] alive[");
+        for (int i = 0; i < aliveOffsets.length; i++) {
+            str.append(i == 0 ? "" : ", ").append(aliveOffsets[i]);
+        }
+        str.append("] temp[");
+        for (int i = 0; i < tempOffsets.length; i++) {
+            str.append(i == 0 ? "" : ", ").append(tempOffsets[i]);
+        }
+        str.append("] def[");
+        for (int i = 0; i < defOffsets.length; i++) {
+            str.append(i == 0 ? "" : ", ").append(defOffsets[i]);
+        }
+        str.append("] state[");
+        for (int i = 0; i < stateOffsets.length; i++) {
+            str.append(i == 0 ? "" : ", ").append(stateOffsets[i]);
+        }
+        str.append("] data[");
+        for (int i = 0; i < dataOffsets.length; i++) {
+            str.append(i == 0 ? "" : ", ").append(dataOffsets[i]);
+        }
+        str.append("]");
+        return str.toString();
+    }
+
+
+    public final String getOpcode(LIRInstruction obj) {
+        if (opcodeConstant != null) {
+            return opcodeConstant;
+        }
+        assert opcodeOffset != -1;
+        return unsafe.getObject(obj, opcodeOffset).toString();
+    }
+
+    public final boolean hasOperands() {
+        return useOffsets.length > 0 || aliveOffsets.length > 0 || tempOffsets.length > 0 || defOffsets.length > 0;
+    }
+
+    public final boolean hasState(LIRInstruction obj) {
+        for (int i = 0; i < stateOffsets.length; i++) {
+            if (getState(obj, stateOffsets[i]) != null) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public final void forEachUse(LIRInstruction obj, ValueProcedure proc) {
+        forEach(obj, directUseCount, useOffsets, OperandMode.USE, useFlags, proc);
+    }
+
+    public final void forEachAlive(LIRInstruction obj, ValueProcedure proc) {
+        forEach(obj, directAliveCount, aliveOffsets, OperandMode.ALIVE, aliveFlags, proc);
+    }
+
+    public final void forEachTemp(LIRInstruction obj, ValueProcedure proc) {
+        forEach(obj, directTempCount, tempOffsets, OperandMode.TEMP, tempFlags, proc);
+    }
+
+    public final void forEachDef(LIRInstruction obj, ValueProcedure proc) {
+        forEach(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]);
+            if (state != null) {
+                state.forEachState(proc);
+            }
+        }
+    }
+
+    public final void forEachState(LIRInstruction obj, StateProcedure proc) {
+        for (int i = 0; i < stateOffsets.length; i++) {
+            LIRFrameState state = getState(obj, stateOffsets[i]);
+            if (state != null) {
+                proc.doState(state);
+            }
+        }
+    }
+
+    private static void forEach(LIRInstruction obj, int directCount, long[] offsets, OperandMode mode, EnumSet<OperandFlag>[] flags, ValueProcedure 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 (isAddress(value)) {
+                    doAddress(asAddress(value), mode, flags[i], proc);
+                } else {
+                    setValue(obj, offsets[i], proc.doValue(value, mode, flags[i]));
+                }
+            } else {
+                Value[] values = getValueArray(obj, offsets[i]);
+                for (int j = 0; j < values.length; j++) {
+                    Value value = values[j];
+                    if (isAddress(value)) {
+                        doAddress(asAddress(value), mode, flags[i], proc);
+                    } else {
+                        values[j] = proc.doValue(value, mode, flags[i]);
+                    }
+                }
+            }
+        }
+    }
+
+    private static void doAddress(Address address, OperandMode mode, EnumSet<OperandFlag> flags, ValueProcedure proc) {
+        assert flags.contains(OperandFlag.ADDR);
+        address.setBase(proc.doValue(address.getBase(), mode, LIRInstruction.ADDRESS_FLAGS));
+        address.setIndex(proc.doValue(address.getIndex(), mode, LIRInstruction.ADDRESS_FLAGS));
+    }
+
+    public final Value forEachRegisterHint(LIRInstruction obj, OperandMode mode, ValueProcedure proc) {
+        int hintDirectCount = 0;
+        long[] hintOffsets = null;
+        if (mode == OperandMode.USE) {
+            hintDirectCount = directDefCount;
+            hintOffsets = defOffsets;
+        } else if (mode == OperandMode.DEF) {
+            hintDirectCount = directUseCount;
+            hintOffsets = useOffsets;
+        } else {
+            return null;
+        }
+
+        for (int i = 0; i < hintOffsets.length; i++) {
+            if (i < hintDirectCount) {
+                Value hintValue = getValue(obj, hintOffsets[i]);
+                Value result = proc.doValue(hintValue, null, null);
+                if (result != null) {
+                    return result;
+                }
+            } else {
+                Value[] hintValues = getValueArray(obj, hintOffsets[i]);
+                for (int j = 0; j < hintValues.length; j++) {
+                    Value hintValue = hintValues[j];
+                    Value result = proc.doValue(hintValue, null, null);
+                    if (result != null) {
+                        return result;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    private static Value getValue(LIRInstruction obj, long offset) {
+        return (Value) unsafe.getObject(obj, offset);
+    }
+
+    private static void setValue(LIRInstruction obj, long offset, Value value) {
+        unsafe.putObject(obj, offset, value);
+    }
+
+    private static Value[] getValueArray(LIRInstruction obj, long offset) {
+        return (Value[]) unsafe.getObject(obj, offset);
+    }
+
+    private static LIRFrameState getState(LIRInstruction obj, long offset) {
+        return (LIRFrameState) unsafe.getObject(obj, offset);
+    }
+
+
+    public String toString(LIRInstruction obj) {
+        StringBuilder result = new StringBuilder();
+
+        appendValues(result, obj, "", " = ", "(", ")", new String[] {""}, defOffsets);
+        result.append(getOpcode(obj).toUpperCase());
+        appendValues(result, obj, " ", "", "(", ")", new String[] {"", "~"}, useOffsets, aliveOffsets);
+        appendValues(result, obj, " ", "", "{", "}", new String[] {""}, tempOffsets);
+
+        for (int i = 0; i < dataOffsets.length; i++) {
+            if (dataOffsets[i] == opcodeOffset) {
+                continue;
+            }
+            result.append(" ").append(fieldNames.get(dataOffsets[i])).append(": ").append(getFieldString(obj, dataOffsets[i]));
+        }
+
+        for (int i = 0; i < stateOffsets.length; i++) {
+            LIRFrameState state = getState(obj, stateOffsets[i]);
+            if (state != null) {
+                result.append(" ").append(fieldNames.get(stateOffsets[i])).append(" [bci:");
+                String sep = "";
+                for (BytecodeFrame cur = state.topFrame; cur != null; cur = cur.caller()) {
+                    result.append(sep).append(cur.getBCI());
+                    sep = ", ";
+                }
+                result.append("]");
+            }
+        }
+
+        return result.toString();
+    }
+
+    private void appendValues(StringBuilder result, LIRInstruction obj, String start, String end, String startMultiple, String endMultiple, String[] prefix, long[]...moffsets) {
+        int total = 0;
+        for (long[] offsets : moffsets) {
+            total += offsets.length;
+        }
+        if (total == 0) {
+            return;
+        }
+
+        result.append(start);
+        if (total > 1) {
+            result.append(startMultiple);
+        }
+        String sep = "";
+        for (int i = 0; i < moffsets.length; i++) {
+            long[] offsets = moffsets[i];
+
+            for (int j = 0; j < offsets.length; j++) {
+                result.append(sep).append(prefix[i]);
+                long offset = offsets[j];
+                if (total > 1) {
+                    result.append(fieldNames.get(offset)).append(": ");
+                }
+                result.append(getFieldString(obj, offset));
+                sep = ", ";
+            }
+        }
+        if (total > 1) {
+            result.append(endMultiple);
+        }
+        result.append(end);
+    }
+
+    private String getFieldString(Object obj, long offset) {
+        Class<?> type = fieldTypes.get(offset);
+        if (type == int.class) {
+            return String.valueOf(unsafe.getInt(obj, offset));
+        } else if (type == long.class) {
+            return String.valueOf(unsafe.getLong(obj, offset));
+        } else if (type == boolean.class) {
+            return String.valueOf(unsafe.getBoolean(obj, offset));
+        } else if (type == float.class) {
+            return String.valueOf(unsafe.getFloat(obj, offset));
+        } else if (type == double.class) {
+            return String.valueOf(unsafe.getDouble(obj, offset));
+        } else if (!type.isPrimitive()) {
+            Object value = unsafe.getObject(obj, offset);
+            if (!type.isArray()) {
+                return String.valueOf(value);
+            } else if (type == int[].class) {
+                return Arrays.toString((int[]) value);
+            } else if (type == double[].class) {
+                return Arrays.toString((double[]) value);
+            } else if (!type.getComponentType().isPrimitive()) {
+                return Arrays.toString((Object[]) value);
+            }
+        }
+        assert false : "unhandled field type: " + type;
+        return "";
+    }
+}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java	Fri Jun 29 18:33:48 2012 -0700
@@ -171,7 +171,7 @@
 
         } else if (isAllocatableRegister(value)) {
             int regNum = asRegister(value).number;
-            if (mode == OperandMode.Alive) {
+            if (mode == OperandMode.ALIVE) {
                 curRegistersDefined.set(regNum);
             }
 
@@ -202,7 +202,7 @@
             assert curInstruction != null;
             variableDefinitions[variableIdx] = curInstruction;
             assert !curVariablesLive.get(variableIdx);
-            if (mode == OperandMode.Output) {
+            if (mode == OperandMode.DEF) {
                 curVariablesLive.set(variableIdx);
             }
 
@@ -216,7 +216,7 @@
             curRegistersDefined.set(regNum);
 
             if (beforeRegisterAllocation) {
-                if (mode == OperandMode.Output) {
+                if (mode == OperandMode.DEF) {
                     curRegistersLive[regNum] = value;
                 } else {
                     curRegistersLive[regNum] = null;
@@ -227,11 +227,11 @@
     }
 
     private static Value allowed(Object op, Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
-        if ((isVariable(value)  && flags.contains(OperandFlag.Register)) ||
-            (isRegister(value)  && flags.contains(OperandFlag.Register)) ||
-            (isStackSlot(value) && flags.contains(OperandFlag.Stack)) ||
-            (isConstant(value)  && flags.contains(OperandFlag.Constant) && mode != OperandMode.Output) ||
-            (isIllegal(value)   && flags.contains(OperandFlag.Illegal))) {
+        if ((isVariable(value)  && flags.contains(OperandFlag.REG)) ||
+            (isRegister(value)  && flags.contains(OperandFlag.REG)) ||
+            (isStackSlot(value) && flags.contains(OperandFlag.STACK)) ||
+            (isConstant(value)  && flags.contains(OperandFlag.CONST) && mode != OperandMode.DEF) ||
+            (isIllegal(value)   && flags.contains(OperandFlag.ILLEGAL))) {
             return value;
         }
         TTY.println("instruction %s", op);
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRXirInstruction.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRXirInstruction.java	Fri Jun 29 18:33:48 2012 -0700
@@ -23,39 +23,47 @@
 package com.oracle.graal.lir;
 
 import static com.oracle.graal.api.code.ValueUtil.*;
-
-import java.util.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
+import com.oracle.graal.api.meta.*;
 import com.oracle.max.cri.xir.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
 
 public abstract class LIRXirInstruction extends LIRInstruction {
+    @Opcode protected final String opcode;
+    @Def({REG, ILLEGAL}) protected Value outputOperand;
+    @Alive({REG, CONST, ILLEGAL}) protected Value[] inputs;
+    @Temp({REG, CONST, ILLEGAL}) protected Value[] temps;
+    @State protected LIRFrameState state;
+    @State protected LIRFrameState stateAfter;
 
-    public final Value[] originalOperands;
+    // Defined as Object[] so that the magic processing of Value[] does not complain this field is not annotated.
+    public final Object[] originalOperands;
+
     public final int outputOperandIndex;
     public final int[] inputOperandIndices;
     public final int[] tempOperandIndices;
     public final XirSnippet snippet;
-    public final LIRDebugInfo infoAfter;
     public final LabelRef trueSuccessor;
     public final LabelRef falseSuccessor;
 
-    public LIRXirInstruction(Object opcode,
-                             XirSnippet snippet,
+    public LIRXirInstruction(XirSnippet snippet,
                              Value[] originalOperands,
                              Value outputOperand,
                              Value[] inputs, Value[] temps,
                              int[] inputOperandIndices, int[] tempOperandIndices,
                              int outputOperandIndex,
-                             LIRDebugInfo info,
-                             LIRDebugInfo infoAfter,
+                             LIRFrameState state,
+                             LIRFrameState stateAfter,
                              LabelRef trueSuccessor,
                              LabelRef falseSuccessor) {
         // Note that we register the XIR input operands as Alive, because the XIR specification allows that input operands
         // are used at any time, even when the temp operands and the actual output operands have already be assigned.
-        super(opcode, isLegal(outputOperand) ? new Value[] {outputOperand} : LIRInstruction.NO_OPERANDS, info, LIRInstruction.NO_OPERANDS, inputs, temps);
-        this.infoAfter = infoAfter;
+        this.opcode = "XIR: " + snippet.template;
+        this.outputOperand = outputOperand;
+        this.inputs = inputs;
+        this.temps = temps;
+        this.state = state;
+        this.stateAfter = stateAfter;
         this.snippet = snippet;
         this.inputOperandIndices = inputOperandIndices;
         this.tempOperandIndices = tempOperandIndices;
@@ -66,31 +74,16 @@
         assert isLegal(outputOperand) || outputOperandIndex == -1;
     }
 
-    @Override
-    protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-        if (mode == OperandMode.Alive || mode == OperandMode.Temp) {
-            return EnumSet.of(OperandFlag.Register, OperandFlag.Constant, OperandFlag.Illegal);
-        } else if (mode == OperandMode.Output && index == 0) {
-            return EnumSet.of(OperandFlag.Register);
-        }
-        throw GraalInternalError.shouldNotReachHere();
-    }
-
     public Value[] getOperands() {
         for (int i = 0; i < inputOperandIndices.length; i++) {
-            originalOperands[inputOperandIndices[i]] = alive(i);
+            originalOperands[inputOperandIndices[i]] = inputs[i];
         }
         for (int i = 0; i < tempOperandIndices.length; i++) {
-            originalOperands[tempOperandIndices[i]] = temp(i);
+            originalOperands[tempOperandIndices[i]] = temps[i];
         }
         if (outputOperandIndex != -1) {
-            originalOperands[outputOperandIndex] = output(0);
+            originalOperands[outputOperandIndex] = outputOperand;
         }
-        return originalOperands;
-    }
-
-    @Override
-    public String name() {
-        return "XIR: " + snippet.template;
+        return (Value[]) originalOperands;
     }
 }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Fri Jun 29 18:33:48 2012 -0700
@@ -22,12 +22,10 @@
  */
 package com.oracle.graal.lir;
 
-import java.util.*;
-
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.lir.asm.*;
 import com.oracle.max.asm.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.lir.asm.*;
+import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
 
 /**
  * A collection of machine-independent LIR operations, as well as interfaces to be implemented for specific kinds or LIR
@@ -54,16 +52,11 @@
         private final Label label;
         private final boolean align;
 
-        protected LabelOp(Object opcode, Value[] outputs, LIRDebugInfo info, Value[] inputs, Value[] alives, Value[] temps, Label label, boolean align) {
-            super(opcode, outputs, info, inputs, alives, temps);
+        public LabelOp(Label label, boolean align) {
             this.label = label;
             this.align = align;
         }
 
-        public LabelOp(Label label, boolean align) {
-            this("LABEL", LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, label, align);
-        }
-
         @Override
         public void emitCode(TargetMethodAssembler tasm) {
             if (align) {
@@ -72,40 +65,25 @@
             tasm.asm.bind(label);
         }
 
-        @Override
-        public String operationString() {
-            return label.toString() + " " + super.operationString();
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            throw GraalInternalError.shouldNotReachHere();
-        }
-
         public Label getLabel() {
             return label;
         }
     }
 
     public static class PhiLabelOp extends LabelOp {
-        public PhiLabelOp(Label label, boolean align, Value[] phiDefinitions) {
-            super("PHI_LABEL", phiDefinitions, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, label, align);
-        }
+        @Def({REG, STACK}) protected Value[] phiDefinitions;
 
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Output) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack);
-            }
-            throw GraalInternalError.shouldNotReachHere();
+        public PhiLabelOp(Label label, boolean align, Value[] phiDefinitions) {
+            super(label, align);
+            this.phiDefinitions = phiDefinitions;
         }
 
         public void markResolved() {
-            outputs = EMPTY;
+            phiDefinitions = EMPTY;
         }
 
         public Value[] getPhiDefinitions() {
-            return outputs;
+            return phiDefinitions;
         }
     }
 
@@ -118,14 +96,11 @@
      */
     public static class JumpOp extends LIRInstruction {
         private final LabelRef destination;
+        @State protected LIRFrameState state;
 
-        protected JumpOp(Object opcode, Value[] outputs, LIRDebugInfo info, Value[] inputs, Value[] alives, Value[] temps, LabelRef destination) {
-            super(opcode, outputs, info, inputs, alives, temps);
+        public JumpOp(LabelRef destination, LIRFrameState state) {
             this.destination = destination;
-        }
-
-        public JumpOp(LabelRef destination, LIRDebugInfo info) {
-            this("JUMP", LIRInstruction.NO_OPERANDS, info, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, destination);
+            this.state = state;
         }
 
         @Override
@@ -133,40 +108,25 @@
             tasm.asm.jmp(destination.label());
         }
 
-        @Override
-        public String operationString() {
-            return  destination + " " + super.operationString();
-        }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            throw GraalInternalError.shouldNotReachHere();
-        }
-
         public LabelRef destination() {
             return destination;
         }
     }
 
     public static class PhiJumpOp extends JumpOp {
-        public PhiJumpOp(LabelRef destination, Value[] phiInputs) {
-            super("PHI_JUMP", LIRInstruction.NO_OPERANDS, null, LIRInstruction.NO_OPERANDS, phiInputs, LIRInstruction.NO_OPERANDS, destination);
-        }
+        @Alive({REG, STACK, CONST}) protected Value[] phiInputs;
 
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Alive) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack, OperandFlag.Constant);
-            }
-            throw GraalInternalError.shouldNotReachHere();
+        public PhiJumpOp(LabelRef destination, Value[] phiInputs) {
+            super(destination, null);
+            this.phiInputs = phiInputs;
         }
 
         public void markResolved() {
-            alives = EMPTY;
+            phiInputs = EMPTY;
         }
 
         public Value[] getPhiInputs() {
-            return alives;
+            return phiInputs;
         }
     }
 
@@ -200,21 +160,15 @@
      * In particular, it is not the actual method prologue.
      */
     public static final class ParametersOp extends LIRInstruction {
+        @Def({REG, STACK}) protected Value[] params;
+
         public ParametersOp(Value[] params) {
-            super("PARAMS", params, null, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+            this.params = params;
         }
 
         @Override
         public void emitCode(TargetMethodAssembler tasm) {
             // No code to emit.
         }
-
-        @Override
-        protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-            if (mode == OperandMode.Output) {
-                return EnumSet.of(OperandFlag.Register, OperandFlag.Stack);
-            }
-            throw GraalInternalError.shouldNotReachHere();
-        }
     }
 }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java	Fri Jun 29 18:33:48 2012 -0700
@@ -159,7 +159,7 @@
         return targetMethod;
     }
 
-    public void recordExceptionHandlers(int pcOffset, LIRDebugInfo info) {
+    public void recordExceptionHandlers(int pcOffset, LIRFrameState info) {
         if (info != null) {
             if (info.exceptionEdge != null) {
                 if (exceptionInfoList == null) {
@@ -170,7 +170,7 @@
         }
     }
 
-    public void recordImplicitException(int pcOffset, LIRDebugInfo info) {
+    public void recordImplicitException(int pcOffset, LIRFrameState info) {
         // record an implicit exception point
         if (info != null) {
             assert lastSafepointPos < pcOffset : lastSafepointPos + "<" + pcOffset;
@@ -180,21 +180,21 @@
         }
     }
 
-    public void recordDirectCall(int posBefore, int posAfter, Object callTarget, LIRDebugInfo info) {
+    public void recordDirectCall(int posBefore, int posAfter, Object callTarget, LIRFrameState info) {
         DebugInfo debugInfo = info != null ? info.debugInfo() : null;
         assert lastSafepointPos < posAfter;
         lastSafepointPos = posAfter;
         targetMethod.recordCall(posBefore, posAfter - posBefore, callTarget, debugInfo, true);
     }
 
-    public void recordIndirectCall(int posBefore, int posAfter, Object callTarget, LIRDebugInfo info) {
+    public void recordIndirectCall(int posBefore, int posAfter, Object callTarget, LIRFrameState info) {
         DebugInfo debugInfo = info != null ? info.debugInfo() : null;
         assert lastSafepointPos < posAfter;
         lastSafepointPos = posAfter;
         targetMethod.recordCall(posBefore, posAfter - posBefore, callTarget, debugInfo, false);
     }
 
-    public void recordSafepoint(int pos, LIRDebugInfo info) {
+    public void recordSafepoint(int pos, LIRFrameState info) {
         // safepoints always need debug info
         DebugInfo debugInfo = info.debugInfo();
         assert lastSafepointPos < pos;
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Fri Jun 29 18:33:48 2012 -0700
@@ -432,18 +432,21 @@
             LIRInstruction inst = lirInstructions.get(i);
             out.printf("nr %4d ", inst.id()).print(COLUMN_END);
 
-            if (inst.info != null) {
+            final StringBuilder stateString = new StringBuilder();
+            inst.forEachState(new LIRInstruction.StateProcedure() {
+                @Override
+                protected void doState(LIRFrameState state) {
+                    if (state.hasDebugInfo()) {
+                        stateString.append(debugInfoToString(state.debugInfo().getBytecodePosition(), state.debugInfo().getRegisterRefMap(), state.debugInfo().getFrameRefMap(), target.arch));
+                    } else {
+                        stateString.append(debugInfoToString(state.topFrame, null, null, target.arch));
+                    }
+                }
+            });
+            if (stateString.length() > 0) {
                 int level = out.indentationLevel();
                 out.adjustIndentation(-level);
-                String state;
-                if (inst.info.hasDebugInfo()) {
-                    state = debugInfoToString(inst.info.debugInfo().getBytecodePosition(), inst.info.debugInfo().getRegisterRefMap(), inst.info.debugInfo().getFrameRefMap(), target.arch);
-                } else {
-                    state = debugInfoToString(inst.info.topFrame, null, null, target.arch);
-                }
-                if (state != null) {
-                    out.print(" st ").print(HOVER_START).print("st").print(HOVER_SEP).print(state).print(HOVER_END).print(COLUMN_END);
-                }
+                out.print(" st ").print(HOVER_START).print("st").print(HOVER_SEP).print(stateString.toString()).print(HOVER_END).print(COLUMN_END);
                 out.adjustIndentation(level);
             }
 
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/MathIntrinsicNode.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/MathIntrinsicNode.java	Fri Jun 29 18:33:48 2012 -0700
@@ -66,12 +66,12 @@
         Variable result = gen.newVariable(kind());
         switch (operation()) {
             case ABS:   gen.append(new Op2Reg(DAND, result, input, Constant.forDouble(Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL)))); break;
-            case SQRT:  gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.Opcode.SQRT, result, input)); break;
-            case LOG:   gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.Opcode.LOG, result, input)); break;
-            case LOG10: gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.Opcode.LOG10, result, input)); break;
-            case SIN:   gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.Opcode.SIN, result, input)); break;
-            case COS:   gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.Opcode.COS, result, input)); break;
-            case TAN:   gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.Opcode.TAN, result, input)); break;
+            case SQRT:  gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.SQRT, result, input)); break;
+            case LOG:   gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.LOG, result, input)); break;
+            case LOG10: gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.LOG10, result, input)); break;
+            case SIN:   gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.SIN, result, input)); break;
+            case COS:   gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.COS, result, input)); break;
+            case TAN:   gen.append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.TAN, result, input)); break;
             default:    throw GraalInternalError.shouldNotReachHere();
         }
         gen.setResult(this, result);
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/target/amd64/AMD64MathIntrinsicOp.java	Thu Jun 28 17:39:06 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/target/amd64/AMD64MathIntrinsicOp.java	Fri Jun 29 18:33:48 2012 -0700
@@ -24,32 +24,31 @@
 
 import static com.oracle.graal.api.code.ValueUtil.*;
 
-import java.util.*;
-
-import com.oracle.max.asm.target.amd64.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
+import com.oracle.max.asm.target.amd64.*;
 
 public class AMD64MathIntrinsicOp extends AMD64LIRInstruction {
-    public enum Opcode  {
+    public enum IntrinsicOpcode  {
         SQRT,
         SIN, COS, TAN,
         LOG, LOG10;
     }
 
-    public AMD64MathIntrinsicOp(Opcode opcode, Value result, Value input) {
-        super(opcode, new Value[] {result}, null, new Value[] {input}, LIRInstruction.NO_OPERANDS, LIRInstruction.NO_OPERANDS);
+    @Opcode private final IntrinsicOpcode opcode;
+    @Def protected Value result;
+    @Use protected Value input;
+
+    public AMD64MathIntrinsicOp(IntrinsicOpcode opcode, Value result, Value input) {
+        this.opcode = opcode;
+        this.result = result;
+        this.input = input;
     }
 
     @Override
     public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-        Opcode opcode = (Opcode) code;
-        Value result = output(0);
-        Value input = input(0);
-
         switch (opcode) {
             case SQRT:  masm.sqrtsd(asDoubleReg(result), asDoubleReg(input)); break;
             case LOG:   masm.flog(asDoubleReg(result), asDoubleReg(input), false); break;
@@ -60,14 +59,4 @@
             default:    throw GraalInternalError.shouldNotReachHere();
         }
     }
-
-    @Override
-    protected EnumSet<OperandFlag> flagsFor(OperandMode mode, int index) {
-        if (mode == OperandMode.Input && index == 0) {
-            return EnumSet.of(OperandFlag.Register);
-        } else if (mode == OperandMode.Output && index == 0) {
-            return EnumSet.of(OperandFlag.Register);
-        }
-        throw GraalInternalError.shouldNotReachHere();
-    }
 }