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 byte b; 46 static int si; 47 static TestClass sTestClassObj; 48 } 49 50 class SubTestClass extends TestClass { 51 int k; 52 } 53 54 class TestClass2 { 55 int i; 56 int j; 57 } 58 59 class TestClass3 { 60 float floatField = 8.0f; 61 boolean test1 = true; 62 } 63 64 class Finalizable { 65 static boolean sVisited = false; 66 static final int VALUE1 = 0xbeef; 67 static final int VALUE2 = 0xcafe; 68 int i; 69 finalize()70 protected void finalize() { 71 if (i != VALUE1) { 72 System.out.println("Where is the beef?"); 73 } 74 sVisited = true; 75 } 76 } 77 78 interface Filter { isValid(int i)79 public boolean isValid(int i); 80 } 81 82 public class Main { 83 84 /// CHECK-START: double Main.calcCircleArea(double) load_store_elimination (before) 85 /// CHECK: NewInstance 86 /// CHECK: InstanceFieldSet 87 /// CHECK: InstanceFieldGet 88 89 /// CHECK-START: double Main.calcCircleArea(double) load_store_elimination (after) 90 /// CHECK-NOT: NewInstance 91 /// CHECK-NOT: InstanceFieldSet 92 /// CHECK-NOT: InstanceFieldGet 93 calcCircleArea(double radius)94 static double calcCircleArea(double radius) { 95 return new Circle(radius).getArea(); 96 } 97 98 /// CHECK-START: int Main.test1(TestClass, TestClass) load_store_elimination (before) 99 /// CHECK: InstanceFieldSet 100 /// CHECK: InstanceFieldSet 101 /// CHECK: InstanceFieldGet 102 /// CHECK: InstanceFieldGet 103 104 /// CHECK-START: int Main.test1(TestClass, TestClass) load_store_elimination (after) 105 /// CHECK: InstanceFieldSet 106 /// CHECK: InstanceFieldSet 107 /// CHECK-NOT: NullCheck 108 /// CHECK-NOT: InstanceFieldGet 109 110 // Different fields shouldn't alias. test1(TestClass obj1, TestClass obj2)111 static int test1(TestClass obj1, TestClass obj2) { 112 obj1.i = 1; 113 obj2.j = 2; 114 return obj1.i + obj2.j; 115 } 116 117 /// CHECK-START: int Main.test2(TestClass) load_store_elimination (before) 118 /// CHECK: InstanceFieldSet 119 /// CHECK: InstanceFieldSet 120 /// CHECK: InstanceFieldGet 121 122 /// CHECK-START: int Main.test2(TestClass) load_store_elimination (after) 123 /// CHECK: InstanceFieldSet 124 /// CHECK-NOT: NullCheck 125 /// CHECK-NOT: InstanceFieldSet 126 /// CHECK-NOT: InstanceFieldGet 127 128 // Redundant store of the same value. test2(TestClass obj)129 static int test2(TestClass obj) { 130 obj.j = 1; 131 obj.j = 1; 132 return obj.j; 133 } 134 135 /// CHECK-START: int Main.test3(TestClass) load_store_elimination (before) 136 /// CHECK: StaticFieldGet 137 /// CHECK: NewInstance 138 /// CHECK: InstanceFieldSet 139 /// CHECK: InstanceFieldSet 140 /// CHECK: InstanceFieldSet 141 /// CHECK: InstanceFieldSet 142 /// CHECK: InstanceFieldGet 143 /// CHECK: InstanceFieldGet 144 /// CHECK: InstanceFieldGet 145 /// CHECK: InstanceFieldGet 146 147 /// CHECK-START: int Main.test3(TestClass) load_store_elimination (after) 148 /// CHECK: StaticFieldGet 149 /// CHECK: NewInstance 150 /// CHECK: InstanceFieldSet 151 /// CHECK: InstanceFieldSet 152 /// CHECK: InstanceFieldSet 153 /// CHECK: InstanceFieldSet 154 /// CHECK-NOT: InstanceFieldGet 155 /// CHECK-NOT: StaticFieldGet 156 157 // A new allocation (even non-singleton) shouldn't alias with pre-existing values. test3(TestClass obj)158 static int test3(TestClass obj) { 159 TestClass obj1 = TestClass.sTestClassObj; 160 TestClass obj2 = new TestClass(); // Cannot alias with obj or obj1 which pre-exist. 161 obj.next = obj2; // Make obj2 a non-singleton. 162 // All stores below need to stay since obj/obj1/obj2 are not singletons. 163 obj.i = 1; 164 obj1.j = 2; 165 // Following stores won't kill values of obj.i and obj1.j. 166 obj2.i = 3; 167 obj2.j = 4; 168 return obj.i + obj1.j + obj2.i + obj2.j; 169 } 170 171 /// CHECK-START: int Main.test4(TestClass, boolean) load_store_elimination (before) 172 /// CHECK-DAG: InstanceFieldSet 173 /// CHECK-DAG: InstanceFieldSet 174 /// CHECK-DAG: InstanceFieldGet 175 /// CHECK-DAG: Return 176 177 /// CHECK-START: int Main.test4(TestClass, boolean) load_store_elimination (after) 178 /// CHECK-DAG: InstanceFieldSet 179 /// CHECK-DAG: InstanceFieldSet 180 /// CHECK-DAG: Return 181 182 /// CHECK-START: int Main.test4(TestClass, boolean) load_store_elimination (after) 183 /// CHECK: NullCheck 184 /// CHECK: NullCheck 185 /// CHECK-NOT: NullCheck 186 187 /// CHECK-START: int Main.test4(TestClass, boolean) load_store_elimination (after) 188 /// CHECK-NOT: InstanceFieldGet 189 190 // Set and merge the same value in two branches. test4(TestClass obj, boolean b)191 static int test4(TestClass obj, boolean b) { 192 if (b) { 193 obj.i = 1; 194 } else { 195 obj.i = 1; 196 } 197 return obj.i; 198 } 199 200 /// CHECK-START: int Main.test5(TestClass, boolean) load_store_elimination (before) 201 /// CHECK-DAG: InstanceFieldSet 202 /// CHECK-DAG: InstanceFieldSet 203 /// CHECK-DAG: InstanceFieldGet 204 /// CHECK-DAG: Return 205 206 /// CHECK-START: int Main.test5(TestClass, boolean) load_store_elimination (after) 207 /// CHECK-DAG: InstanceFieldSet 208 /// CHECK-DAG: InstanceFieldSet 209 /// CHECK-DAG: InstanceFieldGet 210 /// CHECK-DAG: Return 211 212 // Set and merge different values in two branches. test5(TestClass obj, boolean b)213 static int test5(TestClass obj, boolean b) { 214 if (b) { 215 obj.i = 1; 216 } else { 217 obj.i = 2; 218 } 219 return obj.i; 220 } 221 222 /// CHECK-START: int Main.test6(TestClass, TestClass, boolean) load_store_elimination (before) 223 /// CHECK: InstanceFieldSet 224 /// CHECK: InstanceFieldSet 225 /// CHECK: InstanceFieldSet 226 /// CHECK: InstanceFieldGet 227 /// CHECK: InstanceFieldGet 228 229 /// CHECK-START: int Main.test6(TestClass, TestClass, boolean) load_store_elimination (after) 230 /// CHECK: InstanceFieldSet 231 /// CHECK: InstanceFieldSet 232 /// CHECK: InstanceFieldSet 233 /// CHECK: InstanceFieldGet 234 /// CHECK-NOT: NullCheck 235 /// CHECK-NOT: InstanceFieldGet 236 237 // Setting the same value doesn't clear the value for aliased locations. test6(TestClass obj1, TestClass obj2, boolean b)238 static int test6(TestClass obj1, TestClass obj2, boolean b) { 239 obj1.i = 1; 240 obj1.j = 2; 241 if (b) { 242 obj2.j = 2; 243 } 244 return obj1.j + obj2.j; 245 } 246 247 /// CHECK-START: int Main.test7(TestClass) load_store_elimination (before) 248 /// CHECK: InstanceFieldSet 249 /// CHECK: InstanceFieldGet 250 251 /// CHECK-START: int Main.test7(TestClass) load_store_elimination (after) 252 /// CHECK: InstanceFieldSet 253 /// CHECK: InstanceFieldGet 254 255 // Invocation should kill values in non-singleton heap locations. test7(TestClass obj)256 static int test7(TestClass obj) { 257 obj.i = 1; 258 System.out.print(""); 259 return obj.i; 260 } 261 262 /// CHECK-START: int Main.test8() load_store_elimination (before) 263 /// CHECK: NewInstance 264 /// CHECK: InstanceFieldSet 265 /// CHECK: InvokeVirtual 266 /// CHECK: InstanceFieldGet 267 268 /// CHECK-START: int Main.test8() load_store_elimination (after) 269 /// CHECK-NOT: NewInstance 270 /// CHECK-NOT: InstanceFieldSet 271 /// CHECK: InvokeVirtual 272 /// CHECK-NOT: NullCheck 273 /// CHECK-NOT: InstanceFieldGet 274 275 // Invocation should not kill values in singleton heap locations. test8()276 static int test8() { 277 TestClass obj = new TestClass(); 278 obj.i = 1; 279 System.out.print(""); 280 return obj.i; 281 } 282 283 /// CHECK-START: int Main.test9(TestClass) load_store_elimination (before) 284 /// CHECK: NewInstance 285 /// CHECK: InstanceFieldSet 286 /// CHECK: InstanceFieldSet 287 /// CHECK: InstanceFieldGet 288 289 /// CHECK-START: int Main.test9(TestClass) load_store_elimination (after) 290 /// CHECK: NewInstance 291 /// CHECK: InstanceFieldSet 292 /// CHECK: InstanceFieldSet 293 /// CHECK: InstanceFieldGet 294 295 // Invocation should kill values in non-singleton heap locations. test9(TestClass obj)296 static int test9(TestClass obj) { 297 TestClass obj2 = new TestClass(); 298 obj2.i = 1; 299 obj.next = obj2; 300 System.out.print(""); 301 return obj2.i; 302 } 303 304 /// CHECK-START: int Main.test10(TestClass) load_store_elimination (before) 305 /// CHECK-DAG: StaticFieldGet 306 /// CHECK-DAG: InstanceFieldGet 307 /// CHECK-DAG: StaticFieldSet 308 /// CHECK-DAG: InstanceFieldGet 309 310 /// CHECK-START: int Main.test10(TestClass) load_store_elimination (after) 311 /// CHECK-DAG: StaticFieldGet 312 /// CHECK-DAG: InstanceFieldGet 313 /// CHECK-DAG: StaticFieldSet 314 315 /// CHECK-START: int Main.test10(TestClass) load_store_elimination (after) 316 /// CHECK: NullCheck 317 /// CHECK-NOT: NullCheck 318 319 /// CHECK-START: int Main.test10(TestClass) load_store_elimination (after) 320 /// CHECK: InstanceFieldGet 321 /// CHECK-NOT: InstanceFieldGet 322 323 // Static fields shouldn't alias with instance fields. test10(TestClass obj)324 static int test10(TestClass obj) { 325 TestClass.si += obj.i; 326 return obj.i; 327 } 328 329 /// CHECK-START: int Main.test11(TestClass) load_store_elimination (before) 330 /// CHECK: InstanceFieldSet 331 /// CHECK: InstanceFieldGet 332 333 /// CHECK-START: int Main.test11(TestClass) load_store_elimination (after) 334 /// CHECK: InstanceFieldSet 335 /// CHECK-NOT: NullCheck 336 /// CHECK-NOT: InstanceFieldGet 337 338 // Loop without heap writes. 339 // obj.i is actually hoisted to the loop pre-header by licm already. test11(TestClass obj)340 static int test11(TestClass obj) { 341 obj.i = 1; 342 int sum = 0; 343 for (int i = 0; i < 10; i++) { 344 sum += obj.i; 345 } 346 return sum; 347 } 348 349 /// CHECK-START: int Main.test12(TestClass, TestClass) load_store_elimination (before) 350 /// CHECK: InstanceFieldSet 351 /// CHECK: InstanceFieldGet 352 /// CHECK: InstanceFieldSet 353 354 /// CHECK-START: int Main.test12(TestClass, TestClass) load_store_elimination (after) 355 /// CHECK: InstanceFieldSet 356 /// CHECK: InstanceFieldGet 357 /// CHECK: InstanceFieldSet 358 359 // Loop with heap writes. test12(TestClass obj1, TestClass obj2)360 static int test12(TestClass obj1, TestClass obj2) { 361 obj1.i = 1; 362 int sum = 0; 363 for (int i = 0; i < 10; i++) { 364 sum += obj1.i; 365 obj2.i = sum; 366 } 367 return sum; 368 } 369 370 /// CHECK-START: int Main.test13(TestClass, TestClass2) load_store_elimination (before) 371 /// CHECK: InstanceFieldSet 372 /// CHECK: InstanceFieldSet 373 /// CHECK: InstanceFieldGet 374 /// CHECK: InstanceFieldGet 375 376 /// CHECK-START: int Main.test13(TestClass, TestClass2) load_store_elimination (after) 377 /// CHECK: InstanceFieldSet 378 /// CHECK: InstanceFieldSet 379 /// CHECK-NOT: NullCheck 380 /// CHECK-NOT: InstanceFieldGet 381 382 // Different classes shouldn't alias. test13(TestClass obj1, TestClass2 obj2)383 static int test13(TestClass obj1, TestClass2 obj2) { 384 obj1.i = 1; 385 obj2.i = 2; 386 return obj1.i + obj2.i; 387 } 388 389 /// CHECK-START: int Main.test14(TestClass, SubTestClass) load_store_elimination (before) 390 /// CHECK: InstanceFieldSet 391 /// CHECK: InstanceFieldSet 392 /// CHECK: InstanceFieldGet 393 394 /// CHECK-START: int Main.test14(TestClass, SubTestClass) load_store_elimination (after) 395 /// CHECK: InstanceFieldSet 396 /// CHECK: InstanceFieldSet 397 /// CHECK: InstanceFieldGet 398 399 // Subclass may alias with super class. test14(TestClass obj1, SubTestClass obj2)400 static int test14(TestClass obj1, SubTestClass obj2) { 401 obj1.i = 1; 402 obj2.i = 2; 403 return obj1.i; 404 } 405 406 /// CHECK-START: int Main.test15() load_store_elimination (before) 407 /// CHECK: StaticFieldSet 408 /// CHECK: StaticFieldSet 409 /// CHECK: StaticFieldGet 410 411 /// CHECK-START: int Main.test15() load_store_elimination (after) 412 /// CHECK: <<Const2:i\d+>> IntConstant 2 413 /// CHECK: StaticFieldSet 414 /// CHECK-NOT: StaticFieldGet 415 /// CHECK: Return [<<Const2>>] 416 417 // Static field access from subclass's name. test15()418 static int test15() { 419 TestClass.si = 1; 420 SubTestClass.si = 2; 421 return TestClass.si; 422 } 423 424 /// CHECK-START: int Main.test16() load_store_elimination (before) 425 /// CHECK: NewInstance 426 /// CHECK: InstanceFieldSet 427 /// CHECK: InstanceFieldSet 428 /// CHECK: InstanceFieldGet 429 /// CHECK: InstanceFieldGet 430 431 /// CHECK-START: int Main.test16() load_store_elimination (after) 432 /// CHECK-NOT: NewInstance 433 /// CHECK-NOT: InstanceFieldSet 434 /// CHECK-NOT: InstanceFieldGet 435 436 // Test inlined constructor. test16()437 static int test16() { 438 TestClass obj = new TestClass(1, 2); 439 return obj.i + obj.j; 440 } 441 442 /// CHECK-START: int Main.test17() load_store_elimination (before) 443 /// CHECK: NewInstance 444 /// CHECK: InstanceFieldSet 445 /// CHECK: InstanceFieldGet 446 447 /// CHECK-START: int Main.test17() load_store_elimination (after) 448 /// CHECK: <<Const0:i\d+>> IntConstant 0 449 /// CHECK-NOT: NewInstance 450 /// CHECK-NOT: InstanceFieldSet 451 /// CHECK-NOT: InstanceFieldGet 452 /// CHECK: Return [<<Const0>>] 453 454 // Test getting default value. test17()455 static int test17() { 456 TestClass obj = new TestClass(); 457 obj.j = 1; 458 return obj.i; 459 } 460 461 /// CHECK-START: int Main.test18(TestClass) load_store_elimination (before) 462 /// CHECK: InstanceFieldSet 463 /// CHECK: InstanceFieldGet 464 465 /// CHECK-START: int Main.test18(TestClass) load_store_elimination (after) 466 /// CHECK: InstanceFieldSet 467 /// CHECK: InstanceFieldGet 468 469 // Volatile field load/store shouldn't be eliminated. test18(TestClass obj)470 static int test18(TestClass obj) { 471 obj.k = 1; 472 return obj.k; 473 } 474 475 /// CHECK-START: float Main.test19(float[], float[]) load_store_elimination (before) 476 /// CHECK: {{f\d+}} ArrayGet 477 /// CHECK: {{f\d+}} ArrayGet 478 479 /// CHECK-START: float Main.test19(float[], float[]) load_store_elimination (after) 480 /// CHECK: {{f\d+}} ArrayGet 481 /// CHECK-NOT: {{f\d+}} ArrayGet 482 483 // I/F, J/D aliasing should not happen any more and LSE should eliminate the load. test19(float[] fa1, float[] fa2)484 static float test19(float[] fa1, float[] fa2) { 485 fa1[0] = fa2[0]; 486 return fa1[0]; 487 } 488 489 /// CHECK-START: TestClass Main.test20() load_store_elimination (before) 490 /// CHECK: NewInstance 491 /// CHECK: InstanceFieldSet 492 493 /// CHECK-START: TestClass Main.test20() load_store_elimination (after) 494 /// CHECK: NewInstance 495 /// CHECK-NOT: InstanceFieldSet 496 497 // Storing default heap value is redundant if the heap location has the 498 // default heap value. test20()499 static TestClass test20() { 500 TestClass obj = new TestClass(); 501 obj.i = 0; 502 return obj; 503 } 504 505 /// CHECK-START: void Main.test21(TestClass) load_store_elimination (before) 506 /// CHECK: NewInstance 507 /// CHECK: InstanceFieldSet 508 /// CHECK: InstanceFieldSet 509 /// CHECK: InstanceFieldSet 510 /// CHECK: InstanceFieldGet 511 /// CHECK: InstanceFieldGet 512 513 /// CHECK-START: void Main.test21(TestClass) load_store_elimination (after) 514 /// CHECK: NewInstance 515 /// CHECK: InstanceFieldSet 516 /// CHECK: InstanceFieldSet 517 /// CHECK: InstanceFieldSet 518 /// CHECK: InstanceFieldGet 519 /// CHECK: InstanceFieldGet 520 521 // Loop side effects can kill heap values, stores need to be kept in that case. test21(TestClass obj0)522 static void test21(TestClass obj0) { 523 TestClass obj = new TestClass(); 524 obj0.str = "abc"; 525 obj.str = "abc"; 526 for (int i = 0; i < 2; i++) { 527 // Generate some loop side effect that writes into obj. 528 obj.str = "def"; 529 } 530 System.out.print(obj0.str.substring(0, 0) + obj.str.substring(0, 0)); 531 } 532 533 /// CHECK-START: int Main.test22() load_store_elimination (before) 534 /// CHECK: NewInstance 535 /// CHECK: InstanceFieldSet 536 /// CHECK: NewInstance 537 /// CHECK: InstanceFieldSet 538 /// CHECK: InstanceFieldGet 539 /// CHECK: NewInstance 540 /// CHECK: InstanceFieldSet 541 /// CHECK: InstanceFieldGet 542 /// CHECK: InstanceFieldGet 543 544 /// CHECK-START: int Main.test22() load_store_elimination (after) 545 /// CHECK-NOT: NewInstance 546 /// CHECK-NOT: InstanceFieldSet 547 /// CHECK-NOT: NewInstance 548 /// CHECK-NOT: InstanceFieldSet 549 /// CHECK-NOT: InstanceFieldGet 550 /// CHECK-NOT: NewInstance 551 /// CHECK-NOT: InstanceFieldSet 552 /// CHECK-NOT: InstanceFieldGet 553 /// CHECK-NOT: InstanceFieldGet 554 555 // For a singleton, loop side effects can kill its field values only if: 556 // (1) it dominiates the loop header, and 557 // (2) its fields are stored into inside a loop. test22()558 static int test22() { 559 int sum = 0; 560 TestClass obj1 = new TestClass(); 561 obj1.i = 2; // This store can be eliminated since obj1 is never stored into inside a loop. 562 for (int i = 0; i < 2; i++) { 563 TestClass obj2 = new TestClass(); 564 obj2.i = 3; // This store can be eliminated since the singleton is inside the loop. 565 sum += obj2.i; 566 } 567 TestClass obj3 = new TestClass(); 568 obj3.i = 5; // This store can be eliminated since the singleton is created after the loop. 569 sum += obj1.i + obj3.i; 570 return sum; 571 } 572 573 /// CHECK-START: int Main.test23(boolean) load_store_elimination (before) 574 /// CHECK-DAG: NewInstance 575 /// CHECK-DAG: InstanceFieldSet 576 /// CHECK-DAG: InstanceFieldGet 577 /// CHECK-DAG: InstanceFieldSet 578 /// CHECK-DAG: InstanceFieldGet 579 /// CHECK-DAG: InstanceFieldSet 580 /// CHECK-DAG: InstanceFieldGet 581 /// CHECK-DAG: Return 582 583 /// CHECK-START: int Main.test23(boolean) load_store_elimination (after) 584 /// CHECK-DAG: NewInstance 585 /// CHECK-DAG: InstanceFieldSet 586 /// CHECK-DAG: InstanceFieldSet 587 /// CHECK-DAG: InstanceFieldGet 588 /// CHECK-DAG: Return 589 590 /// CHECK-START: int Main.test23(boolean) load_store_elimination (after) 591 /// CHECK: InstanceFieldSet 592 /// CHECK: InstanceFieldSet 593 /// CHECK-NOT: InstanceFieldSet 594 595 /// CHECK-START: int Main.test23(boolean) load_store_elimination (after) 596 /// CHECK: InstanceFieldGet 597 /// CHECK-NOT: InstanceFieldGet 598 599 /// CHECK-START: int Main.test23(boolean) load_store_elimination (after) 600 /// CHECK-DAG: <<Get:i\d+>> InstanceFieldGet 601 /// CHECK-DAG: Return [<<Get>>] 602 603 // Test store elimination on merging. test23(boolean b)604 static int test23(boolean b) { 605 TestClass obj = new TestClass(); 606 obj.i = 3; // This store can be eliminated since the value flows into each branch. 607 if (b) { 608 obj.i += 1; // This store cannot be eliminated due to the merge later. 609 } else { 610 obj.i += 2; // This store cannot be eliminated due to the merge later. 611 } 612 return obj.i; 613 } 614 615 /// CHECK-START: float Main.test24() load_store_elimination (before) 616 /// CHECK-DAG: <<True:i\d+>> IntConstant 1 617 /// CHECK-DAG: <<Float8:f\d+>> FloatConstant 8 618 /// CHECK-DAG: <<Float42:f\d+>> FloatConstant 42 619 /// CHECK-DAG: <<Obj:l\d+>> NewInstance 620 /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<True>>] 621 /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Float8>>] 622 /// CHECK-DAG: <<GetTest:z\d+>> InstanceFieldGet [<<Obj>>] 623 /// CHECK-DAG: <<GetField:f\d+>> InstanceFieldGet [<<Obj>>] 624 /// CHECK-DAG: <<Select:f\d+>> Select [<<Float42>>,<<GetField>>,<<GetTest>>] 625 /// CHECK-DAG: Return [<<Select>>] 626 627 /// CHECK-START: float Main.test24() load_store_elimination (after) 628 /// CHECK-DAG: <<True:i\d+>> IntConstant 1 629 /// CHECK-DAG: <<Float8:f\d+>> FloatConstant 8 630 /// CHECK-DAG: <<Float42:f\d+>> FloatConstant 42 631 /// CHECK-DAG: <<Select:f\d+>> Select [<<Float42>>,<<Float8>>,<<True>>] 632 /// CHECK-DAG: Return [<<Select>>] 633 test24()634 static float test24() { 635 float a = 42.0f; 636 TestClass3 obj = new TestClass3(); 637 if (obj.test1) { 638 a = obj.floatField; 639 } 640 return a; 641 } 642 643 /// CHECK-START: int Main.$noinline$testConversion1(TestClass, int) load_store_elimination (before) 644 /// CHECK-DAG: InstanceFieldSet 645 /// CHECK-DAG: InstanceFieldSet 646 /// CHECK-DAG: InstanceFieldGet 647 /// CHECK-DAG: InstanceFieldSet 648 /// CHECK-DAG: InstanceFieldGet 649 650 /// CHECK-START: int Main.$noinline$testConversion1(TestClass, int) load_store_elimination (after) 651 /// CHECK-DAG: InstanceFieldSet 652 /// CHECK-DAG: InstanceFieldSet 653 /// CHECK-DAG: TypeConversion 654 /// CHECK-DAG: InstanceFieldSet 655 /// CHECK-DAG: InstanceFieldGet $noinline$testConversion1(TestClass obj, int x)656 static int $noinline$testConversion1(TestClass obj, int x) { 657 obj.i = x; 658 if ((x & 1) != 0) { 659 obj.b = (byte) x; 660 obj.i = obj.b; 661 } 662 return obj.i; 663 } 664 665 /// CHECK-START: int Main.$noinline$testConversion2(TestClass, int) load_store_elimination (before) 666 /// CHECK-DAG: InstanceFieldSet 667 /// CHECK-DAG: InstanceFieldSet 668 /// CHECK-DAG: InstanceFieldGet 669 /// CHECK-DAG: InstanceFieldSet 670 /// CHECK-DAG: InstanceFieldGet 671 672 /// CHECK-START: int Main.$noinline$testConversion2(TestClass, int) load_store_elimination (after) 673 /// CHECK-DAG: InstanceFieldSet 674 /// CHECK-DAG: InstanceFieldSet 675 /// CHECK-DAG: TypeConversion 676 /// CHECK-DAG: InstanceFieldSet 677 /// CHECK-DAG: InstanceFieldGet 678 679 /// CHECK-START: int Main.$noinline$testConversion2(TestClass, int) load_store_elimination (after) 680 /// CHECK: TypeConversion 681 /// CHECK-NOT: TypeConversion $noinline$testConversion2(TestClass obj, int x)682 static int $noinline$testConversion2(TestClass obj, int x) { 683 int tmp = 0; 684 obj.i = x; 685 if ((x & 1) != 0) { 686 // The instruction simplifier can remove this TypeConversion if there are 687 // no environment uses. Currently, there is an environment use in NullCheck, 688 // so this TypeConversion remains and GVN removes the second TypeConversion 689 // below. Since we really want to test that the TypeConversion from below 690 // can be moved and used for the load of `obj.b`, we have a similar test 691 // written in smali in 530-checker-lse3, StoreLoad.test3(int), except that 692 // it's using static fields (which would not help with the environment use). 693 obj.b = (byte) x; 694 obj.i = obj.b; 695 tmp = (byte) x; 696 } 697 return obj.i + tmp; 698 } 699 700 /// CHECK-START: void Main.testFinalizable() load_store_elimination (before) 701 /// CHECK: NewInstance 702 /// CHECK: InstanceFieldSet 703 /// CHECK: InstanceFieldSet 704 705 /// CHECK-START: void Main.testFinalizable() load_store_elimination (after) 706 /// CHECK: NewInstance 707 /// CHECK: InstanceFieldSet 708 /// CHECK-NOT: InstanceFieldSet 709 710 // Allocations of finalizable objects cannot be eliminated. testFinalizable()711 static void testFinalizable() { 712 Finalizable finalizable = new Finalizable(); 713 finalizable.i = Finalizable.VALUE2; 714 finalizable.i = Finalizable.VALUE1; 715 } 716 getWeakReference()717 static java.lang.ref.WeakReference<Object> getWeakReference() { 718 return new java.lang.ref.WeakReference<>(new Object()); 719 } 720 testFinalizableByForcingGc()721 static void testFinalizableByForcingGc() { 722 testFinalizable(); 723 java.lang.ref.WeakReference<Object> reference = getWeakReference(); 724 725 Runtime runtime = Runtime.getRuntime(); 726 for (int i = 0; i < 20; ++i) { 727 runtime.gc(); 728 System.runFinalization(); 729 try { 730 Thread.sleep(1); 731 } catch (InterruptedException e) { 732 throw new AssertionError(e); 733 } 734 735 // Check to see if the weak reference has been garbage collected. 736 if (reference.get() == null) { 737 // A little bit more sleep time to make sure. 738 try { 739 Thread.sleep(100); 740 } catch (InterruptedException e) { 741 throw new AssertionError(e); 742 } 743 if (!Finalizable.sVisited) { 744 System.out.println("finalize() not called."); 745 } 746 return; 747 } 748 } 749 System.out.println("testFinalizableByForcingGc() failed to force gc."); 750 } 751 752 /// CHECK-START: int Main.$noinline$testHSelect(boolean) load_store_elimination (before) 753 /// CHECK: InstanceFieldSet 754 /// CHECK: Select 755 756 /// CHECK-START: int Main.$noinline$testHSelect(boolean) load_store_elimination (after) 757 /// CHECK: InstanceFieldSet 758 /// CHECK: Select 759 760 // Test that HSelect creates alias. $noinline$testHSelect(boolean b)761 static int $noinline$testHSelect(boolean b) { 762 if (sFlag) { 763 throw new Error(); 764 } 765 TestClass obj = new TestClass(); 766 TestClass obj2 = null; 767 obj.i = 0xdead; 768 if (b) { 769 obj2 = obj; 770 } 771 return obj2.i; 772 } 773 sumWithFilter(int[] array, Filter f)774 static int sumWithFilter(int[] array, Filter f) { 775 int sum = 0; 776 for (int i = 0; i < array.length; i++) { 777 if (f.isValid(array[i])) { 778 sum += array[i]; 779 } 780 } 781 return sum; 782 } 783 784 /// CHECK-START: int Main.sumWithinRange(int[], int, int) load_store_elimination (before) 785 /// CHECK: NewInstance 786 /// CHECK: InstanceFieldSet 787 /// CHECK: InstanceFieldSet 788 /// CHECK: InstanceFieldGet 789 /// CHECK: InstanceFieldGet 790 791 /// CHECK-START: int Main.sumWithinRange(int[], int, int) load_store_elimination (after) 792 /// CHECK-NOT: NewInstance 793 /// CHECK-NOT: InstanceFieldSet 794 /// CHECK-NOT: InstanceFieldGet 795 796 // A lambda-style allocation can be eliminated after inlining. sumWithinRange(int[] array, final int low, final int high)797 static int sumWithinRange(int[] array, final int low, final int high) { 798 Filter filter = new Filter() { 799 public boolean isValid(int i) { 800 return (i >= low) && (i <= high); 801 } 802 }; 803 return sumWithFilter(array, filter); 804 } 805 806 private static int mI = 0; 807 private static float mF = 0f; 808 809 /// CHECK-START: float Main.testAllocationEliminationWithLoops() load_store_elimination (before) 810 /// CHECK: NewInstance 811 /// CHECK: NewInstance 812 /// CHECK: NewInstance 813 814 /// CHECK-START: float Main.testAllocationEliminationWithLoops() load_store_elimination (after) 815 /// CHECK-NOT: NewInstance 816 testAllocationEliminationWithLoops()817 private static float testAllocationEliminationWithLoops() { 818 for (int i0 = 0; i0 < 5; i0++) { 819 for (int i1 = 0; i1 < 5; i1++) { 820 for (int i2 = 0; i2 < 5; i2++) { 821 int lI0 = ((int) new Integer(((int) new Integer(mI)))); 822 if (((boolean) new Boolean(false))) { 823 for (int i3 = 576 - 1; i3 >= 0; i3--) { 824 mF -= 976981405.0f; 825 } 826 } 827 } 828 } 829 } 830 return 1.0f; 831 } 832 833 /// CHECK-START: TestClass2 Main.testStoreStore() load_store_elimination (before) 834 /// CHECK: NewInstance 835 /// CHECK: InstanceFieldSet 836 /// CHECK: InstanceFieldSet 837 /// CHECK: InstanceFieldSet 838 /// CHECK: InstanceFieldSet 839 840 /// CHECK-START: TestClass2 Main.testStoreStore() load_store_elimination (after) 841 /// CHECK: NewInstance 842 /// CHECK: InstanceFieldSet 843 /// CHECK: InstanceFieldSet 844 /// CHECK-NOT: InstanceFieldSet 845 testStoreStore()846 private static TestClass2 testStoreStore() { 847 TestClass2 obj = new TestClass2(); 848 obj.i = 41; 849 obj.j = 42; 850 obj.i = 41; 851 obj.j = 43; 852 return obj; 853 } 854 855 /// CHECK-START: void Main.testStoreStore2(TestClass2) load_store_elimination (before) 856 /// CHECK: InstanceFieldSet 857 /// CHECK: InstanceFieldSet 858 /// CHECK: InstanceFieldSet 859 /// CHECK: InstanceFieldSet 860 861 /// CHECK-START: void Main.testStoreStore2(TestClass2) load_store_elimination (after) 862 /// CHECK: InstanceFieldSet 863 /// CHECK: InstanceFieldSet 864 /// CHECK-NOT: InstanceFieldSet 865 testStoreStore2(TestClass2 obj)866 private static void testStoreStore2(TestClass2 obj) { 867 obj.i = 41; 868 obj.j = 42; 869 obj.i = 43; 870 obj.j = 44; 871 } 872 873 /// CHECK-START: void Main.testStoreStore3(TestClass2, boolean) load_store_elimination (before) 874 /// CHECK: InstanceFieldSet 875 /// CHECK: InstanceFieldSet 876 /// CHECK: InstanceFieldSet 877 /// CHECK: InstanceFieldSet 878 879 /// CHECK-START: void Main.testStoreStore3(TestClass2, boolean) load_store_elimination (after) 880 /// CHECK: InstanceFieldSet 881 /// CHECK: InstanceFieldSet 882 /// CHECK: InstanceFieldSet 883 /// CHECK-NOT: InstanceFieldSet 884 testStoreStore3(TestClass2 obj, boolean flag)885 private static void testStoreStore3(TestClass2 obj, boolean flag) { 886 obj.i = 41; 887 obj.j = 42; // redundant since it's overwritten in both branches below. 888 if (flag) { 889 obj.j = 43; 890 } else { 891 obj.j = 44; 892 } 893 } 894 895 /// CHECK-START: void Main.testStoreStore4() load_store_elimination (before) 896 /// CHECK: StaticFieldSet 897 /// CHECK: StaticFieldSet 898 899 /// CHECK-START: void Main.testStoreStore4() load_store_elimination (after) 900 /// CHECK: StaticFieldSet 901 /// CHECK-NOT: StaticFieldSet 902 testStoreStore4()903 private static void testStoreStore4() { 904 TestClass.si = 61; 905 TestClass.si = 62; 906 } 907 908 /// CHECK-START: int Main.testStoreStore5(TestClass2, TestClass2) load_store_elimination (before) 909 /// CHECK: InstanceFieldSet 910 /// CHECK: InstanceFieldGet 911 /// CHECK: InstanceFieldSet 912 913 /// CHECK-START: int Main.testStoreStore5(TestClass2, TestClass2) load_store_elimination (after) 914 /// CHECK: InstanceFieldSet 915 /// CHECK: InstanceFieldGet 916 /// CHECK: InstanceFieldSet 917 testStoreStore5(TestClass2 obj1, TestClass2 obj2)918 private static int testStoreStore5(TestClass2 obj1, TestClass2 obj2) { 919 obj1.i = 71; // This store is needed since obj2.i may load from it. 920 int i = obj2.i; 921 obj1.i = 72; 922 return i; 923 } 924 925 /// CHECK-START: int Main.testStoreStore6(TestClass2, TestClass2) load_store_elimination (before) 926 /// CHECK: InstanceFieldSet 927 /// CHECK: InstanceFieldGet 928 /// CHECK: InstanceFieldSet 929 930 /// CHECK-START: int Main.testStoreStore6(TestClass2, TestClass2) load_store_elimination (after) 931 /// CHECK-NOT: InstanceFieldSet 932 /// CHECK: InstanceFieldGet 933 /// CHECK: InstanceFieldSet 934 testStoreStore6(TestClass2 obj1, TestClass2 obj2)935 private static int testStoreStore6(TestClass2 obj1, TestClass2 obj2) { 936 obj1.i = 81; // This store is not needed since obj2.j cannot load from it. 937 int j = obj2.j; 938 obj1.i = 82; 939 return j; 940 } 941 942 /// CHECK-START: int Main.testNoSideEffects(int[]) load_store_elimination (before) 943 /// CHECK: ArraySet 944 /// CHECK: ArraySet 945 /// CHECK: ArraySet 946 /// CHECK: ArrayGet 947 948 /// CHECK-START: int Main.testNoSideEffects(int[]) load_store_elimination (after) 949 /// CHECK: ArraySet 950 /// CHECK: ArraySet 951 /// CHECK-NOT: ArraySet 952 /// CHECK-NOT: ArrayGet 953 testNoSideEffects(int[] array)954 private static int testNoSideEffects(int[] array) { 955 array[0] = 101; 956 array[1] = 102; 957 int bitCount = Integer.bitCount(0x3456); 958 array[1] = 103; 959 return array[0] + bitCount; 960 } 961 962 /// CHECK-START: void Main.testThrow(TestClass2, java.lang.Exception) load_store_elimination (before) 963 /// CHECK: InstanceFieldSet 964 /// CHECK: Throw 965 966 /// CHECK-START: void Main.testThrow(TestClass2, java.lang.Exception) load_store_elimination (after) 967 /// CHECK: InstanceFieldSet 968 /// CHECK: Throw 969 970 // Make sure throw keeps the store. testThrow(TestClass2 obj, Exception e)971 private static void testThrow(TestClass2 obj, Exception e) throws Exception { 972 obj.i = 55; 973 throw e; 974 } 975 976 /// CHECK-START: int Main.testStoreStoreWithDeoptimize(int[]) load_store_elimination (before) 977 /// CHECK: NewInstance 978 /// CHECK: InstanceFieldSet 979 /// CHECK: InstanceFieldSet 980 /// CHECK: InstanceFieldSet 981 /// CHECK: InstanceFieldSet 982 /// CHECK: Deoptimize 983 /// CHECK: ArraySet 984 /// CHECK: ArraySet 985 /// CHECK: ArraySet 986 /// CHECK: ArraySet 987 /// CHECK: ArrayGet 988 /// CHECK: ArrayGet 989 /// CHECK: ArrayGet 990 /// CHECK: ArrayGet 991 992 /// CHECK-START: int Main.testStoreStoreWithDeoptimize(int[]) load_store_elimination (after) 993 /// CHECK: NewInstance 994 /// CHECK: InstanceFieldSet 995 /// CHECK: InstanceFieldSet 996 /// CHECK-NOT: InstanceFieldSet 997 /// CHECK: Deoptimize 998 /// CHECK: ArraySet 999 /// CHECK: ArraySet 1000 /// CHECK: ArraySet 1001 /// CHECK: ArraySet 1002 /// CHECK-NOT: ArrayGet 1003 testStoreStoreWithDeoptimize(int[] arr)1004 private static int testStoreStoreWithDeoptimize(int[] arr) { 1005 TestClass2 obj = new TestClass2(); 1006 obj.i = 41; 1007 obj.j = 42; 1008 obj.i = 41; 1009 obj.j = 43; 1010 arr[0] = 1; // One HDeoptimize here. 1011 arr[1] = 1; 1012 arr[2] = 1; 1013 arr[3] = 1; 1014 return arr[0] + arr[1] + arr[2] + arr[3]; 1015 } 1016 1017 /// CHECK-START: double Main.getCircleArea(double, boolean) load_store_elimination (before) 1018 /// CHECK: NewInstance 1019 1020 /// CHECK-START: double Main.getCircleArea(double, boolean) load_store_elimination (after) 1021 /// CHECK-NOT: NewInstance 1022 getCircleArea(double radius, boolean b)1023 private static double getCircleArea(double radius, boolean b) { 1024 double area = 0d; 1025 if (b) { 1026 area = new Circle(radius).getArea(); 1027 } 1028 return area; 1029 } 1030 1031 /// CHECK-START: double Main.testDeoptimize(int[], double[], double) load_store_elimination (before) 1032 /// CHECK: Deoptimize 1033 /// CHECK: NewInstance 1034 /// CHECK: Deoptimize 1035 /// CHECK: NewInstance 1036 1037 /// CHECK-START: double Main.testDeoptimize(int[], double[], double) load_store_elimination (after) 1038 /// CHECK: Deoptimize 1039 /// CHECK: NewInstance 1040 /// CHECK: Deoptimize 1041 /// CHECK-NOT: NewInstance 1042 testDeoptimize(int[] iarr, double[] darr, double radius)1043 private static double testDeoptimize(int[] iarr, double[] darr, double radius) { 1044 iarr[0] = 1; // One HDeoptimize here. Not triggered. 1045 iarr[1] = 1; 1046 Circle circle1 = new Circle(radius); 1047 iarr[2] = 1; 1048 darr[0] = circle1.getRadius(); // One HDeoptimize here, which holds circle1 live. Triggered. 1049 darr[1] = circle1.getRadius(); 1050 darr[2] = circle1.getRadius(); 1051 darr[3] = circle1.getRadius(); 1052 return new Circle(Math.PI).getArea(); 1053 } 1054 1055 /// CHECK-START: int Main.testAllocationEliminationOfArray1() load_store_elimination (before) 1056 /// CHECK: NewArray 1057 /// CHECK: ArraySet 1058 /// CHECK: ArraySet 1059 /// CHECK: ArrayGet 1060 /// CHECK: ArrayGet 1061 /// CHECK: ArrayGet 1062 /// CHECK: ArrayGet 1063 1064 /// CHECK-START: int Main.testAllocationEliminationOfArray1() load_store_elimination (after) 1065 /// CHECK-NOT: NewArray 1066 /// CHECK-NOT: ArraySet 1067 /// CHECK-NOT: ArrayGet testAllocationEliminationOfArray1()1068 private static int testAllocationEliminationOfArray1() { 1069 int[] array = new int[4]; 1070 array[2] = 4; 1071 array[3] = 7; 1072 return array[0] + array[1] + array[2] + array[3]; 1073 } 1074 1075 /// CHECK-START: int Main.testAllocationEliminationOfArray2() load_store_elimination (before) 1076 /// CHECK: NewArray 1077 /// CHECK: ArraySet 1078 /// CHECK: ArraySet 1079 /// CHECK: ArrayGet 1080 1081 /// CHECK-START: int Main.testAllocationEliminationOfArray2() load_store_elimination (after) 1082 /// CHECK: NewArray 1083 /// CHECK: ArraySet 1084 /// CHECK: ArraySet 1085 /// CHECK: ArrayGet testAllocationEliminationOfArray2()1086 private static int testAllocationEliminationOfArray2() { 1087 // Cannot eliminate array allocation since array is accessed with non-constant 1088 // index (only 3 elements to prevent vectorization of the reduction). 1089 int[] array = new int[3]; 1090 array[1] = 4; 1091 array[2] = 7; 1092 int sum = 0; 1093 for (int e : array) { 1094 sum += e; 1095 } 1096 return sum; 1097 } 1098 1099 /// CHECK-START: int Main.testAllocationEliminationOfArray3(int) load_store_elimination (before) 1100 /// CHECK: NewArray 1101 /// CHECK: ArraySet 1102 /// CHECK: ArrayGet 1103 1104 /// CHECK-START: int Main.testAllocationEliminationOfArray3(int) load_store_elimination (after) 1105 /// CHECK-NOT: NewArray 1106 /// CHECK-NOT: ArraySet 1107 /// CHECK-NOT: ArrayGet testAllocationEliminationOfArray3(int i)1108 private static int testAllocationEliminationOfArray3(int i) { 1109 int[] array = new int[4]; 1110 array[i] = 4; 1111 return array[i]; 1112 } 1113 1114 /// CHECK-START: int Main.testAllocationEliminationOfArray4(int) load_store_elimination (before) 1115 /// CHECK: NewArray 1116 /// CHECK: ArraySet 1117 /// CHECK: ArraySet 1118 /// CHECK: ArrayGet 1119 /// CHECK: ArrayGet 1120 1121 /// CHECK-START: int Main.testAllocationEliminationOfArray4(int) load_store_elimination (after) 1122 /// CHECK: NewArray 1123 /// CHECK: ArraySet 1124 /// CHECK: ArraySet 1125 /// CHECK: ArrayGet 1126 /// CHECK-NOT: ArrayGet testAllocationEliminationOfArray4(int i)1127 private static int testAllocationEliminationOfArray4(int i) { 1128 // Cannot eliminate array allocation due to index aliasing between 1 and i. 1129 int[] array = new int[4]; 1130 array[1] = 2; 1131 array[i] = 4; 1132 return array[1] + array[i]; 1133 } 1134 1135 /// CHECK-START: int Main.testAllocationEliminationOfArray5(int) load_store_elimination (before) 1136 /// CHECK: NewArray 1137 /// CHECK: ArraySet 1138 /// CHECK: ArrayGet 1139 1140 /// CHECK-START: int Main.testAllocationEliminationOfArray5(int) load_store_elimination (after) 1141 /// CHECK: NewArray 1142 /// CHECK-NOT: ArraySet 1143 /// CHECK-NOT: ArrayGet testAllocationEliminationOfArray5(int i)1144 private static int testAllocationEliminationOfArray5(int i) { 1145 // Cannot eliminate array allocation due to unknown i that may 1146 // cause NegativeArraySizeException. 1147 int[] array = new int[i]; 1148 array[1] = 12; 1149 return array[1]; 1150 } 1151 1152 /// CHECK-START: int Main.testExitMerge(boolean) load_store_elimination (before) 1153 /// CHECK: NewInstance 1154 /// CHECK: InstanceFieldSet 1155 /// CHECK: InstanceFieldGet 1156 /// CHECK: Return 1157 /// CHECK: InstanceFieldSet 1158 /// CHECK: Throw 1159 1160 /// CHECK-START: int Main.testExitMerge(boolean) load_store_elimination (after) 1161 /// CHECK-NOT: NewInstance 1162 /// CHECK-NOT: InstanceFieldSet 1163 /// CHECK-NOT: InstanceFieldGet 1164 /// CHECK: Return 1165 /// CHECK-NOT: InstanceFieldSet 1166 /// CHECK: Throw testExitMerge(boolean cond)1167 private static int testExitMerge(boolean cond) { 1168 TestClass obj = new TestClass(); 1169 if (cond) { 1170 obj.i = 1; 1171 return obj.i + 1; 1172 } else { 1173 obj.i = 2; 1174 throw new Error(); 1175 } 1176 } 1177 1178 /// CHECK-START: int Main.testExitMerge2(boolean) load_store_elimination (before) 1179 /// CHECK: NewInstance 1180 /// CHECK: InstanceFieldSet 1181 /// CHECK: InstanceFieldGet 1182 /// CHECK: InstanceFieldSet 1183 /// CHECK: InstanceFieldGet 1184 1185 /// CHECK-START: int Main.testExitMerge2(boolean) load_store_elimination (after) 1186 /// CHECK-NOT: NewInstance 1187 /// CHECK-NOT: InstanceFieldSet 1188 /// CHECK-NOT: InstanceFieldGet testExitMerge2(boolean cond)1189 private static int testExitMerge2(boolean cond) { 1190 TestClass obj = new TestClass(); 1191 int res; 1192 if (cond) { 1193 obj.i = 1; 1194 res = obj.i + 1; 1195 } else { 1196 obj.i = 2; 1197 res = obj.j + 2; 1198 } 1199 return res; 1200 } 1201 1202 /// CHECK-START: void Main.testStoreSameValue() load_store_elimination (before) 1203 /// CHECK: NewArray 1204 /// CHECK: ArrayGet 1205 /// CHECK: ArraySet 1206 1207 /// CHECK-START: void Main.testStoreSameValue() load_store_elimination (after) 1208 /// CHECK: NewArray 1209 /// CHECK-NOT: ArrayGet 1210 /// CHECK-NOT: ArraySet testStoreSameValue()1211 private static void testStoreSameValue() { 1212 Object[] array = new Object[2]; 1213 sArray = array; 1214 Object obj = array[0]; 1215 array[1] = obj; // store the same value as the defaut value. 1216 } 1217 1218 /// CHECK-START: int Main.$noinline$testByteArrayDefaultValue() load_store_elimination (before) 1219 /// CHECK-DAG: NewArray 1220 /// CHECK-DAG: <<Value:b\d+>> ArrayGet 1221 /// CHECK-DAG: Return [<<Value>>] 1222 1223 /// CHECK-START: int Main.$noinline$testByteArrayDefaultValue() load_store_elimination (after) 1224 /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 1225 /// CHECK-DAG: Return [<<Const0>>] 1226 1227 /// CHECK-START: int Main.$noinline$testByteArrayDefaultValue() load_store_elimination (after) 1228 /// CHECK-NOT: NewArray 1229 /// CHECK-NOT: ArrayGet 1230 /// CHECK-NOT: TypeConversion $noinline$testByteArrayDefaultValue()1231 private static int $noinline$testByteArrayDefaultValue() { 1232 byte[] array = new byte[2]; 1233 array[1] = 1; // FIXME: Without any stores, LSA tells LSE not to run. 1234 return array[0]; 1235 } 1236 1237 static Object[] sArray; 1238 1239 /// CHECK-START: int Main.testLocalArrayMerge1(boolean) load_store_elimination (before) 1240 /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 1241 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 1242 /// CHECK-DAG: <<A:l\d+>> NewArray 1243 /// CHECK-DAG: ArraySet [<<A>>,<<Const0>>,<<Const0>>] 1244 /// CHECK-DAG: ArraySet [<<A>>,<<Const0>>,<<Const1>>] 1245 /// CHECK-DAG: ArraySet [<<A>>,<<Const0>>,<<Const1>>] 1246 /// CHECK-DAG: <<Get:i\d+>> ArrayGet [<<A>>,<<Const0>>] 1247 /// CHECK-DAG: Return [<<Get>>] 1248 // 1249 /// CHECK-START: int Main.testLocalArrayMerge1(boolean) load_store_elimination (after) 1250 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 1251 /// CHECK-DAG: Return [<<Const1>>] 1252 // 1253 /// CHECK-START: int Main.testLocalArrayMerge1(boolean) load_store_elimination (after) 1254 /// CHECK-NOT: NewArray 1255 /// CHECK-NOT: ArraySet 1256 /// CHECK-NOT: ArrayGet testLocalArrayMerge1(boolean x)1257 private static int testLocalArrayMerge1(boolean x) { 1258 // The explicit store can be removed right away 1259 // since it is equivalent to the default. 1260 int[] a = { 0 }; 1261 // The diamond pattern stores/load can be replaced 1262 // by the direct value. 1263 if (x) { 1264 a[0] = 1; 1265 } else { 1266 a[0] = 1; 1267 } 1268 return a[0]; 1269 } 1270 1271 /// CHECK-START: int Main.testLocalArrayMerge2(boolean) load_store_elimination (before) 1272 /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 1273 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 1274 /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2 1275 /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3 1276 /// CHECK-DAG: <<A:l\d+>> NewArray 1277 /// CHECK-DAG: ArraySet [<<A>>,<<Const0>>,<<Const1>>] 1278 /// CHECK-DAG: ArraySet [<<A>>,<<Const0>>,<<Const2>>] 1279 /// CHECK-DAG: ArraySet [<<A>>,<<Const0>>,<<Const3>>] 1280 /// CHECK-DAG: <<Get:i\d+>> ArrayGet [<<A>>,<<Const0>>] 1281 /// CHECK-DAG: Return [<<Get>>] 1282 // 1283 /// CHECK-START: int Main.testLocalArrayMerge2(boolean) load_store_elimination (after) 1284 /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 1285 /// CHECK-DAG: <<A:l\d+>> NewArray 1286 /// CHECK-DAG: <<Get:i\d+>> ArrayGet [<<A>>,<<Const0>>] 1287 /// CHECK-DAG: Return [<<Get>>] 1288 // 1289 /// CHECK-START: int Main.testLocalArrayMerge2(boolean) load_store_elimination (after) 1290 /// CHECK-DAG: ArraySet 1291 /// CHECK-DAG: ArraySet 1292 /// CHECK-NOT: ArraySet testLocalArrayMerge2(boolean x)1293 private static int testLocalArrayMerge2(boolean x) { 1294 // The explicit store can be removed eventually even 1295 // though it is not equivalent to the default. 1296 int[] a = { 1 }; 1297 // The diamond pattern stores/load remain. 1298 if (x) { 1299 a[0] = 2; 1300 } else { 1301 a[0] = 3; 1302 } 1303 return a[0]; 1304 } 1305 1306 /// CHECK-START: int Main.testLocalArrayMerge3(boolean) load_store_elimination (after) 1307 /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 1308 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 1309 /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2 1310 /// CHECK-DAG: <<A:l\d+>> NewArray 1311 /// CHECK-DAG: ArraySet [<<A>>,<<Const0>>,<<Const1>>] 1312 /// CHECK-DAG: ArraySet [<<A>>,<<Const0>>,<<Const2>>] 1313 /// CHECK-DAG: <<Get:i\d+>> ArrayGet [<<A>>,<<Const0>>] 1314 /// CHECK-DAG: Return [<<Get>>] testLocalArrayMerge3(boolean x)1315 private static int testLocalArrayMerge3(boolean x) { 1316 // All stores/load remain. 1317 int[] a = { 1 }; 1318 if (x) { 1319 a[0] = 2; 1320 } 1321 return a[0]; 1322 } 1323 1324 /// CHECK-START: int Main.testLocalArrayMerge4(boolean) load_store_elimination (before) 1325 /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 1326 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 1327 /// CHECK-DAG: <<A:l\d+>> NewArray 1328 /// CHECK-DAG: ArraySet [<<A>>,<<Const0>>,<<Const0>>] 1329 /// CHECK-DAG: ArraySet [<<A>>,<<Const0>>,<<Const1>>] 1330 /// CHECK-DAG: ArraySet [<<A>>,<<Const0>>,<<Const1>>] 1331 /// CHECK-DAG: <<Get1:b\d+>> ArrayGet [<<A>>,<<Const0>>] 1332 /// CHECK-DAG: <<Get2:a\d+>> ArrayGet [<<A>>,<<Const0>>] 1333 /// CHECK-DAG: <<Add:i\d+>> Add [<<Get1>>,<<Get2>>] 1334 /// CHECK-DAG: Return [<<Add>>] 1335 // 1336 /// CHECK-START: int Main.testLocalArrayMerge4(boolean) load_store_elimination (after) 1337 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 1338 /// CHECK-DAG: <<Cnv1:b\d+>> TypeConversion [<<Const1>>] 1339 /// CHECK-DAG: <<Cnv2:a\d+>> TypeConversion [<<Const1>>] 1340 /// CHECK-DAG: <<Add:i\d+>> Add [<<Cnv1>>,<<Cnv2>>] 1341 /// CHECK-DAG: Return [<<Add>>] 1342 // 1343 /// CHECK-START: int Main.testLocalArrayMerge4(boolean) load_store_elimination (after) 1344 /// CHECK-NOT: NewArray 1345 /// CHECK-NOT: ArraySet 1346 /// CHECK-NOT: ArrayGet testLocalArrayMerge4(boolean x)1347 private static int testLocalArrayMerge4(boolean x) { 1348 byte[] a = { 0 }; 1349 if (x) { 1350 a[0] = 1; 1351 } else { 1352 a[0] = 1; 1353 } 1354 // Differently typed (signed vs unsigned), 1355 // but same reference. 1356 return a[0] + (a[0] & 0xff); 1357 } 1358 1359 /// CHECK-START: void Main.$noinline$testThrowingArraySet(java.lang.Object[], java.lang.Object) load_store_elimination (before) 1360 /// CHECK-DAG: ArrayGet 1361 /// CHECK-DAG: ArraySet 1362 /// CHECK-DAG: ArraySet 1363 /// CHECK-DAG: ArraySet 1364 /// CHECK-DAG: ArraySet 1365 1366 /// CHECK-START: void Main.$noinline$testThrowingArraySet(java.lang.Object[], java.lang.Object) load_store_elimination (after) 1367 /// CHECK-DAG: ArrayGet 1368 /// CHECK-DAG: ArraySet 1369 /// CHECK-DAG: ArraySet 1370 /// CHECK-DAG: ArraySet 1371 /// CHECK-DAG: ArraySet $noinline$testThrowingArraySet(Object[] a, Object o)1372 private static void $noinline$testThrowingArraySet(Object[] a, Object o) { 1373 Object olda0 = a[0]; 1374 a[0] = null; 1375 a[1] = olda0; 1376 a[0] = o; 1377 a[1] = null; 1378 } 1379 assertIntEquals(int result, int expected)1380 static void assertIntEquals(int result, int expected) { 1381 if (expected != result) { 1382 throw new Error("Expected: " + expected + ", found: " + result); 1383 } 1384 } 1385 assertFloatEquals(float result, float expected)1386 static void assertFloatEquals(float result, float expected) { 1387 if (expected != result) { 1388 throw new Error("Expected: " + expected + ", found: " + result); 1389 } 1390 } 1391 assertDoubleEquals(double result, double expected)1392 static void assertDoubleEquals(double result, double expected) { 1393 if (expected != result) { 1394 throw new Error("Expected: " + expected + ", found: " + result); 1395 } 1396 } 1397 main(String[] args)1398 public static void main(String[] args) { 1399 assertDoubleEquals(Math.PI * Math.PI * Math.PI, calcCircleArea(Math.PI)); 1400 assertIntEquals(test1(new TestClass(), new TestClass()), 3); 1401 assertIntEquals(test2(new TestClass()), 1); 1402 TestClass obj1 = new TestClass(); 1403 TestClass obj2 = new TestClass(); 1404 obj1.next = obj2; 1405 assertIntEquals(test3(obj1), 10); 1406 assertIntEquals(test4(new TestClass(), true), 1); 1407 assertIntEquals(test4(new TestClass(), false), 1); 1408 assertIntEquals(test5(new TestClass(), true), 1); 1409 assertIntEquals(test5(new TestClass(), false), 2); 1410 assertIntEquals(test6(new TestClass(), new TestClass(), true), 4); 1411 assertIntEquals(test6(new TestClass(), new TestClass(), false), 2); 1412 assertIntEquals(test7(new TestClass()), 1); 1413 assertIntEquals(test8(), 1); 1414 obj1 = new TestClass(); 1415 obj2 = new TestClass(); 1416 obj1.next = obj2; 1417 assertIntEquals(test9(new TestClass()), 1); 1418 assertIntEquals(test10(new TestClass(3, 4)), 3); 1419 assertIntEquals(TestClass.si, 3); 1420 assertIntEquals(test11(new TestClass()), 10); 1421 assertIntEquals(test12(new TestClass(), new TestClass()), 10); 1422 assertIntEquals(test13(new TestClass(), new TestClass2()), 3); 1423 SubTestClass obj3 = new SubTestClass(); 1424 assertIntEquals(test14(obj3, obj3), 2); 1425 assertIntEquals(test15(), 2); 1426 assertIntEquals(test16(), 3); 1427 assertIntEquals(test17(), 0); 1428 assertIntEquals(test18(new TestClass()), 1); 1429 float[] fa1 = { 0.8f }; 1430 float[] fa2 = { 1.8f }; 1431 assertFloatEquals(test19(fa1, fa2), 1.8f); 1432 assertFloatEquals(test20().i, 0); 1433 test21(new TestClass()); 1434 assertIntEquals(test22(), 13); 1435 assertIntEquals(test23(true), 4); 1436 assertIntEquals(test23(false), 5); 1437 assertFloatEquals(test24(), 8.0f); 1438 testFinalizableByForcingGc(); 1439 assertIntEquals($noinline$testHSelect(true), 0xdead); 1440 int[] array = {2, 5, 9, -1, -3, 10, 8, 4}; 1441 assertIntEquals(sumWithinRange(array, 1, 5), 11); 1442 assertFloatEquals(testAllocationEliminationWithLoops(), 1.0f); 1443 assertFloatEquals(mF, 0f); 1444 assertDoubleEquals(Math.PI * Math.PI * Math.PI, getCircleArea(Math.PI, true)); 1445 assertDoubleEquals(0d, getCircleArea(Math.PI, false)); 1446 1447 assertIntEquals($noinline$testConversion1(new TestClass(), 300), 300); 1448 assertIntEquals($noinline$testConversion1(new TestClass(), 301), 45); 1449 assertIntEquals($noinline$testConversion2(new TestClass(), 300), 300); 1450 assertIntEquals($noinline$testConversion2(new TestClass(), 301), 90); 1451 1452 int[] iarray = {0, 0, 0}; 1453 double[] darray = {0d, 0d, 0d}; 1454 try { 1455 assertDoubleEquals(Math.PI * Math.PI * Math.PI, testDeoptimize(iarray, darray, Math.PI)); 1456 } catch (Exception e) { 1457 System.out.println(e.getClass().getName()); 1458 } 1459 assertIntEquals(iarray[0], 1); 1460 assertIntEquals(iarray[1], 1); 1461 assertIntEquals(iarray[2], 1); 1462 assertDoubleEquals(darray[0], Math.PI); 1463 assertDoubleEquals(darray[1], Math.PI); 1464 assertDoubleEquals(darray[2], Math.PI); 1465 1466 assertIntEquals(testAllocationEliminationOfArray1(), 11); 1467 assertIntEquals(testAllocationEliminationOfArray2(), 11); 1468 assertIntEquals(testAllocationEliminationOfArray3(2), 4); 1469 assertIntEquals(testAllocationEliminationOfArray4(2), 6); 1470 assertIntEquals(testAllocationEliminationOfArray5(2), 12); 1471 try { 1472 testAllocationEliminationOfArray5(-2); 1473 } catch (NegativeArraySizeException e) { 1474 System.out.println("Got NegativeArraySizeException."); 1475 } 1476 1477 assertIntEquals(testStoreStore().i, 41); 1478 assertIntEquals(testStoreStore().j, 43); 1479 1480 assertIntEquals(testExitMerge(true), 2); 1481 assertIntEquals(testExitMerge2(true), 2); 1482 assertIntEquals(testExitMerge2(false), 2); 1483 1484 TestClass2 testclass2 = new TestClass2(); 1485 testStoreStore2(testclass2); 1486 assertIntEquals(testclass2.i, 43); 1487 assertIntEquals(testclass2.j, 44); 1488 1489 testStoreStore3(testclass2, true); 1490 assertIntEquals(testclass2.i, 41); 1491 assertIntEquals(testclass2.j, 43); 1492 testStoreStore3(testclass2, false); 1493 assertIntEquals(testclass2.i, 41); 1494 assertIntEquals(testclass2.j, 44); 1495 1496 testStoreStore4(); 1497 assertIntEquals(TestClass.si, 62); 1498 1499 int ret = testStoreStore5(testclass2, testclass2); 1500 assertIntEquals(testclass2.i, 72); 1501 assertIntEquals(ret, 71); 1502 1503 testclass2.j = 88; 1504 ret = testStoreStore6(testclass2, testclass2); 1505 assertIntEquals(testclass2.i, 82); 1506 assertIntEquals(ret, 88); 1507 1508 ret = testNoSideEffects(iarray); 1509 assertIntEquals(iarray[0], 101); 1510 assertIntEquals(iarray[1], 103); 1511 assertIntEquals(ret, 108); 1512 1513 try { 1514 testThrow(testclass2, new Exception()); 1515 } catch (Exception e) {} 1516 assertIntEquals(testclass2.i, 55); 1517 1518 assertIntEquals(testStoreStoreWithDeoptimize(new int[4]), 4); 1519 1520 assertIntEquals($noinline$testByteArrayDefaultValue(), 0); 1521 1522 assertIntEquals(testLocalArrayMerge1(true), 1); 1523 assertIntEquals(testLocalArrayMerge1(false), 1); 1524 assertIntEquals(testLocalArrayMerge2(true), 2); 1525 assertIntEquals(testLocalArrayMerge2(false), 3); 1526 assertIntEquals(testLocalArrayMerge3(true), 2); 1527 assertIntEquals(testLocalArrayMerge3(false), 1); 1528 assertIntEquals(testLocalArrayMerge4(true), 2); 1529 assertIntEquals(testLocalArrayMerge4(false), 2); 1530 1531 TestClass[] tca = new TestClass[] { new TestClass(), null }; 1532 try { 1533 $noinline$testThrowingArraySet(tca, new TestClass2()); 1534 } catch (ArrayStoreException expected) { 1535 if (tca[0] != null) { 1536 throw new Error("tca[0] is not null"); 1537 } 1538 if (tca[1] == null) { 1539 throw new Error("tca[1] is null"); 1540 } 1541 } 1542 } 1543 1544 static boolean sFlag; 1545 } 1546