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