1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /** 18 * Tests for autovectorization of loops with control flow. 19 */ 20 public class Main { 21 22 public static final int ARRAY_LENGTH = 128; 23 public static final int USED_ARRAY_LENGTH = ARRAY_LENGTH - 1; 24 25 public static boolean[] booleanArray = new boolean[ARRAY_LENGTH]; 26 public static boolean[] booleanArray2 = new boolean[ARRAY_LENGTH]; 27 public static byte[] byteArray = new byte[ARRAY_LENGTH]; 28 public static short[] shortArray = new short[ARRAY_LENGTH]; 29 public static char[] charArray = new char[ARRAY_LENGTH]; 30 public static int[] intArray = new int[ARRAY_LENGTH]; 31 public static long[] longArray = new long[ARRAY_LENGTH]; 32 public static float[] floatArray = new float[ARRAY_LENGTH]; 33 public static double[] doubleArray = new double[ARRAY_LENGTH]; 34 35 public static final int MAGIC_VALUE_A = 2; 36 public static final int MAGIC_VALUE_B = 10; 37 public static final int MAGIC_VALUE_C = 100; 38 39 public static final int MAGIC_ADD_CONST = 99; 40 41 public static final float MAGIC_FLOAT_VALUE_A = 2.0f; 42 public static final float MAGIC_FLOAT_VALUE_B = 10.0f; 43 public static final float MAGIC_FLOAT_VALUE_C = 100.0f; 44 45 public static final float MAGIC_FLOAT_ADD_CONST = 99.0f; 46 47 /// CHECK-START-ARM64: int Main.$compile$noinline$FullDiamond(int[]) loop_optimization (after) 48 /// CHECK-IF: hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true' 49 // 50 /// CHECK-DAG: <<C0:i\d+>> IntConstant 0 loop:none 51 /// CHECK-DAG: <<C4:i\d+>> IntConstant 4 loop:none 52 /// CHECK-DAG: <<C99:i\d+>> IntConstant 99 loop:none 53 /// CHECK-DAG: <<C100:i\d+>> IntConstant 100 loop:none 54 /// CHECK-DAG: <<Vec4:d\d+>> VecReplicateScalar [<<C4>>,{{j\d+}}] loop:none 55 /// CHECK-DAG: <<Vec99:d\d+>> VecReplicateScalar [<<C99>>,{{j\d+}}] loop:none 56 /// CHECK-DAG: <<Vec100:d\d+>> VecReplicateScalar [<<C100>>,{{j\d+}}] loop:none 57 // 58 /// CHECK-DAG: <<Phi:i\d+>> Phi [<<C0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none 59 /// CHECK-DAG: <<LoopP:j\d+>> VecPredWhile [<<Phi>>,{{i\d+}}] loop:<<Loop>> outer_loop:none 60 // 61 /// CHECK-DAG: <<Load1:d\d+>> VecLoad [<<Arr:l\d+>>,<<Phi>>,<<LoopP>>] loop:<<Loop>> outer_loop:none 62 /// CHECK-DAG: <<Cond:j\d+>> VecEqual [<<Load1>>,<<Vec100>>,<<LoopP>>] loop:<<Loop>> outer_loop:none 63 /// CHECK-DAG: <<CondR:j\d+>> VecPredNot [<<Cond>>,<<LoopP>>] loop:<<Loop>> outer_loop:none 64 /// CHECK-DAG: <<AddT:d\d+>> VecAdd [<<Load1>>,<<Vec99>>,<<CondR>>] loop:<<Loop>> outer_loop:none 65 /// CHECK-DAG: <<StT:d\d+>> VecStore [<<Arr>>,<<Phi>>,<<AddT>>,<<CondR>>] loop:<<Loop>> outer_loop:none 66 /// CHECK-DAG: <<StF:d\d+>> VecStore [<<Arr>>,<<Phi>>,{{d\d+}},<<Cond>>] loop:<<Loop>> outer_loop:none 67 /// CHECK-DAG: <<Ld2:d\d+>> VecLoad [<<Arr>>,<<Phi>>,<<LoopP>>] loop:<<Loop>> outer_loop:none 68 /// CHECK-DAG: <<Add2:d\d+>> VecAdd [<<Ld2>>,<<Vec4>>,<<LoopP>>] loop:<<Loop>> outer_loop:none 69 /// CHECK-DAG: <<St21:d\d+>> VecStore [<<Arr>>,<<Phi>>,<<Add2>>,<<LoopP>>] loop:<<Loop>> outer_loop:none 70 // 71 /// CHECK-ELSE: 72 // 73 /// CHECK-NOT: VecLoad 74 // 75 /// CHECK-FI: $compile$noinline$FullDiamond(int[] x)76 public static int $compile$noinline$FullDiamond(int[] x) { 77 int i = 0; 78 for (; i < USED_ARRAY_LENGTH; i++) { 79 int val = x[i]; 80 if (val != MAGIC_VALUE_C) { 81 x[i] += MAGIC_ADD_CONST; 82 } else { 83 x[i] += 3; 84 } 85 x[i] += 4; 86 } 87 return i; 88 } 89 90 // 91 // Test various types. 92 // 93 94 /// CHECK-START-ARM64: void Main.$compile$noinline$SimpleBoolean(boolean[], boolean[]) loop_optimization (after) 95 /// CHECK-IF: hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true' 96 // 97 /// CHECK-NOT: VecLoad 98 // 99 /// CHECK-FI: 100 // 101 // TODO: Support extra condition types and boolean comparisons. $compile$noinline$SimpleBoolean(boolean[] x, boolean[] y)102 public static void $compile$noinline$SimpleBoolean(boolean[] x, boolean[] y) { 103 for (int i = 0; i < USED_ARRAY_LENGTH; i++) { 104 boolean val = x[i]; 105 if (val != y[i]) { 106 x[i] |= y[i]; 107 } 108 } 109 } 110 111 /// CHECK-START-ARM64: void Main.$compile$noinline$SimpleByte(byte[]) loop_optimization (after) 112 /// CHECK-IF: hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true' 113 // 114 /// CHECK-DAG: VecLoad 115 // 116 /// CHECK-FI: $compile$noinline$SimpleByte(byte[] x)117 public static void $compile$noinline$SimpleByte(byte[] x) { 118 for (int i = 0; i < USED_ARRAY_LENGTH; i++) { 119 byte val = x[i]; 120 if (val != MAGIC_VALUE_C) { 121 x[i] += MAGIC_ADD_CONST; 122 } 123 } 124 } 125 126 /// CHECK-START-ARM64: void Main.$compile$noinline$SimpleUByte(byte[]) loop_optimization (after) 127 /// CHECK-IF: hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true' 128 // 129 /// CHECK-DAG: VecLoad 130 // 131 /// CHECK-FI: $compile$noinline$SimpleUByte(byte[] x)132 public static void $compile$noinline$SimpleUByte(byte[] x) { 133 for (int i = 0; i < USED_ARRAY_LENGTH; i++) { 134 if ((x[i] & 0xFF) != MAGIC_VALUE_C) { 135 x[i] += MAGIC_ADD_CONST; 136 } 137 } 138 } 139 140 /// CHECK-START-ARM64: void Main.$compile$noinline$SimpleShort(short[]) loop_optimization (after) 141 /// CHECK-IF: hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true' 142 // 143 /// CHECK-DAG: VecLoad 144 // 145 /// CHECK-FI: $compile$noinline$SimpleShort(short[] x)146 public static void $compile$noinline$SimpleShort(short[] x) { 147 for (int i = 0; i < USED_ARRAY_LENGTH; i++) { 148 short val = x[i]; 149 if (val != MAGIC_VALUE_C) { 150 x[i] += MAGIC_ADD_CONST; 151 } 152 } 153 } 154 155 /// CHECK-START-ARM64: void Main.$compile$noinline$SimpleChar(char[]) loop_optimization (after) 156 /// CHECK-IF: hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true' 157 // 158 /// CHECK-DAG: VecLoad 159 // 160 /// CHECK-FI: $compile$noinline$SimpleChar(char[] x)161 public static void $compile$noinline$SimpleChar(char[] x) { 162 for (int i = 0; i < USED_ARRAY_LENGTH; i++) { 163 char val = x[i]; 164 if (val != MAGIC_VALUE_C) { 165 x[i] += MAGIC_ADD_CONST; 166 } 167 } 168 } 169 170 /// CHECK-START-ARM64: void Main.$compile$noinline$SimpleInt(int[]) loop_optimization (after) 171 /// CHECK-IF: hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true' 172 // 173 /// CHECK-DAG: VecLoad 174 // 175 /// CHECK-FI: $compile$noinline$SimpleInt(int[] x)176 public static void $compile$noinline$SimpleInt(int[] x) { 177 for (int i = 0; i < USED_ARRAY_LENGTH; i++) { 178 int val = x[i]; 179 if (val != MAGIC_VALUE_C) { 180 x[i] += MAGIC_ADD_CONST; 181 } 182 } 183 } 184 185 /// CHECK-START-ARM64: void Main.$compile$noinline$SimpleLong(long[]) loop_optimization (after) 186 /// CHECK-IF: hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true' 187 // 188 /// CHECK-NOT: VecLoad 189 // 190 /// CHECK-FI: 191 // 192 // TODO: Support long comparisons. $compile$noinline$SimpleLong(long[] x)193 public static void $compile$noinline$SimpleLong(long[] x) { 194 for (int i = 0; i < USED_ARRAY_LENGTH; i++) { 195 long val = x[i]; 196 if (val != MAGIC_VALUE_C) { 197 x[i] += MAGIC_ADD_CONST; 198 } 199 } 200 } 201 202 /// CHECK-START-ARM64: void Main.$compile$noinline$SimpleFloat(float[]) loop_optimization (after) 203 /// CHECK-IF: hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true' 204 // 205 /// CHECK-NOT: VecLoad 206 // 207 /// CHECK-FI: 208 // 209 // TODO: Support FP comparisons. $compile$noinline$SimpleFloat(float[] x)210 public static void $compile$noinline$SimpleFloat(float[] x) { 211 for (int i = 0; i < USED_ARRAY_LENGTH; i++) { 212 float val = x[i]; 213 if (val > 10.0f) { 214 x[i] += 99.1f; 215 } 216 } 217 } 218 219 /// CHECK-START-ARM64: void Main.$compile$noinline$SimpleDouble(double[]) loop_optimization (after) 220 /// CHECK-IF: hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true' 221 // 222 /// CHECK-NOT: VecLoad 223 // 224 /// CHECK-FI: 225 // 226 // TODO: Support FP comparisons. $compile$noinline$SimpleDouble(double[] x)227 public static void $compile$noinline$SimpleDouble(double[] x) { 228 for (int i = 0; i < USED_ARRAY_LENGTH; i++) { 229 double val = x[i]; 230 if (val != 10.0) { 231 x[i] += 99.1; 232 } 233 } 234 } 235 236 // 237 // Narrowing types. 238 // 239 240 /// CHECK-START-ARM64: void Main.$compile$noinline$ByteConv(byte[], byte[]) loop_optimization (after) 241 /// CHECK-IF: hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true' 242 // 243 /// CHECK-DAG: VecLoad 244 // 245 /// CHECK-FI: $compile$noinline$ByteConv(byte[] x, byte[] y)246 public static void $compile$noinline$ByteConv(byte[] x, byte[] y) { 247 for (int i = 0; i < USED_ARRAY_LENGTH; i++) { 248 byte val = (byte)(x[i] + 1); 249 if (val != y[i]) { 250 x[i] += MAGIC_ADD_CONST; 251 } 252 } 253 } 254 255 /// CHECK-START-ARM64: void Main.$compile$noinline$UByteAndWrongConst(byte[]) loop_optimization (after) 256 /// CHECK-IF: hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true' 257 // 258 /// CHECK-NOT: VecLoad 259 // 260 /// CHECK-FI: 261 // 262 // 'NarrowerOperands' not met: the constant is not a ubyte one. $compile$noinline$UByteAndWrongConst(byte[] x)263 public static void $compile$noinline$UByteAndWrongConst(byte[] x) { 264 for (int i = 0; i < USED_ARRAY_LENGTH; i++) { 265 if ((x[i] & 0xFF) != (MAGIC_VALUE_C | 0x100)) { 266 x[i] += MAGIC_ADD_CONST; 267 } 268 } 269 } 270 271 /// CHECK-START-ARM64: void Main.$compile$noinline$ByteNoHiBits(byte[], byte[]) loop_optimization (after) 272 /// CHECK-IF: hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true' 273 // 274 /// CHECK-NOT: VecLoad 275 // 276 /// CHECK-FI: 277 // 278 // Check kNoHiBits case when "wider" operations cannot bring in higher order bits. $compile$noinline$ByteNoHiBits(byte[] x, byte[] y)279 public static void $compile$noinline$ByteNoHiBits(byte[] x, byte[] y) { 280 for (int i = 0; i < USED_ARRAY_LENGTH; i++) { 281 byte val = x[i]; 282 if ((val >>> 3) != y[i]) { 283 x[i] += MAGIC_ADD_CONST; 284 } 285 } 286 } 287 288 // 289 // Test condition types. 290 // 291 292 /// CHECK-START-ARM64: void Main.$compile$noinline$SimpleCondition(int[]) loop_optimization (before) 293 // 294 /// CHECK-DAG: <<C0:i\d+>> IntConstant 0 loop:none 295 /// CHECK-DAG: <<C100:i\d+>> IntConstant 100 loop:none 296 /// CHECK-DAG: <<C199:i\d+>> IntConstant 199 loop:none 297 // 298 /// CHECK-DAG: <<Phi:i\d+>> Phi [<<C0>>,{{i\d+}}] loop:<<Loop:B\d+>> 299 /// CHECK-DAG: <<Load:i\d+>> ArrayGet [<<Arr:l\d+>>,<<Phi>>] loop:<<Loop>> 300 /// CHECK-DAG: <<Cond:z\d+>> NotEqual [<<Load>>,<<C100>>] loop:<<Loop>> 301 /// CHECK-DAG: If [<<Cond>>] loop:<<Loop>> 302 // 303 /// CHECK-DAG: ArraySet [<<Arr>>,<<Phi>>,<<C199>>] loop:<<Loop>> 304 // 305 /// CHECK-START-ARM64: void Main.$compile$noinline$SimpleCondition(int[]) loop_optimization (after) 306 /// CHECK-IF: hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true' 307 // 308 /// CHECK-DAG: <<C0:i\d+>> IntConstant 0 loop:none 309 /// CHECK-DAG: <<C100:i\d+>> IntConstant 100 loop:none 310 /// CHECK-DAG: <<C199:i\d+>> IntConstant 199 loop:none 311 // 312 /// CHECK-DAG: <<Vec100:d\d+>> VecReplicateScalar [<<C100>>,{{j\d+}}] packed_type:Int32 loop:none 313 /// CHECK-DAG: <<Vec199:d\d+>> VecReplicateScalar [<<C199>>,{{j\d+}}] packed_type:Int32 loop:none 314 // 315 /// CHECK-DAG: <<Phi:i\d+>> Phi [<<C0>>,{{i\d+}}] loop:<<Loop:B\d+>> 316 /// CHECK-DAG: <<LoopP:j\d+>> VecPredWhile [<<Phi>>,{{i\d+}}] loop:<<Loop>> 317 // 318 /// CHECK-DAG: <<Load:d\d+>> VecLoad [<<Arr:l\d+>>,<<Phi>>,<<LoopP>>] packed_type:Int32 loop:<<Loop>> 319 /// CHECK-DAG: <<Cond:j\d+>> VecNotEqual [<<Load>>,<<Vec100>>,<<LoopP>>] packed_type:Int32 loop:<<Loop>> 320 /// CHECK-DAG: <<CondR:j\d+>> VecPredNot [<<Cond>>,<<LoopP>>] packed_type:Int32 loop:<<Loop>> 321 /// CHECK-DAG: VecStore [<<Arr>>,<<Phi>>,<<Vec199>>,<<CondR>>] packed_type:Int32 loop:<<Loop>> 322 // 323 /// CHECK-FI: 324 // 325 // Example of a condition being vectorized. See loop_optimization_test.cc and codegen_test.cc for 326 // full testing of vector conditions. $compile$noinline$SimpleCondition(int[] x)327 public static void $compile$noinline$SimpleCondition(int[] x) { 328 for (int i = 0; i < USED_ARRAY_LENGTH; i++) { 329 int val = x[i]; 330 if (val == MAGIC_VALUE_C) { 331 x[i] += MAGIC_ADD_CONST; 332 } 333 } 334 } 335 336 // 337 // Test vectorization idioms. 338 // 339 340 /// CHECK-START-ARM64: void Main.$compile$noinline$Select(int[]) loop_optimization (after) 341 /// CHECK-IF: hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true' 342 // 343 /// CHECK-NOT: VecLoad 344 // 345 /// CHECK-FI: 346 // 347 // TODO: vectorize loops with select in the body. $compile$noinline$Select(int[] x)348 public static void $compile$noinline$Select(int[] x) { 349 for (int i = 0; i < USED_ARRAY_LENGTH; i++) { 350 int val = x[i]; 351 if (val != MAGIC_VALUE_C) { 352 val += MAGIC_ADD_CONST; 353 } 354 x[i] = val; 355 } 356 } 357 358 /// CHECK-START-ARM64: void Main.$compile$noinline$Phi(int[]) loop_optimization (after) 359 /// CHECK-IF: hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true' 360 // 361 /// CHECK-NOT: VecLoad 362 // 363 /// CHECK-FI: 364 // 365 // TODO: vectorize loops with phis in the body. $compile$noinline$Phi(int[] x)366 public static void $compile$noinline$Phi(int[] x) { 367 for (int i = 0; i < USED_ARRAY_LENGTH; i++) { 368 int val = x[i]; 369 if (val != MAGIC_VALUE_C) { 370 val += MAGIC_ADD_CONST; 371 x[i] += val; 372 } 373 x[i] += val; 374 } 375 } 376 377 // TODO: when Phis are supported, test dotprod and sad idioms. 378 379 /// CHECK-START-ARM64: int Main.$compile$noinline$Reduction(int[]) loop_optimization (after) 380 /// CHECK-IF: hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true' 381 // 382 /// CHECK-NOT: VecLoad 383 // 384 /// CHECK-FI: 385 // 386 // TODO: vectorize loops with phis and reductions in the body. $compile$noinline$Reduction(int[] x)387 private static int $compile$noinline$Reduction(int[] x) { 388 int sum = 0; 389 for (int i = 0; i < ARRAY_LENGTH; i++) { 390 int val = x[i]; 391 if (val != MAGIC_VALUE_C) { 392 sum += val + x[i]; 393 } 394 } 395 return sum; 396 } 397 398 /// CHECK-START-ARM64: int Main.$compile$noinline$ReductionBackEdge(int[]) loop_optimization (after) 399 /// CHECK-IF: hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true' 400 // 401 /// CHECK-DAG: VecLoad 402 // 403 /// CHECK-FI: 404 // 405 // Reduction in the back edge block, non-CF-dependent. $compile$noinline$ReductionBackEdge(int[] x)406 public static int $compile$noinline$ReductionBackEdge(int[] x) { 407 int sum = 0; 408 for (int i = 0; i < USED_ARRAY_LENGTH; i++) { 409 int val = x[i]; 410 if (val != MAGIC_VALUE_C) { 411 x[i] += MAGIC_ADD_CONST; 412 } 413 sum += x[i]; 414 } 415 return sum; 416 } 417 418 // 419 // Negative compile tests. 420 // 421 422 public static final int STENCIL_ARRAY_SIZE = 130; 423 424 /// CHECK-START-ARM64: void Main.$compile$noinline$stencilAlike(int[], int[]) loop_optimization (after) 425 /// CHECK-IF: hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true' 426 // 427 /// CHECK-NOT: VecLoad 428 // 429 /// CHECK-FI: 430 // 431 // This loop needs a runtime test for array references disambiguation and a scalar cleanup loop. 432 // Currently we can't generate a scalar clean up loop with control flow. $compile$noinline$stencilAlike(int[] a, int[] b)433 private static void $compile$noinline$stencilAlike(int[] a, int[] b) { 434 for (int i = 1; i < STENCIL_ARRAY_SIZE - 1; i++) { 435 int val0 = b[i - 1]; 436 int val1 = b[i]; 437 int val2 = b[i + 1]; 438 int un = a[i]; 439 if (val1 != MAGIC_VALUE_C) { 440 a[i] = val0 + val1 + val2; 441 } 442 } 443 } 444 445 /// CHECK-START-ARM64: void Main.$compile$noinline$NotDiamondCf(int[]) loop_optimization (after) 446 /// CHECK-IF: hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true' 447 // 448 /// CHECK-NOT: VecLoad 449 // 450 /// CHECK-FI: 451 // 452 // Loops with complex CF are not supported. $compile$noinline$NotDiamondCf(int[] x)453 public static void $compile$noinline$NotDiamondCf(int[] x) { 454 for (int i = 0; i < USED_ARRAY_LENGTH; i++) { 455 int val = x[i]; 456 if (val != MAGIC_VALUE_C) { 457 if (val != 1234) { 458 x[i] += MAGIC_ADD_CONST; 459 } 460 } 461 } 462 } 463 464 /// CHECK-START-ARM64: void Main.$compile$noinline$BrokenInduction(int[]) loop_optimization (after) 465 /// CHECK-IF: hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true' 466 // 467 /// CHECK-NOT: VecLoad 468 // 469 /// CHECK-FI: $compile$noinline$BrokenInduction(int[] x)470 public static void $compile$noinline$BrokenInduction(int[] x) { 471 for (int i = 0; i < USED_ARRAY_LENGTH; i++) { 472 int val = x[i]; 473 if (val != MAGIC_VALUE_C) { 474 x[i] += MAGIC_ADD_CONST; 475 i++; 476 } 477 } 478 } 479 480 // 481 // Non-condition if statements. 482 // 483 484 /// CHECK-START-ARM64: void Main.$compile$noinline$SingleBoolean(int[], boolean) loop_optimization (after) 485 /// CHECK-IF: hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true' 486 // 487 /// CHECK-NOT: VecLoad 488 // 489 /// CHECK-FI: 490 // 491 // Check that single boolean if statements are not vectorized because only binary condition if 492 // statements are supported. $compile$noinline$SingleBoolean(int[] x, boolean y)493 public static void $compile$noinline$SingleBoolean(int[] x, boolean y) { 494 for (int i = 0; i < USED_ARRAY_LENGTH; i++) { 495 if (y) { 496 x[i] += MAGIC_ADD_CONST; 497 } 498 } 499 } 500 501 /// CHECK-START-ARM64: void Main.$compile$noinline$InstanceOf(int[], java.lang.Object) loop_optimization (after) 502 /// CHECK-IF: hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true' 503 // 504 /// CHECK-NOT: VecLoad 505 // 506 /// CHECK-FI: 507 // 508 // Check that control flow without a condition is not vectorized because only binary condition if 509 // statements are supported. $compile$noinline$InstanceOf(int[] x, Object y)510 public static void $compile$noinline$InstanceOf(int[] x, Object y) { 511 for (int i = 0; i < USED_ARRAY_LENGTH; i++) { 512 if (y instanceof Main) { 513 x[i] += MAGIC_ADD_CONST; 514 } 515 } 516 } 517 518 // 519 // Main driver. 520 // 521 main(String[] args)522 public static void main(String[] args) { 523 initIntArray(intArray); 524 int final_ind_value = $compile$noinline$FullDiamond(intArray); 525 expectIntEquals(23755, IntArraySum(intArray)); 526 expectIntEquals(USED_ARRAY_LENGTH, final_ind_value); 527 528 // Types. 529 initBooleanArray(booleanArray); 530 booleanArray2[12] = true; 531 $compile$noinline$SimpleBoolean(booleanArray, booleanArray2); 532 expectIntEquals(86, BooleanArraySum(booleanArray)); 533 534 initByteArray(byteArray); 535 $compile$noinline$SimpleByte(byteArray); 536 expectIntEquals(-64, ByteArraySum(byteArray)); 537 538 initByteArray(byteArray); 539 $compile$noinline$SimpleUByte(byteArray); 540 expectIntEquals(-64, ByteArraySum(byteArray)); 541 542 initShortArray(shortArray); 543 $compile$noinline$SimpleShort(shortArray); 544 expectIntEquals(23121, ShortArraySum(shortArray)); 545 546 initCharArray(charArray); 547 $compile$noinline$SimpleChar(charArray); 548 expectIntEquals(23121, CharArraySum(charArray)); 549 550 initIntArray(intArray); 551 $compile$noinline$SimpleInt(intArray); 552 expectIntEquals(23121, IntArraySum(intArray)); 553 554 initLongArray(longArray); 555 $compile$noinline$SimpleLong(longArray); 556 expectLongEquals(23121, LongArraySum(longArray)); 557 558 initFloatArray(floatArray); 559 $compile$noinline$SimpleFloat(floatArray); 560 expectFloatEquals(18868.2f, FloatArraySum(floatArray)); 561 562 initDoubleArray(doubleArray); 563 $compile$noinline$SimpleDouble(doubleArray); 564 expectDoubleEquals(23129.5, DoubleArraySum(doubleArray)); 565 566 // Narrowing types. 567 initByteArray(byteArray); 568 $compile$noinline$ByteConv(byteArray, byteArray); 569 expectIntEquals(-2, ByteArraySum(byteArray)); 570 571 initByteArray(byteArray); 572 $compile$noinline$UByteAndWrongConst(byteArray); 573 expectIntEquals(-2, ByteArraySum(byteArray)); 574 575 initByteArray(byteArray); 576 $compile$noinline$ByteNoHiBits(byteArray, byteArray); 577 expectIntEquals(-2, ByteArraySum(byteArray)); 578 579 // Conditions. 580 initIntArray(intArray); 581 $compile$noinline$SimpleCondition(intArray); 582 expectIntEquals(18864, IntArraySum(intArray)); 583 584 // Idioms. 585 initIntArray(intArray); 586 $compile$noinline$Select(intArray); 587 expectIntEquals(23121, IntArraySum(intArray)); 588 589 initIntArray(intArray); 590 $compile$noinline$Phi(intArray); 591 expectIntEquals(36748, IntArraySum(intArray)); 592 593 int reduction_result = 0; 594 595 initIntArray(intArray); 596 reduction_result = $compile$noinline$Reduction(intArray); 597 expectIntEquals(14706, IntArraySum(intArray)); 598 expectIntEquals(21012, reduction_result); 599 600 initIntArray(intArray); 601 reduction_result = $compile$noinline$ReductionBackEdge(intArray); 602 expectIntEquals(23121, IntArraySum(intArray)); 603 expectIntEquals(13121, reduction_result); 604 605 int[] stencilArrayA = new int[STENCIL_ARRAY_SIZE]; 606 int[] stencilArrayB = new int[STENCIL_ARRAY_SIZE]; 607 initIntArray(stencilArrayA); 608 initIntArray(stencilArrayB); 609 $compile$noinline$stencilAlike(stencilArrayA, stencilArrayB); 610 expectIntEquals(43602, IntArraySum(stencilArrayA)); 611 612 initIntArray(intArray); 613 $compile$noinline$NotDiamondCf(intArray); 614 expectIntEquals(23121, IntArraySum(intArray)); 615 616 initIntArray(intArray); 617 $compile$noinline$BrokenInduction(intArray); 618 expectIntEquals(18963, IntArraySum(intArray)); 619 620 // Non-condition if statements. 621 initIntArray(intArray); 622 $compile$noinline$SingleBoolean(intArray, true); 623 expectIntEquals(27279, IntArraySum(intArray)); 624 625 initIntArray(intArray); 626 Main instance = new Main(); 627 $compile$noinline$InstanceOf(intArray, instance); 628 expectIntEquals(27279, IntArraySum(intArray)); 629 630 System.out.println("passed"); 631 } 632 initBooleanArray(boolean[] a)633 public static void initBooleanArray(boolean[] a) { 634 for (int i = 0; i < ARRAY_LENGTH; i++) { 635 if (i % 3 != 0) { 636 a[i] = true; 637 } 638 } 639 } 640 initByteArray(byte[] a)641 public static void initByteArray(byte[] a) { 642 for (int i = 0; i < ARRAY_LENGTH; i++) { 643 if (i % 3 == 0) { 644 a[i] = (byte)MAGIC_VALUE_A; 645 } else if (i % 3 == 1) { 646 a[i] = (byte)MAGIC_VALUE_B; 647 } else { 648 a[i] = (byte)MAGIC_VALUE_C; 649 } 650 } 651 a[USED_ARRAY_LENGTH] = 127; 652 } 653 initShortArray(short[] a)654 public static void initShortArray(short[] a) { 655 for (int i = 0; i < ARRAY_LENGTH; i++) { 656 if (i % 3 == 0) { 657 a[i] = (short)MAGIC_VALUE_A; 658 } else if (i % 3 == 1) { 659 a[i] = (short)MAGIC_VALUE_B; 660 } else { 661 a[i] = (short)MAGIC_VALUE_C; 662 } 663 } 664 a[USED_ARRAY_LENGTH] = 10000; 665 } 666 initCharArray(char[] a)667 public static void initCharArray(char[] a) { 668 for (int i = 0; i < ARRAY_LENGTH; i++) { 669 if (i % 3 == 0) { 670 a[i] = (char)MAGIC_VALUE_A; 671 } else if (i % 3 == 1) { 672 a[i] = (char)MAGIC_VALUE_B; 673 } else { 674 a[i] = (char)MAGIC_VALUE_C; 675 } 676 } 677 a[USED_ARRAY_LENGTH] = 10000; 678 } 679 initIntArray(int[] a)680 public static void initIntArray(int[] a) { 681 for (int i = 0; i < ARRAY_LENGTH; i++) { 682 if (i % 3 == 0) { 683 a[i] = MAGIC_VALUE_A; 684 } else if (i % 3 == 1) { 685 a[i] = MAGIC_VALUE_B; 686 } else { 687 a[i] = MAGIC_VALUE_C; 688 } 689 } 690 a[USED_ARRAY_LENGTH] = 10000; 691 } 692 initLongArray(long[] a)693 public static void initLongArray(long[] a) { 694 for (int i = 0; i < ARRAY_LENGTH; i++) { 695 if (i % 3 == 0) { 696 a[i] = MAGIC_VALUE_A; 697 } else if (i % 3 == 1) { 698 a[i] = MAGIC_VALUE_B; 699 } else { 700 a[i] = MAGIC_VALUE_C; 701 } 702 } 703 a[USED_ARRAY_LENGTH] = 10000; 704 } 705 initFloatArray(float[] a)706 public static void initFloatArray(float[] a) { 707 for (int i = 0; i < ARRAY_LENGTH; i++) { 708 if (i % 3 == 0) { 709 a[i] = MAGIC_FLOAT_VALUE_A; 710 } else if (i % 3 == 1) { 711 a[i] = MAGIC_FLOAT_VALUE_B; 712 } else { 713 a[i] = MAGIC_FLOAT_VALUE_C; 714 } 715 } 716 a[USED_ARRAY_LENGTH] = 10000.0f; 717 } 718 initDoubleArray(double[] a)719 public static void initDoubleArray(double[] a) { 720 for (int i = 0; i < ARRAY_LENGTH; i++) { 721 if (i % 3 == 0) { 722 a[i] = MAGIC_FLOAT_VALUE_A; 723 } else if (i % 3 == 1) { 724 a[i] = MAGIC_FLOAT_VALUE_B; 725 } else { 726 a[i] = MAGIC_FLOAT_VALUE_C; 727 } 728 } 729 a[USED_ARRAY_LENGTH] = 10000.0f; 730 } 731 BooleanArraySum(boolean[] a)732 public static byte BooleanArraySum(boolean[] a) { 733 byte sum = 0; 734 for (int i = 0; i < a.length; i++) { 735 sum += a[i] ? 1 : 0; 736 } 737 return sum; 738 } 739 ByteArraySum(byte[] a)740 public static byte ByteArraySum(byte[] a) { 741 byte sum = 0; 742 for (int i = 0; i < a.length; i++) { 743 sum += a[i]; 744 } 745 return sum; 746 } 747 ShortArraySum(short[] a)748 public static short ShortArraySum(short[] a) { 749 short sum = 0; 750 for (int i = 0; i < a.length; i++) { 751 sum += a[i]; 752 } 753 return sum; 754 } 755 CharArraySum(char[] a)756 public static char CharArraySum(char[] a) { 757 char sum = 0; 758 for (int i = 0; i < a.length; i++) { 759 sum += a[i]; 760 } 761 return sum; 762 } 763 IntArraySum(int[] a)764 public static int IntArraySum(int[] a) { 765 int sum = 0; 766 for (int i = 0; i < a.length; i++) { 767 sum += a[i]; 768 } 769 return sum; 770 } 771 LongArraySum(long[] a)772 public static long LongArraySum(long[] a) { 773 long sum = 0; 774 for (int i = 0; i < a.length; i++) { 775 sum += a[i]; 776 } 777 return sum; 778 } 779 FloatArraySum(float[] a)780 public static float FloatArraySum(float[] a) { 781 float sum = 0.0f; 782 for (int i = 0; i < a.length; i++) { 783 sum += a[i]; 784 } 785 return sum; 786 } 787 DoubleArraySum(double[] a)788 public static double DoubleArraySum(double[] a) { 789 double sum = 0.0; 790 for (int i = 0; i < a.length; i++) { 791 sum += a[i]; 792 } 793 return sum; 794 } 795 expectIntEquals(int expected, int result)796 private static void expectIntEquals(int expected, int result) { 797 if (expected != result) { 798 throw new Error("Expected: " + expected + ", found: " + result); 799 } 800 } 801 expectLongEquals(long expected, long result)802 private static void expectLongEquals(long expected, long result) { 803 if (expected != result) { 804 throw new Error("Expected: " + expected + ", found: " + result); 805 } 806 } 807 expectFloatEquals(float expected, float result)808 private static void expectFloatEquals(float expected, float result) { 809 final float THRESHOLD = .1f; 810 if (Math.abs(expected - result) >= THRESHOLD) { 811 throw new Error("Expected: " + expected + ", found: " + result); 812 } 813 } 814 expectDoubleEquals(double expected, double result)815 private static void expectDoubleEquals(double expected, double result) { 816 final double THRESHOLD = .1; 817 if (Math.abs(expected - result) >= THRESHOLD) { 818 throw new Error("Expected: " + expected + ", found: " + result); 819 } 820 } 821 } 822