https://gcc.gnu.org/g:022d58c222229965572e53dc0d24077ff1e94b08
commit 022d58c222229965572e53dc0d24077ff1e94b08 Author: Michael Meissner <[email protected]> Date: Thu Sep 24 22:42:19 2026 -0400 Add ifunc support to extend 16-bit fp to 32/64-bit. This patch rewrites the __extend{bf,hf}{sf,df}2 functions to have ifunc support to generate appropriate code for conversions. Also add _gpr versions to allow doing a conversion with 16-bit fp passed as an unsigned short. 2026-09-24 Michael Meissner <[email protected]> * config/rs6000/extendbf-sfdf2.c: New file. * config/rs6000/extendhf-sfdf2.c: Likewise. * config/rs6000/t-float16: Use extendbf-sff2 and extendhf-sfhf2 instead of the native soft-fp version. Diff: --- libgcc/config/rs6000/extendbf-sfdf2.c | 222 ++++++++++++++++++++++++++++++++++ libgcc/config/rs6000/extendhf-sfdf2.c | 180 +++++++++++++++++++++++++++ libgcc/config/rs6000/t-float16 | 51 +++++--- 3 files changed, 438 insertions(+), 15 deletions(-) diff --git a/libgcc/config/rs6000/extendbf-sfdf2.c b/libgcc/config/rs6000/extendbf-sfdf2.c new file mode 100644 index 000000000000..6e3801e907f3 --- /dev/null +++ b/libgcc/config/rs6000/extendbf-sfdf2.c @@ -0,0 +1,222 @@ +/* Software floating-point emulation. + Return an bfloat16 converted to IEEE single + Copyright (C) 2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +/* This is a clone of soft-fp/extendbfsf2.c for the PowerPC. It + provides both __extendbfsf2 and __extendbfdf2, since both types + return 64-bit floating point formats. + + We provide power8, power9, and power10 versiosns of the conversion function + and we use an ifunc resolver to select the appropriate conversion to + use. + + We provide an alternative version of the conversion that takes the value in + a GPR passed as an unsigned short. This is to allow the calling sequence + where arguments are converted to the 32/64-bit scalar format. If we don't + have the hardware support, we can't use the standard __extend function. */ + +#define FP_NO_EXACT_UNDERFLOW +#include "soft-fp.h" +#include "brain.h" +#include "single.h" +#include "double.h" + +union ushort_bf { + unsigned short us; + BFtype bf; +}; + +typedef SFtype bf_fpr_to_sf_function_t (BFtype a); +typedef SFtype bf_gpr_to_sf_function_t (unsigned short a); + +typedef bf_fpr_to_sf_function_t *bf_fpr_to_sf_ptr_function_t; +typedef bf_gpr_to_sf_function_t *bf_gpr_to_sf_ptr_function_t; + +typedef DFtype bf_fpr_to_df_function_t (BFtype a); +typedef DFtype bf_gpr_to_df_function_t (unsigned short a); + +typedef bf_fpr_to_df_function_t *bf_fpr_to_df_ptr_function_t; +typedef bf_gpr_to_df_function_t *bf_gpr_to_df_ptr_function_t; + +static bf_fpr_to_sf_ptr_function_t __extendbfsf2_ifunc (void); +static bf_gpr_to_sf_ptr_function_t __extendbfsf2_gpr_ifunc (void); + +static bf_fpr_to_sf_function_t __extendbfsf2_p8 + __attribute__ ((__target__("cpu=power8"))); + +static bf_gpr_to_sf_function_t __extendbfsf2_gpr_p8 + __attribute__ ((__target__("cpu=power8"))); + +static bf_fpr_to_sf_function_t __extendbfsf2_p9 + __attribute__ ((__target__("cpu=power9"))); + +static bf_gpr_to_sf_function_t __extendbfsf2_gpr_p9 + __attribute__ ((__target__("cpu=power9"))); + +static bf_fpr_to_sf_function_t __extendbfsf2_p10 + __attribute__ ((__target__("cpu=power10"))); + +static bf_gpr_to_sf_function_t __extendbfsf2_gpr_p10 + __attribute__ ((__target__("cpu=power10"))); + +extern bf_fpr_to_sf_function_t __extendbfsf2 + __attribute__ ((__ifunc__ ("__extendbfsf2_ifunc"))); + +extern bf_gpr_to_sf_function_t __extendbfsf2_gpr + __attribute__ ((__ifunc__ ("__extendbfsf2_gpr_ifunc"))); + +/* Provide DF version as well, given SFtype & DFtype use the same encoding. */ +static bf_fpr_to_df_ptr_function_t __extendbfdf2_ifunc (void); +static bf_gpr_to_df_ptr_function_t __extendbfdf2_gpr_ifunc (void); + +extern bf_fpr_to_df_function_t __extendbfdf2 + __attribute__ ((__ifunc__ ("__extendbfdf2_ifunc"))); + +extern bf_gpr_to_sf_function_t __extendbfdf2_gpr + __attribute__ ((__ifunc__ ("__extendbfdf2_gpr_ifunc"))); + +/* Power8 implementation, BFtype passed in FPR register, no hardware + support. */ +static SFtype +__extendbfsf2_p8 (BFtype a) +{ + FP_DECL_EX; + FP_DECL_B (A); + FP_DECL_S (R); + SFtype r; + + FP_INIT_EXCEPTIONS; + FP_UNPACK_RAW_B (A, a); + FP_EXTEND (S, B, 1, 1, R, A); + FP_PACK_RAW_S (r, R); + FP_HANDLE_EXCEPTIONS; + + return r; +} + +/* Power8 implementation, BFtype passed in GPR register, no hardware + support. */ +static SFtype +__extendbfsf2_gpr_p8 (unsigned short us) +{ + union ushort_bf u; + BFtype a; + + u.us = us; + a = u.bf; + + FP_DECL_EX; + FP_DECL_B (A); + FP_DECL_S (R); + SFtype r; + + FP_INIT_EXCEPTIONS; + FP_UNPACK_RAW_B (A, a); + FP_EXTEND (S, B, 1, 1, R, A); + FP_PACK_RAW_S (r, R); + FP_HANDLE_EXCEPTIONS; + + return r; +} + +/* Power9 implementation, BFtype passed in FPR register, use shift and + XSCVSPDPN. */ +static SFtype +__extendbfsf2_p9 (BFtype a) +{ + return (SFtype) a; +} + +/* Power9 implementation, BFtype passed in GPR register, use shift and + XSCVSPDPN. */ +static SFtype +__extendbfsf2_gpr_p9 (unsigned short a) +{ + union ushort_bf u; + u.us = a; + return (SFtype) u.bf; +} + +/* Power10 implementtion, BFtype passed in FPR register, use XXSPLTW, + XVCVBF16SPN, and XSCVSPDPN. */ +static SFtype +__extendbfsf2_p10 (BFtype a) +{ + return (SFtype) a; +} + +/* Power10 implementtion, BFtype passed in GPR register, use XXSPLTW, + XVCVBF16SPN, and XSCVSPDPN. */ +static SFtype +__extendbfsf2_gpr_p10 (unsigned short a) +{ + union ushort_bf u; + u.us = a; + return (SFtype) u.bf; +} + +/* Determine if we are on power8, power9, or power10. */ +static bf_fpr_to_sf_ptr_function_t +__extendbfsf2_ifunc (void) +{ + return (__builtin_cpu_supports ("arch_3_1") + ? __extendbfsf2_p10 + : (__builtin_cpu_supports ("arch_3_00") + ? __extendbfsf2_p9 + : __extendbfsf2_p8)); +} + +static bf_gpr_to_sf_ptr_function_t +__extendbfsf2_gpr_ifunc (void) +{ + return (__builtin_cpu_supports ("arch_3_1") + ? __extendbfsf2_gpr_p10 + : (__builtin_cpu_supports ("arch_3_00") + ? __extendbfsf2_gpr_p9 + : __extendbfsf2_gpr_p8)); +} + +/* DFtype functions. */ +static bf_fpr_to_df_ptr_function_t +__extendbfdf2_ifunc (void) +{ + return (bf_fpr_to_df_ptr_function_t) (__builtin_cpu_supports ("arch_3_1") + ? __extendbfsf2_p10 + : (__builtin_cpu_supports ("arch_3_00") + ? __extendbfsf2_p9 + : __extendbfsf2_p8)); +} + +static bf_gpr_to_df_ptr_function_t +__extendbfdf2_gpr_ifunc (void) +{ + return (bf_gpr_to_df_ptr_function_t) (__builtin_cpu_supports ("arch_3_1") + ? __extendbfsf2_gpr_p10 + : (__builtin_cpu_supports ("arch_3_00") + ? __extendbfsf2_gpr_p9 + : __extendbfsf2_gpr_p8)); +} diff --git a/libgcc/config/rs6000/extendhf-sfdf2.c b/libgcc/config/rs6000/extendhf-sfdf2.c new file mode 100644 index 000000000000..4ae1629545ec --- /dev/null +++ b/libgcc/config/rs6000/extendhf-sfdf2.c @@ -0,0 +1,180 @@ +/* Software floating-point emulation. + Return an IEEE half converted to IEEE single + Copyright (C) 2021-2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +/* This is a clone of soft-fp/extendhfsf2.c for the PowerPC. It + provides both __extendhfsf2 and __extendhfdf2, since both types + return 64-bit floating point formats. + + We provide power8, and power9 versiosns of the conversion function and we + use an ifunc resolver to select the appropriate conversion to use. + + We provide an alternative version of the conversion that takes the value in + a GPR passed as an unsigned short. This is to allow the calling sequence + where arguments are converted to the 32/64-bit scalar format. If we don't + have the hardware support, we can't use the standard __extend function. */ + +#define FP_NO_EXACT_UNDERFLOW +#include "soft-fp.h" +#include "half.h" +#include "single.h" +#include "double.h" + +union ushort_hf { + unsigned short us; + HFtype hf; +}; + +typedef SFtype hf_fpr_to_sf_function_t (HFtype a); +typedef SFtype hf_gpr_to_sf_function_t (unsigned short a); + +typedef hf_fpr_to_sf_function_t *hf_fpr_to_sf_ptr_function_t; +typedef hf_gpr_to_sf_function_t *hf_gpr_to_sf_ptr_function_t; + +typedef DFtype hf_fpr_to_df_function_t (HFtype a); +typedef DFtype hf_gpr_to_df_function_t (unsigned short a); + +typedef hf_fpr_to_df_function_t *hf_fpr_to_df_ptr_function_t; +typedef hf_gpr_to_df_function_t *hf_gpr_to_df_ptr_function_t; + +static hf_fpr_to_sf_ptr_function_t __extendhfsf2_ifunc (void); +static hf_gpr_to_sf_ptr_function_t __extendhfsf2_gpr_ifunc (void); + +static hf_fpr_to_df_ptr_function_t __extendhfdf2_ifunc (void); +static hf_gpr_to_df_ptr_function_t __extendhfdf2_gpr_ifunc (void); + +static hf_fpr_to_sf_function_t __extendhfsf2_p8 + __attribute__ ((__target__("cpu=power8"))); + +static hf_gpr_to_sf_function_t __extendhfsf2_gpr_p8 + __attribute__ ((__target__("cpu=power8"))); + +static hf_fpr_to_sf_function_t __extendhfsf2_p9 + __attribute__ ((__target__("cpu=power9"))); + +static hf_gpr_to_sf_function_t __extendhfsf2_gpr_p9 + __attribute__ ((__target__("cpu=power9"))); + +extern hf_fpr_to_sf_function_t __extendhfsf2 + __attribute__ ((__ifunc__ ("__extendhfsf2_ifunc"))); + +extern hf_gpr_to_sf_function_t __extendhfsf2_gpr + __attribute__ ((__ifunc__ ("__extendhfsf2_gpr_ifunc"))); + +/* Power8 implementation, HFtype passed in FPR register, no hardware + support. */ +static SFtype +__extendhfsf2_p8 (HFtype a) +{ + FP_DECL_EX; + FP_DECL_H (A); + FP_DECL_S (R); + SFtype r; + + FP_INIT_EXCEPTIONS; + FP_UNPACK_RAW_H (A, a); + FP_EXTEND (S, H, 1, 1, R, A); + FP_PACK_RAW_S (r, R); + FP_HANDLE_EXCEPTIONS; + + return r; +} + +/* Power8 implementation, HFtype passed in GPR register, no hardware + support. */ +static SFtype +__extendhfsf2_gpr_p8 (unsigned short us) +{ + union ushort_hf u; + HFtype a; + + u.us = us; + a = u.hf; + + FP_DECL_EX; + FP_DECL_H (A); + FP_DECL_S (R); + SFtype r; + + FP_INIT_EXCEPTIONS; + FP_UNPACK_RAW_H (A, a); + FP_EXTEND (S, H, 1, 1, R, A); + FP_PACK_RAW_S (r, R); + FP_HANDLE_EXCEPTIONS; + + return r; +} + +/* Power9 implementation, HFtype passed in FPR register, use XVCVHPSP. */ +static SFtype +__extendhfsf2_p9 (HFtype a) +{ + return (SFtype) a; +} + +/* Power9 implementation, HFtype passed in GPR register, use XVCVHPSP. */ +static SFtype +__extendhfsf2_gpr_p9 (unsigned short a) +{ + union ushort_hf u; + u.us = a; + return (SFtype) u.hf; +} + +/* Determine if we are on power8 or power9. */ +static hf_fpr_to_sf_ptr_function_t +__extendhfsf2_ifunc (void) +{ + return (__builtin_cpu_supports ("arch_3_00") + ? __extendhfsf2_p9 + : __extendhfsf2_p8); +} + +static hf_gpr_to_sf_ptr_function_t +__extendhfsf2_gpr_ifunc (void) +{ + return (__builtin_cpu_supports ("arch_3_00") + ? __extendhfsf2_gpr_p9 + : __extendhfsf2_gpr_p8); +} + +/* DFtype functions. */ +static hf_fpr_to_df_ptr_function_t +__extendhfdf2_ifunc (void) +{ + return (hf_fpr_to_df_ptr_function_t) (__builtin_cpu_supports ("arch_3_00") + ? __extendhfsf2_p9 + : __extendhfsf2_p8); +} + +static hf_gpr_to_df_ptr_function_t +__extendhfdf2_gpr_ifunc (void) +{ + return (hf_gpr_to_df_ptr_function_t) (__builtin_cpu_supports ("arch_3_00") + ? __extendhfsf2_gpr_p9 + : __extendhfsf2_gpr_p8); +} diff --git a/libgcc/config/rs6000/t-float16 b/libgcc/config/rs6000/t-float16 index f77df910b3ff..d03c824cc561 100644 --- a/libgcc/config/rs6000/t-float16 +++ b/libgcc/config/rs6000/t-float16 @@ -1,30 +1,51 @@ -# _Float16 library support - -fp16_funcs = eqhf2 extendhfdf2 extendhfsf2 \ - fixhfsi fixhfdi fixhfti fixunshfsi fixunshfdi fixunshfti \ - floatsihf floatdihf floattihf floatunsihf floatundihf floatuntihf \ +# _Float16 library support, source files in soft-ftp +fp16_funcs_1 = eqhf2 \ + fixhfsi fixhfdi fixhfti \ + fixunshfsi fixunshfdi fixunshfti \ + floatsihf floatdihf floattihf \ + floatunsihf floatundihf floatuntihf \ truncdfhf2 truncsfhf2 -fp16_src = $(addprefix $(srcdir)/soft-fp/,$(addsuffix .c,$(fp16_funcs))) -fp16_obj = $(addsuffix $(objext),$(fp16_funcs)) +fp16_src_1 = $(addprefix $(srcdir)/soft-fp/,$(addsuffix .c,$(fp16_funcs_1))) +fp16_obj_1 = $(addsuffix $(objext),$(fp16_funcs_1)) + +# _Float16 library support, source files in config/rs6000 +fp16_funcs_2 = extendhf-sfdf2 +fp16_src_2 = $(addprefix $(srcdir)/config/rs6000/,$(addsuffix .c,$(fp16_funcs_2))) +fp16_obj_2 = $(addsuffix $(objext),$(fp16_funcs_2)) + +# _Float16 combined library support +fp16_funcs = $(fp16_funcs_1) $(fp16_funcs_2) +fp16_src = $(fp16_src_1) $(fp16_src_2) +fp16_obj = $(fp16_obj_1) $(fp16_obj_2) FP16_CFLAGS = -mfloat16 -Wno-psabi \ - -I$(srcdir)/soft-fp -I$(srcdir)/config/rs6000 + -I$(srcdir)/soft-fp \ + -I$(srcdir)/config/rs6000 $(fp16_obj) : INTERNAL_CFLAGS += $(FP16_CFLAGS) -# __bfloat16 library support - -bfp16_funcs = extendbfsf2 floatdibf floatsibf floatundibf floatunsibf \ +# __bf16 library support, source files in soft-ftp +bfp16_funcs_1 = floatsibf floatdibf floattibf \ + floatunsibf floatundibf floatuntibf \ truncdfbf2 truncsfbf2 -bfp16_src = $(addprefix $(srcdir)/soft-fp/,$(addsuffix .c,$(bfp16_funcs))) -bfp16_obj = $(addsuffix $(objext),$(bfp16_funcs)) +bfp16_src_1 = $(addprefix $(srcdir)/soft-fp/,$(addsuffix .c,$(bfp16_funcs_1))) +bfp16_obj_1 = $(addsuffix $(objext),$(bfp16_funcs_1)) -$(bfp16_obj) : INTERNAL_CFLAGS += $(FP16_CFLAGS) +# __bf16 library support, source files in config/rs6000 +bfp16_funcs_2 = extendbf-sfdf2 +bfp16_src_2 = $(addprefix $(srcdir)/config/rs6000/,$(addsuffix .c,$(bfp16_funcs_2))) +bfp16_obj_2 = $(addsuffix $(objext),$(bfp16_funcs_2)) + +# __bf16 combined library support +bfp16_funcs = $(bfp16_funcs_1) $(bfp16_funcs_2) +bfp16_src = $(bfp16_src_1) $(bfp16_src_2) +bfp16_obj = $(bfp16_obj_1) $(bfp16_obj_2) -# Conversion between __bfloat16 and _Float16 +$(bfp16_obj) : INTERNAL_CFLAGS += $(FP16_CFLAGS) +# Conversion between __bf16 and _Float16 both_fp16_funcs = truncbfhf2 trunchfbf2 both_fp16_src = $(addprefix $(srcdir)/soft-fp/,$(addsuffix .c,$(both_fp16_funcs))) both_fp16_obj = $(addsuffix $(objext),$(both_fp16_funcs))
