# HG changeset patch # User Christian Wimmer # Date 1380156058 25200 # Node ID a28f24553ffaba4fd55f9659be8bb3aedcf05404 # Parent 4c96ccce37720de0a4c5da82d55a2c13e34ef5fc Improvements to recent unsafe cast node changes diff -r 4c96ccce3772 -r a28f24553ffa graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiArrayNode.java --- 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 { diff -r 4c96ccce3772 -r a28f24553ffa graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java --- 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)); } diff -r 4c96ccce3772 -r a28f24553ffa graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java --- 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(); + } } diff -r 4c96ccce3772 -r a28f24553ffa graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java --- 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();