changeset 17418:393fe459eadc

Don't cache op field in arithmetic nodes.
author Roland Schatz <roland.schatz@oracle.com>
date Mon, 13 Oct 2014 15:36:11 +0200
parents 2915eff532d4
children 83c3dd41ca64
files graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AddNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryArithmeticNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/DivNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/MulNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RemNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SubNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnaryArithmeticNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java
diffstat 20 files changed, 96 insertions(+), 105 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java	Mon Oct 13 15:26:02 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java	Mon Oct 13 15:36:11 2014 +0200
@@ -138,7 +138,7 @@
         InvariantPredicate invariant = new InvariantPredicate();
         StructuredGraph graph = loopBegin().graph();
         for (BinaryArithmeticNode binary : whole().nodes().filter(BinaryArithmeticNode.class)) {
-            if (!binary.getOp().isAssociative()) {
+            if (!binary.isAssociative()) {
                 continue;
             }
             BinaryArithmeticNode result = BinaryArithmeticNode.reassociate(binary, invariant, binary.getX(), binary.getY());
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AddNode.java	Mon Oct 13 15:26:02 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AddNode.java	Mon Oct 13 15:36:11 2014 +0200
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodeinfo.*;
@@ -38,7 +39,7 @@
     }
 
     protected AddNode(ValueNode x, ValueNode y) {
-        super(ArithmeticOpTable.forStamp(x.stamp()).getAdd(), x, y);
+        super(ArithmeticOpTable::getAdd, x, y);
     }
 
     @Override
@@ -51,7 +52,8 @@
         if (forX.isConstant() && !forY.isConstant()) {
             return AddNode.create(forY, forX);
         }
-        boolean associative = getOp().isAssociative();
+        BinaryOp op = getOp(forX, forY);
+        boolean associative = op.isAssociative();
         if (associative) {
             if (forX instanceof SubNode) {
                 SubNode sub = (SubNode) forX;
@@ -70,7 +72,7 @@
         }
         if (forY.isConstant()) {
             Constant c = forY.asConstant();
-            if (getOp().isNeutral(c)) {
+            if (op.isNeutral(c)) {
                 return forX;
             }
             if (associative) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Mon Oct 13 15:26:02 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Mon Oct 13 15:36:11 2014 +0200
@@ -40,7 +40,7 @@
     }
 
     protected AndNode(ValueNode x, ValueNode y) {
-        super(ArithmeticOpTable.forStamp(x.stamp()).getAnd(), x, y);
+        super(ArithmeticOpTable::getAnd, x, y);
     }
 
     @Override
@@ -58,7 +58,7 @@
         }
         if (forY.isConstant()) {
             Constant c = forY.asConstant();
-            if (getOp().isNeutral(c)) {
+            if (getOp(forX, forY).isNeutral(c)) {
                 return forX;
             }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryArithmeticNode.java	Mon Oct 13 15:26:02 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryArithmeticNode.java	Mon Oct 13 15:36:11 2014 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import java.util.function.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.type.*;
@@ -36,27 +38,33 @@
 @NodeInfo
 public abstract class BinaryArithmeticNode extends BinaryNode implements ArithmeticLIRLowerable {
 
-    protected BinaryOp op;
+    protected final Function<ArithmeticOpTable, BinaryOp> getOp;
 
-    public BinaryArithmeticNode(BinaryOp op, ValueNode x, ValueNode y) {
-        super(op.foldStamp(x.stamp(), y.stamp()), x, y);
-        this.op = op;
+    public BinaryArithmeticNode(Function<ArithmeticOpTable, BinaryOp> getOp, ValueNode x, ValueNode y) {
+        super(getOp.apply(ArithmeticOpTable.forStamp(x.stamp())).foldStamp(x.stamp(), y.stamp()), x, y);
+        this.getOp = getOp;
     }
 
-    public BinaryOp getOp() {
-        return op;
+    protected final BinaryOp getOp(ValueNode forX, ValueNode forY) {
+        ArithmeticOpTable table = ArithmeticOpTable.forStamp(forX.stamp());
+        assert table == ArithmeticOpTable.forStamp(forY.stamp());
+        return getOp.apply(table);
+    }
+
+    public boolean isAssociative() {
+        return getOp(getX(), getY()).isAssociative();
     }
 
     @Override
     public Constant evalConst(Constant... inputs) {
         assert inputs.length == 2;
-        return op.foldConstant(inputs[0], inputs[1]);
+        return getOp(getX(), getY()).foldConstant(inputs[0], inputs[1]);
     }
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
         if (forX.isConstant() && forY.isConstant()) {
-            Constant ret = op.foldConstant(forX.asConstant(), forY.asConstant());
+            Constant ret = getOp(forX, forY).foldConstant(forX.asConstant(), forY.asConstant());
             return ConstantNode.forPrimitive(stamp(), ret);
         }
         return this;
@@ -64,10 +72,7 @@
 
     @Override
     public boolean inferStamp() {
-        ArithmeticOpTable ops = ArithmeticOpTable.forStamp(getX().stamp());
-        assert ops == ArithmeticOpTable.forStamp(getY().stamp());
-        op = ops.getBinaryOp(op);
-        return updateStamp(op.foldStamp(getX().stamp(), getY().stamp()));
+        return updateStamp(getOp(getX(), getY()).foldStamp(getX().stamp(), getY().stamp()));
     }
 
     public static AddNode add(StructuredGraph graph, ValueNode v1, ValueNode v2) {
@@ -160,7 +165,7 @@
      * @param forX
      */
     public static BinaryArithmeticNode reassociate(BinaryArithmeticNode node, NodePredicate criterion, ValueNode forX, ValueNode forY) {
-        assert node.getOp().isAssociative();
+        assert node.getOp(forX, forY).isAssociative();
         ReassociateMatch match1 = findReassociate(node, criterion);
         if (match1 == null) {
             return node;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/DivNode.java	Mon Oct 13 15:26:02 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/DivNode.java	Mon Oct 13 15:36:11 2014 +0200
@@ -39,7 +39,7 @@
     }
 
     protected DivNode(ValueNode x, ValueNode y) {
-        super(ArithmeticOpTable.forStamp(x.stamp()).getDiv(), x, y);
+        super(ArithmeticOpTable::getDiv, x, y);
     }
 
     @Override
@@ -51,7 +51,7 @@
 
         if (forY.isConstant()) {
             Constant c = forY.asConstant();
-            if (getOp().isNeutral(c)) {
+            if (getOp(forX, forY).isNeutral(c)) {
                 return forX;
             }
             if (c.getKind().isNumericInteger()) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java	Mon Oct 13 15:26:02 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java	Mon Oct 13 15:36:11 2014 +0200
@@ -39,34 +39,30 @@
 @NodeInfo
 public class FloatConvertNode extends UnaryArithmeticNode implements ConvertNode, Lowerable, ArithmeticLIRLowerable {
 
-    protected FloatConvertOp reverseOp;
+    protected final FloatConvert op;
 
     public static FloatConvertNode create(FloatConvert op, ValueNode input) {
         return USE_GENERATED_NODES ? new FloatConvertNodeGen(op, input) : new FloatConvertNode(op, input);
     }
 
-    private FloatConvertNode(ArithmeticOpTable table, FloatConvert op, ValueNode input) {
-        super(table.getFloatConvert(op), input);
-        ArithmeticOpTable revTable = ArithmeticOpTable.forStamp(stamp());
-        reverseOp = revTable.getFloatConvert(op.reverse());
-    }
-
     protected FloatConvertNode(FloatConvert op, ValueNode input) {
-        this(ArithmeticOpTable.forStamp(input.stamp()), op, input);
+        super(table -> table.getFloatConvert(op), input);
+        this.op = op;
     }
 
     public FloatConvert getFloatConvert() {
-        return ((FloatConvertOp) getOp()).getFloatConvert();
+        return op;
     }
 
     @Override
     public Constant convert(Constant c) {
-        return op.foldConstant(c);
+        return getOp(getValue()).foldConstant(c);
     }
 
     @Override
     public Constant reverse(Constant c) {
-        return reverseOp.foldConstant(c);
+        FloatConvertOp reverse = ArithmeticOpTable.forStamp(stamp()).getFloatConvert(op.reverse());
+        return reverse.foldConstant(c);
     }
 
     @Override
@@ -89,22 +85,13 @@
 
         if (forValue instanceof FloatConvertNode) {
             FloatConvertNode other = (FloatConvertNode) forValue;
-            if (other.isLossless() && other.op == this.reverseOp) {
+            if (other.isLossless() && other.op == this.op.reverse()) {
                 return other.getValue();
             }
         }
         return this;
     }
 
-    @Override
-    public boolean inferStamp() {
-        boolean changed = super.inferStamp();
-        if (changed) {
-            reverseOp = ArithmeticOpTable.forStamp(stamp()).getFloatConvertOp(reverseOp);
-        }
-        return changed;
-    }
-
     public void lower(LoweringTool tool) {
         tool.getLowerer().lower(this, tool);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java	Mon Oct 13 15:26:02 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java	Mon Oct 13 15:36:11 2014 +0200
@@ -22,9 +22,11 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import java.util.function.*;
+
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.compiler.common.type.ArithmeticOpTable.IntegerConvertOp;
-import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
@@ -36,15 +38,15 @@
 @NodeInfo
 public abstract class IntegerConvertNode extends UnaryNode implements ConvertNode, ArithmeticLIRLowerable {
 
-    protected IntegerConvertOp op;
-    protected IntegerConvertOp reverseOp;
+    protected final Function<ArithmeticOpTable, IntegerConvertOp> getOp;
+    protected final Function<ArithmeticOpTable, IntegerConvertOp> getReverseOp;
 
     protected final int resultBits;
 
-    protected IntegerConvertNode(IntegerConvertOp op, IntegerConvertOp reverseOp, int resultBits, ValueNode input) {
-        super(op.foldStamp(resultBits, input.stamp()), input);
-        this.op = op;
-        this.reverseOp = reverseOp;
+    protected IntegerConvertNode(Function<ArithmeticOpTable, IntegerConvertOp> getOp, Function<ArithmeticOpTable, IntegerConvertOp> getReverseOp, int resultBits, ValueNode input) {
+        super(getOp.apply(ArithmeticOpTable.forStamp(input.stamp())).foldStamp(resultBits, input.stamp()), input);
+        this.getOp = getOp;
+        this.getReverseOp = getReverseOp;
         this.resultBits = resultBits;
     }
 
@@ -60,24 +62,24 @@
         }
     }
 
+    protected final IntegerConvertOp getOp(ValueNode forValue) {
+        return getOp.apply(ArithmeticOpTable.forStamp(forValue.stamp()));
+    }
+
     @Override
     public Constant convert(Constant c) {
-        return op.foldConstant(getInputBits(), getResultBits(), c);
+        return getOp(getValue()).foldConstant(getInputBits(), getResultBits(), c);
     }
 
     @Override
     public Constant reverse(Constant c) {
-        return reverseOp.foldConstant(getResultBits(), getInputBits(), c);
+        IntegerConvertOp reverse = getReverseOp.apply(ArithmeticOpTable.forStamp(stamp()));
+        return reverse.foldConstant(getResultBits(), getInputBits(), c);
     }
 
     @Override
     public boolean inferStamp() {
-        op = ArithmeticOpTable.forStamp(getValue().stamp()).getIntegerConvertOp(op);
-        boolean changed = updateStamp(op.foldStamp(resultBits, getValue().stamp()));
-        if (changed) {
-            reverseOp = ArithmeticOpTable.forStamp(stamp()).getIntegerConvertOp(reverseOp);
-        }
-        return changed;
+        return updateStamp(getOp(getValue()).foldStamp(resultBits, getValue().stamp()));
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/MulNode.java	Mon Oct 13 15:26:02 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/MulNode.java	Mon Oct 13 15:36:11 2014 +0200
@@ -25,6 +25,7 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodeinfo.*;
@@ -39,7 +40,7 @@
     }
 
     protected MulNode(ValueNode x, ValueNode y) {
-        super(ArithmeticOpTable.forStamp(x.stamp()).getMul(), x, y);
+        super(ArithmeticOpTable::getMul, x, y);
     }
 
     @Override
@@ -53,8 +54,9 @@
             return MulNode.create(forY, forX);
         }
         if (forY.isConstant()) {
+            BinaryOp op = getOp(forX, forY);
             Constant c = forY.asConstant();
-            if (getOp().isNeutral(c)) {
+            if (op.isNeutral(c)) {
                 return forX;
             }
 
@@ -90,7 +92,7 @@
                 }
             }
 
-            if (getOp().isAssociative()) {
+            if (op.isAssociative()) {
                 // canonicalize expressions like "(a * 1) * 2"
                 return reassociate(this, ValueNode.isConstantPredicate(), forX, forY);
             }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java	Mon Oct 13 15:26:02 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java	Mon Oct 13 15:36:11 2014 +0200
@@ -39,12 +39,8 @@
         return USE_GENERATED_NODES ? new NarrowNodeGen(input, resultBits) : new NarrowNode(input, resultBits);
     }
 
-    private NarrowNode(ArithmeticOpTable ops, ValueNode input, int resultBits) {
-        super(ops.getNarrow(), ops.getSignExtend(), resultBits, input);
-    }
-
     protected NarrowNode(ValueNode input, int resultBits) {
-        this(ArithmeticOpTable.forStamp(input.stamp()), input, resultBits);
+        super(ArithmeticOpTable::getNarrow, ArithmeticOpTable::getSignExtend, resultBits, input);
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java	Mon Oct 13 15:26:02 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java	Mon Oct 13 15:36:11 2014 +0200
@@ -45,7 +45,7 @@
     }
 
     protected NegateNode(ValueNode value) {
-        super(ArithmeticOpTable.forStamp(value.stamp()).getNeg(), value);
+        super(ArithmeticOpTable::getNeg, value);
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java	Mon Oct 13 15:26:02 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java	Mon Oct 13 15:36:11 2014 +0200
@@ -45,7 +45,7 @@
     }
 
     protected NotNode(ValueNode x) {
-        super(ArithmeticOpTable.forStamp(x.stamp()).getNot(), x);
+        super(ArithmeticOpTable::getNot, x);
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Mon Oct 13 15:26:02 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Mon Oct 13 15:36:11 2014 +0200
@@ -40,7 +40,7 @@
     }
 
     protected OrNode(ValueNode x, ValueNode y) {
-        super(ArithmeticOpTable.forStamp(x.stamp()).getOr(), x, y);
+        super(ArithmeticOpTable::getOr, x, y);
     }
 
     @Override
@@ -58,7 +58,7 @@
         }
         if (forY.isConstant()) {
             Constant c = forY.asConstant();
-            if (getOp().isNeutral(c)) {
+            if (getOp(forX, forY).isNeutral(c)) {
                 return forX;
             }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RemNode.java	Mon Oct 13 15:26:02 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RemNode.java	Mon Oct 13 15:36:11 2014 +0200
@@ -36,7 +36,7 @@
     }
 
     protected RemNode(ValueNode x, ValueNode y) {
-        super(ArithmeticOpTable.forStamp(x.stamp()).getRem(), x, y);
+        super(ArithmeticOpTable::getRem, x, y);
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java	Mon Oct 13 15:26:02 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java	Mon Oct 13 15:36:11 2014 +0200
@@ -39,12 +39,8 @@
         return USE_GENERATED_NODES ? new SignExtendNodeGen(input, resultBits) : new SignExtendNode(input, resultBits);
     }
 
-    private SignExtendNode(ArithmeticOpTable ops, ValueNode input, int resultBits) {
-        super(ops.getSignExtend(), ops.getNarrow(), resultBits, input);
-    }
-
     protected SignExtendNode(ValueNode input, int resultBits) {
-        this(ArithmeticOpTable.forStamp(input.stamp()), input, resultBits);
+        super(ArithmeticOpTable::getSignExtend, ArithmeticOpTable::getNarrow, resultBits, input);
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SubNode.java	Mon Oct 13 15:26:02 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SubNode.java	Mon Oct 13 15:36:11 2014 +0200
@@ -24,6 +24,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodeinfo.*;
@@ -39,7 +40,7 @@
     }
 
     protected SubNode(ValueNode x, ValueNode y) {
-        super(ArithmeticOpTable.forStamp(x.stamp()).getSub(), x, y);
+        super(ArithmeticOpTable::getSub, x, y);
     }
 
     @SuppressWarnings("hiding")
@@ -50,13 +51,14 @@
             return ret;
         }
 
+        BinaryOp op = getOp(forX, forY);
         if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
-            Constant zero = getOp().getZero(forX.stamp());
+            Constant zero = op.getZero(forX.stamp());
             if (zero != null) {
                 return ConstantNode.forPrimitive(stamp(), zero);
             }
         }
-        boolean associative = getOp().isAssociative();
+        boolean associative = op.isAssociative();
         if (associative) {
             if (forX instanceof AddNode) {
                 AddNode x = (AddNode) forX;
@@ -95,7 +97,7 @@
         }
         if (forY.isConstant()) {
             Constant c = forY.asConstant();
-            if (getOp().isNeutral(c)) {
+            if (op.isNeutral(c)) {
                 return forX;
             }
             if (associative) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnaryArithmeticNode.java	Mon Oct 13 15:26:02 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnaryArithmeticNode.java	Mon Oct 13 15:36:11 2014 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.nodes.calc;
 
+import java.util.function.*;
+
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp;
@@ -33,32 +35,31 @@
 @NodeInfo
 public abstract class UnaryArithmeticNode extends UnaryNode implements ArithmeticLIRLowerable {
 
-    protected UnaryOp op;
+    protected final Function<ArithmeticOpTable, UnaryOp> getOp;
 
-    protected UnaryArithmeticNode(UnaryOp op, ValueNode value) {
-        super(op.foldStamp(value.stamp()), value);
-        this.op = op;
+    protected UnaryArithmeticNode(Function<ArithmeticOpTable, UnaryOp> getOp, ValueNode value) {
+        super(getOp.apply(ArithmeticOpTable.forStamp(value.stamp())).foldStamp(value.stamp()), value);
+        this.getOp = getOp;
     }
 
-    public UnaryOp getOp() {
-        return op;
+    protected final UnaryOp getOp(ValueNode forValue) {
+        return getOp.apply(ArithmeticOpTable.forStamp(forValue.stamp()));
     }
 
     public Constant evalConst(Constant... inputs) {
         assert inputs.length == 1;
-        return op.foldConstant(inputs[0]);
+        return getOp(getValue()).foldConstant(inputs[0]);
     }
 
     @Override
     public boolean inferStamp() {
-        op = ArithmeticOpTable.forStamp(getValue().stamp()).getUnaryOp(op);
-        return updateStamp(op.foldStamp(getValue().stamp()));
+        return updateStamp(getOp(getValue()).foldStamp(getValue().stamp()));
     }
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
         if (forValue.isConstant()) {
-            return ConstantNode.forPrimitive(stamp(), op.foldConstant(forValue.asConstant()));
+            return ConstantNode.forPrimitive(stamp(), getOp(forValue).foldConstant(forValue.asConstant()));
         }
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Mon Oct 13 15:26:02 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Mon Oct 13 15:36:11 2014 +0200
@@ -40,7 +40,7 @@
     }
 
     protected XorNode(ValueNode x, ValueNode y) {
-        super(ArithmeticOpTable.forStamp(x.stamp()).getXor(), x, y);
+        super(ArithmeticOpTable::getXor, x, y);
         assert x.stamp().isCompatible(y.stamp());
     }
 
@@ -52,14 +52,14 @@
         }
 
         if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
-            return ConstantNode.forPrimitive(stamp(), getOp().getZero(forX.stamp()));
+            return ConstantNode.forPrimitive(stamp(), getOp(forX, forY).getZero(forX.stamp()));
         }
         if (forX.isConstant() && !forY.isConstant()) {
             return XorNode.create(forY, forX);
         }
         if (forY.isConstant()) {
             Constant c = forY.asConstant();
-            if (getOp().isNeutral(c)) {
+            if (getOp(forX, forY).isNeutral(c)) {
                 return forX;
             }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java	Mon Oct 13 15:26:02 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java	Mon Oct 13 15:36:11 2014 +0200
@@ -41,12 +41,8 @@
         return USE_GENERATED_NODES ? new ZeroExtendNodeGen(input, resultBits) : new ZeroExtendNode(input, resultBits);
     }
 
-    private ZeroExtendNode(ArithmeticOpTable ops, ValueNode input, int resultBits) {
-        super(ops.getZeroExtend(), ops.getNarrow(), resultBits, input);
-    }
-
     protected ZeroExtendNode(ValueNode input, int resultBits) {
-        this(ArithmeticOpTable.forStamp(input.stamp()), input, resultBits);
+        super(ArithmeticOpTable::getZeroExtend, ArithmeticOpTable::getNarrow, resultBits, input);
     }
 
     @Override
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java	Mon Oct 13 15:26:02 2014 +0200
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java	Mon Oct 13 15:36:11 2014 +0200
@@ -182,10 +182,10 @@
 
             Arguments args = new Arguments(key, graph.getGuardsStage(), tool.getLoweringStage());
             args.add("input", convert.getValue());
-            args.add("result", graph.unique(AMD64FloatConvertNode.create(convert.getOp(), convert.getValue())));
+            args.add("result", graph.unique(AMD64FloatConvertNode.create(convert.getFloatConvert(), convert.getValue())));
 
             SnippetTemplate template = template(args);
-            Debug.log("Lowering %s in %s: node=%s, template=%s, arguments=%s", convert.getOp(), graph, convert, template, args);
+            Debug.log("Lowering %s in %s: node=%s, template=%s, arguments=%s", convert.getFloatConvert(), graph, convert, template, args);
             template.instantiate(providers.getMetaAccess(), convert, DEFAULT_REPLACER, tool, args);
             graph.removeFloating(convert);
         }
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java	Mon Oct 13 15:26:02 2014 +0200
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java	Mon Oct 13 15:36:11 2014 +0200
@@ -24,8 +24,7 @@
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
-import com.oracle.graal.compiler.common.type.ArithmeticOpTable.FloatConvertOp;
-import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp;
+import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodeinfo.*;
@@ -41,12 +40,15 @@
 @NodeInfo
 public class AMD64FloatConvertNode extends UnaryArithmeticNode implements ArithmeticLIRLowerable {
 
-    public static AMD64FloatConvertNode create(UnaryOp op, ValueNode value) {
+    protected final FloatConvert op;
+
+    public static AMD64FloatConvertNode create(FloatConvert op, ValueNode value) {
         return USE_GENERATED_NODES ? new AMD64FloatConvertNodeGen(op, value) : new AMD64FloatConvertNode(op, value);
     }
 
-    protected AMD64FloatConvertNode(UnaryOp op, ValueNode value) {
-        super(op, value);
+    protected AMD64FloatConvertNode(FloatConvert op, ValueNode value) {
+        super(table -> table.getFloatConvert(op), value);
+        this.op = op;
     }
 
     @Override
@@ -62,6 +64,6 @@
     }
 
     public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
-        builder.setResult(this, gen.emitFloatConvert(((FloatConvertOp) getOp()).getFloatConvert(), builder.operand(getValue())));
+        builder.setResult(this, gen.emitFloatConvert(op, builder.operand(getValue())));
     }
 }