1 /* 2 * Copyright (c) 2022, 2023, Arm Limited. All rights reserved. 3 * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25 /* 26 * @test 27 * @summary Vectorization test on array type conversions 28 * @library /test/lib / 29 * 30 * @build jdk.test.whitebox.WhiteBox 31 * compiler.vectorization.runner.VectorizationTestRunner 32 * 33 * @requires vm.compiler2.enabled 34 * 35 * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox 36 * 37 * @run main/othervm -Xbootclasspath/a:. 38 * -XX:+UnlockDiagnosticVMOptions 39 * -XX:+WhiteBoxAPI 40 * compiler.vectorization.runner.ArrayTypeConvertTest nCOH_nAV 41 * 42 * @run main/othervm -Xbootclasspath/a:. 43 * -XX:+UnlockDiagnosticVMOptions 44 * -XX:+WhiteBoxAPI 45 * compiler.vectorization.runner.ArrayTypeConvertTest nCOH_yAV 46 * 47 * @run main/othervm -Xbootclasspath/a:. 48 * -XX:+UnlockDiagnosticVMOptions 49 * -XX:+WhiteBoxAPI 50 * compiler.vectorization.runner.ArrayTypeConvertTest yCOH_nAV 51 * 52 * @run main/othervm -Xbootclasspath/a:. 53 * -XX:+UnlockDiagnosticVMOptions 54 * -XX:+WhiteBoxAPI 55 * compiler.vectorization.runner.ArrayTypeConvertTest yCOH_yAV 56 */ 57 58 package compiler.vectorization.runner; 59 60 import compiler.lib.ir_framework.*; 61 62 // Explanation about AlignVector: we require 8-byte alignment of all addresses. 63 // But the array base offset changes with UseCompactObjectHeaders. 64 // It should, however, not affect the alignment constraints. 65 66 public class ArrayTypeConvertTest extends VectorizationTestRunner { 67 68 // We must pass the flags directly to the test-VM, and not the driver vm in the @run above. 69 @Override 70 protected String[] testVMFlags(String[] args) { 71 return switch (args[0]) { 72 case "nCOH_nAV" -> new String[]{"-XX:+UnlockExperimentalVMOptions", "-XX:-UseCompactObjectHeaders", "-XX:-AlignVector"}; 73 case "nCOH_yAV" -> new String[]{"-XX:+UnlockExperimentalVMOptions", "-XX:-UseCompactObjectHeaders", "-XX:+AlignVector"}; 74 case "yCOH_nAV" -> new String[]{"-XX:+UnlockExperimentalVMOptions", "-XX:+UseCompactObjectHeaders", "-XX:-AlignVector"}; 75 case "yCOH_yAV" -> new String[]{"-XX:+UnlockExperimentalVMOptions", "-XX:+UseCompactObjectHeaders", "-XX:+AlignVector"}; 76 default -> { throw new RuntimeException("Test argument not recognized: " + args[0]); } 77 }; 78 } 79 80 private static final int SIZE = 543; 81 82 private byte[] bytes; 83 private short[] shorts; 84 private char[] chars; 85 private int[] ints; 86 private long[] longs; 87 private float[] floats; 88 private double[] doubles; 89 90 public ArrayTypeConvertTest() { 91 bytes = new byte[SIZE]; 92 shorts = new short[SIZE]; 93 chars = new char[SIZE]; 94 ints = new int[SIZE]; 95 longs = new long[SIZE]; 96 floats = new float[SIZE]; 97 doubles = new double[SIZE]; 98 for (int i = 0; i < SIZE; i++) { 99 bytes[i] = (byte) (-i / 128); 100 shorts[i] = (short) (i / 3 - 12345); 101 chars[i] = (char) (i * 2); 102 ints[i] = -22 * i; 103 longs[i] = -258L * i + 99L; 104 floats[i] = (float) (i * 2.498f); 105 doubles[i] = -3 * i; 106 } 107 } 108 109 // ---------------- Integer Extension ---------------- 110 @Test 111 @IR(failOn = {IRNode.STORE_VECTOR}) 112 // Subword vector casts do not work currently, see JDK-8342095. 113 // Assert the vectorization failure so that we are reminded to update 114 // the test when this limitation is addressed in the future. 115 public int[] signExtension() { 116 int[] res = new int[SIZE]; 117 for (int i = 0; i < SIZE; i++) { 118 res[i] = shorts[i]; 119 } 120 return res; 121 } 122 123 @Test 124 @IR(failOn = {IRNode.STORE_VECTOR}) 125 // Subword vector casts do not work currently, see JDK-8342095. 126 // Assert the vectorization failure so that we are reminded to update 127 // the test when this limitation is addressed in the future. 128 public int[] zeroExtension() { 129 int[] res = new int[SIZE]; 130 for (int i = 0; i < SIZE; i++) { 131 res[i] = chars[i]; 132 } 133 return res; 134 } 135 136 @Test 137 @IR(failOn = {IRNode.STORE_VECTOR}) 138 // Subword vector casts do not work currently, see JDK-8342095. 139 // Assert the vectorization failure so that we are reminded to update 140 // the test when this limitation is addressed in the future. 141 public int[] signExtensionFromByte() { 142 int[] res = new int[SIZE]; 143 for (int i = 0; i < SIZE; i++) { 144 res[i] = bytes[i]; 145 } 146 return res; 147 } 148 149 // ---------------- Integer Narrow ---------------- 150 @Test 151 @IR(failOn = {IRNode.STORE_VECTOR}) 152 // Subword vector casts do not work currently, see JDK-8342095. 153 // Assert the vectorization failure so that we are reminded to update 154 // the test when this limitation is addressed in the future. 155 public short[] narrowToSigned() { 156 short[] res = new short[SIZE]; 157 for (int i = 0; i < SIZE; i++) { 158 res[i] = (short) ints[i]; 159 } 160 return res; 161 } 162 163 @Test 164 @IR(failOn = {IRNode.STORE_VECTOR}) 165 // Subword vector casts do not work currently, see JDK-8342095. 166 // Assert the vectorization failure so that we are reminded to update 167 // the test when this limitation is addressed in the future. 168 public char[] narrowToUnsigned() { 169 char[] res = new char[SIZE]; 170 for (int i = 0; i < SIZE; i++) { 171 res[i] = (char) ints[i]; 172 } 173 return res; 174 } 175 176 @Test 177 @IR(failOn = {IRNode.STORE_VECTOR}) 178 // Subword vector casts do not work currently, see JDK-8342095. 179 // Assert the vectorization failure so that we are reminded to update 180 // the test when this limitation is addressed in the future. 181 public byte[] NarrowToByte() { 182 byte[] res = new byte[SIZE]; 183 for (int i = 0; i < SIZE; i++) { 184 res[i] = (byte) ints[i]; 185 } 186 return res; 187 } 188 189 // ---------------- Convert I/L to F/D ---------------- 190 @Test 191 @IR(applyIfCPUFeatureOr = {"asimd", "true", "avx", "true", "rvv", "true"}, 192 counts = {IRNode.VECTOR_CAST_I2F, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0"}) 193 public float[] convertIntToFloat() { 194 float[] res = new float[SIZE]; 195 for (int i = 0; i < SIZE; i++) { 196 res[i] = (float) ints[i]; 197 } 198 return res; 199 } 200 201 @Test 202 @IR(applyIfCPUFeatureOr = {"asimd", "true", "avx", "true", "rvv", "true"}, 203 counts = {IRNode.VECTOR_CAST_I2D, IRNode.VECTOR_SIZE + "min(max_int, max_double)", ">0"}) 204 public double[] convertIntToDouble() { 205 double[] res = new double[SIZE]; 206 for (int i = 0; i < SIZE; i++) { 207 res[i] = (double) ints[i]; 208 } 209 return res; 210 } 211 212 @Test 213 @IR(applyIfCPUFeatureOr = {"sve", "true", "avx512dq", "true", "rvv", "true"}, 214 counts = {IRNode.VECTOR_CAST_L2F, IRNode.VECTOR_SIZE + "min(max_long, max_float)", ">0"}) 215 public float[] convertLongToFloat() { 216 float[] res = new float[SIZE]; 217 for (int i = 0; i < SIZE; i++) { 218 res[i] = (float) longs[i]; 219 } 220 return res; 221 } 222 223 @Test 224 @IR(applyIfCPUFeatureOr = {"asimd", "true", "avx512dq", "true", "rvv", "true"}, 225 counts = {IRNode.VECTOR_CAST_L2D, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0"}) 226 public double[] convertLongToDouble() { 227 double[] res = new double[SIZE]; 228 for (int i = 0; i < SIZE; i++) { 229 res[i] = (double) longs[i]; 230 } 231 return res; 232 } 233 234 // ---------------- Convert Subword-I to F/D ---------------- 235 @Test 236 @IR(applyIfCPUFeatureOr = {"asimd", "true", "avx2", "true", "rvv", "true"}, 237 counts = {IRNode.VECTOR_CAST_S2F, IRNode.VECTOR_SIZE + "min(max_short, max_float)", ">0"}) 238 public float[] convertShortToFloat() { 239 float[] res = new float[SIZE]; 240 for (int i = 0; i < SIZE; i++) { 241 res[i] = (float) shorts[i]; 242 } 243 return res; 244 } 245 246 @Test 247 @IR(applyIfCPUFeatureOr = {"sve", "true", "avx2", "true", "rvv", "true"}, 248 applyIf = {"MaxVectorSize", ">=32"}, 249 counts = {IRNode.VECTOR_CAST_S2D, IRNode.VECTOR_SIZE + "min(max_short, max_double)", ">0"}) 250 public double[] convertShortToDouble() { 251 double[] res = new double[SIZE]; 252 for (int i = 0; i < SIZE; i++) { 253 res[i] = (double) shorts[i]; 254 } 255 return res; 256 } 257 258 @Test 259 @IR(failOn = {IRNode.STORE_VECTOR}) 260 // Subword vector casts do not work currently, see JDK-8342095. 261 // Assert the vectorization failure so that we are reminded to update 262 // the test when this limitation is addressed in the future. 263 public float[] convertCharToFloat() { 264 float[] res = new float[SIZE]; 265 for (int i = 0; i < SIZE; i++) { 266 res[i] = (float) chars[i]; 267 } 268 return res; 269 } 270 271 @Test 272 @IR(failOn = {IRNode.STORE_VECTOR}) 273 // Subword vector casts do not work currently, see JDK-8342095. 274 // Assert the vectorization failure so that we are reminded to update 275 // the test when this limitation is addressed in the future. 276 public double[] convertCharToDouble() { 277 double[] res = new double[SIZE]; 278 for (int i = 0; i < SIZE; i++) { 279 res[i] = (double) chars[i]; 280 } 281 return res; 282 } 283 284 // ---------------- Convert F/D to I/L ---------------- 285 @Test 286 @IR(applyIfCPUFeatureOr = {"asimd", "true", "avx", "true", "rvv", "true"}, 287 counts = {IRNode.VECTOR_CAST_F2I, IRNode.VECTOR_SIZE + "min(max_float, max_int)", ">0"}) 288 public int[] convertFloatToInt() { 289 int[] res = new int[SIZE]; 290 for (int i = 0; i < SIZE; i++) { 291 res[i] = (int) floats[i]; 292 } 293 return res; 294 } 295 296 @Test 297 @IR(applyIfCPUFeatureOr = {"asimd", "true", "avx512dq", "true", "rvv", "true"}, 298 counts = {IRNode.VECTOR_CAST_F2L, IRNode.VECTOR_SIZE + "min(max_float, max_long)", ">0"}) 299 public long[] convertFloatToLong() { 300 long[] res = new long[SIZE]; 301 for (int i = 0; i < SIZE; i++) { 302 res[i] = (long) floats[i]; 303 } 304 return res; 305 } 306 307 @Test 308 @IR(applyIfCPUFeatureOr = {"sve", "true", "avx", "true", "rvv", "true"}, 309 counts = {IRNode.VECTOR_CAST_D2I, IRNode.VECTOR_SIZE + "min(max_double, max_int)", ">0"}) 310 public int[] convertDoubleToInt() { 311 int[] res = new int[SIZE]; 312 for (int i = 0; i < SIZE; i++) { 313 res[i] = (int) doubles[i]; 314 } 315 return res; 316 } 317 318 @Test 319 @IR(applyIfCPUFeatureOr = {"asimd", "true", "avx512dq", "true", "rvv", "true"}, 320 counts = {IRNode.VECTOR_CAST_D2L, IRNode.VECTOR_SIZE + "min(max_double, max_long)", ">0"}) 321 public long[] convertDoubleToLong() { 322 long[] res = new long[SIZE]; 323 for (int i = 0; i < SIZE; i++) { 324 res[i] = (long) doubles[i]; 325 } 326 return res; 327 } 328 329 // ---------------- Convert F/D to Subword-I ---------------- 330 @Test 331 @IR(applyIfCPUFeatureOr = {"asimd", "true", "avx2", "true", "rvv", "true"}, 332 counts = {IRNode.VECTOR_CAST_F2S, IRNode.VECTOR_SIZE + "min(max_float, max_short)", ">0"}) 333 public short[] convertFloatToShort() { 334 short[] res = new short[SIZE]; 335 for (int i = 0; i < SIZE; i++) { 336 res[i] = (short) floats[i]; 337 } 338 return res; 339 } 340 341 @Test 342 @IR(applyIfCPUFeatureOr = {"asimd", "true", "avx2", "true", "rvv", "true"}, 343 counts = {IRNode.VECTOR_CAST_F2S, IRNode.VECTOR_SIZE + "min(max_float, max_char)", ">0"}) 344 public char[] convertFloatToChar() { 345 char[] res = new char[SIZE]; 346 for (int i = 0; i < SIZE; i++) { 347 res[i] = (char) floats[i]; 348 } 349 return res; 350 } 351 352 @Test 353 @IR(applyIfCPUFeatureOr = {"sve", "true", "avx", "true", "rvv", "true"}, 354 applyIf = {"MaxVectorSize", ">=32"}, 355 counts = {IRNode.VECTOR_CAST_D2S, IRNode.VECTOR_SIZE + "min(max_double, max_short)", ">0"}) 356 public short[] convertDoubleToShort() { 357 short[] res = new short[SIZE]; 358 for (int i = 0; i < SIZE; i++) { 359 res[i] = (short) doubles[i]; 360 } 361 return res; 362 } 363 364 @Test 365 @IR(applyIfCPUFeatureOr = {"sve", "true", "avx", "true", "rvv", "true"}, 366 applyIf = {"MaxVectorSize", ">=32"}, 367 counts = {IRNode.VECTOR_CAST_D2S, IRNode.VECTOR_SIZE + "min(max_double, max_char)", ">0"}) 368 public char[] convertDoubleToChar() { 369 char[] res = new char[SIZE]; 370 for (int i = 0; i < SIZE; i++) { 371 res[i] = (char) doubles[i]; 372 } 373 return res; 374 } 375 376 // ---------------- Convert Between F & D ---------------- 377 @Test 378 @IR(applyIfCPUFeatureOr = {"asimd", "true", "avx", "true", "rvv", "true"}, 379 counts = {IRNode.VECTOR_CAST_F2D, IRNode.VECTOR_SIZE + "min(max_float, max_double)", ">0"}) 380 public double[] convertFloatToDouble() { 381 double[] res = new double[SIZE]; 382 for (int i = 0; i < SIZE; i++) { 383 res[i] = (double) floats[i]; 384 } 385 return res; 386 } 387 388 @Test 389 @IR(applyIfCPUFeatureOr = {"asimd", "true", "avx", "true", "rvv", "true"}, 390 counts = {IRNode.VECTOR_CAST_D2F, IRNode.VECTOR_SIZE + "min(max_double, max_float)", ">0"}) 391 public float[] convertDoubleToFloat() { 392 float[] res = new float[SIZE]; 393 for (int i = 0; i < SIZE; i++) { 394 res[i] = (float) doubles[i]; 395 } 396 return res; 397 } 398 }