changeset 11800:a28f24553ffa

Improvements to recent unsafe cast node changes
author Christian Wimmer <christian.wimmer@oracle.com>
date Wed, 25 Sep 2013 17:40:58 -0700
parents 4c96ccce3772
children 63ee8dea4b80
files graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiArrayNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java
diffstat 4 files changed, 75 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiArrayNode.java	Wed Sep 25 13:26:02 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiArrayNode.java	Wed Sep 25 17:40:58 2013 -0700
@@ -22,11 +22,14 @@
  */
 package com.oracle.graal.nodes;
 
+import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.nodes.type.*;
 
 /**
- * The {@code UnsafeCastNode} produces the same value as its input, but with a different type.
+ * A {@link PiNode} that also provides an array length in addition to a more refined stamp. A usage
+ * that reads the array length, such as an {@link ArrayLengthNode}, can be canonicalized base on
+ * this information.
  */
 public final class PiArrayNode extends PiNode implements ArrayLengthProvider {
 
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Wed Sep 25 13:26:02 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java	Wed Sep 25 17:40:58 2013 -0700
@@ -60,10 +60,6 @@
 
     @Override
     public void generate(LIRGeneratorTool generator) {
-        assert kind() == Kind.Object && object.kind() == Kind.Object;
-        assert ObjectStamp.typeOrNull(this) == null || ObjectStamp.typeOrNull(object) == null || ObjectStamp.typeOrNull(this).isInterface() || ObjectStamp.typeOrNull(object).isInterface() ||
-                        ObjectStamp.typeOrNull(object).isAssignableFrom(ObjectStamp.typeOrNull(this));
-
         if (object.kind() != Kind.Void && object.kind() != Kind.Illegal) {
             generator.setResult(this, generator.operand(object));
         }
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java	Wed Sep 25 13:26:02 2013 -0700
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java	Wed Sep 25 17:40:58 2013 -0700
@@ -33,8 +33,11 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.replacements.*;
-import com.oracle.graal.replacements.Snippet.*;
+import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy;
 import com.oracle.graal.word.*;
 import com.oracle.graal.word.nodes.*;
 
@@ -399,4 +402,62 @@
         Word.fromObject(o).writeObject(offset, value);
     }
 
+    private void assertNumWordCasts(String snippetName, int expectedWordCasts) {
+        Assumptions assumptions = new Assumptions(true);
+        HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, null, OptimisticOptimizations.ALL);
+
+        StructuredGraph graph = parse(snippetName);
+        new CanonicalizerPhase(false).apply(graph, context);
+        Assert.assertEquals(expectedWordCasts, graph.getNodes().filter(WordCastNode.class).count());
+    }
+
+    @Test
+    public void testUnusedFromObject() {
+        assertNumWordCasts("unusedFromObject", 0);
+    }
+
+    @Snippet
+    public static void unusedFromObject(Object o) {
+        Word.fromObject(o);
+    }
+
+    @Test
+    public void testUnusedRawValue() {
+        assertNumWordCasts("unusedRawValue", 0);
+    }
+
+    @Snippet
+    public static void unusedRawValue(Object o) {
+        Word.fromObject(o).rawValue();
+    }
+
+    @Test
+    public void testUsedRawValue() {
+        assertNumWordCasts("usedRawValue", 1);
+    }
+
+    @Snippet
+    public static long usedRawValue(Object o) {
+        return Word.fromObject(o).rawValue();
+    }
+
+    @Test
+    public void testUnusedToObject() {
+        assertNumWordCasts("unusedToObject", 0);
+    }
+
+    @Snippet
+    public static void unusedToObject(Word w) {
+        w.toObject();
+    }
+
+    @Test
+    public void testUsedToObject() {
+        assertNumWordCasts("usedToObject", 1);
+    }
+
+    @Snippet
+    public static Object usedToObject(Word w) {
+        return w.toObject();
+    }
 }
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java	Wed Sep 25 13:26:02 2013 -0700
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java	Wed Sep 25 17:40:58 2013 -0700
@@ -32,7 +32,7 @@
  * Cast between Word and Object that is introduced by the {@link WordTypeRewriterPhase}. It has an
  * impact on the pointer maps for the GC, so it must not be scheduled or optimized away.
  */
-public final class WordCastNode extends FixedWithNextNode implements LIRLowerable {
+public final class WordCastNode extends FixedWithNextNode implements LIRLowerable, Canonicalizable {
 
     public static WordCastNode wordToObject(ValueNode input, Kind wordKind) {
         assert input.kind() == wordKind;
@@ -55,6 +55,14 @@
         return input;
     }
 
+    public ValueNode canonical(CanonicalizerTool tool) {
+        if (usages().count() == 0) {
+            /* If the cast is unused, it can be eliminated. */
+            return input;
+        }
+        return this;
+    }
+
     @Override
     public void generate(LIRGeneratorTool generator) {
         assert kind() != input.kind();