Main.java revision 9d750efd66ae7f4b790af3c1ff8de972bbe826d9
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 17public class Main { 18 19 // CHECK-START: int Main.sieve(int) BCE (before) 20 // CHECK: BoundsCheck 21 // CHECK: ArraySet 22 // CHECK: BoundsCheck 23 // CHECK: ArrayGet 24 // CHECK: BoundsCheck 25 // CHECK: ArraySet 26 27 // CHECK-START: int Main.sieve(int) BCE (after) 28 // CHECK-NOT: BoundsCheck 29 // CHECK: ArraySet 30 // CHECK-NOT: BoundsCheck 31 // CHECK: ArrayGet 32 // CHECK: BoundsCheck 33 // CHECK: ArraySet 34 35 static int sieve(int size) { 36 int primeCount = 0; 37 boolean[] flags = new boolean[size + 1]; 38 for (int i = 1; i < size; i++) flags[i] = true; // Can eliminate. 39 for (int i = 2; i < size; i++) { 40 if (flags[i]) { // Can eliminate. 41 primeCount++; 42 for (int k = i + 1; k <= size; k += i) 43 flags[k - 1] = false; // Can't eliminate yet due to (k+i) may overflow. 44 } 45 } 46 return primeCount; 47 } 48 49 50 // CHECK-START: void Main.narrow(int[], int) BCE (before) 51 // CHECK: BoundsCheck 52 // CHECK: ArraySet 53 // CHECK: BoundsCheck 54 // CHECK: ArraySet 55 // CHECK: BoundsCheck 56 // CHECK: ArraySet 57 58 // CHECK-START: void Main.narrow(int[], int) BCE (after) 59 // CHECK-NOT: BoundsCheck 60 // CHECK: ArraySet 61 // CHECK-NOT: BoundsCheck 62 // CHECK: ArraySet 63 // CHECK: BoundsCheck 64 // CHECK: ArraySet 65 // CHECK-NOT: BoundsCheck 66 // CHECK: ArraySet 67 // CHECK: BoundsCheck 68 // CHECK: ArraySet 69 70 static void narrow(int[] array, int offset) { 71 if (offset < 0) { 72 return; 73 } 74 if (offset < array.length) { 75 // offset is in range [0, array.length-1]. 76 // Bounds check can be eliminated. 77 array[offset] = 1; 78 79 int biased_offset1 = offset + 1; 80 // biased_offset1 is in range [1, array.length]. 81 if (biased_offset1 < array.length) { 82 // biased_offset1 is in range [1, array.length-1]. 83 // Bounds check can be eliminated. 84 array[biased_offset1] = 1; 85 } 86 87 int biased_offset2 = offset + 0x70000000; 88 // biased_offset2 is in range [0x70000000, array.length-1+0x70000000]. 89 // It may overflow and be negative. 90 if (biased_offset2 < array.length) { 91 // Even with this test, biased_offset2 can be negative so we can't 92 // eliminate this bounds check. 93 array[biased_offset2] = 1; 94 } 95 96 // offset_sub1 won't underflow since offset is no less than 0. 97 int offset_sub1 = offset - Integer.MAX_VALUE; 98 if (offset_sub1 >= 0) { 99 array[offset_sub1] = 1; // Bounds check can be eliminated. 100 } 101 102 // offset_sub2 can underflow. 103 int offset_sub2 = offset_sub1 - Integer.MAX_VALUE; 104 if (offset_sub2 >= 0) { 105 array[offset_sub2] = 1; // Bounds check can't be eliminated. 106 } 107 } 108 } 109 110 111 // CHECK-START: void Main.constantIndexing1(int[]) BCE (before) 112 // CHECK: BoundsCheck 113 // CHECK: ArraySet 114 // CHECK: BoundsCheck 115 // CHECK: ArraySet 116 117 // CHECK-START: void Main.constantIndexing1(int[]) BCE (after) 118 // CHECK-NOT: Deoptimize 119 // CHECK: BoundsCheck 120 // CHECK: ArraySet 121 // CHECK-NOT: BoundsCheck 122 // CHECK: ArraySet 123 124 static void constantIndexing1(int[] array) { 125 array[5] = 1; 126 array[4] = 1; 127 } 128 129 130 // CHECK-START: void Main.constantIndexing2(int[]) BCE (before) 131 // CHECK: BoundsCheck 132 // CHECK: ArraySet 133 // CHECK: BoundsCheck 134 // CHECK: ArraySet 135 // CHECK: BoundsCheck 136 // CHECK: ArraySet 137 // CHECK: BoundsCheck 138 // CHECK: ArraySet 139 140 // CHECK-START: void Main.constantIndexing2(int[]) BCE (after) 141 // CHECK: LessThanOrEqual 142 // CHECK: Deoptimize 143 // CHECK-NOT: BoundsCheck 144 // CHECK: ArraySet 145 // CHECK-NOT: BoundsCheck 146 // CHECK: ArraySet 147 // CHECK-NOT: BoundsCheck 148 // CHECK: ArraySet 149 // CHECK-NOT: BoundsCheck 150 // CHECK: ArraySet 151 // CHECK: BoundsCheck 152 // CHECK: ArraySet 153 154 static void constantIndexing2(int[] array) { 155 array[1] = 1; 156 array[2] = 1; 157 array[3] = 1; 158 array[4] = 1; 159 array[-1] = 1; 160 } 161 162 163 // CHECK-START: int[] Main.constantIndexing3(int[], int[], boolean) BCE (before) 164 // CHECK: BoundsCheck 165 // CHECK: ArrayGet 166 // CHECK: BoundsCheck 167 // CHECK: ArraySet 168 // CHECK: BoundsCheck 169 // CHECK: ArrayGet 170 // CHECK: BoundsCheck 171 // CHECK: ArraySet 172 // CHECK: BoundsCheck 173 // CHECK: ArrayGet 174 // CHECK: BoundsCheck 175 // CHECK: ArraySet 176 // CHECK: BoundsCheck 177 // CHECK: ArrayGet 178 // CHECK: BoundsCheck 179 // CHECK: ArraySet 180 181 // CHECK-START: int[] Main.constantIndexing3(int[], int[], boolean) BCE (after) 182 // CHECK: LessThanOrEqual 183 // CHECK: Deoptimize 184 // CHECK-NOT: BoundsCheck 185 // CHECK: ArrayGet 186 // CHECK: LessThanOrEqual 187 // CHECK: Deoptimize 188 // CHECK-NOT: BoundsCheck 189 // CHECK: ArraySet 190 // CHECK-NOT: BoundsCheck 191 // CHECK: ArrayGet 192 // CHECK-NOT: BoundsCheck 193 // CHECK: ArraySet 194 // CHECK-NOT: BoundsCheck 195 // CHECK: ArrayGet 196 // CHECK-NOT: BoundsCheck 197 // CHECK: ArraySet 198 // CHECK-NOT: BoundsCheck 199 // CHECK: ArrayGet 200 // CHECK-NOT: BoundsCheck 201 // CHECK: ArraySet 202 203 static int[] constantIndexing3(int[] array1, int[] array2, boolean copy) { 204 if (!copy) { 205 return array1; 206 } 207 array2[0] = array1[0]; 208 array2[1] = array1[1]; 209 array2[2] = array1[2]; 210 array2[3] = array1[3]; 211 return array2; 212 } 213 214 215 // CHECK-START: void Main.constantIndexing4(int[]) BCE (before) 216 // CHECK: BoundsCheck 217 // CHECK: ArraySet 218 219 // CHECK-START: void Main.constantIndexing4(int[]) BCE (after) 220 // CHECK-NOT: LessThanOrEqual 221 // CHECK: BoundsCheck 222 // CHECK: ArraySet 223 224 // There is only one array access. It's not beneficial 225 // to create a compare with deoptimization instruction. 226 static void constantIndexing4(int[] array) { 227 array[0] = 1; 228 } 229 230 231 // CHECK-START: void Main.constantIndexing5(int[]) BCE (before) 232 // CHECK: BoundsCheck 233 // CHECK: ArraySet 234 // CHECK: BoundsCheck 235 // CHECK: ArraySet 236 237 // CHECK-START: void Main.constantIndexing5(int[]) BCE (after) 238 // CHECK-NOT: Deoptimize 239 // CHECK: BoundsCheck 240 // CHECK: ArraySet 241 // CHECK: BoundsCheck 242 // CHECK: ArraySet 243 244 static void constantIndexing5(int[] array) { 245 // We don't apply the deoptimization for very large constant index 246 // since it's likely to be an anomaly and will throw AIOOBE. 247 array[Integer.MAX_VALUE - 1000] = 1; 248 array[Integer.MAX_VALUE - 999] = 1; 249 array[Integer.MAX_VALUE - 998] = 1; 250 } 251 252 // CHECK-START: void Main.loopPattern1(int[]) BCE (before) 253 // CHECK: BoundsCheck 254 // CHECK: ArraySet 255 // CHECK: BoundsCheck 256 // CHECK: ArraySet 257 // CHECK: BoundsCheck 258 // CHECK: ArraySet 259 // CHECK: BoundsCheck 260 // CHECK: ArraySet 261 // CHECK: BoundsCheck 262 // CHECK: ArraySet 263 // CHECK: BoundsCheck 264 // CHECK: ArraySet 265 // CHECK: BoundsCheck 266 // CHECK: ArraySet 267 268 // CHECK-START: void Main.loopPattern1(int[]) BCE (after) 269 // CHECK-NOT: BoundsCheck 270 // CHECK: ArraySet 271 // CHECK-NOT: BoundsCheck 272 // CHECK: ArraySet 273 // CHECK-NOT: BoundsCheck 274 // CHECK: ArraySet 275 // CHECK: BoundsCheck 276 // CHECK: ArraySet 277 // CHECK: BoundsCheck 278 // CHECK: ArraySet 279 // CHECK: BoundsCheck 280 // CHECK: ArraySet 281 // CHECK-NOT: BoundsCheck 282 // CHECK: ArraySet 283 284 static void loopPattern1(int[] array) { 285 for (int i = 0; i < array.length; i++) { 286 array[i] = 1; // Bounds check can be eliminated. 287 } 288 289 for (int i = 1; i < array.length; i++) { 290 array[i] = 1; // Bounds check can be eliminated. 291 } 292 293 for (int i = 1; i < array.length - 1; i++) { 294 array[i] = 1; // Bounds check can be eliminated. 295 } 296 297 for (int i = -1; i < array.length; i++) { 298 array[i] = 1; // Bounds check can't be eliminated. 299 } 300 301 for (int i = 0; i <= array.length; i++) { 302 array[i] = 1; // Bounds check can't be eliminated. 303 } 304 305 for (int i = 0; i < array.length; i += 2) { 306 // We don't have any assumption on max array length yet. 307 // Bounds check can't be eliminated due to overflow concern. 308 array[i] = 1; 309 } 310 311 for (int i = 1; i < array.length; i += 2) { 312 // Bounds check can be eliminated since i is odd so the last 313 // i that's less than array.length is at most (Integer.MAX_VALUE - 2). 314 array[i] = 1; 315 } 316 } 317 318 319 // CHECK-START: void Main.loopPattern2(int[]) BCE (before) 320 // CHECK: BoundsCheck 321 // CHECK: ArraySet 322 // CHECK: BoundsCheck 323 // CHECK: ArraySet 324 // CHECK: BoundsCheck 325 // CHECK: ArraySet 326 // CHECK: BoundsCheck 327 // CHECK: ArraySet 328 // CHECK: BoundsCheck 329 // CHECK: ArraySet 330 // CHECK: BoundsCheck 331 // CHECK: ArraySet 332 333 // CHECK-START: void Main.loopPattern2(int[]) BCE (after) 334 // CHECK-NOT: BoundsCheck 335 // CHECK: ArraySet 336 // CHECK-NOT: BoundsCheck 337 // CHECK: ArraySet 338 // CHECK-NOT: BoundsCheck 339 // CHECK: ArraySet 340 // CHECK: BoundsCheck 341 // CHECK: ArraySet 342 // CHECK: BoundsCheck 343 // CHECK: ArraySet 344 // CHECK-NOT: BoundsCheck 345 // CHECK: ArraySet 346 347 static void loopPattern2(int[] array) { 348 for (int i = array.length - 1; i >= 0; i--) { 349 array[i] = 1; // Bounds check can be eliminated. 350 } 351 352 for (int i = array.length; i > 0; i--) { 353 array[i - 1] = 1; // Bounds check can be eliminated. 354 } 355 356 for (int i = array.length - 1; i > 0; i--) { 357 array[i] = 1; // Bounds check can be eliminated. 358 } 359 360 for (int i = array.length; i >= 0; i--) { 361 array[i] = 1; // Bounds check can't be eliminated. 362 } 363 364 for (int i = array.length; i >= 0; i--) { 365 array[i - 1] = 1; // Bounds check can't be eliminated. 366 } 367 368 for (int i = array.length; i > 0; i -= 20) { 369 // For i >= 0, (i - 20 - 1) is guaranteed not to underflow. 370 array[i - 1] = 1; // Bounds check can be eliminated. 371 } 372 } 373 374 375 // CHECK-START: void Main.loopPattern3(int[]) BCE (before) 376 // CHECK: BoundsCheck 377 // CHECK: ArraySet 378 379 // CHECK-START: void Main.loopPattern3(int[]) BCE (after) 380 // CHECK: BoundsCheck 381 // CHECK: ArraySet 382 383 static void loopPattern3(int[] array) { 384 java.util.Random random = new java.util.Random(); 385 for (int i = 0; ; i++) { 386 if (random.nextInt() % 1000 == 0 && i < array.length) { 387 // Can't eliminate the bound check since not every i++ is 388 // matched with a array length check, so there is some chance that i 389 // overflows and is negative. 390 array[i] = 1; 391 } 392 } 393 } 394 395 396 // CHECK-START: void Main.constantNewArray() BCE (before) 397 // CHECK: BoundsCheck 398 // CHECK: ArraySet 399 // CHECK: BoundsCheck 400 // CHECK: ArraySet 401 // CHECK: BoundsCheck 402 // CHECK: ArraySet 403 // CHECK: BoundsCheck 404 // CHECK: ArraySet 405 // CHECK: BoundsCheck 406 // CHECK: ArraySet 407 408 // CHECK-START: void Main.constantNewArray() BCE (after) 409 // CHECK-NOT: BoundsCheck 410 // CHECK: ArraySet 411 // CHECK: BoundsCheck 412 // CHECK: ArraySet 413 // CHECK-NOT: BoundsCheck 414 // CHECK: ArraySet 415 // CHECK-NOT: BoundsCheck 416 // CHECK: ArraySet 417 // CHECK: BoundsCheck 418 // CHECK: ArraySet 419 420 static void constantNewArray() { 421 int[] array = new int[10]; 422 for (int i = 0; i < 10; i++) { 423 array[i] = 1; // Bounds check can be eliminated. 424 } 425 426 for (int i = 0; i <= 10; i++) { 427 array[i] = 1; // Bounds check can't be eliminated. 428 } 429 430 array[0] = 1; // Bounds check can be eliminated. 431 array[9] = 1; // Bounds check can be eliminated. 432 array[10] = 1; // Bounds check can't be eliminated. 433 } 434 435 436 static byte readData() { 437 return 1; 438 } 439 440 // CHECK-START: void Main.circularBufferProducer() BCE (before) 441 // CHECK: BoundsCheck 442 // CHECK: ArraySet 443 444 // CHECK-START: void Main.circularBufferProducer() BCE (after) 445 // CHECK-NOT: BoundsCheck 446 // CHECK: ArraySet 447 448 static void circularBufferProducer() { 449 byte[] array = new byte[4096]; 450 int i = 0; 451 while (true) { 452 array[i & (array.length - 1)] = readData(); 453 i++; 454 } 455 } 456 457 458 // CHECK-START: void Main.pyramid1(int[]) BCE (before) 459 // CHECK: BoundsCheck 460 // CHECK: ArraySet 461 // CHECK: BoundsCheck 462 // CHECK: ArraySet 463 464 // CHECK-START: void Main.pyramid1(int[]) BCE (after) 465 // CHECK-NOT: BoundsCheck 466 // CHECK: ArraySet 467 // CHECK-NOT: BoundsCheck 468 // CHECK: ArraySet 469 470 // Set array to something like {0, 1, 2, 3, 2, 1, 0}. 471 static void pyramid1(int[] array) { 472 for (int i = 0; i < (array.length + 1) / 2; i++) { 473 array[i] = i; 474 array[array.length - 1 - i] = i; 475 } 476 } 477 478 479 // CHECK-START: void Main.pyramid2(int[]) BCE (before) 480 // CHECK: BoundsCheck 481 // CHECK: ArraySet 482 // CHECK: BoundsCheck 483 // CHECK: ArraySet 484 485 // CHECK-START: void Main.pyramid2(int[]) BCE (after) 486 // CHECK-NOT: BoundsCheck 487 // CHECK: ArraySet 488 // CHECK-NOT: BoundsCheck 489 // CHECK: ArraySet 490 491 // Set array to something like {0, 1, 2, 3, 2, 1, 0}. 492 static void pyramid2(int[] array) { 493 for (int i = 0; i < (array.length + 1) >> 1; i++) { 494 array[i] = i; 495 array[array.length - 1 - i] = i; 496 } 497 } 498 499 500 // CHECK-START: void Main.pyramid3(int[]) BCE (before) 501 // CHECK: BoundsCheck 502 // CHECK: ArraySet 503 // CHECK: BoundsCheck 504 // CHECK: ArraySet 505 506 // CHECK-START: void Main.pyramid3(int[]) BCE (after) 507 // CHECK-NOT: BoundsCheck 508 // CHECK: ArraySet 509 // CHECK-NOT: BoundsCheck 510 // CHECK: ArraySet 511 512 // Set array to something like {0, 1, 2, 3, 2, 1, 0}. 513 static void pyramid3(int[] array) { 514 for (int i = 0; i < (array.length + 1) >>> 1; i++) { 515 array[i] = i; 516 array[array.length - 1 - i] = i; 517 } 518 } 519 520 521 // CHECK-START: boolean Main.isPyramid(int[]) BCE (before) 522 // CHECK: BoundsCheck 523 // CHECK: ArrayGet 524 // CHECK: BoundsCheck 525 // CHECK: ArrayGet 526 527 // CHECK-START: boolean Main.isPyramid(int[]) BCE (after) 528 // CHECK-NOT: BoundsCheck 529 // CHECK: ArrayGet 530 // CHECK-NOT: BoundsCheck 531 // CHECK: ArrayGet 532 533 static boolean isPyramid(int[] array) { 534 int i = 0; 535 int j = array.length - 1; 536 while (i <= j) { 537 if (array[i] != i) { 538 return false; 539 } 540 if (array[j] != i) { 541 return false; 542 } 543 i++; j--; 544 } 545 return true; 546 } 547 548 549 // CHECK-START: void Main.bubbleSort(int[]) GVN (before) 550 // CHECK: BoundsCheck 551 // CHECK: ArrayGet 552 // CHECK: BoundsCheck 553 // CHECK: ArrayGet 554 // CHECK: BoundsCheck 555 // CHECK: ArrayGet 556 // CHECK: BoundsCheck 557 // CHECK: ArrayGet 558 // CHECK: BoundsCheck 559 // CHECK: ArraySet 560 // CHECK: BoundsCheck 561 // CHECK: ArraySet 562 563 // CHECK-START: void Main.bubbleSort(int[]) GVN (after) 564 // CHECK: BoundsCheck 565 // CHECK: ArrayGet 566 // CHECK: BoundsCheck 567 // CHECK: ArrayGet 568 // CHECK-NOT: ArrayGet 569 // CHECK-NOT: ArrayGet 570 // CHECK-NOT: BoundsCheck 571 // CHECK: ArraySet 572 // CHECK-NOT: BoundsCheck 573 // CHECK: ArraySet 574 575 // CHECK-START: void Main.bubbleSort(int[]) BCE (after) 576 // CHECK-NOT: BoundsCheck 577 // CHECK: ArrayGet 578 // CHECK-NOT: BoundsCheck 579 // CHECK: ArrayGet 580 // CHECK-NOT: ArrayGet 581 // CHECK-NOT: ArrayGet 582 // CHECK-NOT: BoundsCheck 583 // CHECK: ArraySet 584 // CHECK-NOT: BoundsCheck 585 // CHECK: ArraySet 586 587 static void bubbleSort(int[] array) { 588 for (int i = 0; i < array.length - 1; i++) { 589 for (int j = 0; j < array.length - i - 1; j++) { 590 if (array[j] > array[j + 1]) { 591 int temp = array[j + 1]; 592 array[j + 1] = array[j]; 593 array[j] = temp; 594 } 595 } 596 } 597 } 598 599 600 static int foo() { 601 try { 602 // This will cause AIOOBE. 603 constantIndexing2(new int[3]); 604 } catch (ArrayIndexOutOfBoundsException e) { 605 return 99; 606 } 607 return 0; 608 } 609 610 611 int sum; 612 613 // CHECK-START: void Main.foo1(int[], int, int) BCE (before) 614 // CHECK: BoundsCheck 615 // CHECK: ArraySet 616 // CHECK-NOT: BoundsCheck 617 // CHECK: ArrayGet 618 619 // CHECK-START: void Main.foo1(int[], int, int) BCE (after) 620 // CHECK: Deoptimize 621 // CHECK: Deoptimize 622 // CHECK: Deoptimize 623 // CHECK-NOT: Deoptimize 624 // CHECK: Phi 625 // CHECK-NOT: BoundsCheck 626 // CHECK: ArraySet 627 // CHECK-NOT: BoundsCheck 628 // CHECK: ArrayGet 629 630 void foo1(int[] array, int start, int end) { 631 // Three HDeoptimize will be added. One for 632 // start >= 0, one for end <= array.length, 633 // and one for null check on array (to hoist null 634 // check and array.length out of loop). 635 for (int i = start ; i < end; i++) { 636 array[i] = 1; 637 sum += array[i]; 638 } 639 } 640 641 642 // CHECK-START: void Main.foo2(int[], int, int) BCE (before) 643 // CHECK: BoundsCheck 644 // CHECK: ArraySet 645 // CHECK-NOT: BoundsCheck 646 // CHECK: ArrayGet 647 648 // CHECK-START: void Main.foo2(int[], int, int) BCE (after) 649 // CHECK: Deoptimize 650 // CHECK: Deoptimize 651 // CHECK: Deoptimize 652 // CHECK-NOT: Deoptimize 653 // CHECK: Phi 654 // CHECK-NOT: BoundsCheck 655 // CHECK: ArraySet 656 // CHECK-NOT: BoundsCheck 657 // CHECK: ArrayGet 658 659 void foo2(int[] array, int start, int end) { 660 // Three HDeoptimize will be added. One for 661 // start >= 0, one for end <= array.length, 662 // and one for null check on array (to hoist null 663 // check and array.length out of loop). 664 for (int i = start ; i <= end; i++) { 665 array[i] = 1; 666 sum += array[i]; 667 } 668 } 669 670 671 // CHECK-START: void Main.foo3(int[], int) BCE (before) 672 // CHECK: BoundsCheck 673 // CHECK: ArraySet 674 // CHECK-NOT: BoundsCheck 675 // CHECK: ArrayGet 676 677 // CHECK-START: void Main.foo3(int[], int) BCE (after) 678 // CHECK: Deoptimize 679 // CHECK: Deoptimize 680 // CHECK-NOT: Deoptimize 681 // CHECK: Phi 682 // CHECK-NOT: BoundsCheck 683 // CHECK: ArraySet 684 // CHECK-NOT: BoundsCheck 685 // CHECK: ArrayGet 686 687 void foo3(int[] array, int end) { 688 // Two HDeoptimize will be added. One for end < array.length, 689 // and one for null check on array (to hoist null check 690 // and array.length out of loop). 691 for (int i = 3 ; i <= end; i++) { 692 array[i] = 1; 693 sum += array[i]; 694 } 695 } 696 697 // CHECK-START: void Main.foo4(int[], int) BCE (before) 698 // CHECK: BoundsCheck 699 // CHECK: ArraySet 700 // CHECK-NOT: BoundsCheck 701 // CHECK: ArrayGet 702 703 // CHECK-START: void Main.foo4(int[], int) BCE (after) 704 // CHECK: Deoptimize 705 // CHECK: Deoptimize 706 // CHECK-NOT: Deoptimize 707 // CHECK: Phi 708 // CHECK-NOT: BoundsCheck 709 // CHECK: ArraySet 710 // CHECK-NOT: BoundsCheck 711 // CHECK: ArrayGet 712 713 void foo4(int[] array, int end) { 714 // Two HDeoptimize will be added. One for end <= array.length, 715 // and one for null check on array (to hoist null check 716 // and array.length out of loop). 717 for (int i = end ; i > 0; i--) { 718 array[i - 1] = 1; 719 sum += array[i - 1]; 720 } 721 } 722 723 724 // CHECK-START: void Main.foo5(int[], int) BCE (before) 725 // CHECK: BoundsCheck 726 // CHECK: ArraySet 727 // CHECK: BoundsCheck 728 // CHECK: ArrayGet 729 // CHECK: BoundsCheck 730 // CHECK: ArrayGet 731 // CHECK: BoundsCheck 732 // CHECK: ArrayGet 733 734 // CHECK-START: void Main.foo5(int[], int) BCE (after) 735 // CHECK-NOT: BoundsCheck 736 // CHECK: ArraySet 737 // CHECK: Deoptimize 738 // CHECK-NOT: Deoptimize 739 // CHECK: Phi 740 // CHECK-NOT: BoundsCheck 741 // CHECK: ArrayGet 742 // CHECK-NOT: BoundsCheck 743 // CHECK: ArrayGet 744 // CHECK-NOT: BoundsCheck 745 // CHECK: ArrayGet 746 747 void foo5(int[] array, int end) { 748 // Bounds check in this loop can be eliminated without deoptimization. 749 for (int i = array.length - 1 ; i >= 0; i--) { 750 array[i] = 1; 751 } 752 // One HDeoptimize will be added. 753 // It's for (end - 2 <= array.length - 2). 754 for (int i = end - 2 ; i > 0; i--) { 755 sum += array[i - 1]; 756 sum += array[i]; 757 sum += array[i + 1]; 758 } 759 } 760 761 762 // CHECK-START: void Main.foo6(int[], int, int) BCE (before) 763 // CHECK: BoundsCheck 764 // CHECK: ArrayGet 765 // CHECK: BoundsCheck 766 // CHECK: ArrayGet 767 // CHECK: BoundsCheck 768 // CHECK: ArrayGet 769 // CHECK: BoundsCheck 770 // CHECK: ArrayGet 771 // CHECK: BoundsCheck 772 // CHECK: ArrayGet 773 // CHECK-NOT: BoundsCheck 774 // CHECK: ArraySet 775 776 // CHECK-START: void Main.foo6(int[], int, int) BCE (after) 777 // CHECK: Deoptimize 778 // CHECK: Deoptimize 779 // CHECK: Deoptimize 780 // CHECK-NOT: Deoptimize 781 // CHECK: Phi 782 // CHECK-NOT: BoundsCheck 783 // CHECK: ArrayGet 784 // CHECK-NOT: BoundsCheck 785 // CHECK: ArrayGet 786 // CHECK-NOT: BoundsCheck 787 // CHECK: ArrayGet 788 // CHECK-NOT: BoundsCheck 789 // CHECK: ArrayGet 790 // CHECK-NOT: BoundsCheck 791 // CHECK: ArrayGet 792 // CHECK-NOT: BoundsCheck 793 // CHECK: ArraySet 794 795 void foo6(int[] array, int start, int end) { 796 // Three HDeoptimize will be added. One for 797 // start >= 2, one for end <= array.length - 3, 798 // and one for null check on array (to hoist null 799 // check and array.length out of loop). 800 for (int i = end; i >= start; i--) { 801 array[i] = (array[i-2] + array[i-1] + array[i] + array[i+1] + array[i+2]) / 5; 802 } 803 } 804 805 806 // CHECK-START: void Main.foo7(int[], int, int, boolean) BCE (before) 807 // CHECK: BoundsCheck 808 // CHECK: ArrayGet 809 // CHECK: BoundsCheck 810 // CHECK: ArrayGet 811 812 // CHECK-START: void Main.foo7(int[], int, int, boolean) BCE (after) 813 // CHECK: Deoptimize 814 // CHECK: Deoptimize 815 // CHECK: Deoptimize 816 // CHECK-NOT: Deoptimize 817 // CHECK: Phi 818 // CHECK: BoundsCheck 819 // CHECK: ArrayGet 820 // CHECK-NOT: BoundsCheck 821 // CHECK: ArrayGet 822 823 void foo7(int[] array, int start, int end, boolean lowEnd) { 824 // Three HDeoptimize will be added. One for 825 // start >= 0, one for end <= array.length, 826 // and one for null check on array (to hoist null 827 // check and array.length out of loop). 828 for (int i = start ; i < end; i++) { 829 if (lowEnd) { 830 // This array access isn't certain. So we don't 831 // use +1000 offset in decision making for deoptimization 832 // conditions. 833 sum += array[i + 1000]; 834 } 835 sum += array[i]; 836 } 837 } 838 839 840 // CHECK-START: void Main.partialLooping(int[], int, int) BCE (before) 841 // CHECK: BoundsCheck 842 // CHECK: ArraySet 843 844 // CHECK-START: void Main.partialLooping(int[], int, int) BCE (after) 845 // CHECK-NOT: Deoptimize 846 // CHECK: BoundsCheck 847 // CHECK: ArraySet 848 849 void partialLooping(int[] array, int start, int end) { 850 // This loop doesn't cover the full range of [start, end) so 851 // adding deoptimization is too aggressive, since end can be 852 // greater than array.length but the loop is never going to work on 853 // more than 2 elements. 854 for (int i = start; i < end; i++) { 855 if (i == 2) { 856 return; 857 } 858 array[i] = 1; 859 } 860 } 861 862 863 static void testUnknownBounds() { 864 boolean caught = false; 865 Main main = new Main(); 866 main.foo1(new int[10], 0, 10); 867 if (main.sum != 10) { 868 System.out.println("foo1 failed!"); 869 } 870 871 caught = false; 872 main = new Main(); 873 try { 874 main.foo1(new int[10], 0, 11); 875 } catch (ArrayIndexOutOfBoundsException e) { 876 caught = true; 877 } 878 if (!caught || main.sum != 10) { 879 System.out.println("foo1 exception failed!"); 880 } 881 882 main = new Main(); 883 main.foo2(new int[10], 0, 9); 884 if (main.sum != 10) { 885 System.out.println("foo2 failed!"); 886 } 887 888 caught = false; 889 main = new Main(); 890 try { 891 main.foo2(new int[10], 0, 10); 892 } catch (ArrayIndexOutOfBoundsException e) { 893 caught = true; 894 } 895 if (!caught || main.sum != 10) { 896 System.out.println("foo2 exception failed!"); 897 } 898 899 main = new Main(); 900 main.foo3(new int[10], 9); 901 if (main.sum != 7) { 902 System.out.println("foo3 failed!"); 903 } 904 905 caught = false; 906 main = new Main(); 907 try { 908 main.foo3(new int[10], 10); 909 } catch (ArrayIndexOutOfBoundsException e) { 910 caught = true; 911 } 912 if (!caught || main.sum != 7) { 913 System.out.println("foo3 exception failed!"); 914 } 915 916 main = new Main(); 917 main.foo4(new int[10], 10); 918 if (main.sum != 10) { 919 System.out.println("foo4 failed!"); 920 } 921 922 caught = false; 923 main = new Main(); 924 try { 925 main.foo4(new int[10], 11); 926 } catch (ArrayIndexOutOfBoundsException e) { 927 caught = true; 928 } 929 if (!caught || main.sum != 0) { 930 System.out.println("foo4 exception failed!"); 931 } 932 933 main = new Main(); 934 main.foo5(new int[10], 10); 935 if (main.sum != 24) { 936 System.out.println("foo5 failed!"); 937 } 938 939 caught = false; 940 main = new Main(); 941 try { 942 main.foo5(new int[10], 11); 943 } catch (ArrayIndexOutOfBoundsException e) { 944 caught = true; 945 } 946 if (!caught || main.sum != 2) { 947 System.out.println("foo5 exception failed!"); 948 } 949 950 main = new Main(); 951 main.foo6(new int[10], 2, 7); 952 953 main = new Main(); 954 int[] array = new int[4]; 955 main.partialLooping(new int[3], 0, 4); 956 if ((array[0] != 1) && (array[1] != 1) && 957 (array[2] != 0) && (array[3] != 0)) { 958 System.out.println("partialLooping failed!"); 959 } 960 961 caught = false; 962 main = new Main(); 963 try { 964 main.foo6(new int[10], 2, 8); 965 } catch (ArrayIndexOutOfBoundsException e) { 966 caught = true; 967 } 968 if (!caught) { 969 System.out.println("foo6 exception failed!"); 970 } 971 972 caught = false; 973 main = new Main(); 974 try { 975 main.foo6(new int[10], 1, 7); 976 } catch (ArrayIndexOutOfBoundsException e) { 977 caught = true; 978 } 979 if (!caught) { 980 System.out.println("foo6 exception failed!"); 981 } 982 983 } 984 985 // Make sure this method is compiled with optimizing. 986 // CHECK-START: void Main.main(java.lang.String[]) register (after) 987 // CHECK: ParallelMove 988 989 public static void main(String[] args) { 990 sieve(20); 991 992 int[] array = {5, 2, 3, 7, 0, 1, 6, 4}; 993 bubbleSort(array); 994 for (int i = 0; i < 8; i++) { 995 if (array[i] != i) { 996 System.out.println("bubble sort failed!"); 997 } 998 } 999 1000 array = new int[7]; 1001 pyramid1(array); 1002 if (!isPyramid(array)) { 1003 System.out.println("pyramid1 failed!"); 1004 } 1005 1006 array = new int[8]; 1007 pyramid2(array); 1008 if (!isPyramid(array)) { 1009 System.out.println("pyramid2 failed!"); 1010 } 1011 1012 java.util.Arrays.fill(array, -1); 1013 pyramid3(array); 1014 if (!isPyramid(array)) { 1015 System.out.println("pyramid3 failed!"); 1016 } 1017 1018 // Make sure this value is kept after deoptimization. 1019 int i = 1; 1020 if (foo() + i != 100) { 1021 System.out.println("foo failed!"); 1022 }; 1023 1024 testUnknownBounds(); 1025 } 1026 1027} 1028