changeset 20025:dc3c886e3cca

Add test to check that DominatorConditionalEliminationPhase rewires ConditionAnchorNodes properly
author Gilles Duboscq <gilles.m.duboscq@oracle.com>
date Wed, 25 Mar 2015 16:31:35 +0100
parents d8275b3e1bd3
children 3bda2c03d089
files graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/matchers/NodeIterableContains.java graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/matchers/NodeIterableCount.java graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/matchers/NodeIterableIsEmpty.java graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ConditionAnchoringTest.java mx/suite.py
diffstat 5 files changed, 234 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/matchers/NodeIterableContains.java	Wed Mar 25 15:24:37 2015 +0100
+++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/matchers/NodeIterableContains.java	Wed Mar 25 16:31:35 2015 +0100
@@ -35,19 +35,16 @@
     }
 
     public void describeTo(Description description) {
-        description.appendText("is a NodeIterable containing").appendValue(node);
+        description.appendText("is a NodeIterable containing ").appendValue(node);
     }
 
     public static <T extends Node> NodeIterableContains<T> contains(T node) {
         return new NodeIterableContains<>(node);
     }
 
-    public static <T extends Node> NodeIterableContains<T> d(T node) {
-        return new NodeIterableContains<>(node);
-    }
-
     @Override
-    protected boolean matchesSafely(NodeIterable<T> iterable, Description description) {
+    protected boolean matchesSafely(NodeIterable<T> iterable, Description mismatchDescription) {
+        mismatchDescription.appendText("is a NodeIterable that does not contain ").appendValue(node);
         return iterable.contains(node);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/matchers/NodeIterableCount.java	Wed Mar 25 16:31:35 2015 +0100
@@ -0,0 +1,50 @@
+/*
+ * 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.graph.test.matchers;
+
+import org.hamcrest.*;
+
+import com.oracle.graal.graph.iterators.*;
+
+public class NodeIterableCount extends TypeSafeDiagnosingMatcher<NodeIterable<?>> {
+    private int count;
+
+    public NodeIterableCount(int count) {
+        this.count = count;
+    }
+
+    @Override
+    public void describeTo(Description description) {
+        description.appendText("is a NodeIterable containing ").appendValue(count).appendText(" elements");
+    }
+
+    public static NodeIterableCount hasCount(int count) {
+        return new NodeIterableCount(count);
+    }
+
+    @Override
+    protected boolean matchesSafely(NodeIterable<?> iterable, Description mismatchDescription) {
+        mismatchDescription.appendText("is a NodeIterable containing ").appendValue(iterable.count()).appendText(" elements");
+        return iterable.count() == count;
+    }
+}
--- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/matchers/NodeIterableIsEmpty.java	Wed Mar 25 15:24:37 2015 +0100
+++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/matchers/NodeIterableIsEmpty.java	Wed Mar 25 16:31:35 2015 +0100
@@ -27,12 +27,14 @@
 
 import com.oracle.graal.graph.iterators.*;
 
-public class NodeIterableIsEmpty extends BaseMatcher<NodeIterable<?>> {
+public class NodeIterableIsEmpty extends TypeSafeDiagnosingMatcher<NodeIterable<?>> {
 
     private static final NodeIterableIsEmpty INSTANCE = new NodeIterableIsEmpty();
 
-    public boolean matches(Object iterable) {
-        return iterable instanceof NodeIterable<?> && ((NodeIterable<?>) iterable).isEmpty();
+    @Override
+    public boolean matchesSafely(NodeIterable<?> iterable, Description mismatchDescription) {
+        mismatchDescription.appendText("is a non-empty NodeIterable");
+        return iterable.isEmpty();
     }
 
     public void describeTo(Description description) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ConditionAnchoringTest.java	Wed Mar 25 16:31:35 2015 +0100
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2015, 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.truffle.test;
+
+import static com.oracle.graal.graph.test.matchers.NodeIterableCount.*;
+import static com.oracle.graal.graph.test.matchers.NodeIterableIsEmpty.*;
+import static org.hamcrest.core.IsInstanceOf.*;
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+import sun.misc.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.graph.iterators.*;
+import com.oracle.graal.graphbuilderconf.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.LoweringTool.StandardLoweringStage;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
+import com.oracle.graal.truffle.nodes.*;
+import com.oracle.graal.truffle.substitutions.*;
+import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.unsafe.*;
+
+public class ConditionAnchoringTest extends GraalCompilerTest {
+    private static final UnsafeAccess access;
+    private static final long offset;
+    private static final Object location = new Object();
+
+    static {
+        Unsafe unsafe = com.oracle.graal.compiler.common.UnsafeAccess.unsafe;
+        access = Truffle.getRuntime().getCapability(UnsafeAccessFactory.class).createUnsafeAccess(unsafe);
+        long fieldOffset = 0;
+        try {
+            fieldOffset = unsafe.objectFieldOffset(CheckedObject.class.getDeclaredField("field"));
+        } catch (NoSuchFieldException | SecurityException e) {
+            e.printStackTrace();
+        }
+        offset = fieldOffset;
+    }
+
+    private static class CheckedObject {
+        int id;
+        int iid;
+        @SuppressWarnings("unused") int field;
+    }
+
+    public int checkedAccess(CheckedObject o) {
+        if (o.id == 42) {
+            return access.getInt(o, offset, o.id == 42, location);
+        }
+        return -1;
+    }
+
+    // test with a different kind of condition (not a comparison against a constant)
+    public int checkedAccess2(CheckedObject o) {
+        if (o.id == o.iid) {
+            return access.getInt(o, offset, o.id == o.iid, location);
+        }
+        return -1;
+    }
+
+    @Test
+    public void test() {
+        test("checkedAccess", 1);
+    }
+
+    @Test
+    public void test2() {
+        test("checkedAccess2", 2);
+    }
+
+    public void test(String name, int ids) {
+        StructuredGraph graph = parseEager(name, AllowAssumptions.YES);
+
+        NodeIterable<UnsafeLoadNode> unsafeNodes = graph.getNodes().filter(UnsafeLoadNode.class);
+        assertThat(unsafeNodes, hasCount(1));
+
+        // lower unsafe load
+        PhaseContext context = new PhaseContext(getProviders());
+        LoweringPhase lowering = new LoweringPhase(new CanonicalizerPhase(), StandardLoweringStage.HIGH_TIER);
+        lowering.apply(graph, context);
+
+        unsafeNodes = graph.getNodes().filter(UnsafeLoadNode.class);
+        NodeIterable<ConditionAnchorNode> conditionAnchors = graph.getNodes().filter(ConditionAnchorNode.class);
+        NodeIterable<ReadNode> reads = graph.getNodes().filter(ReadNode.class);
+        assertThat(unsafeNodes, isEmpty());
+        assertThat(conditionAnchors, hasCount(1));
+        assertThat(reads, hasCount(2 * ids + 1)); // 2 * ids id reads, 1 'field' access
+
+        // float reads and canonicalize to give a chance to conditions to GVN
+        FloatingReadPhase floatingReadPhase = new FloatingReadPhase();
+        floatingReadPhase.apply(graph);
+        CanonicalizerPhase canonicalizerPhase = new CanonicalizerPhase();
+        canonicalizerPhase.apply(graph, context);
+
+        NodeIterable<FloatingReadNode> floatingReads = graph.getNodes().filter(FloatingReadNode.class);
+        assertThat(floatingReads, hasCount(ids + 1)); // 1 id read, 1 'field' access
+
+        // apply DominatorConditionalEliminationPhase
+        DominatorConditionalEliminationPhase conditionalElimination = new DominatorConditionalEliminationPhase(false);
+        conditionalElimination.apply(graph);
+
+        floatingReads = graph.getNodes().filter(FloatingReadNode.class).filter(n -> ((FloatingReadNode) n).location().getLocationIdentity() instanceof ObjectLocationIdentity);
+        conditionAnchors = graph.getNodes().filter(ConditionAnchorNode.class);
+        assertThat(floatingReads, hasCount(1));
+        assertThat(conditionAnchors, isEmpty());
+        FloatingReadNode readNode = floatingReads.first();
+        assertThat(readNode.getGuard(), instanceOf(BeginNode.class));
+        assertThat(readNode.getGuard().asNode().predecessor(), instanceOf(IfNode.class));
+    }
+
+    @Override
+    protected GraphBuilderConfiguration editGraphBuilderConfiguration(GraphBuilderConfiguration conf) {
+        // get UnsafeAccessImpl.unsafeGetInt intrinsified
+        TruffleGraphBuilderPlugins.registerUnsafeAccessImplPlugins(conf.getPlugins().getInvocationPlugins());
+        // get UnsafeAccess.getInt inlined
+        conf.getPlugins().setInlineInvokePlugin(new InlineEverythingPlugin());
+        conf.getPlugins().setLoadFieldPlugin(new FoldLoadsPlugins(getMetaAccess(), getConstantReflection()));
+        return super.editGraphBuilderConfiguration(conf);
+    }
+
+    private static final class InlineEverythingPlugin implements InlineInvokePlugin {
+        public InlineInfo getInlineInfo(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args, JavaType returnType) {
+            assert method.hasBytecodes();
+            return new InlineInfo(method, false, false);
+        }
+    }
+
+    private static final class FoldLoadsPlugins implements LoadFieldPlugin {
+        private final MetaAccessProvider metaAccess;
+        private final ConstantReflectionProvider constantReflection;
+
+        public FoldLoadsPlugins(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection) {
+            this.metaAccess = metaAccess;
+            this.constantReflection = constantReflection;
+        }
+
+        public boolean apply(GraphBuilderContext graphBuilderContext, ValueNode receiver, ResolvedJavaField field) {
+            if (receiver.isConstant()) {
+                JavaConstant asJavaConstant = receiver.asJavaConstant();
+                return tryConstantFold(graphBuilderContext, metaAccess, constantReflection, field, asJavaConstant);
+            }
+            return false;
+        }
+
+        public boolean apply(GraphBuilderContext graphBuilderContext, ResolvedJavaField staticField) {
+            return tryConstantFold(graphBuilderContext, metaAccess, constantReflection, staticField, null);
+        }
+    }
+}
--- a/mx/suite.py	Wed Mar 25 15:24:37 2015 +0100
+++ b/mx/suite.py	Wed Mar 25 16:31:35 2015 +0100
@@ -1079,6 +1079,7 @@
       "sourceDirs" : ["src"],
       "dependencies" : [
         "com.oracle.graal.truffle",
+        "com.oracle.graal.graph.test",
         "com.oracle.graal.compiler.test",
         "com.oracle.truffle.sl.test",
       ],