1 /* 2 * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package org.graalvm.compiler.core.test; 24 25 import org.junit.Assert; 26 import org.junit.Ignore; 27 import org.junit.Test; 28 29 import org.graalvm.compiler.loop.DefaultLoopPolicies; 30 import org.graalvm.compiler.loop.phases.LoopPeelingPhase; 31 import org.graalvm.compiler.nodes.ReturnNode; 32 import org.graalvm.compiler.nodes.StructuredGraph; 33 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; 34 import org.graalvm.compiler.nodes.ValueNode; 35 import org.graalvm.compiler.phases.common.CanonicalizerPhase; 36 import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; 37 import org.graalvm.compiler.phases.common.inlining.InliningPhase; 38 import org.graalvm.compiler.phases.tiers.HighTierContext; 39 import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; 40 41 /** 42 * In the following tests, the usages of local variable "a" are replaced with the integer constant 43 * 0. Then boxing elimination is applied and it is verified that the resulting graph is equal to the 44 * graph of the method that just has a "return 1" statement in it. 45 */ 46 public class BoxingEliminationTest extends GraalCompilerTest { 47 48 private static final Short s = 2; 49 50 @SuppressWarnings("all") 51 public static short referenceSnippet1() { 52 return 1; 53 } 54 55 @SuppressWarnings("all") 56 public static short referenceSnippet2() { 57 return 2; 58 } 59 60 public static Short boxedShort() { 61 return 1; 62 } 63 64 public static Object boxedObjectShort() { 65 return (short) 1; 66 } 67 68 public static Object boxedObjectInteger() { 69 return 1; 70 } 71 72 public static Integer boxedInteger() { 73 return 2; 74 } 75 76 public static Short constantBoxedShort() { 77 return s; 78 } 79 80 @Test 81 public void test1() { 82 compareGraphs("test1Snippet", "referenceSnippet1"); 83 } 84 85 @SuppressWarnings("all") 86 public static short test1Snippet() { 87 return boxedShort(); 88 } 89 90 @Test 91 public void test2() { 92 compareGraphs("test2Snippet", "referenceSnippet1"); 93 } 94 95 @SuppressWarnings("all") 96 public static short test2Snippet() { 97 return (Short) boxedObjectShort(); 98 } 99 100 @Test 101 public void test3() { 102 compareGraphs("test3Snippet", "referenceSnippet1"); 103 } 104 105 @SuppressWarnings("all") 106 public static short test3Snippet() { 107 short b = boxedShort(); 108 if (b < 0) { 109 b = boxedShort(); 110 } 111 return b; 112 } 113 114 @Test 115 public void test4() { 116 compareGraphs("test4Snippet", "referenceSnippet2"); 117 } 118 119 @SuppressWarnings("all") 120 public static short test4Snippet() { 121 return constantBoxedShort(); 122 } 123 124 @Ignore 125 @Test 126 public void testLoop() { 127 compareGraphs("testLoopSnippet", "referenceLoopSnippet", false, true); 128 } 129 130 public static int testLoopSnippet(int n, int a) { 131 Integer sum = a; 132 for (Integer i = 0; i < n; i++) { 133 sum += i; 134 } 135 return sum; 136 } 137 138 public static int referenceLoopSnippet(int n, int a) { 139 int sum = a; 140 for (int i = 0; i < n; i++) { 141 sum += i; 142 } 143 return sum; 144 } 145 146 @Test 147 public void testLoop2() { 148 compareGraphs("testLoop2Snippet", "referenceLoop2Snippet", true, true); 149 } 150 151 public static int testLoop2Snippet(int n, Integer a) { 152 Integer sum = a; 153 for (Integer i = 0; i < n; i++) { 154 sum += i; 155 } 156 return sum; 157 } 158 159 public static int referenceLoop2Snippet(int n, Integer a) { 160 Integer sum0; 161 if (n <= 0) { 162 sum0 = a; 163 } else { 164 int sum = a; 165 for (int i = 0; i < n; i++) { 166 sum += i; 167 } 168 sum0 = sum; 169 } 170 return sum0; 171 } 172 173 public static int referenceIfSnippet(int a) { 174 int result; 175 if (a < 0) { 176 result = 2; 177 } else { 178 result = 1; 179 } 180 return result; 181 } 182 183 @Test 184 public void testIf() { 185 compareGraphs("testIfSnippet", "referenceIfSnippet"); 186 } 187 188 public static int testIfSnippet(int a) { 189 Integer result; 190 if (a < 0) { 191 result = boxedInteger(); 192 } else { 193 result = (Integer) boxedObjectInteger(); 194 } 195 return result; 196 } 197 198 @Test 199 public void testComparison() { 200 compareGraphs("testComparison1Snippet", "referenceComparisonSnippet"); 201 compareGraphs("testComparison2Snippet", "referenceComparisonSnippet"); 202 } 203 204 @SuppressWarnings("cast") 205 public static boolean testComparison1Snippet(int a, int b) { 206 return ((Integer) a) == b; 207 } 208 209 public static boolean testComparison2Snippet(int a, int b) { 210 Integer x = a; 211 Integer y = b; 212 return x == y; 213 } 214 215 public static boolean referenceComparisonSnippet(int a, int b) { 216 return a == b; 217 } 218 219 @Test 220 public void testLateCanonicalization() { 221 compareGraphs("testLateCanonicalizationSnippet", "referenceLateCanonicalizationSnippet"); 222 } 223 224 public static boolean testLateCanonicalizationSnippet(int a) { 225 Integer x = a; 226 Integer y = 1000; 227 return x == y; 228 } 229 230 public static boolean referenceLateCanonicalizationSnippet(int a) { 231 return a == 1000; 232 } 233 234 private StructuredGraph graph; 235 236 public static Integer materializeReferenceSnippet(int a) { 237 return Integer.valueOf(a); 238 } 239 240 public static Integer materializeTest1Snippet(int a) { 241 Integer v = a; 242 243 if (v == a) { 244 return v; 245 } else { 246 return null; 247 } 248 } 249 250 @Test 251 public void materializeTest1() { 252 test("materializeTest1Snippet", 1); 253 } 254 255 public static int intTest1Snippet() { 256 return Integer.valueOf(1); 257 } 258 259 @Test 260 public void intTest1() { 261 ValueNode result = getResult("intTest1Snippet"); 262 Assert.assertTrue(result.isConstant()); 263 Assert.assertEquals(1, result.asJavaConstant().asInt()); 264 } 265 266 public static int mergeTest1Snippet(boolean d, int a, int b) { 267 Integer v; 268 if (d) { 269 v = a; 270 } else { 271 v = b; 272 } 273 return v; 274 } 275 276 @Test 277 public void mergeTest1() { 278 processMethod("mergeTest1Snippet"); 279 } 280 281 public static boolean equalsTest1Snippet(int x, int y) { 282 Integer a = x; 283 Integer b = y; 284 return a == b; 285 } 286 287 @Test 288 public void equalsTest1() { 289 processMethod("equalsTest1Snippet"); 290 } 291 292 public static int loopTest1Snippet(int n, int v) { 293 Integer sum = 0; 294 for (int i = 0; i < n; i++) { 295 sum += v; 296 } 297 return sum; 298 } 299 300 @Test 301 public void loopTest1() { 302 processMethod("loopTest1Snippet"); 303 304 } 305 306 final ValueNode getResult(String snippet) { 307 processMethod(snippet); 308 assertDeepEquals(1, graph.getNodes(ReturnNode.TYPE).count()); 309 return graph.getNodes(ReturnNode.TYPE).first().result(); 310 } 311 312 private void processMethod(final String snippet) { 313 graph = parseEager(snippet, AllowAssumptions.NO); 314 HighTierContext context = getDefaultHighTierContext(); 315 new InliningPhase(new CanonicalizerPhase()).apply(graph, context); 316 new PartialEscapePhase(false, new CanonicalizerPhase()).apply(graph, context); 317 } 318 319 private void compareGraphs(final String snippet, final String referenceSnippet) { 320 compareGraphs(snippet, referenceSnippet, false, false); 321 } 322 323 private void compareGraphs(final String snippet, final String referenceSnippet, final boolean loopPeeling, final boolean excludeVirtual) { 324 graph = parseEager(snippet, AllowAssumptions.NO); 325 HighTierContext context = getDefaultHighTierContext(); 326 CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); 327 canonicalizer.apply(graph, context); 328 new InliningPhase(new CanonicalizerPhase()).apply(graph, context); 329 if (loopPeeling) { 330 new LoopPeelingPhase(new DefaultLoopPolicies()).apply(graph, context); 331 } 332 new DeadCodeEliminationPhase().apply(graph); 333 canonicalizer.apply(graph, context); 334 new PartialEscapePhase(false, canonicalizer).apply(graph, context); 335 336 new DeadCodeEliminationPhase().apply(graph); 337 canonicalizer.apply(graph, context); 338 339 StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.YES); 340 new InliningPhase(new CanonicalizerPhase()).apply(referenceGraph, context); 341 new DeadCodeEliminationPhase().apply(referenceGraph); 342 new CanonicalizerPhase().apply(referenceGraph, context); 343 344 assertEquals(referenceGraph, graph, excludeVirtual, true); 345 } 346 }