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 int k; 58 int l; 59 int m; 60 } 61 62 class TestClass3 { 63 float floatField = 8.0f; 64 boolean test1 = true; 65 } 66 67 // Chosen to have different values with (x + 1) * 10 and (x - 1) * 10. This 68 // means we can easily make sure that different code is in fact executed on 69 // escape and non-escape paths. 70 // Negative so that high-bits will be set for all the 64-bit values allowing us 71 // to easily check for truncation. 72 class TestClass4 { 73 float floatField = -3.0f; 74 double doubleField = -3.0d; 75 short shortField = -3; 76 int intField = -3; 77 byte byteField = -3; 78 long longField = -3l; 79 } 80 81 class Finalizable { 82 static boolean sVisited = false; 83 static final int VALUE1 = 0xbeef; 84 static final int VALUE2 = 0xcafe; 85 int i; 86 finalize()87 protected void finalize() { 88 if (i != VALUE1) { 89 System.out.println("Where is the beef?"); 90 } 91 sVisited = true; 92 } 93 } 94 95 interface Filter { isValid(int i)96 public boolean isValid(int i); 97 } 98 99 public class Main { $noinline$Escape4(TestClass4 o)100 static void $noinline$Escape4(TestClass4 o) { 101 o.floatField += 1.0f; 102 o.doubleField += 1.0d; 103 o.byteField += 1; 104 o.shortField += 1; 105 o.intField += 1; 106 o.longField += 1; 107 } 108 109 static Object ESCAPE = null; $noinline$Escape(TestClass o)110 static void $noinline$Escape(TestClass o) { 111 if (o == null) { 112 return; 113 } 114 ESCAPE = o; 115 o.next.i++; 116 } 117 118 /// CHECK-START: double Main.calcCircleArea(double) load_store_elimination (before) 119 /// CHECK: NewInstance 120 /// CHECK: InstanceFieldSet 121 /// CHECK: InstanceFieldGet 122 123 /// CHECK-START: double Main.calcCircleArea(double) load_store_elimination (after) 124 /// CHECK-NOT: NewInstance 125 /// CHECK-NOT: InstanceFieldSet 126 /// CHECK-NOT: InstanceFieldGet 127 calcCircleArea(double radius)128 static double calcCircleArea(double radius) { 129 return new Circle(radius).getArea(); 130 } 131 132 /// CHECK-START: int Main.test1(TestClass, TestClass) load_store_elimination (before) 133 /// CHECK: InstanceFieldSet 134 /// CHECK: InstanceFieldSet 135 /// CHECK: InstanceFieldGet 136 /// CHECK: InstanceFieldGet 137 138 /// CHECK-START: int Main.test1(TestClass, TestClass) load_store_elimination (after) 139 /// CHECK: InstanceFieldSet 140 /// CHECK: InstanceFieldSet 141 /// CHECK-NOT: NullCheck 142 /// CHECK-NOT: InstanceFieldGet 143 144 // Different fields shouldn't alias. test1(TestClass obj1, TestClass obj2)145 static int test1(TestClass obj1, TestClass obj2) { 146 obj1.i = 1; 147 obj2.j = 2; 148 return obj1.i + obj2.j; 149 } 150 151 /// CHECK-START: int Main.test2(TestClass) load_store_elimination (before) 152 /// CHECK: InstanceFieldSet 153 /// CHECK: InstanceFieldSet 154 /// CHECK: InstanceFieldGet 155 156 /// CHECK-START: int Main.test2(TestClass) load_store_elimination (after) 157 /// CHECK: InstanceFieldSet 158 /// CHECK-NOT: NullCheck 159 /// CHECK-NOT: InstanceFieldSet 160 /// CHECK-NOT: InstanceFieldGet 161 162 // Redundant store of the same value. test2(TestClass obj)163 static int test2(TestClass obj) { 164 obj.j = 1; 165 obj.j = 1; 166 return obj.j; 167 } 168 169 /// CHECK-START: int Main.test3(TestClass) load_store_elimination (before) 170 /// CHECK: StaticFieldGet 171 /// CHECK: NewInstance 172 /// CHECK: InstanceFieldSet 173 /// CHECK: InstanceFieldSet 174 /// CHECK: InstanceFieldSet 175 /// CHECK: InstanceFieldSet 176 /// CHECK: InstanceFieldSet 177 /// CHECK: InstanceFieldGet 178 /// CHECK: InstanceFieldGet 179 /// CHECK: InstanceFieldGet 180 /// CHECK: InstanceFieldGet 181 182 /// CHECK-START: int Main.test3(TestClass) load_store_elimination (after) 183 /// CHECK: StaticFieldGet 184 /// CHECK: NewInstance 185 /// CHECK: InstanceFieldSet 186 /// CHECK: InstanceFieldSet 187 /// CHECK: InstanceFieldSet 188 /// CHECK: InstanceFieldSet 189 /// CHECK: InstanceFieldSet 190 191 /// CHECK-START: int Main.test3(TestClass) load_store_elimination (after) 192 /// CHECK-NOT: InstanceFieldGet 193 194 // A new allocation (even non-singleton) shouldn't alias with pre-existing values. test3(TestClass obj)195 static int test3(TestClass obj) { 196 TestClass obj1 = TestClass.sTestClassObj; 197 TestClass obj2 = new TestClass(); // Cannot alias with obj or obj1 which pre-exist. 198 obj.next = obj2; // Make obj2 a non-singleton. 199 // All stores below need to stay since obj/obj1/obj2 are not singletons. 200 obj.i = 1; 201 obj1.j = 2; 202 // Following stores won't kill values of obj.i and obj1.j. 203 obj2.i = 3; 204 obj2.j = 4; 205 return obj.i + obj1.j + obj2.i + obj2.j; 206 } 207 208 /// CHECK-START: int Main.test4(TestClass, boolean) load_store_elimination (before) 209 /// CHECK-DAG: InstanceFieldSet 210 /// CHECK-DAG: InstanceFieldSet 211 /// CHECK-DAG: InstanceFieldGet 212 /// CHECK-DAG: Return 213 214 /// CHECK-START: int Main.test4(TestClass, boolean) load_store_elimination (after) 215 /// CHECK-DAG: InstanceFieldSet 216 /// CHECK-DAG: InstanceFieldSet 217 /// CHECK-DAG: Return 218 219 /// CHECK-START: int Main.test4(TestClass, boolean) load_store_elimination (after) 220 /// CHECK-NOT: InstanceFieldGet 221 222 /// CHECK-START: int Main.test4(TestClass, boolean) load_store_elimination (after) 223 /// CHECK-NOT: Phi 224 225 // Set and merge the same value in two branches. test4(TestClass obj, boolean b)226 static int test4(TestClass obj, boolean b) { 227 if (b) { 228 obj.i = 1; 229 } else { 230 obj.i = 1; 231 } 232 return obj.i; 233 } 234 235 /// CHECK-START: int Main.test5(TestClass, boolean) load_store_elimination (before) 236 /// CHECK-DAG: <<Int1:i\d+>> IntConstant 1 237 /// CHECK-DAG: <<Int2:i\d+>> IntConstant 2 238 /// CHECK-DAG: <<Obj:l\d+>> ParameterValue 239 /// CHECK-DAG: InstanceFieldSet [{{l\d+}},<<Int1>>] 240 /// CHECK-DAG: InstanceFieldSet [{{l\d+}},<<Int2>>] 241 /// CHECK-DAG: <<GetField:i\d+>> InstanceFieldGet [{{l\d+}}] 242 /// CHECK-DAG: Return [<<GetField>>] 243 244 /// CHECK-START: int Main.test5(TestClass, boolean) load_store_elimination (after) 245 /// CHECK-DAG: <<Int1:i\d+>> IntConstant 1 246 /// CHECK-DAG: <<Int2:i\d+>> IntConstant 2 247 /// CHECK-DAG: <<Obj:l\d+>> ParameterValue 248 /// CHECK-DAG: InstanceFieldSet [{{l\d+}},<<Int1>>] 249 /// CHECK-DAG: InstanceFieldSet [{{l\d+}},<<Int2>>] 250 /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Arg1:i\d+>>,<<Arg2:i\d+>>] 251 /// CHECK-DAG: Return [<<Phi>>] 252 /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>"]) == set(["<<Int1>>","<<Int2>>"]) 253 254 /// CHECK-START: int Main.test5(TestClass, boolean) load_store_elimination (after) 255 /// CHECK-NOT: InstanceFieldGet 256 257 // Set and merge different values in two branches. test5(TestClass obj, boolean b)258 static int test5(TestClass obj, boolean b) { 259 if (b) { 260 obj.i = 1; 261 } else { 262 obj.i = 2; 263 } 264 return obj.i; 265 } 266 267 /// CHECK-START: int Main.test6(TestClass, TestClass, boolean) load_store_elimination (before) 268 /// CHECK-DAG: InstanceFieldSet 269 /// CHECK-DAG: InstanceFieldSet 270 /// CHECK-DAG: InstanceFieldSet 271 /// CHECK-DAG: InstanceFieldGet 272 /// CHECK-DAG: InstanceFieldGet 273 274 /// CHECK-START: int Main.test6(TestClass, TestClass, boolean) load_store_elimination (after) 275 /// CHECK-DAG: InstanceFieldSet 276 /// CHECK-DAG: InstanceFieldSet 277 /// CHECK-DAG: InstanceFieldSet 278 /// CHECK-DAG: InstanceFieldGet 279 280 /// CHECK-START: int Main.test6(TestClass, TestClass, boolean) load_store_elimination (after) 281 /// CHECK: InstanceFieldGet 282 /// CHECK-NOT: InstanceFieldGet 283 284 // Setting the same value doesn't clear the value for aliased locations. test6(TestClass obj1, TestClass obj2, boolean b)285 static int test6(TestClass obj1, TestClass obj2, boolean b) { 286 obj1.i = 1; 287 obj1.j = 2; 288 if (b) { 289 obj2.j = 2; 290 } 291 return obj1.j + obj2.j; 292 } 293 294 /// CHECK-START: int Main.test7(TestClass) load_store_elimination (before) 295 /// CHECK: InstanceFieldSet 296 /// CHECK: InstanceFieldGet 297 298 /// CHECK-START: int Main.test7(TestClass) load_store_elimination (after) 299 /// CHECK: InstanceFieldSet 300 /// CHECK: InstanceFieldGet 301 302 // Invocation should kill values in non-singleton heap locations. test7(TestClass obj)303 static int test7(TestClass obj) { 304 obj.i = 1; 305 System.out.print(""); 306 return obj.i; 307 } 308 309 /// CHECK-START: int Main.test8() load_store_elimination (before) 310 /// CHECK: NewInstance 311 /// CHECK: InstanceFieldSet 312 /// CHECK: InvokeVirtual 313 /// CHECK: InstanceFieldGet 314 315 /// CHECK-START: int Main.test8() load_store_elimination (after) 316 /// CHECK-NOT: NewInstance 317 /// CHECK-NOT: InstanceFieldSet 318 /// CHECK: InvokeVirtual 319 /// CHECK-NOT: NullCheck 320 /// CHECK-NOT: InstanceFieldGet 321 322 // Invocation should not kill values in singleton heap locations. test8()323 static int test8() { 324 TestClass obj = new TestClass(); 325 obj.i = 1; 326 System.out.print(""); 327 return obj.i; 328 } 329 330 /// CHECK-START: int Main.test9(TestClass) load_store_elimination (before) 331 /// CHECK: NewInstance 332 /// CHECK: InstanceFieldSet 333 /// CHECK: InstanceFieldSet 334 /// CHECK: InstanceFieldGet 335 336 /// CHECK-START: int Main.test9(TestClass) load_store_elimination (after) 337 /// CHECK: NewInstance 338 /// CHECK: InstanceFieldSet 339 /// CHECK: InstanceFieldSet 340 /// CHECK: InstanceFieldGet 341 342 // Invocation should kill values in non-singleton heap locations. test9(TestClass obj)343 static int test9(TestClass obj) { 344 TestClass obj2 = new TestClass(); 345 obj2.i = 1; 346 obj.next = obj2; 347 System.out.print(""); 348 return obj2.i; 349 } 350 351 /// CHECK-START: int Main.test10(TestClass) load_store_elimination (before) 352 /// CHECK-DAG: StaticFieldGet 353 /// CHECK-DAG: InstanceFieldGet 354 /// CHECK-DAG: StaticFieldSet 355 /// CHECK-DAG: InstanceFieldGet 356 357 /// CHECK-START: int Main.test10(TestClass) load_store_elimination (after) 358 /// CHECK-DAG: StaticFieldGet 359 /// CHECK-DAG: InstanceFieldGet 360 /// CHECK-DAG: StaticFieldSet 361 362 /// CHECK-START: int Main.test10(TestClass) load_store_elimination (after) 363 /// CHECK: NullCheck 364 /// CHECK-NOT: NullCheck 365 366 /// CHECK-START: int Main.test10(TestClass) load_store_elimination (after) 367 /// CHECK: InstanceFieldGet 368 /// CHECK-NOT: InstanceFieldGet 369 370 // Static fields shouldn't alias with instance fields. test10(TestClass obj)371 static int test10(TestClass obj) { 372 TestClass.si += obj.i; 373 return obj.i; 374 } 375 376 /// CHECK-START: int Main.test11(TestClass) load_store_elimination (before) 377 /// CHECK: InstanceFieldSet 378 /// CHECK: InstanceFieldGet 379 380 /// CHECK-START: int Main.test11(TestClass) load_store_elimination (after) 381 /// CHECK: InstanceFieldSet 382 /// CHECK-NOT: NullCheck 383 /// CHECK-NOT: InstanceFieldGet 384 385 // Loop without heap writes. test11(TestClass obj)386 static int test11(TestClass obj) { 387 obj.i = 1; 388 int sum = 0; 389 for (int i = 0; i < 10; i++) { 390 sum += obj.i; 391 } 392 return sum; 393 } 394 395 /// CHECK-START: int Main.test12(TestClass, TestClass) load_store_elimination (before) 396 /// CHECK: InstanceFieldSet 397 /// CHECK: InstanceFieldGet 398 /// CHECK: InstanceFieldSet 399 400 /// CHECK-START: int Main.test12(TestClass, TestClass) load_store_elimination (after) 401 /// CHECK: InstanceFieldSet 402 /// CHECK: InstanceFieldGet 403 /// CHECK: InstanceFieldSet 404 405 // Loop with heap writes. test12(TestClass obj1, TestClass obj2)406 static int test12(TestClass obj1, TestClass obj2) { 407 obj1.i = 1; 408 int sum = 0; 409 for (int i = 0; i < 10; i++) { 410 sum += obj1.i; 411 obj2.i = sum; 412 } 413 return sum; 414 } 415 416 /// CHECK-START: int Main.test13(TestClass, TestClass2) load_store_elimination (before) 417 /// CHECK: InstanceFieldSet 418 /// CHECK: InstanceFieldSet 419 /// CHECK: InstanceFieldGet 420 /// CHECK: InstanceFieldGet 421 422 /// CHECK-START: int Main.test13(TestClass, TestClass2) load_store_elimination (after) 423 /// CHECK: InstanceFieldSet 424 /// CHECK: InstanceFieldSet 425 /// CHECK-NOT: NullCheck 426 /// CHECK-NOT: InstanceFieldGet 427 428 // Different classes shouldn't alias. test13(TestClass obj1, TestClass2 obj2)429 static int test13(TestClass obj1, TestClass2 obj2) { 430 obj1.i = 1; 431 obj2.i = 2; 432 return obj1.i + obj2.i; 433 } 434 435 /// CHECK-START: int Main.test14(TestClass, SubTestClass) load_store_elimination (before) 436 /// CHECK: InstanceFieldSet 437 /// CHECK: InstanceFieldSet 438 /// CHECK: InstanceFieldGet 439 440 /// CHECK-START: int Main.test14(TestClass, SubTestClass) load_store_elimination (after) 441 /// CHECK: InstanceFieldSet 442 /// CHECK: InstanceFieldSet 443 /// CHECK: InstanceFieldGet 444 445 // Subclass may alias with super class. test14(TestClass obj1, SubTestClass obj2)446 static int test14(TestClass obj1, SubTestClass obj2) { 447 obj1.i = 1; 448 obj2.i = 2; 449 return obj1.i; 450 } 451 452 /// CHECK-START: int Main.test15() load_store_elimination (before) 453 /// CHECK: StaticFieldSet 454 /// CHECK: StaticFieldSet 455 /// CHECK: StaticFieldGet 456 457 /// CHECK-START: int Main.test15() load_store_elimination (after) 458 /// CHECK: <<Const2:i\d+>> IntConstant 2 459 /// CHECK: StaticFieldSet 460 /// CHECK: Return [<<Const2>>] 461 462 /// CHECK-START: int Main.test15() load_store_elimination (after) 463 /// CHECK-NOT: StaticFieldGet 464 465 // Static field access from subclass's name. test15()466 static int test15() { 467 TestClass.si = 1; 468 SubTestClass.si = 2; 469 return TestClass.si; 470 } 471 472 /// CHECK-START: int Main.test16() load_store_elimination (before) 473 /// CHECK: NewInstance 474 /// CHECK: InstanceFieldSet 475 /// CHECK: InstanceFieldSet 476 /// CHECK: InstanceFieldGet 477 /// CHECK: InstanceFieldGet 478 479 /// CHECK-START: int Main.test16() load_store_elimination (after) 480 /// CHECK-NOT: NewInstance 481 /// CHECK-NOT: InstanceFieldSet 482 /// CHECK-NOT: InstanceFieldGet 483 484 // Test inlined constructor. test16()485 static int test16() { 486 TestClass obj = new TestClass(1, 2); 487 return obj.i + obj.j; 488 } 489 490 /// CHECK-START: int Main.test17() load_store_elimination (before) 491 /// CHECK: NewInstance 492 /// CHECK: InstanceFieldSet 493 /// CHECK: InstanceFieldGet 494 495 /// CHECK-START: int Main.test17() load_store_elimination (after) 496 /// CHECK: <<Const0:i\d+>> IntConstant 0 497 /// CHECK-NOT: NewInstance 498 /// CHECK-NOT: InstanceFieldSet 499 /// CHECK-NOT: InstanceFieldGet 500 /// CHECK: Return [<<Const0>>] 501 502 // Test getting default value. test17()503 static int test17() { 504 TestClass obj = new TestClass(); 505 obj.j = 1; 506 return obj.i; 507 } 508 509 /// CHECK-START: int Main.test18(TestClass) load_store_elimination (before) 510 /// CHECK: InstanceFieldSet 511 /// CHECK: InstanceFieldGet 512 513 /// CHECK-START: int Main.test18(TestClass) load_store_elimination (after) 514 /// CHECK: InstanceFieldSet 515 /// CHECK: InstanceFieldGet 516 517 // Volatile field load/store shouldn't be eliminated. test18(TestClass obj)518 static int test18(TestClass obj) { 519 obj.k = 1; 520 return obj.k; 521 } 522 523 /// CHECK-START: float Main.test19(float[], float[]) load_store_elimination (before) 524 /// CHECK: {{f\d+}} ArrayGet 525 /// CHECK: {{f\d+}} ArrayGet 526 527 /// CHECK-START: float Main.test19(float[], float[]) load_store_elimination (after) 528 /// CHECK: {{f\d+}} ArrayGet 529 /// CHECK-NOT: {{f\d+}} ArrayGet 530 531 // I/F, J/D aliasing should not happen any more and LSE should eliminate the load. test19(float[] fa1, float[] fa2)532 static float test19(float[] fa1, float[] fa2) { 533 fa1[0] = fa2[0]; 534 return fa1[0]; 535 } 536 537 /// CHECK-START: TestClass Main.test20() load_store_elimination (before) 538 /// CHECK: NewInstance 539 /// CHECK: InstanceFieldSet 540 541 /// CHECK-START: TestClass Main.test20() load_store_elimination (after) 542 /// CHECK: NewInstance 543 /// CHECK-NOT: InstanceFieldSet 544 545 // Storing default heap value is redundant if the heap location has the 546 // default heap value. test20()547 static TestClass test20() { 548 TestClass obj = new TestClass(); 549 obj.i = 0; 550 return obj; 551 } 552 553 /// CHECK-START: void Main.test21(TestClass) load_store_elimination (before) 554 /// CHECK-DAG: NewInstance 555 /// CHECK-DAG: InstanceFieldSet 556 /// CHECK-DAG: InstanceFieldSet 557 /// CHECK-DAG: InstanceFieldSet 558 /// CHECK-DAG: InstanceFieldGet 559 /// CHECK-DAG: InstanceFieldGet 560 561 /// CHECK-START: void Main.test21(TestClass) load_store_elimination (after) 562 /// CHECK-DAG: InstanceFieldSet 563 564 /// CHECK-START: void Main.test21(TestClass) load_store_elimination (after) 565 /// CHECK-NOT: NewInstance 566 /// CHECK-NOT: InstanceFieldGet 567 568 // Loop side effects can kill heap values, stores need to be kept in that case. test21(TestClass obj0)569 static void test21(TestClass obj0) { 570 TestClass obj = new TestClass(); 571 obj0.str = "abc"; 572 obj.str = "abc"; 573 // Note: This loop is transformed by the loop optimization pass, therefore we 574 // are not checking the exact number of InstanceFieldSet and Phi instructions. 575 for (int i = 0; i < 2; i++) { 576 // Generate some loop side effect that writes into obj. 577 obj.str = "def"; 578 } 579 $noinline$printSubstrings00(obj0.str, obj.str); 580 } 581 $noinline$printSubstrings00(String str1, String str2)582 static void $noinline$printSubstrings00(String str1, String str2) { 583 System.out.print(str1.substring(0, 0) + str2.substring(0, 0)); 584 } 585 586 /// CHECK-START: int Main.test22() load_store_elimination (before) 587 /// CHECK: NewInstance 588 /// CHECK: InstanceFieldSet 589 /// CHECK: NewInstance 590 /// CHECK: InstanceFieldSet 591 /// CHECK: InstanceFieldGet 592 /// CHECK: NewInstance 593 /// CHECK: InstanceFieldSet 594 /// CHECK: InstanceFieldGet 595 /// CHECK: InstanceFieldGet 596 597 /// CHECK-START: int Main.test22() load_store_elimination (after) 598 /// CHECK-NOT: NewInstance 599 /// CHECK-NOT: InstanceFieldSet 600 /// CHECK-NOT: InstanceFieldGet 601 602 // For a singleton, loop side effects can kill its field values only if: 603 // (1) it dominiates the loop header, and 604 // (2) its fields are stored into inside a loop. test22()605 static int test22() { 606 int sum = 0; 607 TestClass obj1 = new TestClass(); 608 obj1.i = 2; // This store can be eliminated since obj1 is never stored into inside a loop. 609 for (int i = 0; i < 2; i++) { 610 TestClass obj2 = new TestClass(); 611 obj2.i = 3; // This store can be eliminated since the singleton is inside the loop. 612 sum += obj2.i; 613 } 614 TestClass obj3 = new TestClass(); 615 obj3.i = 5; // This store can be eliminated since the singleton is created after the loop. 616 sum += obj1.i + obj3.i; 617 return sum; 618 } 619 620 /// CHECK-START: int Main.test23(boolean) load_store_elimination (before) 621 /// CHECK-DAG: <<Int1:i\d+>> IntConstant 1 622 /// CHECK-DAG: <<Int2:i\d+>> IntConstant 2 623 /// CHECK-DAG: <<Int3:i\d+>> IntConstant 3 624 /// CHECK-DAG: <<Obj:l\d+>> NewInstance 625 /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Int3>>] 626 /// CHECK-DAG: <<Add1:i\d+>> Add [<<Get1:i\d+>>,<<Int1>>] 627 /// CHECK-DAG: <<Get1>> InstanceFieldGet [<<Obj>>] 628 /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Add1>>] 629 /// CHECK-DAG: <<Add2:i\d+>> Add [<<Get2:i\d+>>,<<Int2>>] 630 /// CHECK-DAG: <<Get2>> InstanceFieldGet [<<Obj>>] 631 /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Add2>>] 632 /// CHECK-DAG: Return [<<Get3:i\d+>>] 633 /// CHECK-DAG: <<Get3>> InstanceFieldGet [<<Obj>>] 634 635 /// CHECK-START: int Main.test23(boolean) load_store_elimination (after) 636 /// CHECK-DAG: <<Int1:i\d+>> IntConstant 1 637 /// CHECK-DAG: <<Int2:i\d+>> IntConstant 2 638 /// CHECK-DAG: <<Int3:i\d+>> IntConstant 3 639 /// CHECK-DAG: <<Add1:i\d+>> Add [<<Int3>>,<<Int1>>] 640 /// CHECK-DAG: <<Add2:i\d+>> Add [<<Int3>>,<<Int2>>] 641 /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Arg1:i\d+>>,<<Arg2:i\d+>>] 642 /// CHECK-DAG: Return [<<Phi>>] 643 /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>"]) == set(["<<Add1>>","<<Add2>>"]) 644 645 /// CHECK-START: int Main.test23(boolean) load_store_elimination (after) 646 /// CHECK-NOT: NewInstance 647 /// CHECK-NOT: InstanceFieldSet 648 /// CHECK-NOT: InstanceFieldGet 649 650 // Test heap value merging from multiple branches. test23(boolean b)651 static int test23(boolean b) { 652 TestClass obj = new TestClass(); 653 obj.i = 3; // This store can be eliminated since the value flows into each branch. 654 if (b) { 655 obj.i += 1; // This store can be eliminated after replacing the load below with a Phi. 656 } else { 657 obj.i += 2; // This store can be eliminated after replacing the load below with a Phi. 658 } 659 return obj.i; // This load is eliminated by creating a Phi. 660 } 661 662 /// CHECK-START: float Main.test24() load_store_elimination (before) 663 /// CHECK-DAG: <<True:i\d+>> IntConstant 1 664 /// CHECK-DAG: <<Float8:f\d+>> FloatConstant 8 665 /// CHECK-DAG: <<Float42:f\d+>> FloatConstant 42 666 /// CHECK-DAG: <<Obj:l\d+>> NewInstance 667 /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<True>>] 668 /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Float8>>] 669 /// CHECK-DAG: <<GetTest:z\d+>> InstanceFieldGet [<<Obj>>] 670 /// CHECK-DAG: <<GetField:f\d+>> InstanceFieldGet [<<Obj>>] 671 /// CHECK-DAG: <<Select:f\d+>> Select [<<Float42>>,<<GetField>>,<<GetTest>>] 672 /// CHECK-DAG: Return [<<Select>>] 673 674 /// CHECK-START: float Main.test24() load_store_elimination (after) 675 /// CHECK-DAG: <<True:i\d+>> IntConstant 1 676 /// CHECK-DAG: <<Float8:f\d+>> FloatConstant 8 677 /// CHECK-DAG: <<Float42:f\d+>> FloatConstant 42 678 /// CHECK-DAG: <<Select:f\d+>> Select [<<Float42>>,<<Float8>>,<<True>>] 679 /// CHECK-DAG: Return [<<Select>>] 680 681 /// CHECK-START: float Main.test24() load_store_elimination (after) 682 /// CHECK-NOT: NewInstance 683 /// CHECK-NOT: InstanceFieldGet test24()684 static float test24() { 685 float a = 42.0f; 686 TestClass3 obj = new TestClass3(); 687 if (obj.test1) { 688 a = obj.floatField; 689 } 690 return a; 691 } 692 693 /// CHECK-START: int Main.test25(boolean, boolean, boolean) load_store_elimination (before) 694 /// CHECK-DAG: <<Int1:i\d+>> IntConstant 1 695 /// CHECK-DAG: <<Int2:i\d+>> IntConstant 2 696 /// CHECK-DAG: <<Int3:i\d+>> IntConstant 3 697 /// CHECK-DAG: <<Int5:i\d+>> IntConstant 5 698 /// CHECK-DAG: <<Int6:i\d+>> IntConstant 6 699 /// CHECK-DAG: <<Obj:l\d+>> NewInstance 700 /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Int1>>] 701 /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Int2>>] 702 /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Int3>>] 703 /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Int5>>] 704 /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Int6>>] 705 /// CHECK-DAG: <<GetField:i\d+>> InstanceFieldGet [<<Obj>>] 706 /// CHECK-DAG: Return [<<GetField>>] 707 708 /// CHECK-START: int Main.test25(boolean, boolean, boolean) load_store_elimination (after) 709 /// CHECK-DAG: <<Int1:i\d+>> IntConstant 1 710 /// CHECK-DAG: <<Int2:i\d+>> IntConstant 2 711 /// CHECK-DAG: <<Int3:i\d+>> IntConstant 3 712 /// CHECK-DAG: <<Int5:i\d+>> IntConstant 5 713 /// CHECK-DAG: <<Int6:i\d+>> IntConstant 6 714 /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Arg1:i\d+>>,<<Arg2:i\d+>>,<<Arg3:i\d+>>,<<Arg4:i\d+>>,<<Arg5:i\d+>>] 715 /// CHECK-DAG: Return [<<Phi>>] 716 /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>","<<Arg3>>","<<Arg4>>","<<Arg5>>"]) == set(["<<Int1>>","<<Int2>>","<<Int3>>","<<Int5>>","<<Int6>>"]) 717 718 /// CHECK-START: int Main.test25(boolean, boolean, boolean) load_store_elimination (after) 719 /// CHECK-NOT: NewInstance 720 /// CHECK-NOT: InstanceFieldSet 721 /// CHECK-NOT: InstanceFieldGet 722 723 // Test heap value merging from nested branches. test25(boolean b, boolean c, boolean d)724 static int test25(boolean b, boolean c, boolean d) { 725 TestClass obj = new TestClass(); 726 if (b) { 727 if (c) { 728 obj.i = 1; 729 } else { 730 if (d) { 731 obj.i = 2; 732 } else { 733 obj.i = 3; 734 } 735 } 736 } else { 737 if (c) { 738 obj.i = 5; 739 } else { 740 obj.i = 6; 741 } 742 } 743 return obj.i; 744 } 745 746 /// CHECK-START: float Main.test26(int) load_store_elimination (before) 747 /// CHECK-DAG: <<Float0:f\d+>> FloatConstant 0 748 /// CHECK-DAG: <<Float1:f\d+>> FloatConstant 1 749 /// CHECK-DAG: <<Float2:f\d+>> FloatConstant 2 750 /// CHECK-DAG: <<Float3:f\d+>> FloatConstant 3 751 /// CHECK-DAG: <<Float8:f\d+>> FloatConstant 8 752 /// CHECK-DAG: <<Obj:l\d+>> NewInstance 753 /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Float8>>] 754 /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Float0>>] 755 /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Float1>>] 756 /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Float2>>] 757 /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Float3>>] 758 /// CHECK-DAG: <<GetField:f\d+>> InstanceFieldGet [<<Obj>>] 759 /// CHECK-DAG: Return [<<GetField>>] 760 761 /// CHECK-START: float Main.test26(int) load_store_elimination (after) 762 /// CHECK-DAG: <<Float0:f\d+>> FloatConstant 0 763 /// CHECK-DAG: <<Float1:f\d+>> FloatConstant 1 764 /// CHECK-DAG: <<Float2:f\d+>> FloatConstant 2 765 /// CHECK-DAG: <<Float3:f\d+>> FloatConstant 3 766 /// CHECK-DAG: <<Float8:f\d+>> FloatConstant 8 767 /// CHECK-DAG: <<Phi:f\d+>> Phi [<<Arg1:f\d+>>,<<Arg2:f\d+>>,<<Arg3:f\d+>>,<<Arg4:f\d+>>] 768 /// CHECK-DAG: Return [<<Phi>>] 769 /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>","<<Arg3>>","<<Arg4>>"]) == set(["<<Float0>>","<<Float1>>","<<Float2>>","<<Float3>>"]) 770 771 /// CHECK-START: float Main.test26(int) load_store_elimination (after) 772 /// CHECK-NOT: NewInstance 773 /// CHECK-NOT: InstanceFieldSet 774 /// CHECK-NOT: InstanceFieldGet 775 776 // Test heap value merging from switch statement. test26(int b)777 static float test26(int b) { 778 TestClass3 obj = new TestClass3(); 779 switch (b) { 780 case 1: 781 obj.floatField = 3.0f; 782 break; 783 case 2: 784 obj.floatField = 2.0f; 785 break; 786 case 3: 787 obj.floatField = 1.0f; 788 break; 789 default: 790 obj.floatField = 0.0f; 791 break; 792 } 793 return obj.floatField; 794 } 795 796 /// CHECK-START: int Main.test27(boolean, boolean) load_store_elimination (before) 797 /// CHECK-DAG: <<Int1:i\d+>> IntConstant 1 798 /// CHECK-DAG: <<Obj:l\d+>> NewInstance 799 /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Int1>>] 800 /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Int1>>] 801 /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Int1>>] 802 /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Int1>>] 803 /// CHECK-DAG: <<GetField:i\d+>> InstanceFieldGet [<<Obj>>] 804 /// CHECK-DAG: Return [<<GetField>>] 805 806 /// CHECK-START: int Main.test27(boolean, boolean) load_store_elimination (after) 807 /// CHECK-DAG: <<Int1:i\d+>> IntConstant 1 808 /// CHECK-DAG: Return [<<Int1>>] 809 810 /// CHECK-START: int Main.test27(boolean, boolean) load_store_elimination (after) 811 /// CHECK-NOT: NewInstance 812 /// CHECK-NOT: InstanceFieldSet 813 /// CHECK-NOT: InstanceFieldGet 814 /// CHECK-NOT: Phi 815 816 // Test merging same value from nested branches. test27(boolean b, boolean c)817 static int test27(boolean b, boolean c) { 818 TestClass obj = new TestClass(); 819 if (b) { 820 if (c) { 821 obj.i = 1; 822 } else { 823 obj.i = 1; 824 } 825 } else { 826 if (c) { 827 obj.i = 1; 828 } else { 829 obj.i = 1; 830 } 831 } 832 return obj.i; 833 } 834 835 /// CHECK-START: int Main.test28(boolean, boolean) load_store_elimination (before) 836 /// CHECK-DAG: <<Int0:i\d+>> IntConstant 0 837 /// CHECK-DAG: <<Int5:i\d+>> IntConstant 5 838 /// CHECK-DAG: <<Int6:i\d+>> IntConstant 6 839 /// CHECK-DAG: <<Array:l\d+>> NewArray 840 /// CHECK-DAG: ArraySet [<<Array>>,<<Int0>>,<<Int5>>] 841 /// CHECK-DAG: ArraySet [<<Array>>,<<Int0>>,<<Int6>>] 842 /// CHECK-DAG: <<GetIndex:i\d+>> ArrayGet [<<Array>>,<<Int0>>] 843 /// CHECK-DAG: Return [<<GetIndex>>] 844 845 /// CHECK-START: int Main.test28(boolean, boolean) load_store_elimination (after) 846 /// CHECK-DAG: <<Int0:i\d+>> IntConstant 0 847 /// CHECK-DAG: <<Int5:i\d+>> IntConstant 5 848 /// CHECK-DAG: <<Int6:i\d+>> IntConstant 6 849 /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Arg1:i\d+>>,<<Arg2:i\d+>>,<<Arg3:i\d+>>] 850 /// CHECK-DAG: Return [<<Phi>>] 851 /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>","<<Arg3>>"]) == set(["<<Int0>>","<<Int5>>","<<Int6>>"]) 852 853 /// CHECK-START: int Main.test28(boolean, boolean) load_store_elimination (after) 854 /// CHECK-NOT: NewArray 855 /// CHECK-NOT: ArraySet 856 /// CHECK-NOT: ArrayGet 857 858 // Test merging array stores in branches. test28(boolean b, boolean c)859 static int test28(boolean b, boolean c) { 860 int[] array = new int[1]; 861 if (b) { 862 if (c) { 863 array[0] = 5; 864 } else { 865 array[0] = 6; 866 } 867 } else { /* Default value: 0. */ } 868 return array[0]; 869 } 870 871 /// CHECK-START: float Main.test29(boolean) load_store_elimination (before) 872 /// CHECK-DAG: <<Float2:f\d+>> FloatConstant 2 873 /// CHECK-DAG: <<Float5:f\d+>> FloatConstant 5 874 /// CHECK-DAG: <<Float8:f\d+>> FloatConstant 8 875 /// CHECK-DAG: <<Obj:l\d+>> NewInstance 876 /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Float8>>] 877 /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Float2>>] 878 /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Float5>>] 879 /// CHECK-DAG: <<GetField:f\d+>> InstanceFieldGet [<<Obj>>] 880 /// CHECK-DAG: Return [<<GetField>>] 881 882 /// CHECK-START: float Main.test29(boolean) load_store_elimination (after) 883 /// CHECK-DAG: <<Float2:f\d+>> FloatConstant 2 884 /// CHECK-DAG: <<Float5:f\d+>> FloatConstant 5 885 /// CHECK-DAG: <<Float8:f\d+>> FloatConstant 8 886 /// CHECK-DAG: <<Phi:f\d+>> Phi [<<Arg1:f\d+>>,<<Arg2:f\d+>>] 887 /// CHECK-DAG: Return [<<Phi>>] 888 /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>"]) == set(["<<Float5>>","<<Float2>>"]) 889 890 /// CHECK-START: float Main.test29(boolean) load_store_elimination (after) 891 /// CHECK-NOT: NewInstance 892 /// CHECK-NOT: InstanceFieldSet 893 /// CHECK-NOT: InstanceFieldGet 894 895 // Test implicit type conversion in branches. test29(boolean b)896 static float test29(boolean b) { 897 TestClass3 obj = new TestClass3(); 898 if (b) { 899 obj.floatField = 5; // Int 900 } else { 901 obj.floatField = 2L; // Long 902 } 903 return obj.floatField; 904 } 905 906 /// CHECK-START: int Main.test30(TestClass, boolean) load_store_elimination (before) 907 /// CHECK-DAG: <<Int1:i\d+>> IntConstant 1 908 /// CHECK-DAG: <<Int2:i\d+>> IntConstant 2 909 /// CHECK-DAG: InstanceFieldSet [{{l\d+}},<<Int1>>] 910 /// CHECK-DAG: InstanceFieldSet [{{l\d+}},<<Int2>>] 911 /// CHECK-DAG: <<GetField:i\d+>> InstanceFieldGet [{{l\d+}}] 912 /// CHECK-DAG: Return [<<GetField>>] 913 914 /// CHECK-START: int Main.test30(TestClass, boolean) load_store_elimination (after) 915 /// CHECK-DAG: <<Int1:i\d+>> IntConstant 1 916 /// CHECK-DAG: <<Int2:i\d+>> IntConstant 2 917 /// CHECK-DAG: InstanceFieldSet [{{l\d+}},<<Int1>>] 918 /// CHECK-DAG: InstanceFieldSet [{{l\d+}},<<Int2>>] 919 /// CHECK-DAG: <<GetField:i\d+>> InstanceFieldGet [{{l\d+}}] 920 /// CHECK-DAG: Return [<<GetField>>] 921 922 /// CHECK-START: int Main.test30(TestClass, boolean) load_store_elimination (after) 923 /// CHECK-NOT: Phi 924 925 // Don't merge different values in two branches for different variables. test30(TestClass obj, boolean b)926 static int test30(TestClass obj, boolean b) { 927 if (b) { 928 obj.i = 1; 929 } else { 930 obj.j = 2; 931 } 932 return obj.i; 933 } 934 935 /// CHECK-START: int Main.test31(boolean, boolean) load_store_elimination (before) 936 /// CHECK-DAG: <<Int2:i\d+>> IntConstant 2 937 /// CHECK-DAG: <<Int5:i\d+>> IntConstant 5 938 /// CHECK-DAG: <<Int6:i\d+>> IntConstant 6 939 /// CHECK-DAG: InstanceFieldSet [{{l\d+}},<<Int5>>] field_name:{{.*TestClass.i}} 940 /// CHECK-DAG: InstanceFieldSet [{{l\d+}},<<Int6>>] field_name:{{.*TestClass.i}} 941 /// CHECK-DAG: <<Get1:i\d+>> InstanceFieldGet [{{l\d+}}] field_name:{{.*TestClass.i}} 942 /// CHECK-DAG: InstanceFieldSet [{{l\d+}},<<Get1>>] field_name:{{.*TestClass.j}} 943 /// CHECK-DAG: InstanceFieldSet [{{l\d+}},<<Int2>>] field_name:{{.*TestClass.i}} 944 /// CHECK-DAG: <<Get2:i\d+>> InstanceFieldGet [{{l\d+}}] 945 /// CHECK-DAG: Return [<<Get2>>] 946 947 /// CHECK-START: int Main.test31(boolean, boolean) load_store_elimination (after) 948 /// CHECK-DAG: <<Int2:i\d+>> IntConstant 2 949 /// CHECK-DAG: <<Int5:i\d+>> IntConstant 5 950 /// CHECK-DAG: <<Int6:i\d+>> IntConstant 6 951 /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Int5>>,<<Int6>>] 952 /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Phi1>>,<<Int2>>] 953 /// CHECK-DAG: Return [<<Phi2>>] 954 955 /// CHECK-START: int Main.test31(boolean, boolean) load_store_elimination (after) 956 /// CHECK-NOT: NewInstance 957 /// CHECK-NOT: InstanceFieldSet 958 /// CHECK-NOT: InstanceFieldGet 959 960 // Test nested branches that can't be flattened. test31(boolean b, boolean c)961 static int test31(boolean b, boolean c) { 962 TestClass obj = new TestClass(); 963 if (b) { 964 if (c) { 965 obj.i = 5; 966 } else { 967 obj.i = 6; 968 } 969 obj.j = obj.i; 970 } else { 971 obj.i = 2; 972 } 973 return obj.i; 974 } 975 976 /// CHECK-START: int Main.test32(int) load_store_elimination (before) 977 /// CHECK-DAG: <<Int1:i\d+>> IntConstant 1 978 /// CHECK-DAG: <<Int10:i\d+>> IntConstant 10 979 /// CHECK-DAG: InstanceFieldSet [{{l\d+}},<<Int1>>] field_name:{{.*TestClass2.i}} 980 /// CHECK-DAG: InstanceFieldSet [{{l\d+}},<<Int1>>] field_name:{{.*TestClass2.j}} 981 /// CHECK-DAG: InstanceFieldSet [{{l\d+}},<<Int1>>] field_name:{{.*TestClass2.k}} 982 /// CHECK-DAG: InstanceFieldSet [{{l\d+}},<<Int1>>] field_name:{{.*TestClass2.l}} 983 /// CHECK-DAG: InstanceFieldSet [{{l\d+}},<<Int1>>] field_name:{{.*TestClass2.m}} 984 /// CHECK-DAG: Return [<<Int10>>] 985 986 /// CHECK-START: int Main.test32(int) load_store_elimination (after) 987 /// CHECK-DAG: <<Int10:i\d+>> IntConstant 10 988 /// CHECK-DAG: Return [<<Int10>>] 989 990 /// CHECK-START: int Main.test32(int) load_store_elimination (after) 991 /// CHECK-NOT: NewInstance 992 /// CHECK-NOT: InstanceFieldGet 993 /// CHECK-NOT: InstanceFieldSet 994 /// CHECK-NOT: Phi 995 996 // Test no unused Phi instructions are created. test32(int i)997 static int test32(int i) { 998 TestClass2 obj = new TestClass2(); 999 // By default, i/j/k/l/m are initialized to 0. 1000 switch (i) { 1001 case 1: obj.i = 1; break; 1002 case 2: obj.j = 1; break; 1003 case 3: obj.k = 1; break; 1004 case 4: obj.l = 1; break; 1005 case 5: obj.m = 1; break; 1006 } 1007 // So here, each variable has value Phi [0,1,1,1,1,1]. 1008 // But since no heap values are used, we should not be creating these Phis. 1009 return 10; 1010 } 1011 1012 /// CHECK-START: int Main.test33(TestClass, boolean) load_store_elimination (before) 1013 /// CHECK-DAG: InstanceFieldSet 1014 /// CHECK-DAG: InstanceFieldSet 1015 /// CHECK-DAG: <<Phi:i\d+>> Phi 1016 /// CHECK-DAG: InstanceFieldSet [{{l\d+}},<<Phi>>] 1017 1018 /// CHECK-START: int Main.test33(TestClass, boolean) load_store_elimination (after) 1019 /// CHECK-DAG: InstanceFieldSet 1020 /// CHECK-DAG: InstanceFieldSet 1021 /// CHECK-DAG: <<Phi:i\d+>> Phi 1022 1023 /// CHECK-START: int Main.test33(TestClass, boolean) load_store_elimination (after) 1024 /// CHECK: InstanceFieldSet 1025 /// CHECK: InstanceFieldSet 1026 /// CHECK-NOT: InstanceFieldSet 1027 1028 // Test that we are not eliminating the if/else sets to `obj.i`. We have `NullCheck`s on `obj` 1029 // when doing `obj.i`. Since `NullCheck` can throw, we save the stores. 1030 // The 3rd `obj.i` set is redundant and can be eliminated. It will have the same value and it is 1031 // not needed. test33(TestClass obj, boolean x)1032 static int test33(TestClass obj, boolean x) { 1033 int phi; 1034 if (x) { 1035 obj.i = 1; 1036 phi = 1; 1037 } else { 1038 obj.i = 2; 1039 phi = 2; 1040 } 1041 obj.i = phi; 1042 return phi; 1043 } 1044 1045 /// CHECK-START: int Main.test34(TestClass, boolean, boolean) load_store_elimination (before) 1046 /// CHECK-DAG: InstanceFieldSet 1047 /// CHECK-DAG: InstanceFieldSet 1048 /// CHECK-DAG: <<Phi:i\d+>> Phi 1049 /// CHECK-DAG: InstanceFieldSet [{{l\d+}},<<Phi>>] 1050 1051 /// CHECK-START: int Main.test34(TestClass, boolean, boolean) load_store_elimination (after) 1052 /// CHECK-DAG: InstanceFieldSet 1053 /// CHECK-DAG: InstanceFieldSet 1054 /// CHECK-DAG: Phi 1055 1056 /// CHECK-START: int Main.test34(TestClass, boolean, boolean) load_store_elimination (after) 1057 /// CHECK: InstanceFieldSet 1058 /// CHECK: InstanceFieldSet 1059 /// CHECK-NOT: InstanceFieldSet 1060 1061 // Test eliminating a store that writes a Phi equivalent to merged 1062 // heap values of observable stores. test34(TestClass obj, boolean x, boolean y)1063 static int test34(TestClass obj, boolean x, boolean y) { 1064 int phi; 1065 if (x) { 1066 obj.i = 1; 1067 phi = 1; 1068 if (y) { 1069 return 3; 1070 } 1071 } else { 1072 obj.i = 2; 1073 phi = 2; 1074 if (y) { 1075 return 4; 1076 } 1077 } 1078 obj.i = phi; 1079 return phi; 1080 } 1081 1082 /// CHECK-START: int Main.test35(TestClass, boolean, boolean) load_store_elimination (before) 1083 /// CHECK-DAG: InstanceFieldSet 1084 /// CHECK-DAG: InstanceFieldSet 1085 /// CHECK-DAG: InstanceFieldSet 1086 /// CHECK-DAG: InstanceFieldSet 1087 /// CHECK-DAG: InstanceFieldGet 1088 1089 /// CHECK-START: int Main.test35(TestClass, boolean, boolean) load_store_elimination (after) 1090 /// CHECK-DAG: InstanceFieldSet 1091 /// CHECK-DAG: InstanceFieldSet 1092 /// CHECK-DAG: InstanceFieldSet 1093 /// CHECK-DAG: InstanceFieldSet 1094 /// CHECK-DAG: Phi 1095 /// CHECK-DAG: Phi 1096 /// CHECK-DAG: Phi 1097 1098 /// CHECK-START: int Main.test35(TestClass, boolean, boolean) load_store_elimination (after) 1099 /// CHECK-NOT: InstanceFieldGet 1100 1101 // Test Phi creation for load elimination. test35(TestClass obj, boolean x, boolean y)1102 static int test35(TestClass obj, boolean x, boolean y) { 1103 if (x) { 1104 obj.i = 1; 1105 } else { 1106 obj.i = 2; 1107 } 1108 if (y) { 1109 if (x) { 1110 obj.i = 3; 1111 } 1112 obj.j = 5; 1113 } 1114 return obj.i; 1115 } 1116 1117 /// CHECK-START: int Main.test36(TestClass, boolean) load_store_elimination (before) 1118 /// CHECK-DAG: InstanceFieldSet 1119 /// CHECK-DAG: InstanceFieldSet 1120 /// CHECK-DAG: Phi 1121 /// CHECK-DAG: InstanceFieldGet 1122 1123 /// CHECK-START: int Main.test36(TestClass, boolean) load_store_elimination (after) 1124 /// CHECK-DAG: InstanceFieldSet 1125 /// CHECK-DAG: InstanceFieldSet 1126 /// CHECK-DAG: Phi 1127 1128 /// CHECK-START: int Main.test36(TestClass, boolean) load_store_elimination (after) 1129 /// CHECK-NOT: InstanceFieldGet 1130 1131 /// CHECK-START: int Main.test36(TestClass, boolean) load_store_elimination (after) 1132 /// CHECK: Phi 1133 /// CHECK-NOT: Phi 1134 1135 // Test Phi matching for load elimination. test36(TestClass obj, boolean x)1136 static int test36(TestClass obj, boolean x) { 1137 int phi; 1138 if (x) { 1139 obj.i = 1; 1140 phi = 1; 1141 } else { 1142 obj.i = 2; 1143 phi = 2; 1144 } 1145 // The load is replaced by the existing Phi instead of constructing a new one. 1146 return obj.i + phi; 1147 } 1148 1149 /// CHECK-START: int Main.test37(TestClass, boolean) load_store_elimination (before) 1150 /// CHECK-DAG: InstanceFieldSet 1151 /// CHECK-DAG: InstanceFieldGet 1152 /// CHECK-DAG: InstanceFieldSet 1153 1154 /// CHECK-START: int Main.test37(TestClass, boolean) load_store_elimination (after) 1155 /// CHECK-DAG: InstanceFieldSet 1156 /// CHECK-DAG: InstanceFieldGet 1157 /// CHECK-DAG: InstanceFieldSet 1158 1159 // Test preserving observable stores. test37(TestClass obj, boolean x)1160 static int test37(TestClass obj, boolean x) { 1161 if (x) { 1162 obj.i = 1; 1163 } 1164 int tmp = obj.i; // The store above must be kept. 1165 obj.i = 2; 1166 return tmp; 1167 } 1168 1169 /// CHECK-START: int Main.test38(TestClass, boolean) load_store_elimination (before) 1170 /// CHECK-DAG: InstanceFieldSet 1171 /// CHECK-DAG: InstanceFieldSet 1172 /// CHECK-DAG: InstanceFieldSet 1173 /// CHECK-DAG: InstanceFieldSet 1174 1175 /// CHECK-START: int Main.test38(TestClass, boolean) load_store_elimination (after) 1176 /// CHECK: InstanceFieldSet 1177 /// CHECK-NOT: InstanceFieldSet 1178 1179 // Test eliminating store of the same value after eliminating non-observable stores. test38(TestClass obj, boolean x)1180 static int test38(TestClass obj, boolean x) { 1181 obj.i = 1; 1182 if (x) { 1183 return 1; // The store above must be kept. 1184 } 1185 obj.i = 2; // Not observable, shall be eliminated. 1186 obj.i = 3; // Not observable, shall be eliminated. 1187 obj.i = 1; // After eliminating the non-observable stores above, this stores the 1188 // same value that is already stored in `obj.i` and shall be eliminated. 1189 return 2; 1190 } 1191 1192 /// CHECK-START: int Main.test39(TestClass, boolean) load_store_elimination (before) 1193 /// CHECK-DAG: NewInstance 1194 /// CHECK-DAG: InstanceFieldSet 1195 /// CHECK-DAG: NewInstance 1196 /// CHECK-DAG: InstanceFieldSet 1197 /// CHECK-DAG: InstanceFieldGet 1198 /// CHECK-DAG: InstanceFieldGet 1199 1200 /// CHECK-START: int Main.test39(TestClass, boolean) load_store_elimination (after) 1201 /// CHECK-DAG: NewInstance 1202 /// CHECK-DAG: InstanceFieldSet 1203 /// CHECK-DAG: NewInstance 1204 /// CHECK-DAG: InstanceFieldSet 1205 /// CHECK-DAG: Phi 1206 /// CHECK-DAG: InstanceFieldGet 1207 1208 /// CHECK-START: int Main.test39(TestClass, boolean) load_store_elimination (after) 1209 /// CHECK: InstanceFieldGet 1210 /// CHECK-NOT: InstanceFieldGet 1211 1212 // Test creating a reference Phi for load elimination. test39(TestClass obj, boolean x)1213 static int test39(TestClass obj, boolean x) { 1214 obj.next = new TestClass(1, 2); 1215 if (x) { 1216 obj.next = new SubTestClass(); 1217 } 1218 return obj.next.i; 1219 } 1220 test40()1221 private static int test40() { 1222 int[] array = new int[1]; 1223 try { 1224 $noinline$fillArrayTest40(array, 100, 0); 1225 System.out.println("UNREACHABLE"); 1226 } catch (Throwable expected) { 1227 } 1228 assertIntEquals(array[0], 1); 1229 try { 1230 $noinline$fillArrayTest40(array, 100, 1); 1231 System.out.println("UNREACHABLE"); 1232 } catch (Throwable expected) { 1233 } 1234 assertIntEquals(array[0], 2); 1235 $noinline$fillArrayTest40(array, 100, 2); 1236 assertIntEquals(array[0], 150); 1237 return array[0]; 1238 } 1239 1240 /// CHECK-START: void Main.$noinline$fillArrayTest40(int[], int, int) load_store_elimination (before) 1241 /// CHECK: ArraySet 1242 /// CHECK: DivZeroCheck 1243 /// CHECK: ArraySet 1244 /// CHECK: DivZeroCheck 1245 /// CHECK: ArraySet 1246 1247 /// CHECK-START: void Main.$noinline$fillArrayTest40(int[], int, int) load_store_elimination (after) 1248 /// CHECK: ArraySet 1249 /// CHECK: DivZeroCheck 1250 /// CHECK: ArraySet 1251 /// CHECK: DivZeroCheck 1252 /// CHECK: ArraySet 1253 1254 // Check that the stores to array[0] are not eliminated since we can throw in between the stores. $noinline$fillArrayTest40(int[] array, int a, int b)1255 private static void $noinline$fillArrayTest40(int[] array, int a, int b) { 1256 array[0] = 1; 1257 int x = a / b; 1258 array[0] = 2; 1259 int y = a / (b - 1); 1260 array[0] = x + y; 1261 } 1262 1263 /// CHECK-START: int Main.$noinline$testConversion1(TestClass, int) load_store_elimination (before) 1264 /// CHECK-DAG: InstanceFieldSet 1265 /// CHECK-DAG: InstanceFieldSet 1266 /// CHECK-DAG: InstanceFieldGet 1267 /// CHECK-DAG: InstanceFieldSet 1268 /// CHECK-DAG: InstanceFieldGet 1269 1270 /// CHECK-START: int Main.$noinline$testConversion1(TestClass, int) load_store_elimination (after) 1271 /// CHECK-DAG: InstanceFieldSet 1272 /// CHECK-DAG: InstanceFieldSet 1273 /// CHECK-DAG: TypeConversion 1274 /// CHECK-DAG: InstanceFieldSet 1275 /// CHECK-DAG: Phi 1276 1277 /// CHECK-START: int Main.$noinline$testConversion1(TestClass, int) load_store_elimination (after) 1278 /// CHECK: Phi 1279 /// CHECK-NOT: Phi 1280 1281 // Test tracking values containing type conversion. 1282 // Regression test for b/161521389 . $noinline$testConversion1(TestClass obj, int x)1283 static int $noinline$testConversion1(TestClass obj, int x) { 1284 obj.i = x; 1285 if ((x & 1) != 0) { 1286 obj.b = (byte) x; 1287 obj.i = obj.b; 1288 } 1289 return obj.i; 1290 } 1291 1292 /// CHECK-START: int Main.$noinline$testConversion2(TestClass, int) load_store_elimination (before) 1293 /// CHECK-DAG: InstanceFieldSet 1294 /// CHECK-DAG: InstanceFieldSet 1295 /// CHECK-DAG: InstanceFieldGet 1296 /// CHECK-DAG: InstanceFieldSet 1297 /// CHECK-DAG: TypeConversion 1298 /// CHECK-DAG: Phi 1299 /// CHECK-DAG: InstanceFieldGet 1300 1301 /// CHECK-START: int Main.$noinline$testConversion2(TestClass, int) load_store_elimination (after) 1302 /// CHECK-DAG: InstanceFieldSet 1303 /// CHECK-DAG: InstanceFieldSet 1304 /// CHECK-DAG: TypeConversion 1305 /// CHECK-DAG: InstanceFieldSet 1306 /// CHECK-DAG: Phi 1307 /// CHECK-DAG: Phi 1308 1309 /// CHECK-START: int Main.$noinline$testConversion2(TestClass, int) load_store_elimination (after) 1310 /// CHECK: Phi 1311 /// CHECK: Phi 1312 /// CHECK-NOT: Phi 1313 1314 /// CHECK-START: int Main.$noinline$testConversion2(TestClass, int) load_store_elimination (after) 1315 /// CHECK: TypeConversion 1316 /// CHECK-NOT: TypeConversion 1317 1318 /// CHECK-START: int Main.$noinline$testConversion2(TestClass, int) load_store_elimination (after) 1319 /// CHECK-NOT: InstanceFieldGet 1320 1321 // Test moving type conversion when needed. $noinline$testConversion2(TestClass obj, int x)1322 static int $noinline$testConversion2(TestClass obj, int x) { 1323 int tmp = 0; 1324 obj.i = x; 1325 if ((x & 1) != 0) { 1326 // The instruction simplifier can remove this TypeConversion if there are 1327 // no environment uses. Currently, there is an environment use in NullCheck, 1328 // so this TypeConversion remains and GVN removes the second TypeConversion 1329 // below. Since we really want to test that the TypeConversion from below 1330 // can be moved and used for the load of `obj.b`, we have a similar test 1331 // written in smali in 530-checker-lse3, StoreLoad.test3(int), except that 1332 // it's using static fields (which would not help with the environment use). 1333 obj.b = (byte) x; 1334 obj.i = obj.b; 1335 tmp = (byte) x; 1336 } 1337 return obj.i + tmp; 1338 } 1339 1340 /// CHECK-START: int Main.$noinline$testConversion3(TestClass, int) load_store_elimination (before) 1341 /// CHECK-DAG: InstanceFieldSet 1342 /// CHECK-DAG: Phi 1343 /// CHECK-DAG: InstanceFieldSet 1344 /// CHECK-DAG: InstanceFieldGet 1345 /// CHECK-DAG: InstanceFieldSet 1346 /// CHECK-DAG: InstanceFieldGet 1347 1348 /// CHECK-START: int Main.$noinline$testConversion3(TestClass, int) load_store_elimination (after) 1349 /// CHECK-DAG: InstanceFieldSet 1350 /// CHECK-DAG: Phi 1351 /// CHECK-DAG: Phi 1352 /// CHECK-DAG: InstanceFieldSet 1353 /// CHECK-DAG: TypeConversion 1354 /// CHECK-DAG: InstanceFieldSet 1355 1356 /// CHECK-START: int Main.$noinline$testConversion3(TestClass, int) load_store_elimination (after) 1357 /// CHECK: Phi 1358 /// CHECK: Phi 1359 /// CHECK-NOT: Phi 1360 1361 /// CHECK-START: int Main.$noinline$testConversion3(TestClass, int) load_store_elimination (after) 1362 /// CHECK: TypeConversion 1363 /// CHECK-NOT: TypeConversion 1364 1365 /// CHECK-START: int Main.$noinline$testConversion3(TestClass, int) load_store_elimination (after) 1366 /// CHECK-NOT: InstanceFieldGet 1367 1368 // Test tracking values containing type conversion with loop. $noinline$testConversion3(TestClass obj, int x)1369 static int $noinline$testConversion3(TestClass obj, int x) { 1370 obj.i = x; 1371 for (int i = 0; i < x; ++i) { 1372 obj.b = (byte) i; 1373 obj.i = obj.b; 1374 } 1375 return obj.i; 1376 } 1377 1378 /// CHECK-START: int Main.$noinline$testConversion4(TestClass, int) load_store_elimination (before) 1379 /// CHECK-DAG: InstanceFieldSet 1380 /// CHECK-DAG: Phi 1381 /// CHECK-DAG: Phi 1382 /// CHECK-DAG: InstanceFieldSet 1383 /// CHECK-DAG: InstanceFieldGet 1384 /// CHECK-DAG: InstanceFieldSet 1385 /// CHECK-DAG: TypeConversion 1386 /// CHECK-DAG: InstanceFieldGet 1387 1388 /// CHECK-START: int Main.$noinline$testConversion4(TestClass, int) load_store_elimination (after) 1389 /// CHECK-DAG: InstanceFieldSet 1390 /// CHECK-DAG: Phi 1391 /// CHECK-DAG: Phi 1392 /// CHECK-DAG: InstanceFieldSet 1393 /// CHECK-DAG: TypeConversion 1394 /// CHECK-DAG: InstanceFieldSet 1395 1396 /// CHECK-START: int Main.$noinline$testConversion4(TestClass, int) load_store_elimination (after) 1397 /// CHECK: Phi 1398 /// CHECK: Phi 1399 /// CHECK-NOT: Phi 1400 1401 /// CHECK-START: int Main.$noinline$testConversion4(TestClass, int) load_store_elimination (after) 1402 /// CHECK: TypeConversion 1403 /// CHECK-NOT: TypeConversion 1404 1405 /// CHECK-START: int Main.$noinline$testConversion4(TestClass, int) load_store_elimination (after) 1406 /// CHECK-NOT: InstanceFieldGet 1407 1408 // Test moving type conversion when needed with loop. $noinline$testConversion4(TestClass obj, int x)1409 static int $noinline$testConversion4(TestClass obj, int x) { 1410 int tmp = x; 1411 obj.i = x; 1412 for (int i = 0; i < x; ++i) { 1413 obj.b = (byte) i; 1414 obj.i = obj.b; 1415 tmp = (byte) i; 1416 } 1417 return obj.i + tmp; 1418 } 1419 1420 /// CHECK-START: void Main.testFinalizable() load_store_elimination (before) 1421 /// CHECK: NewInstance 1422 /// CHECK: InstanceFieldSet 1423 /// CHECK: InstanceFieldSet 1424 1425 /// CHECK-START: void Main.testFinalizable() load_store_elimination (after) 1426 /// CHECK: NewInstance 1427 /// CHECK: InstanceFieldSet 1428 /// CHECK-NOT: InstanceFieldSet 1429 1430 // Allocations of finalizable objects cannot be eliminated. testFinalizable()1431 static void testFinalizable() { 1432 Finalizable finalizable = new Finalizable(); 1433 finalizable.i = Finalizable.VALUE2; 1434 finalizable.i = Finalizable.VALUE1; 1435 } 1436 getWeakReference()1437 static java.lang.ref.WeakReference<Object> getWeakReference() { 1438 return new java.lang.ref.WeakReference<>(new Object()); 1439 } 1440 testFinalizableByForcingGc()1441 static void testFinalizableByForcingGc() { 1442 testFinalizable(); 1443 java.lang.ref.WeakReference<Object> reference = getWeakReference(); 1444 1445 Runtime runtime = Runtime.getRuntime(); 1446 for (int i = 0; i < 20; ++i) { 1447 runtime.gc(); 1448 System.runFinalization(); 1449 try { 1450 Thread.sleep(1); 1451 } catch (InterruptedException e) { 1452 throw new AssertionError(e); 1453 } 1454 1455 // Check to see if the weak reference has been garbage collected. 1456 if (reference.get() == null) { 1457 // A little bit more sleep time to make sure. 1458 try { 1459 Thread.sleep(100); 1460 } catch (InterruptedException e) { 1461 throw new AssertionError(e); 1462 } 1463 if (!Finalizable.sVisited) { 1464 System.out.println("finalize() not called."); 1465 } 1466 return; 1467 } 1468 } 1469 System.out.println("testFinalizableByForcingGc() failed to force gc."); 1470 } 1471 1472 /// CHECK-START: void Main.testFinalizable() load_store_elimination (before) 1473 /// CHECK: NewInstance 1474 /// CHECK: InstanceFieldSet 1475 /// CHECK: InstanceFieldSet 1476 1477 /// CHECK-START: void Main.testFinalizableWithLoop() load_store_elimination (after) 1478 /// CHECK: NewInstance 1479 /// CHECK: InstanceFieldSet 1480 /// CHECK-NOT: InstanceFieldSet 1481 1482 // Allocations of finalizable objects cannot be eliminated. testFinalizableWithLoop()1483 static void testFinalizableWithLoop() { 1484 for (int i = 0; i < 1000; ++i) { 1485 Finalizable finalizable = new Finalizable(); 1486 finalizable.i = Finalizable.VALUE2; 1487 finalizable.i = Finalizable.VALUE1; 1488 } 1489 } 1490 testFinalizableWithLoopByForcingGc()1491 static void testFinalizableWithLoopByForcingGc() { 1492 testFinalizableWithLoop(); 1493 java.lang.ref.WeakReference<Object> reference = getWeakReference(); 1494 1495 Runtime runtime = Runtime.getRuntime(); 1496 for (int i = 0; i < 20; ++i) { 1497 runtime.gc(); 1498 System.runFinalization(); 1499 try { 1500 Thread.sleep(1); 1501 } catch (InterruptedException e) { 1502 throw new AssertionError(e); 1503 } 1504 1505 // Check to see if the weak reference has been garbage collected. 1506 if (reference.get() == null) { 1507 // A little bit more sleep time to make sure. 1508 try { 1509 Thread.sleep(100); 1510 } catch (InterruptedException e) { 1511 throw new AssertionError(e); 1512 } 1513 if (!Finalizable.sVisited) { 1514 System.out.println("finalize() not called."); 1515 } 1516 return; 1517 } 1518 } 1519 System.out.println("testFinalizableWithLoopByForcingGc() failed to force gc."); 1520 } 1521 1522 /// CHECK-START: int Main.$noinline$testHSelect(boolean) load_store_elimination (before) 1523 /// CHECK: InstanceFieldSet 1524 /// CHECK: Select 1525 1526 /// CHECK-START: int Main.$noinline$testHSelect(boolean) load_store_elimination (after) 1527 /// CHECK: InstanceFieldSet 1528 /// CHECK: Select 1529 1530 // Test that HSelect creates alias. $noinline$testHSelect(boolean b)1531 static int $noinline$testHSelect(boolean b) { 1532 TestClass obj = new TestClass(); 1533 TestClass obj2 = null; 1534 obj.i = 0xdead; 1535 if (b) { 1536 obj2 = obj; 1537 } 1538 return obj2.i; 1539 } 1540 sumWithFilter(int[] array, Filter f)1541 static int sumWithFilter(int[] array, Filter f) { 1542 int sum = 0; 1543 for (int i = 0; i < array.length; i++) { 1544 if (f.isValid(array[i])) { 1545 sum += array[i]; 1546 } 1547 } 1548 return sum; 1549 } 1550 1551 /// CHECK-START: int Main.sumWithinRange(int[], int, int) load_store_elimination (before) 1552 /// CHECK-DAG: NewInstance 1553 /// CHECK-DAG: InstanceFieldSet 1554 /// CHECK-DAG: InstanceFieldSet 1555 /// CHECK-DAG: InstanceFieldGet 1556 /// CHECK-DAG: InstanceFieldGet 1557 1558 /// CHECK-START: int Main.sumWithinRange(int[], int, int) load_store_elimination (after) 1559 /// CHECK-NOT: NewInstance 1560 /// CHECK-NOT: InstanceFieldSet 1561 /// CHECK-NOT: InstanceFieldGet 1562 1563 // A lambda-style allocation can be eliminated after inlining. sumWithinRange(int[] array, final int low, final int high)1564 static int sumWithinRange(int[] array, final int low, final int high) { 1565 Filter filter = new Filter() { 1566 public boolean isValid(int i) { 1567 return (i >= low) && (i <= high); 1568 } 1569 }; 1570 return sumWithFilter(array, filter); 1571 } 1572 1573 private static int mI = 0; 1574 private static float mF = 0f; 1575 1576 /// CHECK-START: float Main.testAllocationEliminationWithLoops() load_store_elimination (before) 1577 /// CHECK: NewInstance 1578 /// CHECK: NewInstance 1579 /// CHECK: NewInstance 1580 1581 /// CHECK-START: float Main.testAllocationEliminationWithLoops() load_store_elimination (after) 1582 /// CHECK-NOT: NewInstance 1583 testAllocationEliminationWithLoops()1584 private static float testAllocationEliminationWithLoops() { 1585 for (int i0 = 0; i0 < 5; i0++) { 1586 for (int i1 = 0; i1 < 5; i1++) { 1587 for (int i2 = 0; i2 < 5; i2++) { 1588 int lI0 = ((int) new Integer(((int) new Integer(mI)))); 1589 if (((boolean) new Boolean(false))) { 1590 for (int i3 = 576 - 1; i3 >= 0; i3--) { 1591 mF -= 976981405.0f; 1592 } 1593 } 1594 } 1595 } 1596 } 1597 return 1.0f; 1598 } 1599 1600 /// CHECK-START: TestClass2 Main.testStoreStore() load_store_elimination (before) 1601 /// CHECK: NewInstance 1602 /// CHECK: InstanceFieldSet 1603 /// CHECK: InstanceFieldSet 1604 /// CHECK: InstanceFieldSet 1605 /// CHECK: InstanceFieldSet 1606 1607 /// CHECK-START: TestClass2 Main.testStoreStore() load_store_elimination (after) 1608 /// CHECK: NewInstance 1609 /// CHECK: InstanceFieldSet 1610 /// CHECK: InstanceFieldSet 1611 /// CHECK-NOT: InstanceFieldSet 1612 testStoreStore()1613 private static TestClass2 testStoreStore() { 1614 TestClass2 obj = new TestClass2(); 1615 obj.i = 41; 1616 obj.j = 42; 1617 obj.i = 41; 1618 obj.j = 43; 1619 return obj; 1620 } 1621 1622 /// CHECK-START: void Main.testStoreStore2(TestClass2) load_store_elimination (before) 1623 /// CHECK: InstanceFieldSet 1624 /// CHECK: InstanceFieldSet 1625 /// CHECK: InstanceFieldSet 1626 /// CHECK: InstanceFieldSet 1627 1628 /// CHECK-START: void Main.testStoreStore2(TestClass2) load_store_elimination (after) 1629 /// CHECK: InstanceFieldSet 1630 /// CHECK: InstanceFieldSet 1631 /// CHECK-NOT: InstanceFieldSet 1632 testStoreStore2(TestClass2 obj)1633 private static void testStoreStore2(TestClass2 obj) { 1634 obj.i = 41; 1635 obj.j = 42; 1636 obj.i = 43; 1637 obj.j = 44; 1638 } 1639 1640 /// CHECK-START: void Main.testStoreStore3(TestClass2, boolean) load_store_elimination (before) 1641 /// CHECK: InstanceFieldSet 1642 /// CHECK: InstanceFieldSet 1643 /// CHECK: InstanceFieldSet 1644 /// CHECK: InstanceFieldSet 1645 1646 /// CHECK-START: void Main.testStoreStore3(TestClass2, boolean) load_store_elimination (after) 1647 /// CHECK: InstanceFieldSet 1648 /// CHECK: InstanceFieldSet 1649 /// CHECK: InstanceFieldSet 1650 /// CHECK-NOT: InstanceFieldSet 1651 1652 /// CHECK-START: void Main.testStoreStore3(TestClass2, boolean) load_store_elimination (after) 1653 /// CHECK-NOT: Phi 1654 testStoreStore3(TestClass2 obj, boolean flag)1655 private static void testStoreStore3(TestClass2 obj, boolean flag) { 1656 obj.i = 41; 1657 obj.j = 42; // redundant since it's overwritten in both branches below. 1658 if (flag) { 1659 obj.j = 43; 1660 } else { 1661 obj.j = 44; 1662 } 1663 } 1664 1665 /// CHECK-START: void Main.testStoreStore4() load_store_elimination (before) 1666 /// CHECK: StaticFieldSet 1667 /// CHECK: StaticFieldSet 1668 1669 /// CHECK-START: void Main.testStoreStore4() load_store_elimination (after) 1670 /// CHECK: StaticFieldSet 1671 /// CHECK-NOT: StaticFieldSet 1672 testStoreStore4()1673 private static void testStoreStore4() { 1674 TestClass.si = 61; 1675 TestClass.si = 62; 1676 } 1677 1678 /// CHECK-START: int Main.testStoreStore5(TestClass2, TestClass2) load_store_elimination (before) 1679 /// CHECK: InstanceFieldSet 1680 /// CHECK: InstanceFieldGet 1681 /// CHECK: InstanceFieldSet 1682 1683 /// CHECK-START: int Main.testStoreStore5(TestClass2, TestClass2) load_store_elimination (after) 1684 /// CHECK: InstanceFieldSet 1685 /// CHECK: InstanceFieldGet 1686 /// CHECK: InstanceFieldSet 1687 testStoreStore5(TestClass2 obj1, TestClass2 obj2)1688 private static int testStoreStore5(TestClass2 obj1, TestClass2 obj2) { 1689 obj1.i = 71; // This store is needed since obj2.i may load from it. 1690 int i = obj2.i; 1691 obj1.i = 72; 1692 return i; 1693 } 1694 1695 /// CHECK-START: int Main.testStoreStore6(TestClass2, TestClass2) load_store_elimination (before) 1696 /// CHECK: InstanceFieldSet 1697 /// CHECK: InstanceFieldGet 1698 /// CHECK: InstanceFieldSet 1699 1700 /// CHECK-START: int Main.testStoreStore6(TestClass2, TestClass2) load_store_elimination (after) 1701 /// CHECK: InstanceFieldSet 1702 /// CHECK: InstanceFieldGet 1703 /// CHECK: InstanceFieldSet 1704 testStoreStore6(TestClass2 obj1, TestClass2 obj2)1705 private static int testStoreStore6(TestClass2 obj1, TestClass2 obj2) { 1706 obj1.i = 81; // Even though the value in `obj1.i` will be overridden below, this store is needed 1707 // since obj2.j has a NullCheck and can throw. 1708 int j = obj2.j; 1709 obj1.i = 82; 1710 return j; 1711 } 1712 1713 /// CHECK-START: int Main.testNoSideEffects(int[]) load_store_elimination (before) 1714 /// CHECK: ArraySet 1715 /// CHECK: ArraySet 1716 /// CHECK: ArraySet 1717 /// CHECK: ArrayGet 1718 1719 /// CHECK-START: int Main.testNoSideEffects(int[]) load_store_elimination (after) 1720 /// CHECK: ArraySet 1721 /// CHECK: ArraySet 1722 /// CHECK-NOT: ArraySet 1723 /// CHECK-NOT: ArrayGet 1724 testNoSideEffects(int[] array)1725 private static int testNoSideEffects(int[] array) { 1726 array[0] = 101; 1727 array[1] = 102; 1728 int bitCount = Integer.bitCount(0x3456); 1729 array[1] = 103; 1730 return array[0] + bitCount; 1731 } 1732 1733 /// CHECK-START: void Main.testThrow(TestClass2, java.lang.Exception) load_store_elimination (before) 1734 /// CHECK: InstanceFieldSet 1735 /// CHECK: Throw 1736 1737 /// CHECK-START: void Main.testThrow(TestClass2, java.lang.Exception) load_store_elimination (after) 1738 /// CHECK: InstanceFieldSet 1739 /// CHECK: Throw 1740 1741 // Make sure throw keeps the store. testThrow(TestClass2 obj, Exception e)1742 private static void testThrow(TestClass2 obj, Exception e) throws Exception { 1743 obj.i = 55; 1744 throw e; 1745 } 1746 1747 /// CHECK-START: int Main.testStoreStoreWithDeoptimize(int[]) load_store_elimination (before) 1748 /// CHECK: NewInstance 1749 /// CHECK: InstanceFieldSet 1750 /// CHECK: InstanceFieldSet 1751 /// CHECK: InstanceFieldSet 1752 /// CHECK: InstanceFieldSet 1753 /// CHECK: Deoptimize 1754 /// CHECK: ArraySet 1755 /// CHECK: ArraySet 1756 /// CHECK: ArraySet 1757 /// CHECK: ArraySet 1758 /// CHECK: ArrayGet 1759 /// CHECK: ArrayGet 1760 /// CHECK: ArrayGet 1761 /// CHECK: ArrayGet 1762 1763 /// CHECK-START: int Main.testStoreStoreWithDeoptimize(int[]) load_store_elimination (after) 1764 /// CHECK: NewInstance 1765 /// CHECK: InstanceFieldSet 1766 /// CHECK: InstanceFieldSet 1767 /// CHECK-NOT: InstanceFieldSet 1768 /// CHECK: Deoptimize 1769 /// CHECK: ArraySet 1770 /// CHECK: ArraySet 1771 /// CHECK: ArraySet 1772 /// CHECK: ArraySet 1773 /// CHECK-NOT: ArrayGet 1774 testStoreStoreWithDeoptimize(int[] arr)1775 private static int testStoreStoreWithDeoptimize(int[] arr) { 1776 TestClass2 obj = new TestClass2(); 1777 obj.i = 41; 1778 obj.j = 42; 1779 obj.i = 41; 1780 obj.j = 43; 1781 arr[0] = 1; // One HDeoptimize here. 1782 arr[1] = 1; 1783 arr[2] = 1; 1784 arr[3] = 1; 1785 return arr[0] + arr[1] + arr[2] + arr[3]; 1786 } 1787 1788 /// CHECK-START: double Main.getCircleArea(double, boolean) load_store_elimination (before) 1789 /// CHECK: NewInstance 1790 1791 /// CHECK-START: double Main.getCircleArea(double, boolean) load_store_elimination (after) 1792 /// CHECK-NOT: NewInstance 1793 getCircleArea(double radius, boolean b)1794 private static double getCircleArea(double radius, boolean b) { 1795 double area = 0d; 1796 if (b) { 1797 area = new Circle(radius).getArea(); 1798 } 1799 return area; 1800 } 1801 1802 /// CHECK-START: double Main.testDeoptimize(int[], double[], double) load_store_elimination (before) 1803 /// CHECK: Deoptimize 1804 /// CHECK: NewInstance 1805 /// CHECK: Deoptimize 1806 /// CHECK: NewInstance 1807 1808 /// CHECK-START: double Main.testDeoptimize(int[], double[], double) load_store_elimination (after) 1809 /// CHECK: Deoptimize 1810 /// CHECK: NewInstance 1811 /// CHECK: Deoptimize 1812 /// CHECK-NOT: NewInstance 1813 testDeoptimize(int[] iarr, double[] darr, double radius)1814 private static double testDeoptimize(int[] iarr, double[] darr, double radius) { 1815 iarr[0] = 1; // One HDeoptimize here. Not triggered. 1816 iarr[1] = 1; 1817 Circle circle1 = new Circle(radius); 1818 iarr[2] = 1; 1819 darr[0] = circle1.getRadius(); // One HDeoptimize here, which holds circle1 live. Triggered. 1820 darr[1] = circle1.getRadius(); 1821 darr[2] = circle1.getRadius(); 1822 darr[3] = circle1.getRadius(); 1823 return new Circle(Math.PI).getArea(); 1824 } 1825 1826 /// CHECK-START: int Main.testAllocationEliminationOfArray1() load_store_elimination (before) 1827 /// CHECK: NewArray 1828 /// CHECK: ArraySet 1829 /// CHECK: ArraySet 1830 /// CHECK: ArrayGet 1831 /// CHECK: ArrayGet 1832 /// CHECK: ArrayGet 1833 /// CHECK: ArrayGet 1834 1835 /// CHECK-START: int Main.testAllocationEliminationOfArray1() load_store_elimination (after) 1836 /// CHECK-NOT: NewArray 1837 /// CHECK-NOT: ArraySet 1838 /// CHECK-NOT: ArrayGet testAllocationEliminationOfArray1()1839 private static int testAllocationEliminationOfArray1() { 1840 int[] array = new int[4]; 1841 array[2] = 4; 1842 array[3] = 7; 1843 return array[0] + array[1] + array[2] + array[3]; 1844 } 1845 1846 /// CHECK-START: int Main.testAllocationEliminationOfArray2() load_store_elimination (before) 1847 /// CHECK: NewArray 1848 /// CHECK: ArraySet 1849 /// CHECK: ArraySet 1850 /// CHECK: ArrayGet 1851 1852 /// CHECK-START-{ARM64,X86,X86_64}: int Main.testAllocationEliminationOfArray2() load_store_elimination (after) 1853 /// CHECK-NOT: NewArray 1854 /// CHECK-NOT: ArraySet 1855 /// CHECK-NOT: ArraySet 1856 /// CHECK-NOT: ArrayGet 1857 1858 // The loop optimization doesn't happen in ARM which leads to LSE not being able to optimize this 1859 // case. 1860 /// CHECK-START-ARM: int Main.testAllocationEliminationOfArray2() load_store_elimination (after) 1861 /// CHECK: NewArray 1862 /// CHECK: ArraySet 1863 /// CHECK: ArraySet 1864 /// CHECK: ArrayGet testAllocationEliminationOfArray2()1865 private static int testAllocationEliminationOfArray2() { 1866 // Array can be eliminated because LSE can reduce the array accesses into 1867 // integer constants. 1868 int[] array = new int[3]; 1869 array[1] = 4; 1870 array[2] = 7; 1871 int sum = 0; 1872 for (int e : array) { 1873 sum += e; 1874 } 1875 return sum; 1876 } 1877 1878 /// CHECK-START: int Main.testAllocationEliminationOfArray3(int) load_store_elimination (before) 1879 /// CHECK: NewArray 1880 /// CHECK: ArraySet 1881 /// CHECK: ArrayGet 1882 1883 /// CHECK-START: int Main.testAllocationEliminationOfArray3(int) load_store_elimination (after) 1884 /// CHECK-NOT: NewArray 1885 /// CHECK-NOT: ArraySet 1886 /// CHECK-NOT: ArrayGet testAllocationEliminationOfArray3(int i)1887 private static int testAllocationEliminationOfArray3(int i) { 1888 int[] array = new int[4]; 1889 array[i] = 4; 1890 return array[i]; 1891 } 1892 1893 /// CHECK-START: int Main.testAllocationEliminationOfArray4(int) load_store_elimination (before) 1894 /// CHECK: NewArray 1895 /// CHECK: ArraySet 1896 /// CHECK: ArraySet 1897 /// CHECK: ArrayGet 1898 /// CHECK: ArrayGet 1899 1900 /// CHECK-START: int Main.testAllocationEliminationOfArray4(int) load_store_elimination (after) 1901 /// CHECK: NewArray 1902 /// CHECK: ArraySet 1903 /// CHECK: ArraySet 1904 /// CHECK: ArrayGet 1905 /// CHECK-NOT: ArrayGet testAllocationEliminationOfArray4(int i)1906 private static int testAllocationEliminationOfArray4(int i) { 1907 // Cannot eliminate array allocation due to index aliasing between 1 and i. 1908 int[] array = new int[4]; 1909 array[1] = 2; 1910 array[i] = 4; 1911 return array[1] + array[i]; 1912 } 1913 1914 /// CHECK-START: int Main.testAllocationEliminationOfArray5(int) load_store_elimination (before) 1915 /// CHECK: NewArray 1916 /// CHECK: ArraySet 1917 /// CHECK: ArrayGet 1918 1919 /// CHECK-START: int Main.testAllocationEliminationOfArray5(int) load_store_elimination (after) 1920 /// CHECK: NewArray 1921 /// CHECK-NOT: ArraySet 1922 /// CHECK-NOT: ArrayGet testAllocationEliminationOfArray5(int i)1923 private static int testAllocationEliminationOfArray5(int i) { 1924 // Cannot eliminate array allocation due to unknown i that may 1925 // cause NegativeArraySizeException. 1926 int[] array = new int[i]; 1927 array[1] = 12; 1928 return array[1]; 1929 } 1930 1931 /// CHECK-START: int Main.testAllocationEliminationOfArray6(boolean) load_store_elimination (before) 1932 /// CHECK: NewArray 1933 /// CHECK: ArraySet 1934 /// CHECK: ArraySet 1935 /// CHECK: ArrayGet 1936 1937 /// CHECK-START: int Main.testAllocationEliminationOfArray6(boolean) load_store_elimination (after) 1938 /// CHECK: NewArray 1939 /// CHECK: ArraySet 1940 /// CHECK: ArraySet 1941 /// CHECK: ArrayGet testAllocationEliminationOfArray6(boolean prevent_loop_opt)1942 private static int testAllocationEliminationOfArray6(boolean prevent_loop_opt) { 1943 // Cannot eliminate array allocation since array is accessed with non-constant 1944 // index (only 3 elements to prevent vectorization of the reduction). 1945 int[] array = new int[3]; 1946 array[1] = 4; 1947 array[2] = 7; 1948 int sum = 0; 1949 for (int e : array) { 1950 sum += e; 1951 1952 // Prevent the loop from being optimized away before LSE. This should 1953 // never be false. 1954 if (!prevent_loop_opt) { 1955 return -1; 1956 } 1957 } 1958 return sum; 1959 } 1960 1961 /// CHECK-START: int Main.testExitMerge(boolean) load_store_elimination (before) 1962 /// CHECK-DAG: NewInstance 1963 /// CHECK-DAG: InstanceFieldSet field_name:TestClass.i 1964 /// CHECK-DAG: InstanceFieldGet field_name:TestClass.i 1965 /// CHECK-DAG: Return 1966 /// CHECK-DAG: InstanceFieldSet field_name:TestClass.i 1967 /// CHECK-DAG: Throw 1968 1969 /// CHECK-START: int Main.testExitMerge(boolean) load_store_elimination (after) 1970 /// CHECK-DAG: Return 1971 /// CHECK-DAG: Throw 1972 1973 /// CHECK-START: int Main.testExitMerge(boolean) load_store_elimination (after) 1974 /// CHECK-NOT: InstanceFieldSet field_name:TestClass.i 1975 /// CHECK-NOT: InstanceFieldGet field_name:TestClass.i 1976 1977 /// CHECK-START: int Main.testExitMerge(boolean) load_store_elimination (after) 1978 /// CHECK: NewInstance 1979 /// CHECK-NOT: NewInstance testExitMerge(boolean cond)1980 private static int testExitMerge(boolean cond) { 1981 TestClass obj = new TestClass(); 1982 if (cond) { 1983 obj.i = 1; 1984 return obj.i + 1; 1985 } else { 1986 obj.i = 2; 1987 throw new Error(); // Note: We have a NewInstance here. 1988 } 1989 } 1990 1991 /// CHECK-START: int Main.testExitMerge2(boolean) load_store_elimination (before) 1992 /// CHECK-DAG: NewInstance 1993 /// CHECK-DAG: InstanceFieldSet 1994 /// CHECK-DAG: InstanceFieldGet 1995 /// CHECK-DAG: InstanceFieldSet 1996 /// CHECK-DAG: InstanceFieldGet 1997 1998 /// CHECK-START: int Main.testExitMerge2(boolean) load_store_elimination (after) 1999 /// CHECK-NOT: NewInstance 2000 /// CHECK-NOT: InstanceFieldSet 2001 /// CHECK-NOT: InstanceFieldGet testExitMerge2(boolean cond)2002 private static int testExitMerge2(boolean cond) { 2003 TestClass obj = new TestClass(); 2004 int res; 2005 if (cond) { 2006 obj.i = 1; 2007 res = obj.i + 1; 2008 } else { 2009 obj.i = 2; 2010 res = obj.j + 2; 2011 } 2012 return res; 2013 } 2014 2015 /// CHECK-START: void Main.testStoreSameValue() load_store_elimination (before) 2016 /// CHECK: NewArray 2017 /// CHECK: ArrayGet 2018 /// CHECK: ArraySet 2019 2020 /// CHECK-START: void Main.testStoreSameValue() load_store_elimination (after) 2021 /// CHECK: NewArray 2022 /// CHECK-NOT: ArrayGet 2023 /// CHECK-NOT: ArraySet testStoreSameValue()2024 private static void testStoreSameValue() { 2025 Object[] array = new Object[2]; 2026 sArray = array; 2027 Object obj = array[0]; 2028 array[1] = obj; // Store the same value as the default value. 2029 } 2030 2031 /// CHECK-START: int Main.$noinline$testByteArrayDefaultValue() load_store_elimination (before) 2032 /// CHECK-DAG: NewArray 2033 /// CHECK-DAG: <<Value:b\d+>> ArrayGet 2034 /// CHECK-DAG: Return [<<Value>>] 2035 2036 /// CHECK-START: int Main.$noinline$testByteArrayDefaultValue() load_store_elimination (after) 2037 /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 2038 /// CHECK-DAG: Return [<<Const0>>] 2039 2040 /// CHECK-START: int Main.$noinline$testByteArrayDefaultValue() load_store_elimination (after) 2041 /// CHECK-NOT: NewArray 2042 /// CHECK-NOT: ArrayGet 2043 /// CHECK-NOT: TypeConversion $noinline$testByteArrayDefaultValue()2044 private static int $noinline$testByteArrayDefaultValue() { 2045 byte[] array = new byte[2]; 2046 array[1] = 1; // FIXME: Without any stores, LSA tells LSE not to run. 2047 return array[0]; 2048 } 2049 2050 static Object[] sArray; 2051 2052 /// CHECK-START: int Main.testLocalArrayMerge1(boolean) load_store_elimination (before) 2053 /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 2054 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 2055 /// CHECK-DAG: <<A:l\d+>> NewArray 2056 /// CHECK-DAG: ArraySet [<<A>>,<<Const0>>,<<Const0>>] 2057 /// CHECK-DAG: ArraySet [<<A>>,<<Const0>>,<<Const1>>] 2058 /// CHECK-DAG: ArraySet [<<A>>,<<Const0>>,<<Const1>>] 2059 /// CHECK-DAG: <<Get:i\d+>> ArrayGet [<<A>>,<<Const0>>] 2060 /// CHECK-DAG: Return [<<Get>>] 2061 // 2062 /// CHECK-START: int Main.testLocalArrayMerge1(boolean) load_store_elimination (after) 2063 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 2064 /// CHECK-DAG: Return [<<Const1>>] 2065 // 2066 /// CHECK-START: int Main.testLocalArrayMerge1(boolean) load_store_elimination (after) 2067 /// CHECK-NOT: NewArray 2068 /// CHECK-NOT: ArraySet 2069 /// CHECK-NOT: ArrayGet testLocalArrayMerge1(boolean x)2070 private static int testLocalArrayMerge1(boolean x) { 2071 // The explicit store can be removed right away 2072 // since it is equivalent to the default. 2073 int[] a = { 0 }; 2074 // The diamond pattern stores/load can be replaced 2075 // by the direct value. 2076 if (x) { 2077 a[0] = 1; 2078 } else { 2079 a[0] = 1; 2080 } 2081 return a[0]; 2082 } 2083 2084 /// CHECK-START: int Main.testLocalArrayMerge2(boolean) load_store_elimination (before) 2085 /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 2086 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 2087 /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2 2088 /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3 2089 /// CHECK-DAG: <<A:l\d+>> NewArray 2090 /// CHECK-DAG: ArraySet [<<A>>,<<Const0>>,<<Const1>>] 2091 /// CHECK-DAG: ArraySet [<<A>>,<<Const0>>,<<Const2>>] 2092 /// CHECK-DAG: ArraySet [<<A>>,<<Const0>>,<<Const3>>] 2093 /// CHECK-DAG: <<Get:i\d+>> ArrayGet [<<A>>,<<Const0>>] 2094 /// CHECK-DAG: Return [<<Get>>] 2095 2096 /// CHECK-START: int Main.testLocalArrayMerge2(boolean) load_store_elimination (after) 2097 /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2 2098 /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3 2099 /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Arg1:i\d+>>,<<Arg2:i\d+>>] 2100 /// CHECK-DAG: Return [<<Phi>>] 2101 /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>"]) == set(["<<Const2>>","<<Const3>>"]) 2102 2103 /// CHECK-START: int Main.testLocalArrayMerge2(boolean) load_store_elimination (after) 2104 /// CHECK-NOT: NewArray 2105 /// CHECK-NOT: ArraySet 2106 /// CHECK-NOT: ArrayGet testLocalArrayMerge2(boolean x)2107 private static int testLocalArrayMerge2(boolean x) { 2108 // The explicit store can be removed eventually even 2109 // though it is not equivalent to the default. 2110 int[] a = { 1 }; 2111 // The load after the diamond pattern is eliminated and replaced with a Phi, 2112 // stores are then also eliminated. 2113 if (x) { 2114 a[0] = 2; 2115 } else { 2116 a[0] = 3; 2117 } 2118 return a[0]; 2119 } 2120 2121 /// CHECK-START: int Main.testLocalArrayMerge3(boolean) load_store_elimination (before) 2122 /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 2123 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 2124 /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2 2125 /// CHECK-DAG: <<A:l\d+>> NewArray 2126 /// CHECK-DAG: ArraySet [<<A>>,<<Const0>>,<<Const1>>] 2127 /// CHECK-DAG: ArraySet [<<A>>,<<Const0>>,<<Const2>>] 2128 /// CHECK-DAG: <<Get:i\d+>> ArrayGet [<<A>>,<<Const0>>] 2129 /// CHECK-DAG: Return [<<Get>>] 2130 2131 /// CHECK-START: int Main.testLocalArrayMerge3(boolean) load_store_elimination (after) 2132 /// CHECK-NOT: NewArray 2133 /// CHECK-NOT: ArraySet 2134 /// CHECK-NOT: ArrayGet testLocalArrayMerge3(boolean x)2135 private static int testLocalArrayMerge3(boolean x) { 2136 int[] a = { 1 }; 2137 if (x) { 2138 a[0] = 2; 2139 } 2140 return a[0]; 2141 } 2142 2143 /// CHECK-START: int Main.testLocalArrayMerge4(boolean) load_store_elimination (before) 2144 /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 2145 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 2146 /// CHECK-DAG: <<A:l\d+>> NewArray 2147 /// CHECK-DAG: ArraySet [<<A>>,<<Const0>>,<<Const0>>] 2148 /// CHECK-DAG: ArraySet [<<A>>,<<Const0>>,<<Const1>>] 2149 /// CHECK-DAG: ArraySet [<<A>>,<<Const0>>,<<Const1>>] 2150 /// CHECK-DAG: <<Get1:b\d+>> ArrayGet [<<A>>,<<Const0>>] 2151 /// CHECK-DAG: <<Get2:a\d+>> ArrayGet [<<A>>,<<Const0>>] 2152 /// CHECK-DAG: <<Add:i\d+>> Add [<<Get1>>,<<Get2>>] 2153 /// CHECK-DAG: Return [<<Add>>] 2154 // 2155 /// CHECK-START: int Main.testLocalArrayMerge4(boolean) load_store_elimination (after) 2156 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 2157 /// CHECK-DAG: <<Cnv1:b\d+>> TypeConversion [<<Const1>>] 2158 /// CHECK-DAG: <<Cnv2:a\d+>> TypeConversion [<<Const1>>] 2159 /// CHECK-DAG: <<Add:i\d+>> Add [<<Cnv1>>,<<Cnv2>>] 2160 /// CHECK-DAG: Return [<<Add>>] 2161 // 2162 /// CHECK-START: int Main.testLocalArrayMerge4(boolean) load_store_elimination (after) 2163 /// CHECK-NOT: NewArray 2164 /// CHECK-NOT: ArraySet 2165 /// CHECK-NOT: ArrayGet testLocalArrayMerge4(boolean x)2166 private static int testLocalArrayMerge4(boolean x) { 2167 byte[] a = { 0 }; 2168 if (x) { 2169 a[0] = 1; 2170 } else { 2171 a[0] = 1; 2172 } 2173 // Differently typed (signed vs unsigned), 2174 // but same reference. 2175 return a[0] + (a[0] & 0xff); 2176 } 2177 2178 /// CHECK-START: int Main.testLocalArrayMerge5(int[], boolean) load_store_elimination (before) 2179 /// CHECK: ArraySet 2180 /// CHECK: ArraySet 2181 /// CHECK: ArraySet 2182 2183 /// CHECK-START: int Main.testLocalArrayMerge5(int[], boolean) load_store_elimination (after) 2184 /// CHECK-NOT: ArraySet 2185 2186 // Test eliminating store of the same value after eliminating non-observable stores. testLocalArrayMerge5(int[] a, boolean x)2187 private static int testLocalArrayMerge5(int[] a, boolean x) { 2188 int old = a[0]; 2189 if (x) { 2190 a[0] = 1; 2191 } else { 2192 a[0] = 1; 2193 } 2194 // This store makes the stores above dead and they will be eliminated. 2195 // That makes this store unnecessary as we're storing the same value already 2196 // present in this location, so it shall also be eliminated. 2197 a[0] = old; 2198 return old; 2199 } 2200 2201 /// CHECK-START: int Main.testLocalArrayMerge6(int[], boolean, boolean) load_store_elimination (before) 2202 /// CHECK-DAG: ArraySet 2203 /// CHECK-DAG: ArraySet 2204 /// CHECK-DAG: ArraySet 2205 /// CHECK-DAG: ArrayGet 2206 /// CHECK-DAG: ArrayGet 2207 2208 /// CHECK-START: int Main.testLocalArrayMerge6(int[], boolean, boolean) load_store_elimination (after) 2209 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 2210 /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2 2211 /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3 2212 /// CHECK-DAG: ArraySet 2213 /// CHECK-DAG: ArraySet 2214 /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Arg1:i\d+>>,<<Arg2:i\d+>>] 2215 /// CHECK-DAG: Return [<<Phi>>] 2216 /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Const3>>,<<Phi>>] 2217 /// CHECK-DAG: Return [<<Sub>>] 2218 /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>"]) == set(["<<Const1>>","<<Const2>>"]) 2219 2220 /// CHECK-START: int Main.testLocalArrayMerge6(int[], boolean, boolean) load_store_elimination (after) 2221 /// CHECK: Phi 2222 /// CHECK-NOT: Phi 2223 2224 /// CHECK-START: int Main.testLocalArrayMerge6(int[], boolean, boolean) load_store_elimination (after) 2225 /// CHECK-NOT: ArrayGet 2226 2227 // Test that we create a single Phi for eliminating two loads in different blocks. testLocalArrayMerge6(int[] a, boolean x, boolean y)2228 private static int testLocalArrayMerge6(int[] a, boolean x, boolean y) { 2229 a[0] = 0; 2230 if (x) { 2231 a[0] = 1; 2232 } else { 2233 a[0] = 2; 2234 } 2235 // Phi for load elimination is created here. 2236 if (y) { 2237 return a[0]; 2238 } else { 2239 return 3 - a[0]; 2240 } 2241 } 2242 2243 /// CHECK-START: int Main.testLocalArrayMerge7(int[], boolean, boolean) load_store_elimination (before) 2244 /// CHECK-DAG: ArraySet 2245 /// CHECK-DAG: ArraySet 2246 /// CHECK-DAG: ArraySet 2247 /// CHECK-DAG: ArrayGet 2248 /// CHECK-DAG: ArraySet 2249 /// CHECK-DAG: ArrayGet 2250 2251 /// CHECK-START: int Main.testLocalArrayMerge7(int[], boolean, boolean) load_store_elimination (after) 2252 /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 2253 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 2254 /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2 2255 /// CHECK-DAG: ArraySet 2256 /// CHECK-DAG: ArraySet 2257 /// CHECK-DAG: ArraySet 2258 /// CHECK-DAG: ArraySet 2259 /// CHECK-DAG: Return [<<Phi2:i\d+>>] 2260 /// CHECK-DAG: <<Phi2>> Phi [<<Arg3:i\d+>>,<<Arg4:i\d+>>] 2261 /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Arg1:i\d+>>,<<Arg2:i\d+>>] 2262 /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>"]) == set(["<<Const1>>","<<Const2>>"]) 2263 /// CHECK-EVAL: set(["<<Arg3>>","<<Arg4>>"]) == set(["<<Const0>>","<<Phi1>>"]) 2264 2265 /// CHECK-START: int Main.testLocalArrayMerge7(int[], boolean, boolean) load_store_elimination (after) 2266 /// CHECK-NOT: ArrayGet 2267 2268 // Test Phi creation for load elimination. testLocalArrayMerge7(int[] a, boolean x, boolean y)2269 private static int testLocalArrayMerge7(int[] a, boolean x, boolean y) { 2270 a[1] = 0; 2271 if (x) { 2272 if (y) { 2273 a[0] = 1; 2274 } else { 2275 a[0] = 2; 2276 } 2277 a[1] = a[0]; 2278 } 2279 return a[1]; 2280 } 2281 2282 /// CHECK-START: int Main.testLocalArrayMerge8(boolean) load_store_elimination (before) 2283 /// CHECK-DAG: NewArray 2284 /// CHECK-DAG: ArraySet 2285 /// CHECK-DAG: ArraySet 2286 /// CHECK-DAG: ArraySet 2287 /// CHECK-DAG: ArraySet 2288 /// CHECK-DAG: ArrayGet 2289 /// CHECK-DAG: ArrayGet 2290 2291 /// CHECK-START: int Main.testLocalArrayMerge8(boolean) load_store_elimination (after) 2292 /// CHECK-NOT: NewArray 2293 /// CHECK-NOT: ArraySet 2294 /// CHECK-NOT: ArrayGet 2295 2296 // Test Merging default value and an identical value. testLocalArrayMerge8(boolean x)2297 private static int testLocalArrayMerge8(boolean x) { 2298 int[] a = new int[2]; 2299 if (x) { 2300 a[0] = 1; // Make sure the store below is not eliminated immediately as 2301 // storing the same value already present in the heap location. 2302 a[0] = 0; // Store the same value as default value to test merging with 2303 // the default value from else-block. 2304 } else { 2305 // Do the same as then-block for a different heap location to avoid 2306 // relying on block ordering. (Test both `default+0` and `0+default`.) 2307 a[1] = 1; 2308 a[1] = 0; 2309 } 2310 return a[0] + a[1]; 2311 } 2312 2313 /// CHECK-START: void Main.$noinline$testThrowingArraySet(java.lang.Object[], java.lang.Object) load_store_elimination (before) 2314 /// CHECK-DAG: ArrayGet 2315 /// CHECK-DAG: ArraySet 2316 /// CHECK-DAG: ArraySet 2317 /// CHECK-DAG: ArraySet 2318 /// CHECK-DAG: ArraySet 2319 2320 /// CHECK-START: void Main.$noinline$testThrowingArraySet(java.lang.Object[], java.lang.Object) load_store_elimination (after) 2321 /// CHECK-DAG: ArrayGet 2322 /// CHECK-DAG: ArraySet 2323 /// CHECK-DAG: ArraySet 2324 /// CHECK-DAG: ArraySet 2325 /// CHECK-DAG: ArraySet $noinline$testThrowingArraySet(Object[] a, Object o)2326 private static void $noinline$testThrowingArraySet(Object[] a, Object o) { 2327 Object olda0 = a[0]; 2328 a[0] = null; 2329 a[1] = olda0; 2330 a[0] = o; 2331 a[1] = null; 2332 } 2333 2334 /// CHECK-START: int Main.testLoop1(TestClass, int) load_store_elimination (before) 2335 /// CHECK-DAG: InstanceFieldSet 2336 /// CHECK-DAG: InstanceFieldSet 2337 /// CHECK-DAG: InstanceFieldGet 2338 /// CHECK-DAG: Phi 2339 2340 /// CHECK-START: int Main.testLoop1(TestClass, int) load_store_elimination (after) 2341 /// CHECK-DAG: InstanceFieldSet 2342 /// CHECK-DAG: InstanceFieldSet 2343 /// CHECK-DAG: Phi 2344 /// CHECK-DAG: Phi 2345 2346 /// CHECK-START: int Main.testLoop1(TestClass, int) load_store_elimination (after) 2347 /// CHECK-NOT: InstanceFieldGet 2348 2349 // Test Phi creation for load elimination with loop. testLoop1(TestClass obj, int n)2350 private static int testLoop1(TestClass obj, int n) { 2351 obj.i = 0; 2352 for (int i = 0; i < n; ++i) { 2353 obj.i = i; 2354 } 2355 return obj.i; 2356 } 2357 2358 /// CHECK-START: int Main.testLoop2(TestClass, int) load_store_elimination (before) 2359 /// CHECK-DAG: InstanceFieldSet 2360 /// CHECK-DAG: InstanceFieldSet 2361 /// CHECK-DAG: InstanceFieldGet 2362 /// CHECK-DAG: Phi 2363 2364 /// CHECK-START: int Main.testLoop2(TestClass, int) load_store_elimination (after) 2365 /// CHECK-DAG: InstanceFieldSet 2366 /// CHECK-DAG: InstanceFieldSet 2367 2368 /// CHECK-START: int Main.testLoop2(TestClass, int) load_store_elimination (after) 2369 /// CHECK-NOT: InstanceFieldGet 2370 2371 /// CHECK-START: int Main.testLoop2(TestClass, int) load_store_elimination (after) 2372 /// CHECK: Phi 2373 /// CHECK-NOT: Phi 2374 2375 // Test that we do not create any Phis for load elimination when 2376 // the heap value was not modified in the loop. testLoop2(TestClass obj, int n)2377 private static int testLoop2(TestClass obj, int n) { 2378 obj.i = 1; 2379 for (int i = 0; i < n; ++i) { 2380 obj.j = i; 2381 } 2382 return obj.i; 2383 } 2384 2385 /// CHECK-START: int Main.testLoop3(TestClass, int) load_store_elimination (before) 2386 /// CHECK-DAG: InstanceFieldSet 2387 /// CHECK-DAG: InstanceFieldSet 2388 /// CHECK-DAG: InstanceFieldGet 2389 2390 /// CHECK-START: int Main.testLoop3(TestClass, int) load_store_elimination (after) 2391 /// CHECK: InstanceFieldSet 2392 /// CHECK-NOT: InstanceFieldSet 2393 2394 /// CHECK-START: int Main.testLoop3(TestClass, int) load_store_elimination (after) 2395 /// CHECK-NOT: InstanceFieldGet 2396 2397 // Test elimination of a store in the loop that stores the same value that was already 2398 // stored before the loop and eliminating the load of that value after the loop. testLoop3(TestClass obj, int n)2399 private static int testLoop3(TestClass obj, int n) { 2400 obj.i = 1; 2401 for (int i = 0; i < n; ++i) { 2402 obj.i = 1; 2403 } 2404 return obj.i; 2405 } 2406 2407 /// CHECK-START: int Main.testLoop4(TestClass, int) load_store_elimination (before) 2408 /// CHECK-DAG: InstanceFieldSet 2409 /// CHECK-DAG: InstanceFieldSet 2410 2411 /// CHECK-START: int Main.testLoop4(TestClass, int) load_store_elimination (after) 2412 /// CHECK: InstanceFieldSet 2413 /// CHECK-NOT: InstanceFieldSet 2414 2415 /// CHECK-START: int Main.testLoop4(TestClass, int) load_store_elimination (after) 2416 /// CHECK-NOT: InstanceFieldGet 2417 2418 // Test store elimination in the loop that stores the same value that was already 2419 // stored before the loop, without any loads of that value. testLoop4(TestClass obj, int n)2420 private static int testLoop4(TestClass obj, int n) { 2421 obj.i = 1; 2422 for (int i = 0; i < n; ++i) { 2423 obj.i = 1; 2424 } 2425 return n; 2426 } 2427 2428 /// CHECK-START: int Main.testLoop5(TestClass, int) load_store_elimination (before) 2429 /// CHECK-DAG: InstanceFieldSet 2430 /// CHECK-DAG: InstanceFieldSet 2431 /// CHECK-DAG: InstanceFieldGet 2432 /// CHECK-DAG: InstanceFieldGet 2433 /// CHECK-DAG: InstanceFieldSet 2434 /// CHECK-DAG: InstanceFieldSet 2435 /// CHECK-DAG: InstanceFieldGet 2436 2437 /// CHECK-START: int Main.testLoop5(TestClass, int) load_store_elimination (after) 2438 /// CHECK: InstanceFieldSet 2439 /// CHECK: InstanceFieldSet 2440 /// CHECK-NOT: InstanceFieldSet 2441 2442 /// CHECK-START: int Main.testLoop5(TestClass, int) load_store_elimination (after) 2443 /// CHECK-NOT: InstanceFieldGet 2444 2445 // Test eliminating loads and stores that just shuffle the same value between 2446 // different heap locations. testLoop5(TestClass obj, int n)2447 private static int testLoop5(TestClass obj, int n) { 2448 // Initialize both `obj.i` and `obj.j` to the same value and then swap these values 2449 // in the loop. We should be able to determine that the values are always the same. 2450 obj.i = n; 2451 obj.j = n; 2452 for (int i = 0; i < n; ++i) { 2453 if ((i & 1) != 0) { 2454 int tmp = obj.i; 2455 obj.i = obj.j; 2456 obj.j = tmp; 2457 } 2458 } 2459 return obj.i; 2460 } 2461 2462 /// CHECK-START: int Main.testLoop6(TestClass, int) load_store_elimination (before) 2463 /// CHECK-DAG: InstanceFieldSet 2464 /// CHECK-DAG: InstanceFieldSet 2465 /// CHECK-DAG: InstanceFieldGet 2466 /// CHECK-DAG: InstanceFieldGet 2467 /// CHECK-DAG: InstanceFieldSet 2468 /// CHECK-DAG: InstanceFieldSet 2469 /// CHECK-DAG: InstanceFieldSet 2470 /// CHECK-DAG: InstanceFieldGet 2471 2472 /// CHECK-START: int Main.testLoop6(TestClass, int) load_store_elimination (after) 2473 /// CHECK: InstanceFieldSet 2474 /// CHECK: InstanceFieldSet 2475 /// CHECK-NOT: InstanceFieldSet 2476 2477 /// CHECK-START: int Main.testLoop6(TestClass, int) load_store_elimination (after) 2478 /// CHECK-NOT: InstanceFieldGet 2479 2480 // Test eliminating loads and stores that just shuffle the same value between 2481 // different heap locations, or store the same value. testLoop6(TestClass obj, int n)2482 private static int testLoop6(TestClass obj, int n) { 2483 // Initialize both `obj.i` and `obj.j` to the same value and then swap these values 2484 // in the loop or set `obj.i` to the same value. We should be able to determine 2485 // that the values are always the same. 2486 obj.i = n; 2487 obj.j = n; 2488 for (int i = 0; i < n; ++i) { 2489 if ((i & 1) != 0) { 2490 int tmp = obj.i; 2491 obj.i = obj.j; 2492 obj.j = tmp; 2493 } else { 2494 obj.i = n; 2495 } 2496 } 2497 return obj.i; 2498 } 2499 2500 /// CHECK-START: int Main.testLoop7(int) load_store_elimination (before) 2501 /// CHECK-DAG: NewInstance 2502 /// CHECK-DAG: InstanceFieldGet 2503 /// CHECK-DAG: InstanceFieldGet 2504 /// CHECK-DAG: InstanceFieldSet 2505 /// CHECK-DAG: InstanceFieldSet 2506 /// CHECK-DAG: InstanceFieldSet 2507 /// CHECK-DAG: InstanceFieldGet 2508 2509 /// CHECK-START: int Main.testLoop7(int) load_store_elimination (after) 2510 /// CHECK-NOT: NewInstance 2511 /// CHECK-NOT: InstanceFieldSet 2512 /// CHECK-NOT: InstanceFieldGet 2513 2514 // Test eliminating loads and stores that just shuffle the default value between 2515 // different heap locations, or store the same value. testLoop7(int n)2516 private static int testLoop7(int n) { 2517 // Leave both `obj.i` and `obj.j` initialized to the default value and then 2518 // swap these values in the loop or set some to the identical value 0. 2519 // We should be able to determine that the values are always the same. 2520 TestClass obj = new TestClass(); 2521 for (int i = 0; i < n; ++i) { 2522 if ((i & 1) != 0) { 2523 int tmp = obj.i; 2524 obj.i = obj.j; 2525 obj.j = tmp; 2526 } else { 2527 obj.i = 0; 2528 } 2529 } 2530 return obj.i; 2531 } 2532 2533 /// CHECK-START: int Main.testLoop8(int) load_store_elimination (before) 2534 /// CHECK-DAG: NewInstance 2535 /// CHECK-DAG: InstanceFieldGet 2536 /// CHECK-DAG: InstanceFieldGet 2537 /// CHECK-DAG: InstanceFieldSet 2538 /// CHECK-DAG: InstanceFieldSet 2539 /// CHECK-DAG: InstanceFieldSet 2540 /// CHECK-DAG: InstanceFieldSet 2541 /// CHECK-DAG: InstanceFieldGet 2542 2543 /// CHECK-START: int Main.testLoop8(int) load_store_elimination (after) 2544 /// CHECK-NOT: NewInstance 2545 /// CHECK-NOT: InstanceFieldSet 2546 /// CHECK-NOT: InstanceFieldGet 2547 2548 /// CHECK-START: int Main.testLoop8(int) load_store_elimination (after) 2549 /// CHECK: Phi 2550 /// CHECK: Phi 2551 /// CHECK-NOT: Phi 2552 2553 // Test eliminating loads and stores that just shuffle the same value between 2554 // different heap locations, or store the same value. The value is loaded 2555 // after conditionally setting a different value after the loop to test that 2556 // this does not cause creation of excessive Phis. testLoop8(int n)2557 private static int testLoop8(int n) { 2558 // Leave both `obj.i` and `obj.j` initialized to the default value and then 2559 // swap these values in the loop or set some to the identical value 0. 2560 // We should be able to determine that the values are always the same. 2561 TestClass obj = new TestClass(); 2562 for (int i = 0; i < n; ++i) { 2563 if ((i & 1) != 0) { 2564 int tmp = obj.i; 2565 obj.i = obj.j; 2566 obj.j = tmp; 2567 } else { 2568 obj.i = 0; 2569 } 2570 } 2571 // Up to this point, `obj.i` is always 0 but the Phi placeholder below 2572 // must not be included in that determination despite using lazy search 2573 // for Phi placeholders triggered by the `obj.i` load below. 2574 if ((n & 1) == 0) { 2575 obj.i = 1; 2576 } 2577 return obj.i; 2578 } 2579 2580 /// CHECK-START: int Main.testLoop9(TestClass, int) load_store_elimination (before) 2581 /// CHECK-DAG: NewInstance 2582 /// CHECK-DAG: InstanceFieldSet 2583 /// CHECK-DAG: InstanceFieldSet 2584 /// CHECK-DAG: Phi 2585 /// CHECK-DAG: InstanceFieldGet 2586 /// CHECK-DAG: InstanceFieldGet 2587 /// CHECK-DAG: InstanceFieldSet 2588 /// CHECK-DAG: InstanceFieldSet 2589 /// CHECK-DAG: InvokeStaticOrDirect 2590 /// CHECK-DAG: InstanceFieldGet 2591 2592 /// CHECK-START: int Main.testLoop9(TestClass, int) load_store_elimination (after) 2593 /// CHECK-DAG: InstanceFieldSet 2594 /// CHECK-DAG: Phi 2595 /// CHECK-DAG: Phi 2596 /// CHECK-DAG: InstanceFieldGet 2597 /// CHECK-DAG: InstanceFieldSet 2598 /// CHECK-DAG: Phi 2599 2600 /// CHECK-START: int Main.testLoop9(TestClass, int) load_store_elimination (after) 2601 /// CHECK: InstanceFieldSet 2602 /// CHECK: InstanceFieldSet 2603 /// CHECK-NOT: InstanceFieldSet 2604 2605 /// CHECK-START: int Main.testLoop9(TestClass, int) load_store_elimination (after) 2606 /// CHECK-NOT: NewInstance 2607 2608 /// CHECK-START: int Main.testLoop9(TestClass, int) load_store_elimination (after) 2609 /// CHECK: InstanceFieldGet 2610 /// CHECK-NOT: InstanceFieldGet 2611 2612 /// CHECK-START: int Main.testLoop9(TestClass, int) load_store_elimination (after) 2613 /// CHECK: Phi 2614 /// CHECK: Phi 2615 /// CHECK: Phi 2616 /// CHECK-NOT: Phi 2617 2618 // Test that unknown value flowing through a loop back-edge prevents 2619 // elimination of a load but that load can be used as an input to a Phi 2620 // created to eliminate another load. testLoop9(TestClass obj, int n)2621 private static int testLoop9(TestClass obj, int n) { 2622 TestClass obj0 = new TestClass(); 2623 // Initialize both `obj.i` and `obj0.i` to the same value and then swap these values 2624 // in the loop or clobber `obj.i`. We should determine that the `obj.i` load in the 2625 // loop must be kept but the `obj0.i` load can be replaced by a Phi chain. 2626 obj0.i = n; 2627 obj.i = n; 2628 for (int i = 0; i < n; ++i) { 2629 if ((i & 1) != 0) { 2630 int tmp = obj0.i; 2631 obj0.i = obj.i; // Load cannot be eliminated. 2632 obj.i = tmp; 2633 } else { 2634 $noinline$clobberObservables(); // Makes obj.i unknown. 2635 } 2636 } 2637 return obj0.i; 2638 } 2639 2640 /// CHECK-START: int Main.testLoop10(TestClass, int) load_store_elimination (before) 2641 /// CHECK-DAG: InstanceFieldSet 2642 /// CHECK-DAG: InstanceFieldGet 2643 /// CHECK-DAG: InstanceFieldSet 2644 /// CHECK-DAG: InstanceFieldGet 2645 2646 /// CHECK-START: int Main.testLoop10(TestClass, int) load_store_elimination (after) 2647 /// CHECK-DAG: InstanceFieldSet 2648 /// CHECK-DAG: InstanceFieldGet 2649 /// CHECK-DAG: InstanceFieldSet 2650 2651 /// CHECK-START: int Main.testLoop10(TestClass, int) load_store_elimination (after) 2652 /// CHECK: InstanceFieldGet 2653 /// CHECK-NOT: InstanceFieldGet 2654 2655 // Test load elimination after finding a non-eliminated load depending 2656 // on loop Phi placeholder. testLoop10(TestClass obj, int n)2657 private static int testLoop10(TestClass obj, int n) { 2658 obj.i = 1; 2659 for (int i = 0; i < n; ++i) { 2660 $noinline$clobberObservables(); 2661 } 2662 int i1 = obj.i; 2663 obj.j = 2; // Use write side effects to stop GVN from eliminating the load below. 2664 int i2 = obj.i; 2665 return i1 + i2; 2666 } 2667 2668 /// CHECK-START: int Main.testLoop11(TestClass, int) load_store_elimination (before) 2669 /// CHECK-DAG: InstanceFieldSet 2670 /// CHECK-DAG: Phi 2671 /// CHECK-DAG: InstanceFieldSet 2672 /// CHECK-DAG: InstanceFieldSet 2673 /// CHECK-DAG: InstanceFieldGet 2674 2675 /// CHECK-START: int Main.testLoop11(TestClass, int) load_store_elimination (after) 2676 /// CHECK-DAG: InstanceFieldSet 2677 /// CHECK-DAG: Phi 2678 /// CHECK-DAG: Phi 2679 /// CHECK-DAG: InstanceFieldSet 2680 /// CHECK-DAG: InstanceFieldSet 2681 /// CHECK-DAG: Phi 2682 2683 /// CHECK-START: int Main.testLoop11(TestClass, int) load_store_elimination (after) 2684 /// CHECK: Phi 2685 /// CHECK: Phi 2686 /// CHECK: Phi 2687 /// CHECK-NOT: Phi 2688 2689 /// CHECK-START: int Main.testLoop11(TestClass, int) load_store_elimination (after) 2690 /// CHECK-NOT: InstanceFieldGet 2691 2692 // Test load elimination creating two Phis that depend on each other. testLoop11(TestClass obj, int n)2693 private static int testLoop11(TestClass obj, int n) { 2694 obj.i = 1; 2695 for (int i = 0; i < n; ++i) { 2696 if ((i & 1) != 0) { 2697 obj.i = 2; 2698 } else { 2699 obj.i = 3; 2700 } 2701 // There shall be a Phi created here for `obj.i` before the "++i". 2702 // This Phi and the loop Phi that shall be created for `obj.i` depend on each other. 2703 } 2704 return obj.i; 2705 } 2706 2707 /// CHECK-START: int Main.testLoop12(TestClass, int) load_store_elimination (before) 2708 /// CHECK-DAG: InstanceFieldSet 2709 /// CHECK-DAG: Phi 2710 /// CHECK-DAG: InstanceFieldSet 2711 /// CHECK-DAG: InstanceFieldSet 2712 /// CHECK-DAG: InstanceFieldGet 2713 2714 /// CHECK-START: int Main.testLoop12(TestClass, int) load_store_elimination (after) 2715 /// CHECK-DAG: InstanceFieldSet 2716 /// CHECK-DAG: Phi 2717 /// CHECK-DAG: Phi 2718 /// CHECK-DAG: InstanceFieldSet 2719 /// CHECK-DAG: InstanceFieldSet 2720 2721 /// CHECK-START: int Main.testLoop12(TestClass, int) load_store_elimination (after) 2722 /// CHECK: Phi 2723 /// CHECK: Phi 2724 /// CHECK-NOT: Phi 2725 2726 /// CHECK-START: int Main.testLoop12(TestClass, int) load_store_elimination (after) 2727 /// CHECK-NOT: InstanceFieldGet 2728 2729 // Test load elimination creating a single Phi with more than 2 inputs. testLoop12(TestClass obj, int n)2730 private static int testLoop12(TestClass obj, int n) { 2731 obj.i = 1; 2732 for (int i = 0; i < n; ) { 2733 // Do the loop variable increment first, so that there are back-edges 2734 // directly from the "then" and "else" blocks below. 2735 ++i; 2736 if ((i & 1) != 0) { 2737 obj.i = 2; 2738 } else { 2739 obj.i = 3; 2740 } 2741 } 2742 return obj.i; 2743 } 2744 2745 /// CHECK-START: int Main.testLoop13(TestClass, int) load_store_elimination (before) 2746 /// CHECK-DAG: NewArray 2747 /// CHECK-DAG: Phi 2748 /// CHECK-DAG: ArrayGet 2749 /// CHECK-DAG: ArraySet 2750 /// CHECK-DAG: ArrayGet 2751 /// CHECK-DAG: ArraySet 2752 /// CHECK-DAG: InstanceFieldGet 2753 /// CHECK-DAG: ArraySet 2754 /// CHECK-DAG: ArrayGet 2755 2756 /// CHECK-START: int Main.testLoop13(TestClass, int) load_store_elimination (after) 2757 /// CHECK-DAG: Phi 2758 /// CHECK-DAG: Phi 2759 /// CHECK-DAG: Phi 2760 /// CHECK-DAG: Phi 2761 /// CHECK-DAG: InstanceFieldGet 2762 2763 /// CHECK-START: int Main.testLoop13(TestClass, int) load_store_elimination (after) 2764 /// CHECK-NOT: NewArray 2765 /// CHECK-NOT: ArrayGet 2766 /// CHECK-NOT: ArraySet 2767 2768 /// CHECK-START: int Main.testLoop13(TestClass, int) load_store_elimination (after) 2769 /// CHECK: Phi 2770 /// CHECK: Phi 2771 /// CHECK: Phi 2772 /// CHECK: Phi 2773 /// CHECK-NOT: Phi 2774 2775 // Test eliminating array allocation, loads and stores and creating loop Phis. testLoop13(TestClass obj, int n)2776 private static int testLoop13(TestClass obj, int n) { 2777 int[] a = new int[3]; 2778 for (int i = 0; i < n; ++i) { 2779 a[0] = a[1]; 2780 a[1] = a[2]; 2781 a[2] = obj.i; 2782 } 2783 return a[0]; 2784 } 2785 2786 /// CHECK-START: int Main.testLoop14(TestClass2, int) load_store_elimination (before) 2787 /// CHECK-DAG: NewArray 2788 /// CHECK-DAG: InstanceFieldSet field_name:TestClass2.i 2789 /// CHECK-DAG: Phi 2790 /// CHECK-DAG: ArrayGet 2791 /// CHECK-DAG: ArraySet 2792 /// CHECK-DAG: ArrayGet 2793 /// CHECK-DAG: ArraySet 2794 /// CHECK-DAG: InstanceFieldGet field_name:TestClass2.i 2795 /// CHECK-DAG: InstanceFieldSet field_name:TestClass2.j 2796 /// CHECK-DAG: InstanceFieldGet field_name:TestClass2.i 2797 /// CHECK-DAG: ArraySet 2798 /// CHECK-DAG: InstanceFieldSet field_name:TestClass2.k 2799 /// CHECK-DAG: InstanceFieldSet field_name:TestClass2.j 2800 /// CHECK-DAG: InstanceFieldGet field_name:TestClass2.i 2801 /// CHECK-DAG: InstanceFieldSet field_name:TestClass2.k 2802 /// CHECK-DAG: ArrayGet 2803 2804 /// CHECK-START: int Main.testLoop14(TestClass2, int) load_store_elimination (after) 2805 /// CHECK-DAG: InstanceFieldSet field_name:TestClass2.i 2806 /// CHECK-DAG: Phi 2807 /// CHECK-DAG: Phi 2808 /// CHECK-DAG: Phi 2809 /// CHECK-DAG: Phi 2810 /// CHECK-DAG: InstanceFieldGet field_name:TestClass2.i 2811 /// CHECK-DAG: InstanceFieldSet field_name:TestClass2.j 2812 /// CHECK-DAG: InstanceFieldSet field_name:TestClass2.k 2813 /// CHECK-DAG: InstanceFieldSet field_name:TestClass2.j 2814 /// CHECK-DAG: InstanceFieldSet field_name:TestClass2.k 2815 2816 /// CHECK-START: int Main.testLoop14(TestClass2, int) load_store_elimination (after) 2817 /// CHECK-NOT: NewArray 2818 2819 /// CHECK-START: int Main.testLoop14(TestClass2, int) load_store_elimination (after) 2820 /// CHECK: InstanceFieldGet field_name:TestClass2.i 2821 /// CHECK-NOT: InstanceFieldGet field_name:TestClass2.i 2822 2823 /// CHECK-START: int Main.testLoop14(TestClass2, int) load_store_elimination (after) 2824 /// CHECK: Phi 2825 /// CHECK: Phi 2826 /// CHECK: Phi 2827 /// CHECK: Phi 2828 /// CHECK-NOT: Phi 2829 2830 // Test load elimination in a loop after determing that the first field load 2831 // (depending on loop Phi placeholder) cannot be eliminated. testLoop14(TestClass2 obj, int n)2832 private static int testLoop14(TestClass2 obj, int n) { 2833 int[] a = new int[3]; 2834 obj.i = 1; 2835 for (int i = 0; i < n; ++i) { 2836 a[0] = a[1]; 2837 a[1] = a[2]; 2838 int i1 = obj.i; 2839 obj.j = 2; // Use write side effects to stop GVN from eliminating the load below. 2840 int i2 = obj.i; 2841 a[2] = i1; 2842 if ((i & 2) != 0) { 2843 obj.k = i2; 2844 } else { 2845 obj.j = 3; // Use write side effects to stop GVN from eliminating the load below. 2846 obj.k = obj.i; 2847 $noinline$clobberObservables(); // Make obj.i unknown. 2848 } 2849 } 2850 return a[0]; 2851 } 2852 2853 /// CHECK-START: int Main.testLoop15(int) load_store_elimination (before) 2854 /// CHECK-DAG: NewArray 2855 /// CHECK-IF: hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true' 2856 // 2857 /// CHECK-DAG: VecPredWhile 2858 /// CHECK-DAG: VecStore 2859 // 2860 /// CHECK-ELSE: 2861 // 2862 /// CHECK-DAG: ArraySet 2863 // 2864 /// CHECK-FI: 2865 // 2866 /// CHECK-DAG: ArrayGet 2867 2868 /// CHECK-START: int Main.testLoop15(int) load_store_elimination (after) 2869 /// CHECK-DAG: NewArray 2870 /// CHECK-IF: hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true' 2871 // 2872 /// CHECK-DAG: VecPredWhile 2873 /// CHECK-DAG: VecStore 2874 // 2875 /// CHECK-ELSE: 2876 // 2877 /// CHECK-DAG: ArraySet 2878 // 2879 /// CHECK-FI: 2880 // 2881 /// CHECK-DAG: ArrayGet 2882 // Test that aliasing array store in the loop is not eliminated 2883 // when a loop Phi placeholder is marked for keeping. testLoop15(int n)2884 private static int testLoop15(int n) { 2885 int[] a = new int[n + 1]; 2886 for (int i = 0; i < n; ++i) { 2887 a[i] = 1; // Cannot be eliminated due to aliasing. 2888 } 2889 return a[0]; 2890 } 2891 2892 /// CHECK-START: int Main.testLoop16(TestClass, int) load_store_elimination (before) 2893 /// CHECK-DAG: InstanceFieldSet 2894 /// CHECK-DAG: Phi 2895 /// CHECK-DAG: InstanceFieldSet 2896 /// CHECK-DAG: InstanceFieldGet 2897 2898 /// CHECK-START: int Main.testLoop16(TestClass, int) load_store_elimination (after) 2899 /// CHECK-DAG: InstanceFieldSet 2900 /// CHECK-DAG: Phi 2901 /// CHECK-DAG: InstanceFieldSet 2902 2903 /// CHECK-START: int Main.testLoop16(TestClass, int) load_store_elimination (after) 2904 /// CHECK-NOT: InstanceFieldGet 2905 2906 /// CHECK-START: int Main.testLoop16(TestClass, int) load_store_elimination (after) 2907 /// CHECK: Phi 2908 /// CHECK-NOT: Phi 2909 2910 // Test that we match an existing loop Phi for eliminating a load. testLoop16(TestClass obj, int n)2911 static int testLoop16(TestClass obj, int n) { 2912 obj.i = 0; 2913 for (int i = 0; i < n; ) { 2914 ++i; 2915 obj.i = i; 2916 } 2917 // The load is replaced by the existing Phi instead of constructing a new one. 2918 return obj.i; 2919 } 2920 2921 /// CHECK-START: int Main.testLoop17(TestClass, int) load_store_elimination (before) 2922 /// CHECK-DAG: InstanceFieldSet 2923 /// CHECK-DAG: Phi 2924 /// CHECK-DAG: InstanceFieldSet 2925 /// CHECK-DAG: InstanceFieldSet 2926 /// CHECK-DAG: Phi 2927 /// CHECK-DAG: InstanceFieldGet 2928 2929 /// CHECK-START: int Main.testLoop17(TestClass, int) load_store_elimination (after) 2930 /// CHECK-DAG: InstanceFieldSet 2931 /// CHECK-DAG: Phi 2932 /// CHECK-DAG: InstanceFieldSet 2933 /// CHECK-DAG: InstanceFieldSet 2934 /// CHECK-DAG: Phi 2935 2936 /// CHECK-START: int Main.testLoop17(TestClass, int) load_store_elimination (after) 2937 /// CHECK-NOT: InstanceFieldGet 2938 2939 /// CHECK-START: int Main.testLoop17(TestClass, int) load_store_elimination (after) 2940 /// CHECK: Phi 2941 /// CHECK: Phi 2942 /// CHECK-NOT: Phi 2943 2944 // Test that we match an existing non-loop Phi for eliminating a load, 2945 // one input of the Phi being invariant across a preceding loop. testLoop17(TestClass obj, int n)2946 static int testLoop17(TestClass obj, int n) { 2947 obj.i = 1; 2948 int phi = 1; 2949 for (int i = 0; i < n; ++i) { 2950 obj.j = 2; // Unrelated. 2951 } 2952 if ((n & 1) != 0) { 2953 obj.i = 2; 2954 phi = 2; 2955 } 2956 // The load is replaced by the existing Phi instead of constructing a new one. 2957 return obj.i + phi; 2958 } 2959 2960 /// CHECK-START: int Main.testLoop18(TestClass, int) load_store_elimination (before) 2961 /// CHECK-DAG: NewArray 2962 /// CHECK-DAG: Phi 2963 /// CHECK-DAG: ArrayGet 2964 /// CHECK-DAG: InstanceFieldSet 2965 2966 /// CHECK-START: int Main.testLoop18(TestClass, int) load_store_elimination (after) 2967 /// CHECK-DAG: NewArray 2968 /// CHECK-DAG: Phi 2969 /// CHECK-DAG: InstanceFieldSet 2970 2971 /// CHECK-START: int Main.testLoop18(TestClass, int) load_store_elimination (after) 2972 /// CHECK-NOT: ArrayGet 2973 2974 // Test eliminating a load of the default value in a loop 2975 // with the array index being defined inside the loop. testLoop18(TestClass obj, int n)2976 static int testLoop18(TestClass obj, int n) { 2977 // The NewArray is kept as it may throw for negative n. 2978 // TODO: Eliminate constructor fence even though the NewArray is kept. 2979 int[] a0 = new int[n]; 2980 for (int i = 0; i < n; ++i) { 2981 obj.i = a0[i]; 2982 } 2983 return n; 2984 } 2985 2986 /// CHECK-START: int Main.testLoop19(TestClass, int) load_store_elimination (before) 2987 /// CHECK-DAG: NewArray 2988 /// CHECK-DAG: Phi 2989 /// CHECK-DAG: ArrayGet 2990 /// CHECK-DAG: InstanceFieldSet 2991 /// CHECK-DAG: ArraySet 2992 2993 /// CHECK-START: int Main.testLoop19(TestClass, int) load_store_elimination (after) 2994 /// CHECK-DAG: NewArray 2995 /// CHECK-DAG: Phi 2996 /// CHECK-DAG: InstanceFieldSet 2997 2998 /// CHECK-START: int Main.testLoop19(TestClass, int) load_store_elimination (after) 2999 /// CHECK-NOT: ArrayGet 3000 /// CHECK-NOT: ArraySet 3001 3002 // Test eliminating a load of the default value and store of an identical value 3003 // in a loop with the array index being defined inside the loop. testLoop19(TestClass obj, int n)3004 static int testLoop19(TestClass obj, int n) { 3005 // The NewArray is kept as it may throw for negative n. 3006 // TODO: Eliminate constructor fence even though the NewArray is kept. 3007 int[] a0 = new int[n]; 3008 for (int i = 0; i < n; ++i) { 3009 obj.i = a0[i]; 3010 a0[i] = 0; // Store the same value as default. 3011 } 3012 return n; 3013 } 3014 3015 /// CHECK-START: int Main.testLoop20(TestClass, int) load_store_elimination (before) 3016 /// CHECK-DAG: NewArray 3017 /// CHECK-DAG: Phi 3018 /// CHECK-DAG: ArrayGet 3019 /// CHECK-DAG: InstanceFieldSet 3020 /// CHECK-DAG: ArraySet 3021 3022 /// CHECK-START: int Main.testLoop20(TestClass, int) load_store_elimination (after) 3023 /// CHECK-DAG: NewArray 3024 /// CHECK-DAG: Phi 3025 /// CHECK-DAG: InstanceFieldSet 3026 3027 /// CHECK-START: int Main.testLoop20(TestClass, int) load_store_elimination (after) 3028 /// CHECK-NOT: ArrayGet 3029 /// CHECK-NOT: ArraySet 3030 3031 // Test eliminating a load of the default value and a conditional store of an 3032 // identical value in a loop with the array index being defined inside the loop. testLoop20(TestClass obj, int n)3033 static int testLoop20(TestClass obj, int n) { 3034 // The NewArray is kept as it may throw for negative n. 3035 // TODO: Eliminate constructor fence even though the NewArray is kept. 3036 int[] a0 = new int[n]; 3037 for (int i = 0; i < n; ++i) { 3038 obj.i = a0[i]; 3039 if ((i & 1) != 0) { 3040 a0[i] = 0; // Store the same value as default. 3041 } 3042 } 3043 return n; 3044 } 3045 3046 /// CHECK-START: int Main.testLoop21(TestClass, int) load_store_elimination (before) 3047 /// CHECK-DAG: InstanceFieldSet 3048 /// CHECK-DAG: InstanceFieldGet 3049 /// CHECK-DAG: InstanceFieldSet 3050 /// CHECK-DAG: InstanceFieldGet 3051 /// CHECK-DAG: InstanceFieldSet 3052 /// CHECK-DAG: InstanceFieldGet 3053 /// CHECK-DAG: InstanceFieldSet 3054 3055 /// CHECK-START: int Main.testLoop21(TestClass, int) load_store_elimination (before) 3056 /// CHECK-NOT: Phi 3057 3058 /// CHECK-START: int Main.testLoop21(TestClass, int) load_store_elimination (after) 3059 /// CHECK-NOT: InstanceFieldGet 3060 3061 /// CHECK-START: int Main.testLoop21(TestClass, int) load_store_elimination (after) 3062 /// CHECK: InstanceFieldSet 3063 /// CHECK: InstanceFieldSet 3064 /// CHECK: InstanceFieldSet 3065 /// CHECK-NOT: InstanceFieldSet 3066 3067 /// CHECK-START: int Main.testLoop21(TestClass, int) load_store_elimination (after) 3068 /// CHECK: Phi 3069 /// CHECK-NOT: Phi 3070 3071 // Test load elimination when an instance field is used as the loop variable. testLoop21(TestClass obj, int n)3072 static int testLoop21(TestClass obj, int n) { 3073 for (obj.i = 0; obj.i < n; ++obj.i) { 3074 obj.j = 0; // Use write side effects to stop GVN from eliminating the load below. 3075 obj.j = obj.i; 3076 } 3077 return n; 3078 } 3079 3080 /// CHECK-START: int Main.testLoop22(TestClass, int) load_store_elimination (before) 3081 /// CHECK-DAG: InstanceFieldSet 3082 /// CHECK-DAG: InstanceFieldGet 3083 /// CHECK-DAG: InstanceFieldSet 3084 /// CHECK-DAG: InstanceFieldGet 3085 /// CHECK-DAG: InstanceFieldSet 3086 /// CHECK-DAG: InstanceFieldGet 3087 /// CHECK-DAG: InstanceFieldSet 3088 /// CHECK-DAG: InstanceFieldSet 3089 3090 /// CHECK-START: int Main.testLoop22(TestClass, int) load_store_elimination (before) 3091 /// CHECK-NOT: Phi 3092 3093 /// CHECK-START: int Main.testLoop22(TestClass, int) load_store_elimination (after) 3094 /// CHECK-NOT: InstanceFieldGet 3095 3096 /// CHECK-START: int Main.testLoop22(TestClass, int) load_store_elimination (after) 3097 /// CHECK: InstanceFieldSet 3098 /// CHECK: InstanceFieldSet 3099 /// CHECK-NOT: InstanceFieldSet 3100 3101 /// CHECK-START: int Main.testLoop22(TestClass, int) load_store_elimination (after) 3102 /// CHECK: Phi 3103 /// CHECK-NOT: Phi 3104 3105 // Test load and store elimination when an instance field is used as the loop 3106 // variable and then overwritten after the loop. testLoop22(TestClass obj, int n)3107 static int testLoop22(TestClass obj, int n) { 3108 for (obj.i = 0; obj.i < n; ++obj.i) { 3109 obj.j = 0; // Use write side effects to stop GVN from eliminating the load below. 3110 obj.j = obj.i; 3111 } 3112 obj.i = 0; 3113 return n; 3114 } 3115 3116 /// CHECK-START: int Main.testLoop23(TestClass, int) load_store_elimination (before) 3117 /// CHECK-DAG: InstanceFieldSet 3118 /// CHECK-DAG: Phi 3119 /// CHECK-DAG: Phi 3120 /// CHECK-DAG: InstanceFieldSet 3121 /// CHECK-DAG: InstanceFieldSet 3122 /// CHECK-DAG: Phi 3123 /// CHECK-DAG: InstanceFieldSet 3124 3125 /// CHECK-START: int Main.testLoop23(TestClass, int) load_store_elimination (after) 3126 /// CHECK-DAG: Phi 3127 /// CHECK-DAG: Phi 3128 /// CHECK-DAG: Phi 3129 /// CHECK-DAG: InstanceFieldSet 3130 3131 /// CHECK-START: int Main.testLoop23(TestClass, int) load_store_elimination (after) 3132 /// CHECK: InstanceFieldSet 3133 /// CHECK-NOT: InstanceFieldSet 3134 3135 // Test elimination of non-observable stores. testLoop23(TestClass obj, int n)3136 static int testLoop23(TestClass obj, int n) { 3137 obj.i = -1; 3138 int phi = -1; 3139 for (int i = 0; i < n; ++i) { 3140 obj.i = i; 3141 phi = i; 3142 } 3143 if ((n & 1) != 0) { 3144 obj.i = 2; 3145 phi = 2; 3146 } 3147 obj.i = phi; // This store shall be kept, the stores above shall be eliminated. 3148 return phi; 3149 } 3150 3151 /// CHECK-START: int Main.testLoop24(TestClass, int) load_store_elimination (before) 3152 /// CHECK-DAG: InstanceFieldSet 3153 /// CHECK-DAG: Phi 3154 /// CHECK-DAG: Phi 3155 /// CHECK-DAG: InstanceFieldSet 3156 /// CHECK-DAG: InstanceFieldSet 3157 /// CHECK-DAG: Phi 3158 /// CHECK-DAG: InstanceFieldSet 3159 3160 /// CHECK-START: int Main.testLoop24(TestClass, int) load_store_elimination (after) 3161 /// CHECK-DAG: InstanceFieldSet 3162 /// CHECK-DAG: Phi 3163 /// CHECK-DAG: Phi 3164 /// CHECK-DAG: InstanceFieldSet 3165 /// CHECK-DAG: InstanceFieldSet 3166 /// CHECK-DAG: Phi 3167 3168 /// CHECK-START: int Main.testLoop24(TestClass, int) load_store_elimination (after) 3169 /// CHECK: InstanceFieldSet 3170 /// CHECK: InstanceFieldSet 3171 /// CHECK: InstanceFieldSet 3172 /// CHECK-NOT: InstanceFieldSet 3173 3174 // Test matching Phis for store elimination. testLoop24(TestClass obj, int n)3175 static int testLoop24(TestClass obj, int n) { 3176 obj.i = -1; 3177 int phi = -1; 3178 for (int i = 0; i < n; ++i) { 3179 obj.i = i; 3180 phi = i; 3181 } 3182 if ((n & 1) != 0) { 3183 obj.i = 2; 3184 phi = 2; 3185 } 3186 if (n == 3) { 3187 return -2; // Make the above stores observable. 3188 } 3189 // As the stores above are observable and kept, we match the merged 3190 // heap value with existing Phis and determine that we're storing 3191 // the same value that's already there, so we eliminate this store. 3192 obj.i = phi; 3193 return phi; 3194 } 3195 3196 /// CHECK-START: int Main.testLoop25(TestClass, int) load_store_elimination (before) 3197 /// CHECK-DAG: InstanceFieldSet 3198 /// CHECK-DAG: Phi 3199 /// CHECK-DAG: Phi 3200 /// CHECK-DAG: InstanceFieldSet 3201 /// CHECK-DAG: Phi 3202 /// CHECK-DAG: InstanceFieldGet 3203 /// CHECK-DAG: InstanceFieldSet 3204 3205 /// CHECK-START: int Main.testLoop25(TestClass, int) load_store_elimination (after) 3206 /// CHECK-DAG: InstanceFieldSet 3207 /// CHECK-DAG: Phi 3208 /// CHECK-DAG: Phi 3209 /// CHECK-DAG: Phi 3210 /// CHECK-DAG: InstanceFieldSet 3211 /// CHECK-DAG: Phi 3212 /// CHECK-DAG: Phi 3213 /// CHECK-DAG: InstanceFieldSet 3214 3215 /// CHECK-START: int Main.testLoop25(TestClass, int) load_store_elimination (after) 3216 /// CHECK-NOT: InstanceFieldGet 3217 3218 // Test that we do not match multiple dependent Phis for load and store elimination. testLoop25(TestClass obj, int n)3219 static int testLoop25(TestClass obj, int n) { 3220 obj.i = 1; 3221 int phi = 1; 3222 for (int i = 0; i < n; ++i) { 3223 if ((i & 1) != 0) { 3224 obj.i = 2; 3225 phi = 2; 3226 } 3227 // There is a Phi here for the variable `phi` before the "++i". 3228 // This Phi and the loop Phi for `phi` depend on each other. 3229 } 3230 if (n == 3) { 3231 return -1; // Make above stores observable. 3232 } 3233 // We're not matching multiple Phi placeholders to existing Phis. Therefore the load 3234 // below requires 2 extra Phis to be created and the store below shall not be eliminated 3235 // even though it stores the same value that's already present in the heap location. 3236 int tmp = obj.i; 3237 obj.i = phi; 3238 return tmp + phi; 3239 } 3240 3241 /// CHECK-START: int Main.testLoop26(TestClass, int) load_store_elimination (before) 3242 /// CHECK-DAG: NewInstance 3243 /// CHECK-DAG: InstanceFieldSet 3244 /// CHECK-DAG: Phi 3245 /// CHECK-DAG: NewInstance 3246 /// CHECK-DAG: InstanceFieldSet 3247 /// CHECK-DAG: InstanceFieldGet 3248 /// CHECK-DAG: InstanceFieldGet 3249 3250 /// CHECK-START: int Main.testLoop26(TestClass, int) load_store_elimination (after) 3251 /// CHECK-DAG: NewInstance 3252 /// CHECK-DAG: InstanceFieldSet 3253 /// CHECK-DAG: Phi 3254 /// CHECK-DAG: Phi 3255 /// CHECK-DAG: NewInstance 3256 /// CHECK-DAG: InstanceFieldSet 3257 /// CHECK-DAG: InstanceFieldGet 3258 3259 /// CHECK-START: int Main.testLoop26(TestClass, int) load_store_elimination (after) 3260 /// CHECK: InstanceFieldGet 3261 /// CHECK-NOT: InstanceFieldGet 3262 3263 // Test load elimination creating a reference Phi. testLoop26(TestClass obj, int n)3264 static int testLoop26(TestClass obj, int n) { 3265 obj.next = new TestClass(1, 2); 3266 for (int i = 0; i < n; ++i) { 3267 obj.next = new SubTestClass(); 3268 } 3269 return obj.next.i; 3270 } 3271 3272 /// CHECK-START: int Main.testLoop27(TestClass, int) load_store_elimination (before) 3273 /// CHECK-DAG: NewInstance 3274 /// CHECK-DAG: InstanceFieldSet 3275 /// CHECK-DAG: Phi 3276 /// CHECK-DAG: NewInstance 3277 /// CHECK-DAG: InstanceFieldSet 3278 /// CHECK-DAG: InstanceFieldGet 3279 /// CHECK-DAG: InstanceFieldGet 3280 3281 /// CHECK-START: int Main.testLoop27(TestClass, int) load_store_elimination (after) 3282 /// CHECK-DAG: NewInstance 3283 /// CHECK-DAG: InstanceFieldSet 3284 /// CHECK-DAG: Phi 3285 /// CHECK-DAG: Phi 3286 /// CHECK-DAG: NewInstance 3287 /// CHECK-DAG: InstanceFieldSet 3288 /// CHECK-DAG: Phi 3289 /// CHECK-DAG: InstanceFieldGet 3290 3291 /// CHECK-START: int Main.testLoop27(TestClass, int) load_store_elimination (after) 3292 /// CHECK: InstanceFieldGet 3293 /// CHECK-NOT: InstanceFieldGet 3294 3295 // Test load elimination creating two reference Phis that depend on each other. testLoop27(TestClass obj, int n)3296 static int testLoop27(TestClass obj, int n) { 3297 obj.next = new TestClass(1, 2); 3298 for (int i = 0; i < n; ++i) { 3299 if ((i & 1) != 0) { 3300 obj.next = new SubTestClass(); 3301 } 3302 // There shall be a Phi created here for `obj.next` before the "++i". 3303 // This Phi and the loop Phi that shall be created for `obj.next` depend on each other. 3304 } 3305 return obj.next.i; 3306 } 3307 3308 /// CHECK-START: int Main.testLoop28(TestClass, int) load_store_elimination (before) 3309 /// CHECK-DAG: InstanceFieldSet 3310 /// CHECK-DAG: NewArray 3311 /// CHECK-DAG: Phi 3312 /// CHECK-DAG: ArrayGet 3313 /// CHECK-DAG: ArraySet 3314 /// CHECK-DAG: ArrayGet 3315 /// CHECK-DAG: ArraySet 3316 /// CHECK-DAG: InstanceFieldGet 3317 /// CHECK-DAG: ArraySet 3318 /// CHECK-DAG: ArrayGet 3319 3320 /// CHECK-START: int Main.testLoop28(TestClass, int) load_store_elimination (after) 3321 /// CHECK-DAG: InstanceFieldSet 3322 /// CHECK-DAG: Phi 3323 /// CHECK-DAG: Phi 3324 /// CHECK-DAG: Phi 3325 /// CHECK-DAG: Phi 3326 /// CHECK-DAG: InstanceFieldGet 3327 3328 /// CHECK-START: int Main.testLoop28(TestClass, int) load_store_elimination (after) 3329 /// CHECK-NOT: NewArray 3330 /// CHECK-NOT: ArrayGet 3331 /// CHECK-NOT: ArraySet 3332 3333 /// CHECK-START: int Main.testLoop28(TestClass, int) load_store_elimination (after) 3334 /// CHECK: Phi 3335 /// CHECK: Phi 3336 /// CHECK: Phi 3337 /// CHECK: Phi 3338 /// CHECK-NOT: Phi 3339 3340 // Test eliminating array allocation, loads and stores and creating loop Phis 3341 // after determining that a field load depending on loop Phi placeholder cannot 3342 // be eliminated. testLoop28(TestClass obj, int n)3343 private static int testLoop28(TestClass obj, int n) { 3344 obj.i = 1; 3345 int[] a = new int[3]; 3346 for (int i = 0; i < n; ++i) { 3347 a[0] = a[1]; 3348 a[1] = a[2]; 3349 a[2] = obj.i; 3350 $noinline$clobberObservables(); 3351 } 3352 return a[0]; 3353 } 3354 3355 /// CHECK-START: int Main.testLoop29(int) load_store_elimination (before) 3356 /// CHECK-DAG: NewArray 3357 /// CHECK-DAG: Phi 3358 /// CHECK-DAG: Phi 3359 /// CHECK-DAG: ArrayGet 3360 /// CHECK-DAG: ArraySet 3361 3362 /// CHECK-START: int Main.testLoop29(int) load_store_elimination (after) 3363 /// CHECK-DAG: NewArray 3364 /// CHECK-DAG: Phi 3365 /// CHECK-DAG: Phi 3366 /// CHECK-DAG: ArrayGet 3367 /// CHECK-DAG: ArraySet 3368 3369 // Test that ArraySet with non-default value prevents matching ArrayGet for 3370 // the same array to default value even when the ArraySet is using an index 3371 // offset by one, making LSA declare that the two heap locations do not alias. testLoop29(int n)3372 private static int testLoop29(int n) { 3373 int[] a = new int[4]; 3374 int sum = 0; 3375 for (int i = 0; i < n; ) { 3376 int value = a[i] + 1; 3377 sum += value; 3378 ++i; 3379 a[i] = value; 3380 } 3381 return sum; 3382 } 3383 3384 /// CHECK-START: int Main.testLoop30(int) load_store_elimination (before) 3385 /// CHECK-DAG: NewArray 3386 /// CHECK-DAG: Phi 3387 /// CHECK-DAG: Phi 3388 /// CHECK-DAG: ArrayGet 3389 /// CHECK-DAG: ArraySet 3390 3391 /// CHECK-START: int Main.testLoop30(int) load_store_elimination (after) 3392 /// CHECK-NOT: ArrayGet 3393 /// CHECK-NOT: ArraySet 3394 3395 // Test that ArraySet with default value does not prevent matching ArrayGet 3396 // for the same array to the default value. testLoop30(int n)3397 private static int testLoop30(int n) { 3398 int[] a = new int[4]; // NewArray is kept due to environment use by Deoptimize. 3399 int sum = 0; 3400 for (int i = 0; i < n; ) { 3401 int value = a[i] + 1; 3402 sum += value; 3403 ++i; 3404 a[i] = 0; 3405 } 3406 return sum; 3407 } 3408 3409 /// CHECK-START: int Main.testLoop31(int) load_store_elimination (before) 3410 /// CHECK-DAG: NewArray 3411 /// CHECK-DAG: Phi 3412 /// CHECK-DAG: Phi 3413 /// CHECK-DAG: ArrayGet 3414 /// CHECK-DAG: ArraySet 3415 3416 /// CHECK-START: int Main.testLoop31(int) load_store_elimination (after) 3417 /// CHECK-NOT: ArrayGet 3418 /// CHECK-NOT: ArraySet 3419 3420 // Test that ArraySet with default value read from the array does not 3421 // prevent matching ArrayGet for the same array to the default value. testLoop31(int n)3422 private static int testLoop31(int n) { 3423 int[] a = new int[4]; // NewArray is kept due to environment use by Deoptimize. 3424 int sum = 0; 3425 for (int i = 0; i < n; ) { 3426 int value = a[i]; 3427 sum += value; 3428 ++i; 3429 a[i] = value; 3430 } 3431 return sum; 3432 } 3433 3434 /// CHECK-START: int Main.testLoop32(TestClass, int) load_store_elimination (before) 3435 /// CHECK-DAG: InstanceFieldSet 3436 /// CHECK-DAG: Phi 3437 /// CHECK-DAG: Phi 3438 /// CHECK-DAG: InstanceFieldSet 3439 /// CHECK-DAG: InstanceFieldSet 3440 /// CHECK-DAG: Phi 3441 /// CHECK-DAG: InstanceFieldSet 3442 3443 /// CHECK-START: int Main.testLoop32(TestClass, int) load_store_elimination (after) 3444 /// CHECK-DAG: InstanceFieldSet 3445 /// CHECK-DAG: Phi 3446 /// CHECK-DAG: Phi 3447 /// CHECK-DAG: InstanceFieldSet 3448 /// CHECK-DAG: InstanceFieldSet 3449 /// CHECK-DAG: Phi 3450 3451 /// CHECK-START: int Main.testLoop32(TestClass, int) load_store_elimination (after) 3452 /// CHECK: InstanceFieldSet 3453 /// CHECK: InstanceFieldSet 3454 /// CHECK: InstanceFieldSet 3455 /// CHECK-NOT: InstanceFieldSet 3456 3457 // Test matching Phis for store elimination. testLoop32(TestClass obj, int n)3458 static int testLoop32(TestClass obj, int n) { 3459 obj.i = -1; 3460 int phi = -1; 3461 for (int i = 0; i < n; ) { 3462 ++i; 3463 if ((i & 1) != 0) { 3464 obj.i = i; 3465 phi = i; 3466 } 3467 } 3468 if ((n & 1) != 0) { 3469 obj.i = 2; 3470 phi = 2; 3471 } 3472 if (n == 3) { 3473 return -2; // Make the above stores observable. 3474 } 3475 // As the stores above are observable and kept, we match the merged 3476 // heap value with existing Phis and determine that we're storing 3477 // the same value that's already there, so we eliminate this store. 3478 obj.i = phi; 3479 return phi; 3480 } 3481 3482 // CHECK-START: int Main.testLoop33(TestClass, int) load_store_elimination (before) 3483 // CHECK-DAG: InstanceFieldSet 3484 // CHECK-DAG: NewArray 3485 // CHECK-DAG: Phi 3486 // CHECK-DAG: ArrayGet 3487 // CHECK-DAG: InstanceFieldSet 3488 // CHECK-DAG: Phi 3489 // CHECK-DAG: ArrayGet 3490 // CHECK-DAG: InstanceFieldGet 3491 // CHECK-DAG: InstanceFieldSet 3492 // CHECK-DAG: InstanceFieldGet 3493 3494 // CHECK-START: int Main.testLoop33(TestClass, int) load_store_elimination (after) 3495 // CHECK-DAG: InstanceFieldSet 3496 // CHECK-DAG: Phi 3497 // CHECK-DAG: InstanceFieldSet 3498 // CHECK-DAG: Phi 3499 // CHECK-DAG: InstanceFieldGet 3500 // CHECK-DAG: InstanceFieldSet 3501 // CHECK-DAG: InstanceFieldGet 3502 3503 // CHECK-START: int Main.testLoop33(TestClass, int) load_store_elimination (after) 3504 // CHECK-NOT: ArrayGet 3505 3506 // Test that when processing Phi placeholder with unknown input, we allow materialized 3507 // default value in pre-header for array location with index defined in the loop. testLoop33(TestClass obj, int n)3508 static int testLoop33(TestClass obj, int n) { 3509 obj.i = 0; 3510 int[] a0 = new int[n]; 3511 for (int i = 0; i < n; ++i) { 3512 obj.i = a0[i]; 3513 $noinline$clobberObservables(); // Make `obj.i` unknown. 3514 } 3515 for (int i = 0; i < n; ++i) { 3516 int zero = a0[i]; 3517 int unknown = obj.i; 3518 obj.j += zero + unknown; 3519 } 3520 return obj.j; 3521 } 3522 3523 /// CHECK-START: int Main.testLoop34(int) load_store_elimination (before) 3524 /// CHECK-DAG: NewArray 3525 /// CHECK-DAG: Phi 3526 /// CHECK-DAG: Phi 3527 /// CHECK-DAG: ArrayGet 3528 /// CHECK-DAG: ArraySet 3529 3530 /// CHECK-START: int Main.testLoop34(int) load_store_elimination (after) 3531 /// CHECK-DAG: NewArray 3532 /// CHECK-DAG: Phi 3533 /// CHECK-DAG: Phi 3534 /// CHECK-DAG: ArrayGet 3535 /// CHECK-DAG: ArraySet 3536 3537 // Test that ArraySet with non-default value prevents matching ArrayGet for 3538 // the same array to default value even when the ArraySet is using an index 3539 // offset by one, making LSA declare that the two heap locations do not alias. 3540 // Also test that the ArraySet is not eliminated. testLoop34(int n)3541 private static int testLoop34(int n) { 3542 int[] a = new int[n + 1]; 3543 int sum = 0; 3544 for (int i = 0; i < n; ) { 3545 int value = a[i] + 1; 3546 sum += value; 3547 ++i; 3548 a[i] = value; 3549 } 3550 return sum; 3551 } 3552 3553 /// CHECK-START: int Main.testLoop35(int) load_store_elimination (before) 3554 /// CHECK-DAG: NewArray 3555 /// CHECK-DAG: Phi 3556 /// CHECK-DAG: Phi 3557 /// CHECK-DAG: ArrayGet 3558 /// CHECK-DAG: ArraySet 3559 /// CHECK-DAG: ArraySet 3560 3561 /// CHECK-START: int Main.testLoop35(int) load_store_elimination (after) 3562 /// CHECK-DAG: NewArray 3563 /// CHECK-DAG: Phi 3564 /// CHECK-DAG: Phi 3565 /// CHECK-DAG: ArrayGet 3566 /// CHECK-DAG: ArraySet 3567 3568 /// CHECK-START: int Main.testLoop35(int) load_store_elimination (after) 3569 /// CHECK: ArraySet 3570 /// CHECK-NOT: ArraySet 3571 3572 // Test that ArraySet with non-default value prevents matching ArrayGet for 3573 // the same array to default value even when the ArraySet is using an index 3574 // offset by one, making LSA declare that the two heap locations do not alias. 3575 // Also test that the ArraySet is not eliminated and that a store after the 3576 // loop is eliminated. testLoop35(int n)3577 private static int testLoop35(int n) { 3578 int[] a = new int[n + 1]; 3579 int sum = 0; 3580 for (int i = 0; i < n; ) { 3581 int value = a[i] + 1; 3582 sum += value; 3583 ++i; 3584 a[i] = value; 3585 } 3586 a[0] = 1; 3587 return sum; 3588 } 3589 3590 /// CHECK-START: int Main.testLoop36(int) load_store_elimination (before) 3591 /// CHECK-DAG: ArraySet 3592 /// CHECK-DAG: Deoptimize 3593 /// CHECK-DAG: ArrayGet 3594 /// CHECK-DAG: ArrayGet 3595 /// CHECK-DAG: ArrayGet 3596 /// CHECK-DAG: ArrayGet 3597 3598 /// CHECK-START: int Main.testLoop36(int) load_store_elimination (before) 3599 /// CHECK-NOT: BoundsCheck 3600 3601 /// CHECK-START: int Main.testLoop36(int) load_store_elimination (after) 3602 /// CHECK-DAG: ArraySet 3603 /// CHECK-DAG: Deoptimize 3604 /// CHECK-DAG: ArrayGet 3605 /// CHECK-DAG: ArrayGet 3606 /// CHECK-DAG: ArrayGet 3607 /// CHECK-DAG: ArrayGet 3608 3609 // Regression test for b/187487955. 3610 // We previously failed a DCHECK() during the search for kept stores when 3611 // we encountered two array locations for the same array and considered 3612 // non-aliasing by LSA when only one of the array locations had index 3613 // defined inside the loop. Note that this situation requires that BCE 3614 // eliminates BoundsCheck instructions, otherwise LSA considers those 3615 // locations aliasing. testLoop36(int n)3616 private static int testLoop36(int n) { 3617 int[] a = new int[n]; 3618 int zero = 0; 3619 int i = 0; 3620 for (; i < n; ++i) { 3621 a[i] = i; 3622 // Extra instructions to avoid loop unrolling. 3623 zero = (((zero ^ 1) + 2) ^ 1) - 2; 3624 zero = (((zero ^ 4) + 8) ^ 4) - 8; 3625 } 3626 // Use 4 loads with consecutive fixed offsets from the loop Phi for `i`. 3627 // BCE shall replace BoundsChecks with Deoptimize, so that indexes here are 3628 // the Phi plus/minus a constant, something that LSA considers non-aliasing 3629 // with the Phi (LSA does not take different loop iterations into account) 3630 // but LSE must consider aliasing across dfferent loop iterations. 3631 return a[i - 1] + a[i - 2] + a[i - 3] + a[i - 4] + zero; 3632 } 3633 3634 /// CHECK-START: int Main.testLoop37(int) load_store_elimination (before) 3635 /// CHECK-DAG: ArraySet 3636 /// CHECK-DAG: Deoptimize 3637 /// CHECK-DAG: ArrayGet 3638 /// CHECK-DAG: ArrayGet 3639 /// CHECK-DAG: ArrayGet 3640 /// CHECK-DAG: ArrayGet 3641 3642 /// CHECK-START: int Main.testLoop37(int) load_store_elimination (before) 3643 /// CHECK-NOT: BoundsCheck 3644 3645 /// CHECK-START: int Main.testLoop37(int) load_store_elimination (after) 3646 /// CHECK-DAG: ArraySet 3647 /// CHECK-DAG: Deoptimize 3648 /// CHECK-DAG: ArrayGet 3649 /// CHECK-DAG: ArrayGet 3650 /// CHECK-DAG: ArrayGet 3651 /// CHECK-DAG: ArrayGet 3652 3653 // Similar to testLoop36 but the writes are done via a different reference to the same array. 3654 // We previously used a reference comparison for back-edge aliasing analysis but this test 3655 // has different references and therefore needs `HeapLocationCollector::CanReferencesAlias()`. testLoop37(int n)3656 private static int testLoop37(int n) { 3657 int[] a = new int[n]; 3658 int[] b = $noinline$returnArg(a); 3659 int zero = 0; 3660 int i = 0; 3661 for (; i < n; ++i) { 3662 b[i] = i; 3663 // Extra instructions to avoid loop unrolling. 3664 zero = (((zero ^ 1) + 2) ^ 1) - 2; 3665 zero = (((zero ^ 4) + 8) ^ 4) - 8; 3666 } 3667 // Use 4 loads with consecutive fixed offsets from the loop Phi for `i`. 3668 // BCE shall replace BoundsChecks with Deoptimize, so that indexes here are 3669 // the Phi plus/minus a constant, something that LSA considers non-aliasing 3670 // with the Phi (LSA does not take different loop iterations into account) 3671 // but LSE must consider aliasing across dfferent loop iterations. 3672 return a[i - 1] + a[i - 2] + a[i - 3] + a[i - 4] + zero; 3673 } 3674 $noinline$returnArg(int[] a)3675 private static int[] $noinline$returnArg(int[] a) { 3676 return a; 3677 } 3678 3679 /// CHECK-START: int Main.testLoop38(int, int[]) load_store_elimination (before) 3680 /// CHECK-DAG: ArraySet 3681 /// CHECK-DAG: Deoptimize 3682 /// CHECK-DAG: ArrayGet 3683 /// CHECK-DAG: ArrayGet 3684 /// CHECK-DAG: ArrayGet 3685 /// CHECK-DAG: ArrayGet 3686 3687 /// CHECK-START: int Main.testLoop38(int, int[]) load_store_elimination (before) 3688 /// CHECK-NOT: BoundsCheck 3689 3690 /// CHECK-START: int Main.testLoop38(int, int[]) load_store_elimination (after) 3691 /// CHECK-DAG: ArraySet 3692 /// CHECK-DAG: Deoptimize 3693 3694 /// CHECK-START: int Main.testLoop38(int, int[]) load_store_elimination (after) 3695 /// CHECK-NOT: ArrayGet 3696 3697 // Similar to testLoop37 but writing to a different array that exists before allocating `a`, 3698 // so that `HeapLocationCollector::CanReferencesAlias()` returns false and all the ArrayGet 3699 // instructions are actually eliminated. testLoop38(int n, int[] b)3700 private static int testLoop38(int n, int[] b) { 3701 int[] a = new int[n]; 3702 int zero = 0; 3703 int i = 0; 3704 for (; i < n; ++i) { 3705 b[i] = i; 3706 // Extra instructions to avoid loop unrolling. 3707 zero = (((zero ^ 1) + 2) ^ 1) - 2; 3708 zero = (((zero ^ 4) + 8) ^ 4) - 8; 3709 } 3710 // Use 4 loads with consecutive fixed offsets from the loop Phi for `i`. 3711 // BCE shall replace BoundsChecks with Deoptimize, so that indexes here are 3712 // the Phi plus/minus a constant, something that LSA considers non-aliasing 3713 // with the Phi (LSA does not take different loop iterations into account) 3714 // but LSE must consider aliasing across dfferent loop iterations. 3715 return a[i - 1] + a[i - 2] + a[i - 3] + a[i - 4] + zero; 3716 } 3717 3718 /// CHECK-START: int Main.testNestedLoop1(TestClass, int) load_store_elimination (before) 3719 /// CHECK-DAG: InstanceFieldSet 3720 /// CHECK-DAG: InstanceFieldGet 3721 3722 /// CHECK-START: int Main.testNestedLoop1(TestClass, int) load_store_elimination (after) 3723 /// CHECK-DAG: InstanceFieldSet 3724 /// CHECK-DAG: InstanceFieldGet 3725 3726 // Test heap value clobbering in nested loop. testNestedLoop1(TestClass obj, int n)3727 private static int testNestedLoop1(TestClass obj, int n) { 3728 obj.i = 1; 3729 for (int i = 0; i < n; ++i) { 3730 for (int j = i + 1; j < n; ++j) { 3731 $noinline$clobberObservables(); 3732 } 3733 } 3734 return obj.i; 3735 } 3736 3737 /// CHECK-START: int Main.testNestedLoop2(TestClass, int) load_store_elimination (before) 3738 /// CHECK-DAG: InstanceFieldSet 3739 /// CHECK-DAG: InstanceFieldSet 3740 /// CHECK-DAG: Phi 3741 /// CHECK-DAG: InstanceFieldGet 3742 /// CHECK-DAG: Phi 3743 /// CHECK-DAG: InstanceFieldSet 3744 /// CHECK-DAG: InstanceFieldGet 3745 3746 /// CHECK-START: int Main.testNestedLoop2(TestClass, int) load_store_elimination (after) 3747 /// CHECK-DAG: InstanceFieldSet 3748 /// CHECK-DAG: InstanceFieldSet 3749 /// CHECK-DAG: Phi 3750 /// CHECK-DAG: Phi 3751 /// CHECK-DAG: InstanceFieldGet 3752 /// CHECK-DAG: Phi 3753 /// CHECK-DAG: InstanceFieldSet 3754 3755 /// CHECK-START: int Main.testNestedLoop2(TestClass, int) load_store_elimination (after) 3756 /// CHECK: InstanceFieldGet 3757 /// CHECK-NOT: InstanceFieldGet 3758 3759 /// CHECK-START: int Main.testNestedLoop2(TestClass, int) load_store_elimination (after) 3760 /// CHECK: Phi 3761 /// CHECK: Phi 3762 /// CHECK: Phi 3763 /// CHECK-NOT: Phi 3764 3765 // Test heap value clobbering in the nested loop and load elimination for a heap 3766 // location then set to known value before the end of the outer loop. testNestedLoop2(TestClass obj, int n)3767 private static int testNestedLoop2(TestClass obj, int n) { 3768 obj.i = 1; 3769 obj.j = 2; 3770 for (int i = 0; i < n; ++i) { 3771 int tmp = obj.j; 3772 for (int j = i + 1; j < n; ++j) { 3773 $noinline$clobberObservables(); 3774 } 3775 obj.i = tmp; 3776 } 3777 return obj.i; 3778 } 3779 3780 /// CHECK-START: int Main.testNestedLoop3(TestClass, int) load_store_elimination (before) 3781 /// CHECK-DAG: InstanceFieldSet 3782 /// CHECK-DAG: Phi 3783 /// CHECK-DAG: InstanceFieldSet 3784 /// CHECK-DAG: Phi 3785 /// CHECK-DAG: InstanceFieldGet 3786 /// CHECK-DAG: InstanceFieldSet 3787 /// CHECK-DAG: InstanceFieldGet 3788 3789 /// CHECK-START: int Main.testNestedLoop3(TestClass, int) load_store_elimination (after) 3790 /// CHECK-DAG: InstanceFieldSet 3791 /// CHECK-DAG: Phi 3792 /// CHECK-DAG: Phi 3793 /// CHECK-DAG: InstanceFieldSet 3794 /// CHECK-DAG: Phi 3795 /// CHECK-DAG: InstanceFieldGet 3796 /// CHECK-DAG: InstanceFieldSet 3797 3798 /// CHECK-START: int Main.testNestedLoop3(TestClass, int) load_store_elimination (after) 3799 /// CHECK: InstanceFieldGet 3800 /// CHECK-NOT: InstanceFieldGet 3801 3802 /// CHECK-START: int Main.testNestedLoop3(TestClass, int) load_store_elimination (after) 3803 /// CHECK: Phi 3804 /// CHECK: Phi 3805 /// CHECK: Phi 3806 /// CHECK-NOT: Phi 3807 3808 // Test heap value clobbering in the nested loop and load elimination for a heap 3809 // location then set to known value before the end of the outer loop. testNestedLoop3(TestClass obj, int n)3810 private static int testNestedLoop3(TestClass obj, int n) { 3811 obj.i = 1; 3812 for (int i = 0; i < n; ++i) { 3813 obj.j = 2; 3814 for (int j = i + 1; j < n; ++j) { 3815 $noinline$clobberObservables(); 3816 } 3817 obj.i = obj.j; 3818 } 3819 return obj.i; 3820 } 3821 3822 /// CHECK-START: int Main.testNestedLoop4(TestClass, int) load_store_elimination (before) 3823 /// CHECK-DAG: InstanceFieldSet 3824 /// CHECK-DAG: Phi 3825 /// CHECK-DAG: Phi 3826 /// CHECK-DAG: InstanceFieldSet 3827 /// CHECK-DAG: InstanceFieldGet 3828 3829 /// CHECK-START: int Main.testNestedLoop4(TestClass, int) load_store_elimination (after) 3830 /// CHECK-DAG: InstanceFieldSet 3831 /// CHECK-DAG: Phi 3832 /// CHECK-DAG: Phi 3833 /// CHECK-DAG: Phi 3834 /// CHECK-DAG: Phi 3835 /// CHECK-DAG: InstanceFieldSet 3836 3837 /// CHECK-START: int Main.testNestedLoop4(TestClass, int) load_store_elimination (after) 3838 /// CHECK-NOT: InstanceFieldGet 3839 3840 /// CHECK-START: int Main.testNestedLoop4(TestClass, int) load_store_elimination (after) 3841 /// CHECK: Phi 3842 /// CHECK: Phi 3843 /// CHECK: Phi 3844 /// CHECK: Phi 3845 /// CHECK-NOT: Phi 3846 3847 // Test creating loop Phis for both inner and outer loop to eliminate a load. testNestedLoop4(TestClass obj, int n)3848 private static int testNestedLoop4(TestClass obj, int n) { 3849 obj.i = 1; 3850 for (int i = 0; i < n; ++i) { 3851 for (int j = i + 1; j < n; ++j) { 3852 obj.i = 2; 3853 } 3854 } 3855 return obj.i; 3856 } 3857 3858 /// CHECK-START: int Main.testNestedLoop5(TestClass, int) load_store_elimination (before) 3859 /// CHECK-DAG: InstanceFieldSet 3860 /// CHECK-DAG: Phi 3861 /// CHECK-DAG: InstanceFieldSet 3862 /// CHECK-DAG: Phi 3863 /// CHECK-DAG: InstanceFieldSet 3864 /// CHECK-DAG: InstanceFieldGet 3865 3866 /// CHECK-START: int Main.testNestedLoop5(TestClass, int) load_store_elimination (after) 3867 /// CHECK-DAG: InstanceFieldSet 3868 /// CHECK-DAG: Phi 3869 /// CHECK-DAG: Phi 3870 /// CHECK-DAG: InstanceFieldSet 3871 /// CHECK-DAG: Phi 3872 /// CHECK-DAG: InstanceFieldSet 3873 3874 /// CHECK-START: int Main.testNestedLoop5(TestClass, int) load_store_elimination (after) 3875 /// CHECK-NOT: InstanceFieldGet 3876 3877 /// CHECK-START: int Main.testNestedLoop5(TestClass, int) load_store_elimination (after) 3878 /// CHECK: Phi 3879 /// CHECK: Phi 3880 /// CHECK: Phi 3881 /// CHECK-NOT: Phi 3882 3883 // Test creating a loop Phi for outer loop to eliminate a load. testNestedLoop5(TestClass obj, int n)3884 private static int testNestedLoop5(TestClass obj, int n) { 3885 obj.i = 1; 3886 for (int i = 0; i < n; ++i) { 3887 obj.i = 2; 3888 for (int j = i + 1; j < n; ++j) { 3889 obj.j = 3; // Unrelated. 3890 } 3891 } 3892 return obj.i; 3893 } 3894 3895 /// CHECK-START: int Main.testNestedLoop6(TestClass, int) load_store_elimination (before) 3896 /// CHECK-DAG: InstanceFieldSet 3897 /// CHECK-DAG: InstanceFieldSet 3898 /// CHECK-DAG: Phi 3899 /// CHECK-DAG: Phi 3900 /// CHECK-DAG: InstanceFieldGet 3901 /// CHECK-DAG: InstanceFieldSet 3902 /// CHECK-DAG: InstanceFieldGet 3903 3904 /// CHECK-START: int Main.testNestedLoop6(TestClass, int) load_store_elimination (after) 3905 /// CHECK-DAG: InstanceFieldSet 3906 /// CHECK-DAG: InstanceFieldSet 3907 /// CHECK-DAG: Phi 3908 /// CHECK-DAG: Phi 3909 /// CHECK-DAG: Phi 3910 /// CHECK-DAG: Phi 3911 /// CHECK-DAG: InstanceFieldGet 3912 /// CHECK-DAG: InstanceFieldSet 3913 3914 /// CHECK-START: int Main.testNestedLoop6(TestClass, int) load_store_elimination (after) 3915 /// CHECK: InstanceFieldGet 3916 /// CHECK-NOT: InstanceFieldGet 3917 3918 /// CHECK-START: int Main.testNestedLoop6(TestClass, int) load_store_elimination (after) 3919 /// CHECK: Phi 3920 /// CHECK: Phi 3921 /// CHECK: Phi 3922 /// CHECK: Phi 3923 /// CHECK-NOT: Phi 3924 3925 // Test heap value clobbering in the nested loop and load elimination for a heap 3926 // location then set to known value before the end of that inner loop. testNestedLoop6(TestClass obj, int n)3927 private static int testNestedLoop6(TestClass obj, int n) { 3928 obj.i = 1; 3929 obj.j = 2; 3930 for (int i = 0; i < n; ++i) { 3931 for (int j = i + 1; j < n; ++j) { 3932 int tmp = obj.j; 3933 $noinline$clobberObservables(); 3934 obj.i = tmp; 3935 } 3936 } 3937 return obj.i; 3938 } 3939 3940 /// CHECK-START: int Main.testNestedLoop7(TestClass, int) load_store_elimination (before) 3941 /// CHECK-DAG: NewArray 3942 /// CHECK-DAG: Phi 3943 /// CHECK-DAG: Phi 3944 /// CHECK-DAG: ArrayGet 3945 /// CHECK-DAG: InstanceFieldSet 3946 3947 /// CHECK-START: int Main.testNestedLoop7(TestClass, int) load_store_elimination (after) 3948 /// CHECK-DAG: NewArray 3949 /// CHECK-DAG: Phi 3950 /// CHECK-DAG: Phi 3951 /// CHECK-DAG: InstanceFieldSet 3952 3953 /// CHECK-START: int Main.testNestedLoop7(TestClass, int) load_store_elimination (after) 3954 /// CHECK-NOT: ArrayGet 3955 3956 // Test load elimination in inner loop reading default value that is loop invariant 3957 // with an index defined inside the inner loop. testNestedLoop7(TestClass obj, int n)3958 private static int testNestedLoop7(TestClass obj, int n) { 3959 // The NewArray is kept as it may throw for negative n. 3960 // TODO: Eliminate constructor fence even though the NewArray is kept. 3961 int[] a0 = new int[n]; 3962 for (int i = 0; i < n; ++i) { 3963 for (int j = i + 1; j < n; ++j) { 3964 obj.i = a0[j]; 3965 } 3966 } 3967 return n; 3968 } 3969 3970 /// CHECK-START: int Main.testNestedLoop8(TestClass, int) load_store_elimination (before) 3971 /// CHECK-DAG: NewInstance 3972 /// CHECK-DAG: InstanceFieldSet 3973 /// CHECK-DAG: Phi 3974 /// CHECK-DAG: Phi 3975 /// CHECK-DAG: NewInstance 3976 /// CHECK-DAG: InstanceFieldSet 3977 /// CHECK-DAG: InstanceFieldGet 3978 /// CHECK-DAG: InstanceFieldGet 3979 3980 /// CHECK-START: int Main.testNestedLoop8(TestClass, int) load_store_elimination (after) 3981 /// CHECK-DAG: NewInstance 3982 /// CHECK-DAG: InstanceFieldSet 3983 /// CHECK-DAG: Phi 3984 /// CHECK-DAG: Phi 3985 /// CHECK-DAG: Phi 3986 /// CHECK-DAG: Phi 3987 /// CHECK-DAG: NewInstance 3988 /// CHECK-DAG: InstanceFieldSet 3989 /// CHECK-DAG: InstanceFieldGet 3990 3991 /// CHECK-START: int Main.testNestedLoop8(TestClass, int) load_store_elimination (after) 3992 /// CHECK: InstanceFieldGet 3993 /// CHECK-NOT: InstanceFieldGet 3994 3995 // Test reference type propagation for Phis created for outer and inner loop. testNestedLoop8(TestClass obj, int n)3996 private static int testNestedLoop8(TestClass obj, int n) { 3997 obj.next = new SubTestClass(); 3998 for (int i = 0; i < n; ++i) { 3999 for (int j = i + 1; j < n; ++j) { 4000 obj.next = new TestClass(); 4001 } 4002 } 4003 // The Phis created in both loop headers for replacing `obj.next` depend on each other. 4004 return obj.next.i; 4005 } 4006 4007 4008 /// CHECK-START: long Main.testOverlapLoop(int) load_store_elimination (before) 4009 /// CHECK-DAG: NewArray 4010 /// CHECK-DAG: ArraySet 4011 /// CHECK-DAG: If 4012 /// CHECK-DAG: ArrayGet 4013 /// CHECK-DAG: ArrayGet 4014 /// CHECK-DAG: ArraySet 4015 /// CHECK-DAG: ArrayGet 4016 /// CHECK-DAG: Goto 4017 4018 /// CHECK-START: long Main.testOverlapLoop(int) load_store_elimination (after) 4019 /// CHECK-DAG: NewArray 4020 /// CHECK-DAG: ArraySet 4021 /// CHECK-DAG: If 4022 /// CHECK-DAG: ArrayGet 4023 /// CHECK-DAG: ArrayGet 4024 /// CHECK-DAG: ArraySet 4025 /// CHECK-DAG: Goto 4026 /// CHECK-NOT: ArrayGet 4027 4028 // Test that we don't incorrectly remove writes needed by later loop iterations 4029 // NB This is fibonacci numbers testOverlapLoop(int cnt)4030 private static long testOverlapLoop(int cnt) { 4031 long[] w = new long[cnt]; 4032 w[1] = 1; 4033 long t = 1; 4034 for (int i = 2; i < cnt; ++i) { 4035 w[i] = w[i - 1] + w[i - 2]; 4036 t = w[i]; 4037 } 4038 return t; 4039 } 4040 $noinline$getBoolean(boolean val)4041 private static boolean $noinline$getBoolean(boolean val) { 4042 return val; 4043 } 4044 4045 /// CHECK-START: int Main.$noinline$testPartialEscape1(TestClass, boolean) load_store_elimination (before) 4046 /// CHECK-DAG: ParameterValue 4047 /// CHECK-DAG: NewInstance 4048 /// CHECK-DAG: InvokeStaticOrDirect 4049 /// CHECK-DAG: InstanceFieldSet 4050 /// CHECK-DAG: InvokeStaticOrDirect 4051 /// CHECK-DAG: InstanceFieldGet 4052 /// CHECK-DAG: InstanceFieldGet 4053 /// CHECK-DAG: InstanceFieldSet 4054 /// CHECK-DAG: InstanceFieldGet 4055 /// CHECK-DAG: InstanceFieldGet 4056 /// CHECK-DAG: Phi 4057 // 4058 /// CHECK-NOT: NewInstance 4059 /// CHECK-NOT: InvokeStaticOrDirect 4060 /// CHECK-NOT: InstanceFieldSet 4061 /// CHECK-NOT: InstanceFieldGet 4062 // 4063 /// CHECK-START: int Main.$noinline$testPartialEscape1(TestClass, boolean) load_store_elimination (after) 4064 /// CHECK-DAG: ParameterValue 4065 /// CHECK-DAG: NewInstance 4066 /// CHECK-DAG: Phi 4067 // 4068 /// CHECK-START: int Main.$noinline$testPartialEscape1(TestClass, boolean) load_store_elimination (after) 4069 /// CHECK: InvokeStaticOrDirect 4070 /// CHECK: InvokeStaticOrDirect 4071 // 4072 /// CHECK-NOT: InvokeStaticOrDirect 4073 4074 /// CHECK-START: int Main.$noinline$testPartialEscape1(TestClass, boolean) load_store_elimination (after) 4075 /// CHECK: InstanceFieldSet 4076 // 4077 // TODO: We should be able to remove this setter by realizing `i` only escapes in a branch. 4078 /// CHECK: InstanceFieldSet 4079 /// CHECK-NOT: InstanceFieldSet 4080 // 4081 /// CHECK-START: int Main.$noinline$testPartialEscape1(TestClass, boolean) load_store_elimination (after) 4082 /// CHECK: InstanceFieldGet 4083 /// CHECK: InstanceFieldGet 4084 /// CHECK: InstanceFieldGet 4085 // 4086 /// CHECK-NOT: InstanceFieldGet $noinline$testPartialEscape1(TestClass obj, boolean escape)4087 private static int $noinline$testPartialEscape1(TestClass obj, boolean escape) { 4088 TestClass i = new SubTestClass(); 4089 int res; 4090 if ($noinline$getBoolean(escape)) { 4091 i.next = obj; 4092 $noinline$Escape(i); 4093 res = i.next.i; 4094 } else { 4095 i.next = obj; 4096 res = i.next.i; 4097 } 4098 return res; 4099 } 4100 $noinline$clobberObservables()4101 private static void $noinline$clobberObservables() {} 4102 assertLongEquals(long result, long expected)4103 static void assertLongEquals(long result, long expected) { 4104 if (expected != result) { 4105 throw new Error("Expected: " + expected + ", found: " + result); 4106 } 4107 } 4108 assertIntEquals(int result, int expected)4109 static void assertIntEquals(int result, int expected) { 4110 if (expected != result) { 4111 throw new Error("Expected: " + expected + ", found: " + result); 4112 } 4113 } 4114 assertFloatEquals(float result, float expected)4115 static void assertFloatEquals(float result, float expected) { 4116 if (expected != result) { 4117 throw new Error("Expected: " + expected + ", found: " + result); 4118 } 4119 } 4120 assertDoubleEquals(double result, double expected)4121 static void assertDoubleEquals(double result, double expected) { 4122 if (expected != result) { 4123 throw new Error("Expected: " + expected + ", found: " + result); 4124 } 4125 } 4126 main(String[] args)4127 public static void main(String[] args) { 4128 assertDoubleEquals(Math.PI * Math.PI * Math.PI, calcCircleArea(Math.PI)); 4129 assertIntEquals(test1(new TestClass(), new TestClass()), 3); 4130 assertIntEquals(test2(new TestClass()), 1); 4131 TestClass obj1 = new TestClass(); 4132 TestClass obj2 = new TestClass(); 4133 obj1.next = obj2; 4134 assertIntEquals(test3(obj1), 10); 4135 assertIntEquals(test4(new TestClass(), true), 1); 4136 assertIntEquals(test4(new TestClass(), false), 1); 4137 assertIntEquals(test5(new TestClass(), true), 1); 4138 assertIntEquals(test5(new TestClass(), false), 2); 4139 assertIntEquals(test6(new TestClass(), new TestClass(), true), 4); 4140 assertIntEquals(test6(new TestClass(), new TestClass(), false), 2); 4141 assertIntEquals(test7(new TestClass()), 1); 4142 assertIntEquals(test8(), 1); 4143 obj1 = new TestClass(); 4144 obj2 = new TestClass(); 4145 obj1.next = obj2; 4146 assertIntEquals(test9(new TestClass()), 1); 4147 assertIntEquals(test10(new TestClass(3, 4)), 3); 4148 assertIntEquals(TestClass.si, 3); 4149 assertIntEquals(test11(new TestClass()), 10); 4150 assertIntEquals(test12(new TestClass(), new TestClass()), 10); 4151 assertIntEquals(test13(new TestClass(), new TestClass2()), 3); 4152 SubTestClass obj3 = new SubTestClass(); 4153 assertIntEquals(test14(obj3, obj3), 2); 4154 assertIntEquals(test15(), 2); 4155 assertIntEquals(test16(), 3); 4156 assertIntEquals(test17(), 0); 4157 assertIntEquals(test18(new TestClass()), 1); 4158 float[] fa1 = { 0.8f }; 4159 float[] fa2 = { 1.8f }; 4160 assertFloatEquals(test19(fa1, fa2), 1.8f); 4161 assertFloatEquals(test20().i, 0); 4162 test21(new TestClass()); 4163 assertIntEquals(test22(), 13); 4164 assertIntEquals(test23(true), 4); 4165 assertIntEquals(test23(false), 5); 4166 assertFloatEquals(test24(), 8.0f); 4167 assertIntEquals(test25(false, true, true), 5); 4168 assertIntEquals(test25(true, false, true), 2); 4169 assertFloatEquals(test26(5), 0.0f); 4170 assertFloatEquals(test26(3), 1.0f); 4171 assertIntEquals(test27(false, true), 1); 4172 assertIntEquals(test27(true, false), 1); 4173 assertIntEquals(test28(false, true), 0); 4174 assertIntEquals(test28(true, true), 5); 4175 assertFloatEquals(test29(true), 5.0f); 4176 assertFloatEquals(test29(false), 2.0f); 4177 assertIntEquals(test30(new TestClass(), true), 1); 4178 assertIntEquals(test30(new TestClass(), false), 0); 4179 assertIntEquals(test31(true, true), 5); 4180 assertIntEquals(test31(true, false), 6); 4181 assertIntEquals(test32(1), 10); 4182 assertIntEquals(test32(2), 10); 4183 assertIntEquals(test33(new TestClass(), true), 1); 4184 assertIntEquals(test33(new TestClass(), false), 2); 4185 assertIntEquals(test34(new TestClass(), true, true), 3); 4186 assertIntEquals(test34(new TestClass(), false, true), 4); 4187 assertIntEquals(test34(new TestClass(), true, false), 1); 4188 assertIntEquals(test34(new TestClass(), false, false), 2); 4189 assertIntEquals(test35(new TestClass(), true, true), 3); 4190 assertIntEquals(test35(new TestClass(), false, true), 2); 4191 assertIntEquals(test35(new TestClass(), true, false), 1); 4192 assertIntEquals(test35(new TestClass(), false, false), 2); 4193 assertIntEquals(test36(new TestClass(), true), 2); 4194 assertIntEquals(test36(new TestClass(), false), 4); 4195 assertIntEquals(test37(new TestClass(), true), 1); 4196 assertIntEquals(test37(new TestClass(), false), 0); 4197 assertIntEquals(test38(new TestClass(), true), 1); 4198 assertIntEquals(test38(new TestClass(), false), 2); 4199 assertIntEquals(test39(new TestClass(), true), 0); 4200 assertIntEquals(test39(new TestClass(), false), 1); 4201 assertIntEquals(test40(), 150); 4202 4203 testFinalizableByForcingGc(); 4204 testFinalizableWithLoopByForcingGc(); 4205 assertIntEquals($noinline$testHSelect(true), 0xdead); 4206 int[] array = {2, 5, 9, -1, -3, 10, 8, 4}; 4207 assertIntEquals(sumWithinRange(array, 1, 5), 11); 4208 assertFloatEquals(testAllocationEliminationWithLoops(), 1.0f); 4209 assertFloatEquals(mF, 0f); 4210 assertDoubleEquals(Math.PI * Math.PI * Math.PI, getCircleArea(Math.PI, true)); 4211 assertDoubleEquals(0d, getCircleArea(Math.PI, false)); 4212 4213 assertIntEquals($noinline$testConversion1(new TestClass(), 300), 300); 4214 assertIntEquals($noinline$testConversion1(new TestClass(), 301), 45); 4215 assertIntEquals($noinline$testConversion2(new TestClass(), 300), 300); 4216 assertIntEquals($noinline$testConversion2(new TestClass(), 301), 90); 4217 assertIntEquals($noinline$testConversion3(new TestClass(), 0), 0); 4218 assertIntEquals($noinline$testConversion3(new TestClass(), 1), 0); 4219 assertIntEquals($noinline$testConversion3(new TestClass(), 128), 127); 4220 assertIntEquals($noinline$testConversion3(new TestClass(), 129), -128); 4221 assertIntEquals($noinline$testConversion4(new TestClass(), 0), 0); 4222 assertIntEquals($noinline$testConversion4(new TestClass(), 1), 0); 4223 assertIntEquals($noinline$testConversion4(new TestClass(), 128), 254); 4224 assertIntEquals($noinline$testConversion4(new TestClass(), 129), -256); 4225 4226 int[] iarray = {0, 0, 0}; 4227 double[] darray = {0d, 0d, 0d}; 4228 try { 4229 assertDoubleEquals(Math.PI * Math.PI * Math.PI, testDeoptimize(iarray, darray, Math.PI)); 4230 } catch (Exception e) { 4231 System.out.println(e.getClass().getName()); 4232 } 4233 assertIntEquals(iarray[0], 1); 4234 assertIntEquals(iarray[1], 1); 4235 assertIntEquals(iarray[2], 1); 4236 assertDoubleEquals(darray[0], Math.PI); 4237 assertDoubleEquals(darray[1], Math.PI); 4238 assertDoubleEquals(darray[2], Math.PI); 4239 4240 assertIntEquals(testAllocationEliminationOfArray1(), 11); 4241 assertIntEquals(testAllocationEliminationOfArray2(), 11); 4242 assertIntEquals(testAllocationEliminationOfArray3(2), 4); 4243 assertIntEquals(testAllocationEliminationOfArray4(2), 6); 4244 assertIntEquals(testAllocationEliminationOfArray5(2), 12); 4245 try { 4246 testAllocationEliminationOfArray5(-2); 4247 } catch (NegativeArraySizeException e) { 4248 System.out.println("Got NegativeArraySizeException."); 4249 } 4250 assertIntEquals(testAllocationEliminationOfArray6(true), 11); 4251 4252 assertIntEquals(testStoreStore().i, 41); 4253 assertIntEquals(testStoreStore().j, 43); 4254 4255 assertIntEquals(testExitMerge(true), 2); 4256 assertIntEquals(testExitMerge2(true), 2); 4257 assertIntEquals(testExitMerge2(false), 2); 4258 4259 TestClass2 testclass2 = new TestClass2(); 4260 testStoreStore2(testclass2); 4261 assertIntEquals(testclass2.i, 43); 4262 assertIntEquals(testclass2.j, 44); 4263 4264 testStoreStore3(testclass2, true); 4265 assertIntEquals(testclass2.i, 41); 4266 assertIntEquals(testclass2.j, 43); 4267 testStoreStore3(testclass2, false); 4268 assertIntEquals(testclass2.i, 41); 4269 assertIntEquals(testclass2.j, 44); 4270 4271 testStoreStore4(); 4272 assertIntEquals(TestClass.si, 62); 4273 4274 int ret = testStoreStore5(testclass2, testclass2); 4275 assertIntEquals(testclass2.i, 72); 4276 assertIntEquals(ret, 71); 4277 4278 testclass2.j = 88; 4279 ret = testStoreStore6(testclass2, testclass2); 4280 assertIntEquals(testclass2.i, 82); 4281 assertIntEquals(ret, 88); 4282 4283 ret = testNoSideEffects(iarray); 4284 assertIntEquals(iarray[0], 101); 4285 assertIntEquals(iarray[1], 103); 4286 assertIntEquals(ret, 108); 4287 4288 try { 4289 testThrow(testclass2, new Exception()); 4290 } catch (Exception e) {} 4291 assertIntEquals(testclass2.i, 55); 4292 4293 assertIntEquals(testStoreStoreWithDeoptimize(new int[4]), 4); 4294 4295 assertIntEquals($noinline$testByteArrayDefaultValue(), 0); 4296 4297 assertIntEquals(testLocalArrayMerge1(true), 1); 4298 assertIntEquals(testLocalArrayMerge1(false), 1); 4299 assertIntEquals(testLocalArrayMerge2(true), 2); 4300 assertIntEquals(testLocalArrayMerge2(false), 3); 4301 assertIntEquals(testLocalArrayMerge3(true), 2); 4302 assertIntEquals(testLocalArrayMerge3(false), 1); 4303 assertIntEquals(testLocalArrayMerge4(true), 2); 4304 assertIntEquals(testLocalArrayMerge4(false), 2); 4305 assertIntEquals(testLocalArrayMerge5(new int[]{ 7 }, true), 7); 4306 assertIntEquals(testLocalArrayMerge5(new int[]{ 9 }, false), 9); 4307 assertIntEquals(testLocalArrayMerge6(new int[1], true, true), 1); 4308 assertIntEquals(testLocalArrayMerge6(new int[1], true, false), 2); 4309 assertIntEquals(testLocalArrayMerge6(new int[1], false, true), 2); 4310 assertIntEquals(testLocalArrayMerge6(new int[1], false, false), 1); 4311 assertIntEquals(testLocalArrayMerge7(new int[2], true, true), 1); 4312 assertIntEquals(testLocalArrayMerge7(new int[2], true, false), 2); 4313 assertIntEquals(testLocalArrayMerge7(new int[2], false, true), 0); 4314 assertIntEquals(testLocalArrayMerge7(new int[2], false, false), 0); 4315 assertIntEquals(testLocalArrayMerge8(true), 0); 4316 assertIntEquals(testLocalArrayMerge8(false), 0); 4317 4318 TestClass[] tca = new TestClass[] { new TestClass(), null }; 4319 try { 4320 $noinline$testThrowingArraySet(tca, new TestClass2()); 4321 } catch (ArrayStoreException expected) { 4322 if (tca[0] != null) { 4323 throw new Error("tca[0] is not null"); 4324 } 4325 if (tca[1] == null) { 4326 throw new Error("tca[1] is null"); 4327 } 4328 } 4329 4330 assertIntEquals(testLoop1(new TestClass(), 0), 0); 4331 assertIntEquals(testLoop1(new TestClass(), 1), 0); 4332 assertIntEquals(testLoop1(new TestClass(), 2), 1); 4333 assertIntEquals(testLoop1(new TestClass(), 3), 2); 4334 assertIntEquals(testLoop2(new TestClass(), 0), 1); 4335 assertIntEquals(testLoop2(new TestClass(), 1), 1); 4336 assertIntEquals(testLoop2(new TestClass(), 2), 1); 4337 assertIntEquals(testLoop2(new TestClass(), 3), 1); 4338 assertIntEquals(testLoop3(new TestClass(), 0), 1); 4339 assertIntEquals(testLoop3(new TestClass(), 1), 1); 4340 assertIntEquals(testLoop3(new TestClass(), 2), 1); 4341 assertIntEquals(testLoop3(new TestClass(), 3), 1); 4342 assertIntEquals(testLoop4(new TestClass(), 0), 0); 4343 assertIntEquals(testLoop4(new TestClass(), 1), 1); 4344 assertIntEquals(testLoop4(new TestClass(), 2), 2); 4345 assertIntEquals(testLoop4(new TestClass(), 3), 3); 4346 assertIntEquals(testLoop5(new TestClass(), 0), 0); 4347 assertIntEquals(testLoop5(new TestClass(), 1), 1); 4348 assertIntEquals(testLoop5(new TestClass(), 2), 2); 4349 assertIntEquals(testLoop5(new TestClass(), 3), 3); 4350 assertIntEquals(testLoop6(new TestClass(), 0), 0); 4351 assertIntEquals(testLoop6(new TestClass(), 1), 1); 4352 assertIntEquals(testLoop6(new TestClass(), 2), 2); 4353 assertIntEquals(testLoop6(new TestClass(), 3), 3); 4354 assertIntEquals(testLoop7(0), 0); 4355 assertIntEquals(testLoop7(1), 0); 4356 assertIntEquals(testLoop7(2), 0); 4357 assertIntEquals(testLoop7(3), 0); 4358 assertIntEquals(testLoop8(0), 1); 4359 assertIntEquals(testLoop8(1), 0); 4360 assertIntEquals(testLoop8(2), 1); 4361 assertIntEquals(testLoop8(3), 0); 4362 assertIntEquals(testLoop9(new TestClass(), 0), 0); 4363 assertIntEquals(testLoop9(new TestClass(), 1), 1); 4364 assertIntEquals(testLoop9(new TestClass(), 2), 2); 4365 assertIntEquals(testLoop9(new TestClass(), 3), 3); 4366 assertIntEquals(testLoop10(new TestClass(), 0), 2); 4367 assertIntEquals(testLoop10(new TestClass(), 1), 2); 4368 assertIntEquals(testLoop10(new TestClass(), 2), 2); 4369 assertIntEquals(testLoop10(new TestClass(), 3), 2); 4370 assertIntEquals(testLoop11(new TestClass(), 0), 1); 4371 assertIntEquals(testLoop11(new TestClass(), 1), 3); 4372 assertIntEquals(testLoop11(new TestClass(), 2), 2); 4373 assertIntEquals(testLoop11(new TestClass(), 3), 3); 4374 assertIntEquals(testLoop12(new TestClass(), 0), 1); 4375 assertIntEquals(testLoop12(new TestClass(), 1), 2); 4376 assertIntEquals(testLoop12(new TestClass(), 2), 3); 4377 assertIntEquals(testLoop12(new TestClass(), 3), 2); 4378 assertIntEquals(testLoop13(new TestClass(1, 2), 0), 0); 4379 assertIntEquals(testLoop13(new TestClass(1, 2), 1), 0); 4380 assertIntEquals(testLoop13(new TestClass(1, 2), 2), 0); 4381 assertIntEquals(testLoop13(new TestClass(1, 2), 3), 1); 4382 assertIntEquals(testLoop14(new TestClass2(), 0), 0); 4383 assertIntEquals(testLoop14(new TestClass2(), 1), 0); 4384 assertIntEquals(testLoop14(new TestClass2(), 2), 0); 4385 assertIntEquals(testLoop14(new TestClass2(), 3), 1); 4386 assertIntEquals(testLoop15(0), 0); 4387 assertIntEquals(testLoop15(1), 1); 4388 assertIntEquals(testLoop15(2), 1); 4389 assertIntEquals(testLoop15(3), 1); 4390 assertIntEquals(testLoop16(new TestClass(), 0), 0); 4391 assertIntEquals(testLoop16(new TestClass(), 1), 1); 4392 assertIntEquals(testLoop16(new TestClass(), 2), 2); 4393 assertIntEquals(testLoop16(new TestClass(), 3), 3); 4394 assertIntEquals(testLoop17(new TestClass(), 0), 2); 4395 assertIntEquals(testLoop17(new TestClass(), 1), 4); 4396 assertIntEquals(testLoop17(new TestClass(), 2), 2); 4397 assertIntEquals(testLoop17(new TestClass(), 3), 4); 4398 assertIntEquals(testLoop18(new TestClass(), 0), 0); 4399 assertIntEquals(testLoop18(new TestClass(), 1), 1); 4400 assertIntEquals(testLoop18(new TestClass(), 2), 2); 4401 assertIntEquals(testLoop18(new TestClass(), 3), 3); 4402 assertIntEquals(testLoop19(new TestClass(), 0), 0); 4403 assertIntEquals(testLoop19(new TestClass(), 1), 1); 4404 assertIntEquals(testLoop19(new TestClass(), 2), 2); 4405 assertIntEquals(testLoop19(new TestClass(), 3), 3); 4406 assertIntEquals(testLoop20(new TestClass(), 0), 0); 4407 assertIntEquals(testLoop20(new TestClass(), 1), 1); 4408 assertIntEquals(testLoop20(new TestClass(), 2), 2); 4409 assertIntEquals(testLoop20(new TestClass(), 3), 3); 4410 assertIntEquals(testLoop21(new TestClass(), 0), 0); 4411 assertIntEquals(testLoop21(new TestClass(), 1), 1); 4412 assertIntEquals(testLoop21(new TestClass(), 2), 2); 4413 assertIntEquals(testLoop21(new TestClass(), 3), 3); 4414 assertIntEquals(testLoop22(new TestClass(), 0), 0); 4415 assertIntEquals(testLoop22(new TestClass(), 1), 1); 4416 assertIntEquals(testLoop22(new TestClass(), 2), 2); 4417 assertIntEquals(testLoop22(new TestClass(), 3), 3); 4418 assertIntEquals(testLoop23(new TestClass(), 0), -1); 4419 assertIntEquals(testLoop23(new TestClass(), 1), 2); 4420 assertIntEquals(testLoop23(new TestClass(), 2), 1); 4421 assertIntEquals(testLoop23(new TestClass(), 3), 2); 4422 assertIntEquals(testLoop24(new TestClass(), 0), -1); 4423 assertIntEquals(testLoop24(new TestClass(), 1), 2); 4424 assertIntEquals(testLoop24(new TestClass(), 2), 1); 4425 assertIntEquals(testLoop24(new TestClass(), 3), -2); 4426 assertIntEquals(testLoop25(new TestClass(), 0), 2); 4427 assertIntEquals(testLoop25(new TestClass(), 1), 2); 4428 assertIntEquals(testLoop25(new TestClass(), 2), 4); 4429 assertIntEquals(testLoop25(new TestClass(), 3), -1); 4430 assertIntEquals(testLoop26(new TestClass(), 0), 1); 4431 assertIntEquals(testLoop26(new TestClass(), 1), 0); 4432 assertIntEquals(testLoop26(new TestClass(), 2), 0); 4433 assertIntEquals(testLoop26(new TestClass(), 3), 0); 4434 assertIntEquals(testLoop27(new TestClass(), 0), 1); 4435 assertIntEquals(testLoop27(new TestClass(), 1), 1); 4436 assertIntEquals(testLoop27(new TestClass(), 2), 0); 4437 assertIntEquals(testLoop27(new TestClass(), 3), 0); 4438 assertIntEquals(testLoop28(new TestClass(1, 2), 0), 0); 4439 assertIntEquals(testLoop28(new TestClass(1, 2), 1), 0); 4440 assertIntEquals(testLoop28(new TestClass(1, 2), 2), 0); 4441 assertIntEquals(testLoop28(new TestClass(1, 2), 3), 1); 4442 assertIntEquals(testLoop29(0), 0); 4443 assertIntEquals(testLoop29(1), 1); 4444 assertIntEquals(testLoop29(2), 3); 4445 assertIntEquals(testLoop29(3), 6); 4446 assertIntEquals(testLoop30(0), 0); 4447 assertIntEquals(testLoop30(1), 1); 4448 assertIntEquals(testLoop30(2), 2); 4449 assertIntEquals(testLoop30(3), 3); 4450 assertIntEquals(testLoop31(0), 0); 4451 assertIntEquals(testLoop31(1), 0); 4452 assertIntEquals(testLoop31(2), 0); 4453 assertIntEquals(testLoop31(3), 0); 4454 assertIntEquals(testLoop32(new TestClass(), 0), -1); 4455 assertIntEquals(testLoop32(new TestClass(), 1), 2); 4456 assertIntEquals(testLoop32(new TestClass(), 2), 1); 4457 assertIntEquals(testLoop32(new TestClass(), 3), -2); 4458 assertIntEquals(testLoop33(new TestClass(), 0), 0); 4459 assertIntEquals(testLoop33(new TestClass(), 1), 0); 4460 assertIntEquals(testLoop33(new TestClass(), 2), 0); 4461 assertIntEquals(testLoop33(new TestClass(), 3), 0); 4462 assertIntEquals(testLoop34(0), 0); 4463 assertIntEquals(testLoop34(1), 1); 4464 assertIntEquals(testLoop34(2), 3); 4465 assertIntEquals(testLoop34(3), 6); 4466 assertIntEquals(testLoop35(0), 0); 4467 assertIntEquals(testLoop35(1), 1); 4468 assertIntEquals(testLoop35(2), 3); 4469 assertIntEquals(testLoop35(3), 6); 4470 assertIntEquals(testLoop36(4), 6); 4471 assertIntEquals(testLoop37(4), 6); 4472 assertIntEquals(testLoop38(4, new int[4]), 0); 4473 4474 assertIntEquals(testNestedLoop1(new TestClass(), 0), 1); 4475 assertIntEquals(testNestedLoop1(new TestClass(), 1), 1); 4476 assertIntEquals(testNestedLoop1(new TestClass(), 2), 1); 4477 assertIntEquals(testNestedLoop1(new TestClass(), 3), 1); 4478 assertIntEquals(testNestedLoop2(new TestClass(), 0), 1); 4479 assertIntEquals(testNestedLoop2(new TestClass(), 1), 2); 4480 assertIntEquals(testNestedLoop2(new TestClass(), 2), 2); 4481 assertIntEquals(testNestedLoop2(new TestClass(), 3), 2); 4482 assertIntEquals(testNestedLoop3(new TestClass(), 0), 1); 4483 assertIntEquals(testNestedLoop3(new TestClass(), 1), 2); 4484 assertIntEquals(testNestedLoop3(new TestClass(), 2), 2); 4485 assertIntEquals(testNestedLoop3(new TestClass(), 3), 2); 4486 assertIntEquals(testNestedLoop4(new TestClass(), 0), 1); 4487 assertIntEquals(testNestedLoop4(new TestClass(), 1), 1); 4488 assertIntEquals(testNestedLoop4(new TestClass(), 2), 2); 4489 assertIntEquals(testNestedLoop4(new TestClass(), 3), 2); 4490 assertIntEquals(testNestedLoop5(new TestClass(), 0), 1); 4491 assertIntEquals(testNestedLoop5(new TestClass(), 1), 2); 4492 assertIntEquals(testNestedLoop5(new TestClass(), 2), 2); 4493 assertIntEquals(testNestedLoop5(new TestClass(), 3), 2); 4494 assertIntEquals(testNestedLoop6(new TestClass(), 0), 1); 4495 assertIntEquals(testNestedLoop6(new TestClass(), 1), 1); 4496 assertIntEquals(testNestedLoop6(new TestClass(), 2), 2); 4497 assertIntEquals(testNestedLoop6(new TestClass(), 3), 2); 4498 assertIntEquals(testNestedLoop7(new TestClass(), 0), 0); 4499 assertIntEquals(testNestedLoop7(new TestClass(), 1), 1); 4500 assertIntEquals(testNestedLoop7(new TestClass(), 2), 2); 4501 assertIntEquals(testNestedLoop7(new TestClass(), 3), 3); 4502 assertIntEquals(testNestedLoop8(new TestClass(), 0), 0); 4503 assertIntEquals(testNestedLoop8(new TestClass(), 1), 0); 4504 assertIntEquals(testNestedLoop8(new TestClass(), 2), 0); 4505 assertIntEquals(testNestedLoop8(new TestClass(), 3), 0); 4506 assertLongEquals(testOverlapLoop(10), 34l); 4507 assertLongEquals(testOverlapLoop(50), 7778742049l); 4508 assertIntEquals($noinline$testPartialEscape1(new TestClass(), true), 1); 4509 assertIntEquals($noinline$testPartialEscape1(new TestClass(), false), 0); 4510 } 4511 } 4512