changeset 17199:88012c1750a0

Move bit logic nodes into the arithmetic node hierarchies.
author Roland Schatz <roland.schatz@oracle.com>
date Wed, 24 Sep 2014 14:29:43 +0200
parents 75177b3cc5a8
children 56458afc02a3
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/IntegerStamp.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/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/BitLogicNode.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/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/type/StampTool.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java
diffstat 14 files changed, 309 insertions(+), 290 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ArithmeticOpTable.java	Wed Sep 24 14:22:01 2014 +0200
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ArithmeticOpTable.java	Wed Sep 24 14:29:43 2014 +0200
@@ -37,6 +37,11 @@
     protected BinaryOp div;
     protected BinaryOp rem;
 
+    protected UnaryOp not;
+    protected BinaryOp and;
+    protected BinaryOp or;
+    protected BinaryOp xor;
+
     public static ArithmeticOpTable forStamp(Stamp s) {
         return ((ArithmeticStamp) s).getOps();
     }
@@ -84,6 +89,34 @@
     }
 
     /**
+     * Describes the bitwise not operation.
+     */
+    public final UnaryOp getNot() {
+        return not;
+    }
+
+    /**
+     * Describes the bitwise and operation.
+     */
+    public final BinaryOp getAnd() {
+        return and;
+    }
+
+    /**
+     * Describes the bitwise or operation.
+     */
+    public final BinaryOp getOr() {
+        return or;
+    }
+
+    /**
+     * Describes the bitwise xor operation.
+     */
+    public final BinaryOp getXor() {
+        return xor;
+    }
+
+    /**
      * Describes a unary arithmetic operation.
      */
     public abstract static class UnaryOp {
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java	Wed Sep 24 14:22:01 2014 +0200
+++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java	Wed Sep 24 14:29:43 2014 +0200
@@ -56,6 +56,24 @@
         assert (upMask & CodeUtil.mask(bits)) == upMask : this;
     }
 
+    public static IntegerStamp stampForMask(int bits, long downMask, long upMask) {
+        long lowerBound;
+        long upperBound;
+        if (((upMask >>> (bits - 1)) & 1) == 0) {
+            lowerBound = downMask;
+            upperBound = upMask;
+        } else if (((downMask >>> (bits - 1)) & 1) == 1) {
+            lowerBound = downMask;
+            upperBound = upMask;
+        } else {
+            lowerBound = downMask | (-1L << (bits - 1));
+            upperBound = CodeUtil.maxValue(bits) & upMask;
+        }
+        lowerBound = CodeUtil.convert(lowerBound, bits, false);
+        upperBound = CodeUtil.convert(upperBound, bits, false);
+        return new IntegerStamp(bits, lowerBound, upperBound, downMask, upMask);
+    }
+
     @Override
     public IntegerStamp unrestricted() {
         return new IntegerStamp(getBits(), CodeUtil.minValue(getBits()), CodeUtil.maxValue(getBits()), 0, CodeUtil.mask(getBits()));
@@ -523,5 +541,99 @@
                 return StampFactory.forInteger(a.getBits(), newLowerBound, newUpperBound);
             }
         };
+
+        OPS.not = new UnaryOp() {
+
+            @Override
+            public Constant foldConstant(Constant value) {
+                return Constant.forIntegerKind(value.getKind(), ~value.asLong());
+            }
+
+            @Override
+            public Stamp foldStamp(Stamp stamp) {
+                IntegerStamp integerStamp = (IntegerStamp) stamp;
+                int bits = integerStamp.getBits();
+                long defaultMask = CodeUtil.mask(bits);
+                return new IntegerStamp(bits, ~integerStamp.upperBound(), ~integerStamp.lowerBound(), (~integerStamp.upMask()) & defaultMask, (~integerStamp.downMask()) & defaultMask);
+            }
+        };
+
+        OPS.and = new BinaryOp(true, true) {
+
+            @Override
+            public Constant foldConstant(Constant a, Constant b) {
+                assert a.getKind() == b.getKind();
+                return Constant.forIntegerKind(a.getKind(), a.asLong() & b.asLong());
+            }
+
+            @Override
+            public Stamp foldStamp(Stamp stamp1, Stamp stamp2) {
+                IntegerStamp a = (IntegerStamp) stamp1;
+                IntegerStamp b = (IntegerStamp) stamp2;
+                assert a.getBits() == b.getBits();
+                return stampForMask(a.getBits(), a.downMask() & b.downMask(), a.upMask() & b.upMask());
+            }
+
+            @Override
+            public boolean isNeutral(Constant n) {
+                int bits = n.getKind().getBitCount();
+                long mask = CodeUtil.mask(bits);
+                return (n.asLong() & mask) == mask;
+            }
+        };
+
+        OPS.or = new BinaryOp(true, true) {
+
+            @Override
+            public Constant foldConstant(Constant a, Constant b) {
+                assert a.getKind() == b.getKind();
+                return Constant.forIntegerKind(a.getKind(), a.asLong() | b.asLong());
+            }
+
+            @Override
+            public Stamp foldStamp(Stamp stamp1, Stamp stamp2) {
+                IntegerStamp a = (IntegerStamp) stamp1;
+                IntegerStamp b = (IntegerStamp) stamp2;
+                assert a.getBits() == b.getBits();
+                return stampForMask(a.getBits(), a.downMask() | b.downMask(), a.upMask() | b.upMask());
+            }
+
+            @Override
+            public boolean isNeutral(Constant n) {
+                return n.asLong() == 0;
+            }
+        };
+
+        OPS.xor = new BinaryOp(true, true) {
+
+            @Override
+            public Constant foldConstant(Constant a, Constant b) {
+                assert a.getKind() == b.getKind();
+                return Constant.forIntegerKind(a.getKind(), a.asLong() ^ b.asLong());
+            }
+
+            @Override
+            public Stamp foldStamp(Stamp stamp1, Stamp stamp2) {
+                IntegerStamp a = (IntegerStamp) stamp1;
+                IntegerStamp b = (IntegerStamp) stamp2;
+                assert a.getBits() == b.getBits();
+
+                long variableBits = (a.downMask() ^ a.upMask()) | (b.downMask() ^ b.upMask());
+                long newDownMask = (a.downMask() ^ b.downMask()) & ~variableBits;
+                long newUpMask = (a.downMask() ^ b.downMask()) | variableBits;
+                return stampForMask(a.getBits(), newDownMask, newUpMask);
+            }
+
+            @Override
+            public boolean isNeutral(Constant n) {
+                return n.asLong() == 0;
+            }
+
+            @Override
+            public Constant getZero(Stamp s) {
+                IntegerStamp stamp = (IntegerStamp) s;
+                return Constant.forPrimitiveInt(stamp.getBits(), 0);
+            }
+        };
     }
 }
--- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java	Wed Sep 24 14:22:01 2014 +0200
+++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java	Wed Sep 24 14:29:43 2014 +0200
@@ -137,11 +137,11 @@
     public void reassociateInvariants() {
         InvariantPredicate invariant = new InvariantPredicate();
         StructuredGraph graph = loopBegin().graph();
-        for (BinaryNode binary : whole().nodes().filter(BinaryNode.class)) {
-            if (!BinaryArithmeticNode.canTryReassociate(binary)) {
+        for (BinaryArithmeticNode binary : whole().nodes().filter(BinaryArithmeticNode.class)) {
+            if (!binary.getOp().isAssociative()) {
                 continue;
             }
-            BinaryNode 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	Wed Sep 24 14:22:01 2014 +0200
+++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java	Wed Sep 24 14:29:43 2014 +0200
@@ -164,15 +164,15 @@
 
     @Test
     public void testXor() {
-        assertEquals(new IntegerStamp(32, 0, 0xff, 0, 0xff), StampTool.xor(new IntegerStamp(32, 0, 0, 0, 0), new IntegerStamp(32, 0, 0xff, 0, 0xff)));
-        assertEquals(new IntegerStamp(32, 0x10, 0x1f, 0x10, 0x1f), StampTool.xor(new IntegerStamp(32, 0, 0, 0, 0), new IntegerStamp(32, 0x10, 0x1f, 0x10, 0x1f)));
-        assertEquals(new IntegerStamp(32, 0x0, 0xf, 0x0, 0xf), StampTool.xor(new IntegerStamp(32, 0x10, 0x10, 0x10, 0x10), new IntegerStamp(32, 0x10, 0x1f, 0x10, 0x1f)));
-        assertEquals(new IntegerStamp(32, 0x10, 0x1f, 0x10, 0x1f), StampTool.xor(new IntegerStamp(32, 0x10, 0x10, 0x10, 0x10), new IntegerStamp(32, 0x0, 0xf, 0x0, 0xf)));
+        assertEquals(new IntegerStamp(32, 0, 0xff, 0, 0xff), IntegerStamp.OPS.getXor().foldStamp(new IntegerStamp(32, 0, 0, 0, 0), new IntegerStamp(32, 0, 0xff, 0, 0xff)));
+        assertEquals(new IntegerStamp(32, 0x10, 0x1f, 0x10, 0x1f), IntegerStamp.OPS.getXor().foldStamp(new IntegerStamp(32, 0, 0, 0, 0), new IntegerStamp(32, 0x10, 0x1f, 0x10, 0x1f)));
+        assertEquals(new IntegerStamp(32, 0x0, 0xf, 0x0, 0xf), IntegerStamp.OPS.getXor().foldStamp(new IntegerStamp(32, 0x10, 0x10, 0x10, 0x10), new IntegerStamp(32, 0x10, 0x1f, 0x10, 0x1f)));
+        assertEquals(new IntegerStamp(32, 0x10, 0x1f, 0x10, 0x1f), IntegerStamp.OPS.getXor().foldStamp(new IntegerStamp(32, 0x10, 0x10, 0x10, 0x10), new IntegerStamp(32, 0x0, 0xf, 0x0, 0xf)));
     }
 
     @Test
     public void testNot() {
-        assertEquals(new IntegerStamp(32, -11, -1, 0xffff_fff0L, 0xffff_ffffL), StampTool.not(new IntegerStamp(32, 0, 10, 0, 0xf)));
+        assertEquals(new IntegerStamp(32, -11, -1, 0xffff_fff0L, 0xffff_ffffL), IntegerStamp.OPS.getNot().foldStamp(new IntegerStamp(32, 0, 10, 0, 0xf)));
     }
 
     @Test
@@ -263,7 +263,8 @@
 
     @Test
     public void testAnd() {
-        assertEquals(new IntegerStamp(32, Integer.MIN_VALUE, 0x40000000L, 0, 0xc0000000L), StampTool.and(StampFactory.forKind(Kind.Int), StampFactory.forConstant(Constant.forInt(0xc0000000))));
+        assertEquals(new IntegerStamp(32, Integer.MIN_VALUE, 0x40000000L, 0, 0xc0000000L),
+                        IntegerStamp.OPS.getAnd().foldStamp(StampFactory.forKind(Kind.Int), StampFactory.forConstant(Constant.forInt(0xc0000000))));
     }
 
     private static void testSignExtendShort(long lower, long upper) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Wed Sep 24 14:22:01 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java	Wed Sep 24 14:29:43 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,58 +30,50 @@
 import com.oracle.graal.nodeinfo.*;
 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 AndNode extends BitLogicNode implements NarrowableArithmeticNode {
+public class AndNode extends BinaryArithmeticNode implements NarrowableArithmeticNode {
 
     public static AndNode create(ValueNode x, ValueNode y) {
         return USE_GENERATED_NODES ? new AndNodeGen(x, y) : new AndNode(x, y);
     }
 
     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(getX().stamp(), getY().stamp()));
-    }
-
-    @Override
-    public Constant evalConst(Constant... inputs) {
-        assert inputs.length == 2;
-        return Constant.forPrimitiveInt(PrimitiveStamp.getBits(stamp()), inputs[0].asLong() & inputs[1].asLong());
+        super(ArithmeticOpTable.forStamp(x.stamp()).getAnd(), x, y);
     }
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        ValueNode ret = super.canonical(tool, forX, forY);
+        if (ret != this) {
+            return ret;
+        }
+
         if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
             return forX;
         }
         if (forX.isConstant() && !forY.isConstant()) {
             return AndNode.create(forY, forX);
         }
-        if (forX.isConstant()) {
-            return ConstantNode.forPrimitive(stamp(), evalConst(forX.asConstant(), forY.asConstant()));
-        } else if (forY.isConstant()) {
-            long rawY = forY.asConstant().asLong();
-            long mask = CodeUtil.mask(PrimitiveStamp.getBits(stamp()));
-            if ((rawY & mask) == mask) {
+        if (forY.isConstant()) {
+            Constant c = forY.asConstant();
+            if (getOp().isNeutral(c)) {
                 return forX;
             }
-            if ((rawY & mask) == 0) {
-                return ConstantNode.forIntegerStamp(stamp(), 0);
-            }
-            if (forX instanceof SignExtendNode) {
-                SignExtendNode ext = (SignExtendNode) forX;
-                if (rawY == ((1L << ext.getInputBits()) - 1)) {
-                    return ZeroExtendNode.create(ext.getValue(), ext.getResultBits());
+
+            if (c.getKind().isNumericInteger()) {
+                long rawY = c.asLong();
+                long mask = CodeUtil.mask(PrimitiveStamp.getBits(stamp()));
+                if ((rawY & mask) == 0) {
+                    return ConstantNode.forIntegerStamp(stamp(), 0);
                 }
-            }
-            if (forX.stamp() instanceof IntegerStamp) {
+                if (forX instanceof SignExtendNode) {
+                    SignExtendNode ext = (SignExtendNode) forX;
+                    if (rawY == ((1L << ext.getInputBits()) - 1)) {
+                        return ZeroExtendNode.create(ext.getValue(), ext.getResultBits());
+                    }
+                }
                 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.
@@ -89,7 +81,7 @@
                 }
             }
 
-            return BinaryArithmeticNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY);
+            return reassociate(this, ValueNode.isConstantPredicate(), forX, forY);
         }
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryArithmeticNode.java	Wed Sep 24 14:22:01 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryArithmeticNode.java	Wed Sep 24 14:29:43 2014 +0200
@@ -116,11 +116,7 @@
         }
     }
 
-    public static boolean canTryReassociate(BinaryNode node) {
-        return (node instanceof BinaryArithmeticNode && ((BinaryArithmeticNode) node).getOp().isAssociative()) || node instanceof AndNode || node instanceof OrNode || node instanceof XorNode;
-    }
-
-    public static ReassociateMatch findReassociate(BinaryNode binary, NodePredicate criterion) {
+    private static ReassociateMatch findReassociate(BinaryNode binary, NodePredicate criterion) {
         boolean resultX = criterion.apply(binary.getX());
         boolean resultY = criterion.apply(binary.getY());
         if (resultX && !resultY) {
@@ -152,14 +148,14 @@
      * Tries to re-associate values which satisfy the criterion. For example with a constantness
      * criterion: {@code (a + 2) + 1 => a + (1 + 2)}
      * <p>
-     * This method accepts only {@linkplain #canTryReassociate(BinaryNode) reassociable} operations
-     * such as +, -, *, &amp;, | and ^
+     * This method accepts only {@linkplain BinaryOp#isAssociative() associative} operations such as
+     * +, -, *, &amp;, | and ^
      *
      * @param forY
      * @param forX
      */
-    public static BinaryNode reassociate(BinaryNode node, NodePredicate criterion, ValueNode forX, ValueNode forY) {
-        assert canTryReassociate(node);
+    public static BinaryArithmeticNode reassociate(BinaryArithmeticNode node, NodePredicate criterion, ValueNode forX, ValueNode forY) {
+        assert node.getOp().isAssociative();
         ReassociateMatch match1 = findReassociate(node, criterion);
         if (match1 == null) {
             return node;
@@ -220,11 +216,11 @@
         } else if (node instanceof MulNode) {
             return BinaryArithmeticNode.mul(a, AddNode.mul(m1, m2));
         } else if (node instanceof AndNode) {
-            return BitLogicNode.and(a, BitLogicNode.and(m1, m2));
+            return AndNode.create(a, AndNode.create(m1, m2));
         } else if (node instanceof OrNode) {
-            return BitLogicNode.or(a, BitLogicNode.or(m1, m2));
+            return OrNode.create(a, OrNode.create(m1, m2));
         } else if (node instanceof XorNode) {
-            return BitLogicNode.xor(a, BitLogicNode.xor(m1, m2));
+            return XorNode.create(a, XorNode.create(m1, m2));
         } else {
             throw GraalInternalError.shouldNotReachHere();
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BitLogicNode.java	Wed Sep 24 14:22:01 2014 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.nodes.calc;
-
-import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.nodeinfo.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.spi.*;
-
-/**
- * The {@code LogicNode} class definition.
- */
-@NodeInfo
-public abstract class BitLogicNode extends BinaryNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode {
-
-    /**
-     * Constructs a new logic operation node.
-     *
-     * @param x the first input into this node
-     * @param y the second input into this node
-     */
-    public BitLogicNode(Stamp stamp, ValueNode x, ValueNode y) {
-        super(stamp, x, y);
-        assert stamp instanceof IntegerStamp;
-    }
-
-    public static BitLogicNode and(StructuredGraph graph, ValueNode v1, ValueNode v2) {
-        return graph.unique(AndNode.create(v1, v2));
-    }
-
-    public static BitLogicNode and(ValueNode v1, ValueNode v2) {
-        return AndNode.create(v1, v2);
-    }
-
-    public static BitLogicNode or(StructuredGraph graph, ValueNode v1, ValueNode v2) {
-        return graph.unique(OrNode.create(v1, v2));
-    }
-
-    public static BitLogicNode or(ValueNode v1, ValueNode v2) {
-        return OrNode.create(v1, v2);
-    }
-
-    public static BitLogicNode xor(StructuredGraph graph, ValueNode v1, ValueNode v2) {
-        return graph.unique(XorNode.create(v1, v2));
-    }
-
-    public static BitLogicNode xor(ValueNode v1, ValueNode v2) {
-        return XorNode.create(v1, v2);
-    }
-}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java	Wed Sep 24 14:22:01 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java	Wed Sep 24 14:29:43 2014 +0200
@@ -22,9 +22,7 @@
  */
 package com.oracle.graal.nodes.calc;
 
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp;
 import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.lir.gen.*;
 import com.oracle.graal.nodeinfo.*;
@@ -35,14 +33,7 @@
  * The {@code NegateNode} node negates its operand.
  */
 @NodeInfo
-public class NegateNode extends UnaryNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode {
-
-    private final UnaryOp op;
-
-    @Override
-    public boolean inferStamp() {
-        return updateStamp(op.foldStamp(getValue().stamp()));
-    }
+public class NegateNode extends UnaryArithmeticNode implements NarrowableArithmeticNode {
 
     /**
      * Creates new NegateNode instance.
@@ -50,27 +41,18 @@
      * @param value the instruction producing the value that is input to this instruction
      */
     public static NegateNode create(ValueNode value) {
-        return create(ArithmeticOpTable.forStamp(value.stamp()).getNeg(), value);
-    }
-
-    public static NegateNode create(UnaryOp op, ValueNode value) {
-        return USE_GENERATED_NODES ? new NegateNodeGen(op, value) : new NegateNode(op, value);
+        return USE_GENERATED_NODES ? new NegateNodeGen(value) : new NegateNode(value);
     }
 
-    protected NegateNode(UnaryOp op, ValueNode value) {
-        super(op.foldStamp(value.stamp()), value);
-        this.op = op;
-    }
-
-    public Constant evalConst(Constant... inputs) {
-        assert inputs.length == 1;
-        return op.foldConstant(inputs[0]);
+    NegateNode(ValueNode value) {
+        super(ArithmeticOpTable.forStamp(value.stamp()).getNeg(), value);
     }
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
-        if (forValue.isConstant()) {
-            return ConstantNode.forPrimitive(stamp(), op.foldConstant(forValue.asConstant()));
+        ValueNode ret = super.canonical(tool, forValue);
+        if (ret != this) {
+            return ret;
         }
         if (forValue instanceof NegateNode) {
             return ((NegateNode) forValue).getValue();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java	Wed Sep 24 14:22:01 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java	Wed Sep 24 14:29:43 2014 +0200
@@ -22,34 +22,21 @@
  */
 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.lir.gen.*;
 import com.oracle.graal.nodeinfo.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 /**
  * Binary negation of long or integer values.
  */
 @NodeInfo
-public class NotNode extends UnaryNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode {
-
-    @Override
-    public boolean inferStamp() {
-        return updateStamp(StampTool.not(getValue().stamp()));
-    }
-
-    @Override
-    public Constant evalConst(Constant... inputs) {
-        assert inputs.length == 1;
-        return Constant.forPrimitiveInt(PrimitiveStamp.getBits(stamp()), ~inputs[0].asLong());
-    }
+public class NotNode extends UnaryArithmeticNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode {
 
     /**
-     * Creates new NegateNode instance.
+     * Creates new NotNode instance.
      *
      * @param x the instruction producing the value that is input to this instruction
      */
@@ -58,13 +45,14 @@
     }
 
     protected NotNode(ValueNode x) {
-        super(StampTool.not(x.stamp()), x);
+        super(ArithmeticOpTable.forStamp(x.stamp()).getNot(), x);
     }
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
-        if (forValue.isConstant()) {
-            return ConstantNode.forConstant(evalConst(forValue.asConstant()), null);
+        ValueNode ret = super.canonical(tool, forValue);
+        if (ret != this) {
+            return ret;
         }
         if (forValue instanceof NotNode) {
             return ((NotNode) forValue).getValue();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Wed Sep 24 14:22:01 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java	Wed Sep 24 14:29:43 2014 +0200
@@ -30,52 +30,46 @@
 import com.oracle.graal.nodeinfo.*;
 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 OrNode extends BitLogicNode {
+public class OrNode extends BinaryArithmeticNode {
 
     public static OrNode create(ValueNode x, ValueNode y) {
         return USE_GENERATED_NODES ? new OrNodeGen(x, y) : new OrNode(x, y);
     }
 
     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(getX().stamp(), getY().stamp()));
-    }
-
-    @Override
-    public Constant evalConst(Constant... inputs) {
-        assert inputs.length == 2;
-        return Constant.forPrimitiveInt(PrimitiveStamp.getBits(stamp()), inputs[0].asLong() | inputs[1].asLong());
+        super(ArithmeticOpTable.forStamp(x.stamp()).getOr(), x, y);
     }
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        ValueNode ret = super.canonical(tool, forX, forY);
+        if (ret != this) {
+            return ret;
+        }
+
         if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
             return forX;
         }
         if (forX.isConstant() && !forY.isConstant()) {
             return create(forY, forX);
         }
-        if (forX.isConstant()) {
-            return ConstantNode.forPrimitive(stamp(), evalConst(forX.asConstant(), forY.asConstant()));
-        } else if (forY.isConstant()) {
-            long rawY = forY.asConstant().asLong();
-            long mask = CodeUtil.mask(PrimitiveStamp.getBits(stamp()));
-            if ((rawY & mask) == mask) {
-                return ConstantNode.forIntegerStamp(stamp(), mask);
-            }
-            if ((rawY & mask) == 0) {
+        if (forY.isConstant()) {
+            Constant c = forY.asConstant();
+            if (getOp().isNeutral(c)) {
                 return forX;
             }
-            return BinaryArithmeticNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY);
+
+            if (c.getKind().isNumericInteger()) {
+                long rawY = c.asLong();
+                long mask = CodeUtil.mask(PrimitiveStamp.getBits(stamp()));
+                if ((rawY & mask) == mask) {
+                    return ConstantNode.forIntegerStamp(stamp(), mask);
+                }
+            }
+            return reassociate(this, ValueNode.isConstantPredicate(), forX, forY);
         }
         return this;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnaryArithmeticNode.java	Wed Sep 24 14:29:43 2014 +0200
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.calc;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp;
+import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodeinfo.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+
+@NodeInfo
+public abstract class UnaryArithmeticNode extends UnaryNode implements ArithmeticLIRLowerable {
+
+    private final UnaryOp op;
+
+    protected UnaryArithmeticNode(UnaryOp op, ValueNode value) {
+        super(op.foldStamp(value.stamp()), value);
+        this.op = op;
+    }
+
+    public UnaryOp getOp() {
+        return op;
+    }
+
+    public Constant evalConst(Constant... inputs) {
+        assert inputs.length == 1;
+        return op.foldConstant(inputs[0]);
+    }
+
+    @Override
+    public boolean inferStamp() {
+        return updateStamp(op.foldStamp(getValue().stamp()));
+    }
+
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
+        if (forValue.isConstant()) {
+            return ConstantNode.forPrimitive(stamp(), op.foldConstant(forValue.asConstant()));
+        }
+        return this;
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Wed Sep 24 14:22:01 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java	Wed Sep 24 14:29:43 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,51 +30,47 @@
 import com.oracle.graal.nodeinfo.*;
 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 XorNode extends BitLogicNode {
+public class XorNode extends BinaryArithmeticNode {
 
     public static XorNode create(ValueNode x, ValueNode y) {
         return USE_GENERATED_NODES ? new XorNodeGen(x, y) : new XorNode(x, y);
     }
 
     protected XorNode(ValueNode x, ValueNode y) {
-        super(StampTool.xor(x.stamp(), y.stamp()), x, y);
+        super(ArithmeticOpTable.forStamp(x.stamp()).getXor(), x, y);
         assert x.stamp().isCompatible(y.stamp());
     }
 
     @Override
-    public boolean inferStamp() {
-        return updateStamp(StampTool.xor(getX().stamp(), getY().stamp()));
-    }
-
-    @Override
-    public Constant evalConst(Constant... inputs) {
-        assert inputs.length == 2;
-        return Constant.forPrimitiveInt(PrimitiveStamp.getBits(stamp()), inputs[0].asLong() ^ inputs[1].asLong());
-    }
-
-    @Override
     public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
+        ValueNode ret = super.canonical(tool, forX, forY);
+        if (ret != this) {
+            return ret;
+        }
+
         if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
-            return ConstantNode.forIntegerStamp(stamp(), 0);
+            return ConstantNode.forPrimitive(stamp(), getOp().getZero(forX.stamp()));
         }
         if (forX.isConstant() && !forY.isConstant()) {
             return XorNode.create(forY, forX);
         }
-        if (forX.isConstant()) {
-            return ConstantNode.forPrimitive(stamp(), evalConst(forX.asConstant(), forY.asConstant()));
-        } else if (forY.isConstant()) {
-            long rawY = forY.asConstant().asLong();
-            long mask = CodeUtil.mask(PrimitiveStamp.getBits(stamp()));
-            if ((rawY & mask) == 0) {
+        if (forY.isConstant()) {
+            Constant c = forY.asConstant();
+            if (getOp().isNeutral(c)) {
                 return forX;
-            } else if ((rawY & mask) == mask) {
-                return NotNode.create(forX);
             }
-            return BinaryArithmeticNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY);
+
+            if (c.getKind().isNumericInteger()) {
+                long rawY = c.asLong();
+                long mask = CodeUtil.mask(PrimitiveStamp.getBits(stamp()));
+                if ((rawY & mask) == mask) {
+                    return NotNode.create(forX);
+                }
+            }
+            return reassociate(this, ValueNode.isConstantPredicate(), forX, forY);
         }
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java	Wed Sep 24 14:22:01 2014 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java	Wed Sep 24 14:29:43 2014 +0200
@@ -34,16 +34,6 @@
  */
 public class StampTool {
 
-    public static Stamp not(Stamp stamp) {
-        if (stamp instanceof IntegerStamp) {
-            IntegerStamp integerStamp = (IntegerStamp) stamp;
-            int bits = integerStamp.getBits();
-            long defaultMask = CodeUtil.mask(bits);
-            return new IntegerStamp(bits, ~integerStamp.upperBound(), ~integerStamp.lowerBound(), (~integerStamp.upMask()) & defaultMask, (~integerStamp.downMask()) & defaultMask);
-        }
-        return stamp.unrestricted();
-    }
-
     public static Stamp meet(Collection<? extends StampProvider> values) {
         Iterator<? extends StampProvider> iterator = values.iterator();
         if (iterator.hasNext()) {
@@ -57,63 +47,6 @@
         }
     }
 
-    public static Stamp stampForMask(int bits, long downMask, long upMask) {
-        long lowerBound;
-        long upperBound;
-        if (((upMask >>> (bits - 1)) & 1) == 0) {
-            lowerBound = downMask;
-            upperBound = upMask;
-        } else if (((downMask >>> (bits - 1)) & 1) == 1) {
-            lowerBound = downMask;
-            upperBound = upMask;
-        } else {
-            lowerBound = downMask | (-1L << (bits - 1));
-            upperBound = CodeUtil.maxValue(bits) & upMask;
-        }
-        lowerBound = CodeUtil.convert(lowerBound, bits, false);
-        upperBound = CodeUtil.convert(upperBound, bits, false);
-        return new IntegerStamp(bits, lowerBound, upperBound, downMask, upMask);
-    }
-
-    public static Stamp and(Stamp stamp1, Stamp stamp2) {
-        if (stamp1 instanceof IntegerStamp && stamp2 instanceof IntegerStamp) {
-            return and((IntegerStamp) stamp1, (IntegerStamp) stamp2);
-        }
-        return StampFactory.illegal();
-    }
-
-    public static Stamp and(IntegerStamp stamp1, IntegerStamp stamp2) {
-        assert stamp1.getBits() == stamp2.getBits();
-        return stampForMask(stamp1.getBits(), stamp1.downMask() & stamp2.downMask(), stamp1.upMask() & stamp2.upMask());
-    }
-
-    public static Stamp or(Stamp stamp1, Stamp stamp2) {
-        if (stamp1 instanceof IntegerStamp && stamp2 instanceof IntegerStamp) {
-            return or((IntegerStamp) stamp1, (IntegerStamp) stamp2);
-        }
-        return StampFactory.illegal();
-    }
-
-    public static Stamp or(IntegerStamp stamp1, IntegerStamp stamp2) {
-        assert stamp1.getBits() == stamp2.getBits();
-        return stampForMask(stamp1.getBits(), stamp1.downMask() | stamp2.downMask(), stamp1.upMask() | stamp2.upMask());
-    }
-
-    public static Stamp xor(Stamp stamp1, Stamp stamp2) {
-        if (stamp1 instanceof IntegerStamp && stamp2 instanceof IntegerStamp) {
-            return xor((IntegerStamp) stamp1, (IntegerStamp) stamp2);
-        }
-        return StampFactory.illegal();
-    }
-
-    public static Stamp xor(IntegerStamp stamp1, IntegerStamp stamp2) {
-        assert stamp1.getBits() == stamp2.getBits();
-        long variableBits = (stamp1.downMask() ^ stamp1.upMask()) | (stamp2.downMask() ^ stamp2.upMask());
-        long newDownMask = (stamp1.downMask() ^ stamp2.downMask()) & ~variableBits;
-        long newUpMask = (stamp1.downMask() ^ stamp2.downMask()) | variableBits;
-        return stampForMask(stamp1.getBits(), newDownMask, newUpMask);
-    }
-
     public static Stamp rightShift(Stamp value, Stamp shift) {
         if (value instanceof IntegerStamp && shift instanceof IntegerStamp) {
             return rightShift((IntegerStamp) value, (IntegerStamp) shift);
@@ -134,7 +67,7 @@
             return new IntegerStamp(bits, value.lowerBound() >> shiftCount, value.upperBound() >> shiftCount, downMask, upMask);
         }
         long mask = IntegerStamp.upMaskFor(bits, value.lowerBound(), value.upperBound());
-        return stampForMask(bits, 0, mask);
+        return IntegerStamp.stampForMask(bits, 0, mask);
     }
 
     public static Stamp unsignedRightShift(Stamp value, Stamp shift) {
@@ -158,7 +91,7 @@
             }
         }
         long mask = IntegerStamp.upMaskFor(bits, value.lowerBound(), value.upperBound());
-        return stampForMask(bits, 0, mask);
+        return IntegerStamp.stampForMask(bits, 0, mask);
     }
 
     public static Stamp leftShift(Stamp value, Stamp shift) {
@@ -197,7 +130,7 @@
                     upMask |= value.upMask() << (i & shiftMask);
                 }
             }
-            Stamp result = stampForMask(bits, downMask, upMask & defaultMask);
+            Stamp result = IntegerStamp.stampForMask(bits, downMask, upMask & defaultMask);
             return result;
         }
         return value.unrestricted();
@@ -231,7 +164,7 @@
             if (inputStamp.lowerBound() < 0 && inputStamp.upperBound() >= 0) {
                 // signed range including 0 and -1
                 // after sign extension, the whole range from 0 to MAX_INT is possible
-                return stampForMask(resultBits, downMask, upMask);
+                return IntegerStamp.stampForMask(resultBits, downMask, upMask);
             }
 
             long lowerBound = CodeUtil.zeroExtend(inputStamp.lowerBound(), inputBits);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java	Wed Sep 24 14:22:01 2014 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java	Wed Sep 24 14:29:43 2014 +0200
@@ -30,7 +30,6 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.nodes.type.*;
 
 @NodeInfo
 public class ReverseBytesNode extends UnaryNode implements LIRLowerable {
@@ -50,9 +49,9 @@
         Stamp newStamp;
         if (getKind() == Kind.Int) {
             long mask = CodeUtil.mask(Kind.Int.getBitCount());
-            newStamp = StampTool.stampForMask(valueStamp.getBits(), reverse((int) valueStamp.downMask()) & mask, reverse((int) valueStamp.upMask()) & mask);
+            newStamp = IntegerStamp.stampForMask(valueStamp.getBits(), reverse((int) valueStamp.downMask()) & mask, reverse((int) valueStamp.upMask()) & mask);
         } else if (getKind() == Kind.Long) {
-            newStamp = StampTool.stampForMask(valueStamp.getBits(), reverse(valueStamp.downMask()), reverse(valueStamp.upMask()));
+            newStamp = IntegerStamp.stampForMask(valueStamp.getBits(), reverse(valueStamp.downMask()), reverse(valueStamp.upMask()));
         } else {
             return false;
         }