1 /*
2 * Copyright (c) 2022, 2024, 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 nCOH_nAV
31 * @run driver compiler.vectorization.TestFloatConversionsVector nCOH_yAV
32 * @run driver compiler.vectorization.TestFloatConversionsVector yCOH_nAV
33 * @run driver compiler.vectorization.TestFloatConversionsVector yCOH_yAV
34 */
35
36 package compiler.vectorization;
37
38 import compiler.lib.ir_framework.*;
39 import jdk.test.lib.Asserts;
40
41 public class TestFloatConversionsVector {
42 private static final int ARRLEN = 1024;
43 private static final int ITERS = 11000;
44 private static float [] finp;
45 private static short [] sout;
46 private static short [] sinp;
47 private static float [] fout;
48
49 public static void main(String args[]) {
50 TestFramework framework = new TestFramework(TestFloatConversionsVector.class);
51 framework.addFlags("-XX:-TieredCompilation", "-XX:CompileThresholdScaling=0.3");
52 switch (args[0]) {
53 case "nCOH_nAV" -> { framework.addFlags("-XX:-UseCompactObjectHeaders", "-XX:-AlignVector"); }
54 case "nCOH_yAV" -> { framework.addFlags("-XX:-UseCompactObjectHeaders", "-XX:+AlignVector"); }
55 case "yCOH_nAV" -> { framework.addFlags("-XX:+UseCompactObjectHeaders", "-XX:-AlignVector"); }
56 case "yCOH_yAV" -> { framework.addFlags("-XX:+UseCompactObjectHeaders", "-XX:+AlignVector"); }
57 default -> { throw new RuntimeException("Test argument not recognized: " + args[0]); }
58 };
59 framework.start();
60 System.out.println("PASSED");
61 }
62
63 @Test
64 @IR(counts = {IRNode.VECTOR_CAST_F2HF, IRNode.VECTOR_SIZE + "min(max_float, max_short)", "> 0"},
65 applyIfOr = {"UseCompactObjectHeaders", "false", "AlignVector", "false"},
66 applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"},
67 applyIfCPUFeatureOr = {"f16c", "true", "avx512f", "true", "zvfh", "true", "asimd", "true", "sve", "true"})
68 public void test_float_float16(short[] sout, float[] finp) {
69 for (int i = 0; i < finp.length; i++) {
70 sout[i] = Float.floatToFloat16(finp[i]);
71 // With AlignVector, we need 8-byte alignment of vector loads/stores.
72 // UseCompactObjectHeaders=false UseCompactObjectHeaders=true
73 // F_adr = base + 16 + 4*i -> i % 2 = 0 F_adr = base + 12 + 4*i -> i % 2 = 1
74 // S_adr = base + 16 + 2*i -> i % 4 = 0 S_adr = base + 12 + 2*i -> i % 4 = 2
75 // -> vectorize -> no vectorization
76 }
77 }
78
79 @Test
80 public void test_float_float16_strided(short[] sout, float[] finp) {
81 for (int i = 0; i < finp.length/2; i++) {
82 sout[i*2] = Float.floatToFloat16(finp[i*2]);
83 }
84 }
85
86 @Test
87 public void test_float_float16_short_vector(short[] sout, float[] finp) {
88 for (int i = 0; i < finp.length; i+= 4) {
89 sout[i+0] = Float.floatToFloat16(finp[i+0]);
90 sout[i+1] = Float.floatToFloat16(finp[i+1]);
91 }
92 }
93
94 @Run(test = {"test_float_float16", "test_float_float16_strided",
95 "test_float_float16_short_vector"}, mode = RunMode.STANDALONE)
96 public void kernel_test_float_float16() {
97 finp = new float[ARRLEN];
98 sout = new short[ARRLEN];
99
100 for (int i = 0; i < ARRLEN; i++) {
101 finp[i] = (float) i * 1.4f;
102 }
103
104 for (int i = 0; i < ITERS; i++) {
105 test_float_float16(sout, finp);
106 }
107
108 // Verifying the result
109 for (int i = 0; i < ARRLEN; i++) {
110 Asserts.assertEquals(Float.floatToFloat16(finp[i]), sout[i]);
111 }
112
113 for (int i = 0; i < ITERS; i++) {
114 test_float_float16_strided(sout, finp);
115 }
116
117 // Verifying the result
118 for (int i = 0; i < ARRLEN/2; i++) {
119 Asserts.assertEquals(Float.floatToFloat16(finp[i*2]), sout[i*2]);
120 }
121
122 for (int i = 0; i < ITERS; i++) {
123 test_float_float16_short_vector(sout, finp);
124 }
125
126 // Verifying the result
127 for (int i = 0; i < ARRLEN; i++) {
128 Asserts.assertEquals(Float.floatToFloat16(finp[i]), sout[i]);
129 }
130 }
131
132 @Test
133 @IR(counts = {IRNode.VECTOR_CAST_HF2F, IRNode.VECTOR_SIZE + "min(max_float, max_short)", "> 0"},
134 applyIfOr = {"UseCompactObjectHeaders", "false", "AlignVector", "false"},
135 applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"},
136 applyIfCPUFeatureOr = {"f16c", "true", "avx512f", "true", "zvfh", "true", "asimd", "true", "sve", "true"})
137 public void test_float16_float(float[] fout, short[] sinp) {
138 for (int i = 0; i < sinp.length; i++) {
139 fout[i] = Float.float16ToFloat(sinp[i]);
140 // With AlignVector, we need 8-byte alignment of vector loads/stores.
141 // UseCompactObjectHeaders=false UseCompactObjectHeaders=true
142 // F_adr = base + 16 + 4*i -> i % 2 = 0 F_adr = base + 12 + 4*i -> i % 2 = 1
143 // S_adr = base + 16 + 2*i -> i % 4 = 0 S_adr = base + 12 + 2*i -> i % 4 = 2
144 // -> vectorize -> no vectorization
145 }
146 }
147
148 @Test
149 public void test_float16_float_strided(float[] fout, short[] sinp) {
150 for (int i = 0; i < sinp.length/2; i++) {
151 fout[i*2] = Float.float16ToFloat(sinp[i*2]);
152 }
153 }
154
155 @Run(test = {"test_float16_float", "test_float16_float_strided"}, mode = RunMode.STANDALONE)
156 public void kernel_test_float16_float() {
157 sinp = new short[ARRLEN];
158 fout = new float[ARRLEN];
159
160 for (int i = 0; i < ARRLEN; i++) {
161 sinp[i] = (short)i;
162 }
163
164 for (int i = 0; i < ITERS; i++) {
165 test_float16_float(fout, sinp);
166 }
167
168 // Verifying the result
169 for (int i = 0; i < ARRLEN; i++) {
170 Asserts.assertEquals(Float.float16ToFloat(sinp[i]), fout[i]);
171 }
172
173 for (int i = 0; i < ITERS; i++) {
174 test_float16_float_strided(fout, sinp);
175 }
176
177 // Verifying the result
178 for (int i = 0; i < ARRLEN/2; i++) {
179 Asserts.assertEquals(Float.float16ToFloat(sinp[i*2]), fout[i*2]);
180 }
181 }
182 }