From 611780d0840bab716dda6ad0bb8dd755fe861005 Mon Sep 17 00:00:00 2001 From: Jatin Bhateja Date: Fri, 24 Oct 2025 13:07:30 +0000 Subject: [PATCH 1/4] 8370409: Incorrect computation in Float16 reduction loop --- src/hotspot/cpu/x86/x86.ad | 1 + .../compiler/c2/TestFloat16Reduction.java | 152 ++++++++++++++++++ 2 files changed, 153 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/c2/TestFloat16Reduction.java diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index efe0482e095ff..90316c46cc4c0 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -10733,6 +10733,7 @@ instruct reinterpretHF2S(rRegI dst, regF src) format %{ "vmovw $dst, $src" %} ins_encode %{ __ vmovw($dst$$Register, $src$$XMMRegister); + __ movswl($dst$$Register, $dst$$Register); %} ins_pipe(pipe_slow); %} diff --git a/test/hotspot/jtreg/compiler/c2/TestFloat16Reduction.java b/test/hotspot/jtreg/compiler/c2/TestFloat16Reduction.java new file mode 100644 index 0000000000000..753f2eb46b995 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/TestFloat16Reduction.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.c2; + +/* + * @test + * @bug 8370409 + * @summary Incorrect computation in Float16 reduction loop + * + * @library /test/lib / + * @run main/othervm -XX:-TieredCompilation + * compiler.c2.TestFloat16Reduction + */ + +import compiler.lib.ir_framework.*; +import compiler.lib.verify.*; +import jdk.test.lib.Utils; + +public class TestFloat16Reduction { + + public static short [] arr = { 15318, 15320, -1024, 15324, 15325, 15327, 15328, 15329 }; + + public static int ITER = 10000; + + public static long GOLDEN_ADD = ADDReduceLong(); + public static long GOLDEN_SUB = SUBReduceLong(); + public static long GOLDEN_MUL = MULReduceLong(); + public static long GOLDEN_DIV = DIVReduceLong(); + public static long GOLDEN_MAX = MAXReduceLong(); + public static long GOLDEN_MIN = MINReduceLong(); + + @Test + @IR(counts = {IRNode.ADD_HF, " >0 "}, applyIfCPUFeature = {"avx512_fp16", "true"}) + @IR(counts = {IRNode.ADD_HF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + static long ADDReduceLong() { + short res = 0; + for (int i = 0; i < 8; i++) { + res = Float.floatToFloat16(Float.float16ToFloat(res) + Float.float16ToFloat(arr[i])); + } + return (long)res; + } + + @Check(test="ADDReduceLong") + static void checkADDReduceLong(long actual) { + Verify.checkEQ(actual, GOLDEN_ADD); + } + + @Test + @IR(counts = {IRNode.SUB_HF, " >0 "}, applyIfCPUFeature = {"avx512_fp16", "true"}) + @IR(counts = {IRNode.SUB_HF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + static long SUBReduceLong() { + short res = 0; + for (int i = 0; i < 8; i++) { + res = Float.floatToFloat16(Float.float16ToFloat(res) - Float.float16ToFloat(arr[i])); + } + return (long)res; + } + + @Check(test="SUBReduceLong") + static void checkSUBReduceLong(long actual) { + Verify.checkEQ(actual, GOLDEN_SUB); + } + + @Test + @IR(counts = {IRNode.MUL_HF, " >0 "}, applyIfCPUFeature = {"avx512_fp16", "true"}) + @IR(counts = {IRNode.MUL_HF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + static long MULReduceLong() { + short res = 0; + for (int i = 0; i < 8; i++) { + res = Float.floatToFloat16(Float.float16ToFloat(res) * Float.float16ToFloat(arr[i])); + } + return (long)res; + } + + @Check(test="MULReduceLong") + static void checkMULReduceLong(long actual) { + Verify.checkEQ(actual, GOLDEN_MUL); + } + + @Test + @IR(counts = {IRNode.DIV_HF, " >0 "}, applyIfCPUFeature = {"avx512_fp16", "true"}) + @IR(counts = {IRNode.DIV_HF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + static long DIVReduceLong() { + short res = 0; + for (int i = 0; i < 8; i++) { + res = Float.floatToFloat16(Float.float16ToFloat(res) / Float.float16ToFloat(arr[i])); + } + return (long)res; + } + + @Check(test="DIVReduceLong") + static void checkDIVReduceLong(long actual) { + Verify.checkEQ(actual, GOLDEN_DIV); + } + + @Test + @IR(counts = {IRNode.MAX_HF, " >0 "}, applyIfCPUFeature = {"avx512_fp16", "true"}) + @IR(counts = {IRNode.MAX_HF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + static long MAXReduceLong() { + short res = 0; + for (int i = 0; i < 8; i++) { + res = Float.floatToFloat16(Math.max(Float.float16ToFloat(res), Float.float16ToFloat(arr[i]))); + } + return (long)res; + } + + @Check(test="MAXReduceLong") + static void checkMAXReduceLong(long actual) { + Verify.checkEQ(actual, GOLDEN_MAX); + } + + @Test + @IR(counts = {IRNode.MIN_HF, " >0 "}, applyIfCPUFeature = {"avx512_fp16", "true"}) + @IR(counts = {IRNode.MIN_HF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + static long MINReduceLong() { + short res = 0; + for (int i = 0; i < 8; i++) { + res = Float.floatToFloat16(Math.min(Float.float16ToFloat(res), Float.float16ToFloat(arr[i]))); + } + return (long)res; + } + + @Check(test = "MINReduceLong") + static void checkMINReduceLong(long actual) { + Verify.checkEQ(actual, GOLDEN_MIN); + } + + public static void main(String [] args) { + TestFramework.run(TestFloat16Reduction.class); + } +} From bd6f290b275047cb4494f60d1321fcf6c62babee Mon Sep 17 00:00:00 2001 From: Jatin Bhateja Date: Fri, 24 Oct 2025 14:34:27 +0000 Subject: [PATCH 2/4] Adding random test inputs --- .../compiler/c2/TestFloat16Reduction.java | 68 +++++++++++-------- 1 file changed, 41 insertions(+), 27 deletions(-) diff --git a/test/hotspot/jtreg/compiler/c2/TestFloat16Reduction.java b/test/hotspot/jtreg/compiler/c2/TestFloat16Reduction.java index 753f2eb46b995..abeadec09bf74 100644 --- a/test/hotspot/jtreg/compiler/c2/TestFloat16Reduction.java +++ b/test/hotspot/jtreg/compiler/c2/TestFloat16Reduction.java @@ -35,117 +35,131 @@ import compiler.lib.ir_framework.*; import compiler.lib.verify.*; +import compiler.lib.generators.Generator; +import static compiler.lib.generators.Generators.G; import jdk.test.lib.Utils; +import java.util.Arrays; public class TestFloat16Reduction { - public static short [] arr = { 15318, 15320, -1024, 15324, 15325, 15327, 15328, 15329 }; + public short [] arr; + private static Generator genHF = G.uniformFloat16s(); - public static int ITER = 10000; - - public static long GOLDEN_ADD = ADDReduceLong(); - public static long GOLDEN_SUB = SUBReduceLong(); - public static long GOLDEN_MUL = MULReduceLong(); - public static long GOLDEN_DIV = DIVReduceLong(); - public static long GOLDEN_MAX = MAXReduceLong(); - public static long GOLDEN_MIN = MINReduceLong(); + public long GOLDEN_ADD; + public long GOLDEN_SUB; + public long GOLDEN_MUL; + public long GOLDEN_DIV; + public long GOLDEN_MAX; + public long GOLDEN_MIN; @Test @IR(counts = {IRNode.ADD_HF, " >0 "}, applyIfCPUFeature = {"avx512_fp16", "true"}) @IR(counts = {IRNode.ADD_HF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) - static long ADDReduceLong() { + long ADDReduceLong() { short res = 0; - for (int i = 0; i < 8; i++) { + for (int i = 0; i < arr.length; i++) { res = Float.floatToFloat16(Float.float16ToFloat(res) + Float.float16ToFloat(arr[i])); } return (long)res; } @Check(test="ADDReduceLong") - static void checkADDReduceLong(long actual) { + void checkADDReduceLong(long actual) { Verify.checkEQ(actual, GOLDEN_ADD); } @Test @IR(counts = {IRNode.SUB_HF, " >0 "}, applyIfCPUFeature = {"avx512_fp16", "true"}) @IR(counts = {IRNode.SUB_HF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) - static long SUBReduceLong() { + long SUBReduceLong() { short res = 0; - for (int i = 0; i < 8; i++) { + for (int i = 0; i < arr.length; i++) { res = Float.floatToFloat16(Float.float16ToFloat(res) - Float.float16ToFloat(arr[i])); } return (long)res; } @Check(test="SUBReduceLong") - static void checkSUBReduceLong(long actual) { + void checkSUBReduceLong(long actual) { Verify.checkEQ(actual, GOLDEN_SUB); } @Test @IR(counts = {IRNode.MUL_HF, " >0 "}, applyIfCPUFeature = {"avx512_fp16", "true"}) @IR(counts = {IRNode.MUL_HF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) - static long MULReduceLong() { + long MULReduceLong() { short res = 0; - for (int i = 0; i < 8; i++) { + for (int i = 0; i < arr.length; i++) { res = Float.floatToFloat16(Float.float16ToFloat(res) * Float.float16ToFloat(arr[i])); } return (long)res; } @Check(test="MULReduceLong") - static void checkMULReduceLong(long actual) { + void checkMULReduceLong(long actual) { Verify.checkEQ(actual, GOLDEN_MUL); } @Test @IR(counts = {IRNode.DIV_HF, " >0 "}, applyIfCPUFeature = {"avx512_fp16", "true"}) @IR(counts = {IRNode.DIV_HF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) - static long DIVReduceLong() { + long DIVReduceLong() { short res = 0; - for (int i = 0; i < 8; i++) { + for (int i = 0; i < arr.length; i++) { res = Float.floatToFloat16(Float.float16ToFloat(res) / Float.float16ToFloat(arr[i])); } return (long)res; } @Check(test="DIVReduceLong") - static void checkDIVReduceLong(long actual) { + void checkDIVReduceLong(long actual) { Verify.checkEQ(actual, GOLDEN_DIV); } @Test @IR(counts = {IRNode.MAX_HF, " >0 "}, applyIfCPUFeature = {"avx512_fp16", "true"}) @IR(counts = {IRNode.MAX_HF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) - static long MAXReduceLong() { + long MAXReduceLong() { short res = 0; - for (int i = 0; i < 8; i++) { + for (int i = 0; i < arr.length; i++) { res = Float.floatToFloat16(Math.max(Float.float16ToFloat(res), Float.float16ToFloat(arr[i]))); } return (long)res; } @Check(test="MAXReduceLong") - static void checkMAXReduceLong(long actual) { + void checkMAXReduceLong(long actual) { Verify.checkEQ(actual, GOLDEN_MAX); } @Test @IR(counts = {IRNode.MIN_HF, " >0 "}, applyIfCPUFeature = {"avx512_fp16", "true"}) @IR(counts = {IRNode.MIN_HF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) - static long MINReduceLong() { + long MINReduceLong() { short res = 0; - for (int i = 0; i < 8; i++) { + for (int i = 0; i < arr.length; i++) { res = Float.floatToFloat16(Math.min(Float.float16ToFloat(res), Float.float16ToFloat(arr[i]))); } return (long)res; } @Check(test = "MINReduceLong") - static void checkMINReduceLong(long actual) { + void checkMINReduceLong(long actual) { Verify.checkEQ(actual, GOLDEN_MIN); } + public TestFloat16Reduction() { + arr = new short[32]; + G.fill(genHF, arr); + + GOLDEN_ADD = ADDReduceLong(); + GOLDEN_SUB = SUBReduceLong(); + GOLDEN_MUL = MULReduceLong(); + GOLDEN_DIV = DIVReduceLong(); + GOLDEN_MAX = MAXReduceLong(); + GOLDEN_MIN = MINReduceLong(); + } + public static void main(String [] args) { TestFramework.run(TestFloat16Reduction.class); } From f5e1a857222aa2fa3179158b7bc87adf04a018b3 Mon Sep 17 00:00:00 2001 From: Jatin Bhateja Date: Thu, 30 Oct 2025 08:57:52 +0000 Subject: [PATCH 3/4] Review comments resolutions --- .../compiler/c2/TestFloat16Reduction.java | 46 ++++++++----------- 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/test/hotspot/jtreg/compiler/c2/TestFloat16Reduction.java b/test/hotspot/jtreg/compiler/c2/TestFloat16Reduction.java index abeadec09bf74..d0c4ab109b978 100644 --- a/test/hotspot/jtreg/compiler/c2/TestFloat16Reduction.java +++ b/test/hotspot/jtreg/compiler/c2/TestFloat16Reduction.java @@ -29,8 +29,7 @@ * @summary Incorrect computation in Float16 reduction loop * * @library /test/lib / - * @run main/othervm -XX:-TieredCompilation - * compiler.c2.TestFloat16Reduction + * @run main/othervm compiler.c2.TestFloat16Reduction */ import compiler.lib.ir_framework.*; @@ -42,20 +41,23 @@ public class TestFloat16Reduction { - public short [] arr; - private static Generator genHF = G.uniformFloat16s(); + static short [] arr = new short[32]; + static Generator genHF = G.uniformFloat16s(); + static { + G.fill(genHF, arr); + } - public long GOLDEN_ADD; - public long GOLDEN_SUB; - public long GOLDEN_MUL; - public long GOLDEN_DIV; - public long GOLDEN_MAX; - public long GOLDEN_MIN; + public static long GOLDEN_ADD = ADDReduceLong(); + public static long GOLDEN_SUB = SUBReduceLong(); + public static long GOLDEN_MUL = MULReduceLong(); + public static long GOLDEN_DIV = DIVReduceLong(); + public static long GOLDEN_MAX = MAXReduceLong(); + public static long GOLDEN_MIN = MINReduceLong(); @Test @IR(counts = {IRNode.ADD_HF, " >0 "}, applyIfCPUFeature = {"avx512_fp16", "true"}) @IR(counts = {IRNode.ADD_HF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) - long ADDReduceLong() { + static long ADDReduceLong() { short res = 0; for (int i = 0; i < arr.length; i++) { res = Float.floatToFloat16(Float.float16ToFloat(res) + Float.float16ToFloat(arr[i])); @@ -71,7 +73,7 @@ void checkADDReduceLong(long actual) { @Test @IR(counts = {IRNode.SUB_HF, " >0 "}, applyIfCPUFeature = {"avx512_fp16", "true"}) @IR(counts = {IRNode.SUB_HF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) - long SUBReduceLong() { + static long SUBReduceLong() { short res = 0; for (int i = 0; i < arr.length; i++) { res = Float.floatToFloat16(Float.float16ToFloat(res) - Float.float16ToFloat(arr[i])); @@ -87,7 +89,7 @@ void checkSUBReduceLong(long actual) { @Test @IR(counts = {IRNode.MUL_HF, " >0 "}, applyIfCPUFeature = {"avx512_fp16", "true"}) @IR(counts = {IRNode.MUL_HF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) - long MULReduceLong() { + static long MULReduceLong() { short res = 0; for (int i = 0; i < arr.length; i++) { res = Float.floatToFloat16(Float.float16ToFloat(res) * Float.float16ToFloat(arr[i])); @@ -103,7 +105,7 @@ void checkMULReduceLong(long actual) { @Test @IR(counts = {IRNode.DIV_HF, " >0 "}, applyIfCPUFeature = {"avx512_fp16", "true"}) @IR(counts = {IRNode.DIV_HF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) - long DIVReduceLong() { + static long DIVReduceLong() { short res = 0; for (int i = 0; i < arr.length; i++) { res = Float.floatToFloat16(Float.float16ToFloat(res) / Float.float16ToFloat(arr[i])); @@ -119,7 +121,7 @@ void checkDIVReduceLong(long actual) { @Test @IR(counts = {IRNode.MAX_HF, " >0 "}, applyIfCPUFeature = {"avx512_fp16", "true"}) @IR(counts = {IRNode.MAX_HF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) - long MAXReduceLong() { + static long MAXReduceLong() { short res = 0; for (int i = 0; i < arr.length; i++) { res = Float.floatToFloat16(Math.max(Float.float16ToFloat(res), Float.float16ToFloat(arr[i]))); @@ -135,7 +137,7 @@ void checkMAXReduceLong(long actual) { @Test @IR(counts = {IRNode.MIN_HF, " >0 "}, applyIfCPUFeature = {"avx512_fp16", "true"}) @IR(counts = {IRNode.MIN_HF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) - long MINReduceLong() { + static long MINReduceLong() { short res = 0; for (int i = 0; i < arr.length; i++) { res = Float.floatToFloat16(Math.min(Float.float16ToFloat(res), Float.float16ToFloat(arr[i]))); @@ -148,18 +150,6 @@ void checkMINReduceLong(long actual) { Verify.checkEQ(actual, GOLDEN_MIN); } - public TestFloat16Reduction() { - arr = new short[32]; - G.fill(genHF, arr); - - GOLDEN_ADD = ADDReduceLong(); - GOLDEN_SUB = SUBReduceLong(); - GOLDEN_MUL = MULReduceLong(); - GOLDEN_DIV = DIVReduceLong(); - GOLDEN_MAX = MAXReduceLong(); - GOLDEN_MIN = MINReduceLong(); - } - public static void main(String [] args) { TestFramework.run(TestFloat16Reduction.class); } From 91970a18beae0f22ab69c1652585cca71ca3954b Mon Sep 17 00:00:00 2001 From: Jatin Bhateja Date: Thu, 30 Oct 2025 14:31:24 +0530 Subject: [PATCH 4/4] Change GOLDEN constants to static variables --- .../jtreg/compiler/c2/TestFloat16Reduction.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/hotspot/jtreg/compiler/c2/TestFloat16Reduction.java b/test/hotspot/jtreg/compiler/c2/TestFloat16Reduction.java index d0c4ab109b978..8bca0592c1980 100644 --- a/test/hotspot/jtreg/compiler/c2/TestFloat16Reduction.java +++ b/test/hotspot/jtreg/compiler/c2/TestFloat16Reduction.java @@ -47,12 +47,12 @@ public class TestFloat16Reduction { G.fill(genHF, arr); } - public static long GOLDEN_ADD = ADDReduceLong(); - public static long GOLDEN_SUB = SUBReduceLong(); - public static long GOLDEN_MUL = MULReduceLong(); - public static long GOLDEN_DIV = DIVReduceLong(); - public static long GOLDEN_MAX = MAXReduceLong(); - public static long GOLDEN_MIN = MINReduceLong(); + static long GOLDEN_ADD = ADDReduceLong(); + static long GOLDEN_SUB = SUBReduceLong(); + static long GOLDEN_MUL = MULReduceLong(); + static long GOLDEN_DIV = DIVReduceLong(); + static long GOLDEN_MAX = MAXReduceLong(); + static long GOLDEN_MIN = MINReduceLong(); @Test @IR(counts = {IRNode.ADD_HF, " >0 "}, applyIfCPUFeature = {"avx512_fp16", "true"})