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 * Regression tests for loop optimizations. 19 */ 20public class Main { 21 22 private static native void ensureJitCompiled(Class<?> cls, String methodName); 23 24 /// CHECK-START: int Main.earlyExitFirst(int) loop_optimization (before) 25 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 26 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none 27 // 28 /// CHECK-START: int Main.earlyExitFirst(int) loop_optimization (after) 29 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 30 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none 31 static int earlyExitFirst(int m) { 32 int k = 0; 33 for (int i = 0; i < 10; i++) { 34 if (i == m) { 35 return k; 36 } 37 k++; 38 } 39 return k; 40 } 41 42 /// CHECK-START: int Main.earlyExitLast(int) loop_optimization (before) 43 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 44 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none 45 // 46 /// CHECK-START: int Main.earlyExitLast(int) loop_optimization (after) 47 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 48 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none 49 static int earlyExitLast(int m) { 50 int k = 0; 51 for (int i = 0; i < 10; i++) { 52 k++; 53 if (i == m) { 54 return k; 55 } 56 } 57 return k; 58 } 59 60 /// CHECK-START: int Main.earlyExitNested() loop_optimization (before) 61 /// CHECK-DAG: Phi loop:<<Loop1:B\d+>> outer_loop:none 62 /// CHECK-DAG: Phi loop:<<Loop1>> outer_loop:none 63 /// CHECK-DAG: Phi loop:<<Loop2:B\d+>> outer_loop:<<Loop1>> 64 /// CHECK-DAG: Phi loop:<<Loop2>> outer_loop:<<Loop1>> 65 // 66 /// CHECK-START: int Main.earlyExitNested() loop_optimization (after) 67 /// CHECK-DAG: Phi loop:<<Loop1:B\d+>> outer_loop:none 68 /// CHECK-DAG: Phi loop:<<Loop1>> outer_loop:none 69 // 70 /// CHECK-START: int Main.earlyExitNested() loop_optimization (after) 71 /// CHECK-NOT: Phi loop:{{B\d+}} outer_loop:{{B\d+}} 72 static int earlyExitNested() { 73 int offset = 0; 74 for (int i = 0; i < 2; i++) { 75 int start = offset; 76 // This loop can be removed. 77 for (int j = 0; j < 2; j++) { 78 offset++; 79 } 80 if (i == 1) { 81 return start; 82 } 83 } 84 return 0; 85 } 86 87 // Regression test for b/33774618: transfer operations involving 88 // narrowing linear induction should be done correctly. 89 // 90 /// CHECK-START: int Main.transferNarrowWrap() loop_optimization (before) 91 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 92 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none 93 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none 94 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none 95 // 96 /// CHECK-START: int Main.transferNarrowWrap() loop_optimization (after) 97 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 98 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none 99 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none 100 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none 101 static int transferNarrowWrap() { 102 short x = 0; 103 int w = 10; 104 int v = 3; 105 for (int i = 0; i < 10; i++) { 106 v = w + 1; // transfer on wrap-around 107 w = x; // wrap-around 108 x += 2; // narrowing linear 109 } 110 return v; 111 } 112 113 // Regression test for b/33774618: transfer operations involving 114 // narrowing linear induction should be done correctly 115 // (currently rejected, could be improved). 116 // 117 /// CHECK-START: int Main.polynomialShort() loop_optimization (before) 118 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 119 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none 120 // 121 /// CHECK-START: int Main.polynomialShort() loop_optimization (after) 122 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 123 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none 124 static int polynomialShort() { 125 int x = 0; 126 for (short i = 0; i < 10; i++) { 127 x = x - i; // polynomial on narrowing linear 128 } 129 return x; 130 } 131 132 // Regression test for b/33774618: transfer operations involving 133 // narrowing linear induction should be done correctly 134 // (currently rejected, could be improved). 135 // 136 /// CHECK-START: int Main.polynomialIntFromLong() loop_optimization (before) 137 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 138 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none 139 // 140 /// CHECK-START: int Main.polynomialIntFromLong() loop_optimization (after) 141 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 142 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none 143 static int polynomialIntFromLong() { 144 int x = 0; 145 for (long i = 0; i < 10; i++) { 146 x = x - (int) i; // polynomial on narrowing linear 147 } 148 return x; 149 } 150 151 /// CHECK-START: int Main.polynomialInt() loop_optimization (before) 152 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 153 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none 154 // 155 /// CHECK-START: int Main.polynomialInt() loop_optimization (after) 156 /// CHECK-NOT: Phi 157 // 158 /// CHECK-START: int Main.polynomialInt() instruction_simplifier$after_bce (after) 159 /// CHECK-DAG: <<Int:i\d+>> IntConstant -45 loop:none 160 /// CHECK-DAG: Return [<<Int>>] loop:none 161 static int polynomialInt() { 162 int x = 0; 163 for (int i = 0; i < 10; i++) { 164 x = x - i; 165 } 166 return x; 167 } 168 169 // Regression test for b/34779592 (found with fuzz testing): overflow for last value 170 // of division truncates to zero, for multiplication it simply truncates. 171 // 172 /// CHECK-START: int Main.geoIntDivLastValue(int) loop_optimization (before) 173 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 174 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none 175 // 176 /// CHECK-START: int Main.geoIntDivLastValue(int) loop_optimization (after) 177 /// CHECK-NOT: Phi 178 // 179 /// CHECK-START: int Main.geoIntDivLastValue(int) instruction_simplifier$after_bce (after) 180 /// CHECK-DAG: <<Int:i\d+>> IntConstant 0 loop:none 181 /// CHECK-DAG: Return [<<Int>>] loop:none 182 static int geoIntDivLastValue(int x) { 183 for (int i = 0; i < 2; i++) { 184 x /= 1081788608; 185 } 186 return x; 187 } 188 189 /// CHECK-START: int Main.geoIntMulLastValue(int) loop_optimization (before) 190 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 191 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none 192 // 193 /// CHECK-START: int Main.geoIntMulLastValue(int) loop_optimization (after) 194 /// CHECK-NOT: Phi 195 // 196 /// CHECK-START: int Main.geoIntMulLastValue(int) instruction_simplifier$after_bce (after) 197 /// CHECK-DAG: <<Par:i\d+>> ParameterValue loop:none 198 /// CHECK-DAG: <<Int:i\d+>> IntConstant -194211840 loop:none 199 /// CHECK-DAG: <<Mul:i\d+>> Mul [<<Par>>,<<Int>>] loop:none 200 /// CHECK-DAG: Return [<<Mul>>] loop:none 201 static int geoIntMulLastValue(int x) { 202 for (int i = 0; i < 2; i++) { 203 x *= 1081788608; 204 } 205 return x; 206 } 207 208 /// CHECK-START: long Main.geoLongDivLastValue(long) loop_optimization (before) 209 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 210 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none 211 // 212 /// CHECK-START: long Main.geoLongDivLastValue(long) loop_optimization (after) 213 /// CHECK-NOT: Phi 214 // 215 /// CHECK-START: long Main.geoLongDivLastValue(long) instruction_simplifier$after_bce (after) 216 /// CHECK-DAG: <<Long:j\d+>> LongConstant 0 loop:none 217 /// CHECK-DAG: Return [<<Long>>] loop:none 218 // 219 // Tests overflow in the divisor (while updating intermediate result). 220 static long geoLongDivLastValue(long x) { 221 for (int i = 0; i < 10; i++) { 222 x /= 1081788608; 223 } 224 return x; 225 } 226 227 /// CHECK-START: long Main.geoLongDivLastValue() loop_optimization (before) 228 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 229 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none 230 // 231 /// CHECK-START: long Main.geoLongDivLastValue() loop_optimization (after) 232 /// CHECK-NOT: Phi 233 // 234 /// CHECK-START: long Main.geoLongDivLastValue() instruction_simplifier$after_bce (after) 235 /// CHECK-DAG: <<Long:j\d+>> LongConstant 0 loop:none 236 /// CHECK-DAG: Return [<<Long>>] loop:none 237 // 238 // Tests overflow in the divisor (while updating base). 239 static long geoLongDivLastValue() { 240 long x = -1; 241 for (int i2 = 0; i2 < 2; i2++) { 242 x /= (Long.MAX_VALUE); 243 } 244 return x; 245 } 246 247 /// CHECK-START: long Main.geoLongMulLastValue(long) loop_optimization (before) 248 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 249 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none 250 // 251 /// CHECK-START: long Main.geoLongMulLastValue(long) loop_optimization (after) 252 /// CHECK-NOT: Phi 253 // 254 /// CHECK-START: long Main.geoLongMulLastValue(long) instruction_simplifier$after_bce (after) 255 /// CHECK-DAG: <<Par:j\d+>> ParameterValue loop:none 256 /// CHECK-DAG: <<Long:j\d+>> LongConstant -8070450532247928832 loop:none 257 /// CHECK-DAG: <<Mul:j\d+>> Mul [<<Par>>,<<Long>>] loop:none 258 /// CHECK-DAG: Return [<<Mul>>] loop:none 259 static long geoLongMulLastValue(long x) { 260 for (int i = 0; i < 10; i++) { 261 x *= 1081788608; 262 } 263 return x; 264 } 265 266 // If vectorized, the narrowing subscript should not cause 267 // type inconsistencies in the synthesized code. 268 static void narrowingSubscript(float[] a) { 269 float val = 2.0f; 270 for (long i = 0; i < a.length; i++) { 271 a[(int) i] += val; 272 } 273 } 274 275 // If vectorized, invariant stride should be recognized 276 // as a reduction, not a unit stride in outer loop. 277 static void reduc(int[] xx, int[] yy) { 278 for (int i0 = 0; i0 < 2; i0++) { 279 for (int i1 = 0; i1 < 469; i1++) { 280 xx[i0] -= (++yy[i1]); 281 } 282 } 283 } 284 285 /// CHECK-START: void Main.string2Bytes(char[], java.lang.String) loop_optimization (before) 286 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>> outer_loop:none 287 /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none 288 // 289 /// CHECK-START-ARM: void Main.string2Bytes(char[], java.lang.String) loop_optimization (after) 290 /// CHECK-NOT: VecLoad 291 // 292 /// CHECK-START-ARM64: void Main.string2Bytes(char[], java.lang.String) loop_optimization (after) 293 /// CHECK-DAG: VecLoad loop:<<Loop:B\d+>> outer_loop:none 294 /// CHECK-DAG: VecStore loop:<<Loop>> outer_loop:none 295 // 296 // NOTE: should correctly deal with compressed and uncompressed cases. 297 // 298 /// CHECK-START-MIPS64: void Main.string2Bytes(char[], java.lang.String) loop_optimization (after) 299 /// CHECK-NOT: VecLoad 300 private static void string2Bytes(char[] a, String b) { 301 int min = Math.min(a.length, b.length()); 302 for (int i = 0; i < min; i++) { 303 a[i] = b.charAt(i); 304 } 305 } 306 307 // A strange function that does not inline. 308 private static void $noinline$foo(boolean x, int n) { 309 if (n < 0) 310 throw new Error("oh no"); 311 if (n > 100) { 312 $noinline$foo(!x, n - 1); 313 $noinline$foo(!x, n - 2); 314 $noinline$foo(!x, n - 3); 315 $noinline$foo(!x, n - 4); 316 } 317 } 318 319 // A loop with environment uses of x (the terminating condition). As exposed by bug 320 // b/37247891, the loop can be unrolled, but should handle the (unlikely, but clearly 321 // not impossible) environment uses of the terminating condition in a correct manner. 322 private static void envUsesInCond() { 323 boolean x = false; 324 for (int i = 0; !(x = i >= 1); i++) { 325 $noinline$foo(true, i); 326 } 327 } 328 329 /// CHECK-START: void Main.oneBoth(short[], char[]) loop_optimization (before) 330 /// CHECK-DAG: <<One:i\d+>> IntConstant 1 loop:none 331 /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 332 /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi>>,<<One>>] loop:<<Loop>> outer_loop:none 333 /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi>>,<<One>>] loop:<<Loop>> outer_loop:none 334 // 335 /// CHECK-START-ARM: void Main.oneBoth(short[], char[]) loop_optimization (after) 336 /// CHECK-DAG: <<One:i\d+>> IntConstant 1 loop:none 337 /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<One>>] loop:none 338 /// CHECK-DAG: VecStore [{{l\d+}},<<Phi:i\d+>>,<<Repl>>] loop:<<Loop:B\d+>> outer_loop:none 339 /// CHECK-DAG: VecStore [{{l\d+}},<<Phi>>,<<Repl>>] loop:<<Loop>> outer_loop:none 340 // 341 /// CHECK-START-ARM64: void Main.oneBoth(short[], char[]) loop_optimization (after) 342 /// CHECK-DAG: <<One:i\d+>> IntConstant 1 loop:none 343 /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<One>>] loop:none 344 /// CHECK-DAG: VecStore [{{l\d+}},<<Phi:i\d+>>,<<Repl>>] loop:<<Loop:B\d+>> outer_loop:none 345 /// CHECK-DAG: VecStore [{{l\d+}},<<Phi>>,<<Repl>>] loop:<<Loop>> outer_loop:none 346 // 347 /// CHECK-START-MIPS64: void Main.oneBoth(short[], char[]) loop_optimization (after) 348 /// CHECK-DAG: <<One:i\d+>> IntConstant 1 loop:none 349 /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<One>>] loop:none 350 /// CHECK-DAG: VecStore [{{l\d+}},<<Phi:i\d+>>,<<Repl>>] loop:<<Loop:B\d+>> outer_loop:none 351 /// CHECK-DAG: VecStore [{{l\d+}},<<Phi>>,<<Repl>>] loop:<<Loop>> outer_loop:none 352 // 353 // Bug b/37764324: integral same-length packed types can be mixed freely. 354 private static void oneBoth(short[] a, char[] b) { 355 for (int i = 0; i < Math.min(a.length, b.length); i++) { 356 a[i] = 1; 357 b[i] = 1; 358 } 359 } 360 361 // Bug b/37768917: potential dynamic BCE vs. loop optimizations 362 // case should be deal with correctly (used to DCHECK fail). 363 private static void arrayInTripCount(int[] a, byte[] b, int n) { 364 for (int k = 0; k < n; k++) { 365 for (int i = 0, u = a[0]; i < u; i++) { 366 b[i] += 2; 367 } 368 } 369 } 370 371 /// CHECK-START: void Main.typeConv(byte[], byte[]) loop_optimization (before) 372 /// CHECK-DAG: <<One:i\d+>> IntConstant 1 loop:none 373 /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 374 /// CHECK-DAG: <<Get:b\d+>> ArrayGet [{{l\d+}},<<Phi>>] loop:<<Loop>> outer_loop:none 375 /// CHECK-DAG: <<Add:i\d+>> Add [<<Get>>,<<One>>] loop:<<Loop>> outer_loop:none 376 /// CHECK-DAG: <<Cnv:b\d+>> TypeConversion [<<Add>>] loop:<<Loop>> outer_loop:none 377 /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>> outer_loop:none 378 // 379 /// CHECK-START-ARM: void Main.typeConv(byte[], byte[]) loop_optimization (after) 380 /// CHECK-DAG: <<One:i\d+>> IntConstant 1 loop:none 381 /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<One>>] loop:none 382 /// CHECK-DAG: <<Load:d\d+>> VecLoad [{{l\d+}},<<Phi1:i\d+>>] loop:<<Loop1:B\d+>> outer_loop:none 383 /// CHECK-DAG: <<Vadd:d\d+>> VecAdd [<<Load>>,<<Repl>>] loop:<<Loop1>> outer_loop:none 384 /// CHECK-DAG: VecStore [{{l\d+}},<<Phi1>>,<<Vadd>>] loop:<<Loop1>> outer_loop:none 385 /// CHECK-DAG: <<Get:b\d+>> ArrayGet [{{l\d+}},<<Phi2:i\d+>>] loop:<<Loop2:B\d+>> outer_loop:none 386 /// CHECK-DAG: <<Add:i\d+>> Add [<<Get>>,<<One>>] loop:<<Loop2>> outer_loop:none 387 /// CHECK-DAG: <<Cnv:b\d+>> TypeConversion [<<Add>>] loop:<<Loop2>> outer_loop:none 388 /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi2>>,<<Cnv>>] loop:<<Loop2>> outer_loop:none 389 // 390 /// CHECK-START-ARM64: void Main.typeConv(byte[], byte[]) loop_optimization (after) 391 /// CHECK-DAG: <<One:i\d+>> IntConstant 1 loop:none 392 /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<One>>] loop:none 393 /// CHECK-DAG: <<Load:d\d+>> VecLoad [{{l\d+}},<<Phi1:i\d+>>] loop:<<Loop1:B\d+>> outer_loop:none 394 /// CHECK-DAG: <<Vadd:d\d+>> VecAdd [<<Load>>,<<Repl>>] loop:<<Loop1>> outer_loop:none 395 /// CHECK-DAG: VecStore [{{l\d+}},<<Phi1>>,<<Vadd>>] loop:<<Loop1>> outer_loop:none 396 /// CHECK-DAG: <<Get:b\d+>> ArrayGet [{{l\d+}},<<Phi2:i\d+>>] loop:<<Loop2:B\d+>> outer_loop:none 397 /// CHECK-DAG: <<Add:i\d+>> Add [<<Get>>,<<One>>] loop:<<Loop2>> outer_loop:none 398 /// CHECK-DAG: <<Cnv:b\d+>> TypeConversion [<<Add>>] loop:<<Loop2>> outer_loop:none 399 /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi2>>,<<Cnv>>] loop:<<Loop2>> outer_loop:none 400 // 401 /// CHECK-START-MIPS64: void Main.typeConv(byte[], byte[]) loop_optimization (after) 402 /// CHECK-DAG: <<One:i\d+>> IntConstant 1 loop:none 403 /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<One>>] loop:none 404 /// CHECK-DAG: <<Load:d\d+>> VecLoad [{{l\d+}},<<Phi1:i\d+>>] loop:<<Loop1:B\d+>> outer_loop:none 405 /// CHECK-DAG: <<Vadd:d\d+>> VecAdd [<<Load>>,<<Repl>>] loop:<<Loop1>> outer_loop:none 406 /// CHECK-DAG: VecStore [{{l\d+}},<<Phi1>>,<<Vadd>>] loop:<<Loop1>> outer_loop:none 407 /// CHECK-DAG: <<Get:b\d+>> ArrayGet [{{l\d+}},<<Phi2:i\d+>>] loop:<<Loop2:B\d+>> outer_loop:none 408 /// CHECK-DAG: <<Add:i\d+>> Add [<<Get>>,<<One>>] loop:<<Loop2>> outer_loop:none 409 /// CHECK-DAG: <<Cnv:b\d+>> TypeConversion [<<Add>>] loop:<<Loop2>> outer_loop:none 410 /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi2>>,<<Cnv>>] loop:<<Loop2>> outer_loop:none 411 // 412 // Scalar code in cleanup loop uses correct byte type on array get and type conversion. 413 private static void typeConv(byte[] a, byte[] b) { 414 int len = Math.min(a.length, b.length); 415 for (int i = 0; i < len; i++) { 416 a[i] = (byte) (b[i] + 1); 417 } 418 } 419 420 // Environment of an instruction, removed during SimplifyInduction, should be adjusted. 421 // 422 /// CHECK-START: void Main.inductionMax(int[]) loop_optimization (before) 423 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 424 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none 425 // 426 /// CHECK-START: void Main.inductionMax(int[]) loop_optimization (after) 427 /// CHECK-NOT: Phi 428 private static void inductionMax(int[] a) { 429 int s = 0; 430 for (int i = 0; i < 10; i++) { 431 s = Math.max(s, 5); 432 } 433 } 434 435 /// CHECK-START: int Main.feedsIntoDeopt(int[]) loop_optimization (before) 436 /// CHECK-DAG: Phi loop:<<Loop1:B\d+>> outer_loop:none 437 /// CHECK-DAG: Phi loop:<<Loop1>> outer_loop:none 438 /// CHECK-DAG: Phi loop:<<Loop2:B\d+>> outer_loop:none 439 // 440 /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>" 441 // 442 /// CHECK-START: int Main.feedsIntoDeopt(int[]) loop_optimization (after) 443 /// CHECK-DAG: Phi loop:{{B\d+}} outer_loop:none 444 /// CHECK-NOT: Phi 445 static int feedsIntoDeopt(int[] a) { 446 // Reduction should be removed. 447 int r = 0; 448 for (int i = 0; i < 100; i++) { 449 r += 10; 450 } 451 // Even though uses feed into deopts of BCE. 452 for (int i = 1; i < 100; i++) { 453 a[i] = a[i - 1]; 454 } 455 return r; 456 } 457 458 static int absCanBeNegative(int x) { 459 int a[] = { 1, 2, 3 }; 460 int y = 0; 461 for (int i = Math.abs(x); i < a.length; i++) { 462 y += a[i]; 463 } 464 return y; 465 } 466 467 // b/65478356: sum up 2-dim array. 468 static int sum(int[][] a) { 469 int sum = 0; 470 for (int y = 0; y < a.length; y++) { 471 int[] aa = a[y]; 472 for (int x = 0; x < aa.length; x++) { 473 sum += aa[x]; 474 } 475 } 476 return sum; 477 } 478 479 // Large loop body should not break unrolling computation. 480 static void largeBody(int[] x) { 481 for (int i = 0; i < 100; i++) { 482 x[i] = x[i] * 1 + x[i] * 2 + x[i] * 3 + x[i] * 4 + x[i] * 5 + x[i] * 6 + 483 x[i] * 7 + x[i] * 8 + x[i] * 9 + x[i] * 10 + x[i] * 11 + x[i] * 12 + 484 x[i] * 13 + x[i] * 14 + x[i] * 15 + x[i] * 1 + x[i] * 2 + x[i] * 3 + x[i] * 4 + 485 x[i] * 5 + x[i] * 6 + x[i] * 7 + x[i] * 8 + x[i] * 9 + x[i] * 10 + x[i] * 11 + 486 x[i] * 12 + x[i] * 13 + x[i] * 14 + x[i] * 15 + x[i] * 1 + x[i] * 2 + x[i] * 3 + 487 x[i] * 4 + x[i] * 5; 488 } 489 } 490 491 // Mixed of 16-bit and 8-bit array references. 492 static void castAndNarrow(byte[] x, char[] y) { 493 for (int i = 0; i < x.length; i++) { 494 x[i] = (byte) ((short) y[i] + 1); 495 } 496 } 497 498 // Avoid bad scheduler-SIMD interaction. 499 static int doNotMoveSIMD() { 500 int sum = 0; 501 for (int j = 0; j <= 8; j++) { 502 int[] a = new int[17]; // a[i] = 0; 503 // ConstructorFence ? 504 for (int i = 0; i < a.length; i++) { 505 a[i] += 1; // a[i] = 1; 506 } 507 for (int i = 0; i < a.length; i++) { 508 sum += a[i]; // expect a[i] = 1; 509 } 510 } 511 return sum; 512 } 513 514 // Ensure spilling saves full SIMD values. 515 private static final int reduction32Values(int[] a, int[] b, int[] c, int[] d) { 516 int s0 = 0; 517 int s1 = 0; 518 int s2 = 0; 519 int s3 = 0; 520 int s4 = 0; 521 int s5 = 0; 522 int s6 = 0; 523 int s7 = 0; 524 int s8 = 0; 525 int s9 = 0; 526 int s10 = 0; 527 int s11 = 0; 528 int s12 = 0; 529 int s13 = 0; 530 int s14 = 0; 531 int s15 = 0; 532 int s16 = 0; 533 int s17 = 0; 534 int s18 = 0; 535 int s19 = 0; 536 int s20 = 0; 537 int s21 = 0; 538 int s22 = 0; 539 int s23 = 0; 540 int s24 = 0; 541 int s25 = 0; 542 int s26 = 0; 543 int s27 = 0; 544 int s28 = 0; 545 int s29 = 0; 546 int s30 = 0; 547 int s31 = 0; 548 for (int i = 1; i < 100; i++) { 549 s0 += a[i]; 550 s1 += b[i]; 551 s2 += c[i]; 552 s3 += d[i]; 553 s4 += a[i]; 554 s5 += b[i]; 555 s6 += c[i]; 556 s7 += d[i]; 557 s8 += a[i]; 558 s9 += b[i]; 559 s10 += c[i]; 560 s11 += d[i]; 561 s12 += a[i]; 562 s13 += b[i]; 563 s14 += c[i]; 564 s15 += d[i]; 565 s16 += a[i]; 566 s17 += b[i]; 567 s18 += c[i]; 568 s19 += d[i]; 569 s20 += a[i]; 570 s21 += b[i]; 571 s22 += c[i]; 572 s23 += d[i]; 573 s24 += a[i]; 574 s25 += b[i]; 575 s26 += c[i]; 576 s27 += d[i]; 577 s28 += a[i]; 578 s29 += b[i]; 579 s30 += c[i]; 580 s31 += d[i]; 581 } 582 return s0 + s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10 + s11 + s12 + s13 + s14 + s15 + 583 s16 + s17 + s18 + s19 + s20 + s21 + s22 + s23 + 584 s24 + s25 + s26 + s27 + s28 + s29 + s30 + s31; 585 } 586 587 public static int reductionIntoReplication() { 588 int[] a = { 1, 2, 3, 4 }; 589 int x = 0; 590 for (int i = 0; i < 4; i++) { 591 x += a[i]; 592 } 593 for (int i = 0; i < 4; i++) { 594 a[i] = x; 595 } 596 return a[3]; 597 } 598 599 public static void main(String[] args) { 600 System.loadLibrary(args[0]); 601 602 expectEquals(10, earlyExitFirst(-1)); 603 for (int i = 0; i <= 10; i++) { 604 expectEquals(i, earlyExitFirst(i)); 605 } 606 expectEquals(10, earlyExitFirst(11)); 607 608 expectEquals(10, earlyExitLast(-1)); 609 for (int i = 0; i < 10; i++) { 610 expectEquals(i + 1, earlyExitLast(i)); 611 } 612 expectEquals(10, earlyExitLast(10)); 613 expectEquals(10, earlyExitLast(11)); 614 615 expectEquals(2, earlyExitNested()); 616 617 expectEquals(17, transferNarrowWrap()); 618 expectEquals(-45, polynomialShort()); 619 expectEquals(-45, polynomialIntFromLong()); 620 expectEquals(-45, polynomialInt()); 621 622 expectEquals(0, geoIntDivLastValue(0)); 623 expectEquals(0, geoIntDivLastValue(1)); 624 expectEquals(0, geoIntDivLastValue(2)); 625 expectEquals(0, geoIntDivLastValue(1081788608)); 626 expectEquals(0, geoIntDivLastValue(-1081788608)); 627 expectEquals(0, geoIntDivLastValue(2147483647)); 628 expectEquals(0, geoIntDivLastValue(-2147483648)); 629 630 expectEquals( 0, geoIntMulLastValue(0)); 631 expectEquals( -194211840, geoIntMulLastValue(1)); 632 expectEquals( -388423680, geoIntMulLastValue(2)); 633 expectEquals(-1041498112, geoIntMulLastValue(1081788608)); 634 expectEquals( 1041498112, geoIntMulLastValue(-1081788608)); 635 expectEquals( 194211840, geoIntMulLastValue(2147483647)); 636 expectEquals( 0, geoIntMulLastValue(-2147483648)); 637 638 expectEquals(0L, geoLongDivLastValue(0L)); 639 expectEquals(0L, geoLongDivLastValue(1L)); 640 expectEquals(0L, geoLongDivLastValue(2L)); 641 expectEquals(0L, geoLongDivLastValue(1081788608L)); 642 expectEquals(0L, geoLongDivLastValue(-1081788608L)); 643 expectEquals(0L, geoLongDivLastValue(2147483647L)); 644 expectEquals(0L, geoLongDivLastValue(-2147483648L)); 645 expectEquals(0L, geoLongDivLastValue(9223372036854775807L)); 646 expectEquals(0L, geoLongDivLastValue(-9223372036854775808L)); 647 648 expectEquals(0L, geoLongDivLastValue()); 649 650 expectEquals( 0L, geoLongMulLastValue(0L)); 651 expectEquals(-8070450532247928832L, geoLongMulLastValue(1L)); 652 expectEquals( 2305843009213693952L, geoLongMulLastValue(2L)); 653 expectEquals( 0L, geoLongMulLastValue(1081788608L)); 654 expectEquals( 0L, geoLongMulLastValue(-1081788608L)); 655 expectEquals( 8070450532247928832L, geoLongMulLastValue(2147483647L)); 656 expectEquals( 0L, geoLongMulLastValue(-2147483648L)); 657 expectEquals( 8070450532247928832L, geoLongMulLastValue(9223372036854775807L)); 658 expectEquals( 0L, geoLongMulLastValue(-9223372036854775808L)); 659 660 float[] a = new float[16]; 661 narrowingSubscript(a); 662 for (int i = 0; i < 16; i++) { 663 expectEquals(2.0f, a[i]); 664 } 665 666 int[] xx = new int[2]; 667 int[] yy = new int[469]; 668 reduc(xx, yy); 669 expectEquals(-469, xx[0]); 670 expectEquals(-938, xx[1]); 671 for (int i = 0; i < 469; i++) { 672 expectEquals(2, yy[i]); 673 } 674 675 char[] aa = new char[23]; 676 String bb = "hello world how are you"; 677 string2Bytes(aa, bb); 678 for (int i = 0; i < aa.length; i++) { 679 expectEquals(aa[i], bb.charAt(i)); 680 } 681 String cc = "\u1010\u2020llo world how are y\u3030\u4040"; 682 string2Bytes(aa, cc); 683 for (int i = 0; i < aa.length; i++) { 684 expectEquals(aa[i], cc.charAt(i)); 685 } 686 687 envUsesInCond(); 688 689 short[] dd = new short[23]; 690 oneBoth(dd, aa); 691 for (int i = 0; i < aa.length; i++) { 692 expectEquals(aa[i], 1); 693 expectEquals(dd[i], 1); 694 } 695 696 xx[0] = 10; 697 byte[] bt = new byte[10]; 698 arrayInTripCount(xx, bt, 20); 699 for (int i = 0; i < bt.length; i++) { 700 expectEquals(40, bt[i]); 701 } 702 703 byte[] b1 = new byte[259]; // few extra iterations 704 byte[] b2 = new byte[259]; 705 for (int i = 0; i < 259; i++) { 706 b1[i] = 0; 707 b2[i] = (byte) i; 708 } 709 typeConv(b1, b2); 710 for (int i = 0; i < 259; i++) { 711 expectEquals((byte)(i + 1), b1[i]); 712 } 713 714 inductionMax(yy); 715 716 int[] f = new int[100]; 717 f[0] = 11; 718 expectEquals(1000, feedsIntoDeopt(f)); 719 for (int i = 0; i < 100; i++) { 720 expectEquals(11, f[i]); 721 } 722 723 expectEquals(0, absCanBeNegative(-3)); 724 expectEquals(3, absCanBeNegative(-2)); 725 expectEquals(5, absCanBeNegative(-1)); 726 expectEquals(6, absCanBeNegative(0)); 727 expectEquals(5, absCanBeNegative(1)); 728 expectEquals(3, absCanBeNegative(2)); 729 expectEquals(0, absCanBeNegative(3)); 730 expectEquals(0, absCanBeNegative(Integer.MAX_VALUE)); 731 // Abs(min_int) = min_int. 732 int verify = 0; 733 try { 734 absCanBeNegative(Integer.MIN_VALUE); 735 verify = 1; 736 } catch (ArrayIndexOutOfBoundsException e) { 737 verify = 2; 738 } 739 expectEquals(2, verify); 740 741 int[][] x = new int[128][128]; 742 for (int i = 0; i < 128; i++) { 743 for (int j = 0; j < 128; j++) { 744 x[i][j] = -i - j; 745 } 746 } 747 expectEquals(-2080768, sum(x)); 748 749 largeBody(f); 750 for (int i = 0; i < 100; i++) { 751 expectEquals(2805, f[i]); 752 } 753 754 char[] cx = new char[259]; 755 for (int i = 0; i < 259; i++) { 756 cx[i] = (char) (i - 100); 757 } 758 castAndNarrow(b1, cx); 759 for (int i = 0; i < 259; i++) { 760 expectEquals((byte)((short) cx[i] + 1), b1[i]); 761 } 762 763 expectEquals(153, doNotMoveSIMD()); 764 765 // This test exposed SIMDization issues on x86 and x86_64 766 // so we make sure the test runs with JIT enabled. 767 ensureJitCompiled(Main.class, "reduction32Values"); 768 { 769 int[] a1 = new int[100]; 770 int[] a2 = new int[100]; 771 int[] a3 = new int[100]; 772 int[] a4 = new int[100]; 773 for (int i = 0; i < 100; i++) { 774 a1[i] = i; 775 a2[i] = 1; 776 a3[i] = 100 - i; 777 a4[i] = i % 16; 778 } 779 expectEquals(85800, reduction32Values(a1, a2, a3, a4)); 780 } 781 782 expectEquals(10, reductionIntoReplication()); 783 784 System.out.println("passed"); 785 } 786 787 private static void expectEquals(int expected, int result) { 788 if (expected != result) { 789 throw new Error("Expected: " + expected + ", found: " + result); 790 } 791 } 792 793 private static void expectEquals(long expected, long result) { 794 if (expected != result) { 795 throw new Error("Expected: " + expected + ", found: " + result); 796 } 797 } 798 799 private static void expectEquals(float expected, float result) { 800 if (expected != result) { 801 throw new Error("Expected: " + expected + ", found: " + result); 802 } 803 } 804} 805