Skip to content

Commit 3239919

Browse files
author
Sandhya Viswanathan
committed
8350835: C2 SuperWord: assert/wrong result when using Float.float16ToFloat with byte instead of short input
Reviewed-by: epeter, kvn
1 parent 47c1960 commit 3239919

File tree

2 files changed

+184
-1
lines changed

2 files changed

+184
-1
lines changed

src/hotspot/share/opto/vectornode.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1497,7 +1497,9 @@ int VectorCastNode::opcode(int sopc, BasicType bt, bool is_signed) {
14971497
// Handle special case for to/from Half Float conversions
14981498
switch (sopc) {
14991499
case Op_ConvHF2F:
1500-
assert(bt == T_SHORT, "");
1500+
if (!is_signed || (bt != T_SHORT)) {
1501+
return 0;
1502+
}
15011503
return Op_VectorCastHF2F;
15021504
case Op_ConvF2HF:
15031505
assert(bt == T_FLOAT, "");
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
/*
2+
* Copyright (c) 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+
* @key randomness
27+
* @bug 8350835
28+
* @summary Test bug fix for JDK-8350835 discovered through Template Framework
29+
* @library /test/lib /
30+
* @run driver compiler.vectorization.TestFloat16ToFloatConv
31+
*/
32+
33+
package compiler.vectorization;
34+
35+
import compiler.lib.ir_framework.*;
36+
import jdk.test.lib.Utils;
37+
import java.util.Random;
38+
39+
import static compiler.lib.generators.Generators.G;
40+
41+
public class TestFloat16ToFloatConv {
42+
private static final Random RANDOM = Utils.getRandomInstance();
43+
private static final int SIZE = 1024;
44+
private static byte[] aB = new byte[SIZE];
45+
private static char[] aC = new char[SIZE];
46+
private static short[] aS = new short[SIZE];
47+
private static int[] aI = new int[SIZE];
48+
private static long[] aL = new long[SIZE];
49+
private static float[] goldB, goldC, goldS, goldI, goldL;
50+
51+
static {
52+
// Fill int and long array using Generators
53+
G.fill(G.ints(), aI);
54+
G.fill(G.longs(), aL);
55+
// Generators do not support byte, char, short array currently so perform manual random fill
56+
for (int i = 0; i < aB.length; i++) {
57+
aB[i] = (byte)RANDOM.nextInt();
58+
aC[i] = (char)RANDOM.nextInt();
59+
aS[i] = (short)RANDOM.nextInt();
60+
}
61+
goldB = testByteKernel(aB);
62+
goldC = testCharKernel(aC);
63+
goldS = testShortKernel(aS);
64+
goldI = testIntKernel(aI);
65+
goldL = testLongKernel(aL);
66+
}
67+
68+
@Test
69+
// Scalar IR for loop body: LoadB, ConvHF2F, StoreF
70+
// Vectorized IR: LoadVector, VectorCastHF2F , StoreVector
71+
// Vectorization disabled as input to VectorCastHF2F would have been a byte vector instead of short vector
72+
// but the VectorCastHF2F expects short vector as input
73+
// See JDK-8352093 for details
74+
@IR(failOn = { IRNode.VECTOR_CAST_HF2F })
75+
public static float[] testByteKernel(byte[] barr) {
76+
float[] res = new float[barr.length];
77+
for (int i = 0; i < barr.length; i++) {
78+
res[i] = Float.float16ToFloat(barr[i]);
79+
}
80+
return res;
81+
}
82+
83+
@Test
84+
@IR(counts = {IRNode.VECTOR_CAST_HF2F, "> 0"},
85+
applyIfOr = {"UseCompactObjectHeaders", "false", "AlignVector", "false"},
86+
applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"},
87+
applyIfCPUFeatureOr = {"f16c", "true", "avx512f", "true", "zvfh", "true", "asimd", "true", "sve", "true"})
88+
public static float[] testCharKernel(char[] carr) {
89+
float[] res = new float[carr.length];
90+
for (int i = 0; i < carr.length; i++) {
91+
res[i] = Float.float16ToFloat((short)carr[i]);
92+
}
93+
return res;
94+
}
95+
96+
@Test
97+
@IR(counts = {IRNode.VECTOR_CAST_HF2F, "> 0"},
98+
applyIfOr = {"UseCompactObjectHeaders", "false", "AlignVector", "false"},
99+
applyIfPlatformOr = {"x64", "true", "aarch64", "true", "riscv64", "true"},
100+
applyIfCPUFeatureOr = {"f16c", "true", "avx512f", "true", "zvfh", "true", "asimd", "true", "sve", "true"})
101+
public static float[] testShortKernel(short[] sarr) {
102+
float[] res = new float[sarr.length];
103+
for (int i = 0; i < sarr.length; i++) {
104+
res[i] = Float.float16ToFloat(sarr[i]);
105+
}
106+
return res;
107+
}
108+
109+
@Test
110+
// Scalar IR for loop body: LoadI, LShiftI by 16, RShiftI by 16, ConvHF2F, StoreF
111+
// Vectorized IR: LoadVector, LShiftVI, RShiftVI, VectorCastHF2F, StoreVector
112+
// Vectorization disabled as input to VectorCastHF2F would have been an int vector instead of short vector
113+
// but the VectorCastHF2F expects short vector as input
114+
// See JDK-8352093 for details
115+
@IR(failOn = { IRNode.VECTOR_CAST_HF2F })
116+
public static float[] testIntKernel(int[] iarr) {
117+
float[] res = new float[iarr.length];
118+
for (int i = 0; i < iarr.length; i++) {
119+
res[i] = Float.float16ToFloat((short)iarr[i]);
120+
}
121+
return res;
122+
}
123+
124+
@Test
125+
// Scalar IR for loop body: ConvL2I, LoadI, LShiftI by 16, RShiftI by 16, ConvHF2F, StoreF
126+
// Vectorized IR: VectorCastL2X, LoadVector, LShiftVI, RShiftVI, VectorCastHF2F, StoreVector
127+
// Vectorization disabled as input to VectorCastHF2F would have been an int vector instead of short vector
128+
// but the VectorCastHF2F expects short vector as input
129+
// See JDK-8352093 for details
130+
@IR(failOn = { IRNode.VECTOR_CAST_HF2F })
131+
public static float[] testLongKernel(long[] larr) {
132+
float[] res = new float[larr.length];
133+
for (int i = 0; i < larr.length; i++) {
134+
res[i] = Float.float16ToFloat((short)larr[i]);
135+
}
136+
return res;
137+
}
138+
139+
public static void checkResult(float[] res, float[] gold) {
140+
for (int i = 0; i < res.length; i++) {
141+
if (Float.floatToIntBits(res[i]) != Float.floatToIntBits(gold[i])) {
142+
throw new RuntimeException("wrong value: " + Float.floatToRawIntBits(res[i]) + " " + Float.floatToRawIntBits(gold[i]));
143+
}
144+
}
145+
}
146+
147+
@Run(test = {"testByteKernel"})
148+
public static void testByte() {
149+
float[] farr = testByteKernel(aB);
150+
checkResult(farr, goldB);
151+
}
152+
153+
@Run(test = {"testCharKernel"})
154+
public static void testChar() {
155+
float[] farr = testCharKernel(aC);
156+
checkResult(farr, goldC);
157+
}
158+
159+
@Run(test = {"testShortKernel"})
160+
public static void testShort() {
161+
float[] farr = testShortKernel(aS);
162+
checkResult(farr, goldS);
163+
}
164+
165+
@Run(test = {"testIntKernel"})
166+
public static void testInt() {
167+
float[] farr = testIntKernel(aI);
168+
checkResult(farr, goldI);
169+
}
170+
171+
@Run(test = {"testLongKernel"})
172+
public static void testLong() {
173+
float[] farr = testLongKernel(aL);
174+
checkResult(farr, goldL);
175+
}
176+
177+
public static void main(String [] args) {
178+
TestFramework.run(TestFloat16ToFloatConv.class);
179+
}
180+
}
181+

0 commit comments

Comments
 (0)