1 /*
2 * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 /**
25 * @test
26 * @bug 8294588
27 * @summary Auto-vectorize Float.floatToFloat16, Float.float16ToFloat APIs
28 * @requires vm.compiler2.enabled
29 * @library /test/lib /
30 * @run driver compiler.vectorization.TestFloatConversionsVector
31 */
32
33 package compiler.vectorization;
34
35 import java.util.Set;
36
37 import compiler.lib.ir_framework.*;
38 import jdk.test.lib.Asserts;
39
40 public class TestFloatConversionsVector {
41 private static final int ARRLEN = 1024;
42 private static final int ITERS = 11000;
43 private static float [] finp;
44 private static short [] sout;
45 private static short [] sinp;
46 private static float [] fout;
47
48 public static void main(String args[]) {
49 TestFramework framework = new TestFramework(TestFloatConversionsVector.class);
50 framework.addFlags("-XX:-TieredCompilation", "-XX:CompileThresholdScaling=0.3");
51 framework.addCrossProductScenarios(Set.of("-XX:-UseCompactObjectHeaders", "-XX:+UseCompactObjectHeaders"),
52 Set.of("-XX:-AlignVector", "-XX:+AlignVector"));
53 framework.start();
54 System.out.println("PASSED");
55 }
56
57 @Test
58 @IR(counts = {IRNode.VECTOR_CAST_F2HF, IRNode.VECTOR_SIZE + "min(max_float, max_short)", "> 0"},
59 applyIfOr = {"UseCompactObjectHeaders", "false", "AlignVector", "false"},
60 applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"},
61 applyIfCPUFeatureOr = {"f16c", "true", "avx512f", "true", "zvfh", "true", "asimd", "true", "sve", "true"})
62 public void test_float_float16(short[] sout, float[] finp) {
63 for (int i = 0; i < finp.length; i++) {
64 sout[i] = Float.floatToFloat16(finp[i]);
65 // With AlignVector, we need 8-byte alignment of vector loads/stores.
66 // UseCompactObjectHeaders=false UseCompactObjectHeaders=true
67 // F_adr = base + 16 + 4*i -> i % 2 = 0 F_adr = base + 12 + 4*i -> i % 2 = 1
68 // S_adr = base + 16 + 2*i -> i % 4 = 0 S_adr = base + 12 + 2*i -> i % 4 = 2
69 // -> vectorize -> no vectorization
70 }
71 }
72
73 @Test
74 public void test_float_float16_strided(short[] sout, float[] finp) {
75 for (int i = 0; i < finp.length/2; i++) {
76 sout[i*2] = Float.floatToFloat16(finp[i*2]);
77 }
78 }
79
80 @Test
81 @IR(counts = {IRNode.VECTOR_CAST_F2HF, IRNode.VECTOR_SIZE_2, "> 0"},
82 applyIfOr = {"UseCompactObjectHeaders", "false", "AlignVector", "false"},
83 applyIfCPUFeature = {"asimd", "true"})
84 public void test_float_float16_short_vector(short[] sout, float[] finp) {
85 for (int i = 0; i < finp.length; i += 4) {
86 sout[i] = Float.floatToFloat16(finp[i]);
87 sout[i + 1] = Float.floatToFloat16(finp[i + 1]);
88 }
89 }
90
91 @Run(test = {"test_float_float16", "test_float_float16_strided",
92 "test_float_float16_short_vector"}, mode = RunMode.STANDALONE)
93 public void kernel_test_float_float16() {
94 finp = new float[ARRLEN];
95 sout = new short[ARRLEN];
96
97 for (int i = 0; i < ARRLEN; i++) {
98 finp[i] = (float) i * 1.4f;
99 }
100
101 for (int i = 0; i < ITERS; i++) {
102 test_float_float16(sout, finp);
103 }
104
105 // Verifying the result
106 for (int i = 0; i < ARRLEN; i++) {
107 Asserts.assertEquals(Float.floatToFloat16(finp[i]), sout[i]);
108 }
109
110 for (int i = 0; i < ITERS; i++) {
111 test_float_float16_strided(sout, finp);
112 }
113
114 // Verifying the result
115 for (int i = 0; i < ARRLEN/2; i++) {
116 Asserts.assertEquals(Float.floatToFloat16(finp[i*2]), sout[i*2]);
117 }
118
119 for (int i = 0; i < ITERS; i++) {
120 test_float_float16_short_vector(sout, finp);
121 }
122
123 // Verifying the result
124 for (int i = 0; i < ARRLEN; i += 4) {
125 Asserts.assertEquals(Float.floatToFloat16(finp[i]), sout[i]);
126 Asserts.assertEquals(Float.floatToFloat16(finp[i + 1]), sout[i + 1]);
127 }
128 }
129
130 @Test
131 @IR(counts = {IRNode.VECTOR_CAST_HF2F, IRNode.VECTOR_SIZE + "min(max_float, max_short)", "> 0"},
132 applyIfOr = {"UseCompactObjectHeaders", "false", "AlignVector", "false"},
133 applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"},
134 applyIfCPUFeatureOr = {"f16c", "true", "avx512f", "true", "zvfh", "true", "asimd", "true", "sve", "true"})
135 public void test_float16_float(float[] fout, short[] sinp) {
136 for (int i = 0; i < sinp.length; i++) {
137 fout[i] = Float.float16ToFloat(sinp[i]);
138 // With AlignVector, we need 8-byte alignment of vector loads/stores.
139 // UseCompactObjectHeaders=false UseCompactObjectHeaders=true
140 // F_adr = base + 16 + 4*i -> i % 2 = 0 F_adr = base + 12 + 4*i -> i % 2 = 1
141 // S_adr = base + 16 + 2*i -> i % 4 = 0 S_adr = base + 12 + 2*i -> i % 4 = 2
142 // -> vectorize -> no vectorization
143 }
144 }
145
146 @Test
147 public void test_float16_float_strided(float[] fout, short[] sinp) {
148 for (int i = 0; i < sinp.length/2; i++) {
149 fout[i*2] = Float.float16ToFloat(sinp[i*2]);
150 }
151 }
152
153 @Test
154 @IR(counts = {IRNode.VECTOR_CAST_HF2F, IRNode.VECTOR_SIZE_2, "> 0"},
155 applyIfOr = {"UseCompactObjectHeaders", "false", "AlignVector", "false"},
156 applyIfCPUFeature = {"asimd", "true"})
157 public void test_float16_float_short_vector(float[] fout, short[] sinp) {
158 for (int i = 0; i < sinp.length; i += 4) {
159 fout[i] = Float.float16ToFloat(sinp[i]);
160 fout[i + 1] = Float.float16ToFloat(sinp[i + 1]);
161 }
162 }
163
164 @Run(test = {"test_float16_float", "test_float16_float_strided",
165 "test_float16_float_short_vector"}, mode = RunMode.STANDALONE)
166 public void kernel_test_float16_float() {
167 sinp = new short[ARRLEN];
168 fout = new float[ARRLEN];
169
170 for (int i = 0; i < ARRLEN; i++) {
171 sinp[i] = (short)i;
172 }
173
174 for (int i = 0; i < ITERS; i++) {
175 test_float16_float(fout, sinp);
176 }
177
178 // Verifying the result
179 for (int i = 0; i < ARRLEN; i++) {
180 Asserts.assertEquals(Float.float16ToFloat(sinp[i]), fout[i]);
181 }
182
183 for (int i = 0; i < ITERS; i++) {
184 test_float16_float_strided(fout, sinp);
185 }
186
187 // Verifying the result
188 for (int i = 0; i < ARRLEN/2; i++) {
189 Asserts.assertEquals(Float.float16ToFloat(sinp[i*2]), fout[i*2]);
190 }
191
192 for (int i = 0; i < ITERS; i++) {
193 test_float16_float_short_vector(fout, sinp);
194 }
195
196 // Verifying the result
197 for (int i = 0; i < ARRLEN; i += 4) {
198 Asserts.assertEquals(Float.float16ToFloat(sinp[i]), fout[i]);
199 Asserts.assertEquals(Float.float16ToFloat(sinp[i + 1]), fout[i + 1]);
200 }
201 }
202 }