1 /* 2 * Copyright (c) 2011, 2018, 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 24 25 package org.graalvm.compiler.core.test; 26 27 import org.graalvm.compiler.loop.DefaultLoopPolicies; 28 import org.graalvm.compiler.loop.phases.LoopPeelingPhase; 29 import org.graalvm.compiler.nodes.ReturnNode; 30 import org.graalvm.compiler.nodes.StructuredGraph; 31 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; 32 import org.graalvm.compiler.nodes.ValueNode; 33 import org.graalvm.compiler.phases.common.CanonicalizerPhase; 34 import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; 35 import org.graalvm.compiler.phases.tiers.HighTierContext; 36 import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; 37 import org.junit.Assert; 38 import org.junit.Ignore; 39 import org.junit.Test; 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") referenceSnippet1()51 public static short referenceSnippet1() { 52 return 1; 53 } 54 55 @SuppressWarnings("all") referenceSnippet2()56 public static short referenceSnippet2() { 57 return 2; 58 } 59 boxedShort()60 public static Short boxedShort() { 61 return 1; 62 } 63 boxedObjectShort()64 public static Object boxedObjectShort() { 65 return (short) 1; 66 } 67 boxedObjectInteger()68 public static Object boxedObjectInteger() { 69 return 1; 70 } 71 boxedInteger()72 public static Integer boxedInteger() { 73 return 2; 74 } 75 constantBoxedShort()76 public static Short constantBoxedShort() { 77 return s; 78 } 79 80 @Test test1()81 public void test1() { 82 compareGraphs("test1Snippet", "referenceSnippet1"); 83 } 84 85 @SuppressWarnings("all") test1Snippet()86 public static short test1Snippet() { 87 return boxedShort(); 88 } 89 90 @Test test2()91 public void test2() { 92 compareGraphs("test2Snippet", "referenceSnippet1"); 93 } 94 95 @SuppressWarnings("all") test2Snippet()96 public static short test2Snippet() { 97 return (Short) boxedObjectShort(); 98 } 99 100 @Test test3()101 public void test3() { 102 compareGraphs("test3Snippet", "referenceSnippet1"); 103 } 104 105 @SuppressWarnings("all") test3Snippet()106 public static short test3Snippet() { 107 short b = boxedShort(); 108 if (b < 0) { 109 b = boxedShort(); 110 } 111 return b; 112 } 113 114 @Test test4()115 public void test4() { 116 compareGraphs("test4Snippet", "referenceSnippet2"); 117 } 118 119 @SuppressWarnings("all") test4Snippet()120 public static short test4Snippet() { 121 return constantBoxedShort(); 122 } 123 124 @Ignore 125 @Test testLoop()126 public void testLoop() { 127 compareGraphs("testLoopSnippet", "referenceLoopSnippet", false, true); 128 } 129 testLoopSnippet(int n, int a)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 referenceLoopSnippet(int n, int a)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 testLoop2()147 public void testLoop2() { 148 compareGraphs("testLoop2Snippet", "referenceLoop2Snippet", true, true); 149 } 150 testLoop2Snippet(int n, Integer a)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 referenceLoop2Snippet(int n, Integer a)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 = 1; i < n; i++) { 166 sum += i; 167 } 168 sum0 = sum; 169 } 170 return sum0; 171 } 172 referenceIfSnippet(int a)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 testIf()184 public void testIf() { 185 compareGraphs("testIfSnippet", "referenceIfSnippet"); 186 } 187 testIfSnippet(int a)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 testComparison()199 public void testComparison() { 200 compareGraphs("testComparison1Snippet", "referenceComparisonSnippet"); 201 compareGraphs("testComparison2Snippet", "referenceComparisonSnippet"); 202 } 203 204 @SuppressWarnings("cast") testComparison1Snippet(int a, int b)205 public static boolean testComparison1Snippet(int a, int b) { 206 return ((Integer) a) == b; 207 } 208 testComparison2Snippet(int a, int b)209 public static boolean testComparison2Snippet(int a, int b) { 210 Integer x = a; 211 Integer y = b; 212 return x == y; 213 } 214 referenceComparisonSnippet(int a, int b)215 public static boolean referenceComparisonSnippet(int a, int b) { 216 return a == b; 217 } 218 219 @Test testLateCanonicalization()220 public void testLateCanonicalization() { 221 compareGraphs("testLateCanonicalizationSnippet", "referenceLateCanonicalizationSnippet"); 222 } 223 testLateCanonicalizationSnippet(int a)224 public static boolean testLateCanonicalizationSnippet(int a) { 225 Integer x = a; 226 Integer y = 1000; 227 return x == y; 228 } 229 referenceLateCanonicalizationSnippet(int a)230 public static boolean referenceLateCanonicalizationSnippet(int a) { 231 return a == 1000; 232 } 233 234 private StructuredGraph graph; 235 materializeReferenceSnippet(int a)236 public static Integer materializeReferenceSnippet(int a) { 237 return Integer.valueOf(a); 238 } 239 materializeTest1Snippet(int a)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 materializeTest1()251 public void materializeTest1() { 252 test("materializeTest1Snippet", 1); 253 } 254 intTest1Snippet()255 public static int intTest1Snippet() { 256 return Integer.valueOf(1); 257 } 258 259 @Test intTest1()260 public void intTest1() { 261 ValueNode result = getResult("intTest1Snippet"); 262 Assert.assertTrue(result.isConstant()); 263 Assert.assertEquals(1, result.asJavaConstant().asInt()); 264 } 265 mergeTest1Snippet(boolean d, int a, int b)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 mergeTest1()277 public void mergeTest1() { 278 processMethod("mergeTest1Snippet"); 279 } 280 equalsTest1Snippet(int x, int y)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 equalsTest1()288 public void equalsTest1() { 289 processMethod("equalsTest1Snippet"); 290 } 291 loopTest1Snippet(int n, int v)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 loopTest1()301 public void loopTest1() { 302 processMethod("loopTest1Snippet"); 303 304 } 305 getResult(String snippet)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 processMethod(final String snippet)312 private void processMethod(final String snippet) { 313 graph = parseEager(snippet, AllowAssumptions.NO); 314 HighTierContext context = getDefaultHighTierContext(); 315 createInliningPhase().apply(graph, context); 316 new PartialEscapePhase(false, new CanonicalizerPhase(), graph.getOptions()).apply(graph, context); 317 } 318 compareGraphs(final String snippet, final String referenceSnippet)319 private void compareGraphs(final String snippet, final String referenceSnippet) { 320 compareGraphs(snippet, referenceSnippet, false, false); 321 } 322 compareGraphs(final String snippet, final String referenceSnippet, final boolean loopPeeling, final boolean excludeVirtual)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 createInliningPhase().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, graph.getOptions()).apply(graph, context); 335 336 new DeadCodeEliminationPhase().apply(graph); 337 canonicalizer.apply(graph, context); 338 339 StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.YES); 340 createInliningPhase().apply(referenceGraph, context); 341 new DeadCodeEliminationPhase().apply(referenceGraph); 342 new CanonicalizerPhase().apply(referenceGraph, context); 343 344 assertEquals(referenceGraph, graph, excludeVirtual, true); 345 } 346 } 347