changeset 16232:e34bb128f227

Merge.
author Doug Simon <doug.simon@oracle.com>
date Wed, 25 Jun 2014 17:34:25 +0200
parents a47528fb2ea0 (current diff) cc4b4fd5c484 (diff)
children 68fb8e4d8043
files graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java
diffstat 120 files changed, 1603 insertions(+), 1361 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java	Wed Jun 25 17:34:25 2014 +0200
@@ -64,8 +64,8 @@
                 FixedWithNextNode fixedWithNextNode = (FixedWithNextNode) node;
                 if (((fixedWithNextNode instanceof IntegerDivNode) || (fixedWithNextNode instanceof IntegerRemNode)) && fixedWithNextNode.getClass() != divRem.getClass()) {
                     FixedBinaryNode otherDivRem = (FixedBinaryNode) fixedWithNextNode;
-                    if (otherDivRem.x() == divRem.x() && otherDivRem.y() == divRem.y() && !hasOperand(otherDivRem)) {
-                        Value[] results = ((AMD64LIRGenerator) gen).emitIntegerDivRem(operand(divRem.x()), operand(divRem.y()), state((DeoptimizingNode) valueNode));
+                    if (otherDivRem.getX() == divRem.getX() && otherDivRem.getY() == divRem.getY() && !hasOperand(otherDivRem)) {
+                        Value[] results = ((AMD64LIRGenerator) gen).emitIntegerDivRem(operand(divRem.getX()), operand(divRem.getY()), state((DeoptimizingNode) valueNode));
                         if (divRem instanceof IntegerDivNode) {
                             setResult(divRem, results[0]);
                             setResult(otherDivRem, results[1]);
@@ -136,7 +136,7 @@
         // emitCompareBranchMemory expects the memory on the right, so mirror the condition if
         // that's not true. It might be mirrored again the actual compare is emitted but that's
         // ok.
-        Condition finalCondition = uncast(compare.x()) == access ? cond.mirror() : cond;
+        Condition finalCondition = uncast(compare.getX()) == access ? cond.mirror() : cond;
         return new ComplexMatchResult() {
             public Value evaluate(NodeLIRBuilder builder) {
                 LabelRef trueLabel = getLIRBlock(ifNode.trueSuccessor());
@@ -364,8 +364,8 @@
 
     @MatchRule("(Or (LeftShift=lshift value Constant) (UnsignedRightShift=rshift value Constant))")
     public ComplexMatchResult rotateLeftConstant(LeftShiftNode lshift, UnsignedRightShiftNode rshift) {
-        if ((lshift.getShiftAmountMask() & (lshift.y().asConstant().asInt() + rshift.y().asConstant().asInt())) == 0) {
-            return builder -> getLIRGeneratorTool().emitRol(operand(lshift.x()), operand(lshift.y()));
+        if ((lshift.getShiftAmountMask() & (lshift.getY().asConstant().asInt() + rshift.getY().asConstant().asInt())) == 0) {
+            return builder -> getLIRGeneratorTool().emitRol(operand(lshift.getX()), operand(lshift.getY()));
         }
         return null;
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Wed Jun 25 17:34:25 2014 +0200
@@ -103,7 +103,7 @@
             IntegerTestNode test = (IntegerTestNode) conditional.condition();
             ParameterNode param0 = graph.getParameter(0);
             ParameterNode param1 = graph.getParameter(1);
-            assertTrue((test.x() == param0 && test.y() == param1) || (test.x() == param1 && test.y() == param0));
+            assertTrue((test.getX() == param0 && test.getY() == param1) || (test.getX() == param1 && test.getY() == param0));
         }
     }
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Wed Jun 25 17:34:25 2014 +0200
@@ -25,10 +25,9 @@
 import org.junit.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.loop.phases.*;
-import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.virtual.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.schedule.*;
@@ -279,7 +278,7 @@
 
     @SuppressWarnings("unused")
     public static void testNewNodeSnippet() {
-        new IntegerAddNode(new IntegerStamp(32, Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0xFFFFFFFF), null, null);
+        new ValueAnchorNode(null);
     }
 
     /**
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java	Wed Jun 25 17:34:25 2014 +0200
@@ -408,17 +408,17 @@
     }
 
     private void emitNullCheckBranch(IsNullNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) {
-        PlatformKind kind = gen.getLIRKind(node.object().stamp()).getPlatformKind();
-        gen.emitCompareBranch(kind, operand(node.object()), kind.getDefaultValue(), Condition.EQ, false, trueSuccessor, falseSuccessor, trueSuccessorProbability);
+        PlatformKind kind = gen.getLIRKind(node.getValue().stamp()).getPlatformKind();
+        gen.emitCompareBranch(kind, operand(node.getValue()), kind.getDefaultValue(), Condition.EQ, false, trueSuccessor, falseSuccessor, trueSuccessorProbability);
     }
 
     public void emitCompareBranch(CompareNode compare, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) {
-        PlatformKind kind = gen.getLIRKind(compare.x().stamp()).getPlatformKind();
-        gen.emitCompareBranch(kind, operand(compare.x()), operand(compare.y()), compare.condition(), compare.unorderedIsTrue(), trueSuccessor, falseSuccessor, trueSuccessorProbability);
+        PlatformKind kind = gen.getLIRKind(compare.getX().stamp()).getPlatformKind();
+        gen.emitCompareBranch(kind, operand(compare.getX()), operand(compare.getY()), compare.condition(), compare.unorderedIsTrue(), trueSuccessor, falseSuccessor, trueSuccessorProbability);
     }
 
     public void emitIntegerTestBranch(IntegerTestNode test, LabelRef trueSuccessor, LabelRef falseSuccessor, double trueSuccessorProbability) {
-        gen.emitIntegerTestBranch(operand(test.x()), operand(test.y()), trueSuccessor, falseSuccessor, trueSuccessorProbability);
+        gen.emitIntegerTestBranch(operand(test.getX()), operand(test.getY()), trueSuccessor, falseSuccessor, trueSuccessorProbability);
     }
 
     public void emitConstantBranch(boolean value, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock) {
@@ -436,17 +436,17 @@
     public Variable emitConditional(LogicNode node, Value trueValue, Value falseValue) {
         if (node instanceof IsNullNode) {
             IsNullNode isNullNode = (IsNullNode) node;
-            PlatformKind kind = gen.getLIRKind(isNullNode.object().stamp()).getPlatformKind();
-            return gen.emitConditionalMove(kind, operand(isNullNode.object()), kind.getDefaultValue(), Condition.EQ, false, trueValue, falseValue);
+            PlatformKind kind = gen.getLIRKind(isNullNode.getValue().stamp()).getPlatformKind();
+            return gen.emitConditionalMove(kind, operand(isNullNode.getValue()), kind.getDefaultValue(), Condition.EQ, false, trueValue, falseValue);
         } else if (node instanceof CompareNode) {
             CompareNode compare = (CompareNode) node;
-            PlatformKind kind = gen.getLIRKind(compare.x().stamp()).getPlatformKind();
-            return gen.emitConditionalMove(kind, operand(compare.x()), operand(compare.y()), compare.condition(), compare.unorderedIsTrue(), trueValue, falseValue);
+            PlatformKind kind = gen.getLIRKind(compare.getX().stamp()).getPlatformKind();
+            return gen.emitConditionalMove(kind, operand(compare.getX()), operand(compare.getY()), compare.condition(), compare.unorderedIsTrue(), trueValue, falseValue);
         } else if (node instanceof LogicConstantNode) {
             return gen.emitMove(((LogicConstantNode) node).getValue() ? trueValue : falseValue);
         } else if (node instanceof IntegerTestNode) {
             IntegerTestNode test = (IntegerTestNode) node;
-            return gen.emitIntegerTestMove(operand(test.x()), operand(test.y()), trueValue, falseValue);
+            return gen.emitIntegerTestMove(operand(test.getX()), operand(test.getY()), trueValue, falseValue);
         } else {
             throw GraalInternalError.unimplemented(node.toString());
         }
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Wed Jun 25 17:34:25 2014 +0200
@@ -28,6 +28,8 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.GraphEvent.NodeEvent;
 import com.oracle.graal.graph.Node.ValueNumberable;
+import com.oracle.graal.graph.NodeClass.NodeClassIterator;
+import com.oracle.graal.graph.NodeClass.Position;
 import com.oracle.graal.graph.iterators.*;
 
 /**
@@ -279,6 +281,22 @@
         return add(node);
     }
 
+    public <T extends Node> T addOrUniqueWithInputs(T node) {
+        NodeClassIterator iterator = node.inputs().iterator();
+        while (iterator.hasNext()) {
+            Position pos = iterator.nextPosition();
+            Node input = pos.get(node);
+            if (input != null && !input.isAlive()) {
+                assert !input.isDeleted();
+                pos.initialize(node, addOrUniqueWithInputs(input));
+            }
+        }
+        if (node.getNodeClass().valueNumberable()) {
+            return uniqueHelper(node, true);
+        }
+        return add(node);
+    }
+
     private <T extends Node> T addHelper(T node) {
         node.initialize(this);
         return node;
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Wed Jun 25 17:34:25 2014 +0200
@@ -35,6 +35,7 @@
 import com.oracle.graal.graph.Node.Successor;
 import com.oracle.graal.graph.Node.Verbosity;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.graph.spi.Canonicalizable.CanonicalizeMethod;
 
 /**
  * Metadata for every {@link Node} type. The metadata includes:
@@ -102,7 +103,7 @@
     /**
      * Determines if this node type implements {@link Canonicalizable}.
      */
-    private final boolean isCanonicalizable;
+    private final CanonicalizeMethod canonicalizeMethod;
 
     /**
      * Determines if this node type implements {@link Simplifiable}.
@@ -116,7 +117,18 @@
     public NodeClass(Class<?> clazz, CalcOffset calcOffset, int[] presetIterableIds, int presetIterableId) {
         super(clazz);
         assert NODE_CLASS.isAssignableFrom(clazz);
-        this.isCanonicalizable = Canonicalizable.class.isAssignableFrom(clazz);
+        if (Canonicalizable.Unary.class.isAssignableFrom(clazz)) {
+            assert !Canonicalizable.Binary.class.isAssignableFrom(clazz) && !Canonicalizable.class.isAssignableFrom(clazz) : clazz;
+            this.canonicalizeMethod = CanonicalizeMethod.UNARY;
+        } else if (Canonicalizable.Binary.class.isAssignableFrom(clazz)) {
+            assert !Canonicalizable.class.isAssignableFrom(clazz) : clazz;
+            this.canonicalizeMethod = CanonicalizeMethod.BINARY;
+        } else if (Canonicalizable.class.isAssignableFrom(clazz)) {
+            this.canonicalizeMethod = CanonicalizeMethod.BASE;
+        } else {
+            this.canonicalizeMethod = null;
+        }
+
         this.isSimplifiable = Simplifiable.class.isAssignableFrom(clazz);
 
         FieldScanner scanner = new FieldScanner(calcOffset);
@@ -249,8 +261,8 @@
     /**
      * Determines if this node type implements {@link Canonicalizable}.
      */
-    public boolean isCanonicalizable() {
-        return isCanonicalizable;
+    public CanonicalizeMethod getCanonicalizeMethod() {
+        return canonicalizeMethod;
     }
 
     /**
@@ -377,6 +389,10 @@
             node.getNodeClass().set(node, this, value);
         }
 
+        void initialize(Node node, Node value) {
+            node.getNodeClass().initializePosition(node, this, value);
+        }
+
         public boolean isValidFor(Node node, Node from) {
             return node.getNodeClass().isValid(this, from.getNodeClass());
         }
@@ -1066,6 +1082,20 @@
         }
     }
 
+    public void initializePosition(Node node, Position pos, Node x) {
+        long offset = pos.isInput() ? inputOffsets[pos.getIndex()] : successorOffsets[pos.getIndex()];
+        if (pos.getSubIndex() == NOT_ITERABLE) {
+            assert x == null || fieldTypes.get((pos.isInput() ? inputOffsets : successorOffsets)[pos.getIndex()]).isAssignableFrom(x.getClass()) : this + ".set(node, pos, " + x + ")";
+            putNode(node, offset, x);
+        } else {
+            NodeList<Node> list = getNodeList(node, offset);
+            while (list.size() <= pos.getSubIndex()) {
+                list.add(null);
+            }
+            list.initialize(pos.getSubIndex(), x);
+        }
+    }
+
     public NodeClassIterable getInputIterable(final Node node) {
         assert getClazz().isInstance(node);
         return new NodeClassIterable() {
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java	Wed Jun 25 17:34:25 2014 +0200
@@ -154,6 +154,12 @@
         return oldValue;
     }
 
+    void initialize(int index, T node) {
+        incModCount();
+        assert index < size();
+        nodes[index] = node;
+    }
+
     void copy(NodeList<T> other) {
         incModCount();
         nodes = Arrays.copyOf(other.nodes, other.size);
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/spi/Canonicalizable.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/spi/Canonicalizable.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -26,5 +26,25 @@
 
 public interface Canonicalizable {
 
+    public enum CanonicalizeMethod {
+        BASE,
+        UNARY,
+        BINARY
+    }
+
     Node canonical(CanonicalizerTool tool);
+
+    public interface Unary<T extends Node> {
+        T canonical(CanonicalizerTool tool, T forValue);
+
+        T getValue();
+    }
+
+    public interface Binary<T extends Node> {
+        T canonical(CanonicalizerTool tool, T forX, T forY);
+
+        T getX();
+
+        T getY();
+    }
 }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java	Wed Jun 25 17:34:25 2014 +0200
@@ -72,10 +72,10 @@
         Value value = gen.load(operand(valueNode));
         AMD64AddressValue address = makeCompressedAddress(compress, location);
         Condition cond = compare.condition();
-        if (access == filterCompression(compare.x())) {
+        if (access == filterCompression(compare.getX())) {
             cond = cond.mirror();
         } else {
-            assert access == filterCompression(compare.y());
+            assert access == filterCompression(compare.getY());
         }
 
         LabelRef trueLabel = getLIRBlock(ifNode.trueSuccessor());
@@ -253,7 +253,7 @@
     @MatchRule("(If (FloatLessThan=compare value (Read=access (Compression=compress object) ConstantLocation=location)))")
     public ComplexMatchResult ifCompareCompressedMemory(IfNode root, CompareNode compare, CompressionNode compress, ValueNode value, ConstantLocationNode location, Access access) {
         if (canFormCompressedMemory(compress, location)) {
-            PlatformKind cmpKind = gen.getLIRKind(compare.x().stamp()).getPlatformKind();
+            PlatformKind cmpKind = gen.getLIRKind(compare.getX().stamp()).getPlatformKind();
             if (cmpKind instanceof Kind) {
                 Kind kind = (Kind) cmpKind;
                 return builder -> {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRFrameState.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRFrameState.java	Wed Jun 25 17:34:25 2014 +0200
@@ -28,7 +28,6 @@
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
-import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
 
 /**
  * Extends {@link LIRFrameState} to handle {@link HotSpotMonitorValue}s correctly.
@@ -40,19 +39,6 @@
     }
 
     @Override
-    protected Value processValue(ValueProcedure proc, Value value) {
-        if (value instanceof HotSpotMonitorValue) {
-            HotSpotMonitorValue monitor = (HotSpotMonitorValue) value;
-            if (processed(monitor.getOwner())) {
-                monitor.setOwner(proc.doValue(monitor.getOwner(), OperandMode.ALIVE, STATE_FLAGS));
-            }
-            return value;
-        } else {
-            return super.processValue(proc, value);
-        }
-    }
-
-    @Override
     protected Value processValue(LIRInstruction inst, InstructionValueProcedure proc, Value value) {
         if (value instanceof HotSpotMonitorValue) {
             HotSpotMonitorValue monitor = (HotSpotMonitorValue) value;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java	Wed Jun 25 17:34:25 2014 +0200
@@ -386,7 +386,7 @@
         ReadNode readArray = graph.add(new ReadNode(thread, arrayLocation, StampFactory.forKind(wordKind), BarrierType.NONE));
         ConstantLocationNode location = ConstantLocationNode.create(LocationIdentity.ANY_LOCATION, Kind.Long, Unsafe.ARRAY_LONG_INDEX_SCALE * index, graph);
         ReadNode read = graph.add(new ReadNode(readArray, location, StampFactory.forKind(Kind.Long), BarrierType.NONE));
-        IntegerAddNode add = graph.unique(new IntegerAddNode(StampFactory.forKind(Kind.Long), read, counter.getIncrement()));
+        IntegerAddNode add = graph.unique(new IntegerAddNode(read, counter.getIncrement()));
         WriteNode write = graph.add(new WriteNode(readArray, add, location, BarrierType.NONE));
 
         graph.addBeforeFixed(counter, thread);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassCastNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassCastNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.hotspot.nodes;
 
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.replacements.*;
@@ -32,10 +31,10 @@
 
 /**
  * {@link MacroNode Macro node} for {@link Class#cast(Object)}.
- * 
+ *
  * @see ClassSubstitutions#cast(Class, Object)
  */
-public class ClassCastNode extends MacroNode implements Canonicalizable {
+public class ClassCastNode extends MacroNode implements Canonicalizable.Binary<ValueNode> {
 
     public ClassCastNode(Invoke invoke) {
         super(invoke);
@@ -49,16 +48,21 @@
         return arguments.get(1);
     }
 
+    public ValueNode getX() {
+        return getJavaClass();
+    }
+
+    public ValueNode getY() {
+        return getObject();
+    }
+
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        ValueNode javaClass = getJavaClass();
-        if (javaClass.isConstant()) {
-            ValueNode object = getObject();
-            Class<?> c = (Class<?>) HotSpotObjectConstant.asObject(javaClass.asConstant());
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forJavaClass, ValueNode forObject) {
+        if (forJavaClass.isConstant()) {
+            Class<?> c = (Class<?>) HotSpotObjectConstant.asObject(forJavaClass.asConstant());
             if (c != null && !c.isPrimitive()) {
                 HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) HotSpotResolvedObjectType.fromClass(c);
-                CheckCastNode checkcast = graph().add(new CheckCastNode(type, object, null, false));
-                return checkcast;
+                return new CheckCastNode(type, forObject, null, false);
             }
         }
         return this;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -40,7 +40,7 @@
  * Compress or uncompress an oop or metaspace pointer.
  */
 @NodeInfo(nameTemplate = "{p#op/s}")
-public final class CompressionNode extends ConvertNode implements LIRLowerable, Canonicalizable {
+public final class CompressionNode extends ConvertNode implements LIRLowerable {
 
     private enum CompressionOp {
         Compress,
@@ -151,11 +151,11 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (getValue().isConstant()) {
-            return ConstantNode.forConstant(stamp(), evalConst(getValue().asConstant()), tool.getMetaAccess(), graph());
-        } else if (getValue() instanceof CompressionNode) {
-            CompressionNode other = (CompressionNode) getValue();
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
+        if (forValue.isConstant()) {
+            return ConstantNode.forConstant(stamp(), evalConst(forValue.asConstant()), tool.getMetaAccess());
+        } else if (forValue instanceof CompressionNode) {
+            CompressionNode other = (CompressionNode) forValue;
             if (op != other.op && encoding.equals(other.encoding)) {
                 return other.getValue();
             }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Wed Jun 25 17:34:25 2014 +0200
@@ -223,7 +223,7 @@
         protected Arguments makeArguments(InstanceOfUsageReplacer replacer, LoweringTool tool) {
             if (replacer.instanceOf instanceof InstanceOfNode) {
                 InstanceOfNode instanceOf = (InstanceOfNode) replacer.instanceOf;
-                ValueNode object = instanceOf.object();
+                ValueNode object = instanceOf.getValue();
                 TypeCheckHints hintInfo = new TypeCheckHints(instanceOf.type(), instanceOf.profile(), tool.assumptions(), TypeCheckMinProfileHitProbability.getValue(), TypeCheckMaxHints.getValue());
                 final HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) instanceOf.type();
                 ConstantNode hub = ConstantNode.forConstant(type.klass(), providers.getMetaAccess(), instanceOf.graph());
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Wed Jun 25 17:34:25 2014 +0200
@@ -461,52 +461,52 @@
 
             @Override
             protected ValueNode genIntegerAdd(Kind kind, ValueNode x, ValueNode y) {
-                return new IntegerAddNode(StampFactory.forKind(kind), x, y);
+                return new IntegerAddNode(x, y);
             }
 
             @Override
             protected ValueNode genIntegerSub(Kind kind, ValueNode x, ValueNode y) {
-                return new IntegerSubNode(StampFactory.forKind(kind), x, y);
+                return new IntegerSubNode(x, y);
             }
 
             @Override
             protected ValueNode genIntegerMul(Kind kind, ValueNode x, ValueNode y) {
-                return new IntegerMulNode(StampFactory.forKind(kind), x, y);
+                return new IntegerMulNode(x, y);
             }
 
             @Override
             protected ValueNode genFloatAdd(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) {
-                return new FloatAddNode(StampFactory.forKind(kind), x, y, isStrictFP);
+                return new FloatAddNode(x, y, isStrictFP);
             }
 
             @Override
             protected ValueNode genFloatSub(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) {
-                return new FloatSubNode(StampFactory.forKind(kind), x, y, isStrictFP);
+                return new FloatSubNode(x, y, isStrictFP);
             }
 
             @Override
             protected ValueNode genFloatMul(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) {
-                return new FloatMulNode(StampFactory.forKind(kind), x, y, isStrictFP);
+                return new FloatMulNode(x, y, isStrictFP);
             }
 
             @Override
             protected ValueNode genFloatDiv(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) {
-                return new FloatDivNode(StampFactory.forKind(kind), x, y, isStrictFP);
+                return new FloatDivNode(x, y, isStrictFP);
             }
 
             @Override
             protected ValueNode genFloatRem(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) {
-                return new FloatRemNode(StampFactory.forKind(kind), x, y, isStrictFP);
+                return new FloatRemNode(x, y, isStrictFP);
             }
 
             @Override
             protected ValueNode genIntegerDiv(Kind kind, ValueNode x, ValueNode y) {
-                return new IntegerDivNode(StampFactory.forKind(kind), x, y);
+                return new IntegerDivNode(x, y);
             }
 
             @Override
             protected ValueNode genIntegerRem(Kind kind, ValueNode x, ValueNode y) {
-                return new IntegerRemNode(StampFactory.forKind(kind), x, y);
+                return new IntegerRemNode(x, y);
             }
 
             @Override
@@ -516,32 +516,32 @@
 
             @Override
             protected ValueNode genLeftShift(Kind kind, ValueNode x, ValueNode y) {
-                return new LeftShiftNode(StampFactory.forKind(kind), x, y);
+                return new LeftShiftNode(x, y);
             }
 
             @Override
             protected ValueNode genRightShift(Kind kind, ValueNode x, ValueNode y) {
-                return new RightShiftNode(StampFactory.forKind(kind), x, y);
+                return new RightShiftNode(x, y);
             }
 
             @Override
             protected ValueNode genUnsignedRightShift(Kind kind, ValueNode x, ValueNode y) {
-                return new UnsignedRightShiftNode(StampFactory.forKind(kind), x, y);
+                return new UnsignedRightShiftNode(x, y);
             }
 
             @Override
             protected ValueNode genAnd(Kind kind, ValueNode x, ValueNode y) {
-                return new AndNode(StampFactory.forKind(kind), x, y);
+                return new AndNode(x, y);
             }
 
             @Override
             protected ValueNode genOr(Kind kind, ValueNode x, ValueNode y) {
-                return new OrNode(StampFactory.forKind(kind), x, y);
+                return new OrNode(x, y);
             }
 
             @Override
             protected ValueNode genXor(Kind kind, ValueNode x, ValueNode y) {
-                return new XorNode(StampFactory.forKind(kind), x, y);
+                return new XorNode(x, y);
             }
 
             @Override
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValue.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValue.java	Wed Jun 25 17:34:25 2014 +0200
@@ -29,7 +29,6 @@
 import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
-import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
 
 /**
  * Base class to represent values that need to be stored in more than one register.
@@ -55,10 +54,6 @@
         valueClass = CompositeValueClass.get(getClass());
     }
 
-    public final void forEachComponent(OperandMode mode, ValueProcedure proc) {
-        valueClass.forEachComponent(this, mode, proc);
-    }
-
     public final void forEachComponent(LIRInstruction inst, OperandMode mode, InstructionValueProcedure proc) {
         valueClass.forEachComponent(inst, this, mode, proc);
     }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java	Wed Jun 25 17:34:25 2014 +0200
@@ -30,7 +30,6 @@
 import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
-import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
 
 /**
  * Lazily associated metadata for every {@link CompositeValue} type. The metadata includes:
@@ -140,10 +139,6 @@
         return str.toString();
     }
 
-    public final void forEachComponent(CompositeValue obj, OperandMode mode, ValueProcedure proc) {
-        forEach(obj, directComponentCount, componentOffsets, mode, componentFlags, proc);
-    }
-
     public final void forEachComponent(LIRInstruction inst, CompositeValue obj, OperandMode mode, InstructionValueProcedure proc) {
         forEach(inst, obj, directComponentCount, componentOffsets, mode, componentFlags, proc);
     }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java	Wed Jun 25 17:34:25 2014 +0200
@@ -31,7 +31,6 @@
 import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
-import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
 
 /**
  * This class represents garbage collection and deoptimization information attached to a LIR
@@ -60,22 +59,6 @@
     }
 
     /**
-     * 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.getValues(), proc);
-            }
-        }
-    }
-
-    /**
      * Iterates the frame state and calls the {@link InstructionValueProcedure} for every variable.
      *
      * @param proc The procedure called for variables.
@@ -97,20 +80,6 @@
      */
     protected static final EnumSet<OperandFlag> STATE_FLAGS = EnumSet.of(OperandFlag.REG, OperandFlag.STACK);
 
-    protected void processValues(Value[] values, ValueProcedure proc) {
-        for (int i = 0; i < values.length; i++) {
-            Value value = values[i];
-            values[i] = processValue(proc, value);
-        }
-    }
-
-    protected Value processValue(ValueProcedure proc, Value value) {
-        if (processed(value)) {
-            return proc.doValue(value, OperandMode.ALIVE, STATE_FLAGS);
-        }
-        return value;
-    }
-
     protected void processValues(LIRInstruction inst, Value[] values, InstructionValueProcedure proc) {
         for (int i = 0; i < values.length; i++) {
             Value value = values[i];
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java	Wed Jun 25 17:34:25 2014 +0200
@@ -46,36 +46,6 @@
      * methods. Clients of the class must only call the doValue method that takes additional
      * parameters.
      */
-    public abstract static class ValueProcedure {
-
-        /**
-         * Iterator method to be overwritten. This version of the iterator does not take additional
-         * parameters to keep the signature short.
-         *
-         * @param value The value that is iterated.
-         * @return The new value to replace the value that was passed in.
-         */
-        protected Value doValue(Value value) {
-            throw GraalInternalError.shouldNotReachHere("One of the doValue() methods must be overwritten");
-        }
-
-        /**
-         * Iterator method to be overwritten. This version of the iterator gets additional
-         * parameters about the processed value.
-         *
-         * @param value The value that is iterated.
-         * @param mode The operand mode for the value.
-         * @param flags A set of flags for the value.
-         * @return The new value to replace the value that was passed in.
-         */
-        public Value doValue(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
-            return doValue(value);
-        }
-    }
-
-    /**
-     * Similar to {@link ValueProcedure} but with an {@link LIRInstruction} parameter.
-     */
     public abstract static class InstructionValueProcedure {
 
         /**
@@ -105,6 +75,46 @@
         }
     }
 
+    /**
+     * Similar to {@link InstructionValueProcedure} but without an {@link LIRInstruction} parameter.
+     */
+    public abstract static class ValueProcedure extends InstructionValueProcedure {
+
+        /**
+         * Iterator method to be overwritten. This version of the iterator does not take additional
+         * parameters to keep the signature short.
+         *
+         * @param value The value that is iterated.
+         * @return The new value to replace the value that was passed in.
+         */
+        protected Value doValue(Value value) {
+            throw GraalInternalError.shouldNotReachHere("One of the doValue() methods must be overwritten");
+        }
+
+        /**
+         * Iterator method to be overwritten. This version of the iterator gets additional
+         * parameters about the processed value.
+         *
+         * @param value The value that is iterated.
+         * @param mode The operand mode for the value.
+         * @param flags A set of flags for the value.
+         * @return The new value to replace the value that was passed in.
+         */
+        protected Value doValue(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
+            return doValue(value);
+        }
+
+        @Override
+        final protected Value doValue(LIRInstruction instruction, Value value) {
+            throw GraalInternalError.shouldNotReachHere("This doValue() methods should never be called");
+        }
+
+        @Override
+        final public Value doValue(LIRInstruction instruction, Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
+            return doValue(value, mode, flags);
+        }
+    }
+
     public abstract static class StateProcedure {
 
         protected abstract void doState(LIRFrameState state);
@@ -287,26 +297,6 @@
         return false;
     }
 
-    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 forEachInput(InstructionValueProcedure proc) {
         instructionClass.forEachUse(this, proc);
     }
@@ -346,7 +336,7 @@
      *            clients can stop the iteration once a suitable hint has been found.
      * @return The non-null value returned by the procedure, or null.
      */
-    public Value forEachRegisterHint(Value value, OperandMode mode, ValueProcedure proc) {
+    public Value forEachRegisterHint(Value value, OperandMode mode, InstructionValueProcedure proc) {
         return instructionClass.forEachRegisterHint(this, mode, proc);
     }
 
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java	Wed Jun 25 17:34:25 2014 +0200
@@ -32,7 +32,6 @@
 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 extends LIRIntrospection {
 
@@ -263,22 +262,6 @@
         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 forEachUse(LIRInstruction obj, InstructionValueProcedure proc) {
         forEach(obj, obj, directUseCount, useOffsets, OperandMode.USE, useFlags, proc);
     }
@@ -295,15 +278,6 @@
         forEach(obj, obj, directDefCount, defOffsets, OperandMode.DEF, defFlags, proc);
     }
 
-    public final void forEachState(LIRInstruction obj, ValueProcedure proc) {
-        for (int i = 0; i < stateOffsets.length; i++) {
-            LIRFrameState state = getState(obj, stateOffsets[i]);
-            if (state != null) {
-                state.forEachState(proc);
-            }
-        }
-    }
-
     public final void forEachState(LIRInstruction obj, InstructionValueProcedure proc) {
         for (int i = 0; i < stateOffsets.length; i++) {
             LIRFrameState state = getState(obj, stateOffsets[i]);
@@ -322,7 +296,7 @@
         }
     }
 
-    public final Value forEachRegisterHint(LIRInstruction obj, OperandMode mode, ValueProcedure proc) {
+    public final Value forEachRegisterHint(LIRInstruction obj, OperandMode mode, InstructionValueProcedure proc) {
         int hintDirectCount = 0;
         long[] hintOffsets = null;
         if (mode == OperandMode.USE) {
@@ -338,7 +312,7 @@
         for (int i = 0; i < hintOffsets.length; i++) {
             if (i < hintDirectCount) {
                 Value hintValue = getValue(obj, hintOffsets[i]);
-                Value result = proc.doValue(hintValue, null, null);
+                Value result = proc.doValue(obj, hintValue, null, null);
                 if (result != null) {
                     return result;
                 }
@@ -346,7 +320,7 @@
                 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);
+                    Value result = proc.doValue(obj, hintValue, null, null);
                     if (result != null) {
                         return result;
                     }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java	Wed Jun 25 17:34:25 2014 +0200
@@ -35,7 +35,6 @@
 import com.oracle.graal.lir.LIRInstruction.InstructionValueProcedure;
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
-import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
 
 abstract class LIRIntrospection extends FieldIntrospection {
 
@@ -120,33 +119,6 @@
         }
     }
 
-    protected static void forEach(Object 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 (value instanceof CompositeValue) {
-                    CompositeValue composite = (CompositeValue) value;
-                    composite.forEachComponent(mode, 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 (value instanceof CompositeValue) {
-                        CompositeValue composite = (CompositeValue) value;
-                        composite.forEachComponent(mode, proc);
-                    } else {
-                        values[j] = proc.doValue(value, mode, flags[i]);
-                    }
-                }
-            }
-        }
-    }
-
     protected static void forEach(LIRInstruction inst, Object obj, int directCount, long[] offsets, OperandMode mode, EnumSet<OperandFlag>[] flags, InstructionValueProcedure proc) {
         for (int i = 0; i < offsets.length; i++) {
             assert LIRInstruction.ALLOWED_FLAGS.get(mode).containsAll(flags[i]);
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java	Wed Jun 25 17:34:25 2014 +0200
@@ -62,7 +62,7 @@
                 range = IntegerArithmeticNode.sub(graph, range, ConstantNode.forIntegerStamp(stamp, 1, graph));
             }
         }
-        IntegerDivNode div = graph.add(new IntegerDivNode(iv.valueNode().stamp().unrestricted(), range, iv.strideNode()));
+        IntegerDivNode div = graph.add(new IntegerDivNode(range, iv.strideNode()));
         graph.addBeforeFixed(loop.entryPoint(), div);
         ConstantNode zero = ConstantNode.forIntegerStamp(stamp, 0, graph);
         if (assumePositive) {
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedOffsetInductionVariable.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedOffsetInductionVariable.java	Wed Jun 25 17:34:25 2014 +0200
@@ -72,7 +72,7 @@
 
     @Override
     public long constantStride() {
-        if (value instanceof IntegerSubNode && base.valueNode() == value.y()) {
+        if (value instanceof IntegerSubNode && base.valueNode() == value.getY()) {
             return -base.constantStride();
         }
         return base.constantStride();
@@ -85,7 +85,7 @@
 
     @Override
     public ValueNode strideNode() {
-        if (value instanceof IntegerSubNode && base.valueNode() == value.y()) {
+        if (value instanceof IntegerSubNode && base.valueNode() == value.getY()) {
             return graph().unique(new NegateNode(base.strideNode()));
         }
         return base.strideNode();
@@ -116,10 +116,10 @@
             return b + o;
         }
         if (value instanceof IntegerSubNode) {
-            if (base.valueNode() == value.x()) {
+            if (base.valueNode() == value.getX()) {
                 return b - o;
             } else {
-                assert base.valueNode() == value.y();
+                assert base.valueNode() == value.getY();
                 return o - b;
             }
         }
@@ -131,10 +131,10 @@
             return IntegerArithmeticNode.add(graph(), b, o);
         }
         if (value instanceof IntegerSubNode) {
-            if (base.valueNode() == value.x()) {
+            if (base.valueNode() == value.getX()) {
                 return IntegerArithmeticNode.sub(graph(), b, o);
             } else {
-                assert base.valueNode() == value.y();
+                assert base.valueNode() == value.getY();
                 return IntegerArithmeticNode.sub(graph(), o, b);
             }
         }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariables.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariables.java	Wed Jun 25 17:34:25 2014 +0200
@@ -95,10 +95,10 @@
     private ValueNode addSub(ValueNode op, ValueNode base) {
         if (op instanceof IntegerAddNode || op instanceof IntegerSubNode) {
             IntegerArithmeticNode aritOp = (IntegerArithmeticNode) op;
-            if (aritOp.x() == base && loop.isOutsideLoop(aritOp.y())) {
-                return aritOp.y();
-            } else if (aritOp.y() == base && loop.isOutsideLoop(aritOp.x())) {
-                return aritOp.x();
+            if (aritOp.getX() == base && loop.isOutsideLoop(aritOp.getY())) {
+                return aritOp.getY();
+            } else if (aritOp.getY() == base && loop.isOutsideLoop(aritOp.getX())) {
+                return aritOp.getX();
             }
         }
         return null;
@@ -107,16 +107,16 @@
     private ValueNode mul(ValueNode op, ValueNode base) {
         if (op instanceof IntegerMulNode) {
             IntegerMulNode mul = (IntegerMulNode) op;
-            if (mul.x() == base && loop.isOutsideLoop(mul.y())) {
-                return mul.y();
-            } else if (mul.y() == base && loop.isOutsideLoop(mul.x())) {
-                return mul.x();
+            if (mul.getX() == base && loop.isOutsideLoop(mul.getY())) {
+                return mul.getY();
+            } else if (mul.getY() == base && loop.isOutsideLoop(mul.getX())) {
+                return mul.getX();
             }
         }
         if (op instanceof LeftShiftNode) {
             LeftShiftNode shift = (LeftShiftNode) op;
-            if (shift.x() == base && shift.y().isConstant()) {
-                return ConstantNode.forInt(1 << shift.y().asConstant().asInt(), base.graph());
+            if (shift.getX() == base && shift.getY().isConstant()) {
+                return ConstantNode.forInt(1 << shift.getY().asConstant().asInt(), base.graph());
             }
         }
         return null;
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java	Wed Jun 25 17:34:25 2014 +0200
@@ -141,11 +141,15 @@
             if (!BinaryNode.canTryReassociate(binary)) {
                 continue;
             }
-            BinaryNode result = BinaryNode.reassociate(binary, invariant);
+            BinaryNode result = BinaryNode.reassociate(binary, invariant, binary.getX(), binary.getY());
             if (result != binary) {
                 if (Debug.isLogEnabled()) {
                     Debug.log("%s : Reassociated %s into %s", MetaUtil.format("%H::%n", graph.method()), binary, result);
                 }
+                if (!result.isAlive()) {
+                    assert !result.isDeleted();
+                    result = graph.addOrUniqueWithInputs(result);
+                }
                 graph.replaceFloating(binary, result);
             }
         }
@@ -177,17 +181,17 @@
             Condition condition = null;
             InductionVariable iv = null;
             ValueNode limit = null;
-            if (isOutsideLoop(lessThan.x())) {
-                iv = getInductionVariables().get(lessThan.y());
+            if (isOutsideLoop(lessThan.getX())) {
+                iv = getInductionVariables().get(lessThan.getY());
                 if (iv != null) {
                     condition = lessThan.condition().mirror();
-                    limit = lessThan.x();
+                    limit = lessThan.getX();
                 }
-            } else if (isOutsideLoop(lessThan.y())) {
-                iv = getInductionVariables().get(lessThan.x());
+            } else if (isOutsideLoop(lessThan.getY())) {
+                iv = getInductionVariables().get(lessThan.getX());
                 if (iv != null) {
                     condition = lessThan.condition();
-                    limit = lessThan.y();
+                    limit = lessThan.getY();
                 }
             }
             if (condition == null) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -78,7 +78,7 @@
     public void simplify(SimplifierTool tool) {
         while (condition instanceof LogicNegationNode) {
             LogicNegationNode negation = (LogicNegationNode) condition;
-            setCondition(negation.getInput());
+            setCondition(negation.getValue());
             negated = !negated;
         }
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -22,22 +22,19 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.ProfilingInfo.TriState;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.spi.*;
 
-public abstract class BinaryOpLogicNode extends LogicNode implements LIRLowerable, Canonicalizable {
+public abstract class BinaryOpLogicNode extends LogicNode implements LIRLowerable, Canonicalizable.Binary<ValueNode> {
 
     @Input private ValueNode x;
     @Input private ValueNode y;
 
-    public ValueNode x() {
+    public ValueNode getX() {
         return x;
     }
 
-    public ValueNode y() {
+    public ValueNode getY() {
         return y;
     }
 
@@ -57,8 +54,6 @@
         this.y = y;
     }
 
-    public abstract TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY);
-
     @Override
     public boolean verify() {
         assertTrue(x.stamp().isCompatible(y.stamp()), "stamps not compatible: %s, %s", x.stamp(), y.stamp());
@@ -66,17 +61,6 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        switch (evaluate(tool.getConstantReflection(), x(), y())) {
-            case FALSE:
-                return LogicConstantNode.contradiction(graph());
-            case TRUE:
-                return LogicConstantNode.tautology(graph());
-        }
-        return this;
-    }
-
-    @Override
     public void generate(NodeLIRBuilderTool gen) {
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConditionAnchorNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConditionAnchorNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -70,7 +70,7 @@
     public Node canonical(CanonicalizerTool tool) {
         if (condition instanceof LogicNegationNode) {
             LogicNegationNode negation = (LogicNegationNode) condition;
-            setCondition(negation.getInput());
+            setCondition(negation.getValue());
             negated = !negated;
         }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -114,10 +114,25 @@
         }
     }
 
+    public static ConstantNode forConstant(Constant constant, MetaAccessProvider metaAccess) {
+        if (constant.getKind().getStackKind() == Kind.Int && constant.getKind() != Kind.Int) {
+            return forInt(constant.asInt());
+        }
+        if (constant.getKind() == Kind.Object) {
+            return new ConstantNode(constant, StampFactory.forConstant(constant, metaAccess));
+        } else {
+            return createPrimitive(constant);
+        }
+    }
+
     public static ConstantNode forConstant(Stamp stamp, Constant constant, MetaAccessProvider metaAccess, StructuredGraph graph) {
         return graph.unique(new ConstantNode(constant, stamp.constant(constant, metaAccess)));
     }
 
+    public static ConstantNode forConstant(Stamp stamp, Constant constant, MetaAccessProvider metaAccess) {
+        return new ConstantNode(constant, stamp.constant(constant, metaAccess));
+    }
+
     /**
      * Returns a node for a Java primitive.
      */
@@ -127,6 +142,14 @@
     }
 
     /**
+     * Returns a node for a Java primitive.
+     */
+    public static ConstantNode forPrimitive(Constant constant) {
+        assert constant.getKind() != Kind.Object;
+        return forConstant(constant, null);
+    }
+
+    /**
      * Returns a node for a primitive of a given type.
      */
     public static ConstantNode forPrimitive(Stamp stamp, Constant constant, StructuredGraph graph) {
@@ -141,6 +164,20 @@
     }
 
     /**
+     * Returns a node for a primitive of a given type.
+     */
+    public static ConstantNode forPrimitive(Stamp stamp, Constant constant) {
+        if (stamp instanceof IntegerStamp) {
+            assert constant.getKind().isNumericInteger() && stamp.getStackKind() == constant.getKind().getStackKind();
+            IntegerStamp istamp = (IntegerStamp) stamp;
+            return forIntegerBits(istamp.getBits(), constant);
+        } else {
+            assert constant.getKind().isNumericFloat() && stamp.getStackKind() == constant.getKind();
+            return forConstant(constant, null);
+        }
+    }
+
+    /**
      * Returns a node for a double constant.
      *
      * @param d the double value for which to create the instruction
@@ -151,6 +188,16 @@
     }
 
     /**
+     * Returns a node for a double constant.
+     *
+     * @param d the double value for which to create the instruction
+     * @return a node for a double constant
+     */
+    public static ConstantNode forDouble(double d) {
+        return createPrimitive(Constant.forDouble(d));
+    }
+
+    /**
      * Returns a node for a float constant.
      *
      * @param f the float value for which to create the instruction
@@ -161,6 +208,16 @@
     }
 
     /**
+     * Returns a node for a float constant.
+     *
+     * @param f the float value for which to create the instruction
+     * @return a node for a float constant
+     */
+    public static ConstantNode forFloat(float f) {
+        return createPrimitive(Constant.forFloat(f));
+    }
+
+    /**
      * Returns a node for an long constant.
      *
      * @param i the long value for which to create the instruction
@@ -171,6 +228,16 @@
     }
 
     /**
+     * Returns a node for an long constant.
+     *
+     * @param i the long value for which to create the instruction
+     * @return a node for an long constant
+     */
+    public static ConstantNode forLong(long i) {
+        return createPrimitive(Constant.forLong(i));
+    }
+
+    /**
      * Returns a node for an integer constant.
      *
      * @param i the integer value for which to create the instruction
@@ -181,6 +248,16 @@
     }
 
     /**
+     * Returns a node for an integer constant.
+     *
+     * @param i the integer value for which to create the instruction
+     * @return a node for an integer constant
+     */
+    public static ConstantNode forInt(int i) {
+        return createPrimitive(Constant.forInt(i));
+    }
+
+    /**
      * Returns a node for a boolean constant.
      *
      * @param i the boolean value for which to create the instruction
@@ -191,6 +268,16 @@
     }
 
     /**
+     * Returns a node for a boolean constant.
+     *
+     * @param i the boolean value for which to create the instruction
+     * @return a node representing the boolean
+     */
+    public static ConstantNode forBoolean(boolean i) {
+        return createPrimitive(Constant.forInt(i ? 1 : 0));
+    }
+
+    /**
      * Returns a node for a byte constant.
      *
      * @param i the byte value for which to create the instruction
@@ -238,6 +325,20 @@
         return forIntegerBits(bits, Constant.forPrimitiveInt(bits, value), graph);
     }
 
+    private static ConstantNode forIntegerBits(int bits, Constant constant) {
+        long value = constant.asLong();
+        long bounds = SignExtendNode.signExtend(value, bits);
+        return new ConstantNode(constant, StampFactory.forInteger(bits, bounds, bounds));
+    }
+
+    /**
+     * Returns a node for a constant integer that's not directly representable as Java primitive
+     * (e.g. short).
+     */
+    public static ConstantNode forIntegerBits(int bits, long value) {
+        return forIntegerBits(bits, Constant.forPrimitiveInt(bits, value));
+    }
+
     /**
      * Returns a node for a constant integer that's compatible to a given stamp.
      */
@@ -250,6 +351,18 @@
         }
     }
 
+    /**
+     * Returns a node for a constant integer that's compatible to a given stamp.
+     */
+    public static ConstantNode forIntegerStamp(Stamp stamp, long value) {
+        if (stamp instanceof IntegerStamp) {
+            IntegerStamp intStamp = (IntegerStamp) stamp;
+            return forIntegerBits(intStamp.getBits(), value);
+        } else {
+            return forIntegerKind(stamp.getStackKind(), value);
+        }
+    }
+
     public static ConstantNode forIntegerKind(Kind kind, long value, StructuredGraph graph) {
         switch (kind) {
             case Byte:
@@ -263,6 +376,19 @@
         }
     }
 
+    public static ConstantNode forIntegerKind(Kind kind, long value) {
+        switch (kind) {
+            case Byte:
+            case Short:
+            case Int:
+                return createPrimitive(Constant.forInt((int) value));
+            case Long:
+                return createPrimitive(Constant.forLong(value));
+            default:
+                throw GraalInternalError.shouldNotReachHere("unknown kind " + kind);
+        }
+    }
+
     public static ConstantNode forFloatingKind(Kind kind, double value, StructuredGraph graph) {
         switch (kind) {
             case Float:
@@ -274,6 +400,17 @@
         }
     }
 
+    public static ConstantNode forFloatingKind(Kind kind, double value) {
+        switch (kind) {
+            case Float:
+                return ConstantNode.forFloat((float) value);
+            case Double:
+                return ConstantNode.forDouble(value);
+            default:
+                throw GraalInternalError.shouldNotReachHere("unknown kind " + kind);
+        }
+    }
+
     /**
      * Returns a node for a constant double that's compatible to a given stamp.
      */
@@ -281,6 +418,13 @@
         return forFloatingKind(stamp.getStackKind(), value, graph);
     }
 
+    /**
+     * Returns a node for a constant double that's compatible to a given stamp.
+     */
+    public static ConstantNode forFloatingStamp(Stamp stamp, double value) {
+        return forFloatingKind(stamp.getStackKind(), value);
+    }
+
     public static ConstantNode defaultForKind(Kind kind, StructuredGraph graph) {
         switch (kind) {
             case Boolean:
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -103,7 +103,7 @@
     public Node canonical(CanonicalizerTool tool) {
         if (condition() instanceof LogicNegationNode) {
             LogicNegationNode negation = (LogicNegationNode) condition();
-            return graph().unique(new GuardNode(negation.getInput(), getAnchor(), reason, action, !negated, speculation));
+            return graph().unique(new GuardNode(negation.getValue(), getAnchor(), reason, action, !negated, speculation));
         } else if (condition() instanceof LogicConstantNode) {
             LogicConstantNode c = (LogicConstantNode) condition();
             if (c.getValue() != negated) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -147,7 +147,7 @@
             setTrueSuccessor(null);
             setFalseSuccessor(null);
             LogicNegationNode negation = (LogicNegationNode) condition();
-            IfNode newIfNode = graph().add(new IfNode(negation.getInput(), falseSucc, trueSucc, 1 - trueSuccessorProbability));
+            IfNode newIfNode = graph().add(new IfNode(negation.getValue(), falseSucc, trueSucc, 1 - trueSuccessorProbability));
             predecessor().replaceFirstSuccessor(this, newIfNode);
             GraphUtil.killWithUnusedFloatingInputs(this);
             return;
@@ -259,7 +259,7 @@
         assert trueSuccessor().usages().isEmpty() && falseSuccessor().usages().isEmpty();
         if (condition() instanceof IntegerLessThanNode) {
             IntegerLessThanNode lessThan = (IntegerLessThanNode) condition();
-            Constant y = lessThan.y().stamp().asConstant();
+            Constant y = lessThan.getY().stamp().asConstant();
             if (y != null && y.asLong() == 0 && falseSuccessor().next() instanceof IfNode) {
                 IfNode ifNode2 = (IfNode) falseSuccessor().next();
                 if (ifNode2.condition() instanceof IntegerLessThanNode) {
@@ -271,24 +271,24 @@
                      * Convert x >= 0 && x < positive which is represented as !(x < 0) && x <
                      * <positive> into an unsigned compare.
                      */
-                    if (lessThan2.x() == lessThan.x() && lessThan2.y().stamp() instanceof IntegerStamp && ((IntegerStamp) lessThan2.y().stamp()).isPositive() &&
+                    if (lessThan2.getX() == lessThan.getX() && lessThan2.getY().stamp() instanceof IntegerStamp && ((IntegerStamp) lessThan2.getY().stamp()).isPositive() &&
                                     sameDestination(trueSuccessor(), ifNode2.falseSuccessor)) {
-                        below = graph().unique(new IntegerBelowThanNode(lessThan2.x(), lessThan2.y()));
+                        below = graph().unique(new IntegerBelowThanNode(lessThan2.getX(), lessThan2.getY()));
                         // swap direction
                         BeginNode tmp = falseSucc;
                         falseSucc = trueSucc;
                         trueSucc = tmp;
-                    } else if (lessThan2.y() == lessThan.x() && sameDestination(trueSuccessor(), ifNode2.trueSuccessor)) {
+                    } else if (lessThan2.getY() == lessThan.getX() && sameDestination(trueSuccessor(), ifNode2.trueSuccessor)) {
                         /*
                          * Convert x >= 0 && x <= positive which is represented as !(x < 0) &&
                          * !(<positive> > x), into x <| positive + 1. This can only be done for
                          * constants since there isn't a IntegerBelowEqualThanNode but that doesn't
                          * appear to be interesting.
                          */
-                        Constant positive = lessThan2.x().asConstant();
+                        Constant positive = lessThan2.getX().asConstant();
                         if (positive != null && positive.asLong() > 0 && positive.asLong() < positive.getKind().getMaxValue()) {
                             ConstantNode newLimit = ConstantNode.forIntegerKind(positive.getKind(), positive.asLong() + 1, graph());
-                            below = graph().unique(new IntegerBelowThanNode(lessThan.x(), newLimit));
+                            below = graph().unique(new IntegerBelowThanNode(lessThan.getX(), newLimit));
                         }
                     }
                     if (below != null) {
@@ -355,7 +355,7 @@
             InstanceOfNode instanceOfA = (InstanceOfNode) a;
             if (b instanceof IsNullNode) {
                 IsNullNode isNullNode = (IsNullNode) b;
-                if (isNullNode.object() == instanceOfA.object()) {
+                if (isNullNode.getValue() == instanceOfA.getValue()) {
                     if (instanceOfA.profile() != null && instanceOfA.profile().getNullSeen() != TriState.FALSE) {
                         instanceOfA.setProfile(new JavaTypeProfile(TriState.FALSE, instanceOfA.profile().getNotRecordedProbability(), instanceOfA.profile().getTypes()));
                     }
@@ -364,7 +364,7 @@
                 }
             } else if (b instanceof InstanceOfNode) {
                 InstanceOfNode instanceOfB = (InstanceOfNode) b;
-                if (instanceOfA.object() == instanceOfB.object() && !instanceOfA.type().isInterface() && !instanceOfB.type().isInterface() &&
+                if (instanceOfA.getValue() == instanceOfB.getValue() && !instanceOfA.type().isInterface() && !instanceOfB.type().isInterface() &&
                                 !instanceOfA.type().isAssignableFrom(instanceOfB.type()) && !instanceOfB.type().isAssignableFrom(instanceOfA.type())) {
                     // Two instanceof on the same value with mutually exclusive types.
                     JavaTypeProfile profileA = instanceOfA.profile();
@@ -425,9 +425,9 @@
                 }
                 Condition comparableCondition = null;
                 Condition conditionB = compareB.condition();
-                if (compareB.x() == compareA.x() && compareB.y() == compareA.y()) {
+                if (compareB.getX() == compareA.getX() && compareB.getY() == compareA.getY()) {
                     comparableCondition = conditionB;
-                } else if (compareB.x() == compareA.y() && compareB.y() == compareA.x()) {
+                } else if (compareB.getX() == compareA.getY() && compareB.getY() == compareA.getX()) {
                     comparableCondition = conditionB.mirror();
                 }
 
@@ -440,13 +440,13 @@
                     }
                 } else if (conditionA == Condition.EQ && conditionB == Condition.EQ) {
                     boolean canSwap = false;
-                    if ((compareA.x() == compareB.x() && valuesDistinct(constantReflection, compareA.y(), compareB.y()))) {
+                    if ((compareA.getX() == compareB.getX() && valuesDistinct(constantReflection, compareA.getY(), compareB.getY()))) {
                         canSwap = true;
-                    } else if ((compareA.x() == compareB.y() && valuesDistinct(constantReflection, compareA.y(), compareB.x()))) {
+                    } else if ((compareA.getX() == compareB.getY() && valuesDistinct(constantReflection, compareA.getY(), compareB.getX()))) {
                         canSwap = true;
-                    } else if ((compareA.y() == compareB.x() && valuesDistinct(constantReflection, compareA.x(), compareB.y()))) {
+                    } else if ((compareA.getY() == compareB.getX() && valuesDistinct(constantReflection, compareA.getX(), compareB.getY()))) {
                         canSwap = true;
-                    } else if ((compareA.y() == compareB.y() && valuesDistinct(constantReflection, compareA.x(), compareB.x()))) {
+                    } else if ((compareA.getY() == compareB.getY() && valuesDistinct(constantReflection, compareA.getX(), compareB.getX()))) {
                         canSwap = true;
                     }
 
@@ -645,7 +645,7 @@
             return false;
         }
         Node singleUsage = mergeUsages.first();
-        if (!(singleUsage instanceof ValuePhiNode) || (singleUsage != compare.x() && singleUsage != compare.y())) {
+        if (!(singleUsage instanceof ValuePhiNode) || (singleUsage != compare.getX() && singleUsage != compare.getY())) {
             return false;
         }
 
@@ -664,8 +664,8 @@
         List<AbstractEndNode> mergePredecessors = merge.cfgPredecessors().snapshot();
         assert phi.valueCount() == merge.forwardEndCount();
 
-        Constant[] xs = constantValues(compare.x(), merge, false);
-        Constant[] ys = constantValues(compare.y(), merge, false);
+        Constant[] xs = constantValues(compare.getX(), merge, false);
+        Constant[] ys = constantValues(compare.getY(), merge, false);
         if (xs == null || ys == null) {
             return false;
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicConstantNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicConstantNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -40,7 +40,7 @@
 
     /**
      * Returns a node for a boolean constant.
-     * 
+     *
      * @param v the boolean value for which to create the instruction
      * @param graph
      * @return a node representing the boolean
@@ -50,6 +50,16 @@
     }
 
     /**
+     * Returns a node for a boolean constant.
+     *
+     * @param v the boolean value for which to create the instruction
+     * @return a node representing the boolean
+     */
+    public static LogicConstantNode forBoolean(boolean v) {
+        return new LogicConstantNode(v);
+    }
+
+    /**
      * Gets a constant for {@code true}.
      */
     public static LogicConstantNode tautology(Graph graph) {
@@ -63,6 +73,20 @@
         return forBoolean(false, graph);
     }
 
+    /**
+     * Gets a constant for {@code true}.
+     */
+    public static LogicConstantNode tautology() {
+        return forBoolean(true);
+    }
+
+    /**
+     * Gets a constant for {@code false}.
+     */
+    public static LogicConstantNode contradiction() {
+        return forBoolean(false);
+    }
+
     public boolean getValue() {
         return value;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNegationNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNegationNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -28,22 +28,22 @@
 /**
  * Logic node that negates its argument.
  */
-public class LogicNegationNode extends LogicNode implements Canonicalizable {
+public class LogicNegationNode extends LogicNode implements Canonicalizable.Unary<LogicNode> {
 
-    @Input(InputType.Condition) private LogicNode input;
+    @Input(InputType.Condition) private LogicNode value;
 
-    public LogicNegationNode(LogicNode input) {
-        this.input = input;
+    public LogicNegationNode(LogicNode value) {
+        this.value = value;
     }
 
-    public LogicNode getInput() {
-        return input;
+    public LogicNode getValue() {
+        return value;
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (input instanceof LogicNegationNode) {
-            return ((LogicNegationNode) input).getInput();
+    public LogicNode canonical(CanonicalizerTool tool, LogicNode forValue) {
+        if (forValue instanceof LogicNegationNode) {
+            return ((LogicNegationNode) forValue).getValue();
         } else {
             return this;
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -243,10 +243,10 @@
             long increment = NO_INCREMENT;
             if (input != null && input instanceof IntegerAddNode) {
                 IntegerAddNode add = (IntegerAddNode) input;
-                if (add.x() == phi && add.y().isConstant()) {
-                    increment = add.y().asConstant().asLong();
-                } else if (add.y() == phi && add.x().isConstant()) {
-                    increment = add.x().asConstant().asLong();
+                if (add.getX() == phi && add.getY().isConstant()) {
+                    increment = add.getY().asConstant().asLong();
+                } else if (add.getY() == phi && add.getX().isConstant()) {
+                    increment = add.getX().asConstant().asLong();
                 }
             } else if (input == phi) {
                 increment = 0;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ShortCircuitOrNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ShortCircuitOrNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,7 +25,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 
-public class ShortCircuitOrNode extends LogicNode implements IterableNodeType, Canonicalizable {
+public class ShortCircuitOrNode extends LogicNode implements IterableNodeType, Canonicalizable.Binary<LogicNode> {
 
     @Input(InputType.Condition) private LogicNode x;
     @Input(InputType.Condition) private LogicNode y;
@@ -65,36 +65,40 @@
         return shortCircuitProbability;
     }
 
-    protected ShortCircuitOrNode canonicalizeNegation() {
-        LogicNode xCond = x;
+    protected ShortCircuitOrNode canonicalizeNegation(LogicNode forX, LogicNode forY) {
+        LogicNode xCond = forX;
         boolean xNeg = xNegated;
         while (xCond instanceof LogicNegationNode) {
-            xCond = ((LogicNegationNode) xCond).getInput();
+            xCond = ((LogicNegationNode) xCond).getValue();
             xNeg = !xNeg;
         }
 
-        LogicNode yCond = y;
+        LogicNode yCond = forY;
         boolean yNeg = yNegated;
         while (yCond instanceof LogicNegationNode) {
-            yCond = ((LogicNegationNode) yCond).getInput();
+            yCond = ((LogicNegationNode) yCond).getValue();
             yNeg = !yNeg;
         }
 
-        if (xCond != x || yCond != y) {
-            return graph().unique(new ShortCircuitOrNode(xCond, xNeg, yCond, yNeg, shortCircuitProbability));
+        if (xCond != forX || yCond != forY) {
+            return new ShortCircuitOrNode(xCond, xNeg, yCond, yNeg, shortCircuitProbability);
         } else {
-            return null;
+            return this;
         }
     }
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
-        ShortCircuitOrNode ret = canonicalizeNegation();
-        if (ret != null) {
+        return canonical(tool, getX(), getY());
+    }
+
+    public LogicNode canonical(CanonicalizerTool tool, LogicNode forX, LogicNode forY) {
+        ShortCircuitOrNode ret = canonicalizeNegation(forX, forY);
+        if (ret != this) {
             return ret;
         }
 
-        if (getX() == getY()) {
+        if (forX == forY) {
             // @formatter:off
             //  a ||  a = a
             //  a || !a = true
@@ -104,40 +108,40 @@
             if (isXNegated()) {
                 if (isYNegated()) {
                     // !a || !a = !a
-                    return graph().unique(new LogicNegationNode(getX()));
+                    return new LogicNegationNode(forX);
                 } else {
                     // !a || a = true
-                    return LogicConstantNode.tautology(graph());
+                    return LogicConstantNode.tautology();
                 }
             } else {
                 if (isYNegated()) {
                     // a || !a = true
-                    return LogicConstantNode.tautology(graph());
+                    return LogicConstantNode.tautology();
                 } else {
                     // a || a = a
-                    return getX();
+                    return forX;
                 }
             }
         }
-        if (getX() instanceof LogicConstantNode) {
-            if (((LogicConstantNode) getX()).getValue() ^ isXNegated()) {
-                return LogicConstantNode.tautology(graph());
+        if (forX instanceof LogicConstantNode) {
+            if (((LogicConstantNode) forX).getValue() ^ isXNegated()) {
+                return LogicConstantNode.tautology();
             } else {
                 if (isYNegated()) {
-                    return graph().unique(new LogicNegationNode(getY()));
+                    return new LogicNegationNode(forY);
                 } else {
-                    return getY();
+                    return forY;
                 }
             }
         }
-        if (getY() instanceof LogicConstantNode) {
-            if (((LogicConstantNode) getY()).getValue() ^ isYNegated()) {
-                return LogicConstantNode.tautology(graph());
+        if (forY instanceof LogicConstantNode) {
+            if (((LogicConstantNode) forY).getValue() ^ isYNegated()) {
+                return LogicConstantNode.tautology();
             } else {
                 if (isXNegated()) {
-                    return graph().unique(new LogicNegationNode(getX()));
+                    return new LogicNegationNode(forX);
                 } else {
-                    return getX();
+                    return forX;
                 }
             }
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/TypeProfileProxyNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -35,7 +35,7 @@
 /**
  * A node that attaches a type profile to a proxied input node.
  */
-public final class TypeProfileProxyNode extends UnaryNode implements Canonicalizable, IterableNodeType, ValueProxy {
+public final class TypeProfileProxyNode extends UnaryNode implements IterableNodeType, ValueProxy {
 
     private final JavaTypeProfile profile;
     private transient ResolvedJavaType lastCheckedType;
@@ -71,12 +71,12 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (StampTool.isExactType(getValue())) {
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
+        if (StampTool.isExactType(forValue)) {
             // The profile is useless - we know the type!
-            return getValue();
-        } else if (getValue() instanceof TypeProfileProxyNode) {
-            TypeProfileProxyNode other = (TypeProfileProxyNode) getValue();
+            return forValue;
+        } else if (forValue instanceof TypeProfileProxyNode) {
+            TypeProfileProxyNode other = (TypeProfileProxyNode) forValue;
             JavaTypeProfile otherProfile = other.getProfile();
             if (otherProfile == lastCheckedProfile) {
                 // We have already incorporated the knowledge about this profile => abort.
@@ -87,33 +87,33 @@
             if (newProfile.equals(otherProfile)) {
                 // We are useless - just use the other proxy node.
                 Debug.log("Canonicalize with other proxy node.");
-                return getValue();
+                return forValue;
             }
             if (newProfile != this.profile) {
                 Debug.log("Improved profile via other profile.");
-                return TypeProfileProxyNode.create(getValue(), newProfile);
+                return new TypeProfileProxyNode(forValue, newProfile);
             }
-        } else if (StampTool.typeOrNull(getValue()) != null) {
-            ResolvedJavaType type = StampTool.typeOrNull(getValue());
+        } else if (StampTool.typeOrNull(forValue) != null) {
+            ResolvedJavaType type = StampTool.typeOrNull(forValue);
             ResolvedJavaType uniqueConcrete = type.findUniqueConcreteSubtype();
             if (uniqueConcrete != null) {
                 // Profile is useless => remove.
                 Debug.log("Profile useless, there is enough static type information available.");
-                return getValue();
+                return forValue;
             }
             if (Objects.equals(type, lastCheckedType)) {
                 // We have already incorporate the knowledge about this type => abort.
                 return this;
             }
             lastCheckedType = type;
-            JavaTypeProfile newProfile = this.profile.restrict(type, StampTool.isObjectNonNull(getValue()));
+            JavaTypeProfile newProfile = this.profile.restrict(type, StampTool.isObjectNonNull(forValue));
             if (newProfile != this.profile) {
                 Debug.log("Improved profile via static type information.");
                 if (newProfile.getTypes().length == 0) {
                     // Only null profiling is not beneficial enough to keep the node around.
-                    return getValue();
+                    return forValue;
                 }
-                return TypeProfileProxyNode.create(getValue(), newProfile);
+                return new TypeProfileProxyNode(forValue, newProfile);
             }
         }
         return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnaryOpLogicNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnaryOpLogicNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -22,29 +22,22 @@
  */
 package com.oracle.graal.nodes;
 
-import com.oracle.graal.api.meta.ProfilingInfo.TriState;
+import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.spi.*;
 
-public abstract class UnaryOpLogicNode extends LogicNode implements LIRLowerable {
+public abstract class UnaryOpLogicNode extends LogicNode implements LIRLowerable, Canonicalizable.Unary<ValueNode> {
 
-    @Input private ValueNode object;
+    @Input private ValueNode value;
 
-    public ValueNode object() {
-        return object;
+    public ValueNode getValue() {
+        return value;
     }
 
-    protected void setX(ValueNode object) {
-        updateUsages(this.object, object);
-        this.object = object;
+    public UnaryOpLogicNode(ValueNode value) {
+        assert value != null;
+        this.value = value;
     }
 
-    public UnaryOpLogicNode(ValueNode object) {
-        assert object != null;
-        this.object = object;
-    }
-
-    public abstract TriState evaluate(ValueNode forObject);
-
     @Override
     public void generate(NodeLIRBuilderTool gen) {
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValuePhiNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValuePhiNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -34,7 +34,7 @@
 @NodeInfo(nameTemplate = "ValuePhi({i#values})")
 public class ValuePhiNode extends PhiNode implements Simplifiable {
 
-    @Input final NodeInputList<ValueNode> values = new NodeInputList<>(this);
+    @Input final NodeInputList<ValueNode> values;
 
     /**
      * Create a value phi with the specified stamp.
@@ -45,6 +45,20 @@
     public ValuePhiNode(Stamp stamp, MergeNode merge) {
         super(stamp, merge);
         assert stamp != StampFactory.forVoid();
+        values = new NodeInputList<>(this);
+    }
+
+    /**
+     * Create a value phi with the specified stamp and the given values.
+     *
+     * @param stamp the stamp of the value
+     * @param merge the merge that the new phi belongs to
+     * @param values the initial values of the phi
+     */
+    public ValuePhiNode(Stamp stamp, MergeNode merge, ValueNode[] values) {
+        super(stamp, merge);
+        assert stamp != StampFactory.forVoid();
+        this.values = new NodeInputList<>(this, values);
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -30,17 +30,19 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "&")
-public final class AndNode extends BitLogicNode implements Canonicalizable, NarrowableArithmeticNode {
+public final class AndNode extends BitLogicNode implements NarrowableArithmeticNode {
 
-    public AndNode(Stamp stamp, ValueNode x, ValueNode y) {
-        super(stamp, x, y);
+    public AndNode(ValueNode x, ValueNode y) {
+        super(StampTool.and(x.stamp(), y.stamp()), x, y);
+        assert x.stamp().isCompatible(y.stamp());
     }
 
     @Override
     public boolean inferStamp() {
-        return updateStamp(StampTool.and(x().stamp(), y().stamp()));
+        return updateStamp(StampTool.and(getX().stamp(), getY().stamp()));
     }
 
     @Override
@@ -50,46 +52,45 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (x() == y()) {
-            return x();
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
+            return forX;
         }
-        if (x().isConstant() && !y().isConstant()) {
-            return graph().unique(new AndNode(stamp(), y(), x()));
+        if (forX.isConstant() && !forY.isConstant()) {
+            return new AndNode(forY, forX);
         }
-        if (x().isConstant()) {
-            return ConstantNode.forPrimitive(stamp(), evalConst(x().asConstant(), y().asConstant()), graph());
-        } else if (y().isConstant()) {
-            long rawY = y().asConstant().asLong();
+        if (forX.isConstant()) {
+            return ConstantNode.forPrimitive(stamp(), evalConst(forX.asConstant(), forY.asConstant()));
+        } else if (forY.isConstant()) {
+            long rawY = forY.asConstant().asLong();
             long mask = IntegerStamp.defaultMask(PrimitiveStamp.getBits(stamp()));
             if ((rawY & mask) == mask) {
-                return x();
+                return forX;
             }
             if ((rawY & mask) == 0) {
-                return ConstantNode.forIntegerStamp(stamp(), 0, graph());
+                return ConstantNode.forIntegerStamp(stamp(), 0);
             }
-            if (x() instanceof SignExtendNode) {
-                SignExtendNode ext = (SignExtendNode) x();
+            if (forX instanceof SignExtendNode) {
+                SignExtendNode ext = (SignExtendNode) forX;
                 if (rawY == ((1L << ext.getInputBits()) - 1)) {
-                    ValueNode result = graph().unique(new ZeroExtendNode(ext.getValue(), ext.getResultBits()));
-                    return result;
+                    return new ZeroExtendNode(ext.getValue(), ext.getResultBits());
                 }
             }
-            if (x().stamp() instanceof IntegerStamp) {
-                IntegerStamp xStamp = (IntegerStamp) x().stamp();
+            if (forX.stamp() instanceof IntegerStamp) {
+                IntegerStamp xStamp = (IntegerStamp) forX.stamp();
                 if (((xStamp.upMask() | xStamp.downMask()) & ~rawY) == 0) {
                     // No bits are set which are outside the mask, so the mask will have no effect.
-                    return x();
+                    return forX;
                 }
             }
 
-            return BinaryNode.reassociate(this, ValueNode.isConstantPredicate());
+            return BinaryNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY);
         }
         return this;
     }
 
     @Override
     public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
-        builder.setResult(this, gen.emitAnd(builder.operand(x()), builder.operand(y())));
+        builder.setResult(this, gen.emitAnd(builder.operand(getX()), builder.operand(getY())));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -25,21 +25,22 @@
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.iterators.*;
+import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 
 /**
  * The {@code BinaryNode} class is the base of arithmetic and logic operations with two inputs.
  */
-public abstract class BinaryNode extends FloatingNode {
+public abstract class BinaryNode extends FloatingNode implements Canonicalizable.Binary<ValueNode> {
 
     @Input private ValueNode x;
     @Input private ValueNode y;
 
-    public ValueNode x() {
+    public ValueNode getX() {
         return x;
     }
 
-    public ValueNode y() {
+    public ValueNode getY() {
         return y;
     }
 
@@ -63,9 +64,9 @@
         public ValueNode getValue(BinaryNode binary) {
             switch (this) {
                 case x:
-                    return binary.x();
+                    return binary.getX();
                 case y:
-                    return binary.y();
+                    return binary.getY();
                 default:
                     throw GraalInternalError.shouldNotReachHere();
             }
@@ -74,9 +75,9 @@
         public ValueNode getOtherValue(BinaryNode binary) {
             switch (this) {
                 case x:
-                    return binary.y();
+                    return binary.getY();
                 case y:
-                    return binary.x();
+                    return binary.getX();
                 default:
                     throw GraalInternalError.shouldNotReachHere();
             }
@@ -89,7 +90,7 @@
         if (stamp instanceof IntegerStamp) {
             return IntegerArithmeticNode.add(graph, x, y);
         } else if (stamp instanceof FloatStamp) {
-            return graph.unique(new FloatAddNode(stamp, x, y, false));
+            return graph.unique(new FloatAddNode(x, y, false));
         } else {
             throw GraalInternalError.shouldNotReachHere();
         }
@@ -101,7 +102,7 @@
         if (stamp instanceof IntegerStamp) {
             return IntegerArithmeticNode.sub(graph, x, y);
         } else if (stamp instanceof FloatStamp) {
-            return graph.unique(new FloatSubNode(stamp, x, y, false));
+            return graph.unique(new FloatSubNode(x, y, false));
         } else {
             throw GraalInternalError.shouldNotReachHere();
         }
@@ -113,7 +114,7 @@
         if (stamp instanceof IntegerStamp) {
             return IntegerArithmeticNode.mul(graph, x, y);
         } else if (stamp instanceof FloatStamp) {
-            return graph.unique(new FloatMulNode(stamp, x, y, false));
+            return graph.unique(new FloatMulNode(x, y, false));
         } else {
             throw GraalInternalError.shouldNotReachHere();
         }
@@ -124,8 +125,8 @@
     }
 
     public static ReassociateMatch findReassociate(BinaryNode binary, NodePredicate criterion) {
-        boolean resultX = criterion.apply(binary.x());
-        boolean resultY = criterion.apply(binary.y());
+        boolean resultX = criterion.apply(binary.getX());
+        boolean resultY = criterion.apply(binary.getY());
         if (resultX && !resultY) {
             return ReassociateMatch.x;
         }
@@ -157,8 +158,11 @@
      * <p>
      * This method accepts only {@linkplain #canTryReassociate(BinaryNode) reassociable} operations
      * such as +, -, *, &amp;, | and ^
+     *
+     * @param forY
+     * @param forX
      */
-    public static BinaryNode reassociate(BinaryNode node, NodePredicate criterion) {
+    public static BinaryNode reassociate(BinaryNode node, NodePredicate criterion, ValueNode forX, ValueNode forY) {
         assert canTryReassociate(node);
         ReassociateMatch match1 = findReassociate(node, criterion);
         if (match1 == null) {
@@ -203,29 +207,28 @@
         ValueNode a = match2.getOtherValue(other);
         if (node instanceof IntegerAddNode || node instanceof IntegerSubNode) {
             BinaryNode associated;
-            StructuredGraph graph = node.graph();
             if (invertM1) {
-                associated = IntegerArithmeticNode.sub(graph, m2, m1);
+                associated = IntegerArithmeticNode.sub(m2, m1);
             } else if (invertM2) {
-                associated = IntegerArithmeticNode.sub(graph, m1, m2);
+                associated = IntegerArithmeticNode.sub(m1, m2);
             } else {
-                associated = IntegerArithmeticNode.add(graph, m1, m2);
+                associated = IntegerArithmeticNode.add(m1, m2);
             }
             if (invertA) {
-                return IntegerArithmeticNode.sub(graph, associated, a);
+                return IntegerArithmeticNode.sub(associated, a);
             }
             if (aSub) {
-                return IntegerArithmeticNode.sub(graph, a, associated);
+                return IntegerArithmeticNode.sub(a, associated);
             }
-            return IntegerArithmeticNode.add(graph, a, associated);
+            return IntegerArithmeticNode.add(a, associated);
         } else if (node instanceof IntegerMulNode) {
-            return IntegerArithmeticNode.mul(node.graph(), a, IntegerAddNode.mul(node.graph(), m1, m2));
+            return IntegerArithmeticNode.mul(a, IntegerAddNode.mul(m1, m2));
         } else if (node instanceof AndNode) {
-            return BitLogicNode.and(node.graph(), a, BitLogicNode.and(node.graph(), m1, m2));
+            return BitLogicNode.and(a, BitLogicNode.and(m1, m2));
         } else if (node instanceof OrNode) {
-            return BitLogicNode.or(node.graph(), a, BitLogicNode.or(node.graph(), m1, m2));
+            return BitLogicNode.or(a, BitLogicNode.or(m1, m2));
         } else if (node instanceof XorNode) {
-            return BitLogicNode.xor(node.graph(), a, BitLogicNode.xor(node.graph(), m1, m2));
+            return BitLogicNode.xor(a, BitLogicNode.xor(m1, m2));
         } else {
             throw GraalInternalError.shouldNotReachHere();
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BitLogicNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BitLogicNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -25,7 +25,6 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * The {@code LogicNode} class definition.
@@ -34,7 +33,7 @@
 
     /**
      * Constructs a new logic operation node.
-     * 
+     *
      * @param x the first input into this node
      * @param y the second input into this node
      */
@@ -44,17 +43,26 @@
     }
 
     public static BitLogicNode and(StructuredGraph graph, ValueNode v1, ValueNode v2) {
-        assert v1.stamp().isCompatible(v2.stamp());
-        return graph.unique(new AndNode(StampTool.and(v1.stamp(), v2.stamp()), v1, v2));
+        return graph.unique(new AndNode(v1, v2));
+    }
+
+    public static BitLogicNode and(ValueNode v1, ValueNode v2) {
+        return new AndNode(v1, v2);
     }
 
     public static BitLogicNode or(StructuredGraph graph, ValueNode v1, ValueNode v2) {
-        assert v1.stamp().isCompatible(v2.stamp());
-        return graph.unique(new OrNode(StampTool.or(v1.stamp(), v2.stamp()), v1, v2));
+        return graph.unique(new OrNode(v1, v2));
+    }
+
+    public static BitLogicNode or(ValueNode v1, ValueNode v2) {
+        return new OrNode(v1, v2);
     }
 
     public static BitLogicNode xor(StructuredGraph graph, ValueNode v1, ValueNode v2) {
-        assert v1.stamp().isCompatible(v2.stamp());
-        return graph.unique(new XorNode(StampTool.xor(v1.stamp(), v2.stamp()), v1, v2));
+        return graph.unique(new XorNode(v1, v2));
+    }
+
+    public static BitLogicNode xor(ValueNode v1, ValueNode v2) {
+        return new XorNode(v1, v2);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -23,10 +23,8 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.calc.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 
@@ -62,7 +60,7 @@
      */
     public abstract boolean unorderedIsTrue();
 
-    private LogicNode optimizeConditional(Constant constant, ConditionalNode conditionalNode, ConstantReflectionProvider constantReflection, Condition cond) {
+    private ValueNode optimizeConditional(Constant constant, ConditionalNode conditionalNode, ConstantReflectionProvider constantReflection, Condition cond) {
         Constant trueConstant = conditionalNode.trueValue().asConstant();
         Constant falseConstant = conditionalNode.falseValue().asConstant();
 
@@ -71,14 +69,14 @@
             boolean falseResult = cond.foldCondition(falseConstant, constant, constantReflection, unorderedIsTrue());
 
             if (trueResult == falseResult) {
-                return LogicConstantNode.forBoolean(trueResult, graph());
+                return LogicConstantNode.forBoolean(trueResult);
             } else {
                 if (trueResult) {
                     assert falseResult == false;
                     return conditionalNode.condition();
                 } else {
                     assert falseResult == true;
-                    return graph().unique(new LogicNegationNode(conditionalNode.condition()));
+                    return new LogicNegationNode(conditionalNode.condition());
 
                 }
             }
@@ -86,46 +84,37 @@
         return this;
     }
 
-    protected LogicNode optimizeNormalizeCmp(Constant constant, NormalizeCompareNode normalizeNode, boolean mirrored) {
+    protected ValueNode optimizeNormalizeCmp(Constant constant, NormalizeCompareNode normalizeNode, boolean mirrored) {
         throw new GraalInternalError("NormalizeCompareNode connected to %s (%s %s %s)", this, constant, normalizeNode, mirrored);
     }
 
     @Override
-    public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) {
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
         if (forX.isConstant() && forY.isConstant()) {
-            return TriState.get(condition().foldCondition(forX.asConstant(), forY.asConstant(), constantReflection, unorderedIsTrue()));
+            return LogicConstantNode.forBoolean(condition().foldCondition(forX.asConstant(), forY.asConstant(), tool.getConstantReflection(), unorderedIsTrue()));
         }
-        return TriState.UNKNOWN;
-    }
-
-    @Override
-    public Node canonical(CanonicalizerTool tool) {
-        Node result = super.canonical(tool);
-        if (result != this) {
-            return result;
-        }
-        if (x().isConstant()) {
-            if ((result = canonicalizeSymmetricConstant(tool, x().asConstant(), y(), true)) != this) {
+        ValueNode result;
+        if (forX.isConstant()) {
+            if ((result = canonicalizeSymmetricConstant(tool, forX.asConstant(), forY, true)) != this) {
                 return result;
             }
-        } else if (y().isConstant()) {
-            if ((result = canonicalizeSymmetricConstant(tool, y().asConstant(), x(), false)) != this) {
+        } else if (forY.isConstant()) {
+            if ((result = canonicalizeSymmetricConstant(tool, forY.asConstant(), forX, false)) != this) {
                 return result;
             }
-        } else if (x() instanceof ConvertNode && y() instanceof ConvertNode) {
-            ConvertNode convertX = (ConvertNode) x();
-            ConvertNode convertY = (ConvertNode) y();
+        } else if (forX instanceof ConvertNode && forY instanceof ConvertNode) {
+            ConvertNode convertX = (ConvertNode) forX;
+            ConvertNode convertY = (ConvertNode) forY;
             if (convertX.preservesOrder(condition()) && convertY.preservesOrder(condition()) && convertX.getValue().stamp().isCompatible(convertY.getValue().stamp())) {
-                return graph().unique(duplicateModified(convertX.getValue(), convertY.getValue()));
+                return duplicateModified(convertX.getValue(), convertY.getValue());
             }
-
         }
         return this;
     }
 
     protected abstract CompareNode duplicateModified(ValueNode newX, ValueNode newY);
 
-    protected Node canonicalizeSymmetricConstant(CanonicalizerTool tool, Constant constant, ValueNode nonConstant, boolean mirrored) {
+    protected ValueNode canonicalizeSymmetricConstant(CanonicalizerTool tool, Constant constant, ValueNode nonConstant, boolean mirrored) {
         if (nonConstant instanceof ConditionalNode) {
             return optimizeConditional(constant, (ConditionalNode) nonConstant, tool.getConstantReflection(), mirrored ? condition().mirror() : condition());
         } else if (nonConstant instanceof NormalizeCompareNode) {
@@ -135,9 +124,9 @@
             ConstantNode newConstant = canonicalConvertConstant(tool, convert, constant);
             if (newConstant != null) {
                 if (mirrored) {
-                    return graph().unique(duplicateModified(newConstant, convert.getValue()));
+                    return duplicateModified(newConstant, convert.getValue());
                 } else {
-                    return graph().unique(duplicateModified(convert.getValue(), newConstant));
+                    return duplicateModified(convert.getValue(), newConstant);
                 }
             }
         }
@@ -148,13 +137,17 @@
         if (convert.preservesOrder(condition())) {
             Constant reverseConverted = convert.reverse(constant);
             if (convert.convert(reverseConverted).equals(constant)) {
-                return ConstantNode.forConstant(convert.getValue().stamp(), reverseConverted, tool.getMetaAccess(), convert.graph());
+                return ConstantNode.forConstant(convert.getValue().stamp(), reverseConverted, tool.getMetaAccess());
             }
         }
         return null;
     }
 
     public static CompareNode createCompareNode(StructuredGraph graph, Condition condition, ValueNode x, ValueNode y) {
+        return graph.unique(createCompareNode(condition, x, y));
+    }
+
+    public static CompareNode createCompareNode(Condition condition, ValueNode x, ValueNode y) {
         assert x.getKind() == y.getKind();
         assert condition.isCanonical() : "condition is not canonical: " + condition;
         assert !x.getKind().isNumericFloat();
@@ -176,6 +169,6 @@
             comparison = new IntegerBelowThanNode(x, y);
         }
 
-        return graph.unique(comparison);
+        return comparison;
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -76,17 +76,17 @@
     public ValueNode canonical(CanonicalizerTool tool) {
         if (condition instanceof LogicNegationNode) {
             LogicNegationNode negated = (LogicNegationNode) condition;
-            return graph().unique(new ConditionalNode(negated.getInput(), falseValue(), trueValue()));
+            return graph().unique(new ConditionalNode(negated.getValue(), falseValue(), trueValue()));
         }
 
         // this optimizes the case where a value that can only be 0 or 1 is materialized to 0 or 1
         if (trueValue().isConstant() && falseValue().isConstant() && condition instanceof IntegerEqualsNode) {
             IntegerEqualsNode equals = (IntegerEqualsNode) condition;
-            if (equals.y().isConstant() && equals.y().asConstant().equals(Constant.INT_0) && equals.x().stamp() instanceof IntegerStamp) {
-                IntegerStamp equalsXStamp = (IntegerStamp) equals.x().stamp();
+            if (equals.getY().isConstant() && equals.getY().asConstant().equals(Constant.INT_0) && equals.getX().stamp() instanceof IntegerStamp) {
+                IntegerStamp equalsXStamp = (IntegerStamp) equals.getX().stamp();
                 if (equalsXStamp.upMask() == 1) {
                     if (trueValue().asConstant().equals(Constant.INT_0) && falseValue().asConstant().equals(Constant.INT_1)) {
-                        return IntegerConvertNode.convertUnsigned(equals.x(), stamp());
+                        return IntegerConvertNode.convertUnsigned(equals.getX(), stamp());
                     }
                 }
             }
@@ -102,7 +102,7 @@
         if (condition instanceof CompareNode && ((CompareNode) condition).condition() == Condition.EQ) {
             // optimize the pattern (x == y) ? x : y
             CompareNode compare = (CompareNode) condition;
-            if ((compare.x() == trueValue() && compare.y() == falseValue()) || (compare.x() == falseValue() && compare.y() == trueValue())) {
+            if ((compare.getX() == trueValue() && compare.getY() == falseValue()) || (compare.getX() == falseValue() && compare.getY() == trueValue())) {
                 return falseValue();
             }
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FixedBinaryNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -23,24 +23,25 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 
-public abstract class FixedBinaryNode extends DeoptimizingFixedWithNextNode {
+public abstract class FixedBinaryNode extends DeoptimizingFixedWithNextNode implements Canonicalizable.Binary<ValueNode> {
 
     @Input private ValueNode x;
     @Input private ValueNode y;
 
-    public ValueNode x() {
-        return x;
-    }
-
-    public ValueNode y() {
-        return y;
-    }
-
     public FixedBinaryNode(Stamp stamp, ValueNode x, ValueNode y) {
         super(stamp);
         this.x = x;
         this.y = y;
     }
+
+    public ValueNode getX() {
+        return x;
+    }
+
+    public ValueNode getY() {
+        return y;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -23,7 +23,6 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
@@ -31,10 +30,10 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(shortName = "+")
-public final class FloatAddNode extends FloatArithmeticNode implements Canonicalizable {
+public final class FloatAddNode extends FloatArithmeticNode {
 
-    public FloatAddNode(Stamp stamp, ValueNode x, ValueNode y, boolean isStrictFP) {
-        super(stamp, x, y, isStrictFP);
+    public FloatAddNode(ValueNode x, ValueNode y, boolean isStrictFP) {
+        super(x.stamp().unrestricted(), x, y, isStrictFP);
     }
 
     public Constant evalConst(Constant... inputs) {
@@ -49,12 +48,12 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (x().isConstant() && !y().isConstant()) {
-            return graph().unique(new FloatAddNode(stamp(), y(), x(), isStrictFP()));
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        if (forX.isConstant() && !forY.isConstant()) {
+            return new FloatAddNode(forY, forX, isStrictFP());
         }
-        if (x().isConstant()) {
-            return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph());
+        if (forX.isConstant()) {
+            return ConstantNode.forConstant(evalConst(forX.asConstant(), forY.asConstant()), null);
         }
         // Constant 0.0 can't be eliminated since it can affect the sign of the result.
         return this;
@@ -62,9 +61,9 @@
 
     @Override
     public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
-        Value op1 = builder.operand(x());
-        Value op2 = builder.operand(y());
-        if (!y().isConstant() && !livesLonger(this, y(), builder)) {
+        Value op1 = builder.operand(getX());
+        Value op2 = builder.operand(getY());
+        if (!getY().isConstant() && !livesLonger(this, getY(), builder)) {
             Value op = op1;
             op1 = op2;
             op2 = op;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -26,7 +26,6 @@
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
@@ -36,7 +35,7 @@
  * A {@code FloatConvert} converts between integers and floating point numbers according to Java
  * semantics.
  */
-public class FloatConvertNode extends ConvertNode implements Canonicalizable, Lowerable, ArithmeticLIRLowerable {
+public class FloatConvertNode extends ConvertNode implements Lowerable, ArithmeticLIRLowerable {
 
     private final FloatConvert op;
 
@@ -147,11 +146,11 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (getValue().isConstant()) {
-            return ConstantNode.forPrimitive(evalConst(getValue().asConstant()), graph());
-        } else if (getValue() instanceof FloatConvertNode) {
-            FloatConvertNode other = (FloatConvertNode) getValue();
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
+        if (forValue.isConstant()) {
+            return ConstantNode.forConstant(evalConst(forValue.asConstant()), null);
+        } else if (forValue instanceof FloatConvertNode) {
+            FloatConvertNode other = (FloatConvertNode) forValue;
             if (other.isLossless() && other.op == this.op.reverse()) {
                 return other.getValue();
             }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatDivNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -23,7 +23,6 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
@@ -31,10 +30,10 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(shortName = "/")
-public final class FloatDivNode extends FloatArithmeticNode implements Canonicalizable {
+public final class FloatDivNode extends FloatArithmeticNode {
 
-    public FloatDivNode(Stamp stamp, ValueNode x, ValueNode y, boolean isStrictFP) {
-        super(stamp, x, y, isStrictFP);
+    public FloatDivNode(ValueNode x, ValueNode y, boolean isStrictFP) {
+        super(x.stamp().unrestricted(), x, y, isStrictFP);
     }
 
     public Constant evalConst(Constant... inputs) {
@@ -49,15 +48,15 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (x().isConstant() && y().isConstant()) {
-            return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph());
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        if (forX.isConstant() && forY.isConstant()) {
+            return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant()));
         }
         return this;
     }
 
     @Override
     public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
-        builder.setResult(this, gen.emitDiv(builder.operand(x()), builder.operand(y()), null));
+        builder.setResult(this, gen.emitDiv(builder.operand(getX()), builder.operand(getY()), null));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -22,12 +22,11 @@
  */
 package com.oracle.graal.nodes.calc;
 
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.ProfilingInfo.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.util.*;
 
@@ -57,17 +56,21 @@
     }
 
     @Override
-    public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) {
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        ValueNode result = super.canonical(tool, forX, forY);
+        if (result != this) {
+            return result;
+        }
         if (forX.stamp() instanceof FloatStamp && forY.stamp() instanceof FloatStamp) {
             FloatStamp xStamp = (FloatStamp) forX.stamp();
             FloatStamp yStamp = (FloatStamp) forY.stamp();
             if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY) && xStamp.isNonNaN() && yStamp.isNonNaN()) {
-                return TriState.TRUE;
+                return LogicConstantNode.tautology();
             } else if (xStamp.alwaysDistinct(yStamp)) {
-                return TriState.FALSE;
+                return LogicConstantNode.contradiction();
             }
         }
-        return super.evaluate(constantReflection, forX, forY);
+        return this;
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -22,12 +22,11 @@
  */
 package com.oracle.graal.nodes.calc;
 
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.util.*;
 
@@ -62,11 +61,15 @@
     }
 
     @Override
-    public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) {
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        ValueNode result = super.canonical(tool, forX, forY);
+        if (result != this) {
+            return result;
+        }
         if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY) && !unorderedIsTrue()) {
-            return TriState.FALSE;
+            return LogicConstantNode.contradiction();
         }
-        return super.evaluate(constantReflection, forX, forY);
+        return this;
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatMulNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -23,7 +23,6 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
@@ -31,10 +30,10 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(shortName = "*")
-public final class FloatMulNode extends FloatArithmeticNode implements Canonicalizable {
+public final class FloatMulNode extends FloatArithmeticNode {
 
-    public FloatMulNode(Stamp stamp, ValueNode x, ValueNode y, boolean isStrictFP) {
-        super(stamp, x, y, isStrictFP);
+    public FloatMulNode(ValueNode x, ValueNode y, boolean isStrictFP) {
+        super(x.stamp().unrestricted(), x, y, isStrictFP);
     }
 
     public Constant evalConst(Constant... inputs) {
@@ -49,21 +48,21 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (x().isConstant() && !y().isConstant()) {
-            return graph().unique(new FloatMulNode(stamp(), y(), x(), isStrictFP()));
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        if (forX.isConstant() && !forY.isConstant()) {
+            return new FloatMulNode(forY, forX, isStrictFP());
         }
-        if (x().isConstant()) {
-            return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph());
+        if (forX.isConstant()) {
+            return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant()));
         }
         return this;
     }
 
     @Override
     public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
-        Value op1 = builder.operand(x());
-        Value op2 = builder.operand(y());
-        if (!y().isConstant() && !FloatAddNode.livesLonger(this, y(), builder)) {
+        Value op1 = builder.operand(getX());
+        Value op2 = builder.operand(getY());
+        if (!getY().isConstant() && !FloatAddNode.livesLonger(this, getY(), builder)) {
             Value op = op1;
             op1 = op2;
             op2 = op;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatRemNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -23,7 +23,6 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
@@ -31,10 +30,10 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(shortName = "%")
-public class FloatRemNode extends FloatArithmeticNode implements Canonicalizable, Lowerable {
+public class FloatRemNode extends FloatArithmeticNode implements Lowerable {
 
-    public FloatRemNode(Stamp stamp, ValueNode x, ValueNode y, boolean isStrictFP) {
-        super(stamp, x, y, isStrictFP);
+    public FloatRemNode(ValueNode x, ValueNode y, boolean isStrictFP) {
+        super(x.stamp().unrestricted(), x, y, isStrictFP);
     }
 
     public Constant evalConst(Constant... inputs) {
@@ -49,9 +48,9 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (x().isConstant() && y().isConstant()) {
-            return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph());
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        if (forX.isConstant() && forY.isConstant()) {
+            return ConstantNode.forPrimitive(evalConst(getX().asConstant(), getY().asConstant()));
         }
         return this;
     }
@@ -63,6 +62,6 @@
 
     @Override
     public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
-        builder.setResult(this, gen.emitRem(builder.operand(x()), builder.operand(y()), null));
+        builder.setResult(this, gen.emitRem(builder.operand(getX()), builder.operand(getY()), null));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -23,18 +23,18 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "-")
-public final class FloatSubNode extends FloatArithmeticNode implements Canonicalizable {
+public final class FloatSubNode extends FloatArithmeticNode {
 
-    public FloatSubNode(Stamp stamp, ValueNode x, ValueNode y, boolean isStrictFP) {
-        super(stamp, x, y, isStrictFP);
+    public FloatSubNode(ValueNode x, ValueNode y, boolean isStrictFP) {
+        super(x.stamp().unrestricted(), x, y, isStrictFP);
     }
 
     public Constant evalConst(Constant... inputs) {
@@ -49,12 +49,12 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (x() == y()) {
-            return ConstantNode.forFloatingStamp(stamp(), 0.0f, graph());
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
+            return ConstantNode.forFloatingStamp(stamp(), 0.0f);
         }
-        if (x().isConstant() && y().isConstant()) {
-            return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph());
+        if (forX.isConstant() && forY.isConstant()) {
+            return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant()));
         }
         // Constant 0.0 can't be eliminated since it can affect the sign of the result.
         return this;
@@ -62,6 +62,6 @@
 
     @Override
     public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
-        builder.setResult(this, gen.emitSub(builder.operand(x()), builder.operand(y())));
+        builder.setResult(this, gen.emitSub(builder.operand(getX()), builder.operand(getY())));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -32,15 +32,15 @@
 import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "+")
-public class IntegerAddNode extends IntegerArithmeticNode implements Canonicalizable, NarrowableArithmeticNode {
+public class IntegerAddNode extends IntegerArithmeticNode implements NarrowableArithmeticNode {
 
-    public IntegerAddNode(Stamp stamp, ValueNode x, ValueNode y) {
-        super(stamp, x, y);
+    public IntegerAddNode(ValueNode x, ValueNode y) {
+        super(StampTool.add(x.stamp(), y.stamp()), x, y);
     }
 
     @Override
     public boolean inferStamp() {
-        return updateStamp(StampTool.add(x().stamp(), y().stamp()));
+        return updateStamp(StampTool.add(getX().stamp(), getY().stamp()));
     }
 
     @Override
@@ -50,51 +50,51 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (x().isConstant() && !y().isConstant()) {
-            return graph().unique(new IntegerAddNode(stamp(), y(), x()));
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        if (forX.isConstant() && !forY.isConstant()) {
+            return new IntegerAddNode(forY, forX);
         }
-        if (x() instanceof IntegerSubNode) {
-            IntegerSubNode sub = (IntegerSubNode) x();
-            if (sub.y() == y()) {
+        if (forX instanceof IntegerSubNode) {
+            IntegerSubNode sub = (IntegerSubNode) forX;
+            if (sub.getY() == forY) {
                 // (a - b) + b
-                return sub.x();
+                return sub.getX();
             }
         }
-        if (y() instanceof IntegerSubNode) {
-            IntegerSubNode sub = (IntegerSubNode) y();
-            if (sub.y() == x()) {
+        if (forY instanceof IntegerSubNode) {
+            IntegerSubNode sub = (IntegerSubNode) forY;
+            if (sub.getY() == forX) {
                 // b + (a - b)
-                return sub.x();
+                return sub.getX();
             }
         }
-        if (x().isConstant()) {
-            return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph());
-        } else if (y().isConstant()) {
-            long c = y().asConstant().asLong();
+        if (forX.isConstant()) {
+            return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant()));
+        } else if (forY.isConstant()) {
+            long c = forY.asConstant().asLong();
             if (c == 0) {
-                return x();
+                return forX;
             }
             // canonicalize expressions like "(a + 1) + 2"
-            BinaryNode reassociated = BinaryNode.reassociate(this, ValueNode.isConstantPredicate());
+            BinaryNode reassociated = BinaryNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY);
             if (reassociated != this) {
                 return reassociated;
             }
         }
-        if (x() instanceof NegateNode) {
-            return IntegerArithmeticNode.sub(graph(), y(), ((NegateNode) x()).getValue());
-        } else if (y() instanceof NegateNode) {
-            return IntegerArithmeticNode.sub(graph(), x(), ((NegateNode) y()).getValue());
+        if (forX instanceof NegateNode) {
+            return IntegerArithmeticNode.sub(forY, ((NegateNode) forX).getValue());
+        } else if (forY instanceof NegateNode) {
+            return IntegerArithmeticNode.sub(forX, ((NegateNode) forY).getValue());
         }
         return this;
     }
 
     @Override
     public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
-        Value op1 = builder.operand(x());
-        assert op1 != null : x() + ", this=" + this;
-        Value op2 = builder.operand(y());
-        if (!y().isConstant() && !FloatAddNode.livesLonger(this, y(), builder)) {
+        Value op1 = builder.operand(getX());
+        assert op1 != null : getX() + ", this=" + this;
+        Value op2 = builder.operand(getY());
+        if (!getY().isConstant() && !FloatAddNode.livesLonger(this, getY(), builder)) {
             Value op = op1;
             op1 = op2;
             op2 = op;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerArithmeticNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerArithmeticNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -25,7 +25,6 @@
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 public abstract class IntegerArithmeticNode extends BinaryNode implements ArithmeticLIRLowerable {
 
@@ -35,15 +34,26 @@
     }
 
     public static IntegerAddNode add(StructuredGraph graph, ValueNode v1, ValueNode v2) {
-        return graph.unique(new IntegerAddNode(StampTool.add(v1.stamp(), v2.stamp()), v1, v2));
+        return graph.unique(new IntegerAddNode(v1, v2));
+    }
+
+    public static IntegerAddNode add(ValueNode v1, ValueNode v2) {
+        return new IntegerAddNode(v1, v2);
     }
 
     public static IntegerMulNode mul(StructuredGraph graph, ValueNode v1, ValueNode v2) {
-        assert v1.stamp().isCompatible(v2.stamp());
-        return graph.unique(new IntegerMulNode(v1.stamp().unrestricted(), v1, v2));
+        return graph.unique(new IntegerMulNode(v1, v2));
+    }
+
+    public static IntegerMulNode mul(ValueNode v1, ValueNode v2) {
+        return new IntegerMulNode(v1, v2);
     }
 
     public static IntegerSubNode sub(StructuredGraph graph, ValueNode v1, ValueNode v2) {
-        return graph.unique(new IntegerSubNode(StampTool.sub(v1.stamp(), v2.stamp()), v1, v2));
+        return graph.unique(new IntegerSubNode(v1, v2));
+    }
+
+    public static IntegerSubNode sub(ValueNode v1, ValueNode v2) {
+        return new IntegerSubNode(v1, v2);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowThanNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowThanNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.nodes.calc;
 
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.ProfilingInfo.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
@@ -57,32 +55,27 @@
     }
 
     @Override
-    public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) {
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        ValueNode result = super.canonical(tool, forX, forY);
+        if (result != this) {
+            return result;
+        }
         if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
-            return TriState.FALSE;
+            return LogicConstantNode.contradiction();
         } else if (forX.stamp() instanceof IntegerStamp && forY.stamp() instanceof IntegerStamp) {
             IntegerStamp xStamp = (IntegerStamp) forX.stamp();
             IntegerStamp yStamp = (IntegerStamp) forY.stamp();
             if (yStamp.isPositive()) {
                 if (xStamp.isPositive() && xStamp.upperBound() < yStamp.lowerBound()) {
-                    return TriState.TRUE;
+                    return LogicConstantNode.tautology();
                 } else if (xStamp.isStrictlyNegative() || xStamp.lowerBound() >= yStamp.upperBound()) {
-                    return TriState.FALSE;
+                    return LogicConstantNode.contradiction();
                 }
             }
         }
-        return super.evaluate(constantReflection, forX, forY);
-    }
-
-    @Override
-    public Node canonical(CanonicalizerTool tool) {
-        Node result = super.canonical(tool);
-        if (result != this) {
-            return result;
-        }
-        if (x().isConstant() && x().asConstant().asLong() == 0) {
+        if (forX.isConstant() && forX.asConstant().asLong() == 0) {
             // 0 |<| y is the same as 0 != y
-            return graph().unique(new LogicNegationNode(CompareNode.createCompareNode(graph(), Condition.EQ, x(), y())));
+            return new LogicNegationNode(CompareNode.createCompareNode(Condition.EQ, forX, forY));
         }
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -22,16 +22,14 @@
  */
 package com.oracle.graal.nodes.calc;
 
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
 /**
  * An {@code IntegerConvert} converts an integer to an integer of different width.
  */
-public abstract class IntegerConvertNode extends ConvertNode implements ArithmeticLIRLowerable, Canonicalizable {
+public abstract class IntegerConvertNode extends ConvertNode implements ArithmeticLIRLowerable {
 
     private final int resultBits;
 
@@ -60,18 +58,16 @@
         }
     }
 
-    protected ValueNode canonicalConvert() {
-        if (getValue().stamp() instanceof IntegerStamp) {
-            int inputBits = ((IntegerStamp) getValue().stamp()).getBits();
+    protected ValueNode canonicalConvert(ValueNode value) {
+        if (value.stamp() instanceof IntegerStamp) {
+            int inputBits = ((IntegerStamp) value.stamp()).getBits();
             if (inputBits == resultBits) {
-                return getValue();
-            } else if (getValue().isConstant()) {
-                Constant ret = evalConst(getValue().asConstant());
-                return ConstantNode.forIntegerBits(resultBits, ret.asLong(), graph());
+                return value;
+            } else if (value.isConstant()) {
+                return ConstantNode.forIntegerBits(resultBits, evalConst(value.asConstant()).asLong());
             }
         }
-
-        return null;
+        return this;
     }
 
     public static ValueNode convert(ValueNode input, Stamp stamp) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -31,62 +31,61 @@
 import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "/")
-public class IntegerDivNode extends FixedBinaryNode implements Canonicalizable, Lowerable, LIRLowerable {
+public class IntegerDivNode extends FixedBinaryNode implements Lowerable, LIRLowerable {
 
-    public IntegerDivNode(Stamp stamp, ValueNode x, ValueNode y) {
-        super(stamp, x, y);
+    public IntegerDivNode(ValueNode x, ValueNode y) {
+        super(x.stamp().unrestricted(), x, y);
     }
 
     @Override
     public boolean inferStamp() {
-        return updateStamp(StampTool.div(x().stamp(), y().stamp()));
+        return updateStamp(StampTool.div(getX().stamp(), getY().stamp()));
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (x().isConstant() && y().isConstant()) {
-            long y = y().asConstant().asLong();
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        if (forX.isConstant() && forY.isConstant()) {
+            long y = forY.asConstant().asLong();
             if (y == 0) {
                 return this; // this will trap, can not canonicalize
             }
-            return ConstantNode.forIntegerStamp(stamp(), x().asConstant().asLong() / y, graph());
-        } else if (y().isConstant()) {
-            long c = y().asConstant().asLong();
+            return ConstantNode.forIntegerStamp(stamp(), forX.asConstant().asLong() / y);
+        } else if (forY.isConstant()) {
+            long c = forY.asConstant().asLong();
             if (c == 1) {
-                return x();
+                return forX;
             }
             if (c == -1) {
-                return graph().unique(new NegateNode(x()));
+                return new NegateNode(forX);
             }
             long abs = Math.abs(c);
-            if (CodeUtil.isPowerOf2(abs) && x().stamp() instanceof IntegerStamp) {
-                Stamp unrestricted = stamp().unrestricted();
-                ValueNode dividend = x();
-                IntegerStamp stampX = (IntegerStamp) x().stamp();
+            if (CodeUtil.isPowerOf2(abs) && forX.stamp() instanceof IntegerStamp) {
+                ValueNode dividend = forX;
+                IntegerStamp stampX = (IntegerStamp) forX.stamp();
                 int log2 = CodeUtil.log2(abs);
                 // no rounding if dividend is positive or if its low bits are always 0
                 if (stampX.canBeNegative() || (stampX.upMask() & (abs - 1)) != 0) {
                     int bits = PrimitiveStamp.getBits(stamp());
-                    RightShiftNode sign = graph().unique(new RightShiftNode(unrestricted, x(), ConstantNode.forInt(bits - 1, graph())));
-                    UnsignedRightShiftNode round = graph().unique(new UnsignedRightShiftNode(unrestricted, sign, ConstantNode.forInt(bits - log2, graph())));
-                    dividend = IntegerArithmeticNode.add(graph(), dividend, round);
+                    RightShiftNode sign = new RightShiftNode(forX, ConstantNode.forInt(bits - 1));
+                    UnsignedRightShiftNode round = new UnsignedRightShiftNode(sign, ConstantNode.forInt(bits - log2));
+                    dividend = IntegerArithmeticNode.add(dividend, round);
                 }
-                RightShiftNode shift = graph().unique(new RightShiftNode(unrestricted, dividend, ConstantNode.forInt(log2, graph())));
+                RightShiftNode shift = new RightShiftNode(dividend, ConstantNode.forInt(log2));
                 if (c < 0) {
-                    return graph().unique(new NegateNode(shift));
+                    return new NegateNode(shift);
                 }
                 return shift;
             }
         }
 
         // Convert the expression ((a - a % b) / b) into (a / b).
-        if (x() instanceof IntegerSubNode) {
-            IntegerSubNode integerSubNode = (IntegerSubNode) x();
-            if (integerSubNode.y() instanceof IntegerRemNode) {
-                IntegerRemNode integerRemNode = (IntegerRemNode) integerSubNode.y();
-                if (integerSubNode.stamp().isCompatible(this.stamp()) && integerRemNode.stamp().isCompatible(this.stamp()) && integerSubNode.x() == integerRemNode.x() &&
-                                this.y() == integerRemNode.y()) {
-                    return graph().add(new IntegerDivNode(stamp(), integerSubNode.x(), this.y()));
+        if (forX instanceof IntegerSubNode) {
+            IntegerSubNode integerSubNode = (IntegerSubNode) forX;
+            if (integerSubNode.getY() instanceof IntegerRemNode) {
+                IntegerRemNode integerRemNode = (IntegerRemNode) integerSubNode.getY();
+                if (integerSubNode.stamp().isCompatible(this.stamp()) && integerRemNode.stamp().isCompatible(this.stamp()) && integerSubNode.getX() == integerRemNode.getX() &&
+                                forY == integerRemNode.getY()) {
+                    return new IntegerDivNode(integerSubNode.getX(), forY);
                 }
             }
         }
@@ -108,11 +107,11 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitDiv(gen.operand(x()), gen.operand(y()), gen.state(this)));
+        gen.setResult(this, gen.getLIRGeneratorTool().emitDiv(gen.operand(getX()), gen.operand(getY()), gen.state(this)));
     }
 
     @Override
     public boolean canDeoptimize() {
-        return !(y().stamp() instanceof IntegerStamp) || ((IntegerStamp) y().stamp()).contains(0);
+        return !(getY().stamp() instanceof IntegerStamp) || ((IntegerStamp) getY().stamp()).contains(0);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -23,7 +23,6 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
@@ -58,15 +57,15 @@
     }
 
     @Override
-    protected LogicNode optimizeNormalizeCmp(Constant constant, NormalizeCompareNode normalizeNode, boolean mirrored) {
+    protected ValueNode optimizeNormalizeCmp(Constant constant, NormalizeCompareNode normalizeNode, boolean mirrored) {
         if (constant.getKind() == Kind.Int && constant.asInt() == 0) {
-            ValueNode a = mirrored ? normalizeNode.y() : normalizeNode.x();
-            ValueNode b = mirrored ? normalizeNode.x() : normalizeNode.y();
+            ValueNode a = mirrored ? normalizeNode.getY() : normalizeNode.getX();
+            ValueNode b = mirrored ? normalizeNode.getX() : normalizeNode.getY();
 
-            if (normalizeNode.x().getKind() == Kind.Double || normalizeNode.x().getKind() == Kind.Float) {
-                return graph().unique(new FloatEqualsNode(a, b));
+            if (normalizeNode.getX().getKind() == Kind.Double || normalizeNode.getX().getKind() == Kind.Float) {
+                return new FloatEqualsNode(a, b);
             } else {
-                return graph().unique(new IntegerEqualsNode(a, b));
+                return new IntegerEqualsNode(a, b);
             }
         }
         return this;
@@ -83,56 +82,56 @@
     }
 
     @Override
-    public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) {
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
         if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
-            return TriState.TRUE;
+            return LogicConstantNode.tautology();
         } else if (forX.stamp().alwaysDistinct(forY.stamp())) {
-            return TriState.FALSE;
+            return LogicConstantNode.contradiction();
         }
-        return super.evaluate(constantReflection, forX, forY);
+        return super.canonical(tool, forX, forY);
     }
 
     @Override
-    protected Node canonicalizeSymmetricConstant(CanonicalizerTool tool, Constant constant, ValueNode nonConstant, boolean mirrored) {
+    protected ValueNode canonicalizeSymmetricConstant(CanonicalizerTool tool, Constant constant, ValueNode nonConstant, boolean mirrored) {
         if (constant.asLong() == 0) {
             if (nonConstant instanceof AndNode) {
                 AndNode andNode = (AndNode) nonConstant;
-                return graph().unique(new IntegerTestNode(andNode.x(), andNode.y()));
+                return new IntegerTestNode(andNode.getX(), andNode.getY());
             } else if (nonConstant instanceof ShiftNode) {
                 if (nonConstant instanceof LeftShiftNode) {
                     LeftShiftNode shift = (LeftShiftNode) nonConstant;
-                    if (shift.y().isConstant()) {
+                    if (shift.getY().isConstant()) {
                         int mask = shift.getShiftAmountMask();
-                        int amount = shift.y().asConstant().asInt() & mask;
-                        if (shift.x().getKind() == Kind.Int) {
-                            return graph().unique(new IntegerTestNode(shift.x(), ConstantNode.forInt(-1 >>> amount, graph())));
+                        int amount = shift.getY().asConstant().asInt() & mask;
+                        if (shift.getX().getKind() == Kind.Int) {
+                            return new IntegerTestNode(shift.getX(), ConstantNode.forInt(-1 >>> amount));
                         } else {
-                            assert shift.x().getKind() == Kind.Long;
-                            return graph().unique(new IntegerTestNode(shift.x(), ConstantNode.forLong(-1L >>> amount, graph())));
+                            assert shift.getX().getKind() == Kind.Long;
+                            return new IntegerTestNode(shift.getX(), ConstantNode.forLong(-1L >>> amount));
                         }
                     }
                 } else if (nonConstant instanceof RightShiftNode) {
                     RightShiftNode shift = (RightShiftNode) nonConstant;
-                    if (shift.y().isConstant() && ((IntegerStamp) shift.x().stamp()).isPositive()) {
+                    if (shift.getY().isConstant() && ((IntegerStamp) shift.getX().stamp()).isPositive()) {
                         int mask = shift.getShiftAmountMask();
-                        int amount = shift.y().asConstant().asInt() & mask;
-                        if (shift.x().getKind() == Kind.Int) {
-                            return graph().unique(new IntegerTestNode(shift.x(), ConstantNode.forInt(-1 << amount, graph())));
+                        int amount = shift.getY().asConstant().asInt() & mask;
+                        if (shift.getX().getKind() == Kind.Int) {
+                            return new IntegerTestNode(shift.getX(), ConstantNode.forInt(-1 << amount));
                         } else {
-                            assert shift.x().getKind() == Kind.Long;
-                            return graph().unique(new IntegerTestNode(shift.x(), ConstantNode.forLong(-1L << amount, graph())));
+                            assert shift.getX().getKind() == Kind.Long;
+                            return new IntegerTestNode(shift.getX(), ConstantNode.forLong(-1L << amount));
                         }
                     }
                 } else if (nonConstant instanceof UnsignedRightShiftNode) {
                     UnsignedRightShiftNode shift = (UnsignedRightShiftNode) nonConstant;
-                    if (shift.y().isConstant()) {
+                    if (shift.getY().isConstant()) {
                         int mask = shift.getShiftAmountMask();
-                        int amount = shift.y().asConstant().asInt() & mask;
-                        if (shift.x().getKind() == Kind.Int) {
-                            return graph().unique(new IntegerTestNode(shift.x(), ConstantNode.forInt(-1 << amount, graph())));
+                        int amount = shift.getY().asConstant().asInt() & mask;
+                        if (shift.getX().getKind() == Kind.Int) {
+                            return new IntegerTestNode(shift.getX(), ConstantNode.forInt(-1 << amount));
                         } else {
-                            assert shift.x().getKind() == Kind.Long;
-                            return graph().unique(new IntegerTestNode(shift.x(), ConstantNode.forLong(-1L << amount, graph())));
+                            assert shift.getX().getKind() == Kind.Long;
+                            return new IntegerTestNode(shift.getX(), ConstantNode.forLong(-1L << amount));
                         }
                     }
                 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -23,7 +23,6 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.ProfilingInfo.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
@@ -58,46 +57,41 @@
     }
 
     @Override
-    protected LogicNode optimizeNormalizeCmp(Constant constant, NormalizeCompareNode normalizeNode, boolean mirrored) {
+    protected ValueNode optimizeNormalizeCmp(Constant constant, NormalizeCompareNode normalizeNode, boolean mirrored) {
         assert condition() == Condition.LT;
         if (constant.getKind() == Kind.Int && constant.asInt() == 0) {
-            ValueNode a = mirrored ? normalizeNode.y() : normalizeNode.x();
-            ValueNode b = mirrored ? normalizeNode.x() : normalizeNode.y();
+            ValueNode a = mirrored ? normalizeNode.getY() : normalizeNode.getX();
+            ValueNode b = mirrored ? normalizeNode.getX() : normalizeNode.getY();
 
-            if (normalizeNode.x().getKind() == Kind.Double || normalizeNode.x().getKind() == Kind.Float) {
-                return graph().unique(new FloatLessThanNode(a, b, mirrored ^ normalizeNode.isUnorderedLess));
+            if (normalizeNode.getX().getKind() == Kind.Double || normalizeNode.getX().getKind() == Kind.Float) {
+                return new FloatLessThanNode(a, b, mirrored ^ normalizeNode.isUnorderedLess);
             } else {
-                return graph().unique(new IntegerLessThanNode(a, b));
+                return new IntegerLessThanNode(a, b);
             }
         }
         return this;
     }
 
     @Override
-    public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) {
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        ValueNode result = super.canonical(tool, forX, forY);
+        if (result != this) {
+            return result;
+        }
         if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
-            return TriState.FALSE;
+            return LogicConstantNode.contradiction();
         } else if (forX.stamp() instanceof IntegerStamp && forY.stamp() instanceof IntegerStamp) {
             IntegerStamp xStamp = (IntegerStamp) forX.stamp();
             IntegerStamp yStamp = (IntegerStamp) forY.stamp();
             if (xStamp.upperBound() < yStamp.lowerBound()) {
-                return TriState.TRUE;
+                return LogicConstantNode.tautology();
             } else if (xStamp.lowerBound() >= yStamp.upperBound()) {
-                return TriState.FALSE;
+                return LogicConstantNode.contradiction();
             }
         }
-        return super.evaluate(constantReflection, forX, forY);
-    }
-
-    @Override
-    public Node canonical(CanonicalizerTool tool) {
-        Node result = super.canonical(tool);
-        if (result != this) {
-            return result;
-        }
-        if (x().stamp() instanceof IntegerStamp && y().stamp() instanceof IntegerStamp) {
-            if (IntegerStamp.sameSign((IntegerStamp) x().stamp(), (IntegerStamp) y().stamp())) {
-                return graph().unique(new IntegerBelowThanNode(x(), y()));
+        if (forX.stamp() instanceof IntegerStamp && forY.stamp() instanceof IntegerStamp) {
+            if (IntegerStamp.sameSign((IntegerStamp) forX.stamp(), (IntegerStamp) forY.stamp())) {
+                return new IntegerBelowThanNode(forX, forY);
             }
         }
         return this;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -32,10 +32,11 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(shortName = "*")
-public class IntegerMulNode extends IntegerArithmeticNode implements Canonicalizable, NarrowableArithmeticNode {
+public class IntegerMulNode extends IntegerArithmeticNode implements NarrowableArithmeticNode {
 
-    public IntegerMulNode(Stamp stamp, ValueNode x, ValueNode y) {
-        super(stamp, x, y);
+    public IntegerMulNode(ValueNode x, ValueNode y) {
+        super(x.stamp().unrestricted(), x, y);
+        assert x.stamp().isCompatible(y.stamp());
     }
 
     @Override
@@ -45,40 +46,40 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (x().isConstant() && !y().isConstant()) {
-            return graph().unique(new IntegerMulNode(stamp(), y(), x()));
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        if (forX.isConstant() && !forY.isConstant()) {
+            return new IntegerMulNode(forY, forX);
         }
-        if (x().isConstant()) {
-            return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph());
-        } else if (y().isConstant()) {
-            long c = y().asConstant().asLong();
+        if (forX.isConstant()) {
+            return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant()));
+        } else if (forY.isConstant()) {
+            long c = forY.asConstant().asLong();
             if (c == 1) {
-                return x();
+                return forX;
             }
             if (c == 0) {
-                return ConstantNode.forIntegerStamp(stamp(), 0, graph());
+                return ConstantNode.forIntegerStamp(stamp(), 0);
             }
             long abs = Math.abs(c);
             if (abs > 0 && CodeUtil.isPowerOf2(abs)) {
-                LeftShiftNode shift = graph().unique(new LeftShiftNode(stamp().unrestricted(), x(), ConstantNode.forInt(CodeUtil.log2(abs), graph())));
+                LeftShiftNode shift = new LeftShiftNode(forX, ConstantNode.forInt(CodeUtil.log2(abs)));
                 if (c < 0) {
-                    return graph().unique(new NegateNode(shift));
+                    return new NegateNode(shift);
                 } else {
                     return shift;
                 }
             }
             // canonicalize expressions like "(a * 1) * 2"
-            return BinaryNode.reassociate(this, ValueNode.isConstantPredicate());
+            return BinaryNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY);
         }
         return this;
     }
 
     @Override
     public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
-        Value op1 = builder.operand(x());
-        Value op2 = builder.operand(y());
-        if (!y().isConstant() && !FloatAddNode.livesLonger(this, y(), builder)) {
+        Value op1 = builder.operand(getX());
+        Value op2 = builder.operand(getY());
+        if (!getY().isConstant() && !FloatAddNode.livesLonger(this, getY(), builder)) {
             Value op = op1;
             op1 = op2;
             op2 = op;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerRemNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -31,31 +31,31 @@
 import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "%")
-public class IntegerRemNode extends FixedBinaryNode implements Canonicalizable, Lowerable, LIRLowerable {
+public class IntegerRemNode extends FixedBinaryNode implements Lowerable, LIRLowerable {
 
-    public IntegerRemNode(Stamp stamp, ValueNode x, ValueNode y) {
-        super(stamp, x, y);
+    public IntegerRemNode(ValueNode x, ValueNode y) {
+        super(x.stamp().unrestricted(), x, y);
     }
 
     @Override
     public boolean inferStamp() {
-        return updateStamp(StampTool.rem(x().stamp(), y().stamp()));
+        return updateStamp(StampTool.rem(getX().stamp(), getY().stamp()));
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (x().isConstant() && y().isConstant()) {
-            long y = y().asConstant().asLong();
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        if (forX.isConstant() && forY.isConstant()) {
+            long y = forY.asConstant().asLong();
             if (y == 0) {
                 return this; // this will trap, can not canonicalize
             }
-            return ConstantNode.forIntegerStamp(stamp(), x().asConstant().asLong() % y, graph());
-        } else if (y().isConstant()) {
-            long c = y().asConstant().asLong();
+            return ConstantNode.forIntegerStamp(stamp(), forX.asConstant().asLong() % y);
+        } else if (forY.isConstant()) {
+            long c = forY.asConstant().asLong();
             if (c == 1 || c == -1) {
-                return ConstantNode.forIntegerStamp(stamp(), 0, graph());
-            } else if (c > 0 && CodeUtil.isPowerOf2(c) && x().stamp() instanceof IntegerStamp && ((IntegerStamp) x().stamp()).isPositive()) {
-                return graph().unique(new AndNode(stamp(), x(), ConstantNode.forIntegerStamp(stamp(), c - 1, graph())));
+                return ConstantNode.forIntegerStamp(stamp(), 0);
+            } else if (c > 0 && CodeUtil.isPowerOf2(c) && forX.stamp() instanceof IntegerStamp && ((IntegerStamp) forX.stamp()).isPositive()) {
+                return new AndNode(forX, ConstantNode.forIntegerStamp(stamp(), c - 1));
             }
         }
         return this;
@@ -68,11 +68,11 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitRem(gen.operand(x()), gen.operand(y()), gen.state(this)));
+        gen.setResult(this, gen.getLIRGeneratorTool().emitRem(gen.operand(getX()), gen.operand(getY()), gen.state(this)));
     }
 
     @Override
     public boolean canDeoptimize() {
-        return !(y().stamp() instanceof IntegerStamp) || ((IntegerStamp) y().stamp()).contains(0);
+        return !(getY().stamp() instanceof IntegerStamp) || ((IntegerStamp) getY().stamp()).contains(0);
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -30,17 +30,18 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "-")
-public class IntegerSubNode extends IntegerArithmeticNode implements Canonicalizable, NarrowableArithmeticNode {
+public class IntegerSubNode extends IntegerArithmeticNode implements NarrowableArithmeticNode {
 
-    public IntegerSubNode(Stamp stamp, ValueNode x, ValueNode y) {
-        super(stamp, x, y);
+    public IntegerSubNode(ValueNode x, ValueNode y) {
+        super(StampTool.sub(x.stamp(), y.stamp()), x, y);
     }
 
     @Override
     public boolean inferStamp() {
-        return updateStamp(StampTool.sub(x().stamp(), y().stamp()));
+        return updateStamp(StampTool.sub(getX().stamp(), getY().stamp()));
     }
 
     @Override
@@ -50,75 +51,75 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (x() == y()) {
-            return ConstantNode.forIntegerStamp(stamp(), 0, graph());
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
+            return ConstantNode.forIntegerStamp(stamp(), 0);
         }
-        if (x() instanceof IntegerAddNode) {
-            IntegerAddNode x = (IntegerAddNode) x();
-            if (x.y() == y()) {
+        if (forX instanceof IntegerAddNode) {
+            IntegerAddNode x = (IntegerAddNode) forX;
+            if (x.getY() == forY) {
                 // (a + b) - b
-                return x.x();
+                return x.getX();
             }
-            if (x.x() == y()) {
+            if (x.getX() == forY) {
                 // (a + b) - a
-                return x.y();
+                return x.getY();
             }
-        } else if (x() instanceof IntegerSubNode) {
-            IntegerSubNode x = (IntegerSubNode) x();
-            if (x.x() == y()) {
+        } else if (forX instanceof IntegerSubNode) {
+            IntegerSubNode x = (IntegerSubNode) forX;
+            if (x.getX() == forY) {
                 // (a - b) - a
-                return graph().unique(new NegateNode(x.y()));
+                return new NegateNode(x.getY());
             }
         }
-        if (y() instanceof IntegerAddNode) {
-            IntegerAddNode y = (IntegerAddNode) y();
-            if (y.x() == x()) {
+        if (forY instanceof IntegerAddNode) {
+            IntegerAddNode y = (IntegerAddNode) forY;
+            if (y.getX() == forX) {
                 // a - (a + b)
-                return graph().unique(new NegateNode(y.y()));
+                return new NegateNode(y.getY());
             }
-            if (y.y() == x()) {
+            if (y.getY() == forX) {
                 // b - (a + b)
-                return graph().unique(new NegateNode(y.x()));
+                return new NegateNode(y.getX());
             }
-        } else if (y() instanceof IntegerSubNode) {
-            IntegerSubNode y = (IntegerSubNode) y();
-            if (y.x() == x()) {
+        } else if (forY instanceof IntegerSubNode) {
+            IntegerSubNode y = (IntegerSubNode) forY;
+            if (y.getX() == forX) {
                 // a - (a - b)
-                return y.y();
+                return y.getY();
             }
         }
-        if (x().isConstant() && y().isConstant()) {
-            return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph());
-        } else if (y().isConstant()) {
-            long c = y().asConstant().asLong();
+        if (forX.isConstant() && forY.isConstant()) {
+            return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant()));
+        } else if (forY.isConstant()) {
+            long c = forY.asConstant().asLong();
             if (c == 0) {
-                return x();
+                return forX;
             }
-            BinaryNode reassociated = BinaryNode.reassociate(this, ValueNode.isConstantPredicate());
+            BinaryNode reassociated = BinaryNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY);
             if (reassociated != this) {
                 return reassociated;
             }
-            if (c < 0 || ((IntegerStamp) StampFactory.forKind(y().getKind())).contains(-c)) {
+            if (c < 0 || ((IntegerStamp) StampFactory.forKind(forY.getKind())).contains(-c)) {
                 // Adding a negative is more friendly to the backend since adds are
                 // commutative, so prefer add when it fits.
-                return IntegerArithmeticNode.add(graph(), x(), ConstantNode.forIntegerStamp(stamp(), -c, graph()));
+                return IntegerArithmeticNode.add(forX, ConstantNode.forIntegerStamp(stamp(), -c));
             }
-        } else if (x().isConstant()) {
-            long c = x().asConstant().asLong();
+        } else if (forX.isConstant()) {
+            long c = forX.asConstant().asLong();
             if (c == 0) {
-                return graph().unique(new NegateNode(y()));
+                return new NegateNode(forY);
             }
-            return BinaryNode.reassociate(this, ValueNode.isConstantPredicate());
+            return BinaryNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY);
         }
-        if (y() instanceof NegateNode) {
-            return IntegerArithmeticNode.add(graph(), x(), ((NegateNode) y()).getValue());
+        if (forY instanceof NegateNode) {
+            return IntegerArithmeticNode.add(forX, ((NegateNode) forY).getValue());
         }
         return this;
     }
 
     @Override
     public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
-        builder.setResult(this, gen.emitSub(builder.operand(x()), builder.operand(y())));
+        builder.setResult(this, gen.emitSub(builder.operand(getX()), builder.operand(getY())));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -22,9 +22,8 @@
  */
 package com.oracle.graal.nodes.calc;
 
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 
 /**
@@ -45,19 +44,19 @@
     }
 
     @Override
-    public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) {
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
         if (forX.isConstant() && forY.isConstant()) {
-            return TriState.get((forX.asConstant().asLong() & forY.asConstant().asLong()) == 0);
+            return LogicConstantNode.forBoolean((forX.asConstant().asLong() & forY.asConstant().asLong()) == 0);
         }
-        if (x().stamp() instanceof IntegerStamp && y().stamp() instanceof IntegerStamp) {
+        if (getX().stamp() instanceof IntegerStamp && getY().stamp() instanceof IntegerStamp) {
             IntegerStamp xStamp = (IntegerStamp) forX.stamp();
             IntegerStamp yStamp = (IntegerStamp) forY.stamp();
             if ((xStamp.upMask() & yStamp.upMask()) == 0) {
-                return TriState.TRUE;
+                return LogicConstantNode.tautology();
             } else if ((xStamp.downMask() & yStamp.downMask()) != 0) {
-                return TriState.FALSE;
+                return LogicConstantNode.contradiction();
             }
         }
-        return TriState.UNKNOWN;
+        return this;
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IsNullNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -23,9 +23,7 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
@@ -34,7 +32,7 @@
 /**
  * An IsNullNode will be true if the supplied value is null, and false if it is non-null.
  */
-public final class IsNullNode extends UnaryOpLogicNode implements Canonicalizable, LIRLowerable, Virtualizable, PiPushable {
+public final class IsNullNode extends UnaryOpLogicNode implements LIRLowerable, Virtualizable, PiPushable {
 
     /**
      * Constructs a new IsNullNode instruction.
@@ -52,38 +50,27 @@
 
     @Override
     public boolean verify() {
-        assertTrue(object() != null, "is null input must not be null");
-        assertTrue(object().stamp() instanceof AbstractObjectStamp, "is null input must be an object");
+        assertTrue(getValue() != null, "is null input must not be null");
+        assertTrue(getValue().stamp() instanceof AbstractObjectStamp, "is null input must be an object");
         return super.verify();
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        switch (evaluate(object())) {
-            case FALSE:
-                return LogicConstantNode.contradiction(graph());
-            case TRUE:
-                return LogicConstantNode.tautology(graph());
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
+        Constant constant = forValue.asConstant();
+        if (constant != null) {
+            assert constant.getKind() == Kind.Object;
+            return LogicConstantNode.forBoolean(constant.isNull());
+        }
+        if (StampTool.isObjectNonNull(forValue.stamp())) {
+            return LogicConstantNode.contradiction();
         }
         return this;
     }
 
     @Override
-    public TriState evaluate(ValueNode forObject) {
-        Constant constant = forObject.asConstant();
-        if (constant != null) {
-            assert constant.getKind() == Kind.Object;
-            return TriState.get(constant.isNull());
-        }
-        if (StampTool.isObjectNonNull(forObject.stamp())) {
-            return TriState.FALSE;
-        }
-        return TriState.UNKNOWN;
-    }
-
-    @Override
     public void virtualize(VirtualizerTool tool) {
-        if (tool.getObjectState(object()) != null) {
+        if (tool.getObjectState(getValue()) != null) {
             tool.replaceWithValue(LogicConstantNode.contradiction(graph()));
         }
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -23,7 +23,6 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
@@ -32,15 +31,15 @@
 import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = "<<")
-public final class LeftShiftNode extends ShiftNode implements Canonicalizable {
+public final class LeftShiftNode extends ShiftNode {
 
-    public LeftShiftNode(Stamp stamp, ValueNode x, ValueNode y) {
-        super(stamp, x, y);
+    public LeftShiftNode(ValueNode x, ValueNode y) {
+        super(x, y);
     }
 
     @Override
     public boolean inferStamp() {
-        return updateStamp(StampTool.leftShift(x().stamp(), y().stamp()));
+        return updateStamp(StampTool.leftShift(getX().stamp(), getY().stamp()));
     }
 
     @Override
@@ -55,39 +54,39 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (x().isConstant() && y().isConstant()) {
-            return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph());
-        } else if (y().isConstant()) {
-            int amount = y().asConstant().asInt();
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        if (forX.isConstant() && forY.isConstant()) {
+            return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant()));
+        } else if (forY.isConstant()) {
+            int amount = forY.asConstant().asInt();
             int originalAmout = amount;
             int mask = getShiftAmountMask();
             amount &= mask;
             if (amount == 0) {
-                return x();
+                return forX;
             }
-            if (x() instanceof ShiftNode) {
-                ShiftNode other = (ShiftNode) x();
-                if (other.y().isConstant()) {
-                    int otherAmount = other.y().asConstant().asInt() & mask;
+            if (forX instanceof ShiftNode) {
+                ShiftNode other = (ShiftNode) forX;
+                if (other.getY().isConstant()) {
+                    int otherAmount = other.getY().asConstant().asInt() & mask;
                     if (other instanceof LeftShiftNode) {
                         int total = amount + otherAmount;
                         if (total != (total & mask)) {
-                            return ConstantNode.forIntegerKind(getKind(), 0, graph());
+                            return ConstantNode.forIntegerKind(getKind(), 0);
                         }
-                        return graph().unique(new LeftShiftNode(stamp(), other.x(), ConstantNode.forInt(total, graph())));
+                        return new LeftShiftNode(other.getX(), ConstantNode.forInt(total));
                     } else if ((other instanceof RightShiftNode || other instanceof UnsignedRightShiftNode) && otherAmount == amount) {
                         if (getKind() == Kind.Long) {
-                            return graph().unique(new AndNode(stamp(), other.x(), ConstantNode.forLong(-1L << amount, graph())));
+                            return new AndNode(other.getX(), ConstantNode.forLong(-1L << amount));
                         } else {
                             assert getKind() == Kind.Int;
-                            return graph().unique(new AndNode(stamp(), other.x(), ConstantNode.forInt(-1 << amount, graph())));
+                            return new AndNode(other.getX(), ConstantNode.forInt(-1 << amount));
                         }
                     }
                 }
             }
             if (originalAmout != amount) {
-                return graph().unique(new LeftShiftNode(stamp(), x(), ConstantNode.forInt(amount, graph())));
+                return new LeftShiftNode(forX, ConstantNode.forInt(amount));
             }
         }
         return this;
@@ -95,6 +94,6 @@
 
     @Override
     public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
-        builder.setResult(this, gen.emitShl(builder.operand(x()), builder.operand(y())));
+        builder.setResult(this, gen.emitShl(builder.operand(getX()), builder.operand(getY())));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -24,7 +24,6 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
@@ -62,20 +61,20 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        ValueNode ret = canonicalConvert();
-        if (ret != null) {
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
+        ValueNode ret = canonicalConvert(forValue);
+        if (ret != this) {
             return ret;
         }
 
-        if (getValue() instanceof NarrowNode) {
+        if (forValue instanceof NarrowNode) {
             // zzzzzzzz yyyyxxxx -(narrow)-> yyyyxxxx -(narrow)-> xxxx
             // ==> zzzzzzzz yyyyxxxx -(narrow)-> xxxx
-            NarrowNode other = (NarrowNode) getValue();
-            return graph().unique(new NarrowNode(other.getValue(), getResultBits()));
-        } else if (getValue() instanceof IntegerConvertNode) {
+            NarrowNode other = (NarrowNode) forValue;
+            return new NarrowNode(other.getValue(), getResultBits());
+        } else if (forValue instanceof IntegerConvertNode) {
             // SignExtendNode or ZeroExtendNode
-            IntegerConvertNode other = (IntegerConvertNode) getValue();
+            IntegerConvertNode other = (IntegerConvertNode) forValue;
             if (getResultBits() == other.getInputBits()) {
                 // xxxx -(extend)-> yyyy xxxx -(narrow)-> xxxx
                 // ==> no-op
@@ -83,20 +82,19 @@
             } else if (getResultBits() < other.getInputBits()) {
                 // yyyyxxxx -(extend)-> zzzzzzzz yyyyxxxx -(narrow)-> xxxx
                 // ==> yyyyxxxx -(narrow)-> xxxx
-                return graph().unique(new NarrowNode(other.getValue(), getResultBits()));
+                return new NarrowNode(other.getValue(), getResultBits());
             } else {
                 if (other instanceof SignExtendNode) {
                     // sxxx -(sign-extend)-> ssssssss sssssxxx -(narrow)-> sssssxxx
                     // ==> sxxx -(sign-extend)-> sssssxxx
-                    return graph().unique(new SignExtendNode(other.getValue(), getResultBits()));
+                    return new SignExtendNode(other.getValue(), getResultBits());
                 } else if (other instanceof ZeroExtendNode) {
                     // xxxx -(zero-extend)-> 00000000 00000xxx -(narrow)-> 0000xxxx
                     // ==> xxxx -(zero-extend)-> 0000xxxx
-                    return graph().unique(new ZeroExtendNode(other.getValue(), getResultBits()));
+                    return new ZeroExtendNode(other.getValue(), getResultBits());
                 }
             }
         }
-
         return this;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -24,7 +24,6 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
@@ -34,7 +33,7 @@
 /**
  * The {@code NegateNode} node negates its operand.
  */
-public final class NegateNode extends UnaryNode implements Canonicalizable, ArithmeticLIRLowerable, NarrowableArithmeticNode {
+public final class NegateNode extends UnaryNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode {
 
     @Override
     public boolean inferStamp() {
@@ -68,16 +67,16 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (getValue().isConstant()) {
-            return ConstantNode.forPrimitive(evalConst(getValue().asConstant()), graph());
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
+        if (forValue.isConstant()) {
+            return ConstantNode.forConstant(evalConst(forValue.asConstant()), null);
         }
-        if (getValue() instanceof NegateNode) {
-            return ((NegateNode) getValue()).getValue();
+        if (forValue instanceof NegateNode) {
+            return ((NegateNode) forValue).getValue();
         }
-        if (getValue() instanceof IntegerSubNode) {
-            IntegerSubNode sub = (IntegerSubNode) getValue();
-            return IntegerArithmeticNode.sub(graph(), sub.y(), sub.x());
+        if (forValue instanceof IntegerSubNode) {
+            IntegerSubNode sub = (IntegerSubNode) forValue;
+            return new IntegerSubNode(sub.getY(), sub.getX());
         }
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -50,15 +51,21 @@
     }
 
     @Override
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        // nothing to do
+        return this;
+    }
+
+    @Override
     public void lower(LoweringTool tool) {
         LogicNode equalComp;
         LogicNode lessComp;
-        if (x().stamp() instanceof FloatStamp) {
-            equalComp = graph().unique(new FloatEqualsNode(x(), y()));
-            lessComp = graph().unique(new FloatLessThanNode(x(), y(), isUnorderedLess));
+        if (getX().stamp() instanceof FloatStamp) {
+            equalComp = graph().unique(new FloatEqualsNode(getX(), getY()));
+            lessComp = graph().unique(new FloatLessThanNode(getX(), getY(), isUnorderedLess));
         } else {
-            equalComp = graph().unique(new IntegerEqualsNode(x(), y()));
-            lessComp = graph().unique(new IntegerLessThanNode(x(), y()));
+            equalComp = graph().unique(new IntegerEqualsNode(getX(), getY()));
+            lessComp = graph().unique(new IntegerLessThanNode(getX(), getY()));
         }
 
         ConditionalNode equalValue = graph().unique(new ConditionalNode(equalComp, ConstantNode.forInt(0, graph()), ConstantNode.forInt(1, graph())));
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -24,7 +24,6 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
@@ -34,7 +33,7 @@
 /**
  * Binary negation of long or integer values.
  */
-public final class NotNode extends UnaryNode implements Canonicalizable, ArithmeticLIRLowerable, NarrowableArithmeticNode {
+public final class NotNode extends UnaryNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode {
 
     @Override
     public boolean inferStamp() {
@@ -57,12 +56,12 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (getValue().isConstant()) {
-            return ConstantNode.forPrimitive(evalConst(getValue().asConstant()), graph());
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
+        if (forValue.isConstant()) {
+            return ConstantNode.forConstant(evalConst(forValue.asConstant()), null);
         }
-        if (getValue() instanceof NotNode) {
-            return ((NotNode) getValue()).getValue();
+        if (forValue instanceof NotNode) {
+            return ((NotNode) forValue).getValue();
         }
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -23,7 +23,6 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.ProfilingInfo.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
@@ -58,26 +57,20 @@
     }
 
     @Override
-    public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) {
-        if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
-            return TriState.TRUE;
-        } else if (forX.stamp().alwaysDistinct(forY.stamp())) {
-            return TriState.FALSE;
-        } else {
-            return super.evaluate(constantReflection, forX, forY);
-        }
-    }
-
-    @Override
-    public Node canonical(CanonicalizerTool tool) {
-        Node result = super.canonical(tool);
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        ValueNode result = super.canonical(tool, forX, forY);
         if (result != this) {
             return result;
         }
-        if (StampTool.isObjectAlwaysNull(x())) {
-            return graph().unique(new IsNullNode(y()));
-        } else if (StampTool.isObjectAlwaysNull(y())) {
-            return graph().unique(new IsNullNode(x()));
+        if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
+            return LogicConstantNode.tautology();
+        } else if (forX.stamp().alwaysDistinct(forY.stamp())) {
+            return LogicConstantNode.contradiction();
+        }
+        if (StampTool.isObjectAlwaysNull(forX)) {
+            return new IsNullNode(forY);
+        } else if (StampTool.isObjectAlwaysNull(forY)) {
+            return new IsNullNode(forX);
         }
         return this;
     }
@@ -103,15 +96,15 @@
 
     @Override
     public void virtualize(VirtualizerTool tool) {
-        State stateX = tool.getObjectState(x());
-        State stateY = tool.getObjectState(y());
+        State stateX = tool.getObjectState(getX());
+        State stateY = tool.getObjectState(getY());
         boolean xVirtual = stateX != null && stateX.getState() == EscapeState.Virtual;
         boolean yVirtual = stateY != null && stateY.getState() == EscapeState.Virtual;
 
         if (xVirtual && !yVirtual) {
-            virtualizeNonVirtualComparison(stateX, stateY != null ? stateY.getMaterializedValue() : y(), tool);
+            virtualizeNonVirtualComparison(stateX, stateY != null ? stateY.getMaterializedValue() : getY(), tool);
         } else if (!xVirtual && yVirtual) {
-            virtualizeNonVirtualComparison(stateY, stateX != null ? stateX.getMaterializedValue() : x(), tool);
+            virtualizeNonVirtualComparison(stateY, stateX != null ? stateX.getMaterializedValue() : getX(), tool);
         } else if (xVirtual && yVirtual) {
             boolean xIdentity = stateX.getVirtualObject().hasIdentity();
             boolean yIdentity = stateY.getVirtualObject().hasIdentity();
@@ -119,7 +112,7 @@
                 /*
                  * One of the two objects has identity, the other doesn't. In code, this looks like
                  * "Integer.valueOf(a) == new Integer(b)", which is always false.
-                 *
+                 * 
                  * In other words: an object created via valueOf can never be equal to one created
                  * by new in the same compilation unit.
                  */
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -30,17 +30,19 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "|")
-public final class OrNode extends BitLogicNode implements Canonicalizable {
+public final class OrNode extends BitLogicNode {
 
-    public OrNode(Stamp stamp, ValueNode x, ValueNode y) {
-        super(stamp, x, y);
+    public OrNode(ValueNode x, ValueNode y) {
+        super(StampTool.or(x.stamp(), y.stamp()), x, y);
+        assert x.stamp().isCompatible(y.stamp());
     }
 
     @Override
     public boolean inferStamp() {
-        return updateStamp(StampTool.or(x().stamp(), y().stamp()));
+        return updateStamp(StampTool.or(getX().stamp(), getY().stamp()));
     }
 
     @Override
@@ -50,31 +52,31 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (x() == y()) {
-            return x();
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
+            return forX;
         }
-        if (x().isConstant() && !y().isConstant()) {
-            return graph().unique(new OrNode(stamp(), y(), x()));
+        if (forX.isConstant() && !forY.isConstant()) {
+            return new OrNode(forY, forX);
         }
-        if (x().isConstant()) {
-            return ConstantNode.forPrimitive(stamp(), evalConst(x().asConstant(), y().asConstant()), graph());
-        } else if (y().isConstant()) {
-            long rawY = y().asConstant().asLong();
+        if (forX.isConstant()) {
+            return ConstantNode.forPrimitive(stamp(), evalConst(forX.asConstant(), forY.asConstant()));
+        } else if (forY.isConstant()) {
+            long rawY = forY.asConstant().asLong();
             long mask = IntegerStamp.defaultMask(PrimitiveStamp.getBits(stamp()));
             if ((rawY & mask) == mask) {
-                return ConstantNode.forIntegerStamp(stamp(), mask, graph());
+                return ConstantNode.forIntegerStamp(stamp(), mask);
             }
             if ((rawY & mask) == 0) {
-                return x();
+                return forX;
             }
-            return BinaryNode.reassociate(this, ValueNode.isConstantPredicate());
+            return BinaryNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY);
         }
         return this;
     }
 
     @Override
     public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
-        builder.setResult(this, gen.emitOr(builder.operand(x()), builder.operand(y())));
+        builder.setResult(this, gen.emitOr(builder.operand(getX()), builder.operand(getY())));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ReinterpretNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -25,7 +25,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
@@ -36,7 +35,7 @@
  * of a primitive value to some other incompatible stamp. The new stamp must have the same width as
  * the old stamp.
  */
-public class ReinterpretNode extends UnaryNode implements Canonicalizable, ArithmeticLIRLowerable {
+public class ReinterpretNode extends UnaryNode implements ArithmeticLIRLowerable {
 
     private ReinterpretNode(Kind to, ValueNode value) {
         this(StampFactory.forKind(to), value);
@@ -81,16 +80,16 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (getValue().isConstant()) {
-            return ConstantNode.forPrimitive(evalConst(getValue().asConstant()), graph());
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
+        if (forValue.isConstant()) {
+            return ConstantNode.forConstant(evalConst(forValue.asConstant()), null);
         }
-        if (stamp().isCompatible(getValue().stamp())) {
-            return getValue();
+        if (stamp().isCompatible(forValue.stamp())) {
+            return forValue;
         }
-        if (getValue() instanceof ReinterpretNode) {
-            ReinterpretNode reinterpret = (ReinterpretNode) getValue();
-            return getValue().graph().unique(new ReinterpretNode(stamp(), reinterpret.getValue()));
+        if (forValue instanceof ReinterpretNode) {
+            ReinterpretNode reinterpret = (ReinterpretNode) forValue;
+            return new ReinterpretNode(stamp(), reinterpret.getValue());
         }
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -31,10 +31,10 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(shortName = ">>")
-public final class RightShiftNode extends ShiftNode implements Canonicalizable {
+public final class RightShiftNode extends ShiftNode {
 
-    public RightShiftNode(Stamp stamp, ValueNode x, ValueNode y) {
-        super(stamp, x, y);
+    public RightShiftNode(ValueNode x, ValueNode y) {
+        super(x, y);
     }
 
     @Override
@@ -49,35 +49,35 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (x().stamp() instanceof IntegerStamp && ((IntegerStamp) x().stamp()).isPositive()) {
-            return graph().unique(new UnsignedRightShiftNode(stamp(), x(), y()));
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        if (forX.stamp() instanceof IntegerStamp && ((IntegerStamp) forX.stamp()).isPositive()) {
+            return new UnsignedRightShiftNode(forX, forY);
         }
-        if (x().isConstant() && y().isConstant()) {
-            return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph());
-        } else if (y().isConstant()) {
-            int amount = y().asConstant().asInt();
+        if (forX.isConstant() && forY.isConstant()) {
+            return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant()));
+        } else if (forY.isConstant()) {
+            int amount = forY.asConstant().asInt();
             int originalAmout = amount;
             int mask = getShiftAmountMask();
             amount &= mask;
             if (amount == 0) {
-                return x();
+                return forX;
             }
-            if (x() instanceof ShiftNode) {
-                ShiftNode other = (ShiftNode) x();
-                if (other.y().isConstant()) {
-                    int otherAmount = other.y().asConstant().asInt() & mask;
+            if (forX instanceof ShiftNode) {
+                ShiftNode other = (ShiftNode) forX;
+                if (other.getY().isConstant()) {
+                    int otherAmount = other.getY().asConstant().asInt() & mask;
                     if (other instanceof RightShiftNode) {
                         int total = amount + otherAmount;
                         if (total != (total & mask)) {
-                            assert other.x().stamp() instanceof IntegerStamp;
-                            IntegerStamp istamp = (IntegerStamp) other.x().stamp();
+                            assert other.getX().stamp() instanceof IntegerStamp;
+                            IntegerStamp istamp = (IntegerStamp) other.getX().stamp();
 
                             if (istamp.isPositive()) {
-                                return ConstantNode.forIntegerKind(getKind(), 0, graph());
+                                return ConstantNode.forIntegerKind(getKind(), 0);
                             }
                             if (istamp.isStrictlyNegative()) {
-                                return ConstantNode.forIntegerKind(getKind(), -1L, graph());
+                                return ConstantNode.forIntegerKind(getKind(), -1L);
                             }
 
                             /*
@@ -85,14 +85,14 @@
                              * full shift for this kind
                              */
                             assert total >= mask;
-                            return graph().unique(new RightShiftNode(stamp(), other.x(), ConstantNode.forInt(mask, graph())));
+                            return new RightShiftNode(other.getX(), ConstantNode.forInt(mask));
                         }
-                        return graph().unique(new RightShiftNode(stamp(), other.x(), ConstantNode.forInt(total, graph())));
+                        return new RightShiftNode(other.getX(), ConstantNode.forInt(total));
                     }
                 }
             }
             if (originalAmout != amount) {
-                return graph().unique(new RightShiftNode(stamp(), x(), ConstantNode.forInt(amount, graph())));
+                return new RightShiftNode(forX, ConstantNode.forInt(amount));
             }
         }
         return this;
@@ -100,6 +100,6 @@
 
     @Override
     public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
-        builder.setResult(this, gen.emitShr(builder.operand(x()), builder.operand(y())));
+        builder.setResult(this, gen.emitShr(builder.operand(getX()), builder.operand(getY())));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ShiftNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ShiftNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -23,7 +23,6 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
@@ -34,12 +33,13 @@
 
     /**
      * Creates a new shift operation.
-     * 
+     *
      * @param x the first input value
      * @param s the second input value
      */
-    public ShiftNode(Stamp stamp, ValueNode x, ValueNode s) {
-        super(stamp, x, s);
+    public ShiftNode(ValueNode x, ValueNode s) {
+        super(x.stamp().unrestricted(), x, s);
+        assert s.getKind() == Kind.Int;
     }
 
     public int getShiftAmountMask() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -24,7 +24,6 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
@@ -68,32 +67,32 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        ValueNode ret = canonicalConvert();
-        if (ret != null) {
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
+        ValueNode ret = canonicalConvert(forValue);
+        if (ret != this) {
             return ret;
         }
 
-        if (getValue() instanceof SignExtendNode) {
+        if (forValue instanceof SignExtendNode) {
             // sxxx -(sign-extend)-> ssss sxxx -(sign-extend)-> ssssssss sssssxxx
             // ==> sxxx -(sign-extend)-> ssssssss sssssxxx
-            SignExtendNode other = (SignExtendNode) getValue();
-            return graph().unique(new SignExtendNode(other.getValue(), getResultBits()));
-        } else if (getValue() instanceof ZeroExtendNode) {
-            ZeroExtendNode other = (ZeroExtendNode) getValue();
+            SignExtendNode other = (SignExtendNode) forValue;
+            return new SignExtendNode(other.getValue(), getResultBits());
+        } else if (forValue instanceof ZeroExtendNode) {
+            ZeroExtendNode other = (ZeroExtendNode) forValue;
             if (other.getResultBits() > other.getInputBits()) {
                 // sxxx -(zero-extend)-> 0000 sxxx -(sign-extend)-> 00000000 0000sxxx
                 // ==> sxxx -(zero-extend)-> 00000000 0000sxxx
-                return graph().unique(new ZeroExtendNode(other.getValue(), getResultBits()));
+                return new ZeroExtendNode(other.getValue(), getResultBits());
             }
         }
 
-        if (getValue().stamp() instanceof IntegerStamp) {
-            IntegerStamp inputStamp = (IntegerStamp) getValue().stamp();
+        if (forValue.stamp() instanceof IntegerStamp) {
+            IntegerStamp inputStamp = (IntegerStamp) forValue.stamp();
             if ((inputStamp.upMask() & (1L << (getInputBits() - 1))) == 0L) {
                 // 0xxx -(sign-extend)-> 0000 0xxx
                 // ==> 0xxx -(zero-extend)-> 0000 0xxx
-                return graph().unique(new ZeroExtendNode(getValue(), getResultBits()));
+                return new ZeroExtendNode(forValue, getResultBits());
             }
         }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnaryNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnaryNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -23,13 +23,14 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 
 /**
  * The {@code UnaryNode} class is the base of arithmetic and bit logic operations with exactly one
  * input.
  */
-public abstract class UnaryNode extends FloatingNode {
+public abstract class UnaryNode extends FloatingNode implements Canonicalizable.Unary<ValueNode> {
 
     @Input private ValueNode value;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedDivNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -23,7 +23,6 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
@@ -31,34 +30,27 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(shortName = "|/|")
-public class UnsignedDivNode extends FixedBinaryNode implements Canonicalizable, Lowerable, LIRLowerable {
+public class UnsignedDivNode extends FixedBinaryNode implements Lowerable, LIRLowerable {
 
-    /**
-     * Used by {@code NodeIntrinsic} in {@code UnsignedMathSubstitutions}.
-     */
-    private UnsignedDivNode(Kind kind, ValueNode x, ValueNode y) {
-        this(StampFactory.forKind(kind), x, y);
-    }
-
-    public UnsignedDivNode(Stamp stamp, ValueNode x, ValueNode y) {
-        super(stamp, x, y);
+    public UnsignedDivNode(ValueNode x, ValueNode y) {
+        super(x.stamp().unrestricted(), x, y);
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (x().isConstant() && y().isConstant()) {
-            long yConst = y().asConstant().asLong();
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        if (forX.isConstant() && forY.isConstant()) {
+            long yConst = forY.asConstant().asLong();
             if (yConst == 0) {
                 return this; // this will trap, cannot canonicalize
             }
-            return ConstantNode.forIntegerStamp(stamp(), UnsignedMath.divide(x().asConstant().asLong(), yConst), graph());
-        } else if (y().isConstant()) {
-            long c = y().asConstant().asLong();
+            return ConstantNode.forIntegerStamp(stamp(), UnsignedMath.divide(forX.asConstant().asLong(), yConst));
+        } else if (forY.isConstant()) {
+            long c = forY.asConstant().asLong();
             if (c == 1) {
-                return x();
+                return forX;
             }
             if (CodeUtil.isPowerOf2(c)) {
-                return graph().unique(new UnsignedRightShiftNode(stamp(), x(), ConstantNode.forInt(CodeUtil.log2(c), graph())));
+                return new UnsignedRightShiftNode(forX, ConstantNode.forInt(CodeUtil.log2(c)));
             }
         }
         return this;
@@ -71,17 +63,17 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitUDiv(gen.operand(x()), gen.operand(y()), gen.state(this)));
+        gen.setResult(this, gen.getLIRGeneratorTool().emitUDiv(gen.operand(getX()), gen.operand(getY()), gen.state(this)));
     }
 
     @Override
     public boolean canDeoptimize() {
-        return !(y().stamp() instanceof IntegerStamp) || ((IntegerStamp) y().stamp()).contains(0);
+        return !(getY().stamp() instanceof IntegerStamp) || ((IntegerStamp) getY().stamp()).contains(0);
     }
 
     @NodeIntrinsic
-    public static native int unsignedDivide(@ConstantNodeParameter Kind kind, int a, int b);
+    public static native int unsignedDivide(int a, int b);
 
     @NodeIntrinsic
-    public static native long unsignedDivide(@ConstantNodeParameter Kind kind, long a, long b);
+    public static native long unsignedDivide(long a, long b);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRemNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -23,7 +23,6 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
@@ -31,33 +30,26 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(shortName = "|%|")
-public class UnsignedRemNode extends FixedBinaryNode implements Canonicalizable, Lowerable, LIRLowerable {
+public class UnsignedRemNode extends FixedBinaryNode implements Lowerable, LIRLowerable {
 
-    /**
-     * Used by {@code NodeIntrinsic} in {@code UnsignedMathSubstitutions}.
-     */
-    private UnsignedRemNode(Kind kind, ValueNode x, ValueNode y) {
-        this(StampFactory.forKind(kind), x, y);
-    }
-
-    public UnsignedRemNode(Stamp stamp, ValueNode x, ValueNode y) {
-        super(stamp, x, y);
+    public UnsignedRemNode(ValueNode x, ValueNode y) {
+        super(x.stamp().unrestricted(), x, y);
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (x().isConstant() && y().isConstant()) {
-            long yConst = y().asConstant().asLong();
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        if (forX.isConstant() && forY.isConstant()) {
+            long yConst = forY.asConstant().asLong();
             if (yConst == 0) {
                 return this; // this will trap, cannot canonicalize
             }
-            return ConstantNode.forIntegerStamp(stamp(), UnsignedMath.remainder(x().asConstant().asLong(), yConst), graph());
-        } else if (y().isConstant()) {
-            long c = y().asConstant().asLong();
+            return ConstantNode.forIntegerStamp(stamp(), UnsignedMath.remainder(forX.asConstant().asLong(), yConst));
+        } else if (forY.isConstant()) {
+            long c = forY.asConstant().asLong();
             if (c == 1) {
-                return ConstantNode.forIntegerStamp(stamp(), 0, graph());
+                return ConstantNode.forIntegerStamp(stamp(), 0);
             } else if (CodeUtil.isPowerOf2(c)) {
-                return graph().unique(new AndNode(stamp(), x(), ConstantNode.forIntegerStamp(stamp(), c - 1, graph())));
+                return new AndNode(forX, ConstantNode.forIntegerStamp(stamp(), c - 1));
             }
         }
         return this;
@@ -70,17 +62,17 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        gen.setResult(this, gen.getLIRGeneratorTool().emitURem(gen.operand(x()), gen.operand(y()), gen.state(this)));
+        gen.setResult(this, gen.getLIRGeneratorTool().emitURem(gen.operand(getX()), gen.operand(getY()), gen.state(this)));
     }
 
     @Override
     public boolean canDeoptimize() {
-        return !(y().stamp() instanceof IntegerStamp) || ((IntegerStamp) y().stamp()).contains(0);
+        return !(getY().stamp() instanceof IntegerStamp) || ((IntegerStamp) getY().stamp()).contains(0);
     }
 
     @NodeIntrinsic
-    public static native int unsignedRemainder(@ConstantNodeParameter Kind kind, int a, int b);
+    public static native int unsignedRemainder(int a, int b);
 
     @NodeIntrinsic
-    public static native long unsignedRemainder(@ConstantNodeParameter Kind kind, long a, long b);
+    public static native long unsignedRemainder(long a, long b);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -23,7 +23,6 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
@@ -32,15 +31,15 @@
 import com.oracle.graal.nodes.type.*;
 
 @NodeInfo(shortName = ">>>")
-public final class UnsignedRightShiftNode extends ShiftNode implements Canonicalizable {
+public final class UnsignedRightShiftNode extends ShiftNode {
 
-    public UnsignedRightShiftNode(Stamp stamp, ValueNode x, ValueNode y) {
-        super(stamp, x, y);
+    public UnsignedRightShiftNode(ValueNode x, ValueNode y) {
+        super(x, y);
     }
 
     @Override
     public boolean inferStamp() {
-        return updateStamp(StampTool.unsignedRightShift(x().stamp(), y().stamp()));
+        return updateStamp(StampTool.unsignedRightShift(getX().stamp(), getY().stamp()));
     }
 
     @Override
@@ -55,39 +54,39 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (x().isConstant() && y().isConstant()) {
-            return ConstantNode.forPrimitive(evalConst(x().asConstant(), y().asConstant()), graph());
-        } else if (y().isConstant()) {
-            int amount = y().asConstant().asInt();
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        if (forX.isConstant() && forY.isConstant()) {
+            return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant()));
+        } else if (forY.isConstant()) {
+            int amount = forY.asConstant().asInt();
             int originalAmout = amount;
             int mask = getShiftAmountMask();
             amount &= mask;
             if (amount == 0) {
-                return x();
+                return forX;
             }
-            if (x() instanceof ShiftNode) {
-                ShiftNode other = (ShiftNode) x();
-                if (other.y().isConstant()) {
-                    int otherAmount = other.y().asConstant().asInt() & mask;
+            if (forX instanceof ShiftNode) {
+                ShiftNode other = (ShiftNode) forX;
+                if (other.getY().isConstant()) {
+                    int otherAmount = other.getY().asConstant().asInt() & mask;
                     if (other instanceof UnsignedRightShiftNode) {
                         int total = amount + otherAmount;
                         if (total != (total & mask)) {
-                            return ConstantNode.forIntegerKind(getKind(), 0, graph());
+                            return ConstantNode.forIntegerKind(getKind(), 0);
                         }
-                        return graph().unique(new UnsignedRightShiftNode(stamp(), other.x(), ConstantNode.forInt(total, graph())));
+                        return new UnsignedRightShiftNode(other.getX(), ConstantNode.forInt(total));
                     } else if (other instanceof LeftShiftNode && otherAmount == amount) {
                         if (getKind() == Kind.Long) {
-                            return graph().unique(new AndNode(stamp(), other.x(), ConstantNode.forLong(-1L >>> amount, graph())));
+                            return new AndNode(other.getX(), ConstantNode.forLong(-1L >>> amount));
                         } else {
                             assert getKind() == Kind.Int;
-                            return graph().unique(new AndNode(stamp(), other.x(), ConstantNode.forInt(-1 >>> amount, graph())));
+                            return new AndNode(other.getX(), ConstantNode.forInt(-1 >>> amount));
                         }
                     }
                 }
             }
             if (originalAmout != amount) {
-                return graph().unique(new UnsignedRightShiftNode(stamp(), x(), ConstantNode.forInt(amount, graph())));
+                return new UnsignedRightShiftNode(forX, ConstantNode.forInt(amount));
             }
         }
         return this;
@@ -95,6 +94,6 @@
 
     @Override
     public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
-        builder.setResult(this, gen.emitUShr(builder.operand(x()), builder.operand(y())));
+        builder.setResult(this, gen.emitUShr(builder.operand(getX()), builder.operand(getY())));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -30,17 +30,19 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "^")
-public final class XorNode extends BitLogicNode implements Canonicalizable {
+public final class XorNode extends BitLogicNode {
 
-    public XorNode(Stamp stamp, ValueNode x, ValueNode y) {
-        super(stamp, x, y);
+    public XorNode(ValueNode x, ValueNode y) {
+        super(StampTool.xor(x.stamp(), y.stamp()), x, y);
+        assert x.stamp().isCompatible(y.stamp());
     }
 
     @Override
     public boolean inferStamp() {
-        return updateStamp(StampTool.xor(x().stamp(), y().stamp()));
+        return updateStamp(StampTool.xor(getX().stamp(), getY().stamp()));
     }
 
     @Override
@@ -50,30 +52,30 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (x() == y()) {
-            return ConstantNode.forIntegerStamp(stamp(), 0, graph());
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
+            return ConstantNode.forIntegerStamp(stamp(), 0);
         }
-        if (x().isConstant() && !y().isConstant()) {
-            return graph().unique(new XorNode(stamp(), y(), x()));
+        if (forX.isConstant() && !forY.isConstant()) {
+            return new XorNode(forY, forX);
         }
-        if (x().isConstant()) {
-            return ConstantNode.forPrimitive(stamp(), evalConst(x().asConstant(), y().asConstant()), graph());
-        } else if (y().isConstant()) {
-            long rawY = y().asConstant().asLong();
+        if (forX.isConstant()) {
+            return ConstantNode.forPrimitive(stamp(), evalConst(forX.asConstant(), forY.asConstant()));
+        } else if (forY.isConstant()) {
+            long rawY = forY.asConstant().asLong();
             long mask = IntegerStamp.defaultMask(PrimitiveStamp.getBits(stamp()));
             if ((rawY & mask) == 0) {
-                return x();
+                return forX;
             } else if ((rawY & mask) == mask) {
-                return graph().unique(new NotNode(x()));
+                return new NotNode(forX);
             }
-            return BinaryNode.reassociate(this, ValueNode.isConstantPredicate());
+            return BinaryNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY);
         }
         return this;
     }
 
     @Override
     public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
-        builder.setResult(this, gen.emitXor(builder.operand(x()), builder.operand(y())));
+        builder.setResult(this, gen.emitXor(builder.operand(getX()), builder.operand(getY())));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -25,7 +25,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
@@ -78,20 +77,20 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        ValueNode ret = canonicalConvert();
-        if (ret != null) {
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
+        ValueNode ret = canonicalConvert(forValue);
+        if (ret != this) {
             return ret;
         }
 
-        if (getValue() instanceof ZeroExtendNode) {
+        if (forValue instanceof ZeroExtendNode) {
             // xxxx -(zero-extend)-> 0000 xxxx -(zero-extend)-> 00000000 0000xxxx
             // ==> xxxx -(zero-extend)-> 00000000 0000xxxx
-            ZeroExtendNode other = (ZeroExtendNode) getValue();
-            return graph().unique(new ZeroExtendNode(other.getValue(), getResultBits()));
+            ZeroExtendNode other = (ZeroExtendNode) forValue;
+            return new ZeroExtendNode(other.getValue(), getResultBits());
         }
-        if (getValue() instanceof NarrowNode) {
-            NarrowNode narrow = (NarrowNode) getValue();
+        if (forValue instanceof NarrowNode) {
+            NarrowNode narrow = (NarrowNode) forValue;
             Stamp inputStamp = narrow.getValue().stamp();
             if (inputStamp instanceof IntegerStamp && inputStamp.isCompatible(stamp())) {
                 IntegerStamp istamp = (IntegerStamp) inputStamp;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -26,7 +26,6 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
@@ -39,7 +38,7 @@
  * This node represents the boxing of a primitive value. This corresponds to a call to the valueOf
  * methods in Integer, Long, etc.
  */
-public class BoxNode extends UnaryNode implements VirtualizableAllocation, Lowerable, Canonicalizable {
+public class BoxNode extends UnaryNode implements VirtualizableAllocation, Lowerable {
 
     private final Kind boxingKind;
 
@@ -58,14 +57,11 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
         /*
          * Constant values are not canonicalized into their constant boxing objects because this
          * would mean that the information that they came from a valueOf is lost.
          */
-        if (usages().isEmpty()) {
-            return null;
-        }
         return this;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BranchProbabilityNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BranchProbabilityNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -24,7 +24,6 @@
 
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.calc.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
@@ -35,7 +34,7 @@
  * the if node's taken probability. Then the branch probability node will be removed. This node is
  * intended primarily for snippets, so that they can define their fast and slow paths.
  */
-public class BranchProbabilityNode extends FloatingNode implements Canonicalizable, Lowerable {
+public class BranchProbabilityNode extends FloatingNode implements Simplifiable, Lowerable {
 
     public static final double LIKELY_PROBABILITY = 0.6;
     public static final double NOT_LIKELY_PROBABILITY = 1 - LIKELY_PROBABILITY;
@@ -67,7 +66,7 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public void simplify(SimplifierTool tool) {
         if (probability.isConstant()) {
             double probabilityValue = probability.asConstant().asDouble();
             if (probabilityValue < 0.0) {
@@ -78,9 +77,9 @@
             boolean couldSet = false;
             for (IntegerEqualsNode node : this.usages().filter(IntegerEqualsNode.class)) {
                 if (node.condition() == Condition.EQ) {
-                    ValueNode other = node.x();
-                    if (node.x() == this) {
-                        other = node.y();
+                    ValueNode other = node.getX();
+                    if (node.getX() == this) {
+                        other = node.getY();
                     }
                     if (other.isConstant()) {
                         double probabilityToSet = probabilityValue;
@@ -94,15 +93,15 @@
                     }
                 }
             }
-            if (!couldSet) {
-                if (isSubstitutionGraph()) {
-                    return this;
+            if (couldSet) {
+                replaceAndDelete(condition);
+                tool.addToWorkList(condition.usages());
+            } else {
+                if (!isSubstitutionGraph()) {
+                    throw new GraalInternalError("Wrong usage of branch probability injection!");
                 }
-                throw new GraalInternalError("Wrong usage of branch probability injection!");
             }
-            return condition;
         }
-        return this;
     }
 
     private boolean isSubstitutionGraph() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -25,7 +25,6 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.meta.ResolvedJavaType.Representation;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
@@ -34,23 +33,23 @@
  * Loads an object's {@linkplain Representation#ObjectHub hub}. The object is not null-checked by
  * this operation.
  */
-public final class LoadHubNode extends FloatingGuardedNode implements Lowerable, Canonicalizable, Virtualizable {
+public final class LoadHubNode extends FloatingGuardedNode implements Lowerable, Canonicalizable.Unary<ValueNode>, Virtualizable {
 
-    @Input private ValueNode object;
+    @Input private ValueNode value;
 
-    public ValueNode object() {
-        return object;
+    public ValueNode getValue() {
+        return value;
     }
 
-    public LoadHubNode(ValueNode object, Kind kind) {
+    public LoadHubNode(ValueNode value, Kind kind) {
         super(getKind(kind), null);
-        this.object = object;
+        this.value = value;
     }
 
-    public LoadHubNode(ValueNode object, Kind kind, ValueNode guard) {
+    public LoadHubNode(ValueNode value, Kind kind, ValueNode guard) {
         super(getKind(kind), (GuardingNode) guard);
-        assert object != guard;
-        this.object = object;
+        assert value != guard;
+        this.value = value;
     }
 
     private static Stamp getKind(Kind kind) {
@@ -63,10 +62,10 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forObject) {
         MetaAccessProvider metaAccess = tool.getMetaAccess();
-        if (metaAccess != null && object.stamp() instanceof ObjectStamp) {
-            ObjectStamp stamp = (ObjectStamp) object.stamp();
+        if (metaAccess != null && forObject.stamp() instanceof ObjectStamp) {
+            ObjectStamp stamp = (ObjectStamp) forObject.stamp();
 
             ResolvedJavaType exactType;
             if (stamp.isExactType()) {
@@ -81,7 +80,7 @@
             }
 
             if (exactType != null) {
-                return ConstantNode.forConstant(exactType.getEncoding(Representation.ObjectHub), metaAccess, graph());
+                return ConstantNode.forConstant(exactType.getEncoding(Representation.ObjectHub), metaAccess);
             }
         }
         return this;
@@ -89,7 +88,7 @@
 
     @Override
     public void virtualize(VirtualizerTool tool) {
-        State state = tool.getObjectState(object);
+        State state = tool.getObjectState(value);
         if (state != null) {
             Constant constantHub = state.getVirtualObject().type().getEncoding(Representation.ObjectHub);
             tool.replaceWithValue(ConstantNode.forConstant(constantHub, tool.getMetaAccessProvider(), graph()));
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadMethodNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -61,7 +61,7 @@
     @Override
     public Node canonical(CanonicalizerTool tool) {
         if (hub instanceof LoadHubNode) {
-            ValueNode object = ((LoadHubNode) hub).object();
+            ValueNode object = ((LoadHubNode) hub).getValue();
             ResolvedJavaType type = StampTool.typeOrNull(object);
             if (StampTool.isExactType(object)) {
                 return resolveExactMethod(tool, type);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -24,13 +24,12 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 
-public class UnboxNode extends UnaryNode implements Virtualizable, Lowerable, Canonicalizable {
+public class UnboxNode extends UnaryNode implements Virtualizable, Lowerable {
 
     private final Kind boxingKind;
 
@@ -61,22 +60,19 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (getValue().isConstant()) {
-            Constant constant = getValue().asConstant();
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
+        if (forValue.isConstant()) {
+            Constant constant = forValue.asConstant();
             Constant unboxed = tool.getConstantReflection().unboxPrimitive(constant);
             if (unboxed != null && unboxed.getKind() == boxingKind) {
-                return ConstantNode.forConstant(unboxed, tool.getMetaAccess(), graph());
+                return ConstantNode.forConstant(unboxed, tool.getMetaAccess());
             }
-        } else if (getValue() instanceof BoxNode) {
-            BoxNode box = (BoxNode) getValue();
+        } else if (forValue instanceof BoxNode) {
+            BoxNode box = (BoxNode) forValue;
             if (boxingKind == box.getBoxingKind()) {
                 return box.getValue();
             }
         }
-        if (usages().isEmpty()) {
-            return null;
-        }
         return this;
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -23,7 +23,6 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
@@ -33,7 +32,7 @@
  * Implements a type check where the type being checked is loaded at runtime. This is used, for
  * instance, to implement an object array store check.
  */
-public final class CheckCastDynamicNode extends FixedWithNextNode implements Canonicalizable, Lowerable {
+public final class CheckCastDynamicNode extends FixedWithNextNode implements Canonicalizable.Binary<ValueNode>, Lowerable {
 
     @Input private ValueNode object;
     @Input private ValueNode hub;
@@ -55,6 +54,25 @@
         this.forStoreCheck = forStoreCheck;
     }
 
+    public ValueNode object() {
+        return object;
+    }
+
+    /**
+     * Gets the runtime-loaded type being cast to.
+     */
+    public ValueNode hub() {
+        return hub;
+    }
+
+    public ValueNode getX() {
+        return object;
+    }
+
+    public ValueNode getY() {
+        return hub;
+    }
+
     public boolean isForStoreCheck() {
         return forStoreCheck;
     }
@@ -70,32 +88,19 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        assert object() != null : this;
-
-        if (StampTool.isObjectAlwaysNull(object())) {
-            return object();
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forObject, ValueNode forHub) {
+        if (StampTool.isObjectAlwaysNull(forObject)) {
+            return forObject;
         }
-        if (hub.isConstant()) {
-            ResolvedJavaType t = tool.getConstantReflection().asJavaType(hub.asConstant());
+        if (forHub.isConstant()) {
+            ResolvedJavaType t = tool.getConstantReflection().asJavaType(forHub.asConstant());
             if (t != null) {
-                return graph().add(new CheckCastNode(t, object(), null, forStoreCheck));
+                return graph().add(new CheckCastNode(t, forObject, null, forStoreCheck));
             }
         }
         return this;
     }
 
-    public ValueNode object() {
-        return object;
-    }
-
-    /**
-     * Gets the runtime-loaded type being cast to.
-     */
-    public ValueNode hub() {
-        return hub;
-    }
-
     @NodeIntrinsic
     public static native <T> T checkCastDynamic(Class<T> type, Object object, @ConstantNodeParameter boolean forStoreCheck);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -23,7 +23,6 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
@@ -34,7 +33,7 @@
  * known at compile time. This is used, for instance, to intrinsify {@link Class#isInstance(Object)}
  * .
  */
-public final class InstanceOfDynamicNode extends LogicNode implements Canonicalizable, Lowerable {
+public final class InstanceOfDynamicNode extends LogicNode implements Canonicalizable.Binary<ValueNode>, Lowerable {
 
     @Input private ValueNode object;
     @Input private ValueNode mirror;
@@ -56,16 +55,14 @@
         tool.getLowerer().lower(this, tool);
     }
 
-    @Override
-    public Node canonical(CanonicalizerTool tool) {
-        assert object() != null : this;
-        if (mirror().isConstant()) {
-            ResolvedJavaType t = tool.getConstantReflection().asJavaType(mirror().asConstant());
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forObject, ValueNode forMirror) {
+        if (forMirror.isConstant()) {
+            ResolvedJavaType t = tool.getConstantReflection().asJavaType(forMirror.asConstant());
             if (t != null) {
                 if (t.isPrimitive()) {
-                    return LogicConstantNode.contradiction(graph());
+                    return LogicConstantNode.contradiction();
                 } else {
-                    return graph().unique(new InstanceOfNode(t, object(), null));
+                    return new InstanceOfNode(t, forObject, null);
                 }
             }
         }
@@ -79,4 +76,12 @@
     public ValueNode mirror() {
         return mirror;
     }
+
+    public ValueNode getX() {
+        return object;
+    }
+
+    public ValueNode getY() {
+        return mirror;
+    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -23,9 +23,7 @@
 package com.oracle.graal.nodes.java;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.meta.ProfilingInfo.TriState;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
@@ -34,7 +32,7 @@
 /**
  * The {@code InstanceOfNode} represents an instanceof test.
  */
-public class InstanceOfNode extends UnaryOpLogicNode implements Canonicalizable, Lowerable, Virtualizable {
+public class InstanceOfNode extends UnaryOpLogicNode implements Lowerable, Virtualizable {
 
     private final ResolvedJavaType type;
     private JavaTypeProfile profile;
@@ -58,40 +56,14 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        switch (evaluate(object())) {
-            case FALSE:
-                return LogicConstantNode.contradiction(graph());
-            case TRUE:
-                return LogicConstantNode.tautology(graph());
-            case UNKNOWN:
-                Stamp stamp = object().stamp();
-                if (stamp instanceof ObjectStamp) {
-                    ObjectStamp objectStamp = (ObjectStamp) stamp;
-                    ResolvedJavaType stampType = objectStamp.type();
-                    if (stampType != null && type().isAssignableFrom(stampType)) {
-                        if (!objectStamp.nonNull()) {
-                            // the instanceof matches if the object is non-null, so return true
-                            // depending on the null-ness.
-                            IsNullNode isNull = graph().unique(new IsNullNode(object()));
-                            return graph().unique(new LogicNegationNode(isNull));
-                        }
-                    }
-                }
-                return this;
-        }
-        return this;
-    }
-
-    @Override
-    public TriState evaluate(ValueNode forObject) {
-        Stamp stamp = forObject.stamp();
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
+        Stamp stamp = forValue.stamp();
         if (!(stamp instanceof ObjectStamp)) {
-            return TriState.UNKNOWN;
+            return this;
         }
         ObjectStamp objectStamp = (ObjectStamp) stamp;
         if (objectStamp.alwaysNull()) {
-            return TriState.FALSE;
+            return LogicConstantNode.contradiction();
         }
 
         ResolvedJavaType stampType = objectStamp.type();
@@ -100,25 +72,32 @@
             if (subType) {
                 if (objectStamp.nonNull()) {
                     // the instanceOf matches, so return true
-                    return TriState.TRUE;
+                    return LogicConstantNode.tautology();
                 }
             } else {
                 if (objectStamp.isExactType()) {
                     // since this type check failed for an exact type we know that it can never
                     // succeed at run time. we also don't care about null values, since they will
                     // also make the check fail.
-                    return TriState.FALSE;
+                    return LogicConstantNode.contradiction();
                 } else {
                     boolean superType = stampType.isAssignableFrom(type());
                     if (!superType && !stampType.isInterface() && !type().isInterface()) {
-                        return TriState.FALSE;
+                        return LogicConstantNode.contradiction();
                     }
                     // since the subtype comparison was only performed on a declared type we don't
                     // really know if it might be true at run time...
                 }
             }
         }
-        return TriState.UNKNOWN;
+        if (stampType != null && type().isAssignableFrom(stampType)) {
+            if (!objectStamp.nonNull()) {
+                // the instanceof matches if the object is non-null, so return true
+                // depending on the null-ness.
+                return new LogicNegationNode(new IsNullNode(forValue));
+            }
+        }
+        return this;
     }
 
     /**
@@ -138,7 +117,7 @@
 
     @Override
     public void virtualize(VirtualizerTool tool) {
-        State state = tool.getObjectState(object());
+        State state = tool.getObjectState(getValue());
         if (state != null) {
             tool.replaceWithValue(LogicConstantNode.forBoolean(type().isAssignableFrom(state.getVirtualObject().type()), graph()));
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -37,7 +37,7 @@
  * The {@code LoadFieldNode} represents a read of a static or instance field.
  */
 @NodeInfo(nameTemplate = "LoadField#{p#field/s}")
-public final class LoadFieldNode extends AccessFieldNode implements Canonicalizable, VirtualizableRoot {
+public final class LoadFieldNode extends AccessFieldNode implements Canonicalizable.Unary<ValueNode>, VirtualizableRoot {
 
     /**
      * Creates a new LoadFieldNode instance.
@@ -49,6 +49,10 @@
         super(createStamp(field), object, field);
     }
 
+    public ValueNode getValue() {
+        return object();
+    }
+
     private static Stamp createStamp(ResolvedJavaField field) {
         Kind kind = field.getKind();
         if (kind == Kind.Object && field.getType() instanceof ResolvedJavaType) {
@@ -60,22 +64,26 @@
 
     @Override
     public Node canonical(CanonicalizerTool tool) {
-        if (usages().isEmpty() && !isVolatile() && (isStatic() || StampTool.isObjectNonNull(object().stamp()))) {
+        return canonical(tool, getValue());
+    }
+
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forObject) {
+        if (usages().isEmpty() && !isVolatile() && (isStatic() || StampTool.isObjectNonNull(forObject.stamp()))) {
             return null;
         }
         MetaAccessProvider metaAccess = tool.getMetaAccess();
         if (tool.canonicalizeReads() && metaAccess != null) {
-            ConstantNode constant = asConstant(metaAccess);
+            ConstantNode constant = asConstant(metaAccess, forObject);
             if (constant != null) {
                 return constant;
             }
-            PhiNode phi = asPhi(metaAccess);
+            PhiNode phi = asPhi(metaAccess, forObject);
             if (phi != null) {
                 return phi;
             }
         }
-        if (!isStatic() && object().isNullConstant()) {
-            return graph().add(new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.NullCheckException));
+        if (!isStatic() && forObject.isNullConstant()) {
+            return new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.NullCheckException);
         }
         return this;
     }
@@ -83,22 +91,22 @@
     /**
      * Gets a constant value for this load if possible.
      */
-    public ConstantNode asConstant(MetaAccessProvider metaAccess) {
+    public ConstantNode asConstant(MetaAccessProvider metaAccess, ValueNode forObject) {
         Constant constant = null;
         if (isStatic()) {
             constant = field().readConstantValue(null);
-        } else if (object().isConstant() && !object().isNullConstant()) {
-            constant = field().readConstantValue(object().asConstant());
+        } else if (forObject.isConstant() && !forObject.isNullConstant()) {
+            constant = field().readConstantValue(forObject.asConstant());
         }
         if (constant != null) {
-            return ConstantNode.forConstant(constant, metaAccess, graph());
+            return ConstantNode.forConstant(constant, metaAccess);
         }
         return null;
     }
 
-    private PhiNode asPhi(MetaAccessProvider metaAccess) {
-        if (!isStatic() && field.isFinal() && object() instanceof ValuePhiNode && ((ValuePhiNode) object()).values().filter(isNotA(ConstantNode.class)).isEmpty()) {
-            PhiNode phi = (PhiNode) object();
+    private PhiNode asPhi(MetaAccessProvider metaAccess, ValueNode forObject) {
+        if (!isStatic() && field.isFinal() && forObject instanceof ValuePhiNode && ((ValuePhiNode) forObject).values().filter(isNotA(ConstantNode.class)).isEmpty()) {
+            PhiNode phi = (PhiNode) forObject;
             Constant[] constants = new Constant[phi.valueCount()];
             for (int i = 0; i < phi.valueCount(); i++) {
                 Constant constantValue = field().readConstantValue(phi.valueAt(i).asConstant());
@@ -107,11 +115,11 @@
                 }
                 constants[i] = constantValue;
             }
-            PhiNode newPhi = graph().addWithoutUnique(new ValuePhiNode(stamp(), phi.merge()));
+            ConstantNode[] constantNodes = new ConstantNode[phi.valueCount()];
             for (int i = 0; i < phi.valueCount(); i++) {
-                newPhi.addInput(ConstantNode.forConstant(constants[i], metaAccess, graph()));
+                constantNodes[i] = ConstantNode.forConstant(constants[i], metaAccess);
             }
-            return newPhi;
+            return new ValuePhiNode(stamp(), phi.merge(), constantNodes);
         }
         return null;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -121,8 +121,8 @@
             tool.addToWorkList(blockSuccessor(survivingEdge));
             graph().removeSplit(this, blockSuccessor(survivingEdge));
         }
-        if (value() instanceof LoadHubNode && ((LoadHubNode) value()).object().stamp() instanceof ObjectStamp) {
-            ObjectStamp stamp = (ObjectStamp) ((LoadHubNode) value()).object().stamp();
+        if (value() instanceof LoadHubNode && ((LoadHubNode) value()).getValue().stamp() instanceof ObjectStamp) {
+            ObjectStamp stamp = (ObjectStamp) ((LoadHubNode) value()).getValue().stamp();
             if (stamp.type() != null) {
                 int validKeys = 0;
                 for (int i = 0; i < keyCount(); i++) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java	Wed Jun 25 17:34:25 2014 +0200
@@ -24,12 +24,15 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.Graph.Mark;
 import com.oracle.graal.graph.Graph.NodeChangedListener;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.graph.spi.Canonicalizable.Binary;
+import com.oracle.graal.graph.spi.Canonicalizable.Unary;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.util.*;
@@ -229,11 +232,50 @@
             return result;
         }
 
+        private static AutoCloseable getCanonicalizeableContractAssertion(Node node) {
+            boolean needsAssertion = false;
+            assert (needsAssertion = true) == true;
+            if (needsAssertion) {
+                Mark mark = node.graph().getMark();
+                return () -> {
+                    assert mark.equals(node.graph().getMark()) : "new node created while canonicalizing " + node.getClass().getSimpleName() + " " + node + ": " +
+                                    node.graph().getNewNodes(mark).snapshot();
+                };
+            } else {
+                return new AutoCloseable() {
+                    public void close() throws Exception {
+                        // nothing to do
+                    }
+                };
+            }
+        }
+
         public boolean baseTryCanonicalize(final Node node, NodeClass nodeClass) {
-            if (nodeClass.isCanonicalizable()) {
+            if (nodeClass.getCanonicalizeMethod() != null) {
                 METRIC_CANONICALIZATION_CONSIDERED_NODES.increment();
                 try (Scope s = Debug.scope("CanonicalizeNode", node)) {
-                    Node canonical = node.canonical(tool);
+                    Node canonical;
+                    switch (nodeClass.getCanonicalizeMethod()) {
+                        case BASE:
+                            canonical = node.canonical(tool);
+                            break;
+                        case UNARY:
+                            try (AutoCloseable verify = getCanonicalizeableContractAssertion(node)) {
+                                @SuppressWarnings("unchecked")
+                                Canonicalizable.Unary<Node> unary = (Unary<Node>) node;
+                                canonical = unary.canonical(tool, unary.getValue());
+                            }
+                            break;
+                        case BINARY:
+                            try (AutoCloseable verify = getCanonicalizeableContractAssertion(node)) {
+                                @SuppressWarnings("unchecked")
+                                Canonicalizable.Binary<Node> binary = (Binary<Node>) node;
+                                canonical = binary.canonical(tool, binary.getX(), binary.getY());
+                            }
+                            break;
+                        default:
+                            throw GraalInternalError.shouldNotReachHere("unexpected CanonicalizeMethod");
+                    }
                     if (performReplacement(node, canonical)) {
                         return true;
                     }
@@ -271,14 +313,19 @@
 //                                         --------------------------------------------
 //       X: must not happen (checked with assertions)
 // @formatter:on
-        private boolean performReplacement(final Node node, Node canonical) {
-            if (canonical == node) {
+        private boolean performReplacement(final Node node, Node newCanonical) {
+            if (newCanonical == node) {
                 Debug.log("Canonicalizer: work on %1s", node);
                 return false;
             } else {
+                Node canonical = newCanonical;
                 Debug.log("Canonicalizer: replacing %1s with %1s", node, canonical);
                 METRIC_CANONICALIZED_NODES.increment();
                 StructuredGraph graph = (StructuredGraph) node.graph();
+                if (canonical != null && !canonical.isAlive()) {
+                    assert !canonical.isDeleted();
+                    canonical = graph.addOrUniqueWithInputs(canonical);
+                }
                 if (node instanceof FloatingNode) {
                     if (canonical == null) {
                         // case 1
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java	Wed Jun 25 17:34:25 2014 +0200
@@ -373,16 +373,16 @@
 
             if (isTrue && condition instanceof InstanceOfNode) {
                 InstanceOfNode instanceOf = (InstanceOfNode) condition;
-                ValueNode object = instanceOf.object();
+                ValueNode object = instanceOf.getValue();
                 state.addNullness(false, object);
                 state.addType(instanceOf.type(), object);
             } else if (condition instanceof IsNullNode) {
                 IsNullNode nullCheck = (IsNullNode) condition;
-                state.addNullness(isTrue, nullCheck.object());
+                state.addNullness(isTrue, nullCheck.getValue());
             } else if (condition instanceof ObjectEqualsNode) {
                 ObjectEqualsNode equals = (ObjectEqualsNode) condition;
-                ValueNode x = equals.x();
-                ValueNode y = equals.y();
+                ValueNode x = equals.getX();
+                ValueNode y = equals.getY();
                 if (isTrue) {
                     if (state.isNull(x) && !state.isNull(y)) {
                         metricObjectEqualsRegistered.increment();
@@ -438,8 +438,8 @@
                         }
                     }
                     if (type != null) {
-                        state.addNullness(false, loadHub.object());
-                        state.addType(type, loadHub.object());
+                        state.addNullness(false, loadHub.getValue());
+                        state.addType(type, loadHub.getValue());
                     }
                 }
             }
@@ -452,16 +452,16 @@
                     return null;
                 }
                 IntegerBelowThanNode below = (IntegerBelowThanNode) guard.condition();
-                if (below.x().getKind() == Kind.Int && below.x().isConstant() && !below.y().isConstant()) {
-                    Stamp stamp = StampTool.unsignedCompare(below.x().stamp(), below.y().stamp());
+                if (below.getX().getKind() == Kind.Int && below.getX().isConstant() && !below.getY().isConstant()) {
+                    Stamp stamp = StampTool.unsignedCompare(below.getX().stamp(), below.getY().stamp());
                     if (stamp != null) {
-                        return new GuardedStamp(below.y(), stamp, guard);
+                        return new GuardedStamp(below.getY(), stamp, guard);
                     }
                 }
-                if (below.y().getKind() == Kind.Int && below.y().isConstant() && !below.x().isConstant()) {
-                    Stamp stamp = StampTool.unsignedCompare(below.x().stamp(), below.y().stamp());
+                if (below.getY().getKind() == Kind.Int && below.getY().isConstant() && !below.getX().isConstant()) {
+                    Stamp stamp = StampTool.unsignedCompare(below.getX().stamp(), below.getY().stamp());
                     if (stamp != null) {
-                        return new GuardedStamp(below.x(), stamp, guard);
+                        return new GuardedStamp(below.getX(), stamp, guard);
                     }
                 }
             }
@@ -522,13 +522,13 @@
             GuardNode existingGuard = null;
             if (guard.condition() instanceof IntegerBelowThanNode) {
                 IntegerBelowThanNode below = (IntegerBelowThanNode) guard.condition();
-                IntegerStamp xStamp = (IntegerStamp) below.x().stamp();
-                IntegerStamp yStamp = (IntegerStamp) below.y().stamp();
-                GuardedStamp cstamp = state.valueConstraints.get(below.x());
+                IntegerStamp xStamp = (IntegerStamp) below.getX().stamp();
+                IntegerStamp yStamp = (IntegerStamp) below.getY().stamp();
+                GuardedStamp cstamp = state.valueConstraints.get(below.getX());
                 if (cstamp != null) {
                     xStamp = (IntegerStamp) cstamp.getStamp();
                 } else {
-                    cstamp = state.valueConstraints.get(below.y());
+                    cstamp = state.valueConstraints.get(below.getY());
                     if (cstamp != null) {
                         yStamp = (IntegerStamp) cstamp.getStamp();
                     }
@@ -552,10 +552,10 @@
                 }
             } else if (guard.condition() instanceof IntegerEqualsNode && guard.negated()) {
                 IntegerEqualsNode equals = (IntegerEqualsNode) guard.condition();
-                GuardedStamp cstamp = state.valueConstraints.get(equals.y());
-                if (cstamp != null && equals.x().isConstant()) {
+                GuardedStamp cstamp = state.valueConstraints.get(equals.getY());
+                if (cstamp != null && equals.getX().isConstant()) {
                     IntegerStamp stamp = (IntegerStamp) cstamp.getStamp();
-                    if (!stamp.contains(equals.x().asConstant().asLong())) {
+                    if (!stamp.contains(equals.getX().asConstant().asLong())) {
                         // x != n is true if n is outside the range of the stamp
                         existingGuard = cstamp.getGuard();
                         Debug.log("existing guard %s %1s proves !%1s", existingGuard, existingGuard.condition(), guard.condition());
@@ -620,7 +620,7 @@
             } else {
                 if (condition instanceof InstanceOfNode) {
                     InstanceOfNode instanceOf = (InstanceOfNode) condition;
-                    ValueNode object = instanceOf.object();
+                    ValueNode object = instanceOf.getValue();
                     if (state.isNull(object)) {
                         metricInstanceOfRemoved.increment();
                         return falseValue;
@@ -633,7 +633,7 @@
                     }
                 } else if (condition instanceof IsNullNode) {
                     IsNullNode isNull = (IsNullNode) condition;
-                    ValueNode object = isNull.object();
+                    ValueNode object = isNull.getValue();
                     if (state.isNull(object)) {
                         metricNullCheckRemoved.increment();
                         return trueValue;
@@ -643,8 +643,8 @@
                     }
                 } else if (condition instanceof ObjectEqualsNode) {
                     ObjectEqualsNode equals = (ObjectEqualsNode) condition;
-                    ValueNode x = equals.x();
-                    ValueNode y = equals.y();
+                    ValueNode x = equals.getX();
+                    ValueNode y = equals.getY();
                     if (state.isNull(x) && state.isNonNull(y) || state.isNonNull(x) && state.isNull(y)) {
                         metricObjectEqualsRemoved.increment();
                         return falseValue;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConvertDeoptimizeToGuardPhase.java	Wed Jun 25 17:34:25 2014 +0200
@@ -71,11 +71,11 @@
                     CompareNode compare = (CompareNode) fixedGuard.condition();
                     List<AbstractEndNode> mergePredecessors = merge.cfgPredecessors().snapshot();
 
-                    Constant[] xs = IfNode.constantValues(compare.x(), merge, true);
+                    Constant[] xs = IfNode.constantValues(compare.getX(), merge, true);
                     if (xs == null) {
                         continue;
                     }
-                    Constant[] ys = IfNode.constantValues(compare.y(), merge, true);
+                    Constant[] ys = IfNode.constantValues(compare.getY(), merge, true);
                     if (ys == null) {
                         continue;
                     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Wed Jun 25 17:34:25 2014 +0200
@@ -117,7 +117,7 @@
         private void processGuard(Node node) {
             GuardNode guard = (GuardNode) node;
             if (guard.negated() && guard.condition() instanceof IsNullNode && (guard.getSpeculation() == null || guard.getSpeculation().equals(Constant.NULL_OBJECT))) {
-                ValueNode obj = ((IsNullNode) guard.condition()).object();
+                ValueNode obj = ((IsNullNode) guard.condition()).getValue();
                 nullGuarded.put(obj, guard);
             }
         }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/UseTrappingNullChecksPhase.java	Wed Jun 25 17:34:25 2014 +0200
@@ -157,7 +157,7 @@
         IsNullNode isNullNode = (IsNullNode) condition;
         BeginNode nonTrappingContinuation = ifNode.falseSuccessor();
         BeginNode trappingContinuation = ifNode.trueSuccessor();
-        NullCheckNode trappingNullCheck = deopt.graph().add(new NullCheckNode(isNullNode.object()));
+        NullCheckNode trappingNullCheck = deopt.graph().add(new NullCheckNode(isNullNode.getValue()));
         trappingNullCheck.setStateBefore(deopt.stateBefore());
         deopt.graph().replaceSplit(ifNode, trappingNullCheck, nonTrappingContinuation);
 
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/CastCheckExtractor.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/CastCheckExtractor.java	Wed Jun 25 17:34:25 2014 +0200
@@ -45,7 +45,7 @@
     private static CastCheckExtractor extractCastCheckInfo(LogicNode x, LogicNode y) {
         if (x instanceof IsNullNode) {
             IsNullNode isNull = (IsNullNode) x;
-            ValueNode subject = isNull.object();
+            ValueNode subject = isNull.getValue();
             if (isInstanceOfCheckOn(y, subject)) {
                 InstanceOfNode iOf = (InstanceOfNode) y;
                 return new CastCheckExtractor(iOf.type(), subject);
@@ -82,6 +82,6 @@
             return false;
         }
         InstanceOfNode io = (InstanceOfNode) cond;
-        return io.object() == subject;
+        return io.getValue() == subject;
     }
 }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/EquationalReasoner.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/EquationalReasoner.java	Wed Jun 25 17:34:25 2014 +0200
@@ -27,10 +27,12 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.graph.spi.Canonicalizable.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
@@ -332,10 +334,32 @@
         }
         FlowUtil.inferStampAndCheck(changed);
         added.add(changed);
-        ValueNode canon = (ValueNode) changed.canonical(tool);
+
+        Node canon;
+        switch (changed.getNodeClass().getCanonicalizeMethod()) {
+            case BASE:
+                canon = changed.canonical(tool);
+                break;
+            case UNARY:
+                @SuppressWarnings("unchecked")
+                Canonicalizable.Unary<Node> unary = (Unary<Node>) changed;
+                canon = unary.canonical(tool, unary.getValue());
+                break;
+            case BINARY:
+                @SuppressWarnings("unchecked")
+                Canonicalizable.Binary<Node> binary = (Binary<Node>) changed;
+                canon = binary.canonical(tool, binary.getX(), binary.getY());
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere("unexpected CanonicalizeMethod");
+        }
+        if (canon != null && !canon.isAlive()) {
+            assert !canon.isDeleted();
+            canon = graph.addOrUniqueWithInputs(canon);
+        }
         // might be already in `added`, no problem adding it again.
-        added.add(canon);
-        rememberSubstitution(f, canon);
+        added.add((ValueNode) canon);
+        rememberSubstitution(f, (ValueNode) canon);
         return canon;
     }
 
@@ -445,7 +469,7 @@
      *
      */
     private LogicNode baseCaseInstanceOfNode(InstanceOfNode instanceOf) {
-        ValueNode scrutinee = GraphUtil.unproxify(instanceOf.object());
+        ValueNode scrutinee = GraphUtil.unproxify(instanceOf.getValue());
         if (!FlowUtil.hasLegalObjectStamp(scrutinee)) {
             return instanceOf;
         }
@@ -470,7 +494,7 @@
      *
      */
     private FloatingNode baseCaseIsNullNode(IsNullNode isNu) {
-        ValueNode object = isNu.object();
+        ValueNode object = isNu.getValue();
         if (!FlowUtil.hasLegalObjectStamp(object)) {
             return isNu;
         }
@@ -489,11 +513,11 @@
      *         otherwise the unmodified argument.
      */
     private LogicNode baseCaseObjectEqualsNode(ObjectEqualsNode equals) {
-        if (!FlowUtil.hasLegalObjectStamp(equals.x()) || !FlowUtil.hasLegalObjectStamp(equals.y())) {
+        if (!FlowUtil.hasLegalObjectStamp(equals.getX()) || !FlowUtil.hasLegalObjectStamp(equals.getY())) {
             return equals;
         }
-        ValueNode x = GraphUtil.unproxify(equals.x());
-        ValueNode y = GraphUtil.unproxify(equals.y());
+        ValueNode x = GraphUtil.unproxify(equals.getX());
+        ValueNode y = GraphUtil.unproxify(equals.getY());
         if (state.isNull(x) && state.isNonNull(y) || state.isNonNull(x) && state.isNull(y)) {
             metricObjectEqualsRemoved.increment();
             return falseConstant;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReduction.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReduction.java	Wed Jun 25 17:34:25 2014 +0200
@@ -234,7 +234,7 @@
                 return;
             }
             // it's unwarranted to assume loadHub.object() to be non-null
-            state.trackCC(loadHub.object(), type, begin);
+            state.trackCC(loadHub.getValue(), type, begin);
         }
     }
 
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/GuardingPiReduction.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/GuardingPiReduction.java	Wed Jun 25 17:34:25 2014 +0200
@@ -359,7 +359,7 @@
             return false;
         }
         IsNullNode isNull = (IsNullNode) cond;
-        return isNull.object() == subject;
+        return isNull.getValue() == subject;
     }
 
     /**
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/State.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/State.java	Wed Jun 25 17:34:25 2014 +0200
@@ -647,7 +647,7 @@
         }
 
         if (condition instanceof LogicNegationNode) {
-            addFact(!isTrue, ((LogicNegationNode) condition).getInput(), anchor);
+            addFact(!isTrue, ((LogicNegationNode) condition).getValue(), anchor);
         } else if (condition instanceof ShortCircuitOrNode) {
             /*
              * We can register the conditions being or-ed as long as the anchor is a fixed node,
@@ -677,7 +677,7 @@
             addFactInstanceOf(isTrue, (InstanceOfNode) condition, anchor);
         } else if (condition instanceof IsNullNode) {
             IsNullNode nullCheck = (IsNullNode) condition;
-            addNullness(isTrue, nullCheck.object(), anchor);
+            addNullness(isTrue, nullCheck.getValue(), anchor);
         } else if (condition instanceof ObjectEqualsNode) {
             addFactObjectEqualsNode(isTrue, (ObjectEqualsNode) condition, anchor);
         } else {
@@ -692,7 +692,7 @@
      *
      */
     private void addFactInstanceOf(boolean isTrue, InstanceOfNode instanceOf, GuardingNode anchor) {
-        ValueNode object = instanceOf.object();
+        ValueNode object = instanceOf.getValue();
         if (isTrue) {
             if (knownNotToPassInstanceOf(object, instanceOf.type())) {
                 impossiblePath();
@@ -710,15 +710,15 @@
     }
 
     private void addFactObjectEqualsNode(boolean isTrue, ObjectEqualsNode equals, GuardingNode anchor) {
-        if (isDependencyTainted(equals.x(), anchor)) {
+        if (isDependencyTainted(equals.getX(), anchor)) {
             return;
         }
-        if (isDependencyTainted(equals.y(), anchor)) {
+        if (isDependencyTainted(equals.getY(), anchor)) {
             return;
         }
         assert anchor instanceof FixedNode;
-        ValueNode x = GraphUtil.unproxify(equals.x());
-        ValueNode y = GraphUtil.unproxify(equals.y());
+        ValueNode x = GraphUtil.unproxify(equals.getX());
+        ValueNode y = GraphUtil.unproxify(equals.getY());
         if (isTrue) {
             if (isNull(x) && isNonNull(y)) {
                 impossiblePath();
@@ -730,12 +730,12 @@
             }
             if (isNull(x) || isNull(y)) {
                 metricObjectEqualsRegistered.increment();
-                addNullness(true, equals.x(), anchor);
-                addNullness(true, equals.y(), anchor);
+                addNullness(true, equals.getX(), anchor);
+                addNullness(true, equals.getY(), anchor);
             } else if (isNonNull(x) || isNonNull(y)) {
                 metricObjectEqualsRegistered.increment();
-                addNullness(false, equals.x(), anchor);
-                addNullness(false, equals.y(), anchor);
+                addNullness(false, equals.getX(), anchor);
+                addNullness(false, equals.getY(), anchor);
             }
             Witness wx = typeInfo(x);
             Witness wy = typeInfo(y);
@@ -748,8 +748,8 @@
                 if (best != null) {
                     assert !best.isInterface();
                     // type tightening is enough, nullness already taken care of
-                    trackCC(equals.x(), best, anchor);
-                    trackCC(equals.y(), best, anchor);
+                    trackCC(equals.getX(), best, anchor);
+                    trackCC(equals.getY(), best, anchor);
                 }
             } else if (wx == null) {
                 typeRefinements.put(x, new Witness(wy));
@@ -759,10 +759,10 @@
         } else {
             if (isNull(x) && !isNonNull(y)) {
                 metricObjectEqualsRegistered.increment();
-                addNullness(false, equals.y(), anchor);
+                addNullness(false, equals.getY(), anchor);
             } else if (!isNonNull(x) && isNull(y)) {
                 metricObjectEqualsRegistered.increment();
-                addNullness(false, equals.x(), anchor);
+                addNullness(false, equals.getX(), anchor);
             }
         }
     }
@@ -911,20 +911,20 @@
     private Evidence outcomeIsNullNode(boolean isTrue, IsNullNode isNullNode) {
         if (isTrue) {
             // grab an anchor attesting nullness
-            final GuardingNode replacement = nonTrivialNullAnchor(isNullNode.object());
+            final GuardingNode replacement = nonTrivialNullAnchor(isNullNode.getValue());
             if (replacement != null) {
                 return new Evidence(replacement);
             }
-            if (isNonNull(isNullNode.object())) {
+            if (isNonNull(isNullNode.getValue())) {
                 return Evidence.COUNTEREXAMPLE;
             }
         } else {
             // grab an anchor attesting non-nullness
-            final Witness w = typeInfo(isNullNode.object());
+            final Witness w = typeInfo(isNullNode.getValue());
             if (w != null && w.isNonNull()) {
                 return new Evidence(w.guard());
             }
-            if (isNull(isNullNode.object())) {
+            if (isNull(isNullNode.getValue())) {
                 return Evidence.COUNTEREXAMPLE;
             }
         }
@@ -936,9 +936,9 @@
      * Utility method for {@link #outcome(boolean, com.oracle.graal.nodes.LogicNode)}
      */
     private Evidence outcomeInstanceOfNode(boolean isTrue, InstanceOfNode iOf) {
-        final Witness w = typeInfo(iOf.object());
+        final Witness w = typeInfo(iOf.getValue());
         if (isTrue) {
-            if (isNull(iOf.object())) {
+            if (isNull(iOf.getValue())) {
                 return Evidence.COUNTEREXAMPLE;
             }
             // grab an anchor attesting instanceof
@@ -957,7 +957,7 @@
         } else {
             // grab an anchor attesting not-instanceof
             // (1 of 2) attempt determining nullness
-            final GuardingNode nullGuard = nonTrivialNullAnchor(iOf.object());
+            final GuardingNode nullGuard = nonTrivialNullAnchor(iOf.getValue());
             if (nullGuard != null) {
                 return new Evidence(nullGuard);
             }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyUsageWithEquals.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/verify/VerifyUsageWithEquals.java	Wed Jun 25 17:34:25 2014 +0200
@@ -67,8 +67,8 @@
     protected boolean verify(StructuredGraph graph, PhaseContext context) {
         for (ObjectEqualsNode cn : graph.getNodes().filter(ObjectEqualsNode.class)) {
             // bail out if we compare an object of type klass with == or != (except null checks)
-            if (checkUsage(cn.x(), cn.y(), context.getMetaAccess()) && checkUsage(cn.y(), cn.x(), context.getMetaAccess())) {
-                throw new VerificationError("Verification of " + klass.getName() + " usage failed: Comparing " + cn.x() + " and " + cn.y() + " in " + graph.method() +
+            if (checkUsage(cn.getX(), cn.getY(), context.getMetaAccess()) && checkUsage(cn.getY(), cn.getX(), context.getMetaAccess())) {
+                throw new VerificationError("Verification of " + klass.getName() + " usage failed: Comparing " + cn.getX() + " and " + cn.getY() + " in " + graph.method() +
                                 " must use .equals() for object equality, not '==' or '!='");
             }
         }
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -26,6 +26,7 @@
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
@@ -50,6 +51,12 @@
         throw GraalInternalError.shouldNotReachHere();
     }
 
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
+        // nothing to do
+        return this;
+    }
+
     public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
         builder.setResult(this, gen.emitFloatConvert(op, builder.operand(getValue())));
     }
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java	Wed Jun 25 17:34:25 2014 +0200
@@ -50,7 +50,7 @@
     protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) {
         InstanceOfNode ion = graph.getNodes().filter(InstanceOfNode.class).first();
         if (ion != null) {
-            InstanceOfNode ionNew = graph.unique(new InstanceOfNode(ion.type(), ion.object(), profile));
+            InstanceOfNode ionNew = graph.unique(new InstanceOfNode(ion.type(), ion.getValue(), profile));
             graph.replaceFloating(ion, ionNew);
         }
     }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java	Wed Jun 25 17:34:25 2014 +0200
@@ -223,7 +223,7 @@
         if (graph.getGuardsStage().ordinal() < StructuredGraph.GuardsStage.FIXED_DEOPTS.ordinal()) {
             return;
         }
-        ValueNode hub = createReadHub(graph, loadHub.object(), loadHub.getGuard());
+        ValueNode hub = createReadHub(graph, loadHub.getValue(), loadHub.getGuard());
         graph.replaceFloating(loadHub, hub);
     }
 
@@ -589,16 +589,16 @@
         }
         if (offset instanceof IntegerAddNode) {
             IntegerAddNode integerAddNode = (IntegerAddNode) offset;
-            if (integerAddNode.y() instanceof ConstantNode) {
-                displacement = integerAddNode.y().asConstant().asLong();
-                offset = integerAddNode.x();
+            if (integerAddNode.getY() instanceof ConstantNode) {
+                displacement = integerAddNode.getY().asConstant().asLong();
+                offset = integerAddNode.getX();
             }
         }
 
         if (offset instanceof LeftShiftNode) {
             LeftShiftNode leftShiftNode = (LeftShiftNode) offset;
-            if (leftShiftNode.y() instanceof ConstantNode) {
-                long shift = leftShiftNode.y().asConstant().asLong();
+            if (leftShiftNode.getY() instanceof ConstantNode) {
+                long shift = leftShiftNode.getY().asConstant().asLong();
                 if (shift >= 1 && shift <= 3) {
                     if (shift == 1) {
                         indexScaling = 2;
@@ -607,7 +607,7 @@
                     } else {
                         indexScaling = 8;
                     }
-                    offset = leftShiftNode.x();
+                    offset = leftShiftNode.getX();
                 }
             }
         }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java	Wed Jun 25 17:34:25 2014 +0200
@@ -141,7 +141,7 @@
                 assert testValue.isConstant();
                 return LogicConstantNode.forBoolean(result.asConstant().equals(testValue.asConstant()), result.graph());
             }
-            if (condition == null || condition.y() != testValue) {
+            if (condition == null || condition.getY() != testValue) {
                 // Re-use previously generated condition if the trueValue for the test is the same
                 condition = createCompareNode(result.graph(), Condition.EQ, result, testValue);
             }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/IntegerSubstitutions.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/IntegerSubstitutions.java	Wed Jun 25 17:34:25 2014 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.replacements;
 
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.replacements.nodes.*;
@@ -58,11 +57,11 @@
 
     @MethodSubstitution
     public static int divideUnsigned(int dividend, int divisor) {
-        return UnsignedDivNode.unsignedDivide(Kind.Int, dividend, divisor);
+        return UnsignedDivNode.unsignedDivide(dividend, divisor);
     }
 
     @MethodSubstitution
     public static int remainderUnsigned(int dividend, int divisor) {
-        return UnsignedRemNode.unsignedRemainder(Kind.Int, dividend, divisor);
+        return UnsignedRemNode.unsignedRemainder(dividend, divisor);
     }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/LongSubstitutions.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/LongSubstitutions.java	Wed Jun 25 17:34:25 2014 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.replacements;
 
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.replacements.nodes.*;
@@ -58,11 +57,11 @@
 
     @MethodSubstitution
     public static long divideUnsigned(long dividend, long divisor) {
-        return UnsignedDivNode.unsignedDivide(Kind.Long, dividend, divisor);
+        return UnsignedDivNode.unsignedDivide(dividend, divisor);
     }
 
     @MethodSubstitution
     public static long remainderUnsigned(long dividend, long divisor) {
-        return UnsignedRemNode.unsignedRemainder(Kind.Long, dividend, divisor);
+        return UnsignedRemNode.unsignedRemainder(dividend, divisor);
     }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsignedMathSubstitutions.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/UnsignedMathSubstitutions.java	Wed Jun 25 17:34:25 2014 +0200
@@ -26,9 +26,7 @@
 import static com.oracle.graal.nodes.calc.ConditionalNode.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.graph.Node.ConstantNodeParameter;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
 import com.oracle.graal.nodes.calc.*;
 
@@ -101,7 +99,7 @@
      */
     @MethodSubstitution
     public static int divide(int a, int b) {
-        return unsignedDivide(Kind.Int, a, b);
+        return unsignedDivide(a, b);
     }
 
     /**
@@ -109,7 +107,7 @@
      */
     @MethodSubstitution
     public static int remainder(int a, int b) {
-        return unsignedRemainder(Kind.Int, a, b);
+        return unsignedRemainder(a, b);
     }
 
     /**
@@ -117,7 +115,7 @@
      */
     @MethodSubstitution
     public static long divide(long a, long b) {
-        return unsignedDivide(Kind.Long, a, b);
+        return unsignedDivide(a, b);
     }
 
     /**
@@ -125,18 +123,18 @@
      */
     @MethodSubstitution
     public static long remainder(long a, long b) {
-        return unsignedRemainder(Kind.Long, a, b);
+        return unsignedRemainder(a, b);
     }
 
     @NodeIntrinsic(UnsignedDivNode.class)
-    private static native int unsignedDivide(@ConstantNodeParameter Kind kind, int a, int b);
+    private static native int unsignedDivide(int a, int b);
 
     @NodeIntrinsic(UnsignedDivNode.class)
-    private static native long unsignedDivide(@ConstantNodeParameter Kind kind, long a, long b);
+    private static native long unsignedDivide(long a, long b);
 
     @NodeIntrinsic(UnsignedRemNode.class)
-    private static native int unsignedRemainder(@ConstantNodeParameter Kind kind, int a, int b);
+    private static native int unsignedRemainder(int a, int b);
 
     @NodeIntrinsic(UnsignedRemNode.class)
-    private static native long unsignedRemainder(@ConstantNodeParameter Kind kind, long a, long b);
+    private static native long unsignedRemainder(long a, long b);
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitCountNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -24,13 +24,12 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 
-public class BitCountNode extends UnaryNode implements LIRLowerable, Canonicalizable {
+public class BitCountNode extends UnaryNode implements LIRLowerable {
 
     public BitCountNode(ValueNode value) {
         super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits()), value);
@@ -46,14 +45,10 @@
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (getValue().isConstant()) {
-            Constant c = getValue().asConstant();
-            if (c.getKind() == Kind.Int) {
-                return ConstantNode.forInt(Integer.bitCount(c.asInt()), graph());
-            } else if (c.getKind() == Kind.Long) {
-                return ConstantNode.forInt(Long.bitCount(c.asLong()), graph());
-            }
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
+        if (forValue.isConstant()) {
+            Constant c = forValue.asConstant();
+            return ConstantNode.forInt(forValue.getKind() == Kind.Int ? bitCount(c.asInt()) : bitCount(c.asLong()));
         }
         return this;
     }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -24,10 +24,15 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 
+/**
+ * Determines the index of the least significant "1" bit. Note that the result is undefined if the
+ * input is zero.
+ */
 public class BitScanForwardNode extends UnaryNode implements LIRLowerable {
 
     public BitScanForwardNode(ValueNode value) {
@@ -54,6 +59,15 @@
         return updateStamp(StampFactory.forInteger(Kind.Int, min, max));
     }
 
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
+        if (forValue.isConstant()) {
+            Constant c = forValue.asConstant();
+            return ConstantNode.forInt(forValue.getKind() == Kind.Int ? scan(c.asInt()) : scan(c.asLong()));
+        }
+        return this;
+    }
+
     @NodeIntrinsic
     public static int scan(long v) {
         if (v == 0) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -24,10 +24,15 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 
+/**
+ * Determines the index of the most significant "1" bit. Note that the result is undefined if the
+ * input is zero.
+ */
 public class BitScanReverseNode extends UnaryNode implements LIRLowerable {
 
     public BitScanReverseNode(ValueNode value) {
@@ -52,6 +57,15 @@
         return updateStamp(StampFactory.forInteger(Kind.Int, min, max));
     }
 
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
+        if (forValue.isConstant()) {
+            Constant c = forValue.asConstant();
+            return ConstantNode.forInt(forValue.getKind() == Kind.Int ? scan(c.asInt()) : scan(c.asLong()));
+        }
+        return this;
+    }
+
     @NodeIntrinsic
     public static int scan(int v) {
         if (v == 0) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
@@ -51,6 +52,15 @@
         return updateStamp(newStamp);
     }
 
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
+        if (forValue.isConstant()) {
+            Constant c = forValue.asConstant();
+            return ConstantNode.forIntegerKind(getKind(), getKind() == Kind.Int ? reverse(c.asInt()) : reverse(c.asLong()));
+        }
+        return this;
+    }
+
     @NodeIntrinsic
     public static int reverse(int v) {
         return Integer.reverseBytes(v);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -24,7 +24,6 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
@@ -36,27 +35,27 @@
  * Node representing an exact integer addition that will throw an {@link ArithmeticException} in
  * case the addition would overflow the 32 bit range.
  */
-public class IntegerAddExactNode extends IntegerAddNode implements Canonicalizable, IntegerExactArithmeticNode {
+public class IntegerAddExactNode extends IntegerAddNode implements IntegerExactArithmeticNode {
 
     public IntegerAddExactNode(ValueNode x, ValueNode y) {
-        super(x.stamp().unrestricted(), x, y);
+        super(x, y);
         assert x.stamp().isCompatible(y.stamp()) && x.stamp() instanceof IntegerStamp;
     }
 
     @Override
     public boolean inferStamp() {
-        // TODO Should probably use a specialised version which understands that it can't overflow
-        return updateStamp(StampTool.add(x().stamp(), y().stamp()));
+        // TODO Should probably use a specialized version which understands that it can't overflow
+        return updateStamp(StampTool.add(getX().stamp(), getY().stamp()));
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (x().isConstant() && !y().isConstant()) {
-            return graph().unique(new IntegerAddExactNode(y(), x()));
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        if (forX.isConstant() && !forY.isConstant()) {
+            return new IntegerAddExactNode(forY, forX);
         }
-        if (x().isConstant()) {
-            Constant xConst = x().asConstant();
-            Constant yConst = y().asConstant();
+        if (forX.isConstant()) {
+            Constant xConst = forX.asConstant();
+            Constant yConst = forY.asConstant();
             assert xConst.getKind() == yConst.getKind();
             try {
                 if (xConst.getKind() == Kind.Int) {
@@ -68,10 +67,10 @@
             } catch (ArithmeticException ex) {
                 // The operation will result in an overflow exception, so do not canonicalize.
             }
-        } else if (y().isConstant()) {
-            long c = y().asConstant().asLong();
+        } else if (forY.isConstant()) {
+            long c = forY.asConstant().asLong();
             if (c == 0) {
-                return x();
+                return forX;
             }
         }
         return this;
@@ -79,7 +78,7 @@
 
     @Override
     public IntegerExactArithmeticSplitNode createSplit(BeginNode next, BeginNode deopt) {
-        return graph().add(new IntegerAddExactSplitNode(stamp(), x(), y(), next, deopt));
+        return graph().add(new IntegerAddExactSplitNode(stamp(), getX(), getY(), next, deopt));
     }
 
     @Override
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -24,7 +24,6 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
@@ -35,39 +34,39 @@
  * Node representing an exact integer multiplication that will throw an {@link ArithmeticException}
  * in case the addition would overflow the 32 bit range.
  */
-public class IntegerMulExactNode extends IntegerMulNode implements Canonicalizable, IntegerExactArithmeticNode {
+public class IntegerMulExactNode extends IntegerMulNode implements IntegerExactArithmeticNode {
 
     public IntegerMulExactNode(ValueNode x, ValueNode y) {
-        super(x.stamp().unrestricted(), x, y);
+        super(x, y);
         assert x.stamp().isCompatible(y.stamp()) && x.stamp() instanceof IntegerStamp;
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (x().isConstant() && !y().isConstant()) {
-            return graph().unique(new IntegerMulExactNode(y(), x()));
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        if (forX.isConstant() && !forY.isConstant()) {
+            return new IntegerMulExactNode(forY, forX);
         }
-        if (x().isConstant()) {
-            Constant xConst = x().asConstant();
-            Constant yConst = y().asConstant();
+        if (forX.isConstant()) {
+            Constant xConst = forX.asConstant();
+            Constant yConst = forY.asConstant();
             assert xConst.getKind() == yConst.getKind();
             try {
                 if (xConst.getKind() == Kind.Int) {
-                    return ConstantNode.forInt(ExactMath.multiplyExact(xConst.asInt(), yConst.asInt()), graph());
+                    return ConstantNode.forInt(ExactMath.multiplyExact(xConst.asInt(), yConst.asInt()));
                 } else {
                     assert xConst.getKind() == Kind.Long;
-                    return ConstantNode.forLong(ExactMath.multiplyExact(xConst.asLong(), yConst.asLong()), graph());
+                    return ConstantNode.forLong(ExactMath.multiplyExact(xConst.asLong(), yConst.asLong()));
                 }
             } catch (ArithmeticException ex) {
                 // The operation will result in an overflow exception, so do not canonicalize.
             }
-        } else if (y().isConstant()) {
-            long c = y().asConstant().asLong();
+        } else if (forY.isConstant()) {
+            long c = forY.asConstant().asLong();
             if (c == 1) {
-                return x();
+                return forX;
             }
             if (c == 0) {
-                return ConstantNode.forIntegerStamp(stamp(), 0, graph());
+                return ConstantNode.forIntegerStamp(stamp(), 0);
             }
         }
         return this;
@@ -75,7 +74,7 @@
 
     @Override
     public IntegerExactArithmeticSplitNode createSplit(BeginNode next, BeginNode deopt) {
-        return graph().add(new IntegerMulExactSplitNode(stamp(), x(), y(), next, deopt));
+        return graph().add(new IntegerMulExactSplitNode(stamp(), getX(), getY(), next, deopt));
     }
 
     @Override
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulHighNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulHighNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -22,10 +22,13 @@
  */
 package com.oracle.graal.truffle.nodes.arithmetic;
 
+import java.util.function.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
@@ -56,10 +59,13 @@
         }
     }
 
-    @Override
-    public boolean inferStamp() {
-        IntegerStamp xStamp = (IntegerStamp) x().stamp();
-        IntegerStamp yStamp = (IntegerStamp) y().stamp();
+    /**
+     * Determines the minimum and maximum result of this node for the given inputs and returns the
+     * result of the given BiFunction on the minimum and maximum values.
+     */
+    private <T> T processExtremes(ValueNode forX, ValueNode forY, BiFunction<Long, Long, T> op) {
+        IntegerStamp xStamp = (IntegerStamp) forX.stamp();
+        IntegerStamp yStamp = (IntegerStamp) forY.stamp();
 
         Kind kind = getKind();
         assert kind == Kind.Int || kind == Kind.Long;
@@ -74,13 +80,24 @@
                 max = Math.max(max, result);
             }
         }
-        return updateStamp(StampFactory.forInteger(getKind(), min, max));
+        return op.apply(min, max);
+    }
+
+    @Override
+    public boolean inferStamp() {
+        return updateStamp(processExtremes(getX(), getY(), (min, max) -> StampFactory.forInteger(getKind(), min, max)));
+    }
+
+    @SuppressWarnings("cast")
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        return processExtremes(forX, forY, (min, max) -> min == (long) max ? ConstantNode.forIntegerKind(getKind(), min) : this);
     }
 
     @Override
     public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
-        Value a = builder.operand(x());
-        Value b = builder.operand(y());
+        Value a = builder.operand(getX());
+        Value b = builder.operand(getY());
         builder.setResult(this, gen.emitMulHigh(a, b));
     }
 
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -24,39 +24,39 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.util.*;
 import com.oracle.truffle.api.*;
 
 /**
  * Node representing an exact integer substraction that will throw an {@link ArithmeticException} in
  * case the addition would overflow the 32 bit range.
  */
-public class IntegerSubExactNode extends IntegerSubNode implements Canonicalizable, IntegerExactArithmeticNode {
+public class IntegerSubExactNode extends IntegerSubNode implements IntegerExactArithmeticNode {
 
     public IntegerSubExactNode(ValueNode x, ValueNode y) {
-        super(StampTool.sub(x.stamp(), y.stamp()), x, y);
+        super(x, y);
         assert x.stamp().isCompatible(y.stamp()) && x.stamp() instanceof IntegerStamp;
     }
 
     @Override
     public boolean inferStamp() {
-        // TODO Should probably use a specialised version which understands that it can't overflow
-        return updateStamp(StampTool.sub(x().stamp(), y().stamp()));
+        // TODO Should probably use a specialized version which understands that it can't overflow
+        return updateStamp(StampTool.sub(getX().stamp(), getY().stamp()));
     }
 
     @Override
-    public Node canonical(CanonicalizerTool tool) {
-        if (x() == y()) {
-            return ConstantNode.forIntegerStamp(stamp(), 0, graph());
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
+            return ConstantNode.forIntegerStamp(stamp(), 0);
         }
-        if (x().isConstant() && y().isConstant()) {
-            Constant xConst = x().asConstant();
-            Constant yConst = y().asConstant();
+        if (forX.isConstant() && forY.isConstant()) {
+            Constant xConst = forX.asConstant();
+            Constant yConst = forY.asConstant();
             assert xConst.getKind() == yConst.getKind();
             try {
                 if (xConst.getKind() == Kind.Int) {
@@ -68,10 +68,10 @@
             } catch (ArithmeticException ex) {
                 // The operation will result in an overflow exception, so do not canonicalize.
             }
-        } else if (y().isConstant()) {
-            long c = y().asConstant().asLong();
+        } else if (forY.isConstant()) {
+            long c = forY.asConstant().asLong();
             if (c == 0) {
-                return x();
+                return forX;
             }
         }
         return this;
@@ -79,7 +79,7 @@
 
     @Override
     public IntegerExactArithmeticSplitNode createSplit(BeginNode next, BeginNode deopt) {
-        return graph().add(new IntegerSubExactSplitNode(stamp(), x(), y(), next, deopt));
+        return graph().add(new IntegerSubExactSplitNode(stamp(), getX(), getY(), next, deopt));
     }
 
     @Override
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/UnsignedMulHighNode.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/UnsignedMulHighNode.java	Wed Jun 25 17:34:25 2014 +0200
@@ -22,10 +22,13 @@
  */
 package com.oracle.graal.truffle.nodes.arithmetic;
 
+import java.util.function.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
@@ -56,10 +59,49 @@
         }
     }
 
+    /**
+     * Determines the minimum and maximum result of this node for the given inputs and returns the
+     * result of the given BiFunction on the minimum and maximum values. Note that the minima and
+     * maxima are calculated using signed min/max functions, while the values themselves are
+     * unsigned.
+     */
+    private <T> T processExtremes(ValueNode forX, ValueNode forY, BiFunction<Long, Long, T> op) {
+        IntegerStamp xStamp = (IntegerStamp) forX.stamp();
+        IntegerStamp yStamp = (IntegerStamp) forY.stamp();
+
+        Kind kind = getKind();
+        assert kind == Kind.Int || kind == Kind.Long;
+        long[] xExtremes = {xStamp.lowerBound(), xStamp.upperBound()};
+        long[] yExtremes = {yStamp.lowerBound(), yStamp.upperBound()};
+        long min = Long.MAX_VALUE;
+        long max = Long.MIN_VALUE;
+        for (long a : xExtremes) {
+            for (long b : yExtremes) {
+                long result = kind == Kind.Int ? ExactMath.multiplyHighUnsigned((int) a, (int) b) : ExactMath.multiplyHighUnsigned(a, b);
+                min = Math.min(min, result);
+                max = Math.max(max, result);
+            }
+        }
+        return op.apply(min, max);
+    }
+
+    @SuppressWarnings("cast")
+    @Override
+    public boolean inferStamp() {
+        // if min is negative, then the value can reach into the unsigned range
+        return updateStamp(processExtremes(getX(), getY(), (min, max) -> (min == (long) max || min >= 0) ? StampFactory.forInteger(getKind(), min, max) : StampFactory.forKind(getKind())));
+    }
+
+    @SuppressWarnings("cast")
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        return processExtremes(forX, forY, (min, max) -> min == (long) max ? ConstantNode.forIntegerKind(getKind(), min) : this);
+    }
+
     @Override
     public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
-        Value a = builder.operand(x());
-        Value b = builder.operand(y());
+        Value a = builder.operand(getX());
+        Value b = builder.operand(getY());
         builder.setResult(this, gen.emitUMulHigh(a, b));
     }
 
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Wed Jun 25 17:34:25 2014 +0200
@@ -134,9 +134,9 @@
      * Fold constant field reads, e.g. enum constants.
      */
     protected void rewriteLoadField(StructuredGraph graph, LoadFieldNode node) {
-        ConstantNode constant = node.asConstant(metaAccess);
+        ConstantNode constant = node.asConstant(metaAccess, node.object());
         if (constant != null) {
-            node.replaceAtUsages(constant);
+            node.replaceAtUsages(graph.unique(constant));
             graph.removeFixed(node);
         }
     }
@@ -199,7 +199,7 @@
                 ValueNode left = arguments.get(0);
                 ValueNode right = operation.rightOperandIsInt() ? toUnsigned(graph, arguments.get(1), Kind.Int) : fromSigned(graph, arguments.get(1));
 
-                ValueNode replacement = graph.addOrUnique(createBinaryNodeInstance(operation.node(), wordKind, left, right));
+                ValueNode replacement = graph.addOrUnique(createBinaryNodeInstance(operation.node(), left, right));
                 if (replacement instanceof FixedWithNextNode) {
                     graph.addBeforeFixed(invoke.asNode(), (FixedWithNextNode) replacement);
                 }
@@ -213,7 +213,7 @@
 
             case NOT:
                 assert arguments.size() == 1;
-                replace(invoke, graph.unique(new XorNode(StampFactory.forKind(wordKind), arguments.get(0), ConstantNode.forIntegerKind(wordKind, -1, graph))));
+                replace(invoke, graph.unique(new XorNode(arguments.get(0), ConstantNode.forIntegerKind(wordKind, -1, graph))));
                 break;
 
             case READ_POINTER:
@@ -333,10 +333,10 @@
      * called for all Word operations which are annotated with @Operation(node = ...) and
      * encapsulates the reflective allocation of the node.
      */
-    private static ValueNode createBinaryNodeInstance(Class<? extends ValueNode> nodeClass, Kind kind, ValueNode left, ValueNode right) {
+    private static ValueNode createBinaryNodeInstance(Class<? extends ValueNode> nodeClass, ValueNode left, ValueNode right) {
         try {
-            Constructor<? extends ValueNode> constructor = nodeClass.getConstructor(Stamp.class, ValueNode.class, ValueNode.class);
-            return constructor.newInstance(StampFactory.forKind(kind), left, right);
+            Constructor<? extends ValueNode> constructor = nodeClass.getConstructor(ValueNode.class, ValueNode.class);
+            return constructor.newInstance(left, right);
         } catch (Throwable ex) {
             throw new GraalInternalError(ex).addContext(nodeClass.getName());
         }
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java	Wed Jun 25 16:57:12 2014 +0200
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java	Wed Jun 25 17:34:25 2014 +0200
@@ -86,8 +86,8 @@
                     MethodCallTargetNode callTarget = (MethodCallTargetNode) usage;
                     verifyInvoke(node, callTarget);
                 } else if (usage instanceof ObjectEqualsNode) {
-                    verify(!isWord(node) || ((ObjectEqualsNode) usage).x() != node, node, usage, "cannot use word type in comparison");
-                    verify(!isWord(node) || ((ObjectEqualsNode) usage).y() != node, node, usage, "cannot use word type in comparison");
+                    verify(!isWord(node) || ((ObjectEqualsNode) usage).getX() != node, node, usage, "cannot use word type in comparison");
+                    verify(!isWord(node) || ((ObjectEqualsNode) usage).getY() != node, node, usage, "cannot use word type in comparison");
                 } else if (usage instanceof ArrayLengthNode) {
                     verify(!isWord(node) || ((ArrayLengthNode) usage).array() != node, node, usage, "cannot get array length from word value");
                 } else if (usage instanceof ValuePhiNode) {