| /* |
| * 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); |
| } |
| } |