changeset 17419:83c3dd41ca64

Simplify ArithmeticOpTable implementation and make it type safe.
author Roland Schatz <roland.schatz@oracle.com>
date Mon, 13 Oct 2014 16:50:01 +0200
parents 393fe459eadc
children e98150919577
files graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ArithmeticOpTable.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java graal/com.oracle.graal.loop/src/com/oracle/graal/loop/BasicInductionVariable.java graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedOffsetInductionVariable.java graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariables.java graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.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/AMD64FloatConvertNode.java
diffstat 27 files changed, 285 insertions(+), 290 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ArithmeticOpTable.java	Mon Oct 13 15:36:11 2014 +0200
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ArithmeticOpTable.java	Mon Oct 13 16:50:01 2014 +0200
@@ -22,35 +22,47 @@
  */
 package com.oracle.graal.compiler.common.type;
 
-import static com.oracle.graal.compiler.common.type.ArithmeticOpTable.IntegerConvertOp.*;
-
+import java.util.*;
+import java.util.function.*;
 import java.util.stream.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp.Add;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp.And;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp.Div;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp.Mul;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp.Or;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp.Rem;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp.Sub;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp.Xor;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.IntegerConvertOp.Narrow;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.IntegerConvertOp.SignExtend;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.IntegerConvertOp.ZeroExtend;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp.Neg;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp.Not;
 
 /**
  * Information about arithmetic operations.
  */
 public final class ArithmeticOpTable {
 
-    private final UnaryOp neg;
-    private final BinaryOp add;
-    private final BinaryOp sub;
+    private final UnaryOp<Neg> neg;
+    private final BinaryOp<Add> add;
+    private final BinaryOp<Sub> sub;
 
-    private final BinaryOp mul;
-    private final BinaryOp div;
-    private final BinaryOp rem;
+    private final BinaryOp<Mul> mul;
+    private final BinaryOp<Div> div;
+    private final BinaryOp<Rem> rem;
 
-    private final UnaryOp not;
-    private final BinaryOp and;
-    private final BinaryOp or;
-    private final BinaryOp xor;
+    private final UnaryOp<Not> not;
+    private final BinaryOp<And> and;
+    private final BinaryOp<Or> or;
+    private final BinaryOp<Xor> xor;
 
-    private final IntegerConvertOp zeroExtend;
-    private final IntegerConvertOp signExtend;
-    private final IntegerConvertOp narrow;
+    private final IntegerConvertOp<ZeroExtend> zeroExtend;
+    private final IntegerConvertOp<SignExtend> signExtend;
+    private final IntegerConvertOp<Narrow> narrow;
 
     private final FloatConvertOp[] floatConvert;
 
@@ -62,120 +74,57 @@
         }
     }
 
-    public static final ArithmeticOpTable EMPTY = create();
+    public static final ArithmeticOpTable EMPTY = new ArithmeticOpTable(null, null, null, null, null, null, null, null, null, null, null, null, null);
 
-    public static ArithmeticOpTable create(Op... ops) {
-        UnaryOp neg = null;
-        BinaryOp add = null;
-        BinaryOp sub = null;
+    public ArithmeticOpTable(UnaryOp<Neg> neg, BinaryOp<Add> add, BinaryOp<Sub> sub, BinaryOp<Mul> mul, BinaryOp<Div> div, BinaryOp<Rem> rem, UnaryOp<Not> not, BinaryOp<And> and, BinaryOp<Or> or,
+                    BinaryOp<Xor> xor, IntegerConvertOp<ZeroExtend> zeroExtend, IntegerConvertOp<SignExtend> signExtend, IntegerConvertOp<Narrow> narrow, FloatConvertOp... floatConvert) {
+        this(neg, add, sub, mul, div, rem, not, and, or, xor, zeroExtend, signExtend, narrow, Stream.of(floatConvert));
+    }
 
-        BinaryOp mul = null;
-        BinaryOp div = null;
-        BinaryOp rem = null;
+    public interface ArithmeticOpWrapper {
 
-        UnaryOp not = null;
-        BinaryOp and = null;
-        BinaryOp or = null;
-        BinaryOp xor = null;
+        <OP> UnaryOp<OP> wrapUnaryOp(UnaryOp<OP> op);
+
+        <OP> BinaryOp<OP> wrapBinaryOp(BinaryOp<OP> op);
 
-        IntegerConvertOp zeroExtend = null;
-        IntegerConvertOp signExtend = null;
-        IntegerConvertOp narrow = null;
+        <OP> IntegerConvertOp<OP> wrapIntegerConvertOp(IntegerConvertOp<OP> op);
 
-        FloatConvertOp[] floatConvert = new FloatConvertOp[FloatConvert.values().length];
+        FloatConvertOp wrapFloatConvertOp(FloatConvertOp op);
+    }
 
-        for (Op op : ops) {
-            if (op instanceof BinaryOp) {
-                BinaryOp binary = (BinaryOp) op;
-                switch (binary.getOperator()) {
-                    case '+':
-                        assert add == null;
-                        add = binary;
-                        break;
-                    case '-':
-                        assert sub == null;
-                        sub = binary;
-                        break;
-                    case '*':
-                        assert mul == null;
-                        mul = binary;
-                        break;
-                    case '/':
-                        assert div == null;
-                        div = binary;
-                        break;
-                    case '%':
-                        assert rem == null;
-                        rem = binary;
-                        break;
-                    case '&':
-                        assert and == null;
-                        and = binary;
-                        break;
-                    case '|':
-                        assert or == null;
-                        or = binary;
-                        break;
-                    case '^':
-                        assert xor == null;
-                        xor = binary;
-                        break;
-                    default:
-                        throw GraalInternalError.shouldNotReachHere("unknown binary operator " + binary.getOperator());
-                }
-            } else if (op instanceof IntegerConvertOp) {
-                IntegerConvertOp convert = (IntegerConvertOp) op;
-                switch (convert.getOperator()) {
-                    case IntegerConvertOp.ZERO_EXTEND:
-                        assert zeroExtend == null;
-                        zeroExtend = convert;
-                        break;
-                    case IntegerConvertOp.SIGN_EXTEND:
-                        assert signExtend == null;
-                        signExtend = convert;
-                        break;
-                    case IntegerConvertOp.NARROW:
-                        assert narrow == null;
-                        narrow = convert;
-                        break;
-                    default:
-                        throw GraalInternalError.shouldNotReachHere("unknown integer conversion operator " + convert.getOperator());
-                }
-            } else if (op instanceof FloatConvertOp) {
-                FloatConvertOp convert = (FloatConvertOp) op;
-                int idx = convert.getFloatConvert().ordinal();
-                assert floatConvert[idx] == null;
-                floatConvert[idx] = convert;
-            } else if (op instanceof UnaryOp) {
-                UnaryOp unary = (UnaryOp) op;
-                switch (unary.getOperator()) {
-                    case '-':
-                        assert neg == null;
-                        neg = unary;
-                        break;
-                    case '~':
-                        assert not == null;
-                        not = unary;
-                        break;
-                    default:
-                        throw GraalInternalError.shouldNotReachHere("unknown unary operator " + unary.getOperator());
-                }
-            } else {
-                throw GraalInternalError.shouldNotReachHere("unknown Op subclass " + op);
-            }
+    private static <T> T wrapIfNonNull(Function<T, T> wrapper, T obj) {
+        if (obj == null) {
+            return null;
+        } else {
+            return wrapper.apply(obj);
         }
+    }
+
+    public static ArithmeticOpTable wrap(ArithmeticOpWrapper wrapper, ArithmeticOpTable inner) {
+        UnaryOp<Neg> neg = wrapIfNonNull(wrapper::wrapUnaryOp, inner.getNeg());
+        BinaryOp<Add> add = wrapIfNonNull(wrapper::wrapBinaryOp, inner.getAdd());
+        BinaryOp<Sub> sub = wrapIfNonNull(wrapper::wrapBinaryOp, inner.getSub());
+
+        BinaryOp<Mul> mul = wrapIfNonNull(wrapper::wrapBinaryOp, inner.getMul());
+        BinaryOp<Div> div = wrapIfNonNull(wrapper::wrapBinaryOp, inner.getDiv());
+        BinaryOp<Rem> rem = wrapIfNonNull(wrapper::wrapBinaryOp, inner.getRem());
+
+        UnaryOp<Not> not = wrapIfNonNull(wrapper::wrapUnaryOp, inner.getNot());
+        BinaryOp<And> and = wrapIfNonNull(wrapper::wrapBinaryOp, inner.getAnd());
+        BinaryOp<Or> or = wrapIfNonNull(wrapper::wrapBinaryOp, inner.getOr());
+        BinaryOp<Xor> xor = wrapIfNonNull(wrapper::wrapBinaryOp, inner.getXor());
+
+        IntegerConvertOp<ZeroExtend> zeroExtend = wrapIfNonNull(wrapper::wrapIntegerConvertOp, inner.getZeroExtend());
+        IntegerConvertOp<SignExtend> signExtend = wrapIfNonNull(wrapper::wrapIntegerConvertOp, inner.getSignExtend());
+        IntegerConvertOp<Narrow> narrow = wrapIfNonNull(wrapper::wrapIntegerConvertOp, inner.getNarrow());
+
+        Stream<FloatConvertOp> floatConvert = Stream.of(inner.floatConvert).filter(Objects::nonNull).map(wrapper::wrapFloatConvertOp);
 
         return new ArithmeticOpTable(neg, add, sub, mul, div, rem, not, and, or, xor, zeroExtend, signExtend, narrow, floatConvert);
     }
 
-    public Stream<Op> getAllOps() {
-        Stream<Op> ops = Stream.of(neg, add, sub, mul, div, rem, not, and, or, xor, zeroExtend, signExtend, narrow);
-        Stream<Op> floatOps = Stream.of(floatConvert);
-        return Stream.concat(ops, floatOps).filter(op -> op != null);
-    }
-
-    private ArithmeticOpTable(UnaryOp neg, BinaryOp add, BinaryOp sub, BinaryOp mul, BinaryOp div, BinaryOp rem, UnaryOp not, BinaryOp and, BinaryOp or, BinaryOp xor, IntegerConvertOp zeroExtend,
-                    IntegerConvertOp signExtend, IntegerConvertOp narrow, FloatConvertOp[] floatConvert) {
+    private ArithmeticOpTable(UnaryOp<Neg> neg, BinaryOp<Add> add, BinaryOp<Sub> sub, BinaryOp<Mul> mul, BinaryOp<Div> div, BinaryOp<Rem> rem, UnaryOp<Not> not, BinaryOp<And> and, BinaryOp<Or> or,
+                    BinaryOp<Xor> xor, IntegerConvertOp<ZeroExtend> zeroExtend, IntegerConvertOp<SignExtend> signExtend, IntegerConvertOp<Narrow> narrow, Stream<FloatConvertOp> floatConvert) {
         this.neg = neg;
         this.add = add;
         this.sub = sub;
@@ -189,170 +138,142 @@
         this.zeroExtend = zeroExtend;
         this.signExtend = signExtend;
         this.narrow = narrow;
-        this.floatConvert = floatConvert;
-    }
-
-    public UnaryOp getUnaryOp(UnaryOp op) {
-        switch (op.getOperator()) {
-            case '-':
-                return getNeg();
-            case '~':
-                return getNot();
-            default:
-                return getFloatConvertOp((FloatConvertOp) op);
-        }
-    }
-
-    public BinaryOp getBinaryOp(BinaryOp op) {
-        switch (op.getOperator()) {
-            case '+':
-                return getAdd();
-            case '-':
-                return getSub();
-            case '*':
-                return getMul();
-            case '/':
-                return getDiv();
-            case '%':
-                return getRem();
-            case '&':
-                return getAnd();
-            case '|':
-                return getOr();
-            case '^':
-                return getXor();
-            default:
-                throw GraalInternalError.shouldNotReachHere("unknown binary operator " + op);
-        }
-    }
-
-    public IntegerConvertOp getIntegerConvertOp(IntegerConvertOp op) {
-        switch (op.getOperator()) {
-            case ZERO_EXTEND:
-                return getZeroExtend();
-            case SIGN_EXTEND:
-                return getSignExtend();
-            case NARROW:
-                return getNarrow();
-            default:
-                throw GraalInternalError.shouldNotReachHere("unknown integer convert operator " + op);
-        }
-    }
-
-    public FloatConvertOp getFloatConvertOp(FloatConvertOp op) {
-        return getFloatConvert(op.getFloatConvert());
+        this.floatConvert = new FloatConvertOp[FloatConvert.values().length];
+        floatConvert.forEach(op -> this.floatConvert[op.getFloatConvert().ordinal()] = op);
     }
 
     /**
      * Describes the unary negation operation.
      */
-    public final UnaryOp getNeg() {
+    public final UnaryOp<Neg> getNeg() {
         return neg;
     }
 
     /**
      * Describes the addition operation.
      */
-    public final BinaryOp getAdd() {
+    public final BinaryOp<Add> getAdd() {
         return add;
     }
 
     /**
      * Describes the subtraction operation.
      */
-    public final BinaryOp getSub() {
+    public final BinaryOp<Sub> getSub() {
         return sub;
     }
 
     /**
      * Describes the multiplication operation.
      */
-    public final BinaryOp getMul() {
+    public final BinaryOp<Mul> getMul() {
         return mul;
     }
 
     /**
      * Describes the division operation.
      */
-    public final BinaryOp getDiv() {
+    public final BinaryOp<Div> getDiv() {
         return div;
     }
 
     /**
      * Describes the remainder operation.
      */
-    public final BinaryOp getRem() {
+    public final BinaryOp<Rem> getRem() {
         return rem;
     }
 
     /**
      * Describes the bitwise not operation.
      */
-    public final UnaryOp getNot() {
+    public final UnaryOp<Not> getNot() {
         return not;
     }
 
     /**
      * Describes the bitwise and operation.
      */
-    public final BinaryOp getAnd() {
+    public final BinaryOp<And> getAnd() {
         return and;
     }
 
     /**
      * Describes the bitwise or operation.
      */
-    public final BinaryOp getOr() {
+    public final BinaryOp<Or> getOr() {
         return or;
     }
 
     /**
      * Describes the bitwise xor operation.
      */
-    public final BinaryOp getXor() {
+    public final BinaryOp<Xor> getXor() {
         return xor;
     }
 
-    public IntegerConvertOp getZeroExtend() {
+    /**
+     * Describes the zero extend conversion.
+     */
+    public IntegerConvertOp<ZeroExtend> getZeroExtend() {
         return zeroExtend;
     }
 
-    public IntegerConvertOp getSignExtend() {
+    /**
+     * Describes the sign extend conversion.
+     */
+    public IntegerConvertOp<SignExtend> getSignExtend() {
         return signExtend;
     }
 
-    public IntegerConvertOp getNarrow() {
+    /**
+     * Describes the narrowing conversion.
+     */
+    public IntegerConvertOp<Narrow> getNarrow() {
         return narrow;
     }
 
+    /**
+     * Describes integer/float/double conversions.
+     */
     public FloatConvertOp getFloatConvert(FloatConvert op) {
         return floatConvert[op.ordinal()];
     }
 
     public abstract static class Op {
 
-        private final char operator;
+        private final String operator;
 
-        protected Op(char operator) {
+        protected Op(String operator) {
             this.operator = operator;
         }
 
-        public char getOperator() {
-            return operator;
-        }
-
         @Override
         public String toString() {
-            return Character.toString(operator);
+            return operator;
         }
     }
 
     /**
      * Describes a unary arithmetic operation.
      */
-    public abstract static class UnaryOp extends Op {
+    public abstract static class UnaryOp<T> extends Op {
+
+        public abstract static class Neg extends UnaryOp<Neg> {
+
+            protected Neg() {
+                super("-");
+            }
+        }
 
-        protected UnaryOp(char operation) {
+        public abstract static class Not extends UnaryOp<Not> {
+
+            protected Not() {
+                super("~");
+            }
+        }
+
+        protected UnaryOp(String operation) {
             super(operation);
         }
 
@@ -370,12 +291,68 @@
     /**
      * Describes a binary arithmetic operation.
      */
-    public abstract static class BinaryOp extends Op {
+    public abstract static class BinaryOp<T> extends Op {
+
+        public abstract static class Add extends BinaryOp<Add> {
+
+            protected Add(boolean associative, boolean commutative) {
+                super("+", associative, commutative);
+            }
+        }
+
+        public abstract static class Sub extends BinaryOp<Sub> {
+
+            protected Sub(boolean associative, boolean commutative) {
+                super("-", associative, commutative);
+            }
+        }
+
+        public abstract static class Mul extends BinaryOp<Mul> {
+
+            protected Mul(boolean associative, boolean commutative) {
+                super("*", associative, commutative);
+            }
+        }
+
+        public abstract static class Div extends BinaryOp<Div> {
+
+            protected Div(boolean associative, boolean commutative) {
+                super("/", associative, commutative);
+            }
+        }
+
+        public abstract static class Rem extends BinaryOp<Rem> {
+
+            protected Rem(boolean associative, boolean commutative) {
+                super("%", associative, commutative);
+            }
+        }
+
+        public abstract static class And extends BinaryOp<And> {
+
+            protected And(boolean associative, boolean commutative) {
+                super("&", associative, commutative);
+            }
+        }
+
+        public abstract static class Or extends BinaryOp<Or> {
+
+            protected Or(boolean associative, boolean commutative) {
+                super("|", associative, commutative);
+            }
+        }
+
+        public abstract static class Xor extends BinaryOp<Xor> {
+
+            protected Xor(boolean associative, boolean commutative) {
+                super("^", associative, commutative);
+            }
+        }
 
         private final boolean associative;
         private final boolean commutative;
 
-        protected BinaryOp(char operation, boolean associative, boolean commutative) {
+        protected BinaryOp(String operation, boolean associative, boolean commutative) {
             super(operation);
             this.associative = associative;
             this.commutative = commutative;
@@ -435,51 +412,49 @@
         }
     }
 
-    public abstract static class FloatConvertOp extends UnaryOp {
+    public abstract static class FloatConvertOp extends UnaryOp<FloatConvertOp> {
 
         private final FloatConvert op;
 
         protected FloatConvertOp(FloatConvert op) {
-            super('\0');
+            super(op.name());
             this.op = op;
         }
 
         public FloatConvert getFloatConvert() {
             return op;
         }
-
-        @Override
-        public String toString() {
-            return op.name();
-        }
     }
 
-    public abstract static class IntegerConvertOp extends Op {
+    public abstract static class IntegerConvertOp<T> extends Op {
+
+        public abstract static class ZeroExtend extends IntegerConvertOp<ZeroExtend> {
+
+            protected ZeroExtend() {
+                super("ZeroExtend");
+            }
+        }
+
+        public abstract static class SignExtend extends IntegerConvertOp<SignExtend> {
 
-        public static final char ZERO_EXTEND = 'z';
-        public static final char SIGN_EXTEND = 's';
-        public static final char NARROW = 'n';
+            protected SignExtend() {
+                super("SignExtend");
+            }
+        }
+
+        public abstract static class Narrow extends IntegerConvertOp<Narrow> {
 
-        protected IntegerConvertOp(char op) {
+            protected Narrow() {
+                super("Narrow");
+            }
+        }
+
+        protected IntegerConvertOp(String op) {
             super(op);
         }
 
         public abstract Constant foldConstant(int inputBits, int resultBits, Constant value);
 
         public abstract Stamp foldStamp(int resultBits, Stamp stamp);
-
-        @Override
-        public String toString() {
-            switch (getOperator()) {
-                case ZERO_EXTEND:
-                    return "ZeroExtend";
-                case SIGN_EXTEND:
-                    return "SignExtend";
-                case NARROW:
-                    return "Narrow";
-                default:
-                    throw GraalInternalError.shouldNotReachHere();
-            }
-        }
     }
 }
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java	Mon Oct 13 15:36:11 2014 +0200
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java	Mon Oct 13 16:50:01 2014 +0200
@@ -255,9 +255,9 @@
         return null;
     }
 
-    private static final ArithmeticOpTable OPS = ArithmeticOpTable.create(
+    private static final ArithmeticOpTable OPS = new ArithmeticOpTable(
 
-    new UnaryOp('-') {
+    new UnaryOp.Neg() {
 
         @Override
         public Constant foldConstant(Constant value) {
@@ -278,7 +278,7 @@
         }
     },
 
-    new BinaryOp('+', false, true) {
+    new BinaryOp.Add(false, true) {
 
         @Override
         public Constant foldConstant(Constant a, Constant b) {
@@ -312,7 +312,7 @@
         }
     },
 
-    new BinaryOp('-', false, false) {
+    new BinaryOp.Sub(false, false) {
 
         @Override
         public Constant foldConstant(Constant a, Constant b) {
@@ -346,7 +346,7 @@
         }
     },
 
-    new BinaryOp('*', false, true) {
+    new BinaryOp.Mul(false, true) {
 
         @Override
         public Constant foldConstant(Constant a, Constant b) {
@@ -380,7 +380,7 @@
         }
     },
 
-    new BinaryOp('/', false, false) {
+    new BinaryOp.Div(false, false) {
 
         @Override
         public Constant foldConstant(Constant a, Constant b) {
@@ -414,7 +414,7 @@
         }
     },
 
-    new BinaryOp('%', false, false) {
+    new BinaryOp.Rem(false, false) {
 
         @Override
         public Constant foldConstant(Constant a, Constant b) {
@@ -436,6 +436,10 @@
         }
     },
 
+    null, null, null, null,
+
+    null, null, null,
+
     new FloatConvertOp(F2I) {
 
         @Override
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java	Mon Oct 13 15:36:11 2014 +0200
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java	Mon Oct 13 16:50:01 2014 +0200
@@ -23,7 +23,6 @@
 package com.oracle.graal.compiler.common.type;
 
 import static com.oracle.graal.compiler.common.calc.FloatConvert.*;
-import static com.oracle.graal.compiler.common.type.ArithmeticOpTable.IntegerConvertOp.*;
 
 import java.util.*;
 
@@ -369,9 +368,9 @@
         return v;
     }
 
-    public static final ArithmeticOpTable OPS = ArithmeticOpTable.create(
+    public static final ArithmeticOpTable OPS = new ArithmeticOpTable(
 
-    new UnaryOp('-') {
+    new UnaryOp.Neg() {
 
         @Override
         public Constant foldConstant(Constant value) {
@@ -391,7 +390,7 @@
         }
     },
 
-    new BinaryOp('+', true, true) {
+    new BinaryOp.Add(true, true) {
 
         @Override
         public Constant foldConstant(Constant a, Constant b) {
@@ -448,7 +447,7 @@
         }
     },
 
-    new BinaryOp('-', true, false) {
+    new BinaryOp.Sub(true, false) {
 
         @Override
         public Constant foldConstant(Constant a, Constant b) {
@@ -473,7 +472,7 @@
         }
     },
 
-    new BinaryOp('*', true, true) {
+    new BinaryOp.Mul(true, true) {
 
         @Override
         public Constant foldConstant(Constant a, Constant b) {
@@ -501,7 +500,7 @@
         }
     },
 
-    new BinaryOp('/', true, false) {
+    new BinaryOp.Div(true, false) {
 
         @Override
         public Constant foldConstant(Constant a, Constant b) {
@@ -529,7 +528,7 @@
         }
     },
 
-    new BinaryOp('%', false, false) {
+    new BinaryOp.Rem(false, false) {
 
         @Override
         public Constant foldConstant(Constant a, Constant b) {
@@ -560,7 +559,7 @@
         }
     },
 
-    new UnaryOp('~') {
+    new UnaryOp.Not() {
 
         @Override
         public Constant foldConstant(Constant value) {
@@ -576,7 +575,7 @@
         }
     },
 
-    new BinaryOp('&', true, true) {
+    new BinaryOp.And(true, true) {
 
         @Override
         public Constant foldConstant(Constant a, Constant b) {
@@ -600,7 +599,7 @@
         }
     },
 
-    new BinaryOp('|', true, true) {
+    new BinaryOp.Or(true, true) {
 
         @Override
         public Constant foldConstant(Constant a, Constant b) {
@@ -622,7 +621,7 @@
         }
     },
 
-    new BinaryOp('^', true, true) {
+    new BinaryOp.Xor(true, true) {
 
         @Override
         public Constant foldConstant(Constant a, Constant b) {
@@ -654,7 +653,7 @@
         }
     },
 
-    new IntegerConvertOp(ZERO_EXTEND) {
+    new IntegerConvertOp.ZeroExtend() {
 
         @Override
         public Constant foldConstant(int inputBits, int resultBits, Constant value) {
@@ -683,7 +682,7 @@
         }
     },
 
-    new IntegerConvertOp(SIGN_EXTEND) {
+    new IntegerConvertOp.SignExtend() {
 
         @Override
         public Constant foldConstant(int inputBits, int resultBits, Constant value) {
@@ -704,7 +703,7 @@
         }
     },
 
-    new IntegerConvertOp(NARROW) {
+    new IntegerConvertOp.Narrow() {
 
         @Override
         public Constant foldConstant(int inputBits, int resultBits, Constant value) {
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/BasicInductionVariable.java	Mon Oct 13 15:36:11 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/BasicInductionVariable.java	Mon Oct 13 16:50:01 2014 +0200
@@ -32,9 +32,9 @@
     private ValuePhiNode phi;
     private ValueNode init;
     private ValueNode rawStride;
-    private BinaryArithmeticNode op;
+    private BinaryArithmeticNode<?> op;
 
-    public BasicInductionVariable(LoopEx loop, ValuePhiNode phi, ValueNode init, ValueNode rawStride, BinaryArithmeticNode op) {
+    public BasicInductionVariable(LoopEx loop, ValuePhiNode phi, ValueNode init, ValueNode rawStride, BinaryArithmeticNode<?> op) {
         super(loop);
         this.phi = phi;
         this.init = init;
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java	Mon Oct 13 15:36:11 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java	Mon Oct 13 16:50:01 2014 +0200
@@ -55,7 +55,7 @@
     public ValueNode maxTripCountNode(boolean assumePositive) {
         StructuredGraph graph = iv.valueNode().graph();
         Stamp stamp = iv.valueNode().stamp();
-        BinaryArithmeticNode range = BinaryArithmeticNode.sub(graph, end, iv.initNode());
+        BinaryArithmeticNode<?> range = BinaryArithmeticNode.sub(graph, end, iv.initNode());
         if (oneOff) {
             if (iv.direction() == Direction.Up) {
                 range = BinaryArithmeticNode.add(graph, range, ConstantNode.forIntegerStamp(stamp, 1, graph));
@@ -144,14 +144,14 @@
         CompareNode cond; // we use a negated guard with a < condition to achieve a >=
         ConstantNode one = ConstantNode.forIntegerStamp(stamp, 1, graph);
         if (iv.direction() == Direction.Up) {
-            BinaryArithmeticNode v1 = sub(graph, ConstantNode.forIntegerStamp(stamp, CodeUtil.maxValue(stamp.getBits()), graph), sub(graph, iv.strideNode(), one));
+            BinaryArithmeticNode<?> v1 = sub(graph, ConstantNode.forIntegerStamp(stamp, CodeUtil.maxValue(stamp.getBits()), graph), sub(graph, iv.strideNode(), one));
             if (oneOff) {
                 v1 = sub(graph, v1, one);
             }
             cond = graph.unique(IntegerLessThanNode.create(v1, end));
         } else {
             assert iv.direction() == Direction.Down;
-            BinaryArithmeticNode v1 = add(graph, ConstantNode.forIntegerStamp(stamp, CodeUtil.minValue(stamp.getBits()), graph), sub(graph, one, iv.strideNode()));
+            BinaryArithmeticNode<?> v1 = add(graph, ConstantNode.forIntegerStamp(stamp, CodeUtil.minValue(stamp.getBits()), graph), sub(graph, one, iv.strideNode()));
             if (oneOff) {
                 v1 = add(graph, v1, one);
             }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedOffsetInductionVariable.java	Mon Oct 13 15:36:11 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedOffsetInductionVariable.java	Mon Oct 13 16:50:01 2014 +0200
@@ -31,9 +31,9 @@
 
     private InductionVariable base;
     private ValueNode offset;
-    private BinaryArithmeticNode value;
+    private BinaryArithmeticNode<?> value;
 
-    public DerivedOffsetInductionVariable(LoopEx loop, InductionVariable base, ValueNode offset, BinaryArithmeticNode value) {
+    public DerivedOffsetInductionVariable(LoopEx loop, InductionVariable base, ValueNode offset, BinaryArithmeticNode<?> value) {
         super(loop);
         this.base = base;
         this.offset = offset;
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariables.java	Mon Oct 13 15:36:11 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariables.java	Mon Oct 13 16:50:01 2014 +0200
@@ -57,7 +57,7 @@
             }
             ValueNode stride = addSub(backValue, phi);
             if (stride != null) {
-                BasicInductionVariable biv = new BasicInductionVariable(loop, (ValuePhiNode) phi, phi.valueAt(forwardEnd), stride, (BinaryArithmeticNode) backValue);
+                BasicInductionVariable biv = new BasicInductionVariable(loop, (ValuePhiNode) phi, phi.valueAt(forwardEnd), stride, (BinaryArithmeticNode<?>) backValue);
                 ivs.put(phi, biv);
                 bivs.add(biv);
             }
@@ -78,7 +78,7 @@
                 ValueNode offset = addSub(op, baseIvNode);
                 ValueNode scale;
                 if (offset != null) {
-                    iv = new DerivedOffsetInductionVariable(loop, baseIv, offset, (BinaryArithmeticNode) op);
+                    iv = new DerivedOffsetInductionVariable(loop, baseIv, offset, (BinaryArithmeticNode<?>) op);
                 } else if (op instanceof NegateNode) {
                     iv = new DerivedScaledInductionVariable(loop, baseIv, (NegateNode) op);
                 } else if ((scale = mul(op, baseIvNode)) != null) {
@@ -95,7 +95,7 @@
 
     private ValueNode addSub(ValueNode op, ValueNode base) {
         if (op.stamp() instanceof IntegerStamp && (op instanceof AddNode || op instanceof SubNode)) {
-            BinaryArithmeticNode aritOp = (BinaryArithmeticNode) op;
+            BinaryArithmeticNode<?> aritOp = (BinaryArithmeticNode<?>) op;
             if (aritOp.getX() == base && loop.isOutsideLoop(aritOp.getY())) {
                 return aritOp.getY();
             } else if (aritOp.getY() == base && loop.isOutsideLoop(aritOp.getX())) {
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java	Mon Oct 13 15:36:11 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java	Mon Oct 13 16:50:01 2014 +0200
@@ -137,11 +137,11 @@
     public void reassociateInvariants() {
         InvariantPredicate invariant = new InvariantPredicate();
         StructuredGraph graph = loopBegin().graph();
-        for (BinaryArithmeticNode binary : whole().nodes().filter(BinaryArithmeticNode.class)) {
+        for (BinaryArithmeticNode<?> binary : whole().nodes().filter(BinaryArithmeticNode.class)) {
             if (!binary.isAssociative()) {
                 continue;
             }
-            BinaryArithmeticNode result = BinaryArithmeticNode.reassociate(binary, invariant, binary.getX(), binary.getY());
+            BinaryArithmeticNode<?> result = BinaryArithmeticNode.reassociate(binary, invariant, binary.getX(), binary.getY());
             if (result != binary) {
                 if (Debug.isLogEnabled()) {
                     Debug.log("%s : Reassociated %s into %s", graph.method().format("%H::%n"), binary, result);
--- a/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java	Mon Oct 13 15:36:11 2014 +0200
+++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java	Mon Oct 13 16:50:01 2014 +0200
@@ -131,7 +131,7 @@
 
     private static Stamp narrowingKindConversion(Stamp stamp, Kind kind) {
         Stamp narrow = IntegerStamp.OPS.getNarrow().foldStamp(kind.getBitCount(), stamp);
-        IntegerConvertOp implicitExtend = kind.isUnsigned() ? IntegerStamp.OPS.getZeroExtend() : IntegerStamp.OPS.getSignExtend();
+        IntegerConvertOp<?> implicitExtend = kind.isUnsigned() ? IntegerStamp.OPS.getZeroExtend() : IntegerStamp.OPS.getSignExtend();
         return implicitExtend.foldStamp(32, narrow);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AddNode.java	Mon Oct 13 15:36:11 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AddNode.java	Mon Oct 13 16:50:01 2014 +0200
@@ -25,6 +25,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.compiler.common.type.ArithmeticOpTable.BinaryOp.Add;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodeinfo.*;
@@ -32,7 +33,7 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(shortName = "+")
-public class AddNode extends BinaryArithmeticNode implements NarrowableArithmeticNode {
+public class AddNode extends BinaryArithmeticNode<Add> implements NarrowableArithmeticNode {
 
     public static AddNode create(ValueNode x, ValueNode y) {
         return USE_GENERATED_NODES ? new AddNodeGen(x, y) : new AddNode(x, y);
@@ -52,7 +53,7 @@
         if (forX.isConstant() && !forY.isConstant()) {
             return AddNode.create(forY, forX);
         }
-        BinaryOp op = getOp(forX, forY);
+        BinaryOp<Add> op = getOp(forX, forY);
         boolean associative = op.isAssociative();
         if (associative) {
             if (forX instanceof SubNode) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Mon Oct 13 15:36:11 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Mon Oct 13 16:50:01 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.And;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodeinfo.*;
@@ -33,7 +34,7 @@
 import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "&")
-public class AndNode extends BinaryArithmeticNode implements NarrowableArithmeticNode {
+public class AndNode extends BinaryArithmeticNode<And> implements NarrowableArithmeticNode {
 
     public static AndNode create(ValueNode x, ValueNode y) {
         return USE_GENERATED_NODES ? new AndNodeGen(x, y) : new AndNode(x, y);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryArithmeticNode.java	Mon Oct 13 15:36:11 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryArithmeticNode.java	Mon Oct 13 16:50:01 2014 +0200
@@ -36,16 +36,16 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo
-public abstract class BinaryArithmeticNode extends BinaryNode implements ArithmeticLIRLowerable {
+public abstract class BinaryArithmeticNode<OP> extends BinaryNode implements ArithmeticLIRLowerable {
 
-    protected final Function<ArithmeticOpTable, BinaryOp> getOp;
+    protected final Function<ArithmeticOpTable, BinaryOp<OP>> getOp;
 
-    public BinaryArithmeticNode(Function<ArithmeticOpTable, BinaryOp> getOp, ValueNode x, ValueNode y) {
+    public BinaryArithmeticNode(Function<ArithmeticOpTable, BinaryOp<OP>> getOp, ValueNode x, ValueNode y) {
         super(getOp.apply(ArithmeticOpTable.forStamp(x.stamp())).foldStamp(x.stamp(), y.stamp()), x, y);
         this.getOp = getOp;
     }
 
-    protected final BinaryOp getOp(ValueNode forX, ValueNode forY) {
+    protected final BinaryOp<OP> getOp(ValueNode forX, ValueNode forY) {
         ArithmeticOpTable table = ArithmeticOpTable.forStamp(forX.stamp());
         assert table == ArithmeticOpTable.forStamp(forY.stamp());
         return getOp.apply(table);
@@ -164,7 +164,7 @@
      * @param forY
      * @param forX
      */
-    public static BinaryArithmeticNode reassociate(BinaryArithmeticNode node, NodePredicate criterion, ValueNode forX, ValueNode forY) {
+    public static BinaryArithmeticNode<?> reassociate(BinaryArithmeticNode<?> node, NodePredicate criterion, ValueNode forX, ValueNode forY) {
         assert node.getOp(forX, forY).isAssociative();
         ReassociateMatch match1 = findReassociate(node, criterion);
         if (match1 == null) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/DivNode.java	Mon Oct 13 15:36:11 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/DivNode.java	Mon Oct 13 16:50:01 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.Div;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodeinfo.*;
@@ -32,7 +33,7 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(shortName = "/")
-public class DivNode extends BinaryArithmeticNode {
+public class DivNode extends BinaryArithmeticNode<Div> {
 
     public static DivNode create(ValueNode x, ValueNode y) {
         return USE_GENERATED_NODES ? new DivNodeGen(x, y) : new DivNode(x, y);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java	Mon Oct 13 15:36:11 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatConvertNode.java	Mon Oct 13 16:50:01 2014 +0200
@@ -37,7 +37,7 @@
  * semantics.
  */
 @NodeInfo
-public class FloatConvertNode extends UnaryArithmeticNode implements ConvertNode, Lowerable, ArithmeticLIRLowerable {
+public class FloatConvertNode extends UnaryArithmeticNode<FloatConvertOp> implements ConvertNode, Lowerable, ArithmeticLIRLowerable {
 
     protected final FloatConvert op;
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java	Mon Oct 13 15:36:11 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerConvertNode.java	Mon Oct 13 16:50:01 2014 +0200
@@ -36,14 +36,14 @@
  * An {@code IntegerConvert} converts an integer to an integer of different width.
  */
 @NodeInfo
-public abstract class IntegerConvertNode extends UnaryNode implements ConvertNode, ArithmeticLIRLowerable {
+public abstract class IntegerConvertNode<OP, REV> extends UnaryNode implements ConvertNode, ArithmeticLIRLowerable {
 
-    protected final Function<ArithmeticOpTable, IntegerConvertOp> getOp;
-    protected final Function<ArithmeticOpTable, IntegerConvertOp> getReverseOp;
+    protected final Function<ArithmeticOpTable, IntegerConvertOp<OP>> getOp;
+    protected final Function<ArithmeticOpTable, IntegerConvertOp<REV>> getReverseOp;
 
     protected final int resultBits;
 
-    protected IntegerConvertNode(Function<ArithmeticOpTable, IntegerConvertOp> getOp, Function<ArithmeticOpTable, IntegerConvertOp> getReverseOp, int resultBits, ValueNode input) {
+    protected IntegerConvertNode(Function<ArithmeticOpTable, IntegerConvertOp<OP>> getOp, Function<ArithmeticOpTable, IntegerConvertOp<REV>> getReverseOp, int resultBits, ValueNode input) {
         super(getOp.apply(ArithmeticOpTable.forStamp(input.stamp())).foldStamp(resultBits, input.stamp()), input);
         this.getOp = getOp;
         this.getReverseOp = getReverseOp;
@@ -62,7 +62,7 @@
         }
     }
 
-    protected final IntegerConvertOp getOp(ValueNode forValue) {
+    protected final IntegerConvertOp<OP> getOp(ValueNode forValue) {
         return getOp.apply(ArithmeticOpTable.forStamp(forValue.stamp()));
     }
 
@@ -73,7 +73,7 @@
 
     @Override
     public Constant reverse(Constant c) {
-        IntegerConvertOp reverse = getReverseOp.apply(ArithmeticOpTable.forStamp(stamp()));
+        IntegerConvertOp<REV> reverse = getReverseOp.apply(ArithmeticOpTable.forStamp(stamp()));
         return reverse.foldConstant(getResultBits(), getInputBits(), c);
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/MulNode.java	Mon Oct 13 15:36:11 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/MulNode.java	Mon Oct 13 16:50:01 2014 +0200
@@ -26,6 +26,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.compiler.common.type.ArithmeticOpTable.BinaryOp.Mul;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodeinfo.*;
@@ -33,7 +34,7 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(shortName = "*")
-public class MulNode extends BinaryArithmeticNode implements NarrowableArithmeticNode {
+public class MulNode extends BinaryArithmeticNode<Mul> implements NarrowableArithmeticNode {
 
     public static MulNode create(ValueNode x, ValueNode y) {
         return USE_GENERATED_NODES ? new MulNodeGen(x, y) : new MulNode(x, y);
@@ -54,7 +55,7 @@
             return MulNode.create(forY, forX);
         }
         if (forY.isConstant()) {
-            BinaryOp op = getOp(forX, forY);
+            BinaryOp<Mul> op = getOp(forX, forY);
             Constant c = forY.asConstant();
             if (op.isNeutral(c)) {
                 return forX;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java	Mon Oct 13 15:36:11 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NarrowNode.java	Mon Oct 13 16:50:01 2014 +0200
@@ -23,6 +23,8 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.IntegerConvertOp.Narrow;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.IntegerConvertOp.SignExtend;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodeinfo.*;
@@ -33,7 +35,7 @@
  * The {@code NarrowNode} converts an integer to a narrower integer.
  */
 @NodeInfo
-public class NarrowNode extends IntegerConvertNode {
+public class NarrowNode extends IntegerConvertNode<Narrow, SignExtend> {
 
     public static NarrowNode create(ValueNode input, int resultBits) {
         return USE_GENERATED_NODES ? new NarrowNodeGen(input, resultBits) : new NarrowNode(input, resultBits);
@@ -62,7 +64,7 @@
             return NarrowNode.create(other.getValue(), getResultBits());
         } else if (forValue instanceof IntegerConvertNode) {
             // SignExtendNode or ZeroExtendNode
-            IntegerConvertNode other = (IntegerConvertNode) forValue;
+            IntegerConvertNode<?, ?> other = (IntegerConvertNode<?, ?>) forValue;
             if (getResultBits() == other.getInputBits()) {
                 // xxxx -(extend)-> yyyy xxxx -(narrow)-> xxxx
                 // ==> no-op
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java	Mon Oct 13 15:36:11 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java	Mon Oct 13 16:50:01 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp.Neg;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodeinfo.*;
@@ -33,7 +34,7 @@
  * The {@code NegateNode} node negates its operand.
  */
 @NodeInfo
-public class NegateNode extends UnaryArithmeticNode implements NarrowableArithmeticNode {
+public class NegateNode extends UnaryArithmeticNode<Neg> implements NarrowableArithmeticNode {
 
     /**
      * Creates new NegateNode instance.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java	Mon Oct 13 15:36:11 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java	Mon Oct 13 16:50:01 2014 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp.Not;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodeinfo.*;
@@ -33,7 +34,7 @@
  * Binary negation of long or integer values.
  */
 @NodeInfo
-public class NotNode extends UnaryArithmeticNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode {
+public class NotNode extends UnaryArithmeticNode<Not> implements ArithmeticLIRLowerable, NarrowableArithmeticNode {
 
     /**
      * Creates new NotNode instance.
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Mon Oct 13 15:36:11 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Mon Oct 13 16:50:01 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.Or;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodeinfo.*;
@@ -33,7 +34,7 @@
 import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "|")
-public class OrNode extends BinaryArithmeticNode {
+public class OrNode extends BinaryArithmeticNode<Or> {
 
     public static OrNode create(ValueNode x, ValueNode y) {
         return USE_GENERATED_NODES ? new OrNodeGen(x, y) : new OrNode(x, y);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RemNode.java	Mon Oct 13 15:36:11 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RemNode.java	Mon Oct 13 16:50:01 2014 +0200
@@ -23,13 +23,14 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp.Rem;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo(shortName = "%")
-public class RemNode extends BinaryArithmeticNode implements Lowerable {
+public class RemNode extends BinaryArithmeticNode<Rem> implements Lowerable {
 
     public static RemNode create(ValueNode x, ValueNode y) {
         return USE_GENERATED_NODES ? new RemNodeGen(x, y) : new RemNode(x, y);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java	Mon Oct 13 15:36:11 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SignExtendNode.java	Mon Oct 13 16:50:01 2014 +0200
@@ -23,6 +23,8 @@
 package com.oracle.graal.nodes.calc;
 
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.IntegerConvertOp.Narrow;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.IntegerConvertOp.SignExtend;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodeinfo.*;
@@ -33,7 +35,7 @@
  * The {@code SignExtendNode} converts an integer to a wider integer using sign extension.
  */
 @NodeInfo
-public class SignExtendNode extends IntegerConvertNode {
+public class SignExtendNode extends IntegerConvertNode<SignExtend, Narrow> {
 
     public static SignExtendNode create(ValueNode input, int resultBits) {
         return USE_GENERATED_NODES ? new SignExtendNodeGen(input, resultBits) : new SignExtendNode(input, resultBits);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SubNode.java	Mon Oct 13 15:36:11 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SubNode.java	Mon Oct 13 16:50:01 2014 +0200
@@ -25,6 +25,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.compiler.common.type.ArithmeticOpTable.BinaryOp.Sub;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodeinfo.*;
@@ -33,7 +34,7 @@
 import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "-")
-public class SubNode extends BinaryArithmeticNode implements NarrowableArithmeticNode {
+public class SubNode extends BinaryArithmeticNode<Sub> implements NarrowableArithmeticNode {
 
     public static SubNode create(ValueNode x, ValueNode y) {
         return USE_GENERATED_NODES ? new SubNodeGen(x, y) : new SubNode(x, y);
@@ -51,7 +52,7 @@
             return ret;
         }
 
-        BinaryOp op = getOp(forX, forY);
+        BinaryOp<Sub> op = getOp(forX, forY);
         if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
             Constant zero = op.getZero(forX.stamp());
             if (zero != null) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnaryArithmeticNode.java	Mon Oct 13 15:36:11 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnaryArithmeticNode.java	Mon Oct 13 16:50:01 2014 +0200
@@ -33,16 +33,16 @@
 import com.oracle.graal.nodes.spi.*;
 
 @NodeInfo
-public abstract class UnaryArithmeticNode extends UnaryNode implements ArithmeticLIRLowerable {
+public abstract class UnaryArithmeticNode<OP> extends UnaryNode implements ArithmeticLIRLowerable {
 
-    protected final Function<ArithmeticOpTable, UnaryOp> getOp;
+    protected final Function<ArithmeticOpTable, UnaryOp<OP>> getOp;
 
-    protected UnaryArithmeticNode(Function<ArithmeticOpTable, UnaryOp> getOp, ValueNode value) {
+    protected UnaryArithmeticNode(Function<ArithmeticOpTable, UnaryOp<OP>> getOp, ValueNode value) {
         super(getOp.apply(ArithmeticOpTable.forStamp(value.stamp())).foldStamp(value.stamp()), value);
         this.getOp = getOp;
     }
 
-    protected final UnaryOp getOp(ValueNode forValue) {
+    protected final UnaryOp<OP> getOp(ValueNode forValue) {
         return getOp.apply(ArithmeticOpTable.forStamp(forValue.stamp()));
     }
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Mon Oct 13 15:36:11 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Mon Oct 13 16:50:01 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.Xor;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodeinfo.*;
@@ -33,7 +34,7 @@
 import com.oracle.graal.nodes.util.*;
 
 @NodeInfo(shortName = "^")
-public class XorNode extends BinaryArithmeticNode {
+public class XorNode extends BinaryArithmeticNode<Xor> {
 
     public static XorNode create(ValueNode x, ValueNode y) {
         return USE_GENERATED_NODES ? new XorNodeGen(x, y) : new XorNode(x, y);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java	Mon Oct 13 15:36:11 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ZeroExtendNode.java	Mon Oct 13 16:50:01 2014 +0200
@@ -25,6 +25,8 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.IntegerConvertOp.Narrow;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.IntegerConvertOp.ZeroExtend;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodeinfo.*;
@@ -35,7 +37,7 @@
  * The {@code ZeroExtendNode} converts an integer to a wider integer using zero extension.
  */
 @NodeInfo
-public class ZeroExtendNode extends IntegerConvertNode {
+public class ZeroExtendNode extends IntegerConvertNode<ZeroExtend, Narrow> {
 
     public static ZeroExtendNode create(ValueNode input, int resultBits) {
         return USE_GENERATED_NODES ? new ZeroExtendNodeGen(input, resultBits) : new ZeroExtendNode(input, resultBits);
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java	Mon Oct 13 15:36:11 2014 +0200
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64FloatConvertNode.java	Mon Oct 13 16:50:01 2014 +0200
@@ -25,6 +25,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.calc.*;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.FloatConvertOp;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodeinfo.*;
@@ -38,7 +39,7 @@
  * fixup code that handles the corner cases that differ between AMD64 and Java.
  */
 @NodeInfo
-public class AMD64FloatConvertNode extends UnaryArithmeticNode implements ArithmeticLIRLowerable {
+public class AMD64FloatConvertNode extends UnaryArithmeticNode<FloatConvertOp> implements ArithmeticLIRLowerable {
 
     protected final FloatConvert op;