1 /* 2 * Copyright (C) 2016 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 /** 18 * Tests on loop optimizations related to induction. 19 */ 20 public class Main { 21 22 static int[] a = new int[10]; 23 24 static int[] novec = new int[20]; // to prevent vectorization 25 26 /// CHECK-START: void Main.deadSingleLoop() loop_optimization (before) 27 /// CHECK-DAG: Phi loop:{{B\d+}} outer_loop:none 28 // 29 /// CHECK-START: void Main.deadSingleLoop() loop_optimization (after) 30 /// CHECK-NOT: Phi deadSingleLoop()31 static void deadSingleLoop() { 32 for (int i = 0; i < 4; i++) { 33 } 34 } 35 36 /// CHECK-START: void Main.deadSingleLoop() loop_optimization (before) 37 /// CHECK-DAG: Phi loop:{{B\d+}} outer_loop:none 38 // 39 /// CHECK-START: void Main.deadSingleLoop() loop_optimization (after) 40 /// CHECK-NOT: Phi deadSingleLoopN(int n)41 static void deadSingleLoopN(int n) { 42 for (int i = 0; i < n; i++) { 43 } 44 } 45 46 /// CHECK-START: void Main.potentialInfiniteLoop(int) loop_optimization (before) 47 /// CHECK-DAG: Phi loop:{{B\d+}} outer_loop:none 48 // 49 /// CHECK-START: void Main.potentialInfiniteLoop(int) loop_optimization (after) 50 /// CHECK-DAG: Phi loop:{{B\d+}} outer_loop:none potentialInfiniteLoop(int n)51 static void potentialInfiniteLoop(int n) { 52 for (int i = 0; i <= n; i++) { // loops forever when n = MAX_INT 53 } 54 } 55 56 /// CHECK-START: void Main.deadNestedLoops() loop_optimization (before) 57 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 58 /// CHECK-DAG: Phi loop:{{B\d+}} outer_loop:<<Loop>> 59 // 60 /// CHECK-START: void Main.deadNestedLoops() loop_optimization (after) 61 /// CHECK-NOT: Phi deadNestedLoops()62 static void deadNestedLoops() { 63 for (int i = 0; i < 4; i++) { 64 for (int j = 0; j < 4; j++) { 65 } 66 } 67 } 68 69 /// CHECK-START: void Main.deadNestedAndFollowingLoops() loop_optimization (before) 70 /// CHECK-DAG: Phi loop:<<Loop1:B\d+>> outer_loop:none 71 /// CHECK-DAG: Phi loop:<<Loop2:B\d+>> outer_loop:<<Loop1>> 72 /// CHECK-DAG: Phi loop:{{B\d+}} outer_loop:<<Loop2>> 73 /// CHECK-DAG: Phi loop:{{B\d+}} outer_loop:<<Loop2>> 74 /// CHECK-DAG: Phi loop:<<Loop3:B\d+>> outer_loop:<<Loop1>> 75 /// CHECK-DAG: Phi loop:{{B\d+}} outer_loop:<<Loop3>> 76 /// CHECK-DAG: Phi loop:{{B\d+}} outer_loop:none 77 // 78 /// CHECK-START: void Main.deadNestedAndFollowingLoops() loop_optimization (after) 79 /// CHECK-NOT: Phi deadNestedAndFollowingLoops()80 static void deadNestedAndFollowingLoops() { 81 for (int i = 0; i < 4; i++) { 82 for (int j = 0; j < 4; j++) { 83 for (int k = 0; k < 4; k++) { 84 } 85 for (int k = 0; k < 4; k++) { 86 } 87 } 88 for (int j = 0; j < 4; j++) { 89 for (int k = 0; k < 4; k++) { 90 } 91 } 92 } 93 for (int i = 0; i < 4; i++) { 94 } 95 } 96 97 /// CHECK-START: void Main.deadConditional(int) loop_optimization (before) 98 /// CHECK-DAG: Phi loop:{{B\d+}} outer_loop:none 99 // 100 /// CHECK-START: void Main.deadConditional(int) loop_optimization (after) 101 /// CHECK-NOT: Phi deadConditional(int n)102 public static void deadConditional(int n) { 103 int k = 0; 104 int m = 0; 105 for (int i = 0; i < n; i++) { 106 if (i == 3) 107 k = i; 108 else 109 m = i; 110 } 111 } 112 113 /// CHECK-START: void Main.deadConditionalCycle(int) loop_optimization (before) 114 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 115 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none 116 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none 117 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none 118 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none 119 // 120 /// CHECK-START: void Main.deadConditionalCycle(int) loop_optimization (after) 121 /// CHECK-NOT: Phi deadConditionalCycle(int n)122 public static void deadConditionalCycle(int n) { 123 int k = 0; 124 int m = 0; 125 for (int i = 0; i < n; i++) { 126 if (i == 3) 127 k--; 128 else 129 m++; 130 } 131 } 132 133 134 /// CHECK-START: void Main.deadInduction() loop_optimization (before) 135 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 136 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none 137 /// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none 138 /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none 139 // 140 /// CHECK-START: void Main.deadInduction() loop_optimization (after) 141 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 142 /// CHECK-NOT: Phi loop:<<Loop>> outer_loop:none 143 /// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none 144 /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none deadInduction()145 static void deadInduction() { 146 int dead = 0; 147 for (int i = 0; i < a.length; i++) { 148 a[i] = novec[2 * i] + 1; 149 dead += 5; 150 } 151 } 152 153 /// CHECK-START: void Main.deadManyInduction() loop_optimization (before) 154 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 155 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none 156 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none 157 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none 158 /// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none 159 /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none 160 // 161 /// CHECK-START: void Main.deadManyInduction() loop_optimization (after) 162 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 163 /// CHECK-NOT: Phi loop:<<Loop>> outer_loop:none 164 /// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none 165 /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none deadManyInduction()166 static void deadManyInduction() { 167 int dead1 = 0, dead2 = 1, dead3 = 3; 168 for (int i = 0; i < a.length; i++) { 169 dead1 += 5; 170 a[i] = novec[2 * i] + 2; 171 dead2 += 10; 172 dead3 += 100; 173 } 174 } 175 176 /// CHECK-START: void Main.deadSequence() loop_optimization (before) 177 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 178 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none 179 /// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none 180 /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none 181 // 182 /// CHECK-START: void Main.deadSequence() loop_optimization (after) 183 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 184 /// CHECK-NOT: Phi loop:<<Loop>> outer_loop:none 185 /// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none 186 /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none deadSequence()187 static void deadSequence() { 188 int dead = 0; 189 for (int i = 0; i < a.length; i++) { 190 a[i] = novec[2 * i] + 3; 191 // Increment value defined inside loop, 192 // but sequence itself not used anywhere. 193 dead += i; 194 } 195 } 196 197 /// CHECK-START: void Main.deadCycleWithException(int) loop_optimization (before) 198 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 199 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none 200 /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none 201 /// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none 202 /// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none 203 /// CHECK-NOT: BoundsCheck 204 // 205 /// CHECK-START: void Main.deadCycleWithException(int) loop_optimization (after) 206 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 207 /// CHECK-NOT: Phi loop:<<Loop>> outer_loop:none 208 /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none 209 /// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none 210 /// CHECK-NOT: ArrayGet loop:<<Loop>> outer_loop:none deadCycleWithException(int k)211 static void deadCycleWithException(int k) { 212 int dead = 0; 213 for (int i = 0; i < a.length; i++) { 214 a[i] = novec[2 * i] + 4; 215 // Increment value of dead cycle may throw exception. Dynamic 216 // BCE takes care of the bounds check though, which enables 217 // removing the ArrayGet after removing the dead cycle. 218 dead += a[k]; 219 } 220 } 221 222 /// CHECK-START: int Main.closedFormInductionUp() loop_optimization (before) 223 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 224 /// CHECK-DAG: <<Phi2:i\d+>> Phi loop:<<Loop>> outer_loop:none 225 /// CHECK-DAG: Return [<<Phi1>>] loop:none 226 // 227 /// CHECK-START: int Main.closedFormInductionUp() loop_optimization (after) 228 /// CHECK-NOT: Phi 229 // 230 /// CHECK-START: int Main.closedFormInductionUp() instruction_simplifier$before_codegen (after) 231 /// CHECK-DAG: <<Int:i\d+>> IntConstant 12395 loop:none 232 /// CHECK-DAG: Return [<<Int>>] loop:none closedFormInductionUp()233 static int closedFormInductionUp() { 234 int closed = 12345; 235 for (int i = 0; i < 10; i++) { 236 closed += 5; 237 } 238 return closed; // only needs last value 239 } 240 241 /// CHECK-START: int Main.closedFormInductionInAndDown(int) loop_optimization (before) 242 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 243 /// CHECK-DAG: <<Phi2:i\d+>> Phi loop:<<Loop>> outer_loop:none 244 /// CHECK-DAG: Return [<<Phi2>>] loop:none 245 // 246 /// CHECK-START: int Main.closedFormInductionInAndDown(int) loop_optimization (after) 247 /// CHECK-NOT: Phi 248 // 249 /// CHECK-START: int Main.closedFormInductionInAndDown(int) instruction_simplifier$before_codegen (after) 250 /// CHECK-DAG: <<Par:i\d+>> ParameterValue loop:none 251 /// CHECK-DAG: <<Int:i\d+>> IntConstant -50 loop:none 252 /// CHECK-DAG: <<Add:i\d+>> Add [<<Int>>,<<Par>>] loop:none 253 /// CHECK-DAG: Return [<<Add>>] loop:none closedFormInductionInAndDown(int closed)254 static int closedFormInductionInAndDown(int closed) { 255 for (int i = 0; i < 10; i++) { 256 closed -= 5; 257 } 258 return closed; // only needs last value 259 } 260 261 /// CHECK-START: int Main.closedFormInductionTrivialIf() loop_optimization (before) 262 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 263 /// CHECK-DAG: <<Phi2:i\d+>> Phi loop:<<Loop>> outer_loop:none 264 /// CHECK-DAG: Select loop:<<Loop>> outer_loop:none 265 /// CHECK-DAG: Return [<<Phi1>>] loop:none 266 // 267 /// CHECK-START: int Main.closedFormInductionTrivialIf() loop_optimization (after) 268 /// CHECK-NOT: Phi 269 /// CHECK-NOT: Select 270 // 271 /// CHECK-START: int Main.closedFormInductionTrivialIf() instruction_simplifier$before_codegen (after) 272 /// CHECK-DAG: <<Int:i\d+>> IntConstant 81 loop:none 273 /// CHECK-DAG: Return [<<Int>>] loop:none closedFormInductionTrivialIf()274 static int closedFormInductionTrivialIf() { 275 int closed = 11; 276 for (int i = 0; i < 10; i++) { 277 // Trivial if becomes trivial select at HIR level. 278 // Make sure this is still recognized as induction. 279 if (i < 5) { 280 closed += 7; 281 } else { 282 closed += 7; 283 } 284 } 285 return closed; // only needs last value 286 } 287 288 /// CHECK-START: int Main.closedFormNested() loop_optimization (before) 289 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop1:B\d+>> outer_loop:none 290 /// CHECK-DAG: <<Phi2:i\d+>> Phi loop:<<Loop1>> outer_loop:none 291 /// CHECK-DAG: <<Phi3:i\d+>> Phi loop:<<Loop2:B\d+>> outer_loop:<<Loop1>> 292 /// CHECK-DAG: <<Phi4:i\d+>> Phi loop:<<Loop2>> outer_loop:<<Loop1>> 293 /// CHECK-DAG: Return [<<Phi1>>] loop:none 294 // 295 /// CHECK-START: int Main.closedFormNested() loop_optimization (after) 296 /// CHECK-NOT: Phi 297 // 298 /// CHECK-START: int Main.closedFormNested() instruction_simplifier$before_codegen (after) 299 /// CHECK-DAG: <<Int:i\d+>> IntConstant 100 loop:none 300 /// CHECK-DAG: Return [<<Int>>] loop:none closedFormNested()301 static int closedFormNested() { 302 int closed = 0; 303 for (int i = 0; i < 10; i++) { 304 for (int j = 0; j < 10; j++) { 305 closed++; 306 } 307 } 308 return closed; // only needs last-value 309 } 310 311 /// CHECK-START: int Main.closedFormNestedAlt() loop_optimization (before) 312 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop1:B\d+>> outer_loop:none 313 /// CHECK-DAG: <<Phi2:i\d+>> Phi loop:<<Loop1>> outer_loop:none 314 /// CHECK-DAG: <<Phi3:i\d+>> Phi loop:<<Loop2:B\d+>> outer_loop:<<Loop1>> 315 /// CHECK-DAG: <<Phi4:i\d+>> Phi loop:<<Loop2>> outer_loop:<<Loop1>> 316 /// CHECK-DAG: Return [<<Phi1>>] loop:none 317 // 318 /// CHECK-START: int Main.closedFormNestedAlt() loop_optimization (after) 319 /// CHECK-NOT: Phi 320 // 321 /// CHECK-START: int Main.closedFormNestedAlt() instruction_simplifier$before_codegen (after) 322 /// CHECK-DAG: <<Int:i\d+>> IntConstant 15082 loop:none 323 /// CHECK-DAG: Return [<<Int>>] loop:none closedFormNestedAlt()324 static int closedFormNestedAlt() { 325 int closed = 12345; 326 for (int i = 0; i < 17; i++) { 327 for (int j = 0; j < 23; j++) { 328 closed += 7; 329 } 330 } 331 return closed; // only needs last-value 332 } 333 334 // TODO: taken test around closed form? closedFormInductionUpN(int n)335 static int closedFormInductionUpN(int n) { 336 int closed = 12345; 337 for (int i = 0; i < n; i++) { 338 closed += 5; 339 } 340 return closed; // only needs last value 341 } 342 343 // TODO: taken test around closed form? closedFormInductionInAndDownN(int closed, int n)344 static int closedFormInductionInAndDownN(int closed, int n) { 345 for (int i = 0; i < n; i++) { 346 closed -= 5; 347 } 348 return closed; // only needs last value 349 } 350 351 // TODO: move closed form even further out? closedFormNestedN(int n)352 static int closedFormNestedN(int n) { 353 int closed = 0; 354 for (int i = 0; i < n; i++) { 355 for (int j = 0; j < 10; j++) { 356 closed++; 357 } 358 } 359 return closed; // only needs last-value 360 } 361 362 // TODO: move closed form even further out? closedFormNestedNAlt(int n)363 static int closedFormNestedNAlt(int n) { 364 int closed = 12345; 365 for (int i = 0; i < n; i++) { 366 for (int j = 0; j < 23; j++) { 367 closed += 7; 368 } 369 } 370 return closed; // only needs last-value 371 } 372 373 // TODO: move closed form even further out? closedFormNestedMN(int m, int n)374 static int closedFormNestedMN(int m, int n) { 375 int closed = 0; 376 for (int i = 0; i < m; i++) { 377 for (int j = 0; j < n; j++) { 378 closed++; 379 } 380 } 381 return closed; // only needs last-value 382 } 383 384 // TODO: move closed form even further out? closedFormNestedMNAlt(int m, int n)385 static int closedFormNestedMNAlt(int m, int n) { 386 int closed = 12345; 387 for (int i = 0; i < m; i++) { 388 for (int j = 0; j < n; j++) { 389 closed += 7; 390 } 391 } 392 return closed; // only needs last-value 393 } 394 395 /// CHECK-START: int Main.mainIndexReturned() loop_optimization (before) 396 /// CHECK-DAG: <<Phi:i\d+>> Phi loop:{{B\d+}} outer_loop:none 397 /// CHECK-DAG: Return [<<Phi>>] loop:none 398 // 399 /// CHECK-START: int Main.mainIndexReturned() loop_optimization (after) 400 /// CHECK-NOT: Phi 401 // 402 /// CHECK-START: int Main.mainIndexReturned() instruction_simplifier$before_codegen (after) 403 /// CHECK-DAG: <<Int:i\d+>> IntConstant 10 loop:none 404 /// CHECK-DAG: Return [<<Int>>] loop:none mainIndexReturned()405 static int mainIndexReturned() { 406 int i; 407 for (i = 0; i < 10; i++); 408 return i; 409 } 410 411 /// CHECK-START: int Main.periodicReturned9() loop_optimization (before) 412 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 413 /// CHECK-DAG: <<Phi2:i\d+>> Phi loop:<<Loop>> outer_loop:none 414 /// CHECK-DAG: Return [<<Phi1>>] loop:none 415 // 416 /// CHECK-START: int Main.periodicReturned9() loop_optimization (after) 417 /// CHECK-NOT: Phi 418 // 419 /// CHECK-START: int Main.periodicReturned9() instruction_simplifier$before_codegen (after) 420 /// CHECK-DAG: <<Int:i\d+>> IntConstant 1 loop:none 421 /// CHECK-DAG: Return [<<Int>>] loop:none periodicReturned9()422 static int periodicReturned9() { 423 int k = 0; 424 for (int i = 0; i < 9; i++) { 425 k = 1 - k; 426 } 427 return k; 428 } 429 430 /// CHECK-START: int Main.periodicReturned10() loop_optimization (before) 431 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 432 /// CHECK-DAG: <<Phi2:i\d+>> Phi loop:<<Loop>> outer_loop:none 433 /// CHECK-DAG: Return [<<Phi1>>] loop:none 434 // 435 /// CHECK-START: int Main.periodicReturned10() loop_optimization (after) 436 /// CHECK-NOT: Phi 437 // 438 /// CHECK-START: int Main.periodicReturned10() instruction_simplifier$before_codegen (after) 439 /// CHECK-DAG: <<Int:i\d+>> IntConstant 0 loop:none 440 /// CHECK-DAG: Return [<<Int>>] loop:none periodicReturned10()441 static int periodicReturned10() { 442 int k = 0; 443 for (int i = 0; i < 10; i++) { 444 k = 1 - k; 445 } 446 return k; 447 } 448 449 /// CHECK-START: int Main.getSum21() loop_optimization (before) 450 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 451 /// CHECK-DAG: <<Phi2:i\d+>> Phi loop:<<Loop>> outer_loop:none 452 /// CHECK-DAG: <<Phi3:i\d+>> Phi loop:<<Loop>> outer_loop:none 453 /// CHECK-DAG: Return [<<Phi2>>] loop:none 454 // 455 /// CHECK-START: int Main.getSum21() loop_optimization (after) 456 /// CHECK-NOT: Phi 457 // 458 /// CHECK-START: int Main.getSum21() instruction_simplifier$before_codegen (after) 459 /// CHECK-DAG: <<Int:i\d+>> IntConstant 21 loop:none 460 /// CHECK-DAG: Return [<<Int>>] loop:none getSum21()461 private static int getSum21() { 462 int k = 0; 463 int sum = 0; 464 for (int i = 0; i < 6; i++) { 465 k++; 466 sum += k; 467 } 468 return sum; 469 } 470 471 // Ensure double induction does not "overshoot" the subscript range. getIncr2(int[] arr)472 private static int getIncr2(int[] arr) { 473 for (int i = 0; i < 12; ) { 474 arr[i++] = 30; 475 arr[i++] = 29; 476 } 477 int sum = 0; 478 for (int i = 0; i < 12; i++) { 479 sum += arr[i]; 480 } 481 return sum; 482 } 483 484 // TODO: handle as closed/empty eventually? mainIndexReturnedN(int n)485 static int mainIndexReturnedN(int n) { 486 int i; 487 for (i = 0; i < n; i++); 488 return i; 489 } 490 491 // TODO: handle as closed/empty eventually? mainIndexShort1(short s)492 static int mainIndexShort1(short s) { 493 int i = 0; 494 for (i = 0; i < s; i++) { } 495 return i; 496 } 497 498 // TODO: handle as closed/empty eventually? mainIndexShort2(short s)499 static int mainIndexShort2(short s) { 500 int i = 0; 501 for (i = 0; s > i; i++) { } 502 return i; 503 } 504 505 /// CHECK-START: int Main.periodicReturnedN(int) loop_optimization (before) 506 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 507 /// CHECK-DAG: <<Phi2:i\d+>> Phi loop:<<Loop>> outer_loop:none 508 /// CHECK-DAG: Return [<<Phi1>>] loop:none 509 // 510 /// CHECK-START: int Main.periodicReturnedN(int) loop_optimization (after) 511 /// CHECK-NOT: Phi periodicReturnedN(int n)512 static int periodicReturnedN(int n) { 513 int k = 0; 514 for (int i = 0; i < n; i++) { 515 k = 1 - k; 516 } 517 return k; 518 } 519 520 // If ever replaced by closed form, last value should be correct! getSumN(int n)521 private static int getSumN(int n) { 522 int k = 0; 523 int sum = 0; 524 for (int i = 0; i < n; i++) { 525 k++; 526 sum += k; 527 } 528 return sum; 529 } 530 531 // If ever replaced by closed form, last value should be correct! closedTwice()532 private static int closedTwice() { 533 int closed = 0; 534 for (int i = 0; i < 10; i++) { 535 closed++; 536 } 537 // Closed form of first loop defines trip count of second loop. 538 int other_closed = 0; 539 for (int i = 0; i < closed; i++) { 540 other_closed++; 541 } 542 return other_closed; 543 } 544 545 /// CHECK-START: int Main.closedFeed() loop_optimization (before) 546 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop1:B\d+>> outer_loop:none 547 /// CHECK-DAG: <<Phi2:i\d+>> Phi loop:<<Loop1>> outer_loop:none 548 /// CHECK-DAG: <<Phi3:i\d+>> Phi loop:<<Loop2:B\d+>> outer_loop:none 549 /// CHECK-DAG: <<Phi4:i\d+>> Phi loop:<<Loop2>> outer_loop:none 550 /// CHECK-DAG: Return [<<Phi3>>] loop:none 551 /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>" 552 // 553 /// CHECK-START: int Main.closedFeed() loop_optimization (after) 554 /// CHECK-NOT: Phi 555 // 556 /// CHECK-START: int Main.closedFeed() instruction_simplifier$before_codegen (after) 557 /// CHECK-DAG: <<Int:i\d+>> IntConstant 20 loop:none 558 /// CHECK-DAG: Return [<<Int>>] loop:none closedFeed()559 private static int closedFeed() { 560 int closed = 0; 561 for (int i = 0; i < 10; i++) { 562 closed++; 563 } 564 // Closed form of first loop feeds into initial value of second loop, 565 // used when generating closed form for the latter. 566 for (int i = 0; i < 10; i++) { 567 closed++; 568 } 569 return closed; 570 } 571 572 /// CHECK-START: int Main.closedLargeUp() loop_optimization (before) 573 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 574 /// CHECK-DAG: <<Phi2:i\d+>> Phi loop:<<Loop>> outer_loop:none 575 /// CHECK-DAG: Return [<<Phi1>>] loop:none 576 // 577 /// CHECK-START: int Main.closedLargeUp() loop_optimization (after) 578 /// CHECK-NOT: Phi 579 // 580 /// CHECK-START: int Main.closedLargeUp() instruction_simplifier$before_codegen (after) 581 /// CHECK-DAG: <<Int:i\d+>> IntConstant -10 loop:none 582 /// CHECK-DAG: Return [<<Int>>] loop:none closedLargeUp()583 private static int closedLargeUp() { 584 int closed = 0; 585 for (int i = 0; i < 10; i++) { 586 closed += 0x7fffffff; 587 } 588 return closed; 589 } 590 591 /// CHECK-START: int Main.closedLargeDown() loop_optimization (before) 592 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 593 /// CHECK-DAG: <<Phi2:i\d+>> Phi loop:<<Loop>> outer_loop:none 594 /// CHECK-DAG: Return [<<Phi1>>] loop:none 595 // 596 /// CHECK-START: int Main.closedLargeDown() loop_optimization (after) 597 /// CHECK-NOT: Phi 598 // 599 /// CHECK-START: int Main.closedLargeDown() instruction_simplifier$before_codegen (after) 600 /// CHECK-DAG: <<Int:i\d+>> IntConstant 10 loop:none 601 /// CHECK-DAG: Return [<<Int>>] loop:none closedLargeDown()602 private static int closedLargeDown() { 603 int closed = 0; 604 for (int i = 0; i < 10; i++) { 605 closed -= 0x7fffffff; 606 } 607 return closed; 608 } 609 610 // Checks that we do not loop optimize if the calculation of the trip count would overflow. 611 /// CHECK-START: int Main.closedLinearStepOverflow() loop_optimization (before) 612 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 613 /// CHECK-DAG: <<Phi2:i\d+>> Phi loop:<<Loop>> outer_loop:none 614 /// CHECK-DAG: Return [<<Phi1>>] loop:none 615 // 616 /// CHECK-START: int Main.closedLinearStepOverflow() loop_optimization (after) 617 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 618 /// CHECK-DAG: <<Phi2:i\d+>> Phi loop:<<Loop>> outer_loop:none 619 /// CHECK-DAG: Return [<<Phi1>>] loop:none closedLinearStepOverflow()620 private static int closedLinearStepOverflow() { 621 int closed = 0; 622 // Note that this isn't a "one-off" error. 623 // We are using MIN and MAX to make sure we overflow. 624 for (int i = Integer.MIN_VALUE; i < (Integer.MAX_VALUE - 80); i += 79) { 625 closed++; 626 } 627 return closed; 628 } 629 630 // Since we cannot guarantee that the start/end wouldn't overflow we do not perform loop 631 // optimization. 632 /// CHECK-START: int Main.$inline$closedByParameters(int, int) loop_optimization (before) 633 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 634 /// CHECK-DAG: <<Phi2:i\d+>> Phi loop:<<Loop>> outer_loop:none 635 /// CHECK-DAG: Return [<<Phi1>>] loop:none 636 // 637 /// CHECK-START: int Main.$inline$closedByParameters(int, int) loop_optimization (after) 638 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 639 /// CHECK-DAG: <<Phi2:i\d+>> Phi loop:<<Loop>> outer_loop:none 640 /// CHECK-DAG: Return [<<Phi1>>] loop:none $inline$closedByParameters(int start, int end)641 private static int $inline$closedByParameters(int start, int end) { 642 int closed = 0; 643 for (int i = start; i < end; i++) { 644 closed++; 645 } 646 return closed; 647 } 648 649 // Since we are inlining `closedByParameters` we know that the parameters are fixed and 650 // therefore we can perform loop optimization. 651 /// CHECK-START: int Main.closedByParametersWithInline() loop_optimization (before) 652 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 653 /// CHECK-DAG: <<Phi2:i\d+>> Phi loop:<<Loop>> outer_loop:none 654 /// CHECK-DAG: Return [<<Phi1>>] loop:none 655 // 656 /// CHECK-START: int Main.closedByParametersWithInline() loop_optimization (after) 657 /// CHECK-NOT: Phi 658 // 659 /// CHECK-START: int Main.closedByParametersWithInline() instruction_simplifier$before_codegen (after) 660 /// CHECK-DAG: <<Int:i\d+>> IntConstant 10 loop:none 661 /// CHECK-DAG: Return [<<Int>>] loop:none closedByParametersWithInline()662 private static int closedByParametersWithInline() { 663 return $inline$closedByParameters(0, 10); 664 } 665 666 /// CHECK-START: int Main.waterFall() loop_optimization (before) 667 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop1:B\d+>> outer_loop:none 668 /// CHECK-DAG: <<Phi2:i\d+>> Phi loop:<<Loop2:B\d+>> outer_loop:none 669 /// CHECK-DAG: <<Phi3:i\d+>> Phi loop:<<Loop3:B\d+>> outer_loop:none 670 /// CHECK-DAG: <<Phi4:i\d+>> Phi loop:<<Loop4:B\d+>> outer_loop:none 671 /// CHECK-DAG: <<Phi5:i\d+>> Phi loop:<<Loop5:B\d+>> outer_loop:none 672 /// CHECK-DAG: Return [<<Phi5>>] loop:none 673 // 674 /// CHECK-START: int Main.waterFall() loop_optimization (after) 675 /// CHECK-NOT: Phi 676 // 677 /// CHECK-START: int Main.waterFall() instruction_simplifier$before_codegen (after) 678 /// CHECK-DAG: <<Int:i\d+>> IntConstant 50 loop:none 679 /// CHECK-DAG: Return [<<Int>>] loop:none waterFall()680 private static int waterFall() { 681 int i = 0; 682 for (; i < 10; i++); 683 for (; i < 20; i++); 684 for (; i < 30; i++); 685 for (; i < 40; i++); 686 for (; i < 50; i++); 687 return i; // this should become just 50 688 } 689 690 /// CHECK-START: boolean Main.periodicBoolIdiom1() loop_optimization (before) 691 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 692 /// CHECK-DAG: <<Phi2:i\d+>> Phi loop:<<Loop>> outer_loop:none 693 /// CHECK-DAG: Return [<<Phi1>>] loop:none 694 // 695 /// CHECK-START: boolean Main.periodicBoolIdiom1() loop_optimization (after) 696 /// CHECK-NOT: Phi 697 // 698 /// CHECK-START: boolean Main.periodicBoolIdiom1() instruction_simplifier$before_codegen (after) 699 /// CHECK-DAG: <<Int:i\d+>> IntConstant 0 loop:none 700 /// CHECK-DAG: Return [<<Int>>] loop:none periodicBoolIdiom1()701 private static boolean periodicBoolIdiom1() { 702 boolean x = true; 703 for (int i = 0; i < 7; i++) { 704 x = !x; 705 } 706 return x; 707 } 708 709 /// CHECK-START: boolean Main.periodicBoolIdiom2() loop_optimization (before) 710 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 711 /// CHECK-DAG: <<Phi2:i\d+>> Phi loop:<<Loop>> outer_loop:none 712 /// CHECK-DAG: Return [<<Phi1>>] loop:none 713 // 714 /// CHECK-START: boolean Main.periodicBoolIdiom2() loop_optimization (after) 715 /// CHECK-NOT: Phi 716 // 717 /// CHECK-START: boolean Main.periodicBoolIdiom2() instruction_simplifier$before_codegen (after) 718 /// CHECK-DAG: <<Int:i\d+>> IntConstant 0 loop:none 719 /// CHECK-DAG: Return [<<Int>>] loop:none periodicBoolIdiom2()720 private static boolean periodicBoolIdiom2() { 721 boolean x = true; 722 for (int i = 0; i < 7; i++) { 723 x = (x != true); 724 } 725 return x; 726 } 727 728 /// CHECK-START: boolean Main.periodicBoolIdiom3() loop_optimization (before) 729 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 730 /// CHECK-DAG: <<Phi2:i\d+>> Phi loop:<<Loop>> outer_loop:none 731 /// CHECK-DAG: Return [<<Phi1>>] loop:none 732 // 733 /// CHECK-START: boolean Main.periodicBoolIdiom3() loop_optimization (after) 734 /// CHECK-NOT: Phi 735 // 736 /// CHECK-START: boolean Main.periodicBoolIdiom3() instruction_simplifier$before_codegen (after) 737 /// CHECK-DAG: <<Int:i\d+>> IntConstant 0 loop:none 738 /// CHECK-DAG: Return [<<Int>>] loop:none periodicBoolIdiom3()739 private static boolean periodicBoolIdiom3() { 740 boolean x = true; 741 for (int i = 0; i < 7; i++) { 742 x = (x == false); 743 } 744 return x; 745 } 746 747 /// CHECK-START: boolean Main.periodicBoolIdiom1N(boolean, int) loop_optimization (before) 748 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 749 /// CHECK-DAG: <<Phi2:i\d+>> Phi loop:<<Loop>> outer_loop:none 750 /// CHECK-DAG: Return [<<Phi2>>] loop:none 751 // 752 /// CHECK-START: boolean Main.periodicBoolIdiom1N(boolean, int) loop_optimization (after) 753 /// CHECK-NOT: Phi periodicBoolIdiom1N(boolean x, int n)754 private static boolean periodicBoolIdiom1N(boolean x, int n) { 755 for (int i = 0; i < n; i++) { 756 x = !x; 757 } 758 return x; 759 } 760 761 /// CHECK-START: boolean Main.periodicBoolIdiom2N(boolean, int) loop_optimization (before) 762 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 763 /// CHECK-DAG: <<Phi2:i\d+>> Phi loop:<<Loop>> outer_loop:none 764 /// CHECK-DAG: Return [<<Phi2>>] loop:none 765 // 766 /// CHECK-START: boolean Main.periodicBoolIdiom2N(boolean, int) loop_optimization (after) 767 /// CHECK-NOT: Phi periodicBoolIdiom2N(boolean x, int n)768 private static boolean periodicBoolIdiom2N(boolean x, int n) { 769 for (int i = 0; i < n; i++) { 770 x = (x != true); 771 } 772 return x; 773 } 774 775 /// CHECK-START: boolean Main.periodicBoolIdiom3N(boolean, int) loop_optimization (before) 776 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 777 /// CHECK-DAG: <<Phi2:i\d+>> Phi loop:<<Loop>> outer_loop:none 778 /// CHECK-DAG: Return [<<Phi2>>] loop:none 779 // 780 /// CHECK-START: boolean Main.periodicBoolIdiom3N(boolean, int) loop_optimization (after) 781 /// CHECK-NOT: Phi periodicBoolIdiom3N(boolean x, int n)782 private static boolean periodicBoolIdiom3N(boolean x, int n) { 783 for (int i = 0; i < n; i++) { 784 x = (x == false); 785 } 786 return x; 787 } 788 789 /// CHECK-START: float Main.periodicFloat10() loop_optimization (before) 790 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 791 /// CHECK-DAG: <<Phi2:f\d+>> Phi loop:<<Loop>> outer_loop:none 792 /// CHECK-DAG: <<Phi3:f\d+>> Phi loop:<<Loop>> outer_loop:none 793 /// CHECK-DAG: <<Phi4:f\d+>> Phi loop:<<Loop>> outer_loop:none 794 /// CHECK-DAG: Return [<<Phi2>>] loop:none 795 // 796 /// CHECK-START: float Main.periodicFloat10() loop_optimization (after) 797 /// CHECK-NOT: Phi 798 // 799 /// CHECK-START: float Main.periodicFloat10() loop_optimization (after) 800 /// CHECK-DAG: <<Float:f\d+>> FloatConstant 2 loop:none 801 /// CHECK-DAG: Return [<<Float>>] loop:none periodicFloat10()802 private static float periodicFloat10() { 803 float r = 4.5f; 804 float s = 2.0f; 805 float t = -1.0f; 806 for (int i = 0; i < 10; i++) { 807 float tmp = t; 808 t = r; 809 r = s; 810 s = tmp; 811 } 812 return r; 813 } 814 815 /// CHECK-START: float Main.periodicFloat11() loop_optimization (before) 816 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 817 /// CHECK-DAG: <<Phi2:f\d+>> Phi loop:<<Loop>> outer_loop:none 818 /// CHECK-DAG: <<Phi3:f\d+>> Phi loop:<<Loop>> outer_loop:none 819 /// CHECK-DAG: <<Phi4:f\d+>> Phi loop:<<Loop>> outer_loop:none 820 /// CHECK-DAG: Return [<<Phi2>>] loop:none 821 // 822 /// CHECK-START: float Main.periodicFloat11() loop_optimization (after) 823 /// CHECK-NOT: Phi 824 // 825 /// CHECK-START: float Main.periodicFloat11() loop_optimization (after) 826 /// CHECK-DAG: <<Float:f\d+>> FloatConstant -1 loop:none 827 /// CHECK-DAG: Return [<<Float>>] loop:none periodicFloat11()828 private static float periodicFloat11() { 829 float r = 4.5f; 830 float s = 2.0f; 831 float t = -1.0f; 832 for (int i = 0; i < 11; i++) { 833 float tmp = t; 834 t = r; 835 r = s; 836 s = tmp; 837 } 838 return r; 839 } 840 841 /// CHECK-START: float Main.periodicFloat12() loop_optimization (before) 842 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 843 /// CHECK-DAG: <<Phi2:f\d+>> Phi loop:<<Loop>> outer_loop:none 844 /// CHECK-DAG: <<Phi3:f\d+>> Phi loop:<<Loop>> outer_loop:none 845 /// CHECK-DAG: <<Phi4:f\d+>> Phi loop:<<Loop>> outer_loop:none 846 /// CHECK-DAG: Return [<<Phi2>>] loop:none 847 // 848 /// CHECK-START: float Main.periodicFloat12() loop_optimization (after) 849 /// CHECK-NOT: Phi 850 // 851 /// CHECK-START: float Main.periodicFloat12() loop_optimization (after) 852 /// CHECK-DAG: <<Float:f\d+>> FloatConstant 4.5 loop:none 853 /// CHECK-DAG: Return [<<Float>>] loop:none periodicFloat12()854 private static float periodicFloat12() { 855 float r = 4.5f; 856 float s = 2.0f; 857 float t = -1.0f; 858 for (int i = 0; i < 12; i++) { 859 float tmp = t; 860 t = r; 861 r = s; 862 s = tmp; 863 } 864 return r; 865 } 866 exceptionExitBeforeAdd()867 private static int exceptionExitBeforeAdd() { 868 int k = 0; 869 try { 870 for (int i = 0; i < 10; i++) { 871 a[i] = 0; 872 k += 10; // increment last 873 } 874 } catch (Exception e) { 875 // Flag error by returning current 876 // value of k negated. 877 return -k - 1; 878 } 879 return k; 880 } 881 exceptionExitAfterAdd()882 private static int exceptionExitAfterAdd() { 883 int k = 0; 884 try { 885 for (int i = 0; i < 10; i++) { 886 k += 10; // increment first 887 a[i] = 0; 888 } 889 } catch (Exception e) { 890 // Flag error by returning current 891 // value of k negated. 892 return -k - 1; 893 } 894 return k; 895 } 896 897 /// CHECK-START: long Main.closedLinearInductionUnmatchedTypesNotOptimized() loop_optimization (before) 898 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 899 /// CHECK-DAG: <<Phi2:j\d+>> Phi loop:<<Loop>> outer_loop:none 900 // 901 /// CHECK-START: long Main.closedLinearInductionUnmatchedTypesNotOptimized() loop_optimization (after) 902 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 903 /// CHECK-DAG: <<Phi2:j\d+>> Phi loop:<<Loop>> outer_loop:none closedLinearInductionUnmatchedTypesNotOptimized()904 private static long closedLinearInductionUnmatchedTypesNotOptimized() { 905 long sum = 0; 906 for (int i = 0; i < 10; ++i) { 907 ++sum; 908 } 909 return sum; 910 } 911 912 /// CHECK-START: short Main.closedLinearInductionNarrowingNotOptimized() loop_optimization (before) 913 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 914 // 915 /// CHECK-START: short Main.closedLinearInductionNarrowingNotOptimized() loop_optimization (after) 916 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none closedLinearInductionNarrowingNotOptimized()917 private static short closedLinearInductionNarrowingNotOptimized() { 918 short i = 0; 919 for (; i < 10; ++i); 920 return i; 921 } 922 main(String[] args)923 public static void main(String[] args) { 924 deadSingleLoop(); 925 deadSingleLoopN(4); 926 potentialInfiniteLoop(4); 927 deadNestedLoops(); 928 deadNestedAndFollowingLoops(); 929 deadConditional(4); 930 deadConditionalCycle(4); 931 932 deadInduction(); 933 for (int i = 0; i < a.length; i++) { 934 expectEquals(1, a[i]); 935 } 936 deadManyInduction(); 937 for (int i = 0; i < a.length; i++) { 938 expectEquals(2, a[i]); 939 } 940 deadSequence(); 941 for (int i = 0; i < a.length; i++) { 942 expectEquals(3, a[i]); 943 } 944 try { 945 deadCycleWithException(-1); 946 throw new Error("Expected: IOOB exception"); 947 } catch (IndexOutOfBoundsException e) { 948 } 949 for (int i = 0; i < a.length; i++) { 950 expectEquals(i == 0 ? 4 : 3, a[i]); 951 } 952 deadCycleWithException(0); 953 for (int i = 0; i < a.length; i++) { 954 expectEquals(4, a[i]); 955 } 956 957 expectEquals(12395, closedFormInductionUp()); 958 expectEquals(12295, closedFormInductionInAndDown(12345)); 959 expectEquals(81, closedFormInductionTrivialIf()); 960 expectEquals(10 * 10, closedFormNested()); 961 expectEquals(12345 + 17 * 23 * 7, closedFormNestedAlt()); 962 for (int n = -4; n < 10; n++) { 963 int tc = (n <= 0) ? 0 : n; 964 expectEquals(12345 + tc * 5, closedFormInductionUpN(n)); 965 expectEquals(12345 - tc * 5, closedFormInductionInAndDownN(12345, n)); 966 expectEquals(tc * 10, closedFormNestedN(n)); 967 expectEquals(12345 + tc * 23 * 7, closedFormNestedNAlt(n)); 968 expectEquals(tc * (tc + 1), closedFormNestedMN(n, n + 1)); 969 expectEquals(12345 + tc * (tc + 1) * 7, closedFormNestedMNAlt(n, n + 1)); 970 } 971 972 expectEquals(10, mainIndexReturned()); 973 expectEquals(1, periodicReturned9()); 974 expectEquals(0, periodicReturned10()); 975 expectEquals(21, getSum21()); 976 expectEquals(354, getIncr2(new int[12])); 977 for (int n = -4; n < 4; n++) { 978 int tc = (n <= 0) ? 0 : n; 979 expectEquals(tc, mainIndexReturnedN(n)); 980 expectEquals(tc, mainIndexShort1((short) n)); 981 expectEquals(tc, mainIndexShort2((short) n)); 982 expectEquals(tc & 1, periodicReturnedN(n)); 983 expectEquals((tc * (tc + 1)) / 2, getSumN(n)); 984 } 985 986 expectEquals(10, closedTwice()); 987 expectEquals(20, closedFeed()); 988 expectEquals(-10, closedLargeUp()); 989 expectEquals(10, closedLargeDown()); 990 expectEquals(54366674, closedLinearStepOverflow()); 991 expectEquals(10, $inline$closedByParameters(0, 10)); 992 expectEquals(10, closedByParametersWithInline()); 993 expectEquals(50, waterFall()); 994 995 expectEquals(false, periodicBoolIdiom1()); 996 expectEquals(false, periodicBoolIdiom2()); 997 expectEquals(false, periodicBoolIdiom3()); 998 for (int n = -4; n < 10; n++) { 999 int tc = (n <= 0) ? 0 : n; 1000 boolean even = (tc & 1) == 0; 1001 expectEquals(even, periodicBoolIdiom1N(true, n)); 1002 expectEquals(!even, periodicBoolIdiom1N(false, n)); 1003 expectEquals(even, periodicBoolIdiom2N(true, n)); 1004 expectEquals(!even, periodicBoolIdiom2N(false, n)); 1005 expectEquals(even, periodicBoolIdiom3N(true, n)); 1006 expectEquals(!even, periodicBoolIdiom3N(false, n)); 1007 } 1008 1009 expectEquals( 2.0f, periodicFloat10()); 1010 expectEquals(-1.0f, periodicFloat11()); 1011 expectEquals( 4.5f, periodicFloat12()); 1012 1013 expectEquals(100, exceptionExitBeforeAdd()); 1014 expectEquals(100, exceptionExitAfterAdd()); 1015 a = null; 1016 expectEquals(-1, exceptionExitBeforeAdd()); 1017 expectEquals(-11, exceptionExitAfterAdd()); 1018 a = new int[4]; 1019 expectEquals(-41, exceptionExitBeforeAdd()); 1020 expectEquals(-51, exceptionExitAfterAdd()); 1021 1022 expectEquals(10, closedLinearInductionUnmatchedTypesNotOptimized()); 1023 expectEquals(10, closedLinearInductionNarrowingNotOptimized()); 1024 1025 System.out.println("passed"); 1026 } 1027 expectEquals(float expected, float result)1028 private static void expectEquals(float expected, float result) { 1029 if (expected != result) { 1030 throw new Error("Expected: " + expected + ", found: " + result); 1031 } 1032 } 1033 expectEquals(int expected, int result)1034 private static void expectEquals(int expected, int result) { 1035 if (expected != result) { 1036 throw new Error("Expected: " + expected + ", found: " + result); 1037 } 1038 } 1039 expectEquals(boolean expected, boolean result)1040 private static void expectEquals(boolean expected, boolean result) { 1041 if (expected != result) { 1042 throw new Error("Expected: " + expected + ", found: " + result); 1043 } 1044 } 1045 } 1046