blob: 03ca1c4136b1e352bc9200c1b8e8e6142a28a940 [file] [log] [blame]
/*
* 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);
}
}