1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 class Circle { Circle(double radius)18 Circle(double radius) { 19 this.radius = radius; 20 } getRadius()21 public double getRadius() { 22 return radius; 23 } getArea()24 public double getArea() { 25 return radius * radius * Math.PI; 26 } 27 private double radius; 28 } 29 30 class TestClass { 31 static { 32 sTestClassObj = new TestClass(-1, -2); 33 } TestClass()34 TestClass() { 35 } TestClass(int i, int j)36 TestClass(int i, int j) { 37 this.i = i; 38 this.j = j; 39 } 40 int i; 41 int j; 42 volatile int k; 43 TestClass next; 44 String str; 45 static int si; 46 static TestClass sTestClassObj; 47 } 48 49 class SubTestClass extends TestClass { 50 int k; 51 } 52 53 class TestClass2 { 54 int i; 55 int j; 56 } 57 58 class TestClass3 { 59 float floatField = 8.0f; 60 boolean test1 = true; 61 } 62 63 class Finalizable { 64 static boolean sVisited = false; 65 static final int VALUE = 0xbeef; 66 int i; 67 finalize()68 protected void finalize() { 69 if (i != VALUE) { 70 System.out.println("Where is the beef?"); 71 } 72 sVisited = true; 73 } 74 } 75 76 interface Filter { isValid(int i)77 public boolean isValid(int i); 78 } 79 80 public class Main { 81 82 /// CHECK-START: double Main.calcCircleArea(double) load_store_elimination (before) 83 /// CHECK: NewInstance 84 /// CHECK: InstanceFieldSet 85 /// CHECK: InstanceFieldGet 86 87 /// CHECK-START: double Main.calcCircleArea(double) load_store_elimination (after) 88 /// CHECK-NOT: NewInstance 89 /// CHECK-NOT: InstanceFieldSet 90 /// CHECK-NOT: InstanceFieldGet 91 calcCircleArea(double radius)92 static double calcCircleArea(double radius) { 93 return new Circle(radius).getArea(); 94 } 95 96 /// CHECK-START: int Main.test1(TestClass, TestClass) load_store_elimination (before) 97 /// CHECK: InstanceFieldSet 98 /// CHECK: InstanceFieldSet 99 /// CHECK: InstanceFieldGet 100 /// CHECK: InstanceFieldGet 101 102 /// CHECK-START: int Main.test1(TestClass, TestClass) load_store_elimination (after) 103 /// CHECK: InstanceFieldSet 104 /// CHECK: InstanceFieldSet 105 /// CHECK-NOT: NullCheck 106 /// CHECK-NOT: InstanceFieldGet 107 108 // Different fields shouldn't alias. test1(TestClass obj1, TestClass obj2)109 static int test1(TestClass obj1, TestClass obj2) { 110 obj1.i = 1; 111 obj2.j = 2; 112 return obj1.i + obj2.j; 113 } 114 115 /// CHECK-START: int Main.test2(TestClass) load_store_elimination (before) 116 /// CHECK: InstanceFieldSet 117 /// CHECK: InstanceFieldSet 118 /// CHECK: InstanceFieldGet 119 120 /// CHECK-START: int Main.test2(TestClass) load_store_elimination (after) 121 /// CHECK: InstanceFieldSet 122 /// CHECK-NOT: NullCheck 123 /// CHECK-NOT: InstanceFieldSet 124 /// CHECK-NOT: InstanceFieldGet 125 126 // Redundant store of the same value. test2(TestClass obj)127 static int test2(TestClass obj) { 128 obj.j = 1; 129 obj.j = 1; 130 return obj.j; 131 } 132 133 /// CHECK-START: int Main.test3(TestClass) load_store_elimination (before) 134 /// CHECK: StaticFieldGet 135 /// CHECK: NewInstance 136 /// CHECK: InstanceFieldSet 137 /// CHECK: InstanceFieldSet 138 /// CHECK: InstanceFieldSet 139 /// CHECK: InstanceFieldSet 140 /// CHECK: InstanceFieldGet 141 /// CHECK: InstanceFieldGet 142 /// CHECK: InstanceFieldGet 143 /// CHECK: InstanceFieldGet 144 145 /// CHECK-START: int Main.test3(TestClass) load_store_elimination (after) 146 /// CHECK: StaticFieldGet 147 /// CHECK: NewInstance 148 /// CHECK: InstanceFieldSet 149 /// CHECK: InstanceFieldSet 150 /// CHECK: InstanceFieldSet 151 /// CHECK: InstanceFieldSet 152 /// CHECK-NOT: InstanceFieldGet 153 /// CHECK-NOT: StaticFieldGet 154 155 // A new allocation (even non-singleton) shouldn't alias with pre-existing values. test3(TestClass obj)156 static int test3(TestClass obj) { 157 TestClass obj1 = TestClass.sTestClassObj; 158 TestClass obj2 = new TestClass(); // Cannot alias with obj or obj1 which pre-exist. 159 obj.next = obj2; // Make obj2 a non-singleton. 160 // All stores below need to stay since obj/obj1/obj2 are not singletons. 161 obj.i = 1; 162 obj1.j = 2; 163 // Following stores won't kill values of obj.i and obj1.j. 164 obj2.i = 3; 165 obj2.j = 4; 166 return obj.i + obj1.j + obj2.i + obj2.j; 167 } 168 169 /// CHECK-START: int Main.test4(TestClass, boolean) load_store_elimination (before) 170 /// CHECK: InstanceFieldSet 171 /// CHECK: InstanceFieldGet 172 /// CHECK: Return 173 /// CHECK: InstanceFieldSet 174 175 /// CHECK-START: int Main.test4(TestClass, boolean) load_store_elimination (after) 176 /// CHECK: InstanceFieldSet 177 /// CHECK-NOT: NullCheck 178 /// CHECK-NOT: InstanceFieldGet 179 /// CHECK: Return 180 /// CHECK: InstanceFieldSet 181 182 // Set and merge the same value in two branches. test4(TestClass obj, boolean b)183 static int test4(TestClass obj, boolean b) { 184 if (b) { 185 obj.i = 1; 186 } else { 187 obj.i = 1; 188 } 189 return obj.i; 190 } 191 192 /// CHECK-START: int Main.test5(TestClass, boolean) load_store_elimination (before) 193 /// CHECK: InstanceFieldSet 194 /// CHECK: InstanceFieldGet 195 /// CHECK: Return 196 /// CHECK: InstanceFieldSet 197 198 /// CHECK-START: int Main.test5(TestClass, boolean) load_store_elimination (after) 199 /// CHECK: InstanceFieldSet 200 /// CHECK: InstanceFieldGet 201 /// CHECK: Return 202 /// CHECK: InstanceFieldSet 203 204 // Set and merge different values in two branches. test5(TestClass obj, boolean b)205 static int test5(TestClass obj, boolean b) { 206 if (b) { 207 obj.i = 1; 208 } else { 209 obj.i = 2; 210 } 211 return obj.i; 212 } 213 214 /// CHECK-START: int Main.test6(TestClass, TestClass, boolean) load_store_elimination (before) 215 /// CHECK: InstanceFieldSet 216 /// CHECK: InstanceFieldSet 217 /// CHECK: InstanceFieldSet 218 /// CHECK: InstanceFieldGet 219 /// CHECK: InstanceFieldGet 220 221 /// CHECK-START: int Main.test6(TestClass, TestClass, boolean) load_store_elimination (after) 222 /// CHECK: InstanceFieldSet 223 /// CHECK: InstanceFieldSet 224 /// CHECK: InstanceFieldSet 225 /// CHECK: InstanceFieldGet 226 /// CHECK-NOT: NullCheck 227 /// CHECK-NOT: InstanceFieldGet 228 229 // Setting the same value doesn't clear the value for aliased locations. test6(TestClass obj1, TestClass obj2, boolean b)230 static int test6(TestClass obj1, TestClass obj2, boolean b) { 231 obj1.i = 1; 232 obj1.j = 2; 233 if (b) { 234 obj2.j = 2; 235 } 236 return obj1.j + obj2.j; 237 } 238 239 /// CHECK-START: int Main.test7(TestClass) load_store_elimination (before) 240 /// CHECK: InstanceFieldSet 241 /// CHECK: InstanceFieldGet 242 243 /// CHECK-START: int Main.test7(TestClass) load_store_elimination (after) 244 /// CHECK: InstanceFieldSet 245 /// CHECK: InstanceFieldGet 246 247 // Invocation should kill values in non-singleton heap locations. test7(TestClass obj)248 static int test7(TestClass obj) { 249 obj.i = 1; 250 System.out.print(""); 251 return obj.i; 252 } 253 254 /// CHECK-START: int Main.test8() load_store_elimination (before) 255 /// CHECK: NewInstance 256 /// CHECK: InstanceFieldSet 257 /// CHECK: InvokeVirtual 258 /// CHECK: InstanceFieldGet 259 260 /// CHECK-START: int Main.test8() load_store_elimination (after) 261 /// CHECK-NOT: NewInstance 262 /// CHECK-NOT: InstanceFieldSet 263 /// CHECK: InvokeVirtual 264 /// CHECK-NOT: NullCheck 265 /// CHECK-NOT: InstanceFieldGet 266 267 // Invocation should not kill values in singleton heap locations. test8()268 static int test8() { 269 TestClass obj = new TestClass(); 270 obj.i = 1; 271 System.out.print(""); 272 return obj.i; 273 } 274 275 /// CHECK-START: int Main.test9(TestClass) load_store_elimination (before) 276 /// CHECK: NewInstance 277 /// CHECK: InstanceFieldSet 278 /// CHECK: InstanceFieldSet 279 /// CHECK: InstanceFieldGet 280 281 /// CHECK-START: int Main.test9(TestClass) load_store_elimination (after) 282 /// CHECK: NewInstance 283 /// CHECK: InstanceFieldSet 284 /// CHECK: InstanceFieldSet 285 /// CHECK: InstanceFieldGet 286 287 // Invocation should kill values in non-singleton heap locations. test9(TestClass obj)288 static int test9(TestClass obj) { 289 TestClass obj2 = new TestClass(); 290 obj2.i = 1; 291 obj.next = obj2; 292 System.out.print(""); 293 return obj2.i; 294 } 295 296 /// CHECK-START: int Main.test10(TestClass) load_store_elimination (before) 297 /// CHECK: StaticFieldGet 298 /// CHECK: InstanceFieldGet 299 /// CHECK: StaticFieldSet 300 /// CHECK: InstanceFieldGet 301 302 /// CHECK-START: int Main.test10(TestClass) load_store_elimination (after) 303 /// CHECK: StaticFieldGet 304 /// CHECK: InstanceFieldGet 305 /// CHECK: StaticFieldSet 306 /// CHECK-NOT: NullCheck 307 /// CHECK-NOT: InstanceFieldGet 308 309 // Static fields shouldn't alias with instance fields. test10(TestClass obj)310 static int test10(TestClass obj) { 311 TestClass.si += obj.i; 312 return obj.i; 313 } 314 315 /// CHECK-START: int Main.test11(TestClass) load_store_elimination (before) 316 /// CHECK: InstanceFieldSet 317 /// CHECK: InstanceFieldGet 318 319 /// CHECK-START: int Main.test11(TestClass) load_store_elimination (after) 320 /// CHECK: InstanceFieldSet 321 /// CHECK-NOT: NullCheck 322 /// CHECK-NOT: InstanceFieldGet 323 324 // Loop without heap writes. 325 // obj.i is actually hoisted to the loop pre-header by licm already. test11(TestClass obj)326 static int test11(TestClass obj) { 327 obj.i = 1; 328 int sum = 0; 329 for (int i = 0; i < 10; i++) { 330 sum += obj.i; 331 } 332 return sum; 333 } 334 335 /// CHECK-START: int Main.test12(TestClass, TestClass) load_store_elimination (before) 336 /// CHECK: InstanceFieldSet 337 /// CHECK: InstanceFieldGet 338 /// CHECK: InstanceFieldSet 339 340 /// CHECK-START: int Main.test12(TestClass, TestClass) load_store_elimination (after) 341 /// CHECK: InstanceFieldSet 342 /// CHECK: InstanceFieldGet 343 /// CHECK: InstanceFieldSet 344 345 // Loop with heap writes. test12(TestClass obj1, TestClass obj2)346 static int test12(TestClass obj1, TestClass obj2) { 347 obj1.i = 1; 348 int sum = 0; 349 for (int i = 0; i < 10; i++) { 350 sum += obj1.i; 351 obj2.i = sum; 352 } 353 return sum; 354 } 355 356 /// CHECK-START: int Main.test13(TestClass, TestClass2) load_store_elimination (before) 357 /// CHECK: InstanceFieldSet 358 /// CHECK: InstanceFieldSet 359 /// CHECK: InstanceFieldGet 360 /// CHECK: InstanceFieldGet 361 362 /// CHECK-START: int Main.test13(TestClass, TestClass2) load_store_elimination (after) 363 /// CHECK: InstanceFieldSet 364 /// CHECK: InstanceFieldSet 365 /// CHECK-NOT: NullCheck 366 /// CHECK-NOT: InstanceFieldGet 367 368 // Different classes shouldn't alias. test13(TestClass obj1, TestClass2 obj2)369 static int test13(TestClass obj1, TestClass2 obj2) { 370 obj1.i = 1; 371 obj2.i = 2; 372 return obj1.i + obj2.i; 373 } 374 375 /// CHECK-START: int Main.test14(TestClass, SubTestClass) load_store_elimination (before) 376 /// CHECK: InstanceFieldSet 377 /// CHECK: InstanceFieldSet 378 /// CHECK: InstanceFieldGet 379 380 /// CHECK-START: int Main.test14(TestClass, SubTestClass) load_store_elimination (after) 381 /// CHECK: InstanceFieldSet 382 /// CHECK: InstanceFieldSet 383 /// CHECK: InstanceFieldGet 384 385 // Subclass may alias with super class. test14(TestClass obj1, SubTestClass obj2)386 static int test14(TestClass obj1, SubTestClass obj2) { 387 obj1.i = 1; 388 obj2.i = 2; 389 return obj1.i; 390 } 391 392 /// CHECK-START: int Main.test15() load_store_elimination (before) 393 /// CHECK: StaticFieldSet 394 /// CHECK: StaticFieldSet 395 /// CHECK: StaticFieldGet 396 397 /// CHECK-START: int Main.test15() load_store_elimination (after) 398 /// CHECK: <<Const2:i\d+>> IntConstant 2 399 /// CHECK: StaticFieldSet 400 /// CHECK: StaticFieldSet 401 /// CHECK-NOT: StaticFieldGet 402 /// CHECK: Return [<<Const2>>] 403 404 // Static field access from subclass's name. test15()405 static int test15() { 406 TestClass.si = 1; 407 SubTestClass.si = 2; 408 return TestClass.si; 409 } 410 411 /// CHECK-START: int Main.test16() load_store_elimination (before) 412 /// CHECK: NewInstance 413 /// CHECK: InstanceFieldSet 414 /// CHECK: InstanceFieldSet 415 /// CHECK: InstanceFieldGet 416 /// CHECK: InstanceFieldGet 417 418 /// CHECK-START: int Main.test16() load_store_elimination (after) 419 /// CHECK-NOT: NewInstance 420 /// CHECK-NOT: InstanceFieldSet 421 /// CHECK-NOT: InstanceFieldGet 422 423 // Test inlined constructor. test16()424 static int test16() { 425 TestClass obj = new TestClass(1, 2); 426 return obj.i + obj.j; 427 } 428 429 /// CHECK-START: int Main.test17() load_store_elimination (before) 430 /// CHECK: NewInstance 431 /// CHECK: InstanceFieldSet 432 /// CHECK: InstanceFieldGet 433 434 /// CHECK-START: int Main.test17() load_store_elimination (after) 435 /// CHECK: <<Const0:i\d+>> IntConstant 0 436 /// CHECK-NOT: NewInstance 437 /// CHECK-NOT: InstanceFieldSet 438 /// CHECK-NOT: InstanceFieldGet 439 /// CHECK: Return [<<Const0>>] 440 441 // Test getting default value. test17()442 static int test17() { 443 TestClass obj = new TestClass(); 444 obj.j = 1; 445 return obj.i; 446 } 447 448 /// CHECK-START: int Main.test18(TestClass) load_store_elimination (before) 449 /// CHECK: InstanceFieldSet 450 /// CHECK: InstanceFieldGet 451 452 /// CHECK-START: int Main.test18(TestClass) load_store_elimination (after) 453 /// CHECK: InstanceFieldSet 454 /// CHECK: InstanceFieldGet 455 456 // Volatile field load/store shouldn't be eliminated. test18(TestClass obj)457 static int test18(TestClass obj) { 458 obj.k = 1; 459 return obj.k; 460 } 461 462 /// CHECK-START: float Main.test19(float[], float[]) load_store_elimination (before) 463 /// CHECK: {{f\d+}} ArrayGet 464 /// CHECK: {{f\d+}} ArrayGet 465 466 /// CHECK-START: float Main.test19(float[], float[]) load_store_elimination (after) 467 /// CHECK: {{f\d+}} ArrayGet 468 /// CHECK-NOT: {{f\d+}} ArrayGet 469 470 // I/F, J/D aliasing should not happen any more and LSE should eliminate the load. test19(float[] fa1, float[] fa2)471 static float test19(float[] fa1, float[] fa2) { 472 fa1[0] = fa2[0]; 473 return fa1[0]; 474 } 475 476 /// CHECK-START: TestClass Main.test20() load_store_elimination (before) 477 /// CHECK: NewInstance 478 /// CHECK: InstanceFieldSet 479 480 /// CHECK-START: TestClass Main.test20() load_store_elimination (after) 481 /// CHECK: NewInstance 482 /// CHECK-NOT: InstanceFieldSet 483 484 // Storing default heap value is redundant if the heap location has the 485 // default heap value. test20()486 static TestClass test20() { 487 TestClass obj = new TestClass(); 488 obj.i = 0; 489 return obj; 490 } 491 492 /// CHECK-START: void Main.test21(TestClass) load_store_elimination (before) 493 /// CHECK: NewInstance 494 /// CHECK: InstanceFieldSet 495 /// CHECK: InstanceFieldSet 496 /// CHECK: InstanceFieldSet 497 /// CHECK: InstanceFieldGet 498 /// CHECK: InstanceFieldGet 499 500 /// CHECK-START: void Main.test21(TestClass) load_store_elimination (after) 501 /// CHECK: NewInstance 502 /// CHECK: InstanceFieldSet 503 /// CHECK: InstanceFieldSet 504 /// CHECK: InstanceFieldSet 505 /// CHECK: InstanceFieldGet 506 /// CHECK: InstanceFieldGet 507 508 // Loop side effects can kill heap values, stores need to be kept in that case. test21(TestClass obj0)509 static void test21(TestClass obj0) { 510 TestClass obj = new TestClass(); 511 obj0.str = "abc"; 512 obj.str = "abc"; 513 for (int i = 0; i < 2; i++) { 514 // Generate some loop side effect that writes into obj. 515 obj.str = "def"; 516 } 517 System.out.print(obj0.str.substring(0, 0) + obj.str.substring(0, 0)); 518 } 519 520 /// CHECK-START: int Main.test22() load_store_elimination (before) 521 /// CHECK: NewInstance 522 /// CHECK: InstanceFieldSet 523 /// CHECK: NewInstance 524 /// CHECK: InstanceFieldSet 525 /// CHECK: InstanceFieldGet 526 /// CHECK: NewInstance 527 /// CHECK: InstanceFieldSet 528 /// CHECK: InstanceFieldGet 529 /// CHECK: InstanceFieldGet 530 531 /// CHECK-START: int Main.test22() load_store_elimination (after) 532 /// CHECK-NOT: NewInstance 533 /// CHECK-NOT: InstanceFieldSet 534 /// CHECK-NOT: NewInstance 535 /// CHECK-NOT: InstanceFieldSet 536 /// CHECK-NOT: InstanceFieldGet 537 /// CHECK-NOT: NewInstance 538 /// CHECK-NOT: InstanceFieldSet 539 /// CHECK-NOT: InstanceFieldGet 540 /// CHECK-NOT: InstanceFieldGet 541 542 // For a singleton, loop side effects can kill its field values only if: 543 // (1) it dominiates the loop header, and 544 // (2) its fields are stored into inside a loop. test22()545 static int test22() { 546 int sum = 0; 547 TestClass obj1 = new TestClass(); 548 obj1.i = 2; // This store can be eliminated since obj1 is never stored into inside a loop. 549 for (int i = 0; i < 2; i++) { 550 TestClass obj2 = new TestClass(); 551 obj2.i = 3; // This store can be eliminated since the singleton is inside the loop. 552 sum += obj2.i; 553 } 554 TestClass obj3 = new TestClass(); 555 obj3.i = 5; // This store can be eliminated since the singleton is created after the loop. 556 sum += obj1.i + obj3.i; 557 return sum; 558 } 559 560 /// CHECK-START: int Main.test23(boolean) load_store_elimination (before) 561 /// CHECK: NewInstance 562 /// CHECK: InstanceFieldSet 563 /// CHECK: InstanceFieldGet 564 /// CHECK: InstanceFieldSet 565 /// CHECK: InstanceFieldGet 566 /// CHECK: Return 567 /// CHECK: InstanceFieldGet 568 /// CHECK: InstanceFieldSet 569 570 /// CHECK-START: int Main.test23(boolean) load_store_elimination (after) 571 /// CHECK: NewInstance 572 /// CHECK-NOT: InstanceFieldSet 573 /// CHECK-NOT: InstanceFieldGet 574 /// CHECK: InstanceFieldSet 575 /// CHECK: InstanceFieldGet 576 /// CHECK: Return 577 /// CHECK-NOT: InstanceFieldGet 578 /// CHECK: InstanceFieldSet 579 580 // Test store elimination on merging. test23(boolean b)581 static int test23(boolean b) { 582 TestClass obj = new TestClass(); 583 obj.i = 3; // This store can be eliminated since the value flows into each branch. 584 if (b) { 585 obj.i += 1; // This store cannot be eliminated due to the merge later. 586 } else { 587 obj.i += 2; // This store cannot be eliminated due to the merge later. 588 } 589 return obj.i; 590 } 591 592 /// CHECK-START: float Main.test24() load_store_elimination (before) 593 /// CHECK-DAG: <<True:i\d+>> IntConstant 1 594 /// CHECK-DAG: <<Float8:f\d+>> FloatConstant 8 595 /// CHECK-DAG: <<Float42:f\d+>> FloatConstant 42 596 /// CHECK-DAG: <<Obj:l\d+>> NewInstance 597 /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<True>>] 598 /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Float8>>] 599 /// CHECK-DAG: <<GetTest:z\d+>> InstanceFieldGet [<<Obj>>] 600 /// CHECK-DAG: <<GetField:f\d+>> InstanceFieldGet [<<Obj>>] 601 /// CHECK-DAG: <<Select:f\d+>> Select [<<Float42>>,<<GetField>>,<<GetTest>>] 602 /// CHECK-DAG: Return [<<Select>>] 603 604 /// CHECK-START: float Main.test24() load_store_elimination (after) 605 /// CHECK-DAG: <<True:i\d+>> IntConstant 1 606 /// CHECK-DAG: <<Float8:f\d+>> FloatConstant 8 607 /// CHECK-DAG: <<Float42:f\d+>> FloatConstant 42 608 /// CHECK-DAG: <<Select:f\d+>> Select [<<Float42>>,<<Float8>>,<<True>>] 609 /// CHECK-DAG: Return [<<Select>>] 610 test24()611 static float test24() { 612 float a = 42.0f; 613 TestClass3 obj = new TestClass3(); 614 if (obj.test1) { 615 a = obj.floatField; 616 } 617 return a; 618 } 619 620 /// CHECK-START: void Main.testFinalizable() load_store_elimination (before) 621 /// CHECK: NewInstance 622 /// CHECK: InstanceFieldSet 623 624 /// CHECK-START: void Main.testFinalizable() load_store_elimination (after) 625 /// CHECK: NewInstance 626 /// CHECK: InstanceFieldSet 627 628 // Allocations and stores into finalizable objects cannot be eliminated. testFinalizable()629 static void testFinalizable() { 630 Finalizable finalizable = new Finalizable(); 631 finalizable.i = Finalizable.VALUE; 632 } 633 getWeakReference()634 static java.lang.ref.WeakReference<Object> getWeakReference() { 635 return new java.lang.ref.WeakReference<>(new Object()); 636 } 637 testFinalizableByForcingGc()638 static void testFinalizableByForcingGc() { 639 testFinalizable(); 640 java.lang.ref.WeakReference<Object> reference = getWeakReference(); 641 642 Runtime runtime = Runtime.getRuntime(); 643 for (int i = 0; i < 20; ++i) { 644 runtime.gc(); 645 System.runFinalization(); 646 try { 647 Thread.sleep(1); 648 } catch (InterruptedException e) { 649 throw new AssertionError(e); 650 } 651 652 // Check to see if the weak reference has been garbage collected. 653 if (reference.get() == null) { 654 // A little bit more sleep time to make sure. 655 try { 656 Thread.sleep(100); 657 } catch (InterruptedException e) { 658 throw new AssertionError(e); 659 } 660 if (!Finalizable.sVisited) { 661 System.out.println("finalize() not called."); 662 } 663 return; 664 } 665 } 666 System.out.println("testFinalizableByForcingGc() failed to force gc."); 667 } 668 669 /// CHECK-START: int Main.$noinline$testHSelect(boolean) load_store_elimination (before) 670 /// CHECK: InstanceFieldSet 671 /// CHECK: Select 672 673 /// CHECK-START: int Main.$noinline$testHSelect(boolean) load_store_elimination (after) 674 /// CHECK: InstanceFieldSet 675 /// CHECK: Select 676 677 // Test that HSelect creates alias. $noinline$testHSelect(boolean b)678 static int $noinline$testHSelect(boolean b) { 679 if (sFlag) { 680 throw new Error(); 681 } 682 TestClass obj = new TestClass(); 683 TestClass obj2 = null; 684 obj.i = 0xdead; 685 if (b) { 686 obj2 = obj; 687 } 688 return obj2.i; 689 } 690 sumWithFilter(int[] array, Filter f)691 static int sumWithFilter(int[] array, Filter f) { 692 int sum = 0; 693 for (int i = 0; i < array.length; i++) { 694 if (f.isValid(array[i])) { 695 sum += array[i]; 696 } 697 } 698 return sum; 699 } 700 701 /// CHECK-START: int Main.sumWithinRange(int[], int, int) load_store_elimination (before) 702 /// CHECK: NewInstance 703 /// CHECK: InstanceFieldSet 704 /// CHECK: InstanceFieldSet 705 /// CHECK: InstanceFieldGet 706 /// CHECK: InstanceFieldGet 707 708 /// CHECK-START: int Main.sumWithinRange(int[], int, int) load_store_elimination (after) 709 /// CHECK-NOT: NewInstance 710 /// CHECK-NOT: InstanceFieldSet 711 /// CHECK-NOT: InstanceFieldGet 712 713 // A lambda-style allocation can be eliminated after inlining. sumWithinRange(int[] array, final int low, final int high)714 static int sumWithinRange(int[] array, final int low, final int high) { 715 Filter filter = new Filter() { 716 public boolean isValid(int i) { 717 return (i >= low) && (i <= high); 718 } 719 }; 720 return sumWithFilter(array, filter); 721 } 722 723 private static int mI = 0; 724 private static float mF = 0f; 725 726 /// CHECK-START: float Main.testAllocationEliminationWithLoops() load_store_elimination (before) 727 /// CHECK: NewInstance 728 /// CHECK: NewInstance 729 /// CHECK: NewInstance 730 731 /// CHECK-START: float Main.testAllocationEliminationWithLoops() load_store_elimination (after) 732 /// CHECK-NOT: NewInstance 733 testAllocationEliminationWithLoops()734 private static float testAllocationEliminationWithLoops() { 735 for (int i0 = 0; i0 < 5; i0++) { 736 for (int i1 = 0; i1 < 5; i1++) { 737 for (int i2 = 0; i2 < 5; i2++) { 738 int lI0 = ((int) new Integer(((int) new Integer(mI)))); 739 if (((boolean) new Boolean(false))) { 740 for (int i3 = 576 - 1; i3 >= 0; i3--) { 741 mF -= 976981405.0f; 742 } 743 } 744 } 745 } 746 } 747 return 1.0f; 748 } 749 750 /// CHECK-START: TestClass2 Main.testStoreStore() load_store_elimination (before) 751 /// CHECK: NewInstance 752 /// CHECK: InstanceFieldSet 753 /// CHECK: InstanceFieldSet 754 /// CHECK: InstanceFieldSet 755 /// CHECK: InstanceFieldSet 756 757 /// CHECK-START: TestClass2 Main.testStoreStore() load_store_elimination (after) 758 /// CHECK: NewInstance 759 /// CHECK: InstanceFieldSet 760 /// CHECK: InstanceFieldSet 761 /// CHECK-NOT: InstanceFieldSet 762 testStoreStore()763 private static TestClass2 testStoreStore() { 764 TestClass2 obj = new TestClass2(); 765 obj.i = 41; 766 obj.j = 42; 767 obj.i = 41; 768 obj.j = 43; 769 return obj; 770 } 771 772 /// CHECK-START: int Main.testStoreStoreWithDeoptimize(int[]) load_store_elimination (before) 773 /// CHECK: NewInstance 774 /// CHECK: InstanceFieldSet 775 /// CHECK: InstanceFieldSet 776 /// CHECK: InstanceFieldSet 777 /// CHECK: InstanceFieldSet 778 /// CHECK: Deoptimize 779 /// CHECK: ArraySet 780 /// CHECK: ArraySet 781 /// CHECK: ArraySet 782 /// CHECK: ArraySet 783 /// CHECK: ArrayGet 784 /// CHECK: ArrayGet 785 /// CHECK: ArrayGet 786 /// CHECK: ArrayGet 787 788 /// CHECK-START: int Main.testStoreStoreWithDeoptimize(int[]) load_store_elimination (after) 789 /// CHECK: NewInstance 790 /// CHECK: InstanceFieldSet 791 /// CHECK: InstanceFieldSet 792 /// CHECK-NOT: InstanceFieldSet 793 /// CHECK: Deoptimize 794 /// CHECK: ArraySet 795 /// CHECK: ArraySet 796 /// CHECK: ArraySet 797 /// CHECK: ArraySet 798 /// CHECK-NOT: ArrayGet 799 testStoreStoreWithDeoptimize(int[] arr)800 private static int testStoreStoreWithDeoptimize(int[] arr) { 801 TestClass2 obj = new TestClass2(); 802 obj.i = 41; 803 obj.j = 42; 804 obj.i = 41; 805 obj.j = 43; 806 arr[0] = 1; // One HDeoptimize here. 807 arr[1] = 1; 808 arr[2] = 1; 809 arr[3] = 1; 810 return arr[0] + arr[1] + arr[2] + arr[3]; 811 } 812 813 /// CHECK-START: double Main.getCircleArea(double, boolean) load_store_elimination (before) 814 /// CHECK: NewInstance 815 816 /// CHECK-START: double Main.getCircleArea(double, boolean) load_store_elimination (after) 817 /// CHECK-NOT: NewInstance 818 getCircleArea(double radius, boolean b)819 private static double getCircleArea(double radius, boolean b) { 820 double area = 0d; 821 if (b) { 822 area = new Circle(radius).getArea(); 823 } 824 return area; 825 } 826 827 /// CHECK-START: double Main.testDeoptimize(int[], double[], double) load_store_elimination (before) 828 /// CHECK: Deoptimize 829 /// CHECK: NewInstance 830 /// CHECK: Deoptimize 831 /// CHECK: NewInstance 832 833 /// CHECK-START: double Main.testDeoptimize(int[], double[], double) load_store_elimination (after) 834 /// CHECK: Deoptimize 835 /// CHECK: NewInstance 836 /// CHECK: Deoptimize 837 /// CHECK-NOT: NewInstance 838 testDeoptimize(int[] iarr, double[] darr, double radius)839 private static double testDeoptimize(int[] iarr, double[] darr, double radius) { 840 iarr[0] = 1; // One HDeoptimize here. Not triggered. 841 iarr[1] = 1; 842 Circle circle1 = new Circle(radius); 843 iarr[2] = 1; 844 darr[0] = circle1.getRadius(); // One HDeoptimize here, which holds circle1 live. Triggered. 845 darr[1] = circle1.getRadius(); 846 darr[2] = circle1.getRadius(); 847 darr[3] = circle1.getRadius(); 848 return new Circle(Math.PI).getArea(); 849 } 850 851 /// CHECK-START: int Main.testAllocationEliminationOfArray1() load_store_elimination (before) 852 /// CHECK: NewArray 853 /// CHECK: ArraySet 854 /// CHECK: ArraySet 855 /// CHECK: ArrayGet 856 /// CHECK: ArrayGet 857 /// CHECK: ArrayGet 858 /// CHECK: ArrayGet 859 860 /// CHECK-START: int Main.testAllocationEliminationOfArray1() load_store_elimination (after) 861 /// CHECK-NOT: NewArray 862 /// CHECK-NOT: ArraySet 863 /// CHECK-NOT: ArrayGet testAllocationEliminationOfArray1()864 private static int testAllocationEliminationOfArray1() { 865 int[] array = new int[4]; 866 array[2] = 4; 867 array[3] = 7; 868 return array[0] + array[1] + array[2] + array[3]; 869 } 870 871 /// CHECK-START: int Main.testAllocationEliminationOfArray2() load_store_elimination (before) 872 /// CHECK: NewArray 873 /// CHECK: ArraySet 874 /// CHECK: ArraySet 875 /// CHECK: ArrayGet 876 877 /// CHECK-START: int Main.testAllocationEliminationOfArray2() load_store_elimination (after) 878 /// CHECK: NewArray 879 /// CHECK: ArraySet 880 /// CHECK: ArraySet 881 /// CHECK: ArrayGet testAllocationEliminationOfArray2()882 private static int testAllocationEliminationOfArray2() { 883 // Cannot eliminate array allocation since array is accessed with non-constant 884 // index. 885 int[] array = new int[4]; 886 array[2] = 4; 887 array[3] = 7; 888 int sum = 0; 889 for (int e : array) { 890 sum += e; 891 } 892 return sum; 893 } 894 895 /// CHECK-START: int Main.testAllocationEliminationOfArray3(int) load_store_elimination (before) 896 /// CHECK: NewArray 897 /// CHECK: ArraySet 898 /// CHECK: ArrayGet 899 900 /// CHECK-START: int Main.testAllocationEliminationOfArray3(int) load_store_elimination (after) 901 /// CHECK-NOT: NewArray 902 /// CHECK-NOT: ArraySet 903 /// CHECK-NOT: ArrayGet testAllocationEliminationOfArray3(int i)904 private static int testAllocationEliminationOfArray3(int i) { 905 int[] array = new int[4]; 906 array[i] = 4; 907 return array[i]; 908 } 909 910 /// CHECK-START: int Main.testAllocationEliminationOfArray4(int) load_store_elimination (before) 911 /// CHECK: NewArray 912 /// CHECK: ArraySet 913 /// CHECK: ArraySet 914 /// CHECK: ArrayGet 915 /// CHECK: ArrayGet 916 917 /// CHECK-START: int Main.testAllocationEliminationOfArray4(int) load_store_elimination (after) 918 /// CHECK: NewArray 919 /// CHECK: ArraySet 920 /// CHECK: ArraySet 921 /// CHECK: ArrayGet 922 /// CHECK-NOT: ArrayGet testAllocationEliminationOfArray4(int i)923 private static int testAllocationEliminationOfArray4(int i) { 924 // Cannot eliminate array allocation due to index aliasing between 1 and i. 925 int[] array = new int[4]; 926 array[1] = 2; 927 array[i] = 4; 928 return array[1] + array[i]; 929 } 930 assertIntEquals(int result, int expected)931 static void assertIntEquals(int result, int expected) { 932 if (expected != result) { 933 throw new Error("Expected: " + expected + ", found: " + result); 934 } 935 } 936 assertFloatEquals(float result, float expected)937 static void assertFloatEquals(float result, float expected) { 938 if (expected != result) { 939 throw new Error("Expected: " + expected + ", found: " + result); 940 } 941 } 942 assertDoubleEquals(double result, double expected)943 static void assertDoubleEquals(double result, double expected) { 944 if (expected != result) { 945 throw new Error("Expected: " + expected + ", found: " + result); 946 } 947 } 948 main(String[] args)949 public static void main(String[] args) { 950 assertDoubleEquals(Math.PI * Math.PI * Math.PI, calcCircleArea(Math.PI)); 951 assertIntEquals(test1(new TestClass(), new TestClass()), 3); 952 assertIntEquals(test2(new TestClass()), 1); 953 TestClass obj1 = new TestClass(); 954 TestClass obj2 = new TestClass(); 955 obj1.next = obj2; 956 assertIntEquals(test3(obj1), 10); 957 assertIntEquals(test4(new TestClass(), true), 1); 958 assertIntEquals(test4(new TestClass(), false), 1); 959 assertIntEquals(test5(new TestClass(), true), 1); 960 assertIntEquals(test5(new TestClass(), false), 2); 961 assertIntEquals(test6(new TestClass(), new TestClass(), true), 4); 962 assertIntEquals(test6(new TestClass(), new TestClass(), false), 2); 963 assertIntEquals(test7(new TestClass()), 1); 964 assertIntEquals(test8(), 1); 965 obj1 = new TestClass(); 966 obj2 = new TestClass(); 967 obj1.next = obj2; 968 assertIntEquals(test9(new TestClass()), 1); 969 assertIntEquals(test10(new TestClass(3, 4)), 3); 970 assertIntEquals(TestClass.si, 3); 971 assertIntEquals(test11(new TestClass()), 10); 972 assertIntEquals(test12(new TestClass(), new TestClass()), 10); 973 assertIntEquals(test13(new TestClass(), new TestClass2()), 3); 974 SubTestClass obj3 = new SubTestClass(); 975 assertIntEquals(test14(obj3, obj3), 2); 976 assertIntEquals(test15(), 2); 977 assertIntEquals(test16(), 3); 978 assertIntEquals(test17(), 0); 979 assertIntEquals(test18(new TestClass()), 1); 980 float[] fa1 = { 0.8f }; 981 float[] fa2 = { 1.8f }; 982 assertFloatEquals(test19(fa1, fa2), 1.8f); 983 assertFloatEquals(test20().i, 0); 984 test21(new TestClass()); 985 assertIntEquals(test22(), 13); 986 assertIntEquals(test23(true), 4); 987 assertIntEquals(test23(false), 5); 988 assertFloatEquals(test24(), 8.0f); 989 testFinalizableByForcingGc(); 990 assertIntEquals($noinline$testHSelect(true), 0xdead); 991 int[] array = {2, 5, 9, -1, -3, 10, 8, 4}; 992 assertIntEquals(sumWithinRange(array, 1, 5), 11); 993 assertFloatEquals(testAllocationEliminationWithLoops(), 1.0f); 994 assertFloatEquals(mF, 0f); 995 assertDoubleEquals(Math.PI * Math.PI * Math.PI, getCircleArea(Math.PI, true)); 996 assertDoubleEquals(0d, getCircleArea(Math.PI, false)); 997 998 int[] iarray = {0, 0, 0}; 999 double[] darray = {0d, 0d, 0d}; 1000 try { 1001 assertDoubleEquals(Math.PI * Math.PI * Math.PI, testDeoptimize(iarray, darray, Math.PI)); 1002 } catch (Exception e) { 1003 System.out.println(e); 1004 } 1005 assertIntEquals(iarray[0], 1); 1006 assertIntEquals(iarray[1], 1); 1007 assertIntEquals(iarray[2], 1); 1008 assertDoubleEquals(darray[0], Math.PI); 1009 assertDoubleEquals(darray[1], Math.PI); 1010 assertDoubleEquals(darray[2], Math.PI); 1011 1012 assertIntEquals(testAllocationEliminationOfArray1(), 11); 1013 assertIntEquals(testAllocationEliminationOfArray2(), 11); 1014 assertIntEquals(testAllocationEliminationOfArray3(2), 4); 1015 assertIntEquals(testAllocationEliminationOfArray4(2), 6); 1016 1017 assertIntEquals(testStoreStore().i, 41); 1018 assertIntEquals(testStoreStore().j, 43); 1019 assertIntEquals(testStoreStoreWithDeoptimize(new int[4]), 4); 1020 } 1021 1022 static boolean sFlag; 1023 } 1024