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 */ 20 public class Main { 21 ensureJitCompiled(Class<?> cls, String methodName)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 earlyExitFirst(int m)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 earlyExitLast(int m)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+}} earlyExitNested()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 transferNarrowWrap()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 polynomialShort()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 polynomialIntFromLong()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 polynomialInt()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 geoIntDivLastValue(int x)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 geoIntMulLastValue(int x)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). geoLongDivLastValue(long x)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). geoLongDivLastValue()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 geoLongMulLastValue(long x)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. narrowingSubscript(float[] a)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. reduc(int[] xx, int[] yy)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-IF: hasIsaFeature("sve") 294 // 295 // TODO: Support CharAt for SVE. 296 /// CHECK-NOT: VecLoad 297 // 298 /// CHECK-ELSE: 299 // 300 /// CHECK-DAG: VecLoad loop:<<Loop:B\d+>> outer_loop:none 301 /// CHECK-DAG: VecStore loop:<<Loop>> outer_loop:none 302 // 303 /// CHECK-FI: 304 // 305 // NOTE: should correctly deal with compressed and uncompressed cases. string2Bytes(char[] a, String b)306 private static void string2Bytes(char[] a, String b) { 307 int min = Math.min(a.length, b.length()); 308 for (int i = 0; i < min; i++) { 309 a[i] = b.charAt(i); 310 } 311 } 312 313 /// CHECK-START-ARM: void Main.$noinline$stringToShorts(short[], java.lang.String) loop_optimization (after) 314 /// CHECK-NOT: VecLoad 315 316 /// CHECK-START-ARM64: void Main.$noinline$stringToShorts(short[], java.lang.String) loop_optimization (after) 317 /// CHECK-IF: hasIsaFeature("sve") 318 // 319 // TODO: Support CharAt for SVE. 320 /// CHECK-NOT: VecLoad 321 // 322 /// CHECK-ELSE: 323 // 324 /// CHECK-DAG: VecLoad loop:<<Loop:B\d+>> outer_loop:none 325 /// CHECK-DAG: VecStore loop:<<Loop>> outer_loop:none 326 // 327 /// CHECK-FI: $noinline$stringToShorts(short[] dest, String src)328 private static void $noinline$stringToShorts(short[] dest, String src) { 329 int min = Math.min(dest.length, src.length()); 330 for (int i = 0; i < min; ++i) { 331 dest[i] = (short) src.charAt(i); 332 } 333 } 334 335 // A strange function that does not inline. $noinline$foo(boolean x, int n)336 private static void $noinline$foo(boolean x, int n) { 337 if (n < 0) 338 throw new Error("oh no"); 339 if (n > 100) { 340 $noinline$foo(!x, n - 1); 341 $noinline$foo(!x, n - 2); 342 $noinline$foo(!x, n - 3); 343 $noinline$foo(!x, n - 4); 344 } 345 } 346 347 // A loop with environment uses of x (the terminating condition). As exposed by bug 348 // b/37247891, the loop can be unrolled, but should handle the (unlikely, but clearly 349 // not impossible) environment uses of the terminating condition in a correct manner. envUsesInCond()350 private static void envUsesInCond() { 351 boolean x = false; 352 for (int i = 0; !(x = i >= 1); i++) { 353 $noinline$foo(true, i); 354 } 355 } 356 357 /// CHECK-START: void Main.oneBoth(short[], char[]) loop_optimization (before) 358 /// CHECK-DAG: <<One:i\d+>> IntConstant 1 loop:none 359 /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 360 /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi>>,<<One>>] loop:<<Loop>> outer_loop:none 361 /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi>>,<<One>>] loop:<<Loop>> outer_loop:none 362 // 363 /// CHECK-START-ARM: void Main.oneBoth(short[], char[]) loop_optimization (after) 364 /// CHECK-DAG: <<One:i\d+>> IntConstant 1 loop:none 365 /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<One>>] loop:none 366 /// CHECK-DAG: VecStore [{{l\d+}},<<Phi:i\d+>>,<<Repl>>] loop:<<Loop:B\d+>> outer_loop:none 367 /// CHECK-DAG: VecStore [{{l\d+}},<<Phi>>,<<Repl>>] loop:<<Loop>> outer_loop:none 368 // 369 /// CHECK-START-ARM64: void Main.oneBoth(short[], char[]) loop_optimization (after) 370 /// CHECK-DAG: <<One:i\d+>> IntConstant 1 loop:none 371 /// CHECK-IF: hasIsaFeature("sve") 372 // 373 /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<One>>,{{j\d+}}] loop:none 374 /// CHECK-DAG: <<LoopP:j\d+>> VecPredWhile loop:<<Loop:B\d+>> outer_loop:none 375 /// CHECK-DAG: VecStore [{{l\d+}},<<Phi:i\d+>>,<<Repl>>,<<LoopP>>] loop:<<Loop>> outer_loop:none 376 /// CHECK-DAG: VecStore [{{l\d+}},<<Phi>>,<<Repl>>,<<LoopP>>] loop:<<Loop>> outer_loop:none 377 // 378 /// CHECK-ELSE: 379 // 380 /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<One>>] loop:none 381 /// CHECK-DAG: VecStore [{{l\d+}},<<Phi:i\d+>>,<<Repl>>] loop:<<Loop:B\d+>> outer_loop:none 382 /// CHECK-DAG: VecStore [{{l\d+}},<<Phi>>,<<Repl>>] loop:<<Loop>> outer_loop:none 383 // 384 /// CHECK-FI: 385 // 386 // Bug b/37764324: integral same-length packed types can be mixed freely. oneBoth(short[] a, char[] b)387 private static void oneBoth(short[] a, char[] b) { 388 for (int i = 0; i < Math.min(a.length, b.length); i++) { 389 a[i] = 1; 390 b[i] = 1; 391 } 392 } 393 394 // Bug b/37768917: potential dynamic BCE vs. loop optimizations 395 // case should be deal with correctly (used to DCHECK fail). arrayInTripCount(int[] a, byte[] b, int n)396 private static void arrayInTripCount(int[] a, byte[] b, int n) { 397 for (int k = 0; k < n; k++) { 398 for (int i = 0, u = a[0]; i < u; i++) { 399 b[i] += 2; 400 } 401 } 402 } 403 404 /// CHECK-START: void Main.typeConv(byte[], byte[]) loop_optimization (before) 405 /// CHECK-DAG: <<One:i\d+>> IntConstant 1 loop:none 406 /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 407 /// CHECK-DAG: <<Get:b\d+>> ArrayGet [{{l\d+}},<<Phi>>] loop:<<Loop>> outer_loop:none 408 /// CHECK-DAG: <<Add:i\d+>> Add [<<Get>>,<<One>>] loop:<<Loop>> outer_loop:none 409 /// CHECK-DAG: <<Cnv:b\d+>> TypeConversion [<<Add>>] loop:<<Loop>> outer_loop:none 410 /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>> outer_loop:none 411 // 412 /// CHECK-START-ARM: void Main.typeConv(byte[], byte[]) loop_optimization (after) 413 /// CHECK-DAG: <<One:i\d+>> IntConstant 1 loop:none 414 415 /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<One>>] loop:none 416 /// CHECK-DAG: <<Load:d\d+>> VecLoad [{{l\d+}},<<Phi1:i\d+>>] loop:<<Loop1:B\d+>> outer_loop:none 417 /// CHECK-DAG: <<Vadd:d\d+>> VecAdd [<<Load>>,<<Repl>>] loop:<<Loop1>> outer_loop:none 418 /// CHECK-DAG: VecStore [{{l\d+}},<<Phi1>>,<<Vadd>>] loop:<<Loop1>> outer_loop:none 419 /// CHECK-DAG: <<Get:b\d+>> ArrayGet [{{l\d+}},<<Phi2:i\d+>>] loop:<<Loop2:B\d+>> outer_loop:none 420 /// CHECK-DAG: <<Add:i\d+>> Add [<<Get>>,<<One>>] loop:<<Loop2>> outer_loop:none 421 /// CHECK-DAG: <<Cnv:b\d+>> TypeConversion [<<Add>>] loop:<<Loop2>> outer_loop:none 422 /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi2>>,<<Cnv>>] loop:<<Loop2>> outer_loop:none 423 // 424 /// CHECK-START-ARM64: void Main.typeConv(byte[], byte[]) loop_optimization (after) 425 /// CHECK-DAG: <<One:i\d+>> IntConstant 1 loop:none 426 /// CHECK-IF: hasIsaFeature("sve") 427 // 428 /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<One>>,{{j\d+}}] loop:none 429 /// CHECK-DAG: <<LoopP:j\d+>> VecPredWhile loop:<<Loop1:B\d+>> outer_loop:none 430 /// CHECK-DAG: <<Load:d\d+>> VecLoad [{{l\d+}},<<Phi1:i\d+>>,<<LoopP>>] loop:<<Loop1>> outer_loop:none 431 /// CHECK-DAG: <<Vadd:d\d+>> VecAdd [<<Load>>,<<Repl>>,<<LoopP>>] loop:<<Loop1>> outer_loop:none 432 /// CHECK-DAG: VecStore [{{l\d+}},<<Phi1>>,<<Vadd>>,<<LoopP>>] loop:<<Loop1>> outer_loop:none 433 // 434 /// CHECK-ELSE: 435 // 436 /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<One>>] loop:none 437 /// CHECK-DAG: <<Load:d\d+>> VecLoad [{{l\d+}},<<Phi1:i\d+>>] loop:<<Loop1:B\d+>> outer_loop:none 438 /// CHECK-DAG: <<Vadd:d\d+>> VecAdd [<<Load>>,<<Repl>>] loop:<<Loop1>> outer_loop:none 439 /// CHECK-DAG: VecStore [{{l\d+}},<<Phi1>>,<<Vadd>>] loop:<<Loop1>> outer_loop:none 440 /// CHECK-DAG: <<Get:b\d+>> ArrayGet [{{l\d+}},<<Phi2:i\d+>>] loop:<<Loop2:B\d+>> outer_loop:none 441 /// CHECK-DAG: <<Add:i\d+>> Add [<<Get>>,<<One>>] loop:<<Loop2>> outer_loop:none 442 /// CHECK-DAG: <<Cnv:b\d+>> TypeConversion [<<Add>>] loop:<<Loop2>> outer_loop:none 443 /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi2>>,<<Cnv>>] loop:<<Loop2>> outer_loop:none 444 // 445 /// CHECK-FI: 446 // 447 // Scalar code in cleanup loop uses correct byte type on array get and type conversion. typeConv(byte[] a, byte[] b)448 private static void typeConv(byte[] a, byte[] b) { 449 int len = Math.min(a.length, b.length); 450 for (int i = 0; i < len; i++) { 451 a[i] = (byte) (b[i] + 1); 452 } 453 } 454 455 // Environment of an instruction, removed during SimplifyInduction, should be adjusted. 456 // 457 /// CHECK-START: void Main.inductionMax(int[]) loop_optimization (before) 458 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none 459 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none 460 // 461 /// CHECK-START: void Main.inductionMax(int[]) loop_optimization (after) 462 /// CHECK-NOT: Phi inductionMax(int[] a)463 private static void inductionMax(int[] a) { 464 int s = 0; 465 for (int i = 0; i < 10; i++) { 466 s = Math.max(s, 5); 467 } 468 } 469 470 /// CHECK-START: int Main.feedsIntoDeopt(int[]) loop_optimization (before) 471 /// CHECK-DAG: Phi loop:<<Loop1:B\d+>> outer_loop:none 472 /// CHECK-DAG: Phi loop:<<Loop1>> outer_loop:none 473 /// CHECK-DAG: Phi loop:<<Loop2:B\d+>> outer_loop:none 474 // 475 /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>" 476 // 477 /// CHECK-START: int Main.feedsIntoDeopt(int[]) loop_optimization (after) 478 /// CHECK-DAG: Phi loop:{{B\d+}} outer_loop:none 479 /// CHECK-NOT: Phi feedsIntoDeopt(int[] a)480 static int feedsIntoDeopt(int[] a) { 481 // Reduction should be removed. 482 int r = 0; 483 for (int i = 0; i < 100; i++) { 484 r += 10; 485 } 486 // Even though uses feed into deopts of BCE. 487 for (int i = 1; i < 100; i++) { 488 a[i] = a[i - 1]; 489 } 490 return r; 491 } 492 absCanBeNegative(int x)493 static int absCanBeNegative(int x) { 494 int a[] = { 1, 2, 3 }; 495 int y = 0; 496 for (int i = Math.abs(x); i < a.length; i++) { 497 y += a[i]; 498 } 499 return y; 500 } 501 502 // b/65478356: sum up 2-dim array. sum(int[][] a)503 static int sum(int[][] a) { 504 int sum = 0; 505 for (int y = 0; y < a.length; y++) { 506 int[] aa = a[y]; 507 for (int x = 0; x < aa.length; x++) { 508 sum += aa[x]; 509 } 510 } 511 return sum; 512 } 513 514 // Large loop body should not break unrolling computation. largeBody(int[] x)515 static void largeBody(int[] x) { 516 for (int i = 0; i < 100; i++) { 517 x[i] = x[i] * 1 + x[i] * 2 + x[i] * 3 + x[i] * 4 + x[i] * 5 + x[i] * 6 + 518 x[i] * 7 + x[i] * 8 + x[i] * 9 + x[i] * 10 + x[i] * 11 + x[i] * 12 + 519 x[i] * 13 + x[i] * 14 + x[i] * 15 + x[i] * 1 + x[i] * 2 + x[i] * 3 + x[i] * 4 + 520 x[i] * 5 + x[i] * 6 + x[i] * 7 + x[i] * 8 + x[i] * 9 + x[i] * 10 + x[i] * 11 + 521 x[i] * 12 + x[i] * 13 + x[i] * 14 + x[i] * 15 + x[i] * 1 + x[i] * 2 + x[i] * 3 + 522 x[i] * 4 + x[i] * 5; 523 } 524 } 525 526 // Mixed of 16-bit and 8-bit array references. castAndNarrow(byte[] x, char[] y)527 static void castAndNarrow(byte[] x, char[] y) { 528 for (int i = 0; i < x.length; i++) { 529 x[i] = (byte) ((short) y[i] + 1); 530 } 531 } 532 533 // Avoid bad scheduler-SIMD interaction. doNotMoveSIMD()534 static int doNotMoveSIMD() { 535 int sum = 0; 536 for (int j = 0; j <= 8; j++) { 537 int[] a = new int[17]; // a[i] = 0; 538 // ConstructorFence ? 539 for (int i = 0; i < a.length; i++) { 540 a[i] += 1; // a[i] = 1; 541 } 542 for (int i = 0; i < a.length; i++) { 543 sum += a[i]; // expect a[i] = 1; 544 } 545 } 546 return sum; 547 } 548 549 // Ensure spilling saves full SIMD values. reduction32Values(int[] a, int[] b, int[] c, int[] d)550 private static final int reduction32Values(int[] a, int[] b, int[] c, int[] d) { 551 int s0 = 0; 552 int s1 = 0; 553 int s2 = 0; 554 int s3 = 0; 555 int s4 = 0; 556 int s5 = 0; 557 int s6 = 0; 558 int s7 = 0; 559 int s8 = 0; 560 int s9 = 0; 561 int s10 = 0; 562 int s11 = 0; 563 int s12 = 0; 564 int s13 = 0; 565 int s14 = 0; 566 int s15 = 0; 567 int s16 = 0; 568 int s17 = 0; 569 int s18 = 0; 570 int s19 = 0; 571 int s20 = 0; 572 int s21 = 0; 573 int s22 = 0; 574 int s23 = 0; 575 int s24 = 0; 576 int s25 = 0; 577 int s26 = 0; 578 int s27 = 0; 579 int s28 = 0; 580 int s29 = 0; 581 int s30 = 0; 582 int s31 = 0; 583 for (int i = 1; i < 100; i++) { 584 s0 += a[i]; 585 s1 += b[i]; 586 s2 += c[i]; 587 s3 += d[i]; 588 s4 += a[i]; 589 s5 += b[i]; 590 s6 += c[i]; 591 s7 += d[i]; 592 s8 += a[i]; 593 s9 += b[i]; 594 s10 += c[i]; 595 s11 += d[i]; 596 s12 += a[i]; 597 s13 += b[i]; 598 s14 += c[i]; 599 s15 += d[i]; 600 s16 += a[i]; 601 s17 += b[i]; 602 s18 += c[i]; 603 s19 += d[i]; 604 s20 += a[i]; 605 s21 += b[i]; 606 s22 += c[i]; 607 s23 += d[i]; 608 s24 += a[i]; 609 s25 += b[i]; 610 s26 += c[i]; 611 s27 += d[i]; 612 s28 += a[i]; 613 s29 += b[i]; 614 s30 += c[i]; 615 s31 += d[i]; 616 } 617 return s0 + s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10 + s11 + s12 + s13 + s14 + s15 + 618 s16 + s17 + s18 + s19 + s20 + s21 + s22 + s23 + 619 s24 + s25 + s26 + s27 + s28 + s29 + s30 + s31; 620 } 621 622 // Ensure spilling saves regular FP values correctly when the graph HasSIMD() 623 // is true. 624 /// CHECK-START-ARM64: float Main.$noinline$ensureSlowPathFPSpillFill(float[], float[], float[], float[], int[]) loop_optimization (after) 625 // 626 // Both regular and SIMD accesses are present. 627 /// CHECK-DAG: VecLoad 628 /// CHECK-DAG: ArrayGet $noinline$ensureSlowPathFPSpillFill(float[] a, float[] b, float[] c, float[] d, int[] e)629 private static final float $noinline$ensureSlowPathFPSpillFill(float[] a, 630 float[] b, 631 float[] c, 632 float[] d, 633 int[] e) { 634 // This loop should be vectorized so the graph->HasSIMD() will be true. 635 // A power-of-2 number of iterations is chosen to avoid peeling/unrolling interference. 636 for (int i = 0; i < 64; i++) { 637 // The actual values of the array elements don't matter, just the 638 // presence of a SIMD loop. 639 e[i]++; 640 } 641 642 float f0 = 0; 643 float f1 = 0; 644 float f2 = 0; 645 float f3 = 0; 646 float f4 = 0; 647 float f5 = 0; 648 float f6 = 0; 649 float f7 = 0; 650 float f8 = 0; 651 float f9 = 0; 652 float f10 = 0; 653 float f11 = 0; 654 float f12 = 0; 655 float f13 = 0; 656 float f14 = 0; 657 float f15 = 0; 658 float f16 = 0; 659 float f17 = 0; 660 float f18 = 0; 661 float f19 = 0; 662 float f20 = 0; 663 float f21 = 0; 664 float f22 = 0; 665 float f23 = 0; 666 float f24 = 0; 667 float f25 = 0; 668 float f26 = 0; 669 float f27 = 0; 670 float f28 = 0; 671 float f29 = 0; 672 float f30 = 0; 673 float f31 = 0; 674 for (int i = 0; i < 100; i++) { 675 f0 += a[i]; 676 f1 += b[i]; 677 f2 += c[i]; 678 f3 += d[i]; 679 f4 += a[i]; 680 f5 += b[i]; 681 f6 += c[i]; 682 f7 += d[i]; 683 f8 += a[i]; 684 f9 += b[i]; 685 f10 += c[i]; 686 f11 += d[i]; 687 f12 += a[i]; 688 f13 += b[i]; 689 f14 += c[i]; 690 f15 += d[i]; 691 f16 += a[i]; 692 f17 += b[i]; 693 f18 += c[i]; 694 f19 += d[i]; 695 f20 += a[i]; 696 f21 += b[i]; 697 f22 += c[i]; 698 f23 += d[i]; 699 f24 += a[i]; 700 f25 += b[i]; 701 f26 += c[i]; 702 f27 += d[i]; 703 f28 += a[i]; 704 f29 += b[i]; 705 f30 += c[i]; 706 f31 += d[i]; 707 } 708 return f0 + f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9 + f10 + f11 + f12 + f13 + f14 + f15 + 709 f16 + f17 + f18 + f19 + f20 + f21 + f22 + f23 + 710 f24 + f25 + f26 + f27 + f28 + f29 + f30 + f31; 711 } 712 reductionIntoReplication()713 public static int reductionIntoReplication() { 714 int[] a = { 1, 2, 3, 4 }; 715 int x = 0; 716 for (int i = 0; i < 4; i++) { 717 x += a[i]; 718 } 719 for (int i = 0; i < 4; i++) { 720 a[i] = x; 721 } 722 return a[3]; 723 } 724 725 // Dot product and SAD vectorization idioms used to have a bug when some 726 // instruction in the loop was visited twice causing a compiler crash. 727 // It happened when two vectorization idioms' matched patterns had a common 728 // sub-expression. 729 730 // Idioms common sub-expression bug: DotProduct and ArraySet. 731 // 732 /// CHECK-START-ARM64: int Main.testDotProdAndSet(byte[], byte[], byte[]) loop_optimization (after) 733 /// CHECK-DAG: VecDotProd 734 /// CHECK-DAG: VecStore testDotProdAndSet(byte[] a, byte[] b, byte[] c)735 public static final int testDotProdAndSet(byte[] a, byte[] b, byte[] c) { 736 int s = 1; 737 for (int i = 0; i < b.length; i++) { 738 int temp = a[i] * b[i]; 739 c[i]= (byte)temp; 740 s += temp; 741 } 742 return s - 1; 743 } 744 745 // Idioms common sub-expression bug: DotProduct and DotProduct. 746 // 747 /// CHECK-START-ARM64: int Main.testDotProdAndDotProd(byte[], byte[]) loop_optimization (after) 748 /// CHECK-DAG: VecDotProd 749 /// CHECK-DAG: VecDotProd testDotProdAndDotProd(byte[] a, byte[] b)750 public static final int testDotProdAndDotProd(byte[] a, byte[] b) { 751 int s0 = 1; 752 int s1 = 1; 753 for (int i = 0; i < b.length; i++) { 754 int temp = a[i] * b[i]; 755 s0 += temp; 756 s1 += temp; 757 } 758 return s0 + s1; 759 } 760 761 // Idioms common sub-expression bug: SAD and ArraySet. 762 // 763 /// CHECK-START-ARM: int Main.testSADAndSet(int[], int[], int[]) loop_optimization (after) 764 /// CHECK-DAG: VecSADAccumulate 765 /// CHECK-DAG: VecStore 766 // 767 /// CHECK-START-ARM64: int Main.testSADAndSet(int[], int[], int[]) loop_optimization (after) 768 /// CHECK-IF: hasIsaFeature("sve") 769 // 770 // VecSADAccumulate is not supported for SVE. 771 /// CHECK-NOT: VecSADAccumulate 772 // 773 /// CHECK-ELSE: 774 // 775 /// CHECK-DAG: VecSADAccumulate 776 /// CHECK-DAG: VecStore 777 // 778 /// CHECK-FI: testSADAndSet(int[] x, int[] y, int[] z)779 public static int testSADAndSet(int[] x, int[] y, int[] z) { 780 int min_length = Math.min(x.length, y.length); 781 int sad = 0; 782 for (int i = 0; i < min_length; i++) { 783 int temp = Math.abs(x[i] - y[i]); 784 z[i] = temp; 785 sad += temp; 786 } 787 return sad; 788 } 789 790 // Idioms common sub-expression bug: SAD and SAD. 791 /// CHECK-START-ARM: int Main.testSADAndSAD(int[], int[]) loop_optimization (after) 792 /// CHECK-DAG: VecSADAccumulate 793 /// CHECK-DAG: VecSADAccumulate 794 // 795 /// CHECK-START-ARM64: int Main.testSADAndSAD(int[], int[]) loop_optimization (after) 796 /// CHECK-IF: hasIsaFeature("sve") 797 // 798 // VecSADAccumulate is not supported for SVE. 799 /// CHECK-NOT: VecSADAccumulate 800 // 801 /// CHECK-ELSE: 802 // 803 /// CHECK-DAG: VecSADAccumulate 804 /// CHECK-DAG: VecSADAccumulate 805 // 806 /// CHECK-FI: testSADAndSAD(int[] x, int[] y)807 public static final int testSADAndSAD(int[] x, int[] y) { 808 int s0 = 1; 809 int s1 = 1; 810 for (int i = 0; i < x.length; i++) { 811 int temp = Math.abs(x[i] - y[i]); 812 s0 += temp; 813 s1 += temp; 814 } 815 return s0 + s1; 816 } 817 818 // Idioms common sub-expression bug: DotProd and DotProd with extra mul. 819 // 820 /// CHECK-START-ARM64: int Main.testDotProdAndDotProdExtraMul0(byte[], byte[]) loop_optimization (after) 821 /// CHECK-DAG: VecMul 822 /// CHECK-DAG: VecDotProd 823 /// CHECK-DAG: VecDotProd testDotProdAndDotProdExtraMul0(byte[] a, byte[] b)824 public static final int testDotProdAndDotProdExtraMul0(byte[] a, byte[] b) { 825 int s0 = 1; 826 int s1 = 1; 827 for (int i = 0; i < b.length; i++) { 828 int temp0 = a[i] * b[i]; 829 int temp1 = (byte)(temp0) * a[i]; 830 s0 += temp1; 831 s1 += temp0; 832 } 833 return s0 + s1; 834 } 835 836 // Idioms common sub-expression bug: DotProd and DotProd with extra mul (reversed order). 837 // 838 /// CHECK-START-ARM64: int Main.testDotProdAndDotProdExtraMul1(byte[], byte[]) loop_optimization (after) 839 /// CHECK-DAG: VecMul 840 /// CHECK-DAG: VecDotProd 841 /// CHECK-DAG: VecDotProd testDotProdAndDotProdExtraMul1(byte[] a, byte[] b)842 public static final int testDotProdAndDotProdExtraMul1(byte[] a, byte[] b) { 843 int s0 = 1; 844 int s1 = 1; 845 for (int i = 0; i < b.length; i++) { 846 int temp0 = a[i] * b[i]; 847 int temp1 = (byte)(temp0) * a[i]; 848 s0 += temp0; 849 s1 += temp1; 850 } 851 return s0 + s1; 852 } 853 854 // Idioms common sub-expression bug: SAD and SAD with extra abs. 855 // 856 /// CHECK-START-ARM: int Main.testSADAndSADExtraAbs0(int[], int[]) loop_optimization (after) 857 /// CHECK-DAG: VecSub 858 /// CHECK-DAG: VecAbs 859 /// CHECK-DAG: VecSADAccumulate 860 /// CHECK-DAG: VecSADAccumulate 861 // 862 /// CHECK-START-ARM64: int Main.testSADAndSADExtraAbs0(int[], int[]) loop_optimization (after) 863 /// CHECK-IF: hasIsaFeature("sve") 864 // 865 // VecSADAccumulate is not supported for SVE. 866 /// CHECK-NOT: VecSADAccumulate 867 // 868 /// CHECK-ELSE: 869 // 870 /// CHECK-DAG: VecSub 871 /// CHECK-DAG: VecAbs 872 /// CHECK-DAG: VecSADAccumulate 873 /// CHECK-DAG: VecSADAccumulate 874 // 875 /// CHECK-FI: testSADAndSADExtraAbs0(int[] x, int[] y)876 public static final int testSADAndSADExtraAbs0(int[] x, int[] y) { 877 int s0 = 1; 878 int s1 = 1; 879 for (int i = 0; i < x.length; i++) { 880 int temp0 = Math.abs(x[i] - y[i]); 881 int temp1 = Math.abs(temp0 - y[i]); 882 s0 += temp1; 883 s1 += temp0; 884 } 885 return s0 + s1; 886 } 887 888 // Idioms common sub-expression bug: SAD and SAD with extra abs (reversed order). 889 // 890 /// CHECK-START-ARM: int Main.testSADAndSADExtraAbs1(int[], int[]) loop_optimization (after) 891 /// CHECK-DAG: VecSub 892 /// CHECK-DAG: VecAbs 893 /// CHECK-DAG: VecSADAccumulate 894 /// CHECK-DAG: VecSADAccumulate 895 // 896 /// CHECK-START-ARM64: int Main.testSADAndSADExtraAbs1(int[], int[]) loop_optimization (after) 897 /// CHECK-IF: hasIsaFeature("sve") 898 // 899 // VecSADAccumulate is not supported for SVE. 900 /// CHECK-NOT: VecSADAccumulate 901 // 902 /// CHECK-ELSE: 903 // 904 /// CHECK-DAG: VecSub 905 /// CHECK-DAG: VecAbs 906 /// CHECK-DAG: VecSADAccumulate 907 /// CHECK-DAG: VecSADAccumulate 908 // 909 /// CHECK-FI: testSADAndSADExtraAbs1(int[] x, int[] y)910 public static final int testSADAndSADExtraAbs1(int[] x, int[] y) { 911 int s0 = 1; 912 int s1 = 1; 913 for (int i = 0; i < x.length; i++) { 914 int temp0 = Math.abs(x[i] - y[i]); 915 int temp1 = Math.abs(temp0 - y[i]); 916 s0 += temp0; 917 s1 += temp1; 918 } 919 return s0 + s1; 920 } 921 922 923 // Idioms common sub-expression bug: SAD and DotProd combined. 924 // 925 /// CHECK-START-ARM64: int Main.testSADAndDotProdCombined0(byte[], byte[]) loop_optimization (after) 926 /// CHECK-IF: hasIsaFeature("sve") 927 // 928 // VecSADAccumulate is not supported for SVE. 929 /// CHECK-NOT: VecSADAccumulate 930 // 931 /// CHECK-ELSE: 932 // 933 /// CHECK-DAG: VecSub 934 /// CHECK-DAG: VecSADAccumulate 935 /// CHECK-DAG: VecDotProd 936 // 937 /// CHECK-FI: testSADAndDotProdCombined0(byte[] x, byte[] y)938 public static final int testSADAndDotProdCombined0(byte[] x, byte[] y) { 939 int s0 = 1; 940 int s1 = 1; 941 for (int i = 0; i < x.length; i++) { 942 int temp0 = x[i] - y[i]; 943 int temp1 = Math.abs(temp0); 944 int temp2 = x[i] * (byte)(temp0); 945 946 s0 += temp1; 947 s1 += temp2; 948 } 949 return s0 + s1; 950 } 951 952 // Idioms common sub-expression bug: SAD and DotProd combined (reversed order). 953 /// CHECK-START-ARM64: int Main.testSADAndDotProdCombined1(byte[], byte[]) loop_optimization (after) 954 /// CHECK-IF: hasIsaFeature("sve") 955 // 956 // VecSADAccumulate is not supported for SVE. 957 /// CHECK-NOT: VecSADAccumulate 958 // 959 /// CHECK-ELSE: 960 // 961 /// CHECK-DAG: VecSub 962 /// CHECK-DAG: VecSADAccumulate 963 /// CHECK-DAG: VecDotProd 964 // 965 /// CHECK-FI: testSADAndDotProdCombined1(byte[] x, byte[] y)966 public static final int testSADAndDotProdCombined1(byte[] x, byte[] y) { 967 int s0 = 1; 968 int s1 = 1; 969 for (int i = 0; i < x.length; i++) { 970 int temp0 = x[i] - y[i]; 971 int temp1 = Math.abs(temp0); 972 int temp2 = x[i] * (byte)(temp0); 973 974 s0 += temp2; 975 s1 += temp1; 976 } 977 return s0 + s1; 978 } 979 980 public static final int ARRAY_SIZE = 512; 981 createAndInitByteArray(int x)982 private static byte[] createAndInitByteArray(int x) { 983 byte[] a = new byte[ARRAY_SIZE]; 984 for (int i = 0; i < a.length; i++) { 985 a[i] = (byte)((~i) + x); 986 } 987 return a; 988 } 989 createAndInitIntArray(int x)990 private static int[] createAndInitIntArray(int x) { 991 int[] a = new int[ARRAY_SIZE]; 992 for (int i = 0; i < a.length; i++) { 993 a[i] = (~i) + x; 994 } 995 return a; 996 } 997 main(String[] args)998 public static void main(String[] args) { 999 System.loadLibrary(args[0]); 1000 1001 expectEquals(10, earlyExitFirst(-1)); 1002 for (int i = 0; i <= 10; i++) { 1003 expectEquals(i, earlyExitFirst(i)); 1004 } 1005 expectEquals(10, earlyExitFirst(11)); 1006 1007 expectEquals(10, earlyExitLast(-1)); 1008 for (int i = 0; i < 10; i++) { 1009 expectEquals(i + 1, earlyExitLast(i)); 1010 } 1011 expectEquals(10, earlyExitLast(10)); 1012 expectEquals(10, earlyExitLast(11)); 1013 1014 expectEquals(2, earlyExitNested()); 1015 1016 expectEquals(17, transferNarrowWrap()); 1017 expectEquals(-45, polynomialShort()); 1018 expectEquals(-45, polynomialIntFromLong()); 1019 expectEquals(-45, polynomialInt()); 1020 1021 expectEquals(0, geoIntDivLastValue(0)); 1022 expectEquals(0, geoIntDivLastValue(1)); 1023 expectEquals(0, geoIntDivLastValue(2)); 1024 expectEquals(0, geoIntDivLastValue(1081788608)); 1025 expectEquals(0, geoIntDivLastValue(-1081788608)); 1026 expectEquals(0, geoIntDivLastValue(2147483647)); 1027 expectEquals(0, geoIntDivLastValue(-2147483648)); 1028 1029 expectEquals( 0, geoIntMulLastValue(0)); 1030 expectEquals( -194211840, geoIntMulLastValue(1)); 1031 expectEquals( -388423680, geoIntMulLastValue(2)); 1032 expectEquals(-1041498112, geoIntMulLastValue(1081788608)); 1033 expectEquals( 1041498112, geoIntMulLastValue(-1081788608)); 1034 expectEquals( 194211840, geoIntMulLastValue(2147483647)); 1035 expectEquals( 0, geoIntMulLastValue(-2147483648)); 1036 1037 expectEquals(0L, geoLongDivLastValue(0L)); 1038 expectEquals(0L, geoLongDivLastValue(1L)); 1039 expectEquals(0L, geoLongDivLastValue(2L)); 1040 expectEquals(0L, geoLongDivLastValue(1081788608L)); 1041 expectEquals(0L, geoLongDivLastValue(-1081788608L)); 1042 expectEquals(0L, geoLongDivLastValue(2147483647L)); 1043 expectEquals(0L, geoLongDivLastValue(-2147483648L)); 1044 expectEquals(0L, geoLongDivLastValue(9223372036854775807L)); 1045 expectEquals(0L, geoLongDivLastValue(-9223372036854775808L)); 1046 1047 expectEquals(0L, geoLongDivLastValue()); 1048 1049 expectEquals( 0L, geoLongMulLastValue(0L)); 1050 expectEquals(-8070450532247928832L, geoLongMulLastValue(1L)); 1051 expectEquals( 2305843009213693952L, geoLongMulLastValue(2L)); 1052 expectEquals( 0L, geoLongMulLastValue(1081788608L)); 1053 expectEquals( 0L, geoLongMulLastValue(-1081788608L)); 1054 expectEquals( 8070450532247928832L, geoLongMulLastValue(2147483647L)); 1055 expectEquals( 0L, geoLongMulLastValue(-2147483648L)); 1056 expectEquals( 8070450532247928832L, geoLongMulLastValue(9223372036854775807L)); 1057 expectEquals( 0L, geoLongMulLastValue(-9223372036854775808L)); 1058 1059 float[] a = new float[16]; 1060 narrowingSubscript(a); 1061 for (int i = 0; i < 16; i++) { 1062 expectEquals(2.0f, a[i]); 1063 } 1064 1065 int[] xx = new int[2]; 1066 int[] yy = new int[469]; 1067 reduc(xx, yy); 1068 expectEquals(-469, xx[0]); 1069 expectEquals(-938, xx[1]); 1070 for (int i = 0; i < 469; i++) { 1071 expectEquals(2, yy[i]); 1072 } 1073 1074 char[] aa = new char[23]; 1075 String bb = "hello world how are you"; 1076 string2Bytes(aa, bb); 1077 for (int i = 0; i < aa.length; i++) { 1078 expectEquals(aa[i], bb.charAt(i)); 1079 } 1080 String cc = "\u1010\u2020llo world how are y\u3030\u4040"; 1081 string2Bytes(aa, cc); 1082 for (int i = 0; i < aa.length; i++) { 1083 expectEquals(aa[i], cc.charAt(i)); 1084 } 1085 1086 short[] s2s = new short[12]; 1087 $noinline$stringToShorts(s2s, "abcdefghijkl"); 1088 for (int i = 0; i < s2s.length; ++i) { 1089 expectEquals((short) "abcdefghijkl".charAt(i), s2s[i]); 1090 } 1091 1092 envUsesInCond(); 1093 1094 short[] dd = new short[23]; 1095 oneBoth(dd, aa); 1096 for (int i = 0; i < aa.length; i++) { 1097 expectEquals(aa[i], 1); 1098 expectEquals(dd[i], 1); 1099 } 1100 1101 xx[0] = 10; 1102 byte[] bt = new byte[10]; 1103 arrayInTripCount(xx, bt, 20); 1104 for (int i = 0; i < bt.length; i++) { 1105 expectEquals(40, bt[i]); 1106 } 1107 1108 byte[] b1 = new byte[259]; // few extra iterations 1109 byte[] b2 = new byte[259]; 1110 for (int i = 0; i < 259; i++) { 1111 b1[i] = 0; 1112 b2[i] = (byte) i; 1113 } 1114 typeConv(b1, b2); 1115 for (int i = 0; i < 259; i++) { 1116 expectEquals((byte)(i + 1), b1[i]); 1117 } 1118 1119 inductionMax(yy); 1120 1121 int[] f = new int[100]; 1122 f[0] = 11; 1123 expectEquals(1000, feedsIntoDeopt(f)); 1124 for (int i = 0; i < 100; i++) { 1125 expectEquals(11, f[i]); 1126 } 1127 1128 expectEquals(0, absCanBeNegative(-3)); 1129 expectEquals(3, absCanBeNegative(-2)); 1130 expectEquals(5, absCanBeNegative(-1)); 1131 expectEquals(6, absCanBeNegative(0)); 1132 expectEquals(5, absCanBeNegative(1)); 1133 expectEquals(3, absCanBeNegative(2)); 1134 expectEquals(0, absCanBeNegative(3)); 1135 expectEquals(0, absCanBeNegative(Integer.MAX_VALUE)); 1136 // Abs(min_int) = min_int. 1137 int verify = 0; 1138 try { 1139 absCanBeNegative(Integer.MIN_VALUE); 1140 verify = 1; 1141 } catch (ArrayIndexOutOfBoundsException e) { 1142 verify = 2; 1143 } 1144 expectEquals(2, verify); 1145 1146 int[][] x = new int[128][128]; 1147 for (int i = 0; i < 128; i++) { 1148 for (int j = 0; j < 128; j++) { 1149 x[i][j] = -i - j; 1150 } 1151 } 1152 expectEquals(-2080768, sum(x)); 1153 1154 largeBody(f); 1155 for (int i = 0; i < 100; i++) { 1156 expectEquals(2805, f[i]); 1157 } 1158 1159 char[] cx = new char[259]; 1160 for (int i = 0; i < 259; i++) { 1161 cx[i] = (char) (i - 100); 1162 } 1163 castAndNarrow(b1, cx); 1164 for (int i = 0; i < 259; i++) { 1165 expectEquals((byte)((short) cx[i] + 1), b1[i]); 1166 } 1167 1168 expectEquals(153, doNotMoveSIMD()); 1169 1170 // This test exposed SIMDization issues on x86 and x86_64 1171 // so we make sure the test runs with JIT enabled. 1172 ensureJitCompiled(Main.class, "reduction32Values"); 1173 { 1174 int[] a1 = new int[100]; 1175 int[] a2 = new int[100]; 1176 int[] a3 = new int[100]; 1177 int[] a4 = new int[100]; 1178 for (int i = 0; i < 100; i++) { 1179 a1[i] = i; 1180 a2[i] = 1; 1181 a3[i] = 100 - i; 1182 a4[i] = i % 16; 1183 } 1184 expectEquals(85800, reduction32Values(a1, a2, a3, a4)); 1185 } 1186 { 1187 float[] a1 = new float[100]; 1188 float[] a2 = new float[100]; 1189 float[] a3 = new float[100]; 1190 float[] a4 = new float[100]; 1191 int[] a5 = new int[100]; 1192 1193 for (int i = 0; i < 100; i++) { 1194 a1[i] = (float)i; 1195 a2[i] = (float)1; 1196 a3[i] = (float)(100 - i); 1197 a4[i] = (i % 16); 1198 } 1199 expectEquals(86608.0f, $noinline$ensureSlowPathFPSpillFill(a1, a2, a3, a4, a5)); 1200 } 1201 1202 expectEquals(10, reductionIntoReplication()); 1203 1204 { 1205 byte[] b_a = createAndInitByteArray(1); 1206 byte[] b_b = createAndInitByteArray(2); 1207 byte[] b_c = createAndInitByteArray(3); 1208 expectEquals(2731008, testDotProdAndSet(b_a, b_b, b_c)); 1209 } 1210 { 1211 byte[] b_a = createAndInitByteArray(1); 1212 byte[] b_b = createAndInitByteArray(2); 1213 expectEquals(5462018, testDotProdAndDotProd(b_a, b_b)); 1214 } 1215 { 1216 int[] i_a = createAndInitIntArray(1); 1217 int[] i_b = createAndInitIntArray(2); 1218 int[] i_c = createAndInitIntArray(3); 1219 expectEquals(512, testSADAndSet(i_a, i_b, i_c)); 1220 } 1221 { 1222 int[] i_a = createAndInitIntArray(1); 1223 int[] i_b = createAndInitIntArray(2); 1224 expectEquals(1026, testSADAndSAD(i_a, i_b)); 1225 } 1226 { 1227 byte[] b_a = createAndInitByteArray(1); 1228 byte[] b_b = createAndInitByteArray(2); 1229 expectEquals(2731266, testDotProdAndDotProdExtraMul0(b_a, b_b)); 1230 } 1231 { 1232 byte[] b_a = createAndInitByteArray(1); 1233 byte[] b_b = createAndInitByteArray(2); 1234 expectEquals(2731266, testDotProdAndDotProdExtraMul1(b_a, b_b)); 1235 } 1236 { 1237 int[] i_a = createAndInitIntArray(1); 1238 int[] i_b = createAndInitIntArray(2); 1239 expectEquals(131330, testSADAndSADExtraAbs0(i_a, i_b)); 1240 } 1241 { 1242 int[] i_a = createAndInitIntArray(1); 1243 int[] i_b = createAndInitIntArray(2); 1244 expectEquals(131330, testSADAndSADExtraAbs1(i_a, i_b)); 1245 } 1246 { 1247 byte[] b_a = createAndInitByteArray(1); 1248 byte[] b_b = createAndInitByteArray(2); 1249 expectEquals(1278, testSADAndDotProdCombined0(b_a, b_b)); 1250 } 1251 { 1252 byte[] b_a = createAndInitByteArray(1); 1253 byte[] b_b = createAndInitByteArray(2); 1254 expectEquals(1278, testSADAndDotProdCombined1(b_a, b_b)); 1255 } 1256 1257 System.out.println("passed"); 1258 } 1259 expectEquals(int expected, int result)1260 private static void expectEquals(int expected, int result) { 1261 if (expected != result) { 1262 throw new Error("Expected: " + expected + ", found: " + result); 1263 } 1264 } 1265 expectEquals(long expected, long result)1266 private static void expectEquals(long expected, long result) { 1267 if (expected != result) { 1268 throw new Error("Expected: " + expected + ", found: " + result); 1269 } 1270 } 1271 expectEquals(float expected, float result)1272 private static void expectEquals(float expected, float result) { 1273 if (expected != result) { 1274 throw new Error("Expected: " + expected + ", found: " + result); 1275 } 1276 } 1277 } 1278