changeset 5679:b32dc49bc024

Merge
author Gilles Duboscq <duboscq@ssw.jku.at>
date Thu, 21 Jun 2012 17:33:45 +0200
parents 2f714239cc68 (current diff) 48a2505efb54 (diff)
children 87fc13b59258 f787843c890c
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java
diffstat 8 files changed, 305 insertions(+), 98 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TLABAllocateNode.java	Thu Jun 21 17:27:58 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TLABAllocateNode.java	Thu Jun 21 17:33:45 2012 +0200
@@ -27,6 +27,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.snippets.*;
 
 /**
  * Allocates some uninitialized area. This is used for TLAB allocation
@@ -37,7 +38,7 @@
     private final int size;
 
     public TLABAllocateNode(int size, Kind wordKind) {
-        super(StampFactory.forKind(wordKind));
+        super(StampFactory.forWord(wordKind, true));
         this.size = size;
     }
 
@@ -55,7 +56,7 @@
      */
     @SuppressWarnings("unused")
     @NodeIntrinsic
-    public static Object allocate(@ConstantNodeParameter int size, @ConstantNodeParameter Kind wordKind) {
+    public static Word allocate(@ConstantNodeParameter int size, @ConstantNodeParameter Kind wordKind) {
         throw new UnsupportedOperationException();
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java	Thu Jun 21 17:27:58 2012 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java	Thu Jun 21 17:33:45 2012 +0200
@@ -24,8 +24,6 @@
 
 import static com.oracle.graal.hotspot.nodes.RegisterNode.*;
 import static com.oracle.graal.hotspot.snippets.DirectObjectStoreNode.*;
-import static com.oracle.graal.nodes.calc.Condition.*;
-import static com.oracle.graal.nodes.extended.UnsafeCastNode.*;
 import static com.oracle.graal.nodes.extended.UnsafeLoadNode.*;
 import static com.oracle.graal.snippets.SnippetTemplate.Arguments.*;
 import static com.oracle.graal.snippets.nodes.ExplodeLoopNode.*;
@@ -55,29 +53,28 @@
 public class NewInstanceSnippets implements SnippetsInterface {
 
     @Snippet
-    public static Object allocate(@ConstantParameter("size") int size) {
+    public static Word allocate(@ConstantParameter("size") int size) {
         Word thread = asWord(register(r15, wordKind()));
         Word top = loadWord(thread, threadTlabTopOffset());
         Word end = loadWord(thread, threadTlabEndOffset());
         Word newTop = top.plus(size);
-        if (newTop.cmp(BE, end)) {
-            Object memory = cast(top, Object.class);
+        if (newTop.belowOrEqual(end)) {
             store(thread, 0, threadTlabTopOffset(), newTop);
-            return memory;
+            return top;
         }
-        return null;
+        return Word.zero();
     }
 
     @Snippet
     public static Object initialize(
-                    @Parameter("memory") Object memory,
+                    @Parameter("memory") Word memory,
                     @Parameter("hub") Object hub,
                     @ConstantParameter("size") int size) {
 
-        if (memory == null) {
+        if (memory == Word.zero()) {
             return NewInstanceStubCall.call(hub);
         }
-        Object instance = cast(memory, Object.class);
+        Object instance = memory.toObject();
         formatInstance(hub, size, instance);
         return verifyOop(instance);
     }
@@ -90,18 +87,24 @@
     }
 
     private static Word asWord(Object object) {
-        return cast(object, Word.class);
+        return Word.fromObject(object);
     }
 
     private static Word loadWord(Object object, int offset) {
-        return cast(load(object, 0, offset, wordKind()), Word.class);
+        Object value = loadObject(object, 0, offset, true);
+        return asWord(value);
+    }
+
+    private static Word loadWord(Word address, int offset) {
+        Object value = loadObject(address, 0, offset, true);
+        return asWord(value);
     }
 
     /**
      * Formats the header of a created instance and zeroes out its body.
      */
     private static void formatInstance(Object hub, int size, Object instance) {
-        Word headerPrototype = cast(load(hub, 0, instanceHeaderPrototypeOffset(), wordKind()), Word.class);
+        Word headerPrototype = loadWord(hub, instanceHeaderPrototypeOffset());
         store(instance, 0, 0, headerPrototype);
         store(instance, 0, hubOffset(), hub);
         explodeLoop();
@@ -159,7 +162,7 @@
             this.useTLAB = useTLAB;
             try {
                 allocate = runtime.getResolvedJavaMethod(NewInstanceSnippets.class.getDeclaredMethod("allocate", int.class));
-                initialize = runtime.getResolvedJavaMethod(NewInstanceSnippets.class.getDeclaredMethod("initialize", Object.class, Object.class, int.class));
+                initialize = runtime.getResolvedJavaMethod(NewInstanceSnippets.class.getDeclaredMethod("initialize", Word.class, Object.class, int.class));
             } catch (NoSuchMethodException e) {
                 throw new GraalInternalError(e);
             }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Thu Jun 21 17:27:58 2012 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java	Thu Jun 21 17:33:45 2012 +0200
@@ -42,7 +42,7 @@
     }
 
     public UnsafeCastNode(ValueNode object, ResolvedJavaType toType) {
-        super(StampFactory.declared(toType, object.stamp().nonNull()));
+        super(toType.kind().isObject() ? StampFactory.declared(toType, object.stamp().nonNull()) : StampFactory.forKind(toType.kind()));
         this.object = object;
         this.toType = toType;
     }
--- a/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/WordTest.java	Thu Jun 21 17:27:58 2012 +0200
+++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/WordTest.java	Thu Jun 21 17:33:45 2012 +0200
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.snippets;
 
-import static com.oracle.graal.nodes.calc.Condition.*;
-
 import java.lang.reflect.*;
 
 import org.junit.*;
@@ -34,7 +32,6 @@
 import com.oracle.graal.compiler.*;
 import com.oracle.graal.compiler.tests.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
 
 /**
  * Tests for the {@link Word} type.
@@ -78,9 +75,9 @@
         long[] words = new long[] {Long.MIN_VALUE, Long.MIN_VALUE + 1, -1L, 0L, 1L, Long.MAX_VALUE - 1, Long.MAX_VALUE};
         for (long word1 : words) {
             for (long word2 : words) {
-                for (Condition cond : new Condition[] {AE, AT, EQ, NE, BE, BT}) {
-                    test("compare" + cond.name(), word1, word2);
-                    test("compare" + cond.name(), word2, word1);
+                for (String method : new String[] {"aboveOrEqual", "above", "belowOrEqual", "below"}) {
+                    test(method, word1, word2);
+                    test(method, word2, word1);
                 }
             }
         }
@@ -97,28 +94,23 @@
     }
 
     @Snippet
-    public static boolean compareAE(long word1, long word2) {
-        return Word.fromLong(word1).cmp(Condition.AE, Word.fromLong(word2));
+    public static boolean aboveOrEqual(long word1, long word2) {
+        return Word.fromLong(word1).aboveOrEqual(Word.fromLong(word2));
     }
+
     @Snippet
-    public static boolean compareAT(long word1, long word2) {
-        return Word.fromLong(word1).cmp(Condition.AT, Word.fromLong(word2));
-    }
-    @Snippet
-    public static boolean compareEQ(long word1, long word2) {
-        return Word.fromLong(word1).cmp(Condition.EQ, Word.fromLong(word2));
+    public static boolean above(long word1, long word2) {
+        return Word.fromLong(word1).above(Word.fromLong(word2));
     }
-    @Snippet
-    public static boolean compareNE(long word1, long word2) {
-        return Word.fromLong(word1).cmp(Condition.NE, Word.fromLong(word2));
-    }
+
     @Snippet
-    public static boolean compareBE(long word1, long word2) {
-        return Word.fromLong(word1).cmp(Condition.BE, Word.fromLong(word2));
+    public static boolean belowOrEqual(long word1, long word2) {
+        return Word.fromLong(word1).belowOrEqual(Word.fromLong(word2));
     }
+
     @Snippet
-    public static boolean compareBT(long word1, long word2) {
-        return Word.fromLong(word1).cmp(Condition.BT, Word.fromLong(word2));
+    public static boolean below(long word1, long word2) {
+        return Word.fromLong(word1).below(Word.fromLong(word2));
     }
 
 }
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java	Thu Jun 21 17:27:58 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java	Thu Jun 21 17:33:45 2012 +0200
@@ -163,6 +163,8 @@
 
                 Debug.dump(graph, "%s: %s", method.name(), GraphBuilderPhase.class.getSimpleName());
 
+                new SnippetVerificationPhase().apply(graph);
+
                 new SnippetIntrinsificationPhase(runtime, pool).apply(graph);
 
                 for (Invoke invoke : graph.getInvokes()) {
@@ -173,7 +175,7 @@
                         InliningUtil.inline(invoke, targetGraph, true);
                         Debug.dump(graph, "after inlining %s", callee);
                         if (GraalOptions.OptCanonicalizer) {
-                            new WordTypeRewriterPhase(target).apply(graph);
+                            new WordTypeRewriterPhase(target.wordKind, runtime.getResolvedJavaType(target.wordKind)).apply(graph);
                             new CanonicalizerPhase(target, runtime, null).apply(graph);
                         }
                     }
@@ -181,7 +183,7 @@
 
                 new SnippetIntrinsificationPhase(runtime, pool).apply(graph);
 
-                new WordTypeRewriterPhase(target).apply(graph);
+                new WordTypeRewriterPhase(target.wordKind, runtime.getResolvedJavaType(target.wordKind)).apply(graph);
 
                 new DeadCodeEliminationPhase().apply(graph);
                 if (GraalOptions.OptCanonicalizer) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetVerificationPhase.java	Thu Jun 21 17:33:45 2012 +0200
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2011, 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.snippets;
+
+import static com.oracle.graal.snippets.WordTypeRewriterPhase.*;
+
+import java.lang.reflect.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.phases.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.Node.NodeIntrinsic;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.nodes.util.*;
+import com.oracle.graal.snippets.Word.*;
+
+/**
+ * Verifies invariants that must hold for snippet code above and beyond normal
+ * bytecode verification.
+ */
+public class SnippetVerificationPhase extends Phase {
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        for (ValueNode node : graph.getNodes().filter(ValueNode.class)) {
+            for (Node usage : node.usages()) {
+                if (usage instanceof AccessMonitorNode) {
+                    verify(!isWord(node), node, usage, "word value has no monitor");
+                } else if (usage instanceof LoadFieldNode) {
+                    verify(!isWord(node) || ((LoadFieldNode) usage).object() != node, node, usage, "cannot load from word value");
+                } else if (usage instanceof StoreFieldNode) {
+                    verify(!isWord(node) || ((StoreFieldNode) usage).object() != node, node, usage, "cannot store to word value");
+                } else if (usage instanceof CheckCastNode) {
+                    verify(!isWord(node), node, usage, "word value cannot be cast");
+                    verify(!isWord(((CheckCastNode) usage).targetClass()), node, usage, "cannot cast to word value");
+                } else if (usage instanceof LoadIndexedNode) {
+                    verify(!isWord(node) || ((LoadIndexedNode) usage).array() != node, node, usage, "cannot load from word value");
+                    verify(!isWord(node) || ((LoadIndexedNode) usage).index() != node, node, usage, "cannot use word value as index");
+                } else if (usage instanceof StoreIndexedNode) {
+                    verify(!isWord(node) || ((StoreIndexedNode) usage).array() != node, node, usage, "cannot store to word value");
+                    verify(!isWord(node) || ((StoreIndexedNode) usage).index() != node, node, usage, "cannot use word value as index");
+                    verify(!isWord(node) || ((StoreIndexedNode) usage).value() != node, node, usage, "cannot store word value to array");
+                } else if (usage instanceof MethodCallTargetNode) {
+                    MethodCallTargetNode callTarget = (MethodCallTargetNode) usage;
+                    ResolvedJavaMethod method = callTarget.targetMethod();
+                    if (method.getAnnotation(NodeIntrinsic.class) == null) {
+                        Invoke invoke = (Invoke) callTarget.usages().first();
+                        NodeInputList<ValueNode> arguments = callTarget.arguments();
+                        boolean isStatic = Modifier.isStatic(method.accessFlags());
+                        int argc = 0;
+                        if (!isStatic) {
+                            ValueNode receiver = arguments.get(argc);
+                            if (receiver == node && isWord(node)) {
+                                Operation operation = method.getAnnotation(Word.Operation.class);
+                                verify(operation != null, node, invoke.node(), "cannot dispatch on word value to non @Operation annotated method " + method);
+                            }
+                            argc++;
+                        }
+                        Signature signature = method.signature();
+                        for (int i = 0; i < signature.argumentCount(false); i++) {
+                            ValueNode argument = arguments.get(argc);
+                            if (argument == node) {
+                                ResolvedJavaType type = (ResolvedJavaType) signature.argumentTypeAt(i, method.holder());
+                                verify((type.toJava() == Word.class) == isWord(argument), node, invoke.node(), "cannot pass word value to non-word parameter " + i + " or vice-versa");
+                            }
+                            argc++;
+                        }
+                    }
+                } else if (usage instanceof ArrayLengthNode) {
+                    verify(!isWord(node) || ((ArrayLengthNode) usage).array() != node, node, usage, "cannot get array length from word value");
+                } else if (usage instanceof PhiNode) {
+                    if (!(node instanceof MergeNode)) {
+                        PhiNode phi = (PhiNode) usage;
+                        for (ValueNode input : phi.values()) {
+                            verify(isWord(node) == isWord(input), node, input, "cannot merge word and non-word values");
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private static void verify(boolean condition, Node node, Node usage, String message) {
+        if (!condition) {
+            error(node, usage, message);
+        }
+    }
+
+    private static void error(Node node, Node usage, String message) {
+        throw new GraalInternalError(String.format("Snippet verification error: %s" +
+                        "%n   node: %s (%s)" +
+                        "%n  usage: %s (%s)", message, node, sourceLocation(node), usage, sourceLocation(usage)));
+    }
+
+    private static String sourceLocation(Node n) {
+        if (n instanceof PhiNode) {
+            StringBuilder buf = new StringBuilder();
+            for (Node usage : n.usages()) {
+                String loc = sourceLocation(usage);
+                if (!loc.equals("<unknown>")) {
+                    if (buf.length() != 0) {
+                        buf.append(", ");
+                    }
+                    buf.append(loc);
+                }
+            }
+            return buf.toString();
+        } else {
+            String loc = GraphUtil.approxSourceLocation(n);
+            return loc == null ? "<unknown>" : loc;
+        }
+    }
+}
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Word.java	Thu Jun 21 17:27:58 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Word.java	Thu Jun 21 17:33:45 2012 +0200
@@ -26,9 +26,6 @@
 
 import java.lang.annotation.*;
 
-import com.oracle.graal.graph.*;
-import com.oracle.graal.nodes.calc.*;
-
 /**
  * Special type for use in snippets to represent machine word sized data.
  */
@@ -47,83 +44,137 @@
      * The canonical {@link Operation} represented by a method in the {@link Word} class.
      */
     public enum Opcode {
+        ZERO,
+        W2A,
+        A2W,
         L2W,
         I2W,
         W2L,
         W2I,
         PLUS,
         MINUS,
-        COMPARE;
+        BELOW,
+        BELOW_EQUAL,
+        ABOVE,
+        ABOVE_EQUAL;
     }
 
-    private Word(long value) {
+    private Word(long value, Object object) {
+        assert object == null || value == 0L;
         this.value = value;
+        this.object = object;
     }
 
     private final long value;
+    private final Object object;
+
+    @Operation(ZERO)
+    public static Word zero() {
+        return new Word(0L, null);
+    }
+
+    @Operation(W2A)
+    public Object toObject() {
+        assert value == 0L;
+        return object;
+    }
+
+    @Operation(A2W)
+    public static Word fromObject(Object value) {
+        return new Word(0L, value);
+    }
 
     @Operation(L2W)
     public static Word fromLong(long value) {
-        return new Word(value);
+        return new Word(value, null);
     }
 
     @Operation(I2W)
     public static Word fromInt(int value) {
-        return new Word(value);
+        return new Word(value, null);
     }
 
     @Operation(W2I)
     public int toInt() {
+        assert object == null;
         return (int) value;
     }
 
     @Operation(W2L)
     public long toLong() {
+        assert object == null;
         return value;
     }
 
-    @Operation(COMPARE)
-    public boolean cmp(Condition condition, Word other) {
+    @Operation(ABOVE)
+    public boolean above(Word other) {
+        assert object == null;
+        assert other.object == null;
+        long a = value;
+        long b = other.value;
+        return (a > b) ^ ((a < 0) != (b < 0));
+    }
+
+    @Operation(ABOVE_EQUAL)
+    public boolean aboveOrEqual(Word other) {
+        assert object == null;
+        assert other.object == null;
         long a = value;
         long b = other.value;
-        switch (condition) {
-            case AE: return (a >= b) ^ ((a < 0) != (b < 0));
-            case AT: return (a > b) ^ ((a < 0) != (b < 0));
-            case BE: return (a <= b) ^ ((a < 0) != (b < 0));
-            case BT: return (a < b) ^ ((a < 0) != (b < 0));
-            case EQ: return a == b;
-            case NE: return a != b;
-            default: throw new GraalInternalError("Unexpected operation on word: " + condition);
-        }
+        return (a >= b) ^ ((a < 0) != (b < 0));
+    }
+
+    @Operation(BELOW)
+    public boolean below(Word other) {
+        assert object == null;
+        assert other.object == null;
+        long a = value;
+        long b = other.value;
+        return (a < b) ^ ((a < 0) != (b < 0));
+    }
+
+    @Operation(BELOW_EQUAL)
+    public boolean belowOrEqual(Word other) {
+        assert object == null;
+        assert other.object == null;
+        long a = value;
+        long b = other.value;
+        return (a <= b) ^ ((a < 0) != (b < 0));
     }
 
     @Operation(PLUS)
     public Word plus(int addend) {
-        return new Word(value + addend);
+        assert object == null;
+        return new Word(value + addend, null);
     }
 
     @Operation(PLUS)
     public Word plus(long addend) {
-        return new Word(value + addend);
+        assert object == null;
+        return new Word(value + addend, null);
     }
 
     @Operation(PLUS)
     public Word plus(Word addend) {
-        return new Word(value + addend.value);
+        assert object == null;
+        return new Word(value + addend.value, null);
     }
 
     @Operation(MINUS)
     public Word minus(int addend) {
-        return new Word(value - addend);
+        assert object == null;
+        return new Word(value - addend, null);
     }
 
     @Operation(MINUS)
     public Word minus(long addend) {
-        return new Word(value - addend);
+        assert object == null;
+        return new Word(value - addend, null);
     }
 
     @Operation(MINUS)
     public Word minus(Word addend) {
-        return new Word(value - addend.value);
+        assert object == null;
+        return new Word(value - addend.value, null);
     }
 }
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java	Thu Jun 21 17:27:58 2012 +0200
+++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java	Thu Jun 21 17:33:45 2012 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.snippets;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.phases.*;
 import com.oracle.graal.graph.*;
@@ -44,9 +43,11 @@
 public class WordTypeRewriterPhase extends Phase {
 
     private final Kind wordKind;
+    private final ResolvedJavaType wordType;
 
-    public WordTypeRewriterPhase(TargetDescription target) {
-        this.wordKind = target.wordKind;
+    public WordTypeRewriterPhase(Kind wordKind, ResolvedJavaType wordType) {
+        this.wordKind = wordKind;
+        this.wordType = wordType;
     }
 
     @Override
@@ -60,14 +61,6 @@
             }
         }
 
-        // Remove all checkcasts to Word
-        for (CheckCastNode checkCastNode : graph.getNodes(CheckCastNode.class).snapshot()) {
-            if (!checkCastNode.object().stamp().kind().isObject()) {
-                checkCastNode.replaceAtUsages(checkCastNode.object());
-                graph.removeFixed(checkCastNode);
-            }
-        }
-
         // Remove unnecessary/redundant unsafe casts
         for (UnsafeCastNode unsafeCastNode : graph.getNodes().filter(UnsafeCastNode.class).snapshot()) {
             if (!unsafeCastNode.isDeleted() && unsafeCastNode.object().stamp() == unsafeCastNode.stamp()) {
@@ -85,11 +78,33 @@
 
                 Opcode opcode = operation.value();
                 switch (opcode) {
-                    case COMPARE: {
-                        assert arguments.size() == 3;
-                        assert arguments.get(1) instanceof ConstantNode;
-                        Condition condition = (Condition) arguments.get(1).asConstant().asObject();
-                        invoke.intrinsify(compare(condition, graph, arguments.first(), arguments.last()));
+                    case ZERO: {
+                        assert arguments.size() == 0;
+                        invoke.intrinsify(wordKind.isLong() ? ConstantNode.forLong(0L, graph) : ConstantNode.forInt(0, graph));
+                        break;
+                    }
+
+                    case ABOVE: {
+                        assert arguments.size() == 2;
+                        invoke.intrinsify(compare(Condition.AT, graph, arguments.first(), arguments.last()));
+                        break;
+                    }
+
+                    case ABOVE_EQUAL: {
+                        assert arguments.size() == 2;
+                        invoke.intrinsify(compare(Condition.AE, graph, arguments.first(), arguments.last()));
+                        break;
+                    }
+
+                    case BELOW: {
+                        assert arguments.size() == 2;
+                        invoke.intrinsify(compare(Condition.BT, graph, arguments.first(), arguments.last()));
+                        break;
+                    }
+
+                    case BELOW_EQUAL: {
+                        assert arguments.size() == 2;
+                        invoke.intrinsify(compare(Condition.BE, graph, arguments.first(), arguments.last()));
                         break;
                     }
 
@@ -100,9 +115,18 @@
                         break;
                     }
 
+                    case W2A: {
+                        assert arguments.size() == 1;
+                        ValueNode value = arguments.first();
+                        ResolvedJavaType targetType = (ResolvedJavaType) targetMethod.signature().returnType(targetMethod.holder());
+                        UnsafeCastNode cast = graph.unique(new UnsafeCastNode(value, targetType));
+                        invoke.intrinsify(cast);
+                        break;
+                    }
+
                     case W2I: {
                         assert arguments.size() == 1;
-                        ValueNode value = arguments.last();
+                        ValueNode value = arguments.first();
                         ValueNode intValue = fromWordKindTo(graph, value, Kind.Int);
                         invoke.intrinsify(intValue);
                         break;
@@ -110,15 +134,24 @@
 
                     case W2L: {
                         assert arguments.size() == 1;
-                        ValueNode value = arguments.last();
+                        ValueNode value = arguments.first();
                         ValueNode longValue = fromWordKindTo(graph, value, Kind.Long);
                         invoke.intrinsify(longValue);
                         break;
                     }
 
+                    case A2W: {
+                        assert arguments.size() == 1;
+                        ValueNode value = arguments.first();
+                        assert value.kind() == Kind.Object : value + ", " + targetMethod;
+                        UnsafeCastNode cast = graph.unique(new UnsafeCastNode(value, wordType));
+                        invoke.intrinsify(cast);
+                        break;
+                    }
+
                     case L2W: {
                         assert arguments.size() == 1;
-                        ValueNode value = arguments.last();
+                        ValueNode value = arguments.first();
                         assert value.kind() == Kind.Long;
                         ValueNode wordValue = asWordKind(graph, value);
                         invoke.intrinsify(wordValue);
@@ -127,7 +160,7 @@
 
                     case I2W: {
                         assert arguments.size() == 1;
-                        ValueNode value = arguments.last();
+                        ValueNode value = arguments.first();
                         assert value.kind() == Kind.Int;
                         invoke.intrinsify(asWordKind(graph, value));
                         break;
@@ -145,7 +178,7 @@
      * Creates comparison node for a given condition and two input values.
      */
     private ValueNode compare(Condition condition, StructuredGraph graph, ValueNode left, ValueNode right) {
-        assert condition.isUnsigned() || condition == Condition.EQ || condition == Condition.NE : condition;
+        assert condition.isUnsigned() : condition;
         assert left.kind() == wordKind;
         assert right.kind() == wordKind;
 
@@ -155,12 +188,7 @@
         ValueNode a = mirror ? right : left;
         ValueNode b = mirror ? left : right;
 
-        MaterializeNode materialize;
-        if (condition == Condition.EQ || condition == Condition.NE) {
-            materialize = MaterializeNode.create(graph.unique(new IntegerEqualsNode(a, b)), graph);
-        } else {
-            materialize = MaterializeNode.create(graph.unique(new IntegerBelowThanNode(a, b)), graph);
-        }
+        MaterializeNode materialize = MaterializeNode.create(graph.unique(new IntegerBelowThanNode(a, b)), graph);
 
         ValueNode op;
         if (condition.canonicalNegate()) {
@@ -207,11 +235,11 @@
         return value;
     }
 
-    public boolean isWord(ValueNode node) {
+    public static boolean isWord(ValueNode node) {
         return isWord(node.stamp().declaredType());
     }
 
-    public boolean isWord(ResolvedJavaType type) {
+    public static boolean isWord(ResolvedJavaType type) {
         if (type != null && type.toJava() == Word.class) {
             return true;
         }
@@ -228,10 +256,6 @@
                 changeToWord((ValueNode) n);
                 PhiNode phi = (PhiNode) n;
                 assert phi.type() == PhiType.Value;
-//                    for (ValueNode v : phi.values()) {
-//                        assertTrue(v.kind() == phi.kind(), "all phi values must have same kind");
-//                    }
-
             } else if (n instanceof ReturnNode) {
                 changeToWord((ValueNode) n);
             }