--- /dev/null 2017-01-22 10:16:57.869617664 -0800 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/BoxingEliminationTest.java 2017-02-15 16:57:23.581438904 -0800 @@ -0,0 +1,346 @@ +/* + * 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 + * 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 org.graalvm.compiler.core.test; + +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +import org.graalvm.compiler.loop.DefaultLoopPolicies; +import org.graalvm.compiler.loop.phases.LoopPeelingPhase; +import org.graalvm.compiler.nodes.ReturnNode; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; +import org.graalvm.compiler.phases.common.inlining.InliningPhase; +import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; + +/** + * In the following tests, the usages of local variable "a" are replaced with the integer constant + * 0. Then boxing elimination is applied and it is verified that the resulting graph is equal to the + * graph of the method that just has a "return 1" statement in it. + */ +public class BoxingEliminationTest extends GraalCompilerTest { + + private static final Short s = 2; + + @SuppressWarnings("all") + public static short referenceSnippet1() { + return 1; + } + + @SuppressWarnings("all") + public static short referenceSnippet2() { + return 2; + } + + public static Short boxedShort() { + return 1; + } + + public static Object boxedObjectShort() { + return (short) 1; + } + + public static Object boxedObjectInteger() { + return 1; + } + + public static Integer boxedInteger() { + return 2; + } + + public static Short constantBoxedShort() { + return s; + } + + @Test + public void test1() { + compareGraphs("test1Snippet", "referenceSnippet1"); + } + + @SuppressWarnings("all") + public static short test1Snippet() { + return boxedShort(); + } + + @Test + public void test2() { + compareGraphs("test2Snippet", "referenceSnippet1"); + } + + @SuppressWarnings("all") + public static short test2Snippet() { + return (Short) boxedObjectShort(); + } + + @Test + public void test3() { + compareGraphs("test3Snippet", "referenceSnippet1"); + } + + @SuppressWarnings("all") + public static short test3Snippet() { + short b = boxedShort(); + if (b < 0) { + b = boxedShort(); + } + return b; + } + + @Test + public void test4() { + compareGraphs("test4Snippet", "referenceSnippet2"); + } + + @SuppressWarnings("all") + public static short test4Snippet() { + return constantBoxedShort(); + } + + @Ignore + @Test + public void testLoop() { + compareGraphs("testLoopSnippet", "referenceLoopSnippet", false, true); + } + + public static int testLoopSnippet(int n, int a) { + Integer sum = a; + for (Integer i = 0; i < n; i++) { + sum += i; + } + return sum; + } + + public static int referenceLoopSnippet(int n, int a) { + int sum = a; + for (int i = 0; i < n; i++) { + sum += i; + } + return sum; + } + + @Test + public void testLoop2() { + compareGraphs("testLoop2Snippet", "referenceLoop2Snippet", true, true); + } + + public static int testLoop2Snippet(int n, Integer a) { + Integer sum = a; + for (Integer i = 0; i < n; i++) { + sum += i; + } + return sum; + } + + public static int referenceLoop2Snippet(int n, Integer a) { + Integer sum0; + if (n <= 0) { + sum0 = a; + } else { + int sum = a; + for (int i = 0; i < n; i++) { + sum += i; + } + sum0 = sum; + } + return sum0; + } + + public static int referenceIfSnippet(int a) { + int result; + if (a < 0) { + result = 2; + } else { + result = 1; + } + return result; + } + + @Test + public void testIf() { + compareGraphs("testIfSnippet", "referenceIfSnippet"); + } + + public static int testIfSnippet(int a) { + Integer result; + if (a < 0) { + result = boxedInteger(); + } else { + result = (Integer) boxedObjectInteger(); + } + return result; + } + + @Test + public void testComparison() { + compareGraphs("testComparison1Snippet", "referenceComparisonSnippet"); + compareGraphs("testComparison2Snippet", "referenceComparisonSnippet"); + } + + @SuppressWarnings("cast") + public static boolean testComparison1Snippet(int a, int b) { + return ((Integer) a) == b; + } + + public static boolean testComparison2Snippet(int a, int b) { + Integer x = a; + Integer y = b; + return x == y; + } + + public static boolean referenceComparisonSnippet(int a, int b) { + return a == b; + } + + @Test + public void testLateCanonicalization() { + compareGraphs("testLateCanonicalizationSnippet", "referenceLateCanonicalizationSnippet"); + } + + public static boolean testLateCanonicalizationSnippet(int a) { + Integer x = a; + Integer y = 1000; + return x == y; + } + + public static boolean referenceLateCanonicalizationSnippet(int a) { + return a == 1000; + } + + private StructuredGraph graph; + + public static Integer materializeReferenceSnippet(int a) { + return Integer.valueOf(a); + } + + public static Integer materializeTest1Snippet(int a) { + Integer v = a; + + if (v == a) { + return v; + } else { + return null; + } + } + + @Test + public void materializeTest1() { + test("materializeTest1Snippet", 1); + } + + public static int intTest1Snippet() { + return Integer.valueOf(1); + } + + @Test + public void intTest1() { + ValueNode result = getResult("intTest1Snippet"); + Assert.assertTrue(result.isConstant()); + Assert.assertEquals(1, result.asJavaConstant().asInt()); + } + + public static int mergeTest1Snippet(boolean d, int a, int b) { + Integer v; + if (d) { + v = a; + } else { + v = b; + } + return v; + } + + @Test + public void mergeTest1() { + processMethod("mergeTest1Snippet"); + } + + public static boolean equalsTest1Snippet(int x, int y) { + Integer a = x; + Integer b = y; + return a == b; + } + + @Test + public void equalsTest1() { + processMethod("equalsTest1Snippet"); + } + + public static int loopTest1Snippet(int n, int v) { + Integer sum = 0; + for (int i = 0; i < n; i++) { + sum += v; + } + return sum; + } + + @Test + public void loopTest1() { + processMethod("loopTest1Snippet"); + + } + + final ValueNode getResult(String snippet) { + processMethod(snippet); + assertDeepEquals(1, graph.getNodes(ReturnNode.TYPE).count()); + return graph.getNodes(ReturnNode.TYPE).first().result(); + } + + private void processMethod(final String snippet) { + graph = parseEager(snippet, AllowAssumptions.NO); + HighTierContext context = getDefaultHighTierContext(); + new InliningPhase(new CanonicalizerPhase()).apply(graph, context); + new PartialEscapePhase(false, new CanonicalizerPhase()).apply(graph, context); + } + + private void compareGraphs(final String snippet, final String referenceSnippet) { + compareGraphs(snippet, referenceSnippet, false, false); + } + + private void compareGraphs(final String snippet, final String referenceSnippet, final boolean loopPeeling, final boolean excludeVirtual) { + graph = parseEager(snippet, AllowAssumptions.NO); + HighTierContext context = getDefaultHighTierContext(); + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + canonicalizer.apply(graph, context); + new InliningPhase(new CanonicalizerPhase()).apply(graph, context); + if (loopPeeling) { + new LoopPeelingPhase(new DefaultLoopPolicies()).apply(graph, context); + } + new DeadCodeEliminationPhase().apply(graph); + canonicalizer.apply(graph, context); + new PartialEscapePhase(false, canonicalizer).apply(graph, context); + + new DeadCodeEliminationPhase().apply(graph); + canonicalizer.apply(graph, context); + + StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.YES); + new InliningPhase(new CanonicalizerPhase()).apply(referenceGraph, context); + new DeadCodeEliminationPhase().apply(referenceGraph); + new CanonicalizerPhase().apply(referenceGraph, context); + + assertEquals(referenceGraph, graph, excludeVirtual, true); + } +}