changeset 15001:27c04ee36dcb

input types
author Lukas Stadler <lukas.stadler@oracle.com>
date Mon, 07 Apr 2014 11:32:04 +0200
parents cc844a4512f1
children 06e50d290784
files graal/com.oracle.graal.graph/src/com/oracle/graal/graph/InputType.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PreWriteBarrier.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/WriteBarrier.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractBeginNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractDeoptimizeNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractStateSplit.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConditionAnchorNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingGuardedNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardPhiNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardProxyNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNegationNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopExitNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryProxyNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ShortCircuitOrNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractWriteNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/DeferredForeignCallNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedAccessNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaReadNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SnippetLocationNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/AllocatedObjectNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java
diffstat 61 files changed, 294 insertions(+), 164 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/InputType.java	Mon Apr 07 11:32:04 2014 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2014, 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.graph;
+
+public enum InputType {
+    /**
+     * Inputs that consume an actual value generated by the referenced node.
+     */
+    Value,
+    /**
+     * Inputs that consume the memory state of the referenced node.
+     */
+    Memory,
+    /**
+     * Inputs that reference a condition.
+     */
+    Condition,
+    /**
+     * Inputs that reference a frame state.
+     */
+    State,
+    /**
+     * Inputs that reference a guard (guards, begin nodes).
+     */
+    Guard,
+    /**
+     * Inputs that reference an anchor (begin nodes, value anchors).
+     */
+    Anchor,
+    /**
+     * Inputs that represent an association between nodes, e.g., a phi and the merge or a loop begin
+     * and loop exits and ends.
+     */
+    Association,
+    /**
+     * Inputs of this type are temporarily exempt from type checking. This should only be used in
+     * exceptional cases and should never survive to later stages of compilation.
+     */
+    Unchecked
+}
\ No newline at end of file
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Mon Apr 07 11:32:04 2014 +0200
@@ -44,9 +44,9 @@
  * this field points to.
  * <p>
  * Nodes which are be value numberable should implement the {@link ValueNumberable} interface.
- * 
+ *
  * <h1>Assertions and Verification</h1>
- * 
+ *
  * The Node class supplies the {@link #assertTrue(boolean, String, Object...)} and
  * {@link #assertFalse(boolean, String, Object...)} methods, which will check the supplied boolean
  * and throw a VerificationError if it has the wrong value. Both methods will always either throw an
@@ -67,8 +67,7 @@
     @Retention(RetentionPolicy.RUNTIME)
     @Target(ElementType.FIELD)
     public static @interface Input {
-
-        boolean notDataflow() default false;
+        InputType value() default InputType.Value;
     }
 
     @Retention(RetentionPolicy.RUNTIME)
@@ -166,7 +165,7 @@
     /**
      * Returns an {@link NodeClassIterable iterable} which can be used to traverse all non-null
      * input edges of this node.
-     * 
+     *
      * @return an {@link NodeClassIterable iterable} for all non-null input edges.
      */
     public NodeClassIterable inputs() {
@@ -176,7 +175,7 @@
     /**
      * Returns an {@link NodeClassIterable iterable} which can be used to traverse all non-null
      * successor edges of this node.
-     * 
+     *
      * @return an {@link NodeClassIterable iterable} for all non-null successor edges.
      */
     public NodeClassIterable successors() {
@@ -288,7 +287,7 @@
     /**
      * Finds the index of the last non-null entry in a node array. The search assumes that all
      * non-null entries precede the first null entry in the array.
-     * 
+     *
      * @param nodes the array to search
      * @return the index of the last non-null entry in {@code nodes} if it exists, else -1
      */
@@ -321,7 +320,7 @@
 
     /**
      * Adds a given node to this node's {@linkplain #usages() usages}.
-     * 
+     *
      * @param node the node to add
      */
     private void addUsage(Node node) {
@@ -352,7 +351,7 @@
 
     /**
      * Removes a given node from this node's {@linkplain #usages() usages}.
-     * 
+     *
      * @param node the node to remove
      * @return whether or not {@code usage} was in the usage list
      */
@@ -536,6 +535,19 @@
         clearUsages();
     }
 
+    public void replaceAtUsages(InputType type, Node other) {
+        assert checkReplaceWith(other);
+        for (Node usage : usages().snapshot()) {
+            NodeClassIterator iter = usage.inputs().iterator();
+            while (iter.hasNext()) {
+                Position pos = iter.nextPosition();
+                if (pos.getInputType(usage) == type) {
+                    pos.set(usage, other);
+                }
+            }
+        }
+    }
+
     private void maybeNotifyChanged(Node usage) {
         if (graph != null) {
             assert !graph.isFrozen();
@@ -656,7 +668,7 @@
      * Must be overridden by subclasses that implement {@link Canonicalizable}. The implementation
      * in {@link Node} exists to obviate the need to cast a node before invoking
      * {@link Canonicalizable#canonical(CanonicalizerTool)}.
-     * 
+     *
      * @param tool
      */
     public Node canonical(CanonicalizerTool tool) {
@@ -667,7 +679,7 @@
      * Must be overridden by subclasses that implement {@link Simplifiable}. The implementation in
      * {@link Node} exists to obviate the need to cast a node before invoking
      * {@link Simplifiable#simplify(SimplifierTool)}.
-     * 
+     *
      * @param tool
      */
     public void simplify(SimplifierTool tool) {
@@ -797,7 +809,7 @@
      * Fills a {@link Map} with properties of this node for use in debugging (e.g., to view in the
      * ideal graph visualizer). Subclasses overriding this method should also fill the map using
      * their superclass.
-     * 
+     *
      * @param map
      */
     public Map<Object, Object> getDebugProperties(Map<Object, Object> map) {
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Mon Apr 07 11:32:04 2014 +0200
@@ -47,7 +47,7 @@
 
     /**
      * Maps {@link Class} values (for {@link Node} types) to {@link NodeClass} values.
-     * 
+     *
      * Only a single Registry instance can be created. If a runtime creates a specialized registry,
      * it must do so before the class initializer of {@link NodeClass} is executed.
      */
@@ -101,7 +101,7 @@
 
         /**
          * Hook for a subclass to be notified of a new mapping added to the registry.
-         * 
+         *
          * @param key
          * @param value
          */
@@ -136,8 +136,11 @@
 
     private final int directInputCount;
     private final long[] inputOffsets;
+    private final InputType[] inputTypes;
+    private final String[] inputNames;
     private final int directSuccessorCount;
     private final long[] successorOffsets;
+    private final String[] successorNames;
     private final Class<?>[] dataTypes;
     private final boolean canGVN;
     private final boolean isLeafNode;
@@ -175,8 +178,21 @@
 
         directInputCount = scanner.inputOffsets.size();
         inputOffsets = sortedLongCopy(scanner.inputOffsets, scanner.inputListOffsets);
+        inputTypes = new InputType[inputOffsets.length];
+        inputNames = new String[inputOffsets.length];
+        for (int i = 0; i < inputOffsets.length; i++) {
+            inputTypes[i] = scanner.types.get(inputOffsets[i]);
+            inputNames[i] = scanner.names.get(inputOffsets[i]);
+            assert inputTypes[i] != null;
+            assert inputNames[i] != null;
+        }
         directSuccessorCount = scanner.successorOffsets.size();
         successorOffsets = sortedLongCopy(scanner.successorOffsets, scanner.successorListOffsets);
+        successorNames = new String[successorOffsets.length];
+        for (int i = 0; i < successorOffsets.length; i++) {
+            successorNames[i] = scanner.names.get(successorOffsets[i]);
+            assert successorNames[i] != null;
+        }
 
         dataOffsets = sortedLongCopy(scanner.dataOffsets);
         dataTypes = new Class[dataOffsets.length];
@@ -304,6 +320,8 @@
         public final ArrayList<Long> inputListOffsets = new ArrayList<>();
         public final ArrayList<Long> successorOffsets = new ArrayList<>();
         public final ArrayList<Long> successorListOffsets = new ArrayList<>();
+        public final HashMap<Long, InputType> types = new HashMap<>();
+        public final HashMap<Long, String> names = new HashMap<>();
 
         protected FieldScanner(CalcOffset calc) {
             super(calc);
@@ -313,6 +331,7 @@
         protected void scanField(Field field, Class<?> type, long offset) {
             if (field.isAnnotationPresent(Node.Input.class)) {
                 assert !field.isAnnotationPresent(Node.Successor.class) : "field cannot be both input and successor";
+                Input inputAnnotation = field.getAnnotation(Node.Input.class);
                 if (INPUT_LIST_CLASS.isAssignableFrom(type)) {
                     GraalInternalError.guarantee(Modifier.isFinal(field.getModifiers()), "NodeInputList input field %s should be final", field);
                     GraalInternalError.guarantee(!Modifier.isPublic(field.getModifiers()), "NodeInputList input field %s should not be public", field);
@@ -323,7 +342,9 @@
                     GraalInternalError.guarantee(Modifier.isPrivate(field.getModifiers()), "Node input field %s should be private", field);
                     inputOffsets.add(offset);
                 }
-                if (field.getAnnotation(Node.Input.class).notDataflow()) {
+                types.put(offset, inputAnnotation.value());
+                names.put(offset, field.getName());
+                if (inputAnnotation.value() != InputType.Value) {
                     fieldNames.put(offset, field.getName() + "#NDF");
                 }
             } else if (field.isAnnotationPresent(Node.Successor.class)) {
@@ -337,6 +358,7 @@
                     GraalInternalError.guarantee(Modifier.isPrivate(field.getModifiers()), "Node successor field %s should be private", field);
                     successorOffsets.add(offset);
                 }
+                names.put(offset, field.getName());
             } else {
                 GraalInternalError.guarantee(!NODE_CLASS.isAssignableFrom(type) || field.getName().equals("Null"), "suspicious node field: %s", field);
                 GraalInternalError.guarantee(!INPUT_LIST_CLASS.isAssignableFrom(type), "suspicious node input list field: %s", field);
@@ -367,7 +389,7 @@
 
     /**
      * Describes an edge slot for a {@link NodeClass}.
-     * 
+     *
      * @see NodeClass#get(Node, Position)
      * @see NodeClass#getName(Position)
      */
@@ -392,6 +414,14 @@
             return node.getNodeClass().get(node, this);
         }
 
+        public InputType getInputType(Node node) {
+            return node.getNodeClass().getInputType(this);
+        }
+
+        public String getInputName(Node node) {
+            return node.getNodeClass().getEdgeName(this);
+        }
+
         public void set(Node node, Node value) {
             node.getNodeClass().set(node, this, value);
         }
@@ -458,7 +488,7 @@
      * of the fields are treated as {@link NodeList}s. All elements of these NodeLists will be
      * visited by the iterator as well. This iterator can be used to iterate over the inputs or
      * successors of a node.
-     * 
+     *
      * An iterator of this type will not return null values, unless the field values are modified
      * concurrently. Concurrent modifications are detected by an assertion on a best-effort basis.
      */
@@ -469,7 +499,7 @@
 
         /**
          * Creates an iterator that will iterate over fields in the given node.
-         * 
+         *
          * @param node the node which contains the fields.
          */
         NodeClassIterator(Node node) {
@@ -761,7 +791,7 @@
 
     /**
      * Populates a given map with the names and values of all data fields.
-     * 
+     *
      * @param node the node from which to take the values.
      * @param properties a map that will be populated.
      */
@@ -922,6 +952,15 @@
         }
     }
 
+    public InputType getInputType(Position pos) {
+        assert pos.input;
+        return inputTypes[pos.index];
+    }
+
+    public String getEdgeName(Position pos) {
+        return pos.input ? inputNames[pos.index] : successorNames[pos.index];
+    }
+
     public NodeList<?> getNodeList(Node node, Position pos) {
         long offset = pos.input ? inputOffsets[pos.index] : successorOffsets[pos.index];
         assert pos.subIndex == NODE_LIST;
@@ -1128,7 +1167,7 @@
      * Clear all inputs in the given node. This is accomplished by setting input fields to null and
      * replacing input lists with new lists. (which is important so that this method can be used to
      * clear the inputs of cloned nodes.)
-     * 
+     *
      * @param node the node to be cleared
      */
     public void clearInputs(Node node) {
@@ -1148,7 +1187,7 @@
      * Clear all successors in the given node. This is accomplished by setting successor fields to
      * null and replacing successor lists with new lists. (which is important so that this method
      * can be used to clear the successors of cloned nodes.)
-     * 
+     *
      * @param node the node to be cleared
      */
     public void clearSuccessors(Node node) {
@@ -1167,7 +1206,7 @@
     /**
      * Copies the inputs from node to newNode. The nodes are expected to be of the exact same
      * NodeClass type.
-     * 
+     *
      * @param node the node from which the inputs should be copied.
      * @param newNode the node to which the inputs should be copied.
      */
@@ -1189,7 +1228,7 @@
     /**
      * Copies the successors from node to newNode. The nodes are expected to be of the exact same
      * NodeClass type.
-     * 
+     *
      * @param node the node from which the successors should be copied.
      * @param newNode the node to which the successors should be copied.
      */
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PreWriteBarrier.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/G1PreWriteBarrier.java	Mon Apr 07 11:32:04 2014 +0200
@@ -22,12 +22,13 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 
 public class G1PreWriteBarrier extends WriteBarrier implements DeoptimizingNode.DeoptBefore {
 
-    @Input private FrameState stateBefore;
+    @Input(InputType.State) private FrameState stateBefore;
     private final boolean nullCheck;
     private final boolean doLoad;
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TailcallNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -31,6 +31,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.gen.*;
 import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.nodes.*;
@@ -43,12 +44,12 @@
  */
 public class TailcallNode extends FixedWithNextNode implements LIRGenResLowerable {
 
-    @Input private FrameState frameState;
+    @Input(InputType.State) private FrameState frameState;
     @Input private ValueNode target;
 
     /**
      * Creates a TailcallNode.
-     * 
+     *
      * @param target points to the start of an nmethod
      * @param frameState the parameters will be taken from this FrameState
      */
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/WriteBarrier.java	Mon Apr 07 11:32:04 2014 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -31,7 +32,7 @@
 
     @Input private ValueNode object;
     @Input private ValueNode value;
-    @Input private LocationNode location;
+    @Input(InputType.Association) private LocationNode location;
     private final boolean precise;
 
     public WriteBarrier(ValueNode object, ValueNode value, LocationNode location, boolean precise) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractBeginNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractBeginNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -35,7 +35,7 @@
 
 public abstract class AbstractBeginNode extends FixedWithNextNode implements StateSplit, LIRLowerable, Simplifiable, GuardingNode, IterableNodeType {
 
-    @Input(notDataflow = true) private FrameState stateAfter;
+    @Input(InputType.State) private FrameState stateAfter;
 
     public FrameState stateAfter() {
         return stateAfter;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractDeoptimizeNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractDeoptimizeNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -34,7 +34,7 @@
  */
 public abstract class AbstractDeoptimizeNode extends ControlSinkNode implements IterableNodeType, DeoptimizingNode.DeoptBefore {
 
-    @Input private FrameState stateBefore;
+    @Input(InputType.State) private FrameState stateBefore;
 
     public AbstractDeoptimizeNode() {
         super(StampFactory.forVoid());
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.type.*;
@@ -30,7 +31,7 @@
 
 public abstract class AbstractFixedGuardNode extends DeoptimizingFixedWithNextNode implements Simplifiable, GuardingNode {
 
-    @Input private LogicNode condition;
+    @Input(InputType.Condition) private LogicNode condition;
     private final DeoptimizationReason reason;
     private final DeoptimizationAction action;
     private boolean negated;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractStateSplit.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractStateSplit.java	Mon Apr 07 11:32:04 2014 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.type.*;
 
 /**
@@ -29,7 +30,7 @@
  */
 public abstract class AbstractStateSplit extends FixedWithNextNode implements StateSplit {
 
-    @Input(notDataflow = true) private FrameState stateAfter;
+    @Input(InputType.State) private FrameState stateAfter;
 
     public FrameState stateAfter() {
         return stateAfter;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConditionAnchorNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConditionAnchorNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -31,7 +31,7 @@
 @NodeInfo(nameTemplate = "ConditionAnchor(!={p#negated})")
 public final class ConditionAnchorNode extends FixedWithNextNode implements Canonicalizable, Lowerable, GuardingNode {
 
-    @Input private LogicNode condition;
+    @Input(InputType.Condition) private LogicNode condition;
     private boolean negated;
 
     public ConditionAnchorNode(LogicNode condition) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizingFixedWithNextNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -22,11 +22,12 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.type.*;
 
 public abstract class DeoptimizingFixedWithNextNode extends FixedWithNextNode implements DeoptimizingNode.DeoptBefore {
 
-    @Input(notDataflow = true) private FrameState stateBefore;
+    @Input(InputType.State) private FrameState stateBefore;
 
     public DeoptimizingFixedWithNextNode(Stamp stamp) {
         super(stamp);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingGuardedNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FloatingGuardedNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -22,13 +22,14 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.type.*;
 
 public abstract class FloatingGuardedNode extends FloatingNode implements GuardedNode {
 
-    @Input private GuardingNode guard;
+    @Input(InputType.Anchor) private GuardingNode guard;
 
     public FloatingGuardedNode(Stamp stamp) {
         super(stamp);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FrameState.java	Mon Apr 07 11:32:04 2014 +0200
@@ -34,7 +34,7 @@
 /**
  * The {@code FrameState} class encapsulates the frame state (i.e. local variables and operand
  * stack) at a particular point in the abstract interpretation.
- * 
+ *
  * This can be used as debug or deoptimization information.
  */
 @NodeInfo(nameTemplate = "FrameState@{p#method/s}:{p#bci}")
@@ -80,16 +80,16 @@
      */
     public static final int INVALID_FRAMESTATE_BCI = -5;
 
-    @Input private FrameState outerFrameState;
+    @Input(InputType.State) private FrameState outerFrameState;
 
     /**
      * Contains the locals, the expressions and the locked objects, in this order.
      */
     @Input private final NodeInputList<ValueNode> values;
 
-    @Input private final NodeInputList<MonitorIdNode> monitorIds;
+    @Input(InputType.Association) private final NodeInputList<MonitorIdNode> monitorIds;
 
-    @Input private final NodeInputList<EscapeObjectState> virtualObjectMappings;
+    @Input(InputType.State) private final NodeInputList<EscapeObjectState> virtualObjectMappings;
 
     /**
      * The bytecode index to which this frame state applies.
@@ -100,7 +100,7 @@
 
     /**
      * Creates a {@code FrameState} with the given locals, stack expressions and locked monitors.
-     * 
+     *
      * @param method the method for this frame state
      * @param bci the bytecode index of the frame state
      * @param values the locals, stack expressions and locked objects, in this order
@@ -130,7 +130,7 @@
 
     /**
      * Simple constructor used to create marker FrameStates.
-     * 
+     *
      * @param bci marker bci, needs to be &lt; 0
      */
     public FrameState(int bci) {
@@ -306,7 +306,7 @@
 
     /**
      * Gets the value in the local variables at the specified index.
-     * 
+     *
      * @param i the index into the locals
      * @return the instruction that produced the value for the specified local
      */
@@ -317,7 +317,7 @@
 
     /**
      * Get the value on the stack at the specified stack index.
-     * 
+     *
      * @param i the index into the stack, with {@code 0} being the bottom of the stack
      * @return the instruction at the specified position in the stack
      */
@@ -328,7 +328,7 @@
 
     /**
      * Get the monitor owner at the specified index.
-     * 
+     *
      * @param i the index into the list of locked monitors.
      * @return the lock owner at the given index.
      */
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -43,7 +43,7 @@
 @NodeInfo(nameTemplate = "Guard(!={p#negated}) {p#reason/s}")
 public class GuardNode extends FloatingGuardedNode implements Canonicalizable, IterableNodeType, GuardingNode, GuardedNode {
 
-    @Input private LogicNode condition;
+    @Input(InputType.Condition) private LogicNode condition;
     private final DeoptimizationReason reason;
     private Constant speculation;
     private DeoptimizationAction action;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardPhiNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardPhiNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -29,7 +29,7 @@
 @NodeInfo(nameTemplate = "GuardPhi({i#values})")
 public class GuardPhiNode extends PhiNode implements GuardingNode {
 
-    @Input final NodeInputList<ValueNode> values = new NodeInputList<>(this);
+    @Input(InputType.Guard) final NodeInputList<ValueNode> values = new NodeInputList<>(this);
 
     public GuardPhiNode(MergeNode merge) {
         super(StampFactory.dependency(), merge);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardProxyNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardProxyNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -22,12 +22,13 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.type.*;
 
 public class GuardProxyNode extends ProxyNode implements GuardingNode {
 
-    @Input private ValueNode value;
+    @Input(InputType.Guard) private ValueNode value;
 
     public GuardProxyNode(ValueNode value, AbstractBeginNode proxyPoint) {
         super(StampFactory.dependency(), proxyPoint);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardedValueNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -32,10 +32,10 @@
 /**
  * A node that changes the type of its input, usually narrowing it. For example, a GuardedValueNode
  * is used to keep the nodes depending on guards inside a loop during speculative guard movement.
- * 
+ *
  * A GuardedValueNode will only go away if its guard is null or {@link StructuredGraph#start()}.
  */
-public class GuardedValueNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, IterableNodeType, GuardingNode, Canonicalizable, ValueProxy {
+public class GuardedValueNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, IterableNodeType, Canonicalizable, ValueProxy {
 
     @Input private ValueNode object;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -34,10 +34,10 @@
  * A node that changes the stamp of its input based on some condition being true.
  */
 @NodeInfo(nameTemplate = "GuardingPi(!={p#negated}) {p#reason/s}")
-public class GuardingPiNode extends FixedWithNextNode implements Lowerable, Virtualizable, GuardingNode, Canonicalizable, ValueProxy {
+public class GuardingPiNode extends FixedWithNextNode implements Lowerable, Virtualizable, Canonicalizable, ValueProxy {
 
     @Input private ValueNode object;
-    @Input private LogicNode condition;
+    @Input(InputType.Condition) private LogicNode condition;
     private final DeoptimizationReason reason;
     private final DeoptimizationAction action;
     private boolean negated;
@@ -59,7 +59,7 @@
 
     /**
      * Creates a guarding pi node.
-     * 
+     *
      * @param object the object whose type is refined if this guard succeeds
      * @param condition the condition to test
      * @param negateCondition the guard succeeds if {@code condition != negateCondition}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -46,7 +46,7 @@
 
     @Successor private AbstractBeginNode trueSuccessor;
     @Successor private AbstractBeginNode falseSuccessor;
-    @Input private LogicNode condition;
+    @Input(InputType.Condition) private LogicNode condition;
     private double trueSuccessorProbability;
 
     public LogicNode condition() {
@@ -73,7 +73,7 @@
 
     /**
      * Gets the true successor.
-     * 
+     *
      * @return the true successor
      */
     public AbstractBeginNode trueSuccessor() {
@@ -82,7 +82,7 @@
 
     /**
      * Gets the false successor.
-     * 
+     *
      * @return the false successor
      */
     public AbstractBeginNode falseSuccessor() {
@@ -101,7 +101,7 @@
 
     /**
      * Gets the node corresponding to the specified outcome of the branch.
-     * 
+     *
      * @param istrue {@code true} if the true successor is requested, {@code false} otherwise
      * @return the corresponding successor
      */
@@ -339,7 +339,7 @@
 
     /**
      * Tries to remove an empty if construct or replace an if construct with a materialization.
-     * 
+     *
      * @return true if a transformation was made, false otherwise
      */
     private boolean removeOrMaterializeIf(SimplifierTool tool) {
@@ -444,7 +444,7 @@
     /**
      * Tries to connect code that initializes a variable directly with the successors of an if
      * construct that switches on the variable. For example, the pseudo code below:
-     * 
+     *
      * <pre>
      * contains(list, e, yes, no) {
      *     if (list == null || e == null) {
@@ -465,9 +465,9 @@
      *     }
      * }
      * </pre>
-     * 
+     *
      * will be transformed into:
-     * 
+     *
      * <pre>
      * contains(list, e, yes, no) {
      *     if (list == null || e == null) {
@@ -483,7 +483,7 @@
      *     }
      * }
      * </pre>
-     * 
+     *
      * @return true if a transformation was made, false otherwise
      */
     private boolean removeIntermediateMaterialization(SimplifierTool tool) {
@@ -633,7 +633,7 @@
      * Connects a set of ends to a given successor, inserting a merge node if there is more than one
      * end. If {@code ends} is not empty, then {@code successor} is added to {@code tool}'s
      * {@linkplain SimplifierTool#addToWorkList(com.oracle.graal.graph.Node) work list}.
-     * 
+     *
      * @param oldMerge the merge being removed
      * @param phiValues the values of the phi at the merge, keyed by the merge ends
      */
@@ -673,7 +673,7 @@
      * Gets an array of constants derived from a node that is either a {@link ConstantNode} or a
      * {@link PhiNode} whose input values are all constants. The length of the returned array is
      * equal to the number of ends terminating in a given merge node.
-     * 
+     *
      * @return null if {@code node} is neither a {@link ConstantNode} nor a {@link PhiNode} whose
      *         input values are all constants
      */
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InfopointNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -32,7 +33,7 @@
 public class InfopointNode extends FixedWithNextNode implements LIRLowerable, NodeWithState {
 
     public final InfopointReason reason;
-    @Input private FrameState state;
+    @Input(InputType.State) private FrameState state;
 
     public InfopointNode(InfopointReason reason, FrameState state) {
         super(StampFactory.forVoid());
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -37,16 +37,16 @@
 @NodeInfo(nameTemplate = "Invoke#{p#targetMethod/s}")
 public final class InvokeNode extends AbstractMemoryCheckpoint implements Invoke, LIRLowerable, MemoryCheckpoint.Single {
 
-    @Input private CallTargetNode callTarget;
-    @Input private FrameState stateDuring;
-    @Input private GuardingNode guard;
+    @Input(InputType.Association) private CallTargetNode callTarget;
+    @Input(InputType.State) private FrameState stateDuring;
+    @Input(InputType.Guard) private GuardingNode guard;
     private final int bci;
     private boolean polymorphic;
     private boolean useForInlining;
 
     /**
      * Constructs a new Invoke instruction.
-     * 
+     *
      * @param callTarget the target method being called
      * @param bci the bytecode index of the original invoke (used for debug infos)
      */
@@ -56,7 +56,7 @@
 
     /**
      * Constructs a new Invoke instruction.
-     * 
+     *
      * @param callTarget the target method being called
      * @param bci the bytecode index of the original invoke (used for debug infos)
      * @param stamp the stamp to be used for this value
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -38,10 +38,10 @@
 
     @Successor private AbstractBeginNode next;
     @Successor private DispatchBeginNode exceptionEdge;
-    @Input private CallTargetNode callTarget;
-    @Input private FrameState stateDuring;
-    @Input private FrameState stateAfter;
-    @Input private GuardingNode guard;
+    @Input(InputType.Association) private CallTargetNode callTarget;
+    @Input(InputType.State) private FrameState stateDuring;
+    @Input(InputType.State) private FrameState stateAfter;
+    @Input(InputType.Guard) private GuardingNode guard;
     private final int bci;
     private boolean polymorphic;
     private boolean useForInlining;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNegationNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNegationNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -30,7 +30,7 @@
  */
 public class LogicNegationNode extends LogicNode implements Canonicalizable {
 
-    @Input private LogicNode input;
+    @Input(InputType.Condition) private LogicNode input;
 
     public LogicNegationNode(LogicNode input) {
         this.input = input;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -38,7 +38,7 @@
     private double loopFrequency;
     private int nextEndIndex;
     private int unswitches;
-    @Input private GuardingNode overflowGuard;
+    @Input(InputType.Guard) private GuardingNode overflowGuard;
 
     public LoopBeginNode() {
         loopFrequency = 1;
@@ -57,7 +57,7 @@
      * Returns the <b>unordered</b> set of {@link LoopEndNode} that correspond to back-edges for
      * this loop. The order of the back-edges is unspecified, if you need to get an ordering
      * compatible for {@link PhiNode} creation, use {@link #orderedLoopEnds()}.
-     * 
+     *
      * @return the set of {@code LoopEndNode} that correspond to back-edges for this loop
      */
     public NodeIterable<LoopEndNode> loopEnds() {
@@ -77,7 +77,7 @@
      * Returns the set of {@link LoopEndNode} that correspond to back-edges for this loop, ordered
      * in increasing {@link #phiPredecessorIndex}. This method is suited to create new loop
      * {@link PhiNode}.
-     * 
+     *
      * @return the set of {@code LoopEndNode} that correspond to back-edges for this loop
      */
     public List<LoopEndNode> orderedLoopEnds() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopEndNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -29,7 +29,7 @@
 
 public final class LoopEndNode extends AbstractEndNode {
 
-    @Input(notDataflow = true) private LoopBeginNode loopBegin;
+    @Input(InputType.Association) private LoopBeginNode loopBegin;
     private boolean canSafepoint;
     private int endIndex;
 
@@ -80,7 +80,7 @@
      * Returns the 0-based index of this loop end. This is <b>not</b> the index into {@link PhiNode}
      * values at the loop begin. Use {@link MergeNode#phiPredecessorIndex(AbstractEndNode)} for this
      * purpose.
-     * 
+     *
      * @return The 0-based index of this loop end.
      */
     public int endIndex() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopExitNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopExitNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -27,7 +27,7 @@
 
 public class LoopExitNode extends BeginStateSplitNode implements IterableNodeType {
 
-    @Input(notDataflow = true) private LoopBeginNode loopBegin;
+    @Input(InputType.Association) private LoopBeginNode loopBegin;
 
     public LoopExitNode(LoopBeginNode loop) {
         assert loop != null;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -32,7 +32,7 @@
  */
 public class MemoryPhiNode extends PhiNode implements MemoryNode {
 
-    @Input final NodeInputList<ValueNode> values = new NodeInputList<>(this);
+    @Input(InputType.Memory) final NodeInputList<ValueNode> values = new NodeInputList<>(this);
     private final LocationIdentity locationIdentity;
 
     public MemoryPhiNode(MergeNode merge, LocationIdentity locationIdentity) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryProxyNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryProxyNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -23,13 +23,14 @@
 package com.oracle.graal.nodes;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
 public class MemoryProxyNode extends ProxyNode implements MemoryProxy, LIRLowerable {
 
-    @Input private ValueNode value;
+    @Input(InputType.Memory) private ValueNode value;
     private final LocationIdentity identity;
 
     public MemoryProxyNode(ValueNode value, AbstractBeginNode exit, LocationIdentity identity) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MergeNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -38,7 +38,7 @@
  */
 public class MergeNode extends BeginStateSplitNode implements IterableNodeType, LIRLowerable {
 
-    @Input(notDataflow = true) private final NodeInputList<AbstractEndNode> ends = new NodeInputList<>(this);
+    @Input(InputType.Association) private final NodeInputList<AbstractEndNode> ends = new NodeInputList<>(this);
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
@@ -68,7 +68,7 @@
 
     /**
      * Determines if a given node is a phi whose {@linkplain PhiNode#merge() merge} is this node.
-     * 
+     *
      * @param value the instruction to test
      * @return {@code true} if {@code value} is a phi and its merge is {@code this}
      */
@@ -79,7 +79,7 @@
     /**
      * Removes the given end from the merge, along with the entries corresponding to this end in the
      * phis connected to the merge.
-     * 
+     *
      * @param pred the end to remove
      */
     public void removeEnd(AbstractEndNode pred) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -29,7 +29,7 @@
 
 public abstract class PhiNode extends FloatingNode {
 
-    @Input(notDataflow = true) private MergeNode merge;
+    @Input(InputType.Association) private MergeNode merge;
 
     protected PhiNode(Stamp stamp, MergeNode merge) {
         super(stamp);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -34,12 +34,12 @@
 /**
  * A node that changes the type of its input, usually narrowing it. For example, a PiNode refines
  * the type of a receiver during type-guarded inlining to be the type tested by the guard.
- * 
+ *
  * In contrast to a {@link GuardedValueNode}, a PiNode is useless as soon as the type of its input
  * is as narrow or narrower than the PiNode's type. The PiNode, and therefore also the scheduling
  * restriction enforced by the anchor, will go away.
  */
-public class PiNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, IterableNodeType, GuardingNode, Canonicalizable, ValueProxy {
+public class PiNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, IterableNodeType, Canonicalizable, ValueProxy {
 
     @Input private ValueNode object;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -36,7 +36,7 @@
  */
 public abstract class ProxyNode extends FloatingNode implements IterableNodeType, ValueNumberable, ValueAndStampProxy {
 
-    @Input(notDataflow = true) private AbstractBeginNode proxyPoint;
+    @Input(InputType.Association) private AbstractBeginNode proxyPoint;
 
     public ProxyNode(Stamp stamp, AbstractBeginNode proxyPoint) {
         super(stamp);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ReturnNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -29,7 +29,7 @@
 public final class ReturnNode extends ControlSinkNode implements LIRLowerable, IterableNodeType {
 
     @Input private ValueNode result;
-    @Input private MemoryMapNode memoryMap;
+    @Input(InputType.Association) private MemoryMapNode memoryMap;
 
     public ValueNode result() {
         return result;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ShortCircuitOrNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ShortCircuitOrNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -27,8 +27,8 @@
 
 public class ShortCircuitOrNode extends LogicNode implements IterableNodeType, Canonicalizable {
 
-    @Input private LogicNode x;
-    @Input private LogicNode y;
+    @Input(InputType.Condition) private LogicNode x;
+    @Input(InputType.Condition) private LogicNode y;
     private boolean xNegated;
     private boolean yNegated;
     private double shortCircuitProbability;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -38,7 +38,7 @@
  */
 public final class ConditionalNode extends BinaryNode implements Canonicalizable, LIRLowerable {
 
-    @Input private LogicNode condition;
+    @Input(InputType.Condition) private LogicNode condition;
 
     public LogicNode condition() {
         return condition;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractWriteNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractWriteNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -27,14 +27,14 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
 
-public abstract class AbstractWriteNode extends FixedAccessNode implements StateSplit, MemoryCheckpoint.Single, MemoryAccess {
+public abstract class AbstractWriteNode extends FixedAccessNode implements StateSplit, MemoryCheckpoint.Single, MemoryAccess, GuardingNode {
 
     @Input private ValueNode value;
-    @Input(notDataflow = true) private FrameState stateAfter;
+    @Input(InputType.State) private FrameState stateAfter;
+    @Input(InputType.Memory) private Node lastLocationAccess;
+
     private final boolean initialization;
 
-    @Input private Node lastLocationAccess;
-
     public FrameState stateAfter() {
         return stateAfter;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
@@ -31,7 +32,7 @@
 public class ComputeAddressNode extends FloatingNode implements LIRLowerable {
 
     @Input private ValueNode object;
-    @Input private ValueNode location;
+    @Input(InputType.Association) private ValueNode location;
 
     public ValueNode getObject() {
         return object;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/DeferredForeignCallNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/DeferredForeignCallNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -35,7 +35,7 @@
 public class DeferredForeignCallNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single {
 
     @Input private final NodeInputList<ValueNode> arguments;
-    @Input private FrameState deoptState;
+    @Input(InputType.State) private FrameState deoptState;
 
     private final ForeignCallDescriptor descriptor;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedAccessNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FixedAccessNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
 
@@ -29,11 +30,11 @@
  * Accesses a value at an memory address specified by an {@linkplain #object object} and a
  * {@linkplain #accessLocation() location}. The access does not include a null check on the object.
  */
-public abstract class FixedAccessNode extends DeoptimizingFixedWithNextNode implements Access, GuardingNode {
+public abstract class FixedAccessNode extends DeoptimizingFixedWithNextNode implements Access {
 
-    @Input private GuardingNode guard;
+    @Input(InputType.Guard) private GuardingNode guard;
     @Input private ValueNode object;
-    @Input private ValueNode location;
+    @Input(InputType.Association) private ValueNode location;
     private boolean nullCheck;
     private BarrierType barrierType;
     private boolean compressible;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingAccessNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -23,13 +23,14 @@
 package com.oracle.graal.nodes.extended;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
 
 public abstract class FloatingAccessNode extends FloatingGuardedNode implements Access, MemoryAccess {
 
     @Input private ValueNode object;
-    @Input private LocationNode location;
+    @Input(InputType.Association) private LocationNode location;
     private BarrierType barrierType;
     private boolean compressible;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -35,7 +35,7 @@
  */
 public final class FloatingReadNode extends FloatingAccessNode implements IterableNodeType, LIRLowerable, Canonicalizable {
 
-    @Input private MemoryNode lastLocationAccess;
+    @Input(InputType.Memory) private MemoryNode lastLocationAccess;
 
     public FloatingReadNode(ValueNode object, LocationNode location, MemoryNode lastLocationAccess, Stamp stamp) {
         this(object, location, lastLocationAccess, stamp, null, BarrierType.NONE, false);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -38,8 +38,8 @@
 public class ForeignCallNode extends AbstractMemoryCheckpoint implements LIRLowerable, DeoptimizingNode.DeoptDuring, MemoryCheckpoint.Multi {
 
     @Input private final NodeInputList<ValueNode> arguments;
+    @Input(InputType.State) private FrameState stateDuring;
     private final ForeignCallsProvider foreignCalls;
-    @Input private FrameState stateDuring;
 
     private final ForeignCallDescriptor descriptor;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaReadNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/JavaReadNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -30,7 +30,7 @@
  * Read a raw memory location according to Java field or array read semantics. It will perform read
  * barriers, implicit conversions and optionally oop uncompression.
  */
-public final class JavaReadNode extends FixedAccessNode implements Lowerable {
+public final class JavaReadNode extends FixedAccessNode implements Lowerable, GuardingNode {
 
     public JavaReadNode(ValueNode object, LocationNode location, BarrierType barrierType, boolean compressible) {
         super(object, location, StampFactory.forKind(location.getValueKind()), barrierType, compressible);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/NullCheckNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -26,7 +26,7 @@
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
-public class NullCheckNode extends DeoptimizingFixedWithNextNode implements LIRLowerable, GuardingNode {
+public class NullCheckNode extends DeoptimizingFixedWithNextNode implements LIRLowerable {
 
     @Input private ValueNode object;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -33,7 +33,7 @@
 /**
  * Reads an {@linkplain FixedAccessNode accessed} value.
  */
-public final class ReadNode extends FloatableAccessNode implements LIRLowerable, Canonicalizable, PiPushable, Virtualizable {
+public final class ReadNode extends FloatableAccessNode implements LIRLowerable, Canonicalizable, PiPushable, Virtualizable, GuardingNode {
 
     public ReadNode(ValueNode object, ValueNode location, Stamp stamp, BarrierType barrierType, boolean compressible) {
         super(object, location, stamp, barrierType, compressible);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SnippetLocationNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SnippetLocationNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -41,7 +41,7 @@
 public final class SnippetLocationNode extends LocationNode implements Canonicalizable {
 
     @Input private ValueNode valueKind;
-    @Input private ValueNode locationIdentity;
+    @Input(InputType.Association) private ValueNode locationIdentity;
     @Input private ValueNode displacement;
     @Input private ValueNode index;
     @Input private ValueNode indexScaling;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeLoadNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -25,6 +25,7 @@
 import static com.oracle.graal.graph.UnsafeAccess.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
@@ -35,7 +36,7 @@
  * performed before the load.
  */
 public class UnsafeLoadNode extends UnsafeAccessNode implements Lowerable, Virtualizable {
-    @Input private LogicNode guardingCondition;
+    @Input(InputType.Condition) private LogicNode guardingCondition;
 
     public UnsafeLoadNode(ValueNode object, ValueNode offset, Kind accessKind, LocationIdentity locationIdentity) {
         this(object, offset, accessKind, locationIdentity, null);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -25,6 +25,7 @@
 import static com.oracle.graal.graph.UnsafeAccess.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
@@ -37,7 +38,7 @@
 public class UnsafeStoreNode extends UnsafeAccessNode implements StateSplit, Lowerable, Virtualizable, MemoryCheckpoint.Single {
 
     @Input private ValueNode value;
-    @Input(notDataflow = true) private FrameState stateAfter;
+    @Input(InputType.State) private FrameState stateAfter;
 
     public UnsafeStoreNode(ValueNode object, ValueNode offset, ValueNode value, Kind accessKind, LocationIdentity locationIdentity) {
         super(StampFactory.forVoid(), object, offset, accessKind, locationIdentity);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ValueAnchorNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.extended;
 
+import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
@@ -32,9 +33,9 @@
 /**
  * The ValueAnchor instruction keeps non-CFG (floating) nodes above a certain point in the graph.
  */
-public final class ValueAnchorNode extends FixedWithNextNode implements LIRLowerable, Simplifiable, Virtualizable, GuardingNode {
+public final class ValueAnchorNode extends FixedWithNextNode implements LIRLowerable, Simplifiable, Virtualizable {
 
-    @Input private ValueNode anchored;
+    @Input(InputType.Guard) private ValueNode anchored;
 
     public ValueAnchorNode(ValueNode value) {
         super(StampFactory.dependency());
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.type.*;
@@ -35,9 +36,9 @@
  */
 public abstract class AccessMonitorNode extends AbstractMemoryCheckpoint implements MemoryCheckpoint, DeoptimizingNode.DeoptBefore, DeoptimizingNode.DeoptAfter {
 
-    @Input private FrameState stateBefore;
+    @Input(InputType.State) private FrameState stateBefore;
     @Input private ValueNode object;
-    @Input private MonitorIdNode monitorId;
+    @Input(InputType.Association) private MonitorIdNode monitorId;
 
     @Override
     public boolean canDeoptimize() {
@@ -64,7 +65,7 @@
 
     /**
      * Creates a new AccessMonitor instruction.
-     * 
+     *
      * @param object the instruction producing the object
      */
     public AccessMonitorNode(ValueNode object, MonitorIdNode monitorId) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
@@ -35,7 +36,7 @@
 
     @Input private ValueNode expectedValue;
     @Input private ValueNode newValue;
-    @Input(notDataflow = true) private FrameState stateAfter;
+    @Input(InputType.State) private FrameState stateAfter;
 
     public FrameState stateAfter() {
         return stateAfter;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -38,7 +38,7 @@
 
     public static final ForeignCallDescriptor REGISTER_FINALIZER = new ForeignCallDescriptor("registerFinalizer", void.class, Object.class);
 
-    @Input private FrameState deoptState;
+    @Input(InputType.State) private FrameState deoptState;
     @Input private ValueNode object;
 
     public ValueNode object() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreFieldNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -36,7 +36,7 @@
 public final class StoreFieldNode extends AccessFieldNode implements StateSplit, VirtualizableRoot {
 
     @Input private ValueNode value;
-    @Input(notDataflow = true) private FrameState stateAfter;
+    @Input(InputType.State) private FrameState stateAfter;
 
     public FrameState stateAfter() {
         return stateAfter;
@@ -58,7 +58,7 @@
 
     /**
      * Creates a new StoreFieldNode.
-     * 
+     *
      * @param object the receiver object
      * @param field the compiler interface field
      * @param value the node representing the value to store to the field
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/StoreIndexedNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
@@ -33,7 +34,7 @@
 public final class StoreIndexedNode extends AccessIndexedNode implements StateSplit, Lowerable, Virtualizable {
 
     @Input private ValueNode value;
-    @Input(notDataflow = true) private FrameState stateAfter;
+    @Input(InputType.State) private FrameState stateAfter;
 
     public FrameState stateAfter() {
         return stateAfter;
@@ -55,7 +56,7 @@
 
     /**
      * Creates a new StoreIndexedNode.
-     * 
+     *
      * @param array the node producing the array
      * @param index the node producing the index
      * @param elementKind the element type
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/AllocatedObjectNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/AllocatedObjectNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.nodes.virtual;
 
+import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
@@ -34,7 +35,7 @@
 public class AllocatedObjectNode extends FloatingNode implements Virtualizable, ArrayLengthProvider {
 
     @Input private VirtualObjectNode virtualObject;
-    @Input private CommitAllocationNode commit;
+    @Input(InputType.Association) private CommitAllocationNode commit;
 
     public AllocatedObjectNode(VirtualObjectNode virtualObject) {
         super(StampFactory.exactNonNull(virtualObject.type()));
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/CommitAllocationNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -37,7 +37,7 @@
 
     @Input private final NodeInputList<VirtualObjectNode> virtualObjects = new NodeInputList<>(this);
     @Input private final NodeInputList<ValueNode> values = new NodeInputList<>(this);
-    @Input private final NodeInputList<MonitorIdNode> locks = new NodeInputList<>(this);
+    @Input(InputType.Association) private final NodeInputList<MonitorIdNode> locks = new NodeInputList<>(this);
     private ArrayList<Integer> lockIndexes = new ArrayList<>(Arrays.asList(0));
 
     public CommitAllocationNode() {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Mon Apr 07 11:32:04 2014 +0200
@@ -707,11 +707,7 @@
                     if (nonNull) {
                         replacementAnchor = searchAnchor(GraphUtil.unproxify(object), type);
                     }
-                    ValueAnchorNode anchor = null;
-                    if (replacementAnchor == null) {
-                        anchor = graph.add(new ValueAnchorNode(null));
-                        replacementAnchor = anchor;
-                    }
+                    replacementAnchor = BeginNode.prevBegin(checkCast);
                     PiNode piNode;
                     if (isNull) {
                         ConstantNode nullObject = ConstantNode.forObject(null, metaAccess, graph);
@@ -720,11 +716,7 @@
                         piNode = graph.unique(new PiNode(object, StampFactory.declared(type, nonNull), replacementAnchor.asNode()));
                     }
                     checkCast.replaceAtUsages(piNode);
-                    if (anchor != null) {
-                        graph.replaceFixedWithFixed(checkCast, anchor);
-                    } else {
-                        graph.removeFixed(checkCast);
-                    }
+                    graph.removeFixed(checkCast);
                     metricCheckCastRemoved.increment();
                 }
             } else if (node instanceof ConditionAnchorNode) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Mon Apr 07 11:32:04 2014 +0200
@@ -103,7 +103,7 @@
         }
 
         private class DummyGuardHandle extends ValueNode implements GuardedNode {
-            @Input private GuardingNode guard;
+            @Input(InputType.Guard) private GuardingNode guard;
 
             public DummyGuardHandle(GuardingNode guard) {
                 super(StampFactory.forVoid());
@@ -177,7 +177,7 @@
 
     /**
      * Checks that second lowering of a given graph did not introduce any new nodes.
-     * 
+     *
      * @param graph a graph that was just {@linkplain #lower lowered}
      * @throws AssertionError if the check fails
      */
@@ -206,7 +206,7 @@
      * Checks that lowering of a given node did not introduce any new {@link Lowerable} nodes that
      * could be lowered in the current {@link LoweringPhase}. Such nodes must be recursively lowered
      * as part of lowering {@code node}.
-     * 
+     *
      * @param node a node that was just lowered
      * @param preLoweringMark the graph mark before {@code node} was lowered
      * @param unscheduledUsages set of {@code node}'s usages that were unscheduled before it was
@@ -349,7 +349,7 @@
          * the context of a usage that dominates all other usages. The fixed nodes resulting from
          * lowering are attached to the fixed node context of the dominating usage. This ensures the
          * post-lowering graph still has a valid schedule.
-         * 
+         *
          * @param node a {@link Lowerable} node
          */
         private Collection<Node> getUnscheduledUsages(Node node) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/TailDuplicationPhase.java	Mon Apr 07 11:32:04 2014 +0200
@@ -57,6 +57,12 @@
 
     private final CanonicalizerPhase canonicalizer;
 
+    private static final class DummyAnchorNode extends FixedWithNextNode implements GuardingNode {
+        public DummyAnchorNode() {
+            super(StampFactory.forVoid());
+        }
+    }
+
     /**
      * This interface is used by tail duplication to let clients decide if tail duplication should
      * be performed.
@@ -67,7 +73,7 @@
          * Queries if tail duplication should be performed at the given merge. If this method
          * returns true then the tail duplication will be performed, because all other checks have
          * happened before.
-         * 
+         *
          * @param merge The merge at which tail duplication can be performed.
          * @param fixedNodeCount The size of the set of fixed nodes that forms the base for the
          *            duplicated set of nodes.
@@ -162,7 +168,7 @@
      * {@link MergeNode#stateAfter()}) then the decision callback is used to determine whether the
      * tail duplication should actually be performed. If replacements is non-null, then this list of
      * {@link PiNode}s is used to replace one value per merge end.
-     * 
+     *
      * @param merge The merge whose tail should be duplicated.
      * @param decision A callback that can make the final decision if tail duplication should occur
      *            or not.
@@ -210,7 +216,7 @@
 
         /**
          * Initializes the tail duplication operation without actually performing any work.
-         * 
+         *
          * @param merge The merge whose tail should be duplicated.
          * @param replacements A list of replacement {@link PiNode}s, or null. If this is non-null,
          *            then the size of the list needs to match the number of end nodes at the merge.
@@ -232,7 +238,7 @@
          * <li>Determines the complete set of duplicated nodes.</li>
          * <li>Performs the actual duplication.</li>
          * </ul>
-         * 
+         *
          * @param phaseContext
          */
         private void duplicate(PhaseContext phaseContext) {
@@ -240,7 +246,7 @@
 
             Mark startMark = graph.getMark();
 
-            ValueAnchorNode anchor = addValueAnchor();
+            DummyAnchorNode anchor = addValueAnchor();
 
             // determine the fixed nodes that should be duplicated (currently: all nodes up until
             // the first control
@@ -283,11 +289,17 @@
 
                 // re-wire the duplicated ValueAnchorNode to the predecessor of the corresponding
                 // EndNode
-                FixedNode anchorDuplicate = (FixedNode) duplicates.get(anchor);
-                ((FixedWithNextNode) forwardEnd.predecessor()).setNext(anchorDuplicate);
+                FixedWithNextNode anchorDuplicate = (FixedWithNextNode) duplicates.get(anchor);
                 // move dependencies on the ValueAnchorNode to the previous BeginNode
-                AbstractBeginNode prevBegin = AbstractBeginNode.prevBegin(anchorDuplicate);
-                anchorDuplicate.replaceAtUsages(prevBegin);
+                AbstractBeginNode prevBegin = AbstractBeginNode.prevBegin(forwardEnd);
+                anchorDuplicate.replaceAtUsages(InputType.Guard, prevBegin);
+                anchorDuplicate.replaceAtUsages(InputType.Anchor, prevBegin);
+                assert anchorDuplicate.usages().isEmpty();
+
+                FixedNode next = anchorDuplicate.next();
+                anchorDuplicate.setNext(null);
+                ((FixedWithNextNode) forwardEnd.predecessor()).setNext(next);
+                anchorDuplicate.safeDelete();
 
                 // re-wire the phi duplicates to the correct input
                 for (PhiNode phi : phiSnapshot) {
@@ -315,19 +327,14 @@
         /**
          * Inserts a new ValueAnchorNode after the merge and transfers all dependency-usages (not
          * phis) to this ValueAnchorNode.
-         * 
+         *
          * @return The new {@link ValueAnchorNode} that was created.
          */
-        private ValueAnchorNode addValueAnchor() {
-            ValueAnchorNode anchor = graph.add(new ValueAnchorNode(null));
+        private DummyAnchorNode addValueAnchor() {
+            DummyAnchorNode anchor = graph.add(new DummyAnchorNode());
             graph.addAfterFixed(merge, anchor);
-            for (Node usage : merge.usages().snapshot()) {
-                if (usage instanceof PhiNode && ((PhiNode) usage).merge() == merge) {
-                    // nothing to do
-                } else {
-                    usage.replaceFirstInput(merge, anchor);
-                }
-            }
+            merge.replaceAtUsages(InputType.Guard, anchor);
+            merge.replaceAtUsages(InputType.Anchor, anchor);
             return anchor;
         }
 
@@ -335,7 +342,7 @@
          * Given a set of fixed nodes, this method determines the set of fixed and floating nodes
          * that needs to be duplicated, i.e., all nodes that due to data flow and other dependencies
          * needs to be duplicated.
-         * 
+         *
          * @param fixedNodes The set of fixed nodes that should be duplicated.
          * @param stateAfter The frame state of the merge that follows the set of fixed nodes. All
          *            {@link ValueNode}s reachable from this state are considered to be reachable
@@ -427,7 +434,7 @@
         /**
          * Creates a new merge and end node construct at the end of the duplicated area. While it is
          * useless in itself (merge with only one end) it simplifies the later duplication step.
-         * 
+         *
          * @param successor The successor of the duplicated set of nodes, i.e., the first node that
          *            should not be duplicated.
          * @param stateAfterMerge The frame state that should be used for the merge.
@@ -461,7 +468,7 @@
          * {@link StampFactory#condition()} stamps that have usages within the duplicated set of
          * nodes need to also be duplicated.</li>
          * </ul>
-         * 
+         *
          * @param duplicatedNodes The set of duplicated nodes that will be modified (expanded).
          * @param newBottomMerge The merge that follows the duplicated set of nodes. It will be used
          *            for newly created phis and to as a target for dependencies that pointed into
@@ -531,7 +538,7 @@
 
         /**
          * Checks if the given node has usages that are not within the given set of nodes.
-         * 
+         *
          * @param node The node whose usages are checked.
          * @param nodeSet The set of nodes that are considered to be "within".
          * @return true if the given node has usages on the outside, false otherwise.
@@ -548,7 +555,7 @@
         /**
          * Replaces the given node with the given replacement at all usages that are not within the
          * given set of nodes.
-         * 
+         *
          * @param node The node to be replaced at outside usages.
          * @param replacement The node that replaced the given node at outside usages.
          * @param nodeSet The set of nodes that are considered to be "within".
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java	Mon Apr 07 16:24:49 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java	Mon Apr 07 11:32:04 2014 +0200
@@ -34,14 +34,14 @@
 
 /**
  * Load of a final value from a location specified as an offset relative to an object.
- * 
+ *
  * Substitution for method {@link CompilerDirectives#unsafeGetFinalObject} and friends.
  */
 public class CustomizedUnsafeLoadFinalNode extends FixedWithNextNode implements Canonicalizable, Virtualizable, Lowerable {
     @Input private ValueNode object;
     @Input private ValueNode offset;
-    @Input private ValueNode condition;
-    @Input private ValueNode location;
+    @Input(InputType.Condition) private ValueNode condition;
+    @Input(InputType.Association) private ValueNode location;
     private final Kind accessKind;
 
     public CustomizedUnsafeLoadFinalNode(ValueNode object, ValueNode offset, ValueNode condition, ValueNode location, Kind accessKind) {