[09/10] libgcc: Add support for HF mode (aka __fp16) in libbid

Message ID 20220509143507.239804-10-christophe.lyon@arm.com
State Superseded
Headers
Series Enable Decimal Floating Point (DFP) on AArch64 |

Commit Message

Christophe Lyon May 9, 2022, 2:35 p.m. UTC
  This patch adds support for trunc and extend operations between HF
mode (__fp16) and Decimal Floating Point formats (_Decimal32,
_Decimal64 and _Decimal128).

For simplicity we rely on the implicit conversions inserted by the
compiler between HF and SD/DF/TF modes.  The existing bid*_to_binary*
and binary*_to_bid* functions are non-trivial and at this stage it is
not clear if there is a performance-critical use case involving __fp16
and _Decimal* formats.

The patch also adds two executable tests for AArch64, to make sure the
right functions are used, available (link phase) and functional.

2022-05-04  Christophe Lyon  <christophe.lyon@arm.com>

libgcc/ChangeLog:

	* Makefile.in (D32PBIT_FUNCS): Add _hf_to_sd and _sd_to_hf.
	(D64PBIT_FUNCS): Add _hf_to_dd and _dd_to_hf.
	(D128PBIT_FUNCS): Add _hf_to_td _td_to_hf.

libgcc/config/libbid/ChangeLog:

	* bid_gcc_intrinsics.h (LIBGCC2_HAS_HF_MODE): Define according to
	__LIBGCC_HAS_HF_MODE__.
	(BID_HAS_HF_MODE): Define.
	(HFtype): Define.
	(__bid_extendhfsd): New prototype.
	(__bid_extendhfdd): Likewise.
	(__bid_extendhftd): Likewise.
	(__bid_truncsdhf): Likewise.
	(__bid_truncddhf): Likewise.
	(__bid_trunctdhf): Likewise.
	* _dd_to_hf.c: New file.
	* _hf_to_dd.c: New file.
	* _hf_to_sd.c: New file.
	* _hf_to_td.c: New file.
	* _sd_to_hf.c: New file.
	* _td_to_hf.c: New file.

gcc/testsuite/ChangeLog:

	* gcc.target/aarch64/convert-dfp-2.c: New test.
	* gcc.target/aarch64/convert-dfp.c: New test.
---
 .../gcc.target/aarch64/convert-dfp-2.c        | 42 +++++++++++++
 .../gcc.target/aarch64/convert-dfp.c          | 60 +++++++++++++++++++
 libgcc/Makefile.in                            |  9 ++-
 libgcc/config/libbid/_dd_to_hf.c              | 36 +++++++++++
 libgcc/config/libbid/_hf_to_dd.c              | 36 +++++++++++
 libgcc/config/libbid/_hf_to_sd.c              | 36 +++++++++++
 libgcc/config/libbid/_hf_to_td.c              | 36 +++++++++++
 libgcc/config/libbid/_sd_to_hf.c              | 36 +++++++++++
 libgcc/config/libbid/_td_to_hf.c              | 36 +++++++++++
 libgcc/config/libbid/bid_gcc_intrinsics.h     | 30 +++++++++-
 10 files changed, 352 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/aarch64/convert-dfp-2.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/convert-dfp.c
 create mode 100644 libgcc/config/libbid/_dd_to_hf.c
 create mode 100644 libgcc/config/libbid/_hf_to_dd.c
 create mode 100644 libgcc/config/libbid/_hf_to_sd.c
 create mode 100644 libgcc/config/libbid/_hf_to_td.c
 create mode 100644 libgcc/config/libbid/_sd_to_hf.c
 create mode 100644 libgcc/config/libbid/_td_to_hf.c
  

Comments

Joseph Myers May 9, 2022, 9:27 p.m. UTC | #1
On Mon, 9 May 2022, Christophe Lyon via Gcc-patches wrote:

> This patch adds support for trunc and extend operations between HF
> mode (__fp16) and Decimal Floating Point formats (_Decimal32,
> _Decimal64 and _Decimal128).
> 
> For simplicity we rely on the implicit conversions inserted by the
> compiler between HF and SD/DF/TF modes.  The existing bid*_to_binary*
> and binary*_to_bid* functions are non-trivial and at this stage it is
> not clear if there is a performance-critical use case involving __fp16
> and _Decimal* formats.

Note that for conversion from DFP to HFmode, double rounding (going via 
SFmode) probably produces incorrectly rounded results in some cases 
(though we already have such incorrect results in the other direction for 
DPD; see bug 97635).

> The patch also adds two executable tests for AArch64, to make sure the
> right functions are used, available (link phase) and functional.

Wouldn't it be better to have tests that apply for all targets supporting 
both HFmode and BID DFP, which includes x86 / x86_64 (with SSE2 support) 
as well, using _Float16 as the type name (and the float16 / 
float16_runtime effective-target keywords to test for the relevant support 
and dg-add-options float16)?

> +HFtype
> +__bid_truncddhf (_Decimal64 x) {
> +  HFtype res;
> +  union decimal64 ux;
> +
> +  ux.d = x;
> +  res = __bid64_to_binary32 (ux.i);
> +  return (res);
> +}

Doesn't this need appropriate LIBGCC2_HAS_HF_MODE || BID_HAS_HF_MODE 
conditionals like some of the other functions you're adding?

> +HFtype
> +__bid_truncsdhf (_Decimal32 x) {
> +  HFtype res;
> +  union decimal32 ux;
> +
> +  ux.d = x;
> +  res = __bid32_to_binary32 (ux.i);
> +  return (res);
> +}

Likewise.

> +HFtype
> +__bid_trunctdhf (_Decimal128 x) {
> +  HFtype res;
> +  union decimal128 ux;
> +
> +  ux.d = x;
> +  res = __bid128_to_binary32 (ux.i);
> +  return (res);
> +}

Likewise.

> +#if LIBGCC2_HAS_HF_MODE
> +typedef float HFtype __attribute__ ((mode (HF)));
> +#endif /* LIBGCC2_HAS_HF_MODE */
>  typedef float SFtype __attribute__ ((mode (SF)));
>  typedef float DFtype __attribute__ ((mode (DF)));
>  #if LIBGCC2_HAS_XF_MODE
> @@ -98,6 +111,12 @@ typedef __attribute__ ((aligned(16))) struct
>  #endif
>  #endif
>  
> +#if BID_HAS_HF_MODE
> +#ifndef HFtype
> +#define HFtype __fp16
> +#endif

That seems wrong; the __fp16 name is specific to Arm / AArch64.  I'd 
expect the typedef alone to be specific; in any case, the "mode" attribute 
is the appropriate way to define this type.
  
Christophe Lyon May 10, 2022, 8:08 a.m. UTC | #2
On 5/9/22 23:27, Joseph Myers wrote:
> On Mon, 9 May 2022, Christophe Lyon via Gcc-patches wrote:
> 
>> This patch adds support for trunc and extend operations between HF
>> mode (__fp16) and Decimal Floating Point formats (_Decimal32,
>> _Decimal64 and _Decimal128).
>>
>> For simplicity we rely on the implicit conversions inserted by the
>> compiler between HF and SD/DF/TF modes.  The existing bid*_to_binary*
>> and binary*_to_bid* functions are non-trivial and at this stage it is
>> not clear if there is a performance-critical use case involving __fp16
>> and _Decimal* formats.
> 
> Note that for conversion from DFP to HFmode, double rounding (going via
> SFmode) probably produces incorrectly rounded results in some cases
> (though we already have such incorrect results in the other direction for
> DPD; see bug 97635).

Thanks for the pointer.
I was aware of such imprecision in the code I introduce, but not in 
existing one. I don't think this is a blocker for this patch, is it?


>> The patch also adds two executable tests for AArch64, to make sure the
>> right functions are used, available (link phase) and functional.
> 
> Wouldn't it be better to have tests that apply for all targets supporting
> both HFmode and BID DFP, which includes x86 / x86_64 (with SSE2 support)
> as well, using _Float16 as the type name (and the float16 /
> float16_runtime effective-target keywords to test for the relevant support
> and dg-add-options float16)?
> 
Indeed! What would be the appropriate directory for such tests?

>> +HFtype
>> +__bid_truncddhf (_Decimal64 x) {
>> +  HFtype res;
>> +  union decimal64 ux;
>> +
>> +  ux.d = x;
>> +  res = __bid64_to_binary32 (ux.i);
>> +  return (res);
>> +}
> 
> Doesn't this need appropriate LIBGCC2_HAS_HF_MODE || BID_HAS_HF_MODE
> conditionals like some of the other functions you're adding?
Yes, you are right, I'll fix that.


>> +HFtype
>> +__bid_truncsdhf (_Decimal32 x) {
>> +  HFtype res;
>> +  union decimal32 ux;
>> +
>> +  ux.d = x;
>> +  res = __bid32_to_binary32 (ux.i);
>> +  return (res);
>> +}
> 
> Likewise.
OK

>> +HFtype
>> +__bid_trunctdhf (_Decimal128 x) {
>> +  HFtype res;
>> +  union decimal128 ux;
>> +
>> +  ux.d = x;
>> +  res = __bid128_to_binary32 (ux.i);
>> +  return (res);
>> +}
> 
> Likewise.
OK

>> +#if LIBGCC2_HAS_HF_MODE
>> +typedef float HFtype __attribute__ ((mode (HF)));
>> +#endif /* LIBGCC2_HAS_HF_MODE */
>>   typedef float SFtype __attribute__ ((mode (SF)));
>>   typedef float DFtype __attribute__ ((mode (DF)));
>>   #if LIBGCC2_HAS_XF_MODE
>> @@ -98,6 +111,12 @@ typedef __attribute__ ((aligned(16))) struct
>>   #endif
>>   #endif
>>   
>> +#if BID_HAS_HF_MODE
>> +#ifndef HFtype
>> +#define HFtype __fp16
>> +#endif
> 
> That seems wrong; the __fp16 name is specific to Arm / AArch64.  I'd
> expect the typedef alone to be specific; in any case, the "mode" attribute
> is the appropriate way to define this type.
> 
I'll change that to __float16 (like __float128 we have a few lines below 
for TFtype).

Thanks!

Christophe
  
Joseph Myers May 10, 2022, 8:26 p.m. UTC | #3
On Tue, 10 May 2022, Christophe Lyon via Gcc-patches wrote:

> > Note that for conversion from DFP to HFmode, double rounding (going via
> > SFmode) probably produces incorrectly rounded results in some cases
> > (though we already have such incorrect results in the other direction for
> > DPD; see bug 97635).
> 
> Thanks for the pointer.
> I was aware of such imprecision in the code I introduce, but not in existing
> one. I don't think this is a blocker for this patch, is it?

I don't think it's a blocker.

> > Wouldn't it be better to have tests that apply for all targets supporting
> > both HFmode and BID DFP, which includes x86 / x86_64 (with SSE2 support)
> > as well, using _Float16 as the type name (and the float16 /
> > float16_runtime effective-target keywords to test for the relevant support
> > and dg-add-options float16)?
> > 
> Indeed! What would be the appropriate directory for such tests?

Maybe gcc.dg/dfp, or gcc.dg/torture if it's useful to run the tests for 
multiple choices of optimization options.

> > That seems wrong; the __fp16 name is specific to Arm / AArch64.  I'd
> > expect the typedef alone to be specific; in any case, the "mode" attribute
> > is the appropriate way to define this type.
> > 
> I'll change that to __float16 (like __float128 we have a few lines below for
> TFtype).

There's _Float16, but no such type as __float16.
  

Patch

diff --git a/gcc/testsuite/gcc.target/aarch64/convert-dfp-2.c b/gcc/testsuite/gcc.target/aarch64/convert-dfp-2.c
new file mode 100644
index 00000000000..ebbbc649455
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/convert-dfp-2.c
@@ -0,0 +1,42 @@ 
+/* { dg-do run } */
+/* { dg-options "-save-temps" } */
+
+/* Test conversions from DFP to smaller types.  */
+
+_Decimal32 var32;
+_Decimal64 var64;
+_Decimal128 var128;
+__fp16 var16;
+
+void foo32 (_Decimal32 param32)
+{
+  var16 = param32;
+}
+
+void foo64 (_Decimal64 param64)
+{
+  var16 = param64;
+  var32 = param64;
+}
+
+void foo128 (_Decimal128 param128)
+{
+  var16 = param128;
+  var32 = param128;
+  var64 = param128;
+}
+
+int main ()
+{
+  foo32 (var32);
+  foo64 (var64);
+  foo128 (var128);
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times {\tbl\t__bid_truncsdhf} 1 } } */
+/* { dg-final { scan-assembler-times {\tbl\t__bid_truncddhf} 1 } } */
+/* { dg-final { scan-assembler-times {\tbl\t__bid_truncddsd2} 1 } } */
+/* { dg-final { scan-assembler-times {\tbl\t__bid_trunctdhf} 1 } } */
+/* { dg-final { scan-assembler-times {\tbl\t__bid_trunctdsd2} 1 } } */
+/* { dg-final { scan-assembler-times {\tbl\t__bid_trunctddd2} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/convert-dfp.c b/gcc/testsuite/gcc.target/aarch64/convert-dfp.c
new file mode 100644
index 00000000000..cd5ada46e3d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/convert-dfp.c
@@ -0,0 +1,60 @@ 
+/* { dg-do run } */
+/* { dg-options "-save-temps" } */
+
+/* Test conversions to/from DFP values.  */
+
+extern void abort ();
+
+_Decimal32 var32 = 1.2df;
+
+int foo32 (_Decimal32 param32, _Decimal64 param64, _Decimal128 param128, __fp16 param16)
+{
+  return (param32 == var32)
+    + (param64 == var32)
+    + (param128 == var32)
+    /* Small enough relative difference?  */
+    + ((((_Decimal32)param16 - var32) / var32) < 0.002df);
+}
+
+_Decimal64 var64 = 1.2dd;
+
+int foo64 (_Decimal32 param32, _Decimal64 param64, _Decimal128 param128, __fp16 param16)
+{
+  return (param32 == var64)
+    + (param64 == var64)
+    + (param128 == var64)
+    /* Small enough relative difference?  */
+    + ((((_Decimal64)param16 - var64) / var64) < 0.002dd);
+}
+
+_Decimal128 var128 = 1.2dl;
+
+int foo128 (_Decimal32 param32, _Decimal64 param64, _Decimal128 param128, __fp16 param16)
+{
+  return (param32 == var128)
+    + (param64 == var128)
+    + (param128 == var128)
+    /* Small enough relative difference?  */
+    + ((((_Decimal128)param16 - var128) / var128) < 0.002dl);
+}
+
+int main()
+{
+  if (foo32 (1.2df, 1.2dd, 1.2dl, (__fp16)1.2) != 4)
+    abort ();
+
+  if (foo64 (1.2df, 1.2dd, 1.2dl, (__fp16)1.2) != 4)
+    abort ();
+
+  if (foo128 (1.2df, 1.2dd, 1.2dl, (__fp16)1.2) != 4)
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times {\tbl\t__bid_extendsddd2} 2 } } */
+/* { dg-final { scan-assembler-times {\tbl\t__bid_extendsdtd2} 2 } } */
+/* { dg-final { scan-assembler-times {\tbl\t__bid_extendddtd2} 2 } } */
+/* { dg-final { scan-assembler-times {\tbl\t__bid_extendhfsd} 1 } } */
+/* { dg-final { scan-assembler-times {\tbl\t__bid_extendhfdd} 1 } } */
+/* { dg-final { scan-assembler-times {\tbl\t__bid_extendhftd} 1 } } */
diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in
index 09b3ec8bc2e..1fe708a93f7 100644
--- a/libgcc/Makefile.in
+++ b/libgcc/Makefile.in
@@ -677,7 +677,8 @@  D32PBIT_FUNCS = _addsub_sd _div_sd _mul_sd _plus_sd _minus_sd \
 	_si_to_sd _di_to_sd _usi_to_sd _udi_to_sd \
 	_sd_to_sf _sd_to_df _sd_to_xf _sd_to_tf \
 	_sf_to_sd _df_to_sd _xf_to_sd _tf_to_sd \
-	_sd_to_dd _sd_to_td _unord_sd _conv_sd
+	_sd_to_dd _sd_to_td _unord_sd _conv_sd \
+	_hf_to_sd _sd_to_hf
 
 D64PBIT_FUNCS = _addsub_dd _div_dd _mul_dd _plus_dd _minus_dd \
 	_eq_dd _ne_dd _lt_dd _gt_dd _le_dd _ge_dd \
@@ -685,7 +686,8 @@  D64PBIT_FUNCS = _addsub_dd _div_dd _mul_dd _plus_dd _minus_dd \
 	_si_to_dd _di_to_dd _usi_to_dd _udi_to_dd \
 	_dd_to_sf _dd_to_df _dd_to_xf _dd_to_tf \
 	_sf_to_dd _df_to_dd _xf_to_dd _tf_to_dd \
-	_dd_to_sd _dd_to_td _unord_dd _conv_dd
+	_dd_to_sd _dd_to_td _unord_dd _conv_dd \
+	_hf_to_dd _dd_to_hf
 
 D128PBIT_FUNCS = _addsub_td _div_td _mul_td _plus_td _minus_td \
 	_eq_td _ne_td _lt_td _gt_td _le_td _ge_td \
@@ -693,7 +695,8 @@  D128PBIT_FUNCS = _addsub_td _div_td _mul_td _plus_td _minus_td \
 	_si_to_td _di_to_td _usi_to_td _udi_to_td \
 	_td_to_sf _td_to_df _td_to_xf _td_to_tf \
 	_sf_to_td _df_to_td _xf_to_td _tf_to_td \
-	_td_to_sd _td_to_dd _unord_td _conv_td
+	_td_to_sd _td_to_dd _unord_td _conv_td \
+	_hf_to_td _td_to_hf
 
 ifeq ($(enable_decimal_float),bid)
 ifneq ($(D32PBIT),)
diff --git a/libgcc/config/libbid/_dd_to_hf.c b/libgcc/config/libbid/_dd_to_hf.c
new file mode 100644
index 00000000000..c69af77a703
--- /dev/null
+++ b/libgcc/config/libbid/_dd_to_hf.c
@@ -0,0 +1,36 @@ 
+/* Copyright (C) 2022 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC 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
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "bid_conf.h"
+#include "bid_functions.h"
+#include "bid_gcc_intrinsics.h"
+
+HFtype
+__bid_truncddhf (_Decimal64 x) {
+  HFtype res;
+  union decimal64 ux;
+
+  ux.d = x;
+  res = __bid64_to_binary32 (ux.i);
+  return (res);
+}
diff --git a/libgcc/config/libbid/_hf_to_dd.c b/libgcc/config/libbid/_hf_to_dd.c
new file mode 100644
index 00000000000..f85100e24f8
--- /dev/null
+++ b/libgcc/config/libbid/_hf_to_dd.c
@@ -0,0 +1,36 @@ 
+/* Copyright (C) 2022 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC 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
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "bid_conf.h"
+#include "bid_functions.h"
+#include "bid_gcc_intrinsics.h"
+
+#if LIBGCC2_HAS_HF_MODE || BID_HAS_HF_MODE
+_Decimal64
+__bid_extendhfdd (HFtype x) {
+  union decimal64 res;
+  SFtype xsf = x;
+  res.i = __binary32_to_bid64 (xsf);
+  return (res.d);
+}
+#endif
diff --git a/libgcc/config/libbid/_hf_to_sd.c b/libgcc/config/libbid/_hf_to_sd.c
new file mode 100644
index 00000000000..285b80c6e05
--- /dev/null
+++ b/libgcc/config/libbid/_hf_to_sd.c
@@ -0,0 +1,36 @@ 
+/* Copyright (C) 2022 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC 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
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "bid_conf.h"
+#include "bid_functions.h"
+#include "bid_gcc_intrinsics.h"
+
+#if LIBGCC2_HAS_HF_MODE || BID_HAS_HF_MODE
+_Decimal32
+__bid_extendhfsd (HFtype x) {
+  union decimal32 res;
+  SFtype xsf = x;
+  res.i = __binary32_to_bid32 (xsf);
+  return (res.d);
+}
+#endif
diff --git a/libgcc/config/libbid/_hf_to_td.c b/libgcc/config/libbid/_hf_to_td.c
new file mode 100644
index 00000000000..99b661ec727
--- /dev/null
+++ b/libgcc/config/libbid/_hf_to_td.c
@@ -0,0 +1,36 @@ 
+/* Copyright (C) 2022 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC 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
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "bid_conf.h"
+#include "bid_functions.h"
+#include "bid_gcc_intrinsics.h"
+
+#if LIBGCC2_HAS_HF_MODE || BID_HAS_HF_MODE
+_Decimal128
+__bid_extendhftd (HFtype x) {
+  union decimal128 res;
+  SFtype xsf = x;
+  res.i = __binary32_to_bid128 (xsf);
+  return (res.d);
+}
+#endif
diff --git a/libgcc/config/libbid/_sd_to_hf.c b/libgcc/config/libbid/_sd_to_hf.c
new file mode 100644
index 00000000000..5e5b1e303e6
--- /dev/null
+++ b/libgcc/config/libbid/_sd_to_hf.c
@@ -0,0 +1,36 @@ 
+/* Copyright (C) 2022 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC 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
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "bid_conf.h"
+#include "bid_functions.h"
+#include "bid_gcc_intrinsics.h"
+
+HFtype
+__bid_truncsdhf (_Decimal32 x) {
+  HFtype res;
+  union decimal32 ux;
+
+  ux.d = x;
+  res = __bid32_to_binary32 (ux.i);
+  return (res);
+}
diff --git a/libgcc/config/libbid/_td_to_hf.c b/libgcc/config/libbid/_td_to_hf.c
new file mode 100644
index 00000000000..a71d278b3c7
--- /dev/null
+++ b/libgcc/config/libbid/_td_to_hf.c
@@ -0,0 +1,36 @@ 
+/* Copyright (C) 2022 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC 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
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "bid_conf.h"
+#include "bid_functions.h"
+#include "bid_gcc_intrinsics.h"
+
+HFtype
+__bid_trunctdhf (_Decimal128 x) {
+  HFtype res;
+  union decimal128 ux;
+
+  ux.d = x;
+  res = __bid128_to_binary32 (ux.i);
+  return (res);
+}
diff --git a/libgcc/config/libbid/bid_gcc_intrinsics.h b/libgcc/config/libbid/bid_gcc_intrinsics.h
index b0a23debc15..feeb7ce9fc9 100644
--- a/libgcc/config/libbid/bid_gcc_intrinsics.h
+++ b/libgcc/config/libbid/bid_gcc_intrinsics.h
@@ -31,6 +31,12 @@  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #include "tm.h"
 #include "libgcc_tm.h"
 
+#ifdef __LIBGCC_HAS_HF_MODE__
+#define LIBGCC2_HAS_HF_MODE 1
+#else
+#define LIBGCC2_HAS_HF_MODE 0
+#endif
+
 #ifdef __LIBGCC_HAS_XF_MODE__
 #define LIBGCC2_HAS_XF_MODE 1
 #else
@@ -43,6 +49,10 @@  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #define LIBGCC2_HAS_TF_MODE 0
 #endif
 
+#ifndef BID_HAS_HF_MODE
+#define BID_HAS_HF_MODE LIBGCC2_HAS_HF_MODE
+#endif
+
 #ifndef BID_HAS_XF_MODE
 #define BID_HAS_XF_MODE LIBGCC2_HAS_XF_MODE
 #endif
@@ -53,6 +63,9 @@  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
 /* Some handy typedefs.  */
 
+#if LIBGCC2_HAS_HF_MODE
+typedef float HFtype __attribute__ ((mode (HF)));
+#endif /* LIBGCC2_HAS_HF_MODE */
 typedef float SFtype __attribute__ ((mode (SF)));
 typedef float DFtype __attribute__ ((mode (DF)));
 #if LIBGCC2_HAS_XF_MODE
@@ -98,6 +111,12 @@  typedef __attribute__ ((aligned(16))) struct
 #endif
 #endif
 
+#if BID_HAS_HF_MODE
+#ifndef HFtype
+#define HFtype __fp16
+#endif
+#endif
+
 #ifndef SFtype
 #define SFtype float
 #endif
@@ -110,8 +129,7 @@  typedef __attribute__ ((aligned(16))) struct
 #ifndef XFtype
 #define XFtype long double
 #endif
-
-#endif   /* IN_LIBGCC2 */
+#endif
 
 #if BID_HAS_TF_MODE
 #ifndef TFtype
@@ -249,6 +267,14 @@  extern _Decimal128 __bid_extendxftd (XFtype);
 extern int isinfd32 (_Decimal32);
 extern int isinfd64 (_Decimal64);
 extern int isinfd128 (_Decimal128);
+#if BID_HAS_HF_MODE
+extern _Decimal32 __bid_extendhfsd (HFtype);
+extern _Decimal64 __bid_extendhfdd (HFtype);
+extern _Decimal128 __bid_extendhftd (HFtype);
+extern HFtype __bid_truncsdhf (_Decimal32);
+extern HFtype __bid_truncddhf (_Decimal64);
+extern HFtype __bid_trunctdhf (_Decimal128);
+#endif
 #endif  /* BID_HAS_GCC_DECIMAL_INTRINSICS */
 
 extern void __dfp_set_round (int);