changeset 13999:f2b300c6e621

Refactor Stamp hierarchy.
author Roland Schatz <roland.schatz@oracle.com>
date Thu, 20 Feb 2014 14:42:01 +0100
parents aabdacb9555c
children 958c99d0790c
files graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AbstractMethodHandleNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/GraphKit.java graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.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/ValueNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/FloatStamp.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/GenericStamp.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IllegalStamp.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/PrimitiveStamp.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/Stamp.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/InferStamps.java graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java
diffstat 19 files changed, 587 insertions(+), 253 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java	Thu Feb 20 12:08:04 2014 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Kind.java	Thu Feb 20 14:42:01 2014 +0100
@@ -129,6 +129,15 @@
     }
 
     /**
+     * Checks whether this type is a Java primitive type representing an unsigned number.
+     * 
+     * @return {@code true} if the kind is {@link #Boolean} or {@link #Char}.
+     */
+    public boolean isUnsigned() {
+        return this == Kind.Boolean || this == Kind.Char;
+    }
+
+    /**
      * Checks whether this type is a Java primitive type representing a floating point number.
      * 
      * @return {@code true} if this is {@link #Float} or {@link #Double}.
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Thu Feb 20 12:08:04 2014 +0100
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Thu Feb 20 14:42:01 2014 +0100
@@ -64,6 +64,7 @@
 import com.oracle.graal.lir.amd64.AMD64Move.StackLeaOp;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.util.*;
 
 /**
@@ -353,7 +354,7 @@
 
     @Override
     public void emitNullCheck(ValueNode v, DeoptimizingNode deoping) {
-        assert v.kind() == Kind.Object;
+        assert v.stamp() instanceof ObjectStamp;
         append(new AMD64Move.NullCheckOp(load(operand(v)), state(deoping)));
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java	Thu Feb 20 12:08:04 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/LoadJavaMirrorWithKlassPhase.java	Thu Feb 20 14:42:01 2014 +0100
@@ -63,7 +63,7 @@
             ConstantNode klassNode = ConstantNode.forConstant(klass, metaAccess, graph);
 
             Stamp stamp = StampFactory.exactNonNull(metaAccess.lookupJavaType(Class.class));
-            LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, stamp.kind(), classMirrorOffset, graph);
+            LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, Kind.Object, classMirrorOffset, graph);
             FloatingReadNode freadNode = graph.unique(new FloatingReadNode(klassNode, location, null, stamp));
             return freadNode;
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AbstractMethodHandleNode.java	Thu Feb 20 12:08:04 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AbstractMethodHandleNode.java	Thu Feb 20 14:42:01 2014 +0100
@@ -45,6 +45,7 @@
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.java.SelfReplacingMethodCallTargetNode;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.nodes.type.GenericStamp.*;
 import com.oracle.graal.replacements.nodes.MacroNode;
 
 /**
@@ -281,7 +282,7 @@
         // invoker's stamp would be wrong because it's a less concrete type
         // (usually java.lang.Object).
         InvokeNode invoke;
-        if (callTarget.returnStamp().kind() != stamp().kind()) {
+        if (stamp() instanceof GenericStamp && ((GenericStamp) stamp()).type() == GenericStampType.Void) {
             invoke = new InvokeNode(callTarget, getBci(), stamp());
         } else {
             invoke = new InvokeNode(callTarget, getBci());
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/GraphKit.java	Thu Feb 20 12:08:04 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/GraphKit.java	Thu Feb 20 14:42:01 2014 +0100
@@ -123,7 +123,7 @@
         }
         for (int i = 0; i != args.length; i++) {
             Kind expected = signature.getParameterKind(i).getStackKind();
-            Kind actual = args[i].stamp().kind();
+            Kind actual = args[i].stamp().getStackKind();
             if (expected != actual) {
                 throw new AssertionError(graph + ": wrong kind of value for argument " + i + " of calls to " + method + " [" + actual + " != " + expected + "]");
             }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java	Thu Feb 20 12:08:04 2014 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java	Thu Feb 20 14:42:01 2014 +0100
@@ -90,7 +90,7 @@
             if (kind == Kind.Object && type instanceof ResolvedJavaType) {
                 stamp = StampFactory.declared((ResolvedJavaType) type);
             } else {
-                stamp = StampFactory.forKind(type.getKind());
+                stamp = StampFactory.forKind(kind);
             }
             ParameterNode param = graph.unique(new ParameterNode(index, stamp));
             storeLocal(javaIndex, param);
--- a/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java	Thu Feb 20 12:08:04 2014 +0100
+++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java	Thu Feb 20 14:42:01 2014 +0100
@@ -44,83 +44,83 @@
 
     @Test
     public void testBooleanConstant() {
-        assertEquals(new IntegerStamp(Kind.Int, 1, 1, 0x1, 0x1), ConstantNode.forBoolean(true, graph).stamp());
-        assertEquals(new IntegerStamp(Kind.Int, 0, 0, 0x0, 0x0), ConstantNode.forBoolean(false, graph).stamp());
+        assertEquals(new IntegerStamp(32, false, 1, 1, 0x1, 0x1), ConstantNode.forBoolean(true, graph).stamp());
+        assertEquals(new IntegerStamp(32, false, 0, 0, 0x0, 0x0), ConstantNode.forBoolean(false, graph).stamp());
     }
 
     @Test
     public void testByteConstant() {
-        assertEquals(new IntegerStamp(Kind.Int, 0, 0, 0x0, 0x0), ConstantNode.forByte((byte) 0, graph).stamp());
-        assertEquals(new IntegerStamp(Kind.Int, 16, 16, 0x10, 0x10), ConstantNode.forByte((byte) 16, graph).stamp());
-        assertEquals(new IntegerStamp(Kind.Int, -16, -16, 0xfffffff0L, 0xfffffff0L), ConstantNode.forByte((byte) -16, graph).stamp());
-        assertEquals(new IntegerStamp(Kind.Int, 127, 127, 0x7f, 0x7f), ConstantNode.forByte((byte) 127, graph).stamp());
-        assertEquals(new IntegerStamp(Kind.Int, -128, -128, 0xffffff80L, 0xffffff80L), ConstantNode.forByte((byte) -128, graph).stamp());
+        assertEquals(new IntegerStamp(32, false, 0, 0, 0x0, 0x0), ConstantNode.forByte((byte) 0, graph).stamp());
+        assertEquals(new IntegerStamp(32, false, 16, 16, 0x10, 0x10), ConstantNode.forByte((byte) 16, graph).stamp());
+        assertEquals(new IntegerStamp(32, false, -16, -16, 0xfffffff0L, 0xfffffff0L), ConstantNode.forByte((byte) -16, graph).stamp());
+        assertEquals(new IntegerStamp(32, false, 127, 127, 0x7f, 0x7f), ConstantNode.forByte((byte) 127, graph).stamp());
+        assertEquals(new IntegerStamp(32, false, -128, -128, 0xffffff80L, 0xffffff80L), ConstantNode.forByte((byte) -128, graph).stamp());
     }
 
     @Test
     public void testShortConstant() {
-        assertEquals(new IntegerStamp(Kind.Int, 0, 0, 0x0, 0x0), ConstantNode.forShort((short) 0, graph).stamp());
-        assertEquals(new IntegerStamp(Kind.Int, 128, 128, 0x80, 0x80), ConstantNode.forShort((short) 128, graph).stamp());
-        assertEquals(new IntegerStamp(Kind.Int, -128, -128, 0xffffff80L, 0xffffff80L), ConstantNode.forShort((short) -128, graph).stamp());
-        assertEquals(new IntegerStamp(Kind.Int, 32767, 32767, 0x7fff, 0x7fff), ConstantNode.forShort((short) 32767, graph).stamp());
-        assertEquals(new IntegerStamp(Kind.Int, -32768, -32768, 0xffff8000L, 0xffff8000L), ConstantNode.forShort((short) -32768, graph).stamp());
+        assertEquals(new IntegerStamp(32, false, 0, 0, 0x0, 0x0), ConstantNode.forShort((short) 0, graph).stamp());
+        assertEquals(new IntegerStamp(32, false, 128, 128, 0x80, 0x80), ConstantNode.forShort((short) 128, graph).stamp());
+        assertEquals(new IntegerStamp(32, false, -128, -128, 0xffffff80L, 0xffffff80L), ConstantNode.forShort((short) -128, graph).stamp());
+        assertEquals(new IntegerStamp(32, false, 32767, 32767, 0x7fff, 0x7fff), ConstantNode.forShort((short) 32767, graph).stamp());
+        assertEquals(new IntegerStamp(32, false, -32768, -32768, 0xffff8000L, 0xffff8000L), ConstantNode.forShort((short) -32768, graph).stamp());
     }
 
     @Test
     public void testCharConstant() {
-        assertEquals(new IntegerStamp(Kind.Int, 0, 0, 0x0, 0x0), ConstantNode.forChar((char) 0, graph).stamp());
-        assertEquals(new IntegerStamp(Kind.Int, 'A', 'A', 'A', 'A'), ConstantNode.forChar('A', graph).stamp());
-        assertEquals(new IntegerStamp(Kind.Int, 128, 128, 0x80, 0x80), ConstantNode.forChar((char) 128, graph).stamp());
-        assertEquals(new IntegerStamp(Kind.Int, 65535, 65535, 0xffff, 0xffff), ConstantNode.forChar((char) 65535, graph).stamp());
+        assertEquals(new IntegerStamp(32, false, 0, 0, 0x0, 0x0), ConstantNode.forChar((char) 0, graph).stamp());
+        assertEquals(new IntegerStamp(32, false, 'A', 'A', 'A', 'A'), ConstantNode.forChar('A', graph).stamp());
+        assertEquals(new IntegerStamp(32, false, 128, 128, 0x80, 0x80), ConstantNode.forChar((char) 128, graph).stamp());
+        assertEquals(new IntegerStamp(32, false, 65535, 65535, 0xffff, 0xffff), ConstantNode.forChar((char) 65535, graph).stamp());
     }
 
     @Test
     public void testIntConstant() {
-        assertEquals(new IntegerStamp(Kind.Int, 0, 0, 0x0, 0x0), ConstantNode.forInt(0, graph).stamp());
-        assertEquals(new IntegerStamp(Kind.Int, 128, 128, 0x80, 0x80), ConstantNode.forInt(128, graph).stamp());
-        assertEquals(new IntegerStamp(Kind.Int, -128, -128, 0xffffff80L, 0xffffff80L), ConstantNode.forInt(-128, graph).stamp());
-        assertEquals(new IntegerStamp(Kind.Int, Integer.MAX_VALUE, Integer.MAX_VALUE, 0x7fffffff, 0x7fffffff), ConstantNode.forInt(Integer.MAX_VALUE, graph).stamp());
-        assertEquals(new IntegerStamp(Kind.Int, Integer.MIN_VALUE, Integer.MIN_VALUE, 0x80000000L, 0x80000000L), ConstantNode.forInt(Integer.MIN_VALUE, graph).stamp());
+        assertEquals(new IntegerStamp(32, false, 0, 0, 0x0, 0x0), ConstantNode.forInt(0, graph).stamp());
+        assertEquals(new IntegerStamp(32, false, 128, 128, 0x80, 0x80), ConstantNode.forInt(128, graph).stamp());
+        assertEquals(new IntegerStamp(32, false, -128, -128, 0xffffff80L, 0xffffff80L), ConstantNode.forInt(-128, graph).stamp());
+        assertEquals(new IntegerStamp(32, false, Integer.MAX_VALUE, Integer.MAX_VALUE, 0x7fffffff, 0x7fffffff), ConstantNode.forInt(Integer.MAX_VALUE, graph).stamp());
+        assertEquals(new IntegerStamp(32, false, Integer.MIN_VALUE, Integer.MIN_VALUE, 0x80000000L, 0x80000000L), ConstantNode.forInt(Integer.MIN_VALUE, graph).stamp());
     }
 
     @Test
     public void testLongConstant() {
-        assertEquals(new IntegerStamp(Kind.Long, 0, 0, 0x0, 0x0), ConstantNode.forLong(0, graph).stamp());
-        assertEquals(new IntegerStamp(Kind.Long, 128, 128, 0x80, 0x80), ConstantNode.forLong(128, graph).stamp());
-        assertEquals(new IntegerStamp(Kind.Long, -128, -128, 0xffffffffffffff80L, 0xffffffffffffff80L), ConstantNode.forLong(-128, graph).stamp());
-        assertEquals(new IntegerStamp(Kind.Long, Long.MAX_VALUE, Long.MAX_VALUE, 0x7fffffffffffffffL, 0x7fffffffffffffffL), ConstantNode.forLong(Long.MAX_VALUE, graph).stamp());
-        assertEquals(new IntegerStamp(Kind.Long, Long.MIN_VALUE, Long.MIN_VALUE, 0x8000000000000000L, 0x8000000000000000L), ConstantNode.forLong(Long.MIN_VALUE, graph).stamp());
+        assertEquals(new IntegerStamp(64, false, 0, 0, 0x0, 0x0), ConstantNode.forLong(0, graph).stamp());
+        assertEquals(new IntegerStamp(64, false, 128, 128, 0x80, 0x80), ConstantNode.forLong(128, graph).stamp());
+        assertEquals(new IntegerStamp(64, false, -128, -128, 0xffffffffffffff80L, 0xffffffffffffff80L), ConstantNode.forLong(-128, graph).stamp());
+        assertEquals(new IntegerStamp(64, false, Long.MAX_VALUE, Long.MAX_VALUE, 0x7fffffffffffffffL, 0x7fffffffffffffffL), ConstantNode.forLong(Long.MAX_VALUE, graph).stamp());
+        assertEquals(new IntegerStamp(64, false, Long.MIN_VALUE, Long.MIN_VALUE, 0x8000000000000000L, 0x8000000000000000L), ConstantNode.forLong(Long.MIN_VALUE, graph).stamp());
     }
 
     @Test
     public void testPositiveRanges() {
-        assertEquals(new IntegerStamp(Kind.Int, 0, 0, 0, 0), StampFactory.forInteger(Kind.Int, 0, 0));
-        assertEquals(new IntegerStamp(Kind.Int, 0, 1, 0, 1), StampFactory.forInteger(Kind.Int, 0, 1));
-        assertEquals(new IntegerStamp(Kind.Int, 0, 0x123, 0, 0x1ff), StampFactory.forInteger(Kind.Int, 0, 0x123));
-        assertEquals(new IntegerStamp(Kind.Int, 0x120, 0x123, 0x120, 0x123), StampFactory.forInteger(Kind.Int, 0x120, 0x123));
-        assertEquals(new IntegerStamp(Kind.Int, 10000, 15000, 0x2000, 0x3fff), StampFactory.forInteger(Kind.Int, 10000, 15000));
-        assertEquals(new IntegerStamp(Kind.Long, 0, 1, 0, 1), StampFactory.forInteger(Kind.Long, 0, 1));
-        assertEquals(new IntegerStamp(Kind.Long, 10000, 15000, 0x2000, 0x3fff), StampFactory.forInteger(Kind.Long, 10000, 15000));
-        assertEquals(new IntegerStamp(Kind.Long, 140000000000L, 150000000000L, 0x2000000000L, 0x23ffffffffL), StampFactory.forInteger(Kind.Long, 140000000000L, 150000000000L));
+        assertEquals(new IntegerStamp(32, false, 0, 0, 0, 0), StampFactory.forInteger(Kind.Int, 0, 0));
+        assertEquals(new IntegerStamp(32, false, 0, 1, 0, 1), StampFactory.forInteger(Kind.Int, 0, 1));
+        assertEquals(new IntegerStamp(32, false, 0, 0x123, 0, 0x1ff), StampFactory.forInteger(Kind.Int, 0, 0x123));
+        assertEquals(new IntegerStamp(32, false, 0x120, 0x123, 0x120, 0x123), StampFactory.forInteger(Kind.Int, 0x120, 0x123));
+        assertEquals(new IntegerStamp(32, false, 10000, 15000, 0x2000, 0x3fff), StampFactory.forInteger(Kind.Int, 10000, 15000));
+        assertEquals(new IntegerStamp(64, false, 0, 1, 0, 1), StampFactory.forInteger(Kind.Long, 0, 1));
+        assertEquals(new IntegerStamp(64, false, 10000, 15000, 0x2000, 0x3fff), StampFactory.forInteger(Kind.Long, 10000, 15000));
+        assertEquals(new IntegerStamp(64, false, 140000000000L, 150000000000L, 0x2000000000L, 0x23ffffffffL), StampFactory.forInteger(Kind.Long, 140000000000L, 150000000000L));
     }
 
     @Test
     public void testNegativeRanges() {
-        assertEquals(new IntegerStamp(Kind.Int, -2, -1, 0xfffffffeL, 0xffffffffL), StampFactory.forInteger(Kind.Int, -2, -1));
-        assertEquals(new IntegerStamp(Kind.Int, -20, -10, 0xffffffe0L, 0xffffffffL), StampFactory.forInteger(Kind.Int, -20, -10));
-        assertEquals(new IntegerStamp(Kind.Int, -10000, 0, 0, 0xffffffffL), StampFactory.forInteger(Kind.Int, -10000, 0));
-        assertEquals(new IntegerStamp(Kind.Int, -10000, -1, 0xffffc000L, 0xffffffffL), StampFactory.forInteger(Kind.Int, -10000, -1));
-        assertEquals(new IntegerStamp(Kind.Int, -10010, -10000, 0xffffd8e0L, 0xffffd8ffL), StampFactory.forInteger(Kind.Int, -10010, -10000));
-        assertEquals(new IntegerStamp(Kind.Long, -2, -1, 0xfffffffffffffffeL, 0xffffffffffffffffL), StampFactory.forInteger(Kind.Long, -2, -1));
-        assertEquals(new IntegerStamp(Kind.Long, -10010, -10000, 0xffffffffffffd8e0L, 0xffffffffffffd8ffL), StampFactory.forInteger(Kind.Long, -10010, -10000));
-        assertEquals(new IntegerStamp(Kind.Long, -150000000000L, -140000000000L, 0xffffffdc00000000L, 0xffffffdfffffffffL), StampFactory.forInteger(Kind.Long, -150000000000L, -140000000000L));
+        assertEquals(new IntegerStamp(32, false, -2, -1, 0xfffffffeL, 0xffffffffL), StampFactory.forInteger(Kind.Int, -2, -1));
+        assertEquals(new IntegerStamp(32, false, -20, -10, 0xffffffe0L, 0xffffffffL), StampFactory.forInteger(Kind.Int, -20, -10));
+        assertEquals(new IntegerStamp(32, false, -10000, 0, 0, 0xffffffffL), StampFactory.forInteger(Kind.Int, -10000, 0));
+        assertEquals(new IntegerStamp(32, false, -10000, -1, 0xffffc000L, 0xffffffffL), StampFactory.forInteger(Kind.Int, -10000, -1));
+        assertEquals(new IntegerStamp(32, false, -10010, -10000, 0xffffd8e0L, 0xffffd8ffL), StampFactory.forInteger(Kind.Int, -10010, -10000));
+        assertEquals(new IntegerStamp(64, false, -2, -1, 0xfffffffffffffffeL, 0xffffffffffffffffL), StampFactory.forInteger(Kind.Long, -2, -1));
+        assertEquals(new IntegerStamp(64, false, -10010, -10000, 0xffffffffffffd8e0L, 0xffffffffffffd8ffL), StampFactory.forInteger(Kind.Long, -10010, -10000));
+        assertEquals(new IntegerStamp(64, false, -150000000000L, -140000000000L, 0xffffffdc00000000L, 0xffffffdfffffffffL), StampFactory.forInteger(Kind.Long, -150000000000L, -140000000000L));
     }
 
     @Test
     public void testMixedRanges() {
-        assertEquals(new IntegerStamp(Kind.Int, -1, 0, 0, 0xffffffffL), StampFactory.forInteger(Kind.Int, -1, 0));
-        assertEquals(new IntegerStamp(Kind.Int, -10000, 1000, 0, 0xffffffffL), StampFactory.forInteger(Kind.Int, -10000, 1000));
-        assertEquals(new IntegerStamp(Kind.Long, -10000, 1000, 0, 0xffffffffffffffffL), StampFactory.forInteger(Kind.Long, -10000, 1000));
+        assertEquals(new IntegerStamp(32, false, -1, 0, 0, 0xffffffffL), StampFactory.forInteger(Kind.Int, -1, 0));
+        assertEquals(new IntegerStamp(32, false, -10000, 1000, 0, 0xffffffffL), StampFactory.forInteger(Kind.Int, -10000, 1000));
+        assertEquals(new IntegerStamp(64, false, -10000, 1000, 0, 0xffffffffffffffffL), StampFactory.forInteger(Kind.Long, -10000, 1000));
     }
 
     @Test
@@ -159,15 +159,15 @@
 
     @Test
     public void testXor() {
-        assertEquals(new IntegerStamp(Kind.Int, 0, 0xff, 0, 0xff), StampTool.xor(new IntegerStamp(Kind.Int, 0, 0, 0, 0), new IntegerStamp(Kind.Int, 0, 0xff, 0, 0xff)));
-        assertEquals(new IntegerStamp(Kind.Int, 0x10, 0x1f, 0x10, 0x1f), StampTool.xor(new IntegerStamp(Kind.Int, 0, 0, 0, 0), new IntegerStamp(Kind.Int, 0x10, 0x1f, 0x10, 0x1f)));
-        assertEquals(new IntegerStamp(Kind.Int, 0x0, 0xf, 0x0, 0xf), StampTool.xor(new IntegerStamp(Kind.Int, 0x10, 0x10, 0x10, 0x10), new IntegerStamp(Kind.Int, 0x10, 0x1f, 0x10, 0x1f)));
-        assertEquals(new IntegerStamp(Kind.Int, 0x10, 0x1f, 0x10, 0x1f), StampTool.xor(new IntegerStamp(Kind.Int, 0x10, 0x10, 0x10, 0x10), new IntegerStamp(Kind.Int, 0x0, 0xf, 0x0, 0xf)));
+        assertEquals(new IntegerStamp(32, false, 0, 0xff, 0, 0xff), StampTool.xor(new IntegerStamp(32, false, 0, 0, 0, 0), new IntegerStamp(32, false, 0, 0xff, 0, 0xff)));
+        assertEquals(new IntegerStamp(32, false, 0x10, 0x1f, 0x10, 0x1f), StampTool.xor(new IntegerStamp(32, false, 0, 0, 0, 0), new IntegerStamp(32, false, 0x10, 0x1f, 0x10, 0x1f)));
+        assertEquals(new IntegerStamp(32, false, 0x0, 0xf, 0x0, 0xf), StampTool.xor(new IntegerStamp(32, false, 0x10, 0x10, 0x10, 0x10), new IntegerStamp(32, false, 0x10, 0x1f, 0x10, 0x1f)));
+        assertEquals(new IntegerStamp(32, false, 0x10, 0x1f, 0x10, 0x1f), StampTool.xor(new IntegerStamp(32, false, 0x10, 0x10, 0x10, 0x10), new IntegerStamp(32, false, 0x0, 0xf, 0x0, 0xf)));
     }
 
     @Test
     public void testNot() {
-        assertEquals(new IntegerStamp(Kind.Int, -11, -1, 0xffff_fff0L, 0xffff_ffffL), StampTool.not(new IntegerStamp(Kind.Int, 0, 10, 0, 0xf)));
+        assertEquals(new IntegerStamp(32, false, -11, -1, 0xffff_fff0L, 0xffff_ffffL), StampTool.not(new IntegerStamp(32, false, 0, 10, 0, 0xf)));
     }
 
     @Test
@@ -258,6 +258,6 @@
 
     @Test
     public void testAnd() {
-        assertEquals(new IntegerStamp(Kind.Int, Integer.MIN_VALUE, 0x40000000L, 0, 0xc0000000L), StampTool.and(StampFactory.forKind(Kind.Int), StampFactory.forConstant(Constant.forInt(0xc0000000))));
+        assertEquals(new IntegerStamp(32, false, Integer.MIN_VALUE, 0x40000000L, 0, 0xc0000000L), StampTool.and(StampFactory.forKind(Kind.Int), StampFactory.forConstant(Constant.forInt(0xc0000000))));
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Thu Feb 20 12:08:04 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java	Thu Feb 20 14:42:01 2014 +0100
@@ -80,7 +80,7 @@
     }
 
     public final Kind kind() {
-        return stamp().kind();
+        return stamp().getStackKind();
     }
 
     /**
@@ -126,13 +126,6 @@
         return null;
     }
 
-    @Override
-    public boolean verify() {
-        assertTrue(kind() != null, "Should have a valid kind");
-        assertTrue(kind() == kind().getStackKind(), "Should have a stack kind : %s", kind());
-        return super.verify();
-    }
-
     public ValueNode asNode() {
         return this;
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/FloatStamp.java	Thu Feb 20 12:08:04 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/FloatStamp.java	Thu Feb 20 14:42:01 2014 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,20 +23,20 @@
 package com.oracle.graal.nodes.type;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
 
-public class FloatStamp extends Stamp {
+public class FloatStamp extends PrimitiveStamp {
 
     private final double lowerBound;
     private final double upperBound;
     private final boolean nonNaN;
 
-    protected FloatStamp(Kind kind) {
-        this(kind, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, false);
-        assert kind == Kind.Float || kind == Kind.Double;
+    protected FloatStamp(int bits) {
+        this(bits, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, false);
     }
 
-    protected FloatStamp(Kind kind, double lowerBound, double upperBound, boolean nonNaN) {
-        super(kind);
+    protected FloatStamp(int bits, double lowerBound, double upperBound, boolean nonNaN) {
+        super(bits);
         assert (!nonNaN && Double.isNaN(lowerBound) && Double.isNaN(upperBound)) || lowerBound <= upperBound;
         this.lowerBound = lowerBound;
         this.upperBound = upperBound;
@@ -44,8 +44,29 @@
     }
 
     @Override
+    public Stamp unrestricted() {
+        return new FloatStamp(getBits());
+    }
+
+    @Override
+    public Kind getStackKind() {
+        if (getBits() > 32) {
+            return Kind.Double;
+        } else {
+            return Kind.Float;
+        }
+    }
+
+    @Override
     public ResolvedJavaType javaType(MetaAccessProvider metaAccess) {
-        return metaAccess.lookupJavaType(kind().toJavaClass());
+        switch (getBits()) {
+            case 32:
+                return metaAccess.lookupJavaType(Float.TYPE);
+            case 64:
+                return metaAccess.lookupJavaType(Double.TYPE);
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
     }
 
     /**
@@ -81,7 +102,8 @@
     @Override
     public String toString() {
         StringBuilder str = new StringBuilder();
-        str.append(kind().getTypeChar());
+        str.append('f');
+        str.append(getBits());
         str.append(nonNaN ? "!" : "");
         if (lowerBound == upperBound) {
             str.append(" [").append(lowerBound).append(']');
@@ -103,7 +125,7 @@
             return StampFactory.illegal(Kind.Illegal);
         }
         FloatStamp other = (FloatStamp) otherStamp;
-        assert kind() == other.kind();
+        assert getBits() == other.getBits();
         double meetUpperBound = Math.max(upperBound, other.upperBound);
         double meetLowerBound = Math.min(lowerBound, other.lowerBound);
         boolean meetNonNaN = nonNaN && other.nonNaN;
@@ -112,7 +134,7 @@
         } else if (meetLowerBound == other.lowerBound && meetUpperBound == other.upperBound && meetNonNaN == other.nonNaN) {
             return other;
         } else {
-            return new FloatStamp(kind(), meetLowerBound, meetUpperBound, meetNonNaN);
+            return new FloatStamp(getBits(), meetLowerBound, meetUpperBound, meetNonNaN);
         }
     }
 
@@ -128,7 +150,7 @@
             return StampFactory.illegal(Kind.Illegal);
         }
         FloatStamp other = (FloatStamp) otherStamp;
-        assert kind() == other.kind();
+        assert getBits() == other.getBits();
         double joinUpperBound = Math.min(upperBound, other.upperBound);
         double joinLowerBound = Math.max(lowerBound, other.lowerBound);
         boolean joinNonNaN = nonNaN || other.nonNaN;
@@ -137,9 +159,9 @@
         } else if (joinLowerBound == other.lowerBound && joinUpperBound == other.upperBound && joinNonNaN == other.nonNaN) {
             return other;
         } else if (joinLowerBound > joinUpperBound) {
-            return StampFactory.illegal(kind());
+            return illegal();
         } else {
-            return new FloatStamp(kind(), joinLowerBound, joinUpperBound, joinNonNaN);
+            return new FloatStamp(getBits(), joinLowerBound, joinUpperBound, joinNonNaN);
         }
     }
 
@@ -148,7 +170,7 @@
         final int prime = 31;
         int result = 1;
         long temp;
-        result = prime * result + kind().hashCode();
+        result = prime * result + super.hashCode();
         temp = Double.doubleToLongBits(lowerBound);
         result = prime * result + (int) (temp ^ (temp >>> 32));
         result = prime * result + (nonNaN ? 1231 : 1237);
@@ -158,17 +180,26 @@
     }
 
     @Override
+    public boolean isCompatible(Stamp stamp) {
+        if (this == stamp) {
+            return true;
+        }
+        if (stamp instanceof FloatStamp) {
+            FloatStamp other = (FloatStamp) stamp;
+            return getBits() == other.getBits();
+        }
+        return false;
+    }
+
+    @Override
     public boolean equals(Object obj) {
         if (this == obj) {
             return true;
         }
-        if (obj == null || getClass() != obj.getClass()) {
+        if (obj == null || getClass() != obj.getClass() || !super.equals(obj)) {
             return false;
         }
         FloatStamp other = (FloatStamp) obj;
-        if (kind() != other.kind()) {
-            return false;
-        }
         if (Double.doubleToLongBits(lowerBound) != Double.doubleToLongBits(other.lowerBound)) {
             return false;
         }
@@ -184,10 +215,10 @@
     @Override
     public Constant asConstant() {
         if (nonNaN && lowerBound == upperBound) {
-            switch (kind()) {
-                case Float:
+            switch (getBits()) {
+                case 32:
                     return Constant.forFloat((float) lowerBound);
-                case Double:
+                case 64:
                     return Constant.forDouble(lowerBound);
             }
         }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/GenericStamp.java	Thu Feb 20 12:08:04 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/GenericStamp.java	Thu Feb 20 14:42:01 2014 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,7 +33,6 @@
     private final GenericStampType type;
 
     protected GenericStamp(GenericStampType type) {
-        super(type == GenericStampType.Void ? Kind.Void : Kind.Illegal);
         this.type = type;
     }
 
@@ -42,8 +41,23 @@
     }
 
     @Override
+    public Stamp unrestricted() {
+        return this;
+    }
+
+    @Override
+    public Kind getStackKind() {
+        if (type == GenericStampType.Void) {
+            return Kind.Void;
+        } else {
+            return Kind.Illegal;
+        }
+    }
+
+    @Override
     public ResolvedJavaType javaType(MetaAccessProvider metaAccess) {
-        return metaAccess.lookupJavaType(kind().toJavaClass());
+        assert type == GenericStampType.Void;
+        return metaAccess.lookupJavaType(Void.TYPE);
     }
 
     @Override
@@ -79,6 +93,18 @@
     }
 
     @Override
+    public boolean isCompatible(Stamp stamp) {
+        if (this == stamp) {
+            return true;
+        }
+        if (stamp instanceof GenericStamp) {
+            GenericStamp other = (GenericStamp) stamp;
+            return type == other.type;
+        }
+        return false;
+    }
+
+    @Override
     public int hashCode() {
         return 31 + ((type == null) ? 0 : type.hashCode());
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IllegalStamp.java	Thu Feb 20 12:08:04 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IllegalStamp.java	Thu Feb 20 14:42:01 2014 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,12 +26,33 @@
 
 /**
  * This stamp represents the illegal type. Values with this type can not exist at run time.
- * 
  */
-public final class IllegalStamp extends Stamp {
+public final class IllegalStamp extends PrimitiveStamp {
+
+    private final Kind kind;
 
     public IllegalStamp(Kind kind) {
-        super(kind);
+        super(0);
+        this.kind = kind;
+    }
+
+    public Kind kind() {
+        return kind;
+    }
+
+    @Override
+    public Kind getStackKind() {
+        return kind;
+    }
+
+    @Override
+    public Stamp unrestricted() {
+        return this;
+    }
+
+    @Override
+    public Stamp illegal() {
+        return this;
     }
 
     @Override
@@ -50,6 +71,18 @@
     }
 
     @Override
+    public boolean isCompatible(Stamp stamp) {
+        if (this == stamp) {
+            return true;
+        }
+        if (stamp instanceof IllegalStamp) {
+            IllegalStamp other = (IllegalStamp) stamp;
+            return kind == other.kind;
+        }
+        return false;
+    }
+
+    @Override
     public String toString() {
         return "ILLEGAL";
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java	Thu Feb 20 12:08:04 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/IntegerStamp.java	Thu Feb 20 14:42:01 2014 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,38 +31,79 @@
 /**
  * Describes the possible values of a {@link ValueNode} that produces an int or long result.
  * 
- * The description consists of (inclusive, signed) lower and upper bounds and up (may be set) and
- * down (always set) bit-masks.
+ * The description consists of (inclusive) lower and upper bounds and up (may be set) and down
+ * (always set) bit-masks.
  */
-public class IntegerStamp extends Stamp {
+public class IntegerStamp extends PrimitiveStamp {
+
+    private final boolean unsigned;
 
     private final long lowerBound;
     private final long upperBound;
     private final long downMask;
     private final long upMask;
 
-    public IntegerStamp(Kind kind) {
-        this(kind.getStackKind(), kind.getMinValue(), kind.getMaxValue(), 0, defaultMask(isUnsignedKind(kind) ? kind : kind.getStackKind()));
-    }
-
-    public IntegerStamp(Kind kind, long lowerBound, long upperBound, long downMask, long upMask) {
-        super(kind);
+    public IntegerStamp(int bits, boolean unsigned, long lowerBound, long upperBound, long downMask, long upMask) {
+        super(bits);
+        this.unsigned = unsigned;
         this.lowerBound = lowerBound;
         this.upperBound = upperBound;
         this.downMask = downMask;
         this.upMask = upMask;
         assert lowerBound <= upperBound : this;
-        assert lowerBound >= kind.getMinValue() : this;
-        assert upperBound <= kind.getMaxValue() : this;
-        assert (downMask & defaultMask(kind)) == downMask : this;
-        assert (upMask & defaultMask(kind)) == upMask : this;
+        assert lowerBound >= defaultMinValue(bits, unsigned) : this;
+        assert upperBound <= defaultMaxValue(bits, unsigned) : this;
+        assert (downMask & defaultMask(bits)) == downMask : this;
+        assert (upMask & defaultMask(bits)) == upMask : this;
         assert (lowerBound & downMask) == downMask : this;
         assert (upperBound & downMask) == downMask : this;
     }
 
     @Override
+    public Stamp unrestricted() {
+        return new IntegerStamp(getBits(), unsigned, defaultMinValue(getBits(), unsigned), defaultMaxValue(getBits(), unsigned), 0, defaultMask(getBits()));
+    }
+
+    @Override
+    public Kind getStackKind() {
+        if (getBits() > 32) {
+            return Kind.Long;
+        } else {
+            return Kind.Int;
+        }
+    }
+
+    @Override
     public ResolvedJavaType javaType(MetaAccessProvider metaAccess) {
-        return metaAccess.lookupJavaType(kind().toJavaClass());
+        switch (getBits()) {
+            case 1:
+                assert unsigned;
+                return metaAccess.lookupJavaType(Boolean.TYPE);
+            case 8:
+                assert !unsigned;
+                return metaAccess.lookupJavaType(Byte.TYPE);
+            case 16:
+                if (unsigned) {
+                    return metaAccess.lookupJavaType(Character.TYPE);
+                } else {
+                    return metaAccess.lookupJavaType(Short.TYPE);
+                }
+            case 32:
+                assert !unsigned;
+                return metaAccess.lookupJavaType(Integer.TYPE);
+            case 64:
+                assert !unsigned;
+                return metaAccess.lookupJavaType(Long.TYPE);
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+    }
+
+    /**
+     * Check whether the value described by this stamp is unsigned.
+     */
+    public boolean isUnsigned() {
+        return unsigned;
     }
 
     /**
@@ -94,11 +135,11 @@
     }
 
     public boolean isUnrestricted() {
-        return lowerBound == kind().getMinValue() && upperBound == kind().getMaxValue() && downMask == 0 && upMask == defaultMask(kind());
+        return lowerBound == defaultMinValue(getBits(), unsigned) && upperBound == defaultMaxValue(getBits(), unsigned) && downMask == 0 && upMask == defaultMask(getBits());
     }
 
     public boolean contains(long value) {
-        return value >= lowerBound && value <= upperBound && (value & downMask) == downMask && (value & upMask) == (value & defaultMask(kind()));
+        return value >= lowerBound && value <= upperBound && (value & downMask) == downMask && (value & upMask) == (value & defaultMask(getBits()));
     }
 
     public boolean isPositive() {
@@ -128,17 +169,18 @@
     @Override
     public String toString() {
         StringBuilder str = new StringBuilder();
-        str.append(kind().getTypeChar());
+        str.append(unsigned ? 'u' : 'i');
+        str.append(getBits());
         if (lowerBound == upperBound) {
             str.append(" [").append(lowerBound).append(']');
-        } else if (lowerBound != kind().getMinValue() || upperBound != kind().getMaxValue()) {
+        } else if (lowerBound != defaultMinValue(getBits(), unsigned) || upperBound != defaultMaxValue(getBits(), unsigned)) {
             str.append(" [").append(lowerBound).append(" - ").append(upperBound).append(']');
         }
         if (downMask != 0) {
             str.append(" \u21ca");
             new Formatter(str).format("%016x", downMask);
         }
-        if (upMask != defaultMask(kind())) {
+        if (upMask != defaultMask(getBits())) {
             str.append(" \u21c8");
             new Formatter(str).format("%016x", upMask);
         }
@@ -146,15 +188,15 @@
     }
 
     private Stamp createStamp(IntegerStamp other, long newUpperBound, long newLowerBound, long newDownMask, long newUpMask) {
-        assert kind() == other.kind();
+        assert getBits() == other.getBits() && unsigned == other.unsigned;
         if (newLowerBound > newUpperBound || (newDownMask & (~newUpMask)) != 0) {
-            return StampFactory.illegal(kind());
+            return illegal();
         } else if (newLowerBound == lowerBound && newUpperBound == upperBound && newDownMask == downMask && newUpMask == upMask) {
             return this;
         } else if (newLowerBound == other.lowerBound && newUpperBound == other.upperBound && newDownMask == other.downMask && newUpMask == other.upMask) {
             return other;
         } else {
-            return new IntegerStamp(kind(), newLowerBound, newUpperBound, newDownMask, newUpMask);
+            return new IntegerStamp(getBits(), unsigned, newLowerBound, newUpperBound, newDownMask, newUpMask);
         }
     }
 
@@ -191,10 +233,22 @@
     }
 
     @Override
+    public boolean isCompatible(Stamp stamp) {
+        if (this == stamp) {
+            return true;
+        }
+        if (stamp instanceof IntegerStamp) {
+            IntegerStamp other = (IntegerStamp) stamp;
+            return getBits() == other.getBits() && unsigned == other.unsigned;
+        }
+        return false;
+    }
+
+    @Override
     public int hashCode() {
         final int prime = 31;
         int result = 1;
-        result = prime * result + kind().hashCode();
+        result = prime * result + super.hashCode();
         result = prime * result + (int) (lowerBound ^ (lowerBound >>> 32));
         result = prime * result + (int) (upperBound ^ (upperBound >>> 32));
         result = prime * result + (int) (downMask ^ (downMask >>> 32));
@@ -207,41 +261,43 @@
         if (this == obj) {
             return true;
         }
-        if (obj == null || getClass() != obj.getClass()) {
+        if (obj == null || getClass() != obj.getClass() || !super.equals(obj)) {
             return false;
         }
         IntegerStamp other = (IntegerStamp) obj;
-        if (lowerBound != other.lowerBound || upperBound != other.upperBound || downMask != other.downMask || upMask != other.upMask || kind() != other.kind()) {
+        if (lowerBound != other.lowerBound || upperBound != other.upperBound || downMask != other.downMask || upMask != other.upMask) {
             return false;
         }
         return true;
     }
 
-    public static long defaultMask(Kind kind) {
-        switch (kind) {
-            case Boolean:
-                return 0x01L;
-            case Byte:
-                return 0xffL;
-            case Char:
-                return 0xffffL;
-            case Short:
-                return 0xffffL;
-            case Int:
-                return 0xffffffffL;
-            case Long:
-                return 0xffffffffffffffffL;
-            default:
-                throw GraalInternalError.shouldNotReachHere();
+    public static long defaultMask(int bits) {
+        assert 0 < bits && bits <= 64;
+        if (bits == 64) {
+            return 0xffffffffffffffffL;
+        } else {
+            return (1L << bits) - 1;
         }
     }
 
-    public static long upMaskFor(Kind kind, long lowerBound, long upperBound) {
+    public static long defaultMinValue(int bits, boolean unsigned) {
+        if (unsigned) {
+            return 0;
+        } else {
+            return -1L << (bits - 1);
+        }
+    }
+
+    public static long defaultMaxValue(int bits, boolean unsigned) {
+        return defaultMask(unsigned ? bits : bits - 1);
+    }
+
+    public static long upMaskFor(int bits, long lowerBound, long upperBound) {
         long mask = lowerBound | upperBound;
         if (mask == 0) {
             return 0;
         } else {
-            return ((-1L) >>> Long.numberOfLeadingZeros(mask)) & defaultMask(kind);
+            return ((-1L) >>> Long.numberOfLeadingZeros(mask)) & defaultMask(bits);
         }
     }
 
@@ -259,12 +315,23 @@
     @Override
     public Constant asConstant() {
         if (lowerBound == upperBound) {
-            return Constant.forIntegerKind(kind(), lowerBound, null);
+            switch (getBits()) {
+                case 1:
+                    return Constant.forBoolean(lowerBound != 0);
+                case 8:
+                    return Constant.forByte((byte) lowerBound);
+                case 16:
+                    if (unsigned) {
+                        return Constant.forChar((char) lowerBound);
+                    } else {
+                        return Constant.forShort((short) lowerBound);
+                    }
+                case 32:
+                    return Constant.forInt((int) lowerBound);
+                case 64:
+                    return Constant.forLong(lowerBound);
+            }
         }
         return null;
     }
-
-    private static boolean isUnsignedKind(Kind kind) {
-        return kind == Kind.Char;
-    }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java	Thu Feb 20 12:08:04 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java	Thu Feb 20 14:42:01 2014 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,7 +36,6 @@
     private final boolean alwaysNull;
 
     public ObjectStamp(ResolvedJavaType type, boolean exactType, boolean nonNull, boolean alwaysNull) {
-        super(Kind.Object);
         assert !exactType || (type != null && (isConcreteType(type)));
         this.type = type;
         this.exactType = exactType;
@@ -45,6 +44,16 @@
     }
 
     @Override
+    public Stamp unrestricted() {
+        return StampFactory.object();
+    }
+
+    @Override
+    public Kind getStackKind() {
+        return Kind.Object;
+    }
+
+    @Override
     public ResolvedJavaType javaType(MetaAccessProvider metaAccess) {
         if (type != null) {
             return type;
@@ -71,7 +80,7 @@
     @Override
     public String toString() {
         StringBuilder str = new StringBuilder();
-        str.append(kind().getTypeChar());
+        str.append('a');
         str.append(nonNull ? "!" : "").append(exactType ? "#" : "").append(' ').append(type == null ? "-" : type.getName()).append(alwaysNull ? " NULL" : "");
         return str.toString();
     }
@@ -123,6 +132,20 @@
         return join0(otherStamp, false);
     }
 
+    @Override
+    public boolean isCompatible(Stamp other) {
+        if (this == other) {
+            return true;
+        }
+        if (other instanceof ObjectStamp) {
+            return true;
+        }
+        if (other instanceof IllegalStamp) {
+            return ((IllegalStamp) other).kind() == Kind.Object;
+        }
+        return false;
+    }
+
     /**
      * Returns the stamp representing the type of this stamp after a cast to the type represented by
      * the {@code to} stamp. While this is very similar to a {@link #join} operation, in the case
@@ -294,4 +317,14 @@
         }
         return false;
     }
+
+    public static boolean isObject(Stamp stamp) {
+        if (stamp instanceof ObjectStamp) {
+            return true;
+        } else if (stamp instanceof IllegalStamp) {
+            return ((IllegalStamp) stamp).kind() == Kind.Object;
+        } else {
+            return false;
+        }
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/PrimitiveStamp.java	Thu Feb 20 14:42:01 2014 +0100
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.type;
+
+import com.oracle.graal.nodes.*;
+
+/**
+ * Describes the possible values of a {@link ValueNode} that produces a primitive value as result.
+ */
+public abstract class PrimitiveStamp extends Stamp {
+
+    private final int bits;
+
+    protected PrimitiveStamp(int bits) {
+        this.bits = bits;
+    }
+
+    /**
+     * The width in bits of the value described by this stamp.
+     */
+    public int getBits() {
+        return bits;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + bits;
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof PrimitiveStamp) {
+            PrimitiveStamp other = (PrimitiveStamp) obj;
+            return bits == other.bits;
+        }
+        return false;
+    }
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/Stamp.java	Thu Feb 20 12:08:04 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/Stamp.java	Thu Feb 20 14:42:01 2014 +0100
@@ -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,14 +30,7 @@
  */
 public abstract class Stamp {
 
-    private final Kind kind;
-
-    protected Stamp(Kind kind) {
-        this.kind = kind;
-    }
-
-    public Kind kind() {
-        return kind;
+    protected Stamp() {
     }
 
     /**
@@ -51,6 +44,13 @@
     }
 
     /**
+     * Gets a Java {@link Kind} that can be used to store a value of this stamp on the Java bytecode
+     * stack. Returns {@link Kind#Illegal} if a value of this stamp can not be stored on the
+     * bytecode stack.
+     */
+    public abstract Kind getStackKind();
+
+    /**
      * Returns the union of this stamp and the given stamp. Typically used to create stamps for
      * {@link PhiNode}s.
      * 
@@ -68,6 +68,23 @@
     public abstract Stamp join(Stamp other);
 
     /**
+     * Returns a stamp of the same kind, but allowing the full value range of the kind.
+     */
+    public abstract Stamp unrestricted();
+
+    /**
+     * Returns an illegal stamp that has the same kind, but no valid values.
+     */
+    public Stamp illegal() {
+        return StampFactory.illegal(getStackKind());
+    }
+
+    /**
+     * Test whether two stamps have the same base type.
+     */
+    public abstract boolean isCompatible(Stamp other);
+
+    /**
      * If this stamp represents a single value, the methods returns this single value. It returns
      * null otherwise.
      * 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java	Thu Feb 20 12:08:04 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java	Thu Feb 20 14:42:01 2014 +0100
@@ -46,16 +46,31 @@
         stampCache[kind.ordinal()] = stamp;
     }
 
+    private static void setIntCache(Kind kind) {
+        int bits = kind.getStackKind().getBitCount();
+        long mask;
+        if (kind.isUnsigned()) {
+            mask = IntegerStamp.defaultMask(kind.getBitCount());
+        } else {
+            mask = IntegerStamp.defaultMask(bits);
+        }
+        setCache(kind, new IntegerStamp(bits, false, kind.getMinValue(), kind.getMaxValue(), 0, mask));
+    }
+
+    private static void setFloatCache(Kind kind) {
+        setCache(kind, new FloatStamp(kind.getBitCount()));
+    }
+
     static {
-        setCache(Kind.Boolean, new IntegerStamp(Kind.Boolean));
-        setCache(Kind.Byte, new IntegerStamp(Kind.Byte));
-        setCache(Kind.Short, new IntegerStamp(Kind.Short));
-        setCache(Kind.Char, new IntegerStamp(Kind.Char));
-        setCache(Kind.Int, new IntegerStamp(Kind.Int));
-        setCache(Kind.Long, new IntegerStamp(Kind.Long));
+        setIntCache(Kind.Boolean);
+        setIntCache(Kind.Byte);
+        setIntCache(Kind.Short);
+        setIntCache(Kind.Char);
+        setIntCache(Kind.Int);
+        setIntCache(Kind.Long);
 
-        setCache(Kind.Float, new FloatStamp(Kind.Float));
-        setCache(Kind.Double, new FloatStamp(Kind.Double));
+        setFloatCache(Kind.Float);
+        setFloatCache(Kind.Double);
 
         setCache(Kind.Object, objectStamp);
         setCache(Kind.Void, voidStamp);
@@ -64,6 +79,9 @@
         }
     }
 
+    /**
+     * Return a stamp for a Java kind, as it would be represented on the bytecode stack.
+     */
     public static Stamp forKind(Kind kind) {
         assert stampCache[kind.ordinal()] != null : "unexpected forKind(" + kind + ")";
         return stampCache[kind.ordinal()];
@@ -106,13 +124,21 @@
     }
 
     public static IntegerStamp forInteger(Kind kind, long lowerBound, long upperBound, long downMask, long upMask) {
-        return new IntegerStamp(kind, lowerBound, upperBound, downMask, upMask);
+        return new IntegerStamp(kind.getBitCount(), kind.isUnsigned(), lowerBound, upperBound, downMask, upMask);
     }
 
     public static IntegerStamp forInteger(Kind kind, long lowerBound, long upperBound) {
-        long defaultMask = IntegerStamp.defaultMask(kind);
+        return forInteger(kind.getBitCount(), kind.isUnsigned(), lowerBound, upperBound);
+    }
+
+    public static IntegerStamp forInteger(int bits, boolean unsigned) {
+        return new IntegerStamp(bits, unsigned, IntegerStamp.defaultMinValue(bits, unsigned), IntegerStamp.defaultMaxValue(bits, unsigned), 0, IntegerStamp.defaultMask(bits));
+    }
+
+    public static IntegerStamp forInteger(int bits, boolean unsigned, long lowerBound, long upperBound) {
+        long defaultMask = IntegerStamp.defaultMask(bits);
         if (lowerBound == upperBound) {
-            return new IntegerStamp(kind, lowerBound, lowerBound, lowerBound & defaultMask, lowerBound & defaultMask);
+            return new IntegerStamp(bits, unsigned, lowerBound, lowerBound, lowerBound & defaultMask, lowerBound & defaultMask);
         }
         final long downMask;
         final long upMask;
@@ -136,11 +162,12 @@
                 downMask = lowerBound & ~(-1L >>> (lowerBoundLeadingOnes + sameBitCount)) | ~(-1L >>> lowerBoundLeadingOnes);
             }
         }
-        return forInteger(kind, lowerBound, upperBound, downMask & defaultMask, upMask & defaultMask);
+        return new IntegerStamp(bits, unsigned, lowerBound, upperBound, downMask & defaultMask, upMask & defaultMask);
     }
 
     public static FloatStamp forFloat(Kind kind, double lowerBound, double upperBound, boolean nonNaN) {
-        return new FloatStamp(kind, lowerBound, upperBound, nonNaN);
+        assert kind.isNumericFloat();
+        return new FloatStamp(kind.getBitCount(), lowerBound, upperBound, nonNaN);
     }
 
     public static Stamp forConstant(Constant value) {
@@ -152,7 +179,7 @@
             case Short:
             case Int:
             case Long:
-                long mask = value.asLong() & IntegerStamp.defaultMask(kind);
+                long mask = value.asLong() & IntegerStamp.defaultMask(kind.getBitCount());
                 return forInteger(kind.getStackKind(), value.asLong(), value.asLong(), mask, mask);
             case Float:
                 return forFloat(kind, value.asFloat(), value.asFloat(), !Float.isNaN(value.asFloat()));
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java	Thu Feb 20 12:08:04 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java	Thu Feb 20 14:42:01 2014 +0100
@@ -31,41 +31,48 @@
  */
 public class StampTool {
 
-    public static Kind joinKind(Kind a, Kind b) {
+    private static Kind joinKind(Kind a, Kind b) {
         if (a == b) {
             return a;
         }
         return Kind.Illegal;
     }
 
-    public static Kind joinKind(Stamp a, Stamp b) {
-        return joinKind(a.kind(), b.kind());
+    /**
+     * Create an {@link IllegalStamp} from two incompatible input stamps, joining the kind of the
+     * input stamps if possible.
+     */
+    private static Stamp joinIllegal(Stamp a, Stamp b) {
+        IllegalStamp ia = (IllegalStamp) a.illegal();
+        IllegalStamp ib = (IllegalStamp) b.illegal();
+        return StampFactory.illegal(joinKind(ia.kind(), ib.kind()));
     }
 
     public static Stamp negate(Stamp stamp) {
-        Kind kind = stamp.kind();
         if (stamp instanceof IntegerStamp) {
             IntegerStamp integerStamp = (IntegerStamp) stamp;
-            if (integerStamp.lowerBound() != kind.getMinValue()) {
+            int bits = integerStamp.getBits();
+            if (integerStamp.lowerBound() != IntegerStamp.defaultMinValue(bits, false)) {
                 // TODO(ls) check if the mask calculation is correct...
-                return StampFactory.forInteger(kind, -integerStamp.upperBound(), -integerStamp.lowerBound());
+                return StampFactory.forInteger(bits, false, -integerStamp.upperBound(), -integerStamp.lowerBound());
             }
         } else if (stamp instanceof FloatStamp) {
             FloatStamp floatStamp = (FloatStamp) stamp;
-            return new FloatStamp(kind, -floatStamp.upperBound(), -floatStamp.lowerBound(), floatStamp.isNonNaN());
+            return new FloatStamp(floatStamp.getBits(), -floatStamp.upperBound(), -floatStamp.lowerBound(), floatStamp.isNonNaN());
         }
 
-        return StampFactory.forKind(kind);
+        return stamp.unrestricted();
     }
 
     public static Stamp not(Stamp stamp) {
         if (stamp instanceof IntegerStamp) {
             IntegerStamp integerStamp = (IntegerStamp) stamp;
-            assert stamp.kind() == Kind.Int || stamp.kind() == Kind.Long;
-            long defaultMask = IntegerStamp.defaultMask(stamp.kind());
-            return new IntegerStamp(stamp.kind(), ~integerStamp.upperBound(), ~integerStamp.lowerBound(), (~integerStamp.upMask()) & defaultMask, (~integerStamp.downMask()) & defaultMask);
+            int bits = integerStamp.getBits();
+            long defaultMask = IntegerStamp.defaultMask(bits);
+            return new IntegerStamp(bits, integerStamp.isUnsigned(), ~integerStamp.upperBound(), ~integerStamp.lowerBound(), (~integerStamp.upMask()) & defaultMask, (~integerStamp.downMask()) &
+                            defaultMask);
         }
-        return StampFactory.forKind(stamp.kind());
+        return stamp.unrestricted();
     }
 
     public static Stamp meet(Collection<? extends StampProvider> values) {
@@ -85,7 +92,7 @@
         if (stamp1 instanceof IntegerStamp && stamp2 instanceof IntegerStamp) {
             return add((IntegerStamp) stamp1, (IntegerStamp) stamp2);
         }
-        return StampFactory.illegal(joinKind(stamp1, stamp2));
+        return joinIllegal(stamp1, stamp2);
     }
 
     private static long carryBits(long x, long y) {
@@ -100,47 +107,56 @@
         if (stamp1 instanceof IntegerStamp && stamp2 instanceof IntegerStamp) {
             return div((IntegerStamp) stamp1, (IntegerStamp) stamp2);
         }
-        return StampFactory.illegal(joinKind(stamp1, stamp2));
+        return joinIllegal(stamp1, stamp2);
     }
 
     public static Stamp div(IntegerStamp stamp1, IntegerStamp stamp2) {
-        assert stamp1.kind() == stamp2.kind();
-        Kind kind = stamp1.kind();
+        assert stamp1.getBits() == stamp2.getBits() && stamp1.isUnsigned() == stamp2.isUnsigned();
         if (stamp2.isStrictlyPositive()) {
             long lowerBound = stamp1.lowerBound() / stamp2.lowerBound();
             long upperBound = stamp1.upperBound() / stamp2.lowerBound();
-            return StampFactory.forInteger(kind, lowerBound, upperBound);
+            return StampFactory.forInteger(stamp1.getBits(), stamp1.isUnsigned(), lowerBound, upperBound);
         }
-        return StampFactory.forKind(kind);
+        return stamp1.unrestricted();
     }
 
-    private static boolean addOverflowsPositively(long x, long y, Kind kind) {
+    private static boolean addOverflowsPositively(long x, long y, int bits, boolean unsigned) {
         long result = x + y;
-        if (kind == Kind.Long) {
-            return (~x & ~y & result) < 0;
+        if (bits == 64) {
+            if (unsigned) {
+                return ((x | y) & ~result) < 0;
+            } else {
+                return (~x & ~y & result) < 0;
+            }
         } else {
-            assert kind == Kind.Int;
-            return result > Integer.MAX_VALUE;
+            return result > IntegerStamp.defaultMaxValue(bits, unsigned);
         }
     }
 
-    private static boolean addOverflowsNegatively(long x, long y, Kind kind) {
+    private static boolean addOverflowsNegatively(long x, long y, int bits, boolean unsigned) {
+        if (unsigned) {
+            return false;
+        }
+
         long result = x + y;
-        if (kind == Kind.Long) {
+        if (bits == 64) {
             return (x & y & ~result) < 0;
         } else {
-            assert kind == Kind.Int;
-            return result < Integer.MIN_VALUE;
+            return result < IntegerStamp.defaultMinValue(bits, unsigned);
         }
     }
 
     public static IntegerStamp add(IntegerStamp stamp1, IntegerStamp stamp2) {
-        if (stamp1.isUnrestricted() || stamp2.isUnrestricted()) {
-            return (IntegerStamp) StampFactory.forKind(stamp1.kind());
+        int bits = stamp1.getBits();
+        boolean unsigned = stamp1.isUnsigned();
+        assert bits == stamp2.getBits() && unsigned == stamp2.isUnsigned();
+
+        if (stamp1.isUnrestricted()) {
+            return stamp1;
+        } else if (stamp2.isUnrestricted()) {
+            return stamp2;
         }
-        Kind kind = stamp1.kind();
-        assert stamp1.kind() == stamp2.kind();
-        long defaultMask = IntegerStamp.defaultMask(kind);
+        long defaultMask = IntegerStamp.defaultMask(bits);
         long variableBits = (stamp1.downMask() ^ stamp1.upMask()) | (stamp2.downMask() ^ stamp2.upMask());
         long variableBitsWithCarry = variableBits | (carryBits(stamp1.downMask(), stamp2.downMask()) ^ carryBits(stamp1.upMask(), stamp2.upMask()));
         long newDownMask = (stamp1.downMask() + stamp2.downMask()) & ~variableBitsWithCarry;
@@ -151,102 +167,105 @@
 
         long lowerBound;
         long upperBound;
-        boolean lowerOverflowsPositively = addOverflowsPositively(stamp1.lowerBound(), stamp2.lowerBound(), kind);
-        boolean upperOverflowsPositively = addOverflowsPositively(stamp1.upperBound(), stamp2.upperBound(), kind);
-        boolean lowerOverflowsNegatively = addOverflowsNegatively(stamp1.lowerBound(), stamp2.lowerBound(), kind);
-        boolean upperOverflowsNegatively = addOverflowsNegatively(stamp1.upperBound(), stamp2.upperBound(), kind);
+        boolean lowerOverflowsPositively = addOverflowsPositively(stamp1.lowerBound(), stamp2.lowerBound(), bits, unsigned);
+        boolean upperOverflowsPositively = addOverflowsPositively(stamp1.upperBound(), stamp2.upperBound(), bits, unsigned);
+        boolean lowerOverflowsNegatively = addOverflowsNegatively(stamp1.lowerBound(), stamp2.lowerBound(), bits, unsigned);
+        boolean upperOverflowsNegatively = addOverflowsNegatively(stamp1.upperBound(), stamp2.upperBound(), bits, unsigned);
         if ((lowerOverflowsNegatively && !upperOverflowsNegatively) || (!lowerOverflowsPositively && upperOverflowsPositively)) {
-            lowerBound = kind.getMinValue();
-            upperBound = kind.getMaxValue();
+            lowerBound = IntegerStamp.defaultMinValue(bits, unsigned);
+            upperBound = IntegerStamp.defaultMaxValue(bits, unsigned);
         } else {
-            lowerBound = signExtend((stamp1.lowerBound() + stamp2.lowerBound()) & defaultMask, kind);
-            upperBound = signExtend((stamp1.upperBound() + stamp2.upperBound()) & defaultMask, kind);
+            lowerBound = (stamp1.lowerBound() + stamp2.lowerBound()) & defaultMask;
+            upperBound = (stamp1.upperBound() + stamp2.upperBound()) & defaultMask;
+            if (!unsigned) {
+                lowerBound = signExtend(lowerBound, bits);
+                upperBound = signExtend(upperBound, bits);
+            }
         }
-        IntegerStamp limit = StampFactory.forInteger(kind, lowerBound, upperBound);
+        IntegerStamp limit = StampFactory.forInteger(bits, unsigned, lowerBound, upperBound);
         newUpMask &= limit.upMask();
-        upperBound = signExtend(upperBound & newUpMask, kind);
+        upperBound &= newUpMask;
+        if (!unsigned) {
+            upperBound = signExtend(upperBound, bits);
+        }
         newDownMask |= limit.downMask();
         lowerBound |= newDownMask;
-        return new IntegerStamp(kind, lowerBound, upperBound, newDownMask, newUpMask);
+        return new IntegerStamp(bits, unsigned, lowerBound, upperBound, newDownMask, newUpMask);
     }
 
     public static Stamp sub(IntegerStamp stamp1, IntegerStamp stamp2) {
         if (stamp1.isUnrestricted() || stamp2.isUnrestricted()) {
-            return StampFactory.forKind(stamp1.kind());
+            return stamp1.unrestricted();
         }
         return add(stamp1, (IntegerStamp) StampTool.negate(stamp2));
     }
 
-    private static Stamp stampForMask(Kind kind, long downMask, long upMask) {
+    private static Stamp stampForMask(int bits, long downMask, long upMask) {
         long lowerBound;
         long upperBound;
-        if (((upMask >>> (kind.getBitCount() - 1)) & 1) == 0) {
+        if (((upMask >>> (bits - 1)) & 1) == 0) {
             lowerBound = downMask;
             upperBound = upMask;
-        } else if (((downMask >>> (kind.getBitCount() - 1)) & 1) == 1) {
+        } else if (((downMask >>> (bits - 1)) & 1) == 1) {
             lowerBound = downMask;
             upperBound = upMask;
         } else {
-            lowerBound = downMask | (-1L << (kind.getBitCount() - 1));
-            upperBound = kind.getMaxValue() & upMask;
+            lowerBound = downMask | (-1L << (bits - 1));
+            upperBound = IntegerStamp.defaultMaxValue(bits, false) & upMask;
         }
-        if (kind == Kind.Int) {
-            return StampFactory.forInteger(kind, (int) lowerBound, (int) upperBound, downMask, upMask);
-        } else {
-            return StampFactory.forInteger(kind, lowerBound, upperBound, downMask, upMask);
-        }
+        return new IntegerStamp(bits, false, 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(joinKind(stamp1, stamp2));
+        return joinIllegal(stamp1, stamp2);
     }
 
     public static Stamp and(IntegerStamp stamp1, IntegerStamp stamp2) {
-        assert stamp1.kind() == stamp2.kind();
-        return stampForMask(stamp1.kind(), stamp1.downMask() & stamp2.downMask(), stamp1.upMask() & stamp2.upMask());
+        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(joinKind(stamp1, stamp2));
+        return joinIllegal(stamp1, stamp2);
     }
 
     public static Stamp or(IntegerStamp stamp1, IntegerStamp stamp2) {
-        assert stamp1.kind() == stamp2.kind();
-        return stampForMask(stamp1.kind(), stamp1.downMask() | stamp2.downMask(), stamp1.upMask() | stamp2.upMask());
+        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(joinKind(stamp1, stamp2));
+        return joinIllegal(stamp1, stamp2);
     }
 
     public static Stamp xor(IntegerStamp stamp1, IntegerStamp stamp2) {
-        assert stamp1.kind() == stamp2.kind();
+        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.kind(), newDownMask, newUpMask);
+        return stampForMask(stamp1.getBits(), newDownMask, newUpMask);
     }
 
     public static Stamp unsignedRightShift(Stamp value, Stamp shift) {
         if (value instanceof IntegerStamp && shift instanceof IntegerStamp) {
             return unsignedRightShift((IntegerStamp) value, (IntegerStamp) shift);
         }
-        return StampFactory.illegal(value.kind());
+        return value.illegal();
     }
 
     public static Stamp unsignedRightShift(IntegerStamp value, IntegerStamp shift) {
-        Kind kind = value.kind();
+        int bits = value.getBits();
         if (shift.lowerBound() == shift.upperBound()) {
-            long shiftMask = kind == Kind.Int ? 0x1FL : 0x3FL;
+            long shiftMask = bits > 32 ? 0x3FL : 0x1FL;
             long shiftCount = shift.lowerBound() & shiftMask;
             if (shiftCount != 0) {
                 long lowerBound;
@@ -260,28 +279,28 @@
                     lowerBound = value.lowerBound() >>> shiftCount;
                     upperBound = value.upperBound() >>> shiftCount;
                 }
-                return new IntegerStamp(kind, lowerBound, upperBound, downMask, upMask);
+                return new IntegerStamp(bits, value.isUnsigned(), lowerBound, upperBound, downMask, upMask);
             }
         }
-        long mask = IntegerStamp.upMaskFor(kind, value.lowerBound(), value.upperBound());
-        return stampForMask(kind, 0, mask);
+        long mask = IntegerStamp.upMaskFor(bits, value.lowerBound(), value.upperBound());
+        return stampForMask(bits, 0, mask);
     }
 
     public static Stamp leftShift(Stamp value, Stamp shift) {
         if (value instanceof IntegerStamp && shift instanceof IntegerStamp) {
             return leftShift((IntegerStamp) value, (IntegerStamp) shift);
         }
-        return StampFactory.illegal(value.kind());
+        return value.illegal();
     }
 
     public static Stamp leftShift(IntegerStamp value, IntegerStamp shift) {
-        Kind kind = value.kind();
-        long defaultMask = IntegerStamp.defaultMask(kind);
+        int bits = value.getBits();
+        long defaultMask = IntegerStamp.defaultMask(bits);
         if (value.upMask() == 0) {
             return value;
         }
-        int shiftBits = kind == Kind.Int ? 5 : 6;
-        long shiftMask = kind == Kind.Int ? 0x1FL : 0x3FL;
+        int shiftBits = bits > 32 ? 6 : 5;
+        long shiftMask = bits > 32 ? 0x3FL : 0x1FL;
         if ((shift.lowerBound() >>> shiftBits) == (shift.upperBound() >>> shiftBits)) {
             long downMask = defaultMask;
             long upMask = 0;
@@ -291,14 +310,20 @@
                     upMask |= value.upMask() << (i & shiftMask);
                 }
             }
-            Stamp result = stampForMask(kind, downMask, upMask & IntegerStamp.defaultMask(kind));
+            Stamp result = stampForMask(bits, downMask, upMask & defaultMask);
             return result;
         }
-        return StampFactory.forKind(kind);
+        return value.unrestricted();
     }
 
     public static Stamp intToLong(IntegerStamp intStamp) {
-        return StampFactory.forInteger(Kind.Long, intStamp.lowerBound(), intStamp.upperBound(), signExtend(intStamp.downMask(), Kind.Int), signExtend(intStamp.upMask(), Kind.Int));
+        long downMask = intStamp.downMask();
+        long upMask = intStamp.upMask();
+        if (!intStamp.isUnsigned()) {
+            downMask = signExtend(downMask, intStamp.getBits());
+            upMask = signExtend(upMask, intStamp.getBits());
+        }
+        return new IntegerStamp(64, intStamp.isUnsigned(), intStamp.lowerBound(), intStamp.upperBound(), downMask, upMask);
     }
 
     public static IntegerStamp narrowingKindConversion(IntegerStamp fromStamp, Kind toKind) {
@@ -316,11 +341,19 @@
             lowerBound = saturate(fromStamp.lowerBound(), toKind);
         }
 
-        long defaultMask = IntegerStamp.defaultMask(toKind);
-        long intMask = IntegerStamp.defaultMask(Kind.Int);
+        long defaultMask = IntegerStamp.defaultMask(toKind.getBitCount());
+        long intMask = IntegerStamp.defaultMask(32);
         long newUpMask = signExtend(fromStamp.upMask() & defaultMask, toKind) & intMask;
         long newDownMask = signExtend(fromStamp.downMask() & defaultMask, toKind) & intMask;
-        return new IntegerStamp(toKind.getStackKind(), (int) ((lowerBound | newDownMask) & newUpMask), (int) ((upperBound | newDownMask) & newUpMask), newDownMask, newUpMask);
+        return new IntegerStamp(toKind.getStackKind().getBitCount(), false, (int) ((lowerBound | newDownMask) & newUpMask), (int) ((upperBound | newDownMask) & newUpMask), newDownMask, newUpMask);
+    }
+
+    private static long signExtend(long value, int bits) {
+        if (bits < 64 && (value >>> (bits - 1) & 1) == 1) {
+            return value | (-1L << bits);
+        } else {
+            return value;
+        }
     }
 
     private static long signExtend(long value, Kind valueKind) {
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/InferStamps.java	Thu Feb 20 12:08:04 2014 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/InferStamps.java	Thu Feb 20 14:42:01 2014 +0100
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.phases.graph;
 
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
@@ -50,9 +49,9 @@
         for (Node n : graph.getNodes()) {
             if (n instanceof PhiNode || n instanceof ValueAndStampProxy) {
                 ValueNode node = (ValueNode) n;
-                if (node.kind() == Kind.Object) {
+                if (ObjectStamp.isObject(node.stamp())) {
                     assert !(node.stamp() instanceof IllegalStamp) : "We assume all Phi and Proxy stamps are legal before the analysis";
-                    node.setStamp(StampFactory.illegal(node.kind()));
+                    node.setStamp(node.stamp().illegal());
                 }
             }
         }
@@ -69,7 +68,7 @@
             for (Node n : graph.getNodes()) {
                 if (n instanceof ValueNode) {
                     ValueNode node = (ValueNode) n;
-                    if (node.kind() == Kind.Object) {
+                    if (ObjectStamp.isObject(node.stamp())) {
                         stampChanged |= node.inferStamp();
                     }
                 }
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Thu Feb 20 12:08:04 2014 +0100
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Thu Feb 20 14:42:01 2014 +0100
@@ -370,7 +370,7 @@
     }
 
     protected ValueNode readOp(StructuredGraph graph, ValueNode base, Invoke invoke, LocationNode location, Kind readKind, BarrierType barrierType, boolean compressible) {
-        ReadNode read = graph.add(new ReadNode(base, location, StampFactory.forKind(readKind), barrierType, compressible));
+        ReadNode read = graph.add(new ReadNode(base, location, StampFactory.forKind(readKind.getStackKind()), barrierType, compressible));
         graph.addBeforeFixed(invoke.asNode(), read);
         /*
          * The read must not float outside its block otherwise it may float above an explicit zero