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:-UseCompactObjectHeaders", "-XX:-AlignVector"};
73 case "nCOH_yAV" -> new String[]{"-XX:-UseCompactObjectHeaders", "-XX:+AlignVector"};
74 case "yCOH_nAV" -> new String[]{"-XX:+UseCompactObjectHeaders", "-XX:-AlignVector"};
75 case "yCOH_yAV" -> new String[]{"-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 }