public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 00/10] Enable Decimal Floating Point (DFP) on AArch64
@ 2022-05-09 14:34 Christophe Lyon
  2022-05-09 14:34 ` [PATCH 01/10] aarch64: Enable DFP (Decimal Floating-point) (BID format) Christophe Lyon
                   ` (10 more replies)
  0 siblings, 11 replies; 33+ messages in thread
From: Christophe Lyon @ 2022-05-09 14:34 UTC (permalink / raw)
  To: gcc-patches

This patch series enables support of DFP on AArch64, using the BID
format (Binary Integer Decimal).  There is no HW support for DFP on
AArch64, and we made a choice similar to x86: BID format using
libgcc's libbid for software emulation.

This work was done independently from Andrew's patch, which I
discovered some time after I started [1].  The essence is similar
although the AArch64 back-end evolved quite a bit since then, and I add
several tests.

The ABI has been documented a few months ago: _Decimal32 is treated
like float, _Decimal64 is treated like double and _Decimal128 is
treated like long double, using the same registers and conventions
(sN, dN, qN, varargs handling).

I have patches for GDB, which I'll send once this series is committed
in GCC since the first GDB patch is to merge the libdecnumber updated.

As of testing, I have also used libdfp, which required only a couple
of minor patches, and its testsuite passes.

I have tested the whole series on aarch64, aarch64_be and x86_64, no
regression, all the DFP tests pass.

OK?

Thanks,
Christophe



[1] https://gcc.gnu.org/legacy-ml/gcc-patches/2017-07/msg00788.html

Christophe Lyon (10):
  aarch64: Enable DFP (Decimal Floating-point) (BID format)
  aarch64: Add backend support for DFP
  libgcc: Enable XF mode conversions to/from DFP modes only if supported
  libgcc: enable DFP for AArch64
  testsuite:: Fix pr39986.c testcase for AArch64
  testsuite: Add new tests for DFP under aarch64/aapcs64
  testsuite: enable more BID DFP tests for AArch64
  testsuite: Add C++ unwinding tests with Decimal Floating-Point
  libgcc: Add support for HF mode (aka __fp16) in libbid
  libgcc: use __builtin_clz and __builtin_ctz in libbid

 config/dfp.m4                                 |   3 +-
 gcc/config/aarch64/aarch64.cc                 |  95 ++++++++++---
 gcc/config/aarch64/aarch64.md                 |  86 ++++++------
 gcc/config/aarch64/iterators.md               |  28 +++-
 gcc/configure                                 |   3 +-
 gcc/doc/sourcebuild.texi                      |   3 +
 gcc/testsuite/c-c++-common/dfp/pr39986.c      |  22 +--
 gcc/testsuite/g++.dg/eh/dfp-1.C               |  54 +++++++
 gcc/testsuite/g++.dg/eh/dfp-2.C               |  54 +++++++
 gcc/testsuite/g++.dg/eh/dfp-saves-aarch64.C   |  49 +++++++
 .../gcc.dg/dfp/bid-non-canonical-d128-1.c     |   3 +-
 .../gcc.dg/dfp/bid-non-canonical-d128-2.c     |   3 +-
 .../gcc.dg/dfp/bid-non-canonical-d128-3.c     |   3 +-
 .../gcc.dg/dfp/bid-non-canonical-d128-4.c     |   3 +-
 .../gcc.dg/dfp/bid-non-canonical-d32-1.c      |   3 +-
 .../gcc.dg/dfp/bid-non-canonical-d32-2.c      |   3 +-
 .../gcc.dg/dfp/bid-non-canonical-d64-1.c      |   3 +-
 .../gcc.dg/dfp/bid-non-canonical-d64-2.c      |   3 +-
 .../gcc.target/aarch64/aapcs64/aapcs64.exp    |   8 ++
 .../gcc.target/aarch64/aapcs64/dfp-1.c        |  24 ++++
 .../gcc.target/aarch64/aapcs64/func-ret-1.c   |   7 +
 .../gcc.target/aarch64/aapcs64/func-ret-3.c   |  67 +++++++++
 .../gcc.target/aarch64/aapcs64/ice_dfp_5.c    |  20 +++
 .../aarch64/aapcs64/test_align_dfp-1.c        | 126 +++++++++++++++++
 .../aarch64/aapcs64/test_align_dfp-4.c        |  42 ++++++
 .../gcc.target/aarch64/aapcs64/test_dfp_1.c   |  31 ++++
 .../gcc.target/aarch64/aapcs64/test_dfp_10.c  |  26 ++++
 .../gcc.target/aarch64/aapcs64/test_dfp_11.c  |  34 +++++
 .../gcc.target/aarch64/aapcs64/test_dfp_12.c  |  44 ++++++
 .../gcc.target/aarch64/aapcs64/test_dfp_13.c  |  34 +++++
 .../gcc.target/aarch64/aapcs64/test_dfp_14.c  |  35 +++++
 .../gcc.target/aarch64/aapcs64/test_dfp_15.c  |  21 +++
 .../gcc.target/aarch64/aapcs64/test_dfp_16.c  |  32 +++++
 .../gcc.target/aarch64/aapcs64/test_dfp_17.c  |  37 +++++
 .../gcc.target/aarch64/aapcs64/test_dfp_18.c  |  34 +++++
 .../gcc.target/aarch64/aapcs64/test_dfp_19.c  |  35 +++++
 .../gcc.target/aarch64/aapcs64/test_dfp_2.c   |  17 +++
 .../gcc.target/aarch64/aapcs64/test_dfp_20.c  |  22 +++
 .../gcc.target/aarch64/aapcs64/test_dfp_21.c  |  21 +++
 .../gcc.target/aarch64/aapcs64/test_dfp_22.c  |  19 +++
 .../gcc.target/aarch64/aapcs64/test_dfp_23.c  |  42 ++++++
 .../gcc.target/aarch64/aapcs64/test_dfp_24.c  |  22 +++
 .../gcc.target/aarch64/aapcs64/test_dfp_25.c  |  61 ++++++++
 .../gcc.target/aarch64/aapcs64/test_dfp_26.c  |  54 +++++++
 .../gcc.target/aarch64/aapcs64/test_dfp_27.c  |  46 ++++++
 .../gcc.target/aarch64/aapcs64/test_dfp_3.c   |  18 +++
 .../gcc.target/aarch64/aapcs64/test_dfp_5.c   |  24 ++++
 .../gcc.target/aarch64/aapcs64/test_dfp_6.c   |  26 ++++
 .../gcc.target/aarch64/aapcs64/test_dfp_7.c   |  30 ++++
 .../gcc.target/aarch64/aapcs64/test_dfp_8.c   |  24 ++++
 .../gcc.target/aarch64/aapcs64/test_dfp_9.c   |  32 +++++
 .../aarch64/aapcs64/test_quad_double_dfp.c    |  26 ++++
 .../gcc.target/aarch64/aapcs64/type-def.h     | 132 ++++++++++++++++++
 .../gcc.target/aarch64/aapcs64/va_arg_dfp-1.c |  60 ++++++++
 .../aarch64/aapcs64/va_arg_dfp-10.c           |  29 ++++
 .../aarch64/aapcs64/va_arg_dfp-11.c           |  32 +++++
 .../aarch64/aapcs64/va_arg_dfp-12.c           |  64 +++++++++
 .../aarch64/aapcs64/va_arg_dfp-13.c           |  59 ++++++++
 .../aarch64/aapcs64/va_arg_dfp-14.c           |  35 +++++
 .../aarch64/aapcs64/va_arg_dfp-16.c           |  28 ++++
 .../gcc.target/aarch64/aapcs64/va_arg_dfp-2.c |  75 ++++++++++
 .../gcc.target/aarch64/aapcs64/va_arg_dfp-3.c |  94 +++++++++++++
 .../gcc.target/aarch64/aapcs64/va_arg_dfp-4.c |  90 ++++++++++++
 .../gcc.target/aarch64/aapcs64/va_arg_dfp-5.c |  47 +++++++
 .../gcc.target/aarch64/aapcs64/va_arg_dfp-6.c |  40 ++++++
 .../gcc.target/aarch64/aapcs64/va_arg_dfp-8.c |  25 ++++
 .../gcc.target/aarch64/aapcs64/va_arg_dfp-9.c |  31 ++++
 .../gcc.target/aarch64/convert-dfp-2.c        |  42 ++++++
 .../gcc.target/aarch64/convert-dfp.c          |  60 ++++++++
 gcc/testsuite/lib/target-supports.exp         |  11 ++
 libdecnumber/configure                        |   3 +-
 libgcc/Makefile.in                            |   9 +-
 libgcc/config.host                            |   6 +
 libgcc/config/libbid/_dd_to_hf.c              |  36 +++++
 libgcc/config/libbid/_dd_to_xf.c              |   2 +
 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/_sd_to_xf.c              |   2 +
 libgcc/config/libbid/_td_to_hf.c              |  36 +++++
 libgcc/config/libbid/_td_to_xf.c              |   2 +
 libgcc/config/libbid/_xf_to_dd.c              |   2 +
 libgcc/config/libbid/_xf_to_sd.c              |   2 +
 libgcc/config/libbid/_xf_to_td.c              |   2 +
 libgcc/config/libbid/bid_binarydecimal.c      |  51 +------
 libgcc/config/libbid/bid_gcc_intrinsics.h     |  30 +++-
 libgcc/configure                              |   3 +-
 88 files changed, 2698 insertions(+), 148 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/eh/dfp-1.C
 create mode 100644 gcc/testsuite/g++.dg/eh/dfp-2.C
 create mode 100644 gcc/testsuite/g++.dg/eh/dfp-saves-aarch64.C
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/dfp-1.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/ice_dfp_5.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_align_dfp-1.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_align_dfp-4.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_1.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_10.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_11.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_12.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_13.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_14.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_15.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_16.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_17.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_18.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_19.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_2.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_20.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_21.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_22.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_23.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_24.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_25.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_26.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_27.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_3.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_5.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_6.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_7.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_8.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_9.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_quad_double_dfp.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-1.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-10.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-11.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-12.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-13.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-14.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-16.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-2.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-3.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-4.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-5.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-6.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-8.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-9.c
 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

-- 
2.25.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 01/10] aarch64: Enable DFP (Decimal Floating-point) (BID format)
  2022-05-09 14:34 [PATCH 00/10] Enable Decimal Floating Point (DFP) on AArch64 Christophe Lyon
@ 2022-05-09 14:34 ` Christophe Lyon
  2022-05-09 14:34 ` [PATCH 02/10] aarch64: Add backend support for DFP Christophe Lyon
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 33+ messages in thread
From: Christophe Lyon @ 2022-05-09 14:34 UTC (permalink / raw)
  To: gcc-patches

This patch enables DFP support on aarch64, by updating config/dfp.m4
and regenerating the involved configure scripts.
We enable the BID format.

2022-03-31  Christophe Lyon  <christophe.lyon@arm.com>

	* config/dfp.m4: Add aarch64 support.
	* gcc/configure: Regenerate.
	* libdecnumber/configure: Regenerate.
	* libgcc/configure: Regenerate.
---
 config/dfp.m4          | 3 ++-
 gcc/configure          | 3 ++-
 libdecnumber/configure | 3 ++-
 libgcc/configure       | 3 ++-
 4 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/config/dfp.m4 b/config/dfp.m4
index 5b6a3f9d114..d1d151b2da7 100644
--- a/config/dfp.m4
+++ b/config/dfp.m4
@@ -38,6 +38,7 @@ Valid choices are 'yes', 'bid', 'dpd', and 'no'.]) ;;
 ],
 [
   case $1 in
+    aarch64* | \
     powerpc*-*-linux* | i?86*-*-linux* | x86_64*-*-linux* | s390*-*-linux* | \
     i?86*-*-elfiamcu | i?86*-*-gnu* | x86_64*-*-gnu* | \
     i?86*-*-mingw* | x86_64*-*-mingw* | \
@@ -55,7 +56,7 @@ Valid choices are 'yes', 'bid', 'dpd', and 'no'.]) ;;
 case x$enable_decimal_float in
   xyes)
     case $1 in
-      i?86*-*-* | x86_64*-*-*)
+      aarch64* | i?86*-*-* | x86_64*-*-*)
 	enable_decimal_float=bid
 	;;
       *)
diff --git a/gcc/configure b/gcc/configure
index 5ce0557719a..37e0dd5e414 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -7896,6 +7896,7 @@ Valid choices are 'yes', 'bid', 'dpd', and 'no'." "$LINENO" 5 ;;
 else
 
   case $target in
+    aarch64* | \
     powerpc*-*-linux* | i?86*-*-linux* | x86_64*-*-linux* | s390*-*-linux* | \
     i?86*-*-elfiamcu | i?86*-*-gnu* | x86_64*-*-gnu* | \
     i?86*-*-mingw* | x86_64*-*-mingw* | \
@@ -7916,7 +7917,7 @@ fi
 case x$enable_decimal_float in
   xyes)
     case $target in
-      i?86*-*-* | x86_64*-*-*)
+      aarch64* | i?86*-*-* | x86_64*-*-*)
 	enable_decimal_float=bid
 	;;
       *)
diff --git a/libdecnumber/configure b/libdecnumber/configure
index da5302f9315..fb6db05565a 100755
--- a/libdecnumber/configure
+++ b/libdecnumber/configure
@@ -4903,6 +4903,7 @@ Valid choices are 'yes', 'bid', 'dpd', and 'no'." "$LINENO" 5 ;;
 else
 
   case $target in
+    aarch64* | \
     powerpc*-*-linux* | i?86*-*-linux* | x86_64*-*-linux* | s390*-*-linux* | \
     i?86*-*-elfiamcu | i?86*-*-gnu* | x86_64*-*-gnu* | \
     i?86*-*-mingw* | x86_64*-*-mingw* | \
@@ -4923,7 +4924,7 @@ fi
 case x$enable_decimal_float in
   xyes)
     case $target in
-      i?86*-*-* | x86_64*-*-*)
+      aarch64* | i?86*-*-* | x86_64*-*-*)
 	enable_decimal_float=bid
 	;;
       *)
diff --git a/libgcc/configure b/libgcc/configure
index 1f9b2ac578b..61f3ace2891 100755
--- a/libgcc/configure
+++ b/libgcc/configure
@@ -4771,6 +4771,7 @@ Valid choices are 'yes', 'bid', 'dpd', and 'no'." "$LINENO" 5 ;;
 else
 
   case $host in
+    aarch64* | \
     powerpc*-*-linux* | i?86*-*-linux* | x86_64*-*-linux* | s390*-*-linux* | \
     i?86*-*-elfiamcu | i?86*-*-gnu* | x86_64*-*-gnu* | \
     i?86*-*-mingw* | x86_64*-*-mingw* | \
@@ -4791,7 +4792,7 @@ fi
 case x$enable_decimal_float in
   xyes)
     case $host in
-      i?86*-*-* | x86_64*-*-*)
+      aarch64* | i?86*-*-* | x86_64*-*-*)
 	enable_decimal_float=bid
 	;;
       *)
-- 
2.25.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 02/10] aarch64: Add backend support for DFP
  2022-05-09 14:34 [PATCH 00/10] Enable Decimal Floating Point (DFP) on AArch64 Christophe Lyon
  2022-05-09 14:34 ` [PATCH 01/10] aarch64: Enable DFP (Decimal Floating-point) (BID format) Christophe Lyon
@ 2022-05-09 14:34 ` Christophe Lyon
  2022-05-10  9:23   ` Richard Sandiford
  2022-05-13 16:08   ` [PATCH v2 " Christophe Lyon
  2022-05-09 14:35 ` [PATCH 03/10] libgcc: Enable XF mode conversions to/from DFP modes only if supported Christophe Lyon
                   ` (8 subsequent siblings)
  10 siblings, 2 replies; 33+ messages in thread
From: Christophe Lyon @ 2022-05-09 14:34 UTC (permalink / raw)
  To: gcc-patches

This patch updates the aarch64 backend as needed to support DFP modes
(SD, DD and TD).

2022-03-31  Christophe Lyon  <christophe.lyon@arm.com>

	gcc/
	* config/aarch64/aarch64.cc
	(aarch64_split_128bit_move): Handle DFP modes.
	(aarch64_gen_storewb_pair): Likewise.
	(aarch64_gen_loadwb_pair): Likewise.
	(aarch64_gen_store_pair): Likewise.
	(aarch64_gen_load_pair): Likewise.
	(aarch64_mode_valid_for_sched_fusion_p): Likewise.
	(aarch64_classify_address): Likewise.
	(aarch64_legitimize_address_displacement): Likewise.
	(aarch64_can_const_movi_rtx_p): Likewise.
	(aarch64_anchor_offset): Likewise.
	(aarch64_secondary_reload): Likewise.
	(aarch64_rtx_costs): Likewise.
	(aarch64_gimplify_va_arg_expr): Likewise.
	(aapcs_vfp_sub_candidate): Likewise.
	(aarch64_vfp_is_call_or_return_candidate): Likewise.
	(aarch64_output_scalar_simd_mov_immediate): Likewise.
	(aarch64_gen_adjusted_ldpstp): Likewise.
	(aarch64_scalar_mode_supported_p): Accept DFP modes if enabled.
	* config/aarch64/aarch64.md
	(movsf_aarch64): Use SFD iterator and rename into
	mov<mode>_aarch64.
	(movdf_aarch64): Use DFD iterator and rename into
	mov<mode>_aarch64.
	(movtf_aarch64): Use TFD iterator and rename into
	mov<mode>_aarch64.
	(split pattern for move TF mode): Use TFD iterator.
	(load_pair_dw_tftf): Use TX iterator and rename into
	load_pair_dw_<mode><mode>.
	(store_pair_dw_tftf): Likewise.
	(loadwb_pair<GPF:mode>_<P:mode>): Use GPF_PAIR iterator.
	(storewb_pair<GPF:mode>_<P:mode>): Likewise.
	* config/aarch64/aarch64/iterators.md
	(GPF_PAIR): New iterator.
	(GPF_TF_F16_MOV): Add DFP modes.
	(SFD, DFD, TFD): New iterators.
	(GPF_TF): Add DFP modes.
	(TX, DX, DX2): Likewise.
---
 gcc/config/aarch64/aarch64.cc   | 95 +++++++++++++++++++++++++--------
 gcc/config/aarch64/aarch64.md   | 86 ++++++++++++++---------------
 gcc/config/aarch64/iterators.md | 28 +++++++---
 3 files changed, 136 insertions(+), 73 deletions(-)

diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index bd855758778..0f1b3c04158 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -4828,7 +4828,7 @@ aarch64_split_128bit_move (rtx dst, rtx src)
 
   machine_mode mode = GET_MODE (dst);
 
-  gcc_assert (mode == TImode || mode == TFmode);
+  gcc_assert (mode == TImode || mode == TFmode || mode == TDmode);
   gcc_assert (!(side_effects_p (src) || side_effects_p (dst)));
   gcc_assert (mode == GET_MODE (src) || GET_MODE (src) == VOIDmode);
 
@@ -8464,10 +8464,18 @@ aarch64_gen_storewb_pair (machine_mode mode, rtx base, rtx reg, rtx reg2,
       return gen_storewb_pairdf_di (base, base, reg, reg2,
 				    GEN_INT (-adjustment),
 				    GEN_INT (UNITS_PER_WORD - adjustment));
+    case E_DDmode:
+      return gen_storewb_pairdd_di (base, base, reg, reg2,
+				    GEN_INT (-adjustment),
+				    GEN_INT (UNITS_PER_WORD - adjustment));
     case E_TFmode:
       return gen_storewb_pairtf_di (base, base, reg, reg2,
 				    GEN_INT (-adjustment),
 				    GEN_INT (UNITS_PER_VREG - adjustment));
+    case E_TDmode:
+      return gen_storewb_pairtd_di (base, base, reg, reg2,
+				    GEN_INT (-adjustment),
+				    GEN_INT (UNITS_PER_VREG - adjustment));
     default:
       gcc_unreachable ();
     }
@@ -8510,9 +8518,15 @@ aarch64_gen_loadwb_pair (machine_mode mode, rtx base, rtx reg, rtx reg2,
     case E_DFmode:
       return gen_loadwb_pairdf_di (base, base, reg, reg2, GEN_INT (adjustment),
 				   GEN_INT (UNITS_PER_WORD));
+    case E_DDmode:
+      return gen_loadwb_pairdd_di (base, base, reg, reg2, GEN_INT (adjustment),
+				   GEN_INT (UNITS_PER_WORD));
     case E_TFmode:
       return gen_loadwb_pairtf_di (base, base, reg, reg2, GEN_INT (adjustment),
 				   GEN_INT (UNITS_PER_VREG));
+    case E_TDmode:
+      return gen_loadwb_pairtd_di (base, base, reg, reg2, GEN_INT (adjustment),
+				   GEN_INT (UNITS_PER_VREG));
     default:
       gcc_unreachable ();
     }
@@ -8561,9 +8575,15 @@ aarch64_gen_store_pair (machine_mode mode, rtx mem1, rtx reg1, rtx mem2,
     case E_DFmode:
       return gen_store_pair_dw_dfdf (mem1, reg1, mem2, reg2);
 
+    case E_DDmode:
+      return gen_store_pair_dw_dddd (mem1, reg1, mem2, reg2);
+
     case E_TFmode:
       return gen_store_pair_dw_tftf (mem1, reg1, mem2, reg2);
 
+    case E_TDmode:
+      return gen_store_pair_dw_tdtd (mem1, reg1, mem2, reg2);
+
     case E_V4SImode:
       return gen_vec_store_pairv4siv4si (mem1, reg1, mem2, reg2);
 
@@ -8590,9 +8610,15 @@ aarch64_gen_load_pair (machine_mode mode, rtx reg1, rtx mem1, rtx reg2,
     case E_DFmode:
       return gen_load_pair_dw_dfdf (reg1, mem1, reg2, mem2);
 
+    case E_DDmode:
+      return gen_load_pair_dw_dddd (reg1, mem1, reg2, mem2);
+
     case E_TFmode:
       return gen_load_pair_dw_tftf (reg1, mem1, reg2, mem2);
 
+    case E_TDmode:
+      return gen_load_pair_dw_tdtd (reg1, mem1, reg2, mem2);
+
     case E_V4SImode:
       return gen_load_pairv4siv4si (reg1, mem1, reg2, mem2);
 
@@ -10568,6 +10594,7 @@ aarch64_mode_valid_for_sched_fusion_p (machine_mode mode)
 {
   return mode == SImode || mode == DImode
 	 || mode == SFmode || mode == DFmode
+	 || mode == SDmode || mode == DDmode
 	 || (aarch64_vector_mode_supported_p (mode)
 	     && (known_eq (GET_MODE_SIZE (mode), 8)
 		 || (known_eq (GET_MODE_SIZE (mode), 16)
@@ -10610,12 +10637,13 @@ aarch64_classify_address (struct aarch64_address_info *info,
   vec_flags &= ~VEC_PARTIAL;
 
   /* On BE, we use load/store pair for all large int mode load/stores.
-     TI/TFmode may also use a load/store pair.  */
+     TI/TF/TDmode may also use a load/store pair.  */
   bool advsimd_struct_p = (vec_flags == (VEC_ADVSIMD | VEC_STRUCT));
   bool load_store_pair_p = (type == ADDR_QUERY_LDP_STP
 			    || type == ADDR_QUERY_LDP_STP_N
 			    || mode == TImode
 			    || mode == TFmode
+			    || mode == TDmode
 			    || (BYTES_BIG_ENDIAN && advsimd_struct_p));
   /* If we are dealing with ADDR_QUERY_LDP_STP_N that means the incoming mode
      corresponds to the actual size of the memory being loaded/stored and the
@@ -10689,7 +10717,7 @@ aarch64_classify_address (struct aarch64_address_info *info,
 	  info->offset = op1;
 	  info->const_offset = offset;
 
-	  /* TImode and TFmode values are allowed in both pairs of X
+	  /* TImode, TFmode and TDmode values are allowed in both pairs of X
 	     registers and individual Q registers.  The available
 	     address modes are:
 	     X,X: 7-bit signed scaled offset
@@ -10698,7 +10726,7 @@ aarch64_classify_address (struct aarch64_address_info *info,
 	     When performing the check for pairs of X registers i.e.  LDP/STP
 	     pass down DImode since that is the natural size of the LDP/STP
 	     instruction memory accesses.  */
-	  if (mode == TImode || mode == TFmode)
+	  if (mode == TImode || mode == TFmode || mode == TDmode)
 	    return (aarch64_offset_7bit_signed_scaled_p (DImode, offset)
 		    && (aarch64_offset_9bit_signed_unscaled_p (mode, offset)
 			|| offset_12bit_unsigned_scaled_p (mode, offset)));
@@ -10821,14 +10849,14 @@ aarch64_classify_address (struct aarch64_address_info *info,
 	  info->offset = XEXP (XEXP (x, 1), 1);
 	  info->const_offset = offset;
 
-	  /* TImode and TFmode values are allowed in both pairs of X
+	  /* TImode, TFmode and TDmode values are allowed in both pairs of X
 	     registers and individual Q registers.  The available
 	     address modes are:
 	     X,X: 7-bit signed scaled offset
 	     Q:   9-bit signed offset
 	     We conservatively require an offset representable in either mode.
 	   */
-	  if (mode == TImode || mode == TFmode)
+	  if (mode == TImode || mode == TFmode || mode == TDmode)
 	    return (aarch64_offset_7bit_signed_scaled_p (mode, offset)
 		    && aarch64_offset_9bit_signed_unscaled_p (mode, offset));
 
@@ -10990,9 +11018,9 @@ aarch64_legitimize_address_displacement (rtx *offset1, rtx *offset2,
 	 offset.  Use 4KB range for 1- and 2-byte accesses and a 16KB
 	 range otherwise to increase opportunities for sharing the base
 	 address of different sizes.  Unaligned accesses use the signed
-	 9-bit range, TImode/TFmode use the intersection of signed
+	 9-bit range, TImode/TFmode/TDmode use the intersection of signed
 	 scaled 7-bit and signed 9-bit offset.  */
-      if (mode == TImode || mode == TFmode)
+      if (mode == TImode || mode == TFmode || mode == TDmode)
 	second_offset = ((const_offset + 0x100) & 0x1f8) - 0x100;
       else if ((const_offset & (size - 1)) != 0)
 	second_offset = ((const_offset + 0x100) & 0x1ff) - 0x100;
@@ -11156,7 +11184,7 @@ aarch64_can_const_movi_rtx_p (rtx x, machine_mode mode)
   else
     return false;
 
-   /* use a 64 bit mode for everything except for DI/DF mode, where we use
+   /* use a 64 bit mode for everything except for DI/DF/DD mode, where we use
      a 128 bit vector mode.  */
   int width = GET_MODE_BITSIZE (imode) == 64 ? 128 : 64;
 
@@ -12356,7 +12384,7 @@ aarch64_anchor_offset (HOST_WIDE_INT offset, HOST_WIDE_INT size,
   if (IN_RANGE (offset, -256, 0))
     return 0;
 
-  if (mode == TImode || mode == TFmode)
+  if (mode == TImode || mode == TFmode || mode == TDmode)
     return (offset + 0x100) & ~0x1ff;
 
   /* Use 12-bit offset by access size.  */
@@ -12465,7 +12493,9 @@ aarch64_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x,
 
   /* Without the TARGET_SIMD instructions we cannot move a Q register
      to a Q register directly.  We need a scratch.  */
-  if (REG_P (x) && (mode == TFmode || mode == TImode) && mode == GET_MODE (x)
+  if (REG_P (x)
+      && (mode == TFmode || mode == TImode || mode == TDmode)
+      && mode == GET_MODE (x)
       && FP_REGNUM_P (REGNO (x)) && !TARGET_SIMD
       && reg_class_subset_p (rclass, FP_REGS))
     {
@@ -12473,14 +12503,16 @@ aarch64_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x,
       return NO_REGS;
     }
 
-  /* A TFmode or TImode memory access should be handled via an FP_REGS
+  /* A TFmode, TImode or TDmode memory access should be handled via an FP_REGS
      because AArch64 has richer addressing modes for LDR/STR instructions
      than LDP/STP instructions.  */
   if (TARGET_FLOAT && rclass == GENERAL_REGS
       && known_eq (GET_MODE_SIZE (mode), 16) && MEM_P (x))
     return FP_REGS;
 
-  if (rclass == FP_REGS && (mode == TImode || mode == TFmode) && CONSTANT_P(x))
+  if (rclass == FP_REGS
+      && (mode == TImode || mode == TFmode || mode == TDmode)
+      && CONSTANT_P(x))
       return GENERAL_REGS;
 
   return NO_REGS;
@@ -13611,9 +13643,9 @@ aarch64_rtx_costs (rtx x, machine_mode mode, int outer ATTRIBUTE_UNUSED,
 		*cost += extra_cost->ldst.storev;
 	      else if (GET_MODE_CLASS (mode) == MODE_INT)
 		*cost += extra_cost->ldst.store;
-	      else if (mode == SFmode)
+	      else if (mode == SFmode || mode == SDmode)
 		*cost += extra_cost->ldst.storef;
-	      else if (mode == DFmode)
+	      else if (mode == DFmode || mode == DDmode)
 		*cost += extra_cost->ldst.stored;
 
 	      *cost +=
@@ -13737,11 +13769,11 @@ aarch64_rtx_costs (rtx x, machine_mode mode, int outer ATTRIBUTE_UNUSED,
 	  /* mov[df,sf]_aarch64.  */
 	  if (aarch64_float_const_representable_p (x))
 	    /* FMOV (scalar immediate).  */
-	    *cost += extra_cost->fp[mode == DFmode].fpconst;
+	    *cost += extra_cost->fp[mode == DFmode || mode == DDmode].fpconst;
 	  else if (!aarch64_float_const_zero_rtx_p (x))
 	    {
 	      /* This will be a load from memory.  */
-	      if (mode == DFmode)
+	      if (mode == DFmode || mode == DDmode)
 		*cost += extra_cost->ldst.loadd;
 	      else
 		*cost += extra_cost->ldst.loadf;
@@ -13767,9 +13799,9 @@ aarch64_rtx_costs (rtx x, machine_mode mode, int outer ATTRIBUTE_UNUSED,
 	    *cost += extra_cost->ldst.loadv;
 	  else if (GET_MODE_CLASS (mode) == MODE_INT)
 	    *cost += extra_cost->ldst.load;
-	  else if (mode == SFmode)
+	  else if (mode == SFmode || mode == SDmode)
 	    *cost += extra_cost->ldst.loadf;
-	  else if (mode == DFmode)
+	  else if (mode == DFmode || mode == DDmode)
 	    *cost += extra_cost->ldst.loadd;
 
 	  *cost +=
@@ -19795,6 +19827,18 @@ aarch64_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
 	  field_t = long_double_type_node;
 	  field_ptr_t = long_double_ptr_type_node;
 	  break;
+	case SDmode:
+	  field_t = dfloat32_type_node;
+	  field_ptr_t = build_pointer_type (dfloat32_type_node);
+	  break;
+	case DDmode:
+	  field_t = dfloat64_type_node;
+	  field_ptr_t = build_pointer_type (dfloat64_type_node);
+	  break;
+	case TDmode:
+	  field_t = dfloat128_type_node;
+	  field_ptr_t = build_pointer_type (dfloat128_type_node);
+	  break;
 	case E_HFmode:
 	  field_t = aarch64_fp16_type_node;
 	  field_ptr_t = aarch64_fp16_ptr_type_node;
@@ -20046,7 +20090,8 @@ aapcs_vfp_sub_candidate (const_tree type, machine_mode *modep,
     case REAL_TYPE:
       mode = TYPE_MODE (type);
       if (mode != DFmode && mode != SFmode
-	  && mode != TFmode && mode != HFmode)
+	  && mode != TFmode && mode != HFmode
+	  && mode != SDmode && mode != DDmode && mode != TDmode)
 	return -1;
 
       if (*modep == VOIDmode)
@@ -20362,7 +20407,8 @@ aarch64_vfp_is_call_or_return_candidate (machine_mode mode,
   machine_mode new_mode = VOIDmode;
   bool composite_p = aarch64_composite_type_p (type, mode);
 
-  if ((!composite_p && GET_MODE_CLASS (mode) == MODE_FLOAT)
+  if ((!composite_p && ((GET_MODE_CLASS (mode) == MODE_FLOAT)
+			|| GET_MODE_CLASS (mode) == MODE_DECIMAL_FLOAT))
       || aarch64_short_vector_p (type, mode))
     {
       *count = 1;
@@ -23264,7 +23310,7 @@ aarch64_output_scalar_simd_mov_immediate (rtx immediate, scalar_int_mode mode)
     }
 
   machine_mode vmode;
-  /* use a 64 bit mode for everything except for DI/DF mode, where we use
+  /* use a 64 bit mode for everything except for DI/DF/DD mode, where we use
      a 128 bit vector mode.  */
   int width = GET_MODE_BITSIZE (mode) == 64 ? 128 : 64;
 
@@ -26082,7 +26128,7 @@ aarch64_gen_adjusted_ldpstp (rtx *operands, bool load,
     base_off = (off_val_1 + off_val_3) / 2;
   else
     /* However, due to issues with negative LDP/STP offset generation for
-       larger modes, for DF, DI and vector modes. we must not use negative
+       larger modes, for DF, DD, DI and vector modes. we must not use negative
        addresses smaller than 9 signed unadjusted bits can store.  This
        provides the most range in this case.  */
     base_off = off_val_1;
@@ -26360,6 +26406,9 @@ aarch64_libgcc_floating_mode_supported_p (scalar_float_mode mode)
 static bool
 aarch64_scalar_mode_supported_p (scalar_mode mode)
 {
+  if (DECIMAL_FLOAT_MODE_P (mode))
+    return default_decimal_float_supported_p ();
+
   return (mode == HFmode
 	  ? true
 	  : default_scalar_mode_supported_p (mode));
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index f5c635938ad..b5b69da4fab 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -1477,11 +1477,11 @@ (define_insn "*mov<mode>_aarch64"
    (set_attr "arch" "simd,fp16,simd,simd,simd,fp16,simd,*,*,*,*,*")]
 )
 
-(define_insn "*movsf_aarch64"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=w,w  ,?r,w,w  ,w  ,w,m,r,m ,r,r")
-	(match_operand:SF 1 "general_operand"      "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r,M"))]
-  "TARGET_FLOAT && (register_operand (operands[0], SFmode)
-    || aarch64_reg_or_fp_zero (operands[1], SFmode))"
+(define_insn "*mov<mode>_aarch64"
+  [(set (match_operand:SFD 0 "nonimmediate_operand" "=w,w  ,?r,w,w  ,w  ,w,m,r,m ,r,r")
+	(match_operand:SFD 1 "general_operand"      "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r,M"))]
+  "TARGET_FLOAT && (register_operand (operands[0], <MODE>mode)
+    || aarch64_reg_or_fp_zero (operands[1], <MODE>mode))"
   "@
    movi\\t%0.2s, #0
    fmov\\t%s0, %w1
@@ -1501,11 +1501,11 @@ (define_insn "*movsf_aarch64"
    (set_attr "arch" "simd,*,*,*,*,simd,*,*,*,*,*,*")]
 )
 
-(define_insn "*movdf_aarch64"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=w, w  ,?r,w,w  ,w  ,w,m,r,m ,r,r")
-	(match_operand:DF 1 "general_operand"      "Y , ?rY, w,w,Ufc,Uvi,m,w,m,rY,r,N"))]
-  "TARGET_FLOAT && (register_operand (operands[0], DFmode)
-    || aarch64_reg_or_fp_zero (operands[1], DFmode))"
+(define_insn "*mov<mode>_aarch64"
+  [(set (match_operand:DFD 0 "nonimmediate_operand" "=w, w  ,?r,w,w  ,w  ,w,m,r,m ,r,r")
+	(match_operand:DFD 1 "general_operand"      "Y , ?rY, w,w,Ufc,Uvi,m,w,m,rY,r,N"))]
+  "TARGET_FLOAT && (register_operand (operands[0], <MODE>mode)
+    || aarch64_reg_or_fp_zero (operands[1], <MODE>mode))"
   "@
    movi\\t%d0, #0
    fmov\\t%d0, %x1
@@ -1545,13 +1545,13 @@ (define_split
   }
 )
 
-(define_insn "*movtf_aarch64"
-  [(set (match_operand:TF 0
+(define_insn "*mov<mode>_aarch64"
+  [(set (match_operand:TFD 0
 	 "nonimmediate_operand" "=w,?r ,w ,?r,w,?w,w,m,?r,m ,m")
-	(match_operand:TF 1
+	(match_operand:TFD 1
 	 "general_operand"      " w,?rY,?r,w ,Y,Y ,m,w,m ,?r,Y"))]
-  "TARGET_FLOAT && (register_operand (operands[0], TFmode)
-    || aarch64_reg_or_fp_zero (operands[1], TFmode))"
+  "TARGET_FLOAT && (register_operand (operands[0], <MODE>mode)
+    || aarch64_reg_or_fp_zero (operands[1], <MODE>mode))"
   "@
    mov\\t%0.16b, %1.16b
    #
@@ -1571,8 +1571,8 @@ (define_insn "*movtf_aarch64"
 )
 
 (define_split
-   [(set (match_operand:TF 0 "register_operand" "")
-	 (match_operand:TF 1 "nonmemory_operand" ""))]
+   [(set (match_operand:TFD 0 "register_operand" "")
+	 (match_operand:TFD 1 "nonmemory_operand" ""))]
   "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
   [(const_int 0)]
   {
@@ -1746,16 +1746,16 @@ (define_insn "load_pair_dw_<DX:mode><DX2:mode>"
    (set_attr "arch" "*,fp")]
 )
 
-(define_insn "load_pair_dw_tftf"
-  [(set (match_operand:TF 0 "register_operand" "=w")
-	(match_operand:TF 1 "aarch64_mem_pair_operand" "Ump"))
-   (set (match_operand:TF 2 "register_operand" "=w")
-	(match_operand:TF 3 "memory_operand" "m"))]
+(define_insn "load_pair_dw_<mode><mode>"
+  [(set (match_operand:TX 0 "register_operand" "=w")
+	(match_operand:TX 1 "aarch64_mem_pair_operand" "Ump"))
+   (set (match_operand:TX 2 "register_operand" "=w")
+	(match_operand:TX 3 "memory_operand" "m"))]
    "TARGET_SIMD
     && rtx_equal_p (XEXP (operands[3], 0),
 		    plus_constant (Pmode,
 				   XEXP (operands[1], 0),
-				   GET_MODE_SIZE (TFmode)))"
+				   GET_MODE_SIZE (<MODE>mode)))"
   "ldp\\t%q0, %q2, %z1"
   [(set_attr "type" "neon_ldp_q")
    (set_attr "fp" "yes")]
@@ -1796,16 +1796,16 @@ (define_insn "store_pair_dw_<DX:mode><DX2:mode>"
    (set_attr "arch" "*,fp")]
 )
 
-(define_insn "store_pair_dw_tftf"
-  [(set (match_operand:TF 0 "aarch64_mem_pair_operand" "=Ump")
-	(match_operand:TF 1 "register_operand" "w"))
-   (set (match_operand:TF 2 "memory_operand" "=m")
-	(match_operand:TF 3 "register_operand" "w"))]
+(define_insn "store_pair_dw_<mode><mode>"
+  [(set (match_operand:TX 0 "aarch64_mem_pair_operand" "=Ump")
+	(match_operand:TX 1 "register_operand" "w"))
+   (set (match_operand:TX 2 "memory_operand" "=m")
+	(match_operand:TX 3 "register_operand" "w"))]
    "TARGET_SIMD &&
     rtx_equal_p (XEXP (operands[2], 0),
 		 plus_constant (Pmode,
 				XEXP (operands[0], 0),
-				GET_MODE_SIZE (TFmode)))"
+				GET_MODE_SIZE (<MODE>mode)))"
   "stp\\t%q1, %q3, %z0"
   [(set_attr "type" "neon_stp_q")
    (set_attr "fp" "yes")]
@@ -1828,18 +1828,18 @@ (define_insn "loadwb_pair<GPI:mode>_<P:mode>"
   [(set_attr "type" "load_<GPI:ldpstp_sz>")]
 )
 
-(define_insn "loadwb_pair<GPF:mode>_<P:mode>"
+(define_insn "loadwb_pair<GPF_PAIR:mode>_<P:mode>"
   [(parallel
     [(set (match_operand:P 0 "register_operand" "=k")
           (plus:P (match_operand:P 1 "register_operand" "0")
                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
-     (set (match_operand:GPF 2 "register_operand" "=w")
-          (mem:GPF (match_dup 1)))
-     (set (match_operand:GPF 3 "register_operand" "=w")
-          (mem:GPF (plus:P (match_dup 1)
+     (set (match_operand:GPF_PAIR 2 "register_operand" "=w")
+          (mem:GPF_PAIR (match_dup 1)))
+     (set (match_operand:GPF_PAIR 3 "register_operand" "=w")
+          (mem:GPF_PAIR (plus:P (match_dup 1)
                    (match_operand:P 5 "const_int_operand" "n"))))])]
-  "INTVAL (operands[5]) == GET_MODE_SIZE (<GPF:MODE>mode)"
-  "ldp\\t%<GPF:w>2, %<GPF:w>3, [%1], %4"
+  "INTVAL (operands[5]) == GET_MODE_SIZE (<GPF_PAIR:MODE>mode)"
+  "ldp\\t%<GPF_PAIR:w>2, %<GPF_PAIR:w>3, [%1], %4"
   [(set_attr "type" "neon_load1_2reg")]
 )
 
@@ -1876,19 +1876,19 @@ (define_insn "storewb_pair<GPI:mode>_<P:mode>"
   [(set_attr "type" "store_<GPI:ldpstp_sz>")]
 )
 
-(define_insn "storewb_pair<GPF:mode>_<P:mode>"
+(define_insn "storewb_pair<GPF_PAIR:mode>_<P:mode>"
   [(parallel
     [(set (match_operand:P 0 "register_operand" "=&k")
           (plus:P (match_operand:P 1 "register_operand" "0")
                   (match_operand:P 4 "aarch64_mem_pair_offset" "n")))
-     (set (mem:GPF (plus:P (match_dup 0)
+     (set (mem:GPF_PAIR (plus:P (match_dup 0)
                    (match_dup 4)))
-          (match_operand:GPF 2 "register_operand" "w"))
-     (set (mem:GPF (plus:P (match_dup 0)
+          (match_operand:GPF_PAIR 2 "register_operand" "w"))
+     (set (mem:GPF_PAIR (plus:P (match_dup 0)
                    (match_operand:P 5 "const_int_operand" "n")))
-          (match_operand:GPF 3 "register_operand" "w"))])]
-  "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPF:MODE>mode)"
-  "stp\\t%<GPF:w>2, %<GPF:w>3, [%0, %4]!"
+          (match_operand:GPF_PAIR 3 "register_operand" "w"))])]
+  "INTVAL (operands[5]) == INTVAL (operands[4]) + GET_MODE_SIZE (<GPF_PAIR:MODE>mode)"
+  "stp\\t%<GPF_PAIR:w>2, %<GPF_PAIR:w>3, [%0, %4]!"
   [(set_attr "type" "neon_store1_2reg<q>")]
 )
 
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index 88af964de7e..8a6801a6716 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -54,6 +54,10 @@ (define_mode_iterator ALLX [QI HI SI])
 ;; Iterator for General Purpose Floating-point registers (32- and 64-bit modes)
 (define_mode_iterator GPF [SF DF])
 
+;; Iterator for General Purpose Floating-point registers suitable for
+;; load/store by pairs
+(define_mode_iterator GPF_PAIR [SF DF SD DD])
+
 ;; Iterator for all scalar floating point modes (HF, SF, DF)
 (define_mode_iterator GPF_F16 [(HF "AARCH64_ISA_F16") SF DF])
 
@@ -64,14 +68,24 @@ (define_mode_iterator GPF_HF [HF SF DF])
 (define_mode_iterator HFBF [HF BF])
 
 ;; Iterator for all scalar floating point modes suitable for moving, including
-;; special BF type (HF, SF, DF, TF and BF)
-(define_mode_iterator GPF_TF_F16_MOV [HF BF SF DF TF])
+;; special BF type and decimal floating point types (HF, SF, DF, TF, BF,
+;; SD, DD and TD)
+(define_mode_iterator GPF_TF_F16_MOV [HF BF SF DF TF SD DD TD])
+
+;; Iterator for scalar 32bit fp modes (SF, SD)
+(define_mode_iterator SFD [SD SF])
+
+;; Iterator for scalar 64bit fp modes (DF, DD)
+(define_mode_iterator DFD [DD DF])
+
+;; Iterator for scalar 128bit fp modes (TF, TD)
+(define_mode_iterator TFD [TD TF])
 
 ;; Double vector modes.
 (define_mode_iterator VDF [V2SF V4HF])
 
-;; Iterator for all scalar floating point modes (SF, DF and TF)
-(define_mode_iterator GPF_TF [SF DF TF])
+;; Iterator for all scalar floating point modes (SF, DF, TF SD, DD, and TD)
+(define_mode_iterator GPF_TF [SF DF TF SD DD TD])
 
 ;; Integer Advanced SIMD modes.
 (define_mode_iterator VDQ_I [V8QI V16QI V4HI V8HI V2SI V4SI V2DI])
@@ -298,7 +312,7 @@ (define_mode_iterator VB [V8QI V16QI])
 ;; 2 and 4 lane SI modes.
 (define_mode_iterator VS [V2SI V4SI])
 
-(define_mode_iterator TX [TI TF])
+(define_mode_iterator TX [TI TF TD])
 
 ;; Advanced SIMD opaque structure modes.
 (define_mode_iterator VSTRUCT [OI CI XI])
@@ -400,10 +414,10 @@ (define_mode_iterator VSTRUCT_QD [V2x8QI V2x4HI V2x2SI V2x1DI
 				  V4x8HF V4x4SF V4x2DF V4x8BF])
 
 ;; Double scalar modes
-(define_mode_iterator DX [DI DF])
+(define_mode_iterator DX [DI DF DD])
 
 ;; Duplicate of the above
-(define_mode_iterator DX2 [DI DF])
+(define_mode_iterator DX2 [DI DF DD])
 
 ;; Single scalar modes
 (define_mode_iterator SX [SI SF])
-- 
2.25.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 03/10] libgcc: Enable XF mode conversions to/from DFP modes only if supported
  2022-05-09 14:34 [PATCH 00/10] Enable Decimal Floating Point (DFP) on AArch64 Christophe Lyon
  2022-05-09 14:34 ` [PATCH 01/10] aarch64: Enable DFP (Decimal Floating-point) (BID format) Christophe Lyon
  2022-05-09 14:34 ` [PATCH 02/10] aarch64: Add backend support for DFP Christophe Lyon
@ 2022-05-09 14:35 ` Christophe Lyon
  2022-05-09 14:35 ` [PATCH 04/10] libgcc: enable DFP for AArch64 Christophe Lyon
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 33+ messages in thread
From: Christophe Lyon @ 2022-05-09 14:35 UTC (permalink / raw)
  To: gcc-patches

Some targets do not support XF mode (eg AArch64), so don't build the
corresponding to/from DFP modes convertion routines if
__LIBGCC_HAS_XF_MODE__ is not defined.

2022-03-31  Christophe Lyon  <christophe.lyon@arm.com>

	libgcc/
	* config/libbid/_dd_to_xf.c: Check __LIBGCC_HAS_XF_MODE__.
	* config/libbid/_sd_to_xf.c: Likewise.
	* config/libbid/_td_to_xf.c: Likewise.
	* config/libbid/_xf_to_dd.c: Likewise.
	* config/libbid/_xf_to_sd.c: Likewise.
	* config/libbid/_xf_to_td.c: Likewise.
---
 libgcc/config/libbid/_dd_to_xf.c | 2 ++
 libgcc/config/libbid/_sd_to_xf.c | 2 ++
 libgcc/config/libbid/_td_to_xf.c | 2 ++
 libgcc/config/libbid/_xf_to_dd.c | 2 ++
 libgcc/config/libbid/_xf_to_sd.c | 2 ++
 libgcc/config/libbid/_xf_to_td.c | 2 ++
 6 files changed, 12 insertions(+)

diff --git a/libgcc/config/libbid/_dd_to_xf.c b/libgcc/config/libbid/_dd_to_xf.c
index 5a2abbbb1f4..e4b12e8ac4f 100644
--- a/libgcc/config/libbid/_dd_to_xf.c
+++ b/libgcc/config/libbid/_dd_to_xf.c
@@ -25,6 +25,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #include "bid_functions.h"
 #include "bid_gcc_intrinsics.h"
 
+#ifdef __LIBGCC_HAS_XF_MODE__
 XFtype
 __bid_extendddxf (_Decimal64 x) {
   XFtype res;
@@ -34,3 +35,4 @@ __bid_extendddxf (_Decimal64 x) {
   res = __bid64_to_binary80 (ux.i);
   return (res);
 }
+#endif
diff --git a/libgcc/config/libbid/_sd_to_xf.c b/libgcc/config/libbid/_sd_to_xf.c
index 9af09913684..288ccb25075 100644
--- a/libgcc/config/libbid/_sd_to_xf.c
+++ b/libgcc/config/libbid/_sd_to_xf.c
@@ -25,6 +25,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #include "bid_functions.h"
 #include "bid_gcc_intrinsics.h"
 
+#ifdef __LIBGCC_HAS_XF_MODE__
 XFtype
 __bid_extendsdxf (_Decimal32 x) {
   XFtype res;
@@ -34,3 +35,4 @@ __bid_extendsdxf (_Decimal32 x) {
   res = __bid32_to_binary80 (ux.i);
   return (res);
 }
+#endif
diff --git a/libgcc/config/libbid/_td_to_xf.c b/libgcc/config/libbid/_td_to_xf.c
index b0c76a71497..e990282162d 100644
--- a/libgcc/config/libbid/_td_to_xf.c
+++ b/libgcc/config/libbid/_td_to_xf.c
@@ -25,6 +25,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #include "bid_functions.h"
 #include "bid_gcc_intrinsics.h"
 
+#ifdef __LIBGCC_HAS_XF_MODE__
 XFtype
 __bid_trunctdxf (_Decimal128 x) {
   XFtype res;
@@ -34,3 +35,4 @@ __bid_trunctdxf (_Decimal128 x) {
   res = __bid128_to_binary80 (ux.i);
   return (res);
 }
+#endif
diff --git a/libgcc/config/libbid/_xf_to_dd.c b/libgcc/config/libbid/_xf_to_dd.c
index 9feb0f2c3d6..e3246a1c2e1 100644
--- a/libgcc/config/libbid/_xf_to_dd.c
+++ b/libgcc/config/libbid/_xf_to_dd.c
@@ -25,9 +25,11 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #include "bid_functions.h"
 #include "bid_gcc_intrinsics.h"
 
+#ifdef __LIBGCC_HAS_XF_MODE__
 _Decimal64
 __bid_truncxfdd (XFtype x) {
   union decimal64 res;
   res.i = __binary80_to_bid64 (x);
   return (res.d);
 }
+#endif
diff --git a/libgcc/config/libbid/_xf_to_sd.c b/libgcc/config/libbid/_xf_to_sd.c
index 7d46548af6c..9147e979182 100644
--- a/libgcc/config/libbid/_xf_to_sd.c
+++ b/libgcc/config/libbid/_xf_to_sd.c
@@ -25,9 +25,11 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #include "bid_functions.h"
 #include "bid_gcc_intrinsics.h"
 
+#ifdef __LIBGCC_HAS_XF_MODE__
 _Decimal32
 __bid_truncxfsd (XFtype x) {
   union decimal32 res;
   res.i = __binary80_to_bid32 (x);
   return (res.d);
 }
+#endif
diff --git a/libgcc/config/libbid/_xf_to_td.c b/libgcc/config/libbid/_xf_to_td.c
index 07987fdcc3a..c8d102b0b7f 100644
--- a/libgcc/config/libbid/_xf_to_td.c
+++ b/libgcc/config/libbid/_xf_to_td.c
@@ -25,9 +25,11 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #include "bid_functions.h"
 #include "bid_gcc_intrinsics.h"
 
+#ifdef __LIBGCC_HAS_XF_MODE__
 _Decimal128
 __bid_extendxftd (XFtype x) {
   union decimal128 res;
   res.i = __binary80_to_bid128 (x);
   return (res.d);
 }
+#endif
-- 
2.25.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 04/10] libgcc: enable DFP for AArch64
  2022-05-09 14:34 [PATCH 00/10] Enable Decimal Floating Point (DFP) on AArch64 Christophe Lyon
                   ` (2 preceding siblings ...)
  2022-05-09 14:35 ` [PATCH 03/10] libgcc: Enable XF mode conversions to/from DFP modes only if supported Christophe Lyon
@ 2022-05-09 14:35 ` Christophe Lyon
  2022-05-09 14:35 ` [PATCH 05/10] testsuite:: Fix pr39986.c testcase " Christophe Lyon
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 33+ messages in thread
From: Christophe Lyon @ 2022-05-09 14:35 UTC (permalink / raw)
  To: gcc-patches

DFP support on AArch64 relies on libgcc, so enable its DFP routines
for all AArch64 targets.

2022-03-31  Christophe Lyon  <christophe.lyon@arm.com>

	* libgcc/config.host: Add t-dfprules to AArch64 targets.
---
 libgcc/config.host | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/libgcc/config.host b/libgcc/config.host
index 8c56fcae5d2..927d34a9573 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -382,6 +382,7 @@ aarch64*-*-elf | aarch64*-*-rtems*)
 	tmake_file="${tmake_file} ${cpu_type}/t-aarch64"
 	tmake_file="${tmake_file} ${cpu_type}/t-lse t-slibgcc-libgcc"
 	tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm"
+	tmake_file="${tmake_file} t-dfprules"
 	md_unwind_header=aarch64/aarch64-unwind.h
 	;;
 aarch64*-*-freebsd*)
@@ -389,18 +390,21 @@ aarch64*-*-freebsd*)
 	tmake_file="${tmake_file} ${cpu_type}/t-aarch64"
 	tmake_file="${tmake_file} ${cpu_type}/t-lse t-slibgcc-libgcc"
 	tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm"
+	tmake_file="${tmake_file} t-dfprules"
 	md_unwind_header=aarch64/freebsd-unwind.h
 	;;
 aarch64*-*-netbsd*)
 	extra_parts="$extra_parts crtfastmath.o"
 	tmake_file="${tmake_file} ${cpu_type}/t-aarch64"
 	tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm"
+	tmake_file="${tmake_file} t-dfprules"
 	md_unwind_header=aarch64/aarch64-unwind.h
 	;;
 aarch64*-*-fuchsia*)
 	tmake_file="${tmake_file} ${cpu_type}/t-aarch64"
 	tmake_file="${tmake_file} ${cpu_type}/t-lse t-slibgcc-libgcc"
 	tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp"
+	tmake_file="${tmake_file} t-dfprules"
 	;;
 aarch64*-*-linux*)
 	extra_parts="$extra_parts crtfastmath.o"
@@ -408,6 +412,7 @@ aarch64*-*-linux*)
 	tmake_file="${tmake_file} ${cpu_type}/t-aarch64"
 	tmake_file="${tmake_file} ${cpu_type}/t-lse t-slibgcc-libgcc"
 	tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm"
+	tmake_file="${tmake_file} t-dfprules"
 	;;
 aarch64*-*-vxworks7*)
 	extra_parts="$extra_parts crtfastmath.o"
@@ -415,6 +420,7 @@ aarch64*-*-vxworks7*)
 	tmake_file="${tmake_file} ${cpu_type}/t-aarch64"
 	tmake_file="${tmake_file} ${cpu_type}/t-lse t-slibgcc-libgcc"
 	tmake_file="${tmake_file} ${cpu_type}/t-softfp t-softfp t-crtfm"
+	tmake_file="${tmake_file} t-dfprules"
 	;;
 alpha*-*-linux*)
 	tmake_file="${tmake_file} alpha/t-alpha alpha/t-ieee t-crtfm alpha/t-linux"
-- 
2.25.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 05/10] testsuite:: Fix pr39986.c testcase for AArch64
  2022-05-09 14:34 [PATCH 00/10] Enable Decimal Floating Point (DFP) on AArch64 Christophe Lyon
                   ` (3 preceding siblings ...)
  2022-05-09 14:35 ` [PATCH 04/10] libgcc: enable DFP for AArch64 Christophe Lyon
@ 2022-05-09 14:35 ` Christophe Lyon
  2022-05-09 14:35 ` [PATCH 06/10] testsuite: Add new tests for DFP under aarch64/aapcs64 Christophe Lyon
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 33+ messages in thread
From: Christophe Lyon @ 2022-05-09 14:35 UTC (permalink / raw)
  To: gcc-patches

The testcase in c-c++-common/dfp/pr39986.c detects if DFP constants
are correctly emitted in the assembly.  However, AArch64 uses .word
instead of the expected .long directive. With this patch, we now
accept both.

2022-03-31  Christophe Lyon <christophe.lyon@arm.com>

	gcc/testsuite/
	* c-c++-common/dfp/pr39986.c: Accept .word directive.
---
 gcc/testsuite/c-c++-common/dfp/pr39986.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/gcc/testsuite/c-c++-common/dfp/pr39986.c b/gcc/testsuite/c-c++-common/dfp/pr39986.c
index e7c9ce98283..4dfbf2446cc 100644
--- a/gcc/testsuite/c-c++-common/dfp/pr39986.c
+++ b/gcc/testsuite/c-c++-common/dfp/pr39986.c
@@ -14,19 +14,19 @@ _Decimal128 f = -678901.234e-6dl;
 /* The first value is DPD, the second is BID.  The order differs depending
    on whether the target is big-endian or little-endian.  */
 
-/* { dg-final { scan-assembler ".long\t(572653859|822183807)\n" } } */
+/* { dg-final { scan-assembler "(.long|.word)\t(572653859|822183807)\n" } } */
 
-/* { dg-final { scan-assembler ".long\t(-1572863965|-1308622825)\n" } } */
+/* { dg-final { scan-assembler "(.long|.word)\t(-1572863965|-1308622825)\n" } } */
 
-/* { dg-final { scan-assembler ".long\t(52|34)\n" } } */
-/* { dg-final { scan-assembler ".long\t(572784640|824180736)\n" } } */
+/* { dg-final { scan-assembler "(.long|.word)\t(52|34)\n" } } */
+/* { dg-final { scan-assembler "(.long|.word)\t(572784640|824180736)\n" } } */
 
-/* { dg-final { scan-assembler ".long\t(4736|4500)\n" } } */
-/* { dg-final { scan-assembler ".long\t(-1574174720|-1319108608)\n" } } */
+/* { dg-final { scan-assembler "(.long|.word)\t(4736|4500)\n" } } */
+/* { dg-final { scan-assembler "(.long|.word)\t(-1574174720|-1319108608)\n" } } */
 
-/* { dg-final { scan-assembler ".long\t(-1975952433|957645077)\n" } } */
-/* { dg-final { scan-assembler ".long\t(190215|132222)\n" } } */
-/* { dg-final { scan-assembler ".long\t(574193664|835452928)\n" } } */
+/* { dg-final { scan-assembler "(.long|.word)\t(-1975952433|957645077)\n" } } */
+/* { dg-final { scan-assembler "(.long|.word)\t(190215|132222)\n" } } */
+/* { dg-final { scan-assembler "(.long|.word)\t(574193664|835452928)\n" } } */
 
-/* { dg-final { scan-assembler ".long\t(931280180|678901234)\n" } } */
-/* { dg-final { scan-assembler ".long\t(-1576681472|-1339162624)\n" } } */
+/* { dg-final { scan-assembler "(.long|.word)\t(931280180|678901234)\n" } } */
+/* { dg-final { scan-assembler "(.long|.word)\t(-1576681472|-1339162624)\n" } } */
-- 
2.25.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 06/10] testsuite: Add new tests for DFP under aarch64/aapcs64
  2022-05-09 14:34 [PATCH 00/10] Enable Decimal Floating Point (DFP) on AArch64 Christophe Lyon
                   ` (4 preceding siblings ...)
  2022-05-09 14:35 ` [PATCH 05/10] testsuite:: Fix pr39986.c testcase " Christophe Lyon
@ 2022-05-09 14:35 ` Christophe Lyon
  2022-05-09 14:35 ` [PATCH 07/10] testsuite: enable more BID DFP tests for AArch64 Christophe Lyon
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 33+ messages in thread
From: Christophe Lyon @ 2022-05-09 14:35 UTC (permalink / raw)
  To: gcc-patches

This patch copies all existing tests involving float/double/long
double types and replaces them with _Decimal32/_Decimal64/_Decimal128.
I thought it would be clearer/easier to maintain to do it this way
rather than adding tests for DFP types in the existing testcases,
except for func-ret-1.c and func-ret-3.c.

This makes sure all cases tested for traditional floating-point are
equally tested for decimal floating-point.

The patch also adds a test involving loading DFP values from memory.

2022-03-31  Christophe Lyon  <christophe.lyon@arm.com>

	gcc/testsuite/
	* gcc.target/aarch64/aapcs64/aapcs64.exp: Support new dfp*.c tests.
	* gcc.target/aarch64/aapcs64/func-ret-1.c: Add DFP tests.
	* gcc.target/aarch64/aapcs64/func-ret-3.c: Add DFP tests.
	* gcc.target/aarch64/aapcs64/type-def.h: Add DFP types.
	* gcc.target/aarch64/aapcs64/dfp-1.c: New test.
	* gcc.target/aarch64/aapcs64/ice_dfp_5.c: New test.
	* gcc.target/aarch64/aapcs64/test_align_dfp-1.c: New test.
	* gcc.target/aarch64/aapcs64/test_align_dfp-4.c: New test.
	* gcc.target/aarch64/aapcs64/test_dfp_1.c: New test.
	* gcc.target/aarch64/aapcs64/test_dfp_10.c: New test.
	* gcc.target/aarch64/aapcs64/test_dfp_11.c: New test.
	* gcc.target/aarch64/aapcs64/test_dfp_12.c: New test.
	* gcc.target/aarch64/aapcs64/test_dfp_13.c: New test.
	* gcc.target/aarch64/aapcs64/test_dfp_14.c: New test.
	* gcc.target/aarch64/aapcs64/test_dfp_15.c: New test.
	* gcc.target/aarch64/aapcs64/test_dfp_16.c: New test.
	* gcc.target/aarch64/aapcs64/test_dfp_17.c: New test.
	* gcc.target/aarch64/aapcs64/test_dfp_18.c: New test.
	* gcc.target/aarch64/aapcs64/test_dfp_19.c: New test.
	* gcc.target/aarch64/aapcs64/test_dfp_2.c: New test.
	* gcc.target/aarch64/aapcs64/test_dfp_20.c: New test.
	* gcc.target/aarch64/aapcs64/test_dfp_21.c: New test.
	* gcc.target/aarch64/aapcs64/test_dfp_22.c: New test.
	* gcc.target/aarch64/aapcs64/test_dfp_23.c: New test.
	* gcc.target/aarch64/aapcs64/test_dfp_24.c: New test.
	* gcc.target/aarch64/aapcs64/test_dfp_25.c: New test.
	* gcc.target/aarch64/aapcs64/test_dfp_26.c: New test.
	* gcc.target/aarch64/aapcs64/test_dfp_27.c: New test.
	* gcc.target/aarch64/aapcs64/test_dfp_3.c: New test.
	* gcc.target/aarch64/aapcs64/test_dfp_5.c: New test.
	* gcc.target/aarch64/aapcs64/test_dfp_6.c: New test.
	* gcc.target/aarch64/aapcs64/test_dfp_7.c: New test.
	* gcc.target/aarch64/aapcs64/test_dfp_8.c: New test.
	* gcc.target/aarch64/aapcs64/test_dfp_9.c: New test.
	* gcc.target/aarch64/aapcs64/test_quad_double_dfp.c: New test.
	* gcc.target/aarch64/aapcs64/va_arg_dfp-1.c: New test.
	* gcc.target/aarch64/aapcs64/va_arg_dfp-10.c: New test.
	* gcc.target/aarch64/aapcs64/va_arg_dfp-11.c: New test.
	* gcc.target/aarch64/aapcs64/va_arg_dfp-12.c: New test.
	* gcc.target/aarch64/aapcs64/va_arg_dfp-13.c: New test.
	* gcc.target/aarch64/aapcs64/va_arg_dfp-14.c: New test.
	* gcc.target/aarch64/aapcs64/va_arg_dfp-16.c: New test.
	* gcc.target/aarch64/aapcs64/va_arg_dfp-2.c: New test.
	* gcc.target/aarch64/aapcs64/va_arg_dfp-3.c: New test.
	* gcc.target/aarch64/aapcs64/va_arg_dfp-4.c: New test.
	* gcc.target/aarch64/aapcs64/va_arg_dfp-5.c: New test.
	* gcc.target/aarch64/aapcs64/va_arg_dfp-6.c: New test.
	* gcc.target/aarch64/aapcs64/va_arg_dfp-8.c: New test.
	* gcc.target/aarch64/aapcs64/va_arg_dfp-9.c: New test.
---
 .../gcc.target/aarch64/aapcs64/aapcs64.exp    |   8 ++
 .../gcc.target/aarch64/aapcs64/dfp-1.c        |  24 ++++
 .../gcc.target/aarch64/aapcs64/func-ret-1.c   |   7 +
 .../gcc.target/aarch64/aapcs64/func-ret-3.c   |  67 +++++++++
 .../gcc.target/aarch64/aapcs64/ice_dfp_5.c    |  20 +++
 .../aarch64/aapcs64/test_align_dfp-1.c        | 126 +++++++++++++++++
 .../aarch64/aapcs64/test_align_dfp-4.c        |  42 ++++++
 .../gcc.target/aarch64/aapcs64/test_dfp_1.c   |  31 ++++
 .../gcc.target/aarch64/aapcs64/test_dfp_10.c  |  26 ++++
 .../gcc.target/aarch64/aapcs64/test_dfp_11.c  |  34 +++++
 .../gcc.target/aarch64/aapcs64/test_dfp_12.c  |  44 ++++++
 .../gcc.target/aarch64/aapcs64/test_dfp_13.c  |  34 +++++
 .../gcc.target/aarch64/aapcs64/test_dfp_14.c  |  35 +++++
 .../gcc.target/aarch64/aapcs64/test_dfp_15.c  |  21 +++
 .../gcc.target/aarch64/aapcs64/test_dfp_16.c  |  32 +++++
 .../gcc.target/aarch64/aapcs64/test_dfp_17.c  |  37 +++++
 .../gcc.target/aarch64/aapcs64/test_dfp_18.c  |  34 +++++
 .../gcc.target/aarch64/aapcs64/test_dfp_19.c  |  35 +++++
 .../gcc.target/aarch64/aapcs64/test_dfp_2.c   |  17 +++
 .../gcc.target/aarch64/aapcs64/test_dfp_20.c  |  22 +++
 .../gcc.target/aarch64/aapcs64/test_dfp_21.c  |  21 +++
 .../gcc.target/aarch64/aapcs64/test_dfp_22.c  |  19 +++
 .../gcc.target/aarch64/aapcs64/test_dfp_23.c  |  42 ++++++
 .../gcc.target/aarch64/aapcs64/test_dfp_24.c  |  22 +++
 .../gcc.target/aarch64/aapcs64/test_dfp_25.c  |  61 ++++++++
 .../gcc.target/aarch64/aapcs64/test_dfp_26.c  |  54 +++++++
 .../gcc.target/aarch64/aapcs64/test_dfp_27.c  |  46 ++++++
 .../gcc.target/aarch64/aapcs64/test_dfp_3.c   |  18 +++
 .../gcc.target/aarch64/aapcs64/test_dfp_5.c   |  24 ++++
 .../gcc.target/aarch64/aapcs64/test_dfp_6.c   |  26 ++++
 .../gcc.target/aarch64/aapcs64/test_dfp_7.c   |  30 ++++
 .../gcc.target/aarch64/aapcs64/test_dfp_8.c   |  24 ++++
 .../gcc.target/aarch64/aapcs64/test_dfp_9.c   |  32 +++++
 .../aarch64/aapcs64/test_quad_double_dfp.c    |  26 ++++
 .../gcc.target/aarch64/aapcs64/type-def.h     | 132 ++++++++++++++++++
 .../gcc.target/aarch64/aapcs64/va_arg_dfp-1.c |  60 ++++++++
 .../aarch64/aapcs64/va_arg_dfp-10.c           |  29 ++++
 .../aarch64/aapcs64/va_arg_dfp-11.c           |  32 +++++
 .../aarch64/aapcs64/va_arg_dfp-12.c           |  64 +++++++++
 .../aarch64/aapcs64/va_arg_dfp-13.c           |  59 ++++++++
 .../aarch64/aapcs64/va_arg_dfp-14.c           |  35 +++++
 .../aarch64/aapcs64/va_arg_dfp-16.c           |  28 ++++
 .../gcc.target/aarch64/aapcs64/va_arg_dfp-2.c |  75 ++++++++++
 .../gcc.target/aarch64/aapcs64/va_arg_dfp-3.c |  94 +++++++++++++
 .../gcc.target/aarch64/aapcs64/va_arg_dfp-4.c |  90 ++++++++++++
 .../gcc.target/aarch64/aapcs64/va_arg_dfp-5.c |  47 +++++++
 .../gcc.target/aarch64/aapcs64/va_arg_dfp-6.c |  40 ++++++
 .../gcc.target/aarch64/aapcs64/va_arg_dfp-8.c |  25 ++++
 .../gcc.target/aarch64/aapcs64/va_arg_dfp-9.c |  31 ++++
 49 files changed, 1982 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/dfp-1.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/ice_dfp_5.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_align_dfp-1.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_align_dfp-4.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_1.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_10.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_11.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_12.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_13.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_14.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_15.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_16.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_17.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_18.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_19.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_2.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_20.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_21.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_22.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_23.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_24.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_25.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_26.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_27.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_3.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_5.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_6.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_7.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_8.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_9.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_quad_double_dfp.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-1.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-10.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-11.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-12.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-13.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-14.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-16.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-2.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-3.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-4.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-5.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-6.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-8.c
 create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-9.c

diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/aapcs64.exp b/gcc/testsuite/gcc.target/aarch64/aapcs64/aapcs64.exp
index 3e652c483c7..caa6e5b9b81 100644
--- a/gcc/testsuite/gcc.target/aarch64/aapcs64/aapcs64.exp
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/aapcs64.exp
@@ -88,4 +88,12 @@ foreach src [lsort [glob -nocomplain $srcdir/$subdir/ice_*.c]] {
     }
 }
 
+# Test DFP support
+foreach src [lsort [glob -nocomplain $srcdir/$subdir/dfp*.c]] {
+    if {[runtest_file_p $runtests $src]} {
+	    c-torture [list $src] \
+			    $additional_flags
+    }
+}
+
 torture-finish
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/dfp-1.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/dfp-1.c
new file mode 100644
index 00000000000..95868102495
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/dfp-1.c
@@ -0,0 +1,24 @@
+/* Test loading DFP values from memory.  */
+
+/* { dg-do compile { target aarch64*-*-* } } */
+
+_Decimal32 var32 = 1.2df;
+
+int foo32(_Decimal32 param32)
+{
+	return param32 == var32;
+}
+
+_Decimal64 var64 = 1.2df;
+
+int foo64(_Decimal64 param64)
+{
+	return param64 == var64;
+}
+
+_Decimal128 var128 = 1.2df;
+
+int foo128(_Decimal128 param128)
+{
+	return param128 == var128;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-1.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-1.c
index 29a1ca6d45b..5405e1e4920 100644
--- a/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-1.c
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-1.c
@@ -14,6 +14,8 @@ vf2_t vf2 = (vf2_t){ 17.f, 18.f };
 vi4_t vi4 = (vi4_t){ 0xdeadbabe, 0xbabecafe, 0xcafebeef, 0xbeefdead };
 vlf1_t vlf1 = (vlf1_t) { 17.0 };
 
+vldf1_t vldf1 = (vldf1_t) { 17.0dl };
+
 union int128_t qword;
 
 int *int_ptr = (int *)0xabcdef0123456789ULL;
@@ -45,4 +47,9 @@ FUNC_VAL_CHECK (13,         vi4_t,        vi4, Q0, i32in128)
 FUNC_VAL_CHECK (14,         int *,    int_ptr, X0, flat)
 FUNC_VAL_CHECK (15,         vlf1_t,    vlf1, Q0, flat)
 FUNC_VAL_CHECK (16,         __fp16,    0xabcd, H0, flat)
+
+FUNC_VAL_CHECK (17,     _Decimal32, 65432.12345df, S0, flat)
+FUNC_VAL_CHECK (18,     _Decimal64, 9876543.212345dd, D0, flat)
+FUNC_VAL_CHECK (19,    _Decimal128, 98765432123456789.987654321dl, Q0, flat)
+FUNC_VAL_CHECK (20,        vldf1_t, vldf1, Q0, flat)
 #endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-3.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-3.c
index ff9b7e6d4b8..ad312b675b9 100644
--- a/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-3.c
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/func-ret-3.c
@@ -30,6 +30,23 @@ struct non_hfa_fffd_t non_hfa_fffd = {33.f, 34.f, 35.f, 36.0};
 union hfa_union_t hfa_union;
 union non_hfa_union_t non_hfa_union;
 
+/* Decimal Floating-point.  */
+struct hfa_dfx1_t hfa_dfx1 = {12.345df};
+struct hfa_dfx2_t hfa_dfx2 = {123.456df, 234.456df};
+struct hfa_ddx2_t hfa_ddx2 = {234.567dd, 345.678dd};
+struct hfa_ddx4_t hfa_ddx4 = {1234.123dd, 2345.234dd, 3456.345dd, 4567.456dd};
+struct hfa_dldx3_t hfa_dldx3 = {123456.7890dl, 234567.8901dl, 345678.9012dl};
+struct non_hfa_dfx5_t non_hfa_dfx5 = {456.789df, 567.890df, 678.901df, 789.012df, 890.123df};
+struct hfa_dffs_t hfa_dffs;
+struct non_hfa_dffs_t non_hfa_dffs;
+struct non_hfa_dffs_2_t non_hfa_dffs_2;
+struct hva_vdf2x1_t hva_vdf2x1;
+struct non_hfa_dffd_t non_hfa_dffd = {23.df, 24.df, 25.0dd};
+struct non_hfa_dffvf2_t non_hfa_dffvf2;
+struct non_hfa_dfffd_t non_hfa_dfffd = {33.df, 34.df, 35.df, 36.0dd};
+union hfa_dunion_t hfa_dunion;
+union non_hfa_dunion_t non_hfa_dunion;
+
 #define HAS_DATA_INIT_FUNC
 void init_data ()
 {
@@ -61,6 +78,36 @@ void init_data ()
   non_hfa_ffs_2.s.b = 51;
   non_hfa_ffs_2.c = 52.f;
   non_hfa_ffs_2.d = 53.f;
+
+  /* Decimal floating-point.  */
+  hva_vdf2x1.a = (vdf2_t){17.df, 18.df};
+
+  non_hfa_dffvf2.a = 29.df;
+  non_hfa_dffvf2.b = 30.df;
+  non_hfa_dffvf2.c = (vdf2_t){31.df, 32.df};
+
+  hfa_dunion.s.a = 37.df;
+  hfa_dunion.s.b = 38.df;
+  hfa_dunion.c   = 39.df;
+
+  non_hfa_dunion.a = 40.0dd;
+  non_hfa_dunion.b = 41.df;
+
+  hfa_dffs.a = 42.df;
+  hfa_dffs.b = 43.df;
+  hfa_dffs.c.a = 44.df;
+  hfa_dffs.c.b = 45.df;
+
+  non_hfa_dffs.a = 46.df;
+  non_hfa_dffs.b = 47.df;
+  non_hfa_dffs.c.a = 48.0dd;
+  non_hfa_dffs.c.b = 49.0dd;
+
+  non_hfa_dffs_2.s.a = 50;
+  non_hfa_dffs_2.s.b = 51;
+  non_hfa_dffs_2.c = 52.df;
+  non_hfa_dffs_2.d = 53.df;
+
 }
 
 #include "abitest-2.h"
@@ -90,4 +137,24 @@ FUNC_VAL_CHECK (18, struct non_hfa_ffs_t  , non_hfa_ffs  , X8, flat)
 FUNC_VAL_CHECK (19, struct non_hfa_ffs_2_t, non_hfa_ffs_2, X0, flat)
 FUNC_VAL_CHECK (20, union  non_hfa_union_t, non_hfa_union, X0, flat)
 
+/* Decimal floating-point.  */
+FUNC_VAL_CHECK (21, struct hfa_dfx1_t , hfa_dfx1  , S0, flat)
+FUNC_VAL_CHECK (22, struct hfa_dfx2_t , hfa_dfx2  , S0, flat)
+FUNC_VAL_CHECK (23, struct hfa_ddx2_t , hfa_ddx2  , D0, flat)
+
+FUNC_VAL_CHECK (24, struct hfa_ddx4_t , hfa_ddx4  , D0, flat)
+FUNC_VAL_CHECK (25, struct hfa_dldx3_t, hfa_dldx3 , Q0, flat)
+FUNC_VAL_CHECK (26, struct hfa_dffs_t , hfa_dffs  , S0, flat)
+FUNC_VAL_CHECK (27, union hfa_dunion_t, hfa_dunion, S0, flat)
+
+FUNC_VAL_CHECK (28, struct hva_vdf2x1_t, hva_vdf2x1, D0, flat)
+
+FUNC_VAL_CHECK (29, struct non_hfa_dfx5_t  , non_hfa_dfx5  , X8, flat)
+FUNC_VAL_CHECK (30, struct non_hfa_dffd_t  , non_hfa_dffd  , X0, flat)
+FUNC_VAL_CHECK (31, struct non_hfa_dffvf2_t, non_hfa_dffvf2, X0, flat)
+FUNC_VAL_CHECK (32, struct non_hfa_dfffd_t , non_hfa_dfffd , X8, flat)
+FUNC_VAL_CHECK (33, struct non_hfa_dffs_t  , non_hfa_dffs  , X8, flat)
+FUNC_VAL_CHECK (34, struct non_hfa_dffs_2_t, non_hfa_dffs_2, X0, flat)
+FUNC_VAL_CHECK (35, union  non_hfa_dunion_t, non_hfa_dunion, X0, flat)
+
 #endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/ice_dfp_5.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/ice_dfp_5.c
new file mode 100644
index 00000000000..4d0fdd9bc39
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/ice_dfp_5.c
@@ -0,0 +1,20 @@
+/* { dg-do compile { target aarch64*-*-* } } */
+
+struct S
+{
+  union
+    {
+      _Decimal128 b;
+    } a;
+};
+
+struct S s;
+
+extern struct S a[5];
+extern struct S check (struct S, struct S *, struct S);
+extern void checkx (struct S);
+
+void test (void)
+{
+  checkx (check (s, &a[1], a[2]));
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/test_align_dfp-1.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_align_dfp-1.c
new file mode 100644
index 00000000000..35913e9f2d1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_align_dfp-1.c
@@ -0,0 +1,126 @@
+/* Test AAPCS64 layout.
+
+   Test the comformance to the alignment and padding requirements.
+
+   B.4  If the argument type is a Composite Type then the size of the
+        argument is rounded up to the nearest multiple of 8 bytes.
+   C.4  If the argument is an HFA, a Quad-precision Floating-point or Short
+	Vector Type then the NSAA is rounded up to the larger of 8 or the
+	Natural Alignment of the argument's type.
+   C.12 The NSAA is rounded up to the larger of 8 or the Natural Alignment
+	of the argument's type.
+   C.14 If the size of the argument is less than 8 bytes then the size of
+	the argument is set ot 8 bytes.  The effect is as if the argument
+	was copied to the least significant bits of a 64-bit register and
+	the remaining bits filled with unspecified values.  */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define TESTFILE "test_align-1.c"
+#include "type-def.h"
+
+struct y
+{
+  int p;
+  int q;
+  int r;
+  int s;
+};
+
+struct y v1 = { 1, 2, 3, 4 };
+struct y v2 = { 5, 6, 7, 8 };
+struct y v3 = { 9, 10, 11, 12 };
+struct y v4 = { 13, 14, 15, 16 };
+
+struct z
+{
+  _Decimal64 x[4];
+};
+
+struct z a = { 5.0dd, 6.0dd, 7.0dd, 8.0dd };
+struct z b = { 9.0dd, 10.0dd, 11.0dd, 12.0dd };
+
+vf4_t c = { 13.f, 14.f, 15.f, 16.f };
+
+struct x
+{
+  vf4_t v;
+} w;
+
+char ch='a';
+short sh=13;
+int i=14;
+long long ll=15;
+
+struct s1
+{
+  short sh[3];
+} s1;
+
+struct s2
+{
+  int i[2];
+  char c;
+} s2;
+
+struct ldx2_t
+{
+  _Decimal128 ld[2];
+} ldx2 = { 12345.67890dl, 23456.78901dl };
+
+union u_t
+{
+  _Decimal128 ld;
+  _Decimal64 d[2];
+} u;
+
+#define HAS_DATA_INIT_FUNC
+void init_data ()
+{
+  w.v = (vf4_t){ 17.f, 18.f, 19.f, 20.f };
+  s1.sh[0] = 16;
+  s1.sh[1] = 17;
+  s1.sh[2] = 18;
+  s2.i[0] = 19;
+  s2.i[1] = 20;
+  s2.c = 21;
+  u.ld = 34567.89012L;
+}
+
+#include "abitest.h"
+#else
+
+  ARG(struct y, v1, X0)
+  ARG(struct y, v2, X2)
+  ARG(struct y, v3, X4)
+  ARG(struct y, v4, X6)
+  ARG(struct z, a, D0)
+  ARG(struct z, b, D4)
+  ARG(_Decimal64, 12.5, STACK)
+  ARG(vf4_t, c, STACK+16)       /* [C.4] 16-byte aligned short vector */
+  ARG(_Decimal64, 17.0dd, STACK+32)
+  ARG(struct x, w, STACK+48)    /* [C.12] 16-byte aligned small struct */
+#ifndef __AAPCS64_BIG_ENDIAN__
+  ARG(char, ch, STACK+64)       /* [C.14] char  padded to the size of 8 bytes */
+  ARG(short, sh, STACK+72)      /* [C.14] short padded to the size of 8 bytes */
+  ARG(int, i, STACK+80)         /* [C.14] int   padded to the size of 8 bytes */
+#else
+  ARG(char, ch, STACK+71)
+  ARG(short, sh, STACK+78)
+  ARG(int, i, STACK+84)
+#endif
+  ARG(long long, ll, STACK+88)
+  ARG(struct s1, s1, STACK+96)  /* [B.4] small struct padded to the size of 8 bytes */
+  ARG(_Decimal64, 18.0dd, STACK+104)
+  ARG(struct s2, s2, STACK+112) /* [B.4] small struct padded to the size of 16 bytes */
+  ARG(_Decimal64, 19.0dd, STACK+128)
+  ARG(_Decimal128, 30.0dl, STACK+144)  /* [C.4] 16-byte aligned quad-precision */
+  ARG(_Decimal64, 31.0dd, STACK+160)
+  ARG(struct ldx2_t, ldx2, STACK+176) /* [C.4] 16-byte aligned HFA */
+  ARG(_Decimal64, 32.0dd, STACK+208)
+  ARG(__int128, 33, STACK+224)  /* [C.12] 16-byte aligned 128-bit integer */
+  ARG(_Decimal64, 34.0dd, STACK+240)
+  ARG(union u_t, u, STACK+256)  /* [C.12] 16-byte aligned small composite (union in this case) */
+  LAST_ARG_NONFLAT (int, 35.0, STACK+272, i32in64)
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/test_align_dfp-4.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_align_dfp-4.c
new file mode 100644
index 00000000000..50ee7c0cc9d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_align_dfp-4.c
@@ -0,0 +1,42 @@
+/* Test AAPCS64 layout.
+
+   C.3 If the argument is an HFA then the NSRN is set to 8 and the size
+   of the argument is rounded up to the nearest multiple of 8 bytes.
+
+   TODO: add the check of an HFA containing half-precision floating-point
+   when __f16 is supported in A64 GCC.  */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define TESTFILE "test_align_dfp-4.c"
+
+struct z1
+{
+  _Decimal64 x[4];
+};
+
+struct z1 a = { 5.0dd, 6.0dd, 7.0dd, 8.0dd };
+
+struct z2
+{
+  _Decimal32 x[3];
+};
+
+struct z2 b = { 13.df, 14.df, 15.df };
+struct z2 c = { 16.df, 17.df, 18.df };
+
+#include "abitest.h"
+#else
+
+  ARG(struct z1, a, D0)
+  ARG(_Decimal64, 9.0dd, D4)
+  ARG(_Decimal64, 10.0dd, D5)
+  ARG(struct z2, b, STACK)       /* [C.3] on stack and size padded to 16 bytes */
+#ifndef __AAPCS64_BIG_ENDIAN__
+  ARG(_Decimal32, 15.5df, STACK+16)    /* [C.3] NSRN has been set to 8 */
+#else
+  ARG(_Decimal32, 15.5df, STACK+20)
+#endif
+  LAST_ARG(struct z2, c, STACK+24)
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_1.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_1.c
new file mode 100644
index 00000000000..3435261b07d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_1.c
@@ -0,0 +1,31 @@
+/* Test AAPCS64 layout */
+
+/* C.7  If the argument is an Integral Type, the size of the argument is
+	less than or equal to 8 bytes and the NGRN is less than 8, the
+	argument is copied to the least significant bits in x[NGRN].  The
+	NGRN is incremented by one.  The argument has now been allocated.  */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define TESTFILE "test_dfp_1.c"
+/* TODO: review if we need this */
+#define RUNTIME_ENDIANNESS_CHECK
+#include "abitest.h"
+#else
+  ARG(int, 4, W0)
+  ARG(_Decimal64, 4.0dd, D0)
+  ARG(int, 3, W1)
+  /* TODO: review the way of memcpy char, short, etc.  */
+#ifndef __AAPCS64_BIG_ENDIAN__
+  ARG(char, 0xEF, X2)
+  ARG(short, 0xBEEF, X3)
+  ARG(int, 0xDEADBEEF, X4)
+#else
+  /* TODO: need the model/qemu to be big-endian as well  */
+  ARG(char, 0xEF, X2+7)
+  ARG(short, 0xBEEF, X3+6)
+  ARG(int, 0xDEADBEEF, X4+4)
+#endif
+  LAST_ARG(long long, 0xDEADBEEFCAFEBABELL, X5)
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_10.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_10.c
new file mode 100644
index 00000000000..8c1ccd1e7ff
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_10.c
@@ -0,0 +1,26 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define TESTFILE "test_dfp_10.c"
+
+struct z
+{
+  _Decimal64 x[4];
+};
+
+struct z a = { 5.0dd, 6.0dd, 7.0dd, 8.0dd };
+struct z b = { 9.0dd, 10.0dd, 11.0dd, 12.0dd };
+
+#include "abitest.h"
+#else
+
+  ARG(int, 7, W0)
+  DOTS
+  ANON(struct z, a, D0)
+  ANON(struct z, b, D4)
+  ANON(_Decimal64, 0.5dd, STACK)
+  LAST_ANON(_Decimal64, 1.5dd, STACK+8)
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_11.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_11.c
new file mode 100644
index 00000000000..d06de66cc17
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_11.c
@@ -0,0 +1,34 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define TESTFILE "test_dfp_11.c"
+
+__complex__ x = 1.0+2.0i;
+
+struct y
+{
+  int p;
+  int q;
+  int r;
+  int s;
+} v = { 1, 2, 3, 4 };
+
+struct z
+{
+  _Decimal64 x[4];
+};
+
+struct z a = { 5.0dd, 6.0dd, 7.0dd, 8.0dd };
+struct z b = { 9.0dd, 10.0dd, 11.0dd, 12.0dd };
+
+#include "abitest.h"
+#else
+  ARG(_Decimal64, 11.0dd, D0)
+  DOTS
+  ANON(struct z, a, D1)
+  ANON(struct z, b, STACK)
+  LAST_ANON(_Decimal64, 0.5dd, STACK+32)
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_12.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_12.c
new file mode 100644
index 00000000000..491bfd9964e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_12.c
@@ -0,0 +1,44 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define TESTFILE "test_dfp_12.c"
+
+
+struct y
+{
+  long p;
+  long q;
+  long r;
+  long s;
+} v = { 1, 2, 3, 4 };
+
+struct y1
+{
+  int p;
+  int q;
+  int r;
+  int s;
+} v1 = { 1, 2, 3, 4 };
+
+
+struct z
+{
+  _Decimal64 x[4];
+};
+
+struct z a = { 5.0dd, 6.0dd, 7.0dd, 8.0dd };
+struct z b = { 9.0dd, 10.0dd, 11.0dd, 12.0dd };
+
+#define MYFUNCTYPE struct y
+
+#include "abitest.h"
+#else
+  ARG(int, 7, W0)
+  ARG(struct y1, v1, X1)
+  ARG(struct z, a, D0)
+  ARG(struct z, b, D4)
+  LAST_ARG(_Decimal64, 0.5dd, STACK)
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_13.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_13.c
new file mode 100644
index 00000000000..6012185285b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_13.c
@@ -0,0 +1,34 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+
+#define TESTFILE "test_dfp_13.c"
+
+
+struct y
+{
+  int p;
+  int q;
+  int r;
+  int s;
+} v = { 1, 2, 3, 4 };
+
+struct z
+{
+  _Decimal64 x[4];
+};
+
+struct z a = { 5.0dd, 6.0dd, 7.0dd, 8.0dd };
+struct z b = { 9.0dd, 10.0dd, 11.0dd, 12.0dd };
+
+#include "abitest.h"
+#else
+  ARG(int, 7, W0)
+  ARG(struct y, v, X1)
+  ARG(struct z, a, D0)
+  ARG(_Decimal64, 1.0dd, D4)
+  ARG(struct z, b, STACK)
+  LAST_ARG(_Decimal64, 0.5dd, STACK+32)
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_14.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_14.c
new file mode 100644
index 00000000000..9d1cf2d94d1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_14.c
@@ -0,0 +1,35 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define TESTFILE "test_dfp_14.c"
+
+
+struct y
+{
+  int p;
+  int q;
+  int r;
+  int s;
+} v = { 1, 2, 3, 4 };
+
+struct z
+{
+  _Decimal64 x[4];
+};
+
+struct z a = { 5.0dd, 6.0dd, 7.0dd, 8.0dd };
+struct z b = { 9.0dd, 10.0dd, 11.0dd, 12.0dd };
+
+#include "abitest.h"
+#else
+  ARG(int, 7, W0)
+  ARG(int, 9, W1)
+  ARG(struct z, a, D0)
+  ARG(_Decimal64, 1.0dd, D4)
+  ARG(struct z, b, STACK)
+  ARG(int, 4, W2)
+  LAST_ARG(_Decimal64, 0.5dd, STACK+32)
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_15.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_15.c
new file mode 100644
index 00000000000..8ec7b4662a4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_15.c
@@ -0,0 +1,21 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define TESTFILE "test_dfp_15.c"
+
+#include "abitest.h"
+#else
+  ARG(_Decimal64, 1.0dd, D0)
+  ARG(_Decimal64, 2.0dd, D1)
+  ARG(_Decimal64, 3.0dd, D2)
+  ARG(_Decimal64, 4.0dd, D3)
+  ARG(_Decimal64, 5.0dd, D4)
+  ARG(_Decimal64, 6.0dd, D5)
+  ARG(_Decimal64, 7.0dd, D6)
+  ARG(_Decimal64, 8.0dd, D7)
+  ARG(_Decimal64, 9.0dd, STACK)
+  LAST_ARG(_Decimal64, 10.0dd, STACK+8)
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_16.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_16.c
new file mode 100644
index 00000000000..cdbfd96c475
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_16.c
@@ -0,0 +1,32 @@
+/* Test AAPCS layout */
+/* C.5 If the argument is a Half- or Single- precision Floating-point type,
+   then the size of the argument is set to 8 bytes.  The effect is as if
+   the argument had been copied to the least significant bits of a 64-bit
+   register and the remaining bits filled with unspecified values.  */
+/* TODO: add the check of half-precision floating-point when it is supported
+   by the A64 GCC.  */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define TESTFILE "test_dfp_16.c"
+
+#include "abitest.h"
+#else
+  ARG(_Decimal32, 1.0df, S0)
+  ARG(_Decimal32, 2.0df, S1)
+  ARG(_Decimal32, 3.0df, S2)
+  ARG(_Decimal32, 4.0df, S3)
+  ARG(_Decimal32, 5.0df, S4)
+  ARG(_Decimal32, 6.0df, S5)
+  ARG(_Decimal32, 7.0df, S6)
+  ARG(_Decimal32, 8.0df, S7)
+#ifndef __AAPCS64_BIG_ENDIAN__
+  ARG(_Decimal32, 9.0df, STACK)
+  LAST_ARG(_Decimal32, 10.0df, STACK+8)
+#else
+  ARG(_Decimal32, 9.0df, STACK+4)
+  LAST_ARG(_Decimal32, 10.0df, STACK+12)
+#endif
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_17.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_17.c
new file mode 100644
index 00000000000..22dc462bf7c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_17.c
@@ -0,0 +1,37 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define TESTFILE "test_dfp_17.c"
+
+__complex__ x = 1.0+2.0i;
+
+struct y
+{
+  int p;
+  int q;
+  int r;
+  int s;
+} v = { 1, 2, 3, 4 };
+
+struct z
+{
+  _Decimal64 x[4];
+};
+
+_Decimal32 f1 = 25.0df;
+struct z a = { 5.0dd, 6.0dd, 7.0dd, 8.0dd };
+struct z b = { 9.0dd, 10.0dd, 11.0dd, 12.0dd };
+
+#include "abitest.h"
+#else
+  ARG(_Decimal64, 11.0dd, D0)
+  DOTS
+  ANON(struct z, a, D1)
+  ANON(struct z, b, STACK)
+  ANON(int , 5, W0)
+  ANON(_Decimal32, f1, STACK+32) /* Note: no promotion to _Decimal64.  */
+  LAST_ANON(_Decimal64, 0.5dd, STACK+40)
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_18.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_18.c
new file mode 100644
index 00000000000..bb90b0c906f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_18.c
@@ -0,0 +1,34 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+
+#define TESTFILE "test_dfp_18.c"
+
+
+struct y
+{
+  long long p;
+  long long q;
+  long long r;
+  long long s;
+} v = { 1, 2, 3, 4 };
+
+struct z
+{
+  _Decimal64 x[4];
+};
+
+struct z a = { 5.0dd, 6.0dd, 7.0dd, 8.0dd };
+struct z b = { 9.0dd, 10.0dd, 11.0dd, 12.0dd };
+
+#include "abitest.h"
+#else
+  ARG(int, 7, W0)
+  PTR(struct y, v, X1)
+  ARG(struct z, a, D0)
+  ARG(_Decimal64, 1.0dd, D4)
+  ARG(struct z, b, STACK)
+  LAST_ARG(_Decimal64, 0.5dd, STACK+32)
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_19.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_19.c
new file mode 100644
index 00000000000..e8210ec3c93
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_19.c
@@ -0,0 +1,35 @@
+/* Test AAPCS64 layout.  */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define TESTFILE "test_dfp_19.c"
+
+struct y
+{
+  int p1;
+  int p2;
+  _Decimal32 q;
+  int r1;
+  int r2;
+  char x;
+} v = { -1, 1, 2.0df, 3, 18, 19, 20};
+
+struct z
+{
+  _Decimal64 x[4];
+};
+
+struct z a = { 5.0dd, 6.0dd, 7.0dd, 8.0dd };
+struct z b = { 9.0dd, 10.0dd, 11.0dd, 12.0dd };
+
+#include "abitest.h"
+#else
+  ARG(int, 7, W0)
+  DOTS
+  ANON(_Decimal64, 4.0dd, D0)
+  ANON(struct z, a, D1)
+  ANON(struct z, b, STACK)
+  PTR_ANON(struct y, v, X1)
+  LAST_ANON(int, 10, W2)
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_2.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_2.c
new file mode 100644
index 00000000000..5e9716cdb0f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_2.c
@@ -0,0 +1,17 @@
+/* Test AAPCS64 layout */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define TESTFILE "test_dfp_2.c"
+#include "abitest.h"
+
+#else
+  ARG(_Decimal32, 1.0df, S0)
+  ARG(_Decimal64, 4.0dd, D1)
+  ARG(_Decimal32, 2.0df, S2)
+  ARG(_Decimal64, 5.0dd, D3)
+  ARG(__fp16, 8.0f, H4)
+  LAST_ARG(int, 3, W0)
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_20.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_20.c
new file mode 100644
index 00000000000..4c524b18dbe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_20.c
@@ -0,0 +1,22 @@
+/* Test AAPCS64 layout */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define TESTFILE "test_dfp_20.c"
+
+#include "abitest.h"
+
+#else
+  ARG(int, 8, W0)
+  ARG(_Decimal64, 1.0dd, D0)
+  ARG(_Decimal64, 2.0dd, D1)
+  ARG(_Decimal64, 3.0dd, D2)
+  ARG(_Decimal64, 4.0dd, D3)
+  ARG(_Decimal64, 5.0dd, D4)
+  ARG(_Decimal64, 6.0dd, D5)
+  ARG(_Decimal64, 7.0dd, D6)
+  DOTS
+  ANON(_Complex double, 1234.0 + 567.0i, STACK)
+  LAST_ANON(_Decimal64, -987.0dd, STACK+16)
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_21.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_21.c
new file mode 100644
index 00000000000..37c4177d9b8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_21.c
@@ -0,0 +1,21 @@
+/* Test AAPCS64 layout */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define TESTFILE "test_dfp_21.c"
+
+#include "abitest.h"
+
+#else
+  ARG(int, 8, W0)
+  ARG(_Decimal64, 1.0dd, D0)
+  ARG(_Decimal64, 2.0dd, D1)
+  ARG(_Decimal64, 3.0dd, D2)
+  ARG(_Decimal64, 4.0dd, D3)
+  ARG(_Decimal64, 5.0dd, D4)
+  ARG(_Decimal64, 6.0dd, D5)
+  ARG(_Decimal64, 7.0dd, D6)
+  ARG(_Complex double, 1234.0 + 567.0i, STACK)
+  LAST_ARG(_Decimal64, -987.0dd, STACK+16)
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_22.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_22.c
new file mode 100644
index 00000000000..497566836a8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_22.c
@@ -0,0 +1,19 @@
+/* Test AAPCS64 layout */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define TESTFILE "test_dfp_22.c"
+
+struct y
+{
+  _Decimal32 p;
+  _Decimal32 q;
+} v = { 345.0df, 678.0df };
+
+#include "abitest.h"
+#else
+  ARG(_Decimal32, 123.0df, S0)
+  ARG(struct y, v, S1)
+  LAST_ARG(_Decimal32, 901.0df, S3)
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_23.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_23.c
new file mode 100644
index 00000000000..82e72192c3d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_23.c
@@ -0,0 +1,42 @@
+/* Test AAPCS64 layout.
+
+   Larger than machine-supported vector size.  The behavior is unspecified by
+   the AAPCS64 document; the implementation opts for pass by reference.  */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define TESTFILE "test_dfp_23.c"
+
+typedef char A __attribute__ ((vector_size (64)));
+
+struct y
+{
+  _Decimal64 df[8];
+};
+
+union u
+{
+  struct y x;
+  A a;
+} u;
+
+#define HAS_DATA_INIT_FUNC
+void init_data ()
+{
+  u.x.df[0] = 1.0dd;
+  u.x.df[1] = 2.0dd;
+  u.x.df[2] = 3.0dd;
+  u.x.df[3] = 4.0dd;
+  u.x.df[4] = 5.0dd;
+  u.x.df[5] = 6.0dd;
+  u.x.df[6] = 7.0dd;
+  u.x.df[7] = 8.0dd;
+}
+
+#include "abitest.h"
+#else
+ARG (_Decimal32, 123.0df, S0)
+PTR (A, u.a, X0)
+LAST_ARG_NONFLAT (int, 0xdeadbeef, X1, i32in64)
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_24.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_24.c
new file mode 100644
index 00000000000..0b76c9de8c6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_24.c
@@ -0,0 +1,22 @@
+/* Test AAPCS64 layout.  */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define TESTFILE "test_dfp_24.c"
+
+typedef _Decimal128 TDtype;
+
+#include "abitest.h"
+#else
+  ARG(TDtype, 1.0dl, Q0)
+  ARG(TDtype, 2.0dl, Q1)
+  ARG(TDtype, 3.0dl, Q2)
+  ARG(TDtype, 4.0dl, Q3)
+  ARG(TDtype, 5.0dl, Q4)
+  ARG(TDtype, 6.0dl, Q5)
+  ARG(TDtype, 7.0dl, Q6)
+  ARG(TDtype, 8.0dl, Q7)
+  ARG(_Decimal64, 9.0dd, STACK)
+  LAST_ARG(TDtype, 10.0dl, STACK+16)
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_25.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_25.c
new file mode 100644
index 00000000000..04372adc1e4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_25.c
@@ -0,0 +1,61 @@
+/* Test AAPCS64 layout
+
+   Test homogeneous floating-point aggregates and homogeneous short-vector
+   aggregates, which should be passed in SIMD/FP registers or via the
+   stack.  */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define TESTFILE "test_dfp_25.c"
+
+typedef _Decimal32 vf2_t __attribute__((vector_size (8)));
+struct x0
+{
+  vf2_t v;
+} s0;
+struct x3
+{
+  vf2_t v[2];
+} s3;
+struct x4
+{
+  vf2_t v[3];
+} s4;
+
+typedef _Decimal32 vf4_t __attribute__((vector_size(16)));
+struct x1
+{
+  vf4_t v;
+} s1;
+
+struct x2
+{
+  _Decimal64 df[3];
+} s2;
+
+#define HAS_DATA_INIT_FUNC
+void init_data ()
+{
+  s0.v = (vf2_t){ 17.df, 18.df };
+  s1.v = (vf4_t){ 567.890df, 678.901df, 789.012df, 890.123df };
+  s2.df[0] = 123.456dd;
+  s2.df[1] = 234.567dd;
+  s2.df[2] = 345.678dd;
+  s3.v[0] = (vf2_t){ 19.df, 20.df };
+  s3.v[1] = (vf2_t){ 23.df, 24.df };
+  s4.v[0] = (vf2_t){ 27.df, 28.df };
+  s4.v[1] = (vf2_t){ 31.df, 32.df };
+  s4.v[2] = (vf2_t){ 35.df, 36.df };
+}
+
+#include "abitest.h"
+#else
+ARG (struct x0, s0, D0)
+ARG (struct x2, s2, D1)
+ARG (struct x1, s1, Q4)
+ARG (struct x3, s3, D5)
+ARG (struct x4, s4, STACK)
+ARG (int, 0xdeadbeef, W0)
+LAST_ARG (_Decimal64, 456.789dd, STACK+24)
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_26.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_26.c
new file mode 100644
index 00000000000..e95175bfe78
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_26.c
@@ -0,0 +1,54 @@
+/* Test AAPCS64 layout.
+
+   Test some small structures that should be passed in GPRs.  */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define TESTFILE "test_dfp_26.c"
+
+struct y0
+{
+  char ch;
+} c0 = { 'A' };
+
+struct y2
+{
+  long long ll[2];
+} c2 = { 0xDEADBEEF, 0xCAFEBABE };
+
+struct y3
+{
+  int i[3];
+} c3 = { 56789, 67890, 78901 };
+
+typedef _Decimal32 vf2_t __attribute__((vector_size (8)));
+struct x0
+{
+  vf2_t v;
+} s0;
+
+typedef short vh4_t __attribute__((vector_size (8)));
+
+struct x1
+{
+  vh4_t v[2];
+} s1;
+
+#define HAS_DATA_INIT_FUNC
+void init_data ()
+{
+  s0.v = (vf2_t){ 17.df, 18.df };
+  s1.v[0] = (vh4_t){ 345, 456, 567, 678 };
+  s1.v[1] = (vh4_t){ 789, 890, 901, 123 };
+}
+
+#include "abitest.h"
+#else
+ARG (struct y0, c0, X0)
+ARG (struct y2, c2, X1)
+ARG (struct y3, c3, X3)
+ARG_NONFLAT (struct x0, s0, D0, f32in64)
+ARG (struct x1, s1, D1)
+LAST_ARG_NONFLAT (int, 89012, X5, i32in64)
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_27.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_27.c
new file mode 100644
index 00000000000..12dfe7ed12c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_27.c
@@ -0,0 +1,46 @@
+/* Test AAPCS64 layout
+
+   Test named homogeneous floating-point aggregates of __fp16 data,
+   which should be passed in SIMD/FP registers or via the stack.  */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define TESTFILE "test_dfp_27.c"
+
+struct x0
+{
+  __fp16 v[1];
+} f16x1;
+
+struct x1
+{
+  __fp16 v[2];
+} f16x2;
+
+struct x2
+{
+  __fp16 v[3];
+} f16x3;
+
+#define HAS_DATA_INIT_FUNC
+void init_data ()
+{
+  f16x1.v[0] = 2.0f;
+  f16x2.v[0] = 4.0f;
+  f16x2.v[1] = 8.0f;
+  f16x3.v[0] = 16.0f;
+  f16x3.v[1] = 32.0f;
+  f16x3.v[2] = 64.0f;
+}
+
+#include "abitest.h"
+#else
+ARG (struct x0, f16x1, H0)
+ARG (struct x1, f16x2, H1)
+ARG (struct x2, f16x3, H3)
+ARG (struct x1, f16x2, H6)
+ARG (struct x0, f16x1, STACK)
+ARG (int, 0xdeadbeef, W0)
+LAST_ARG (_Decimal64, 456.789dd, STACK+8)
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_3.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_3.c
new file mode 100644
index 00000000000..c92cb143cda
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_3.c
@@ -0,0 +1,18 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define TESTFILE "test_dfp_3.c"
+
+__complex__ x = 1.0+2.0i;
+
+#include "abitest.h"
+#else
+ARG (_Decimal32, 1.0df, S0)
+ARG (__complex__ double, x, D1)
+ARG (_Decimal32, 2.0df, S3)
+ARG (_Decimal64, 5.0dd, D4)
+LAST_ARG_NONFLAT (int, 3, X0, i32in64)
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_5.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_5.c
new file mode 100644
index 00000000000..90b30310b74
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_5.c
@@ -0,0 +1,24 @@
+/* Test AAPCS64 layout */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define TESTFILE "test_dfp_5.c"
+
+__complex__ float x = 1.0+2.0i;
+
+struct y
+{
+  long p;
+  long q;
+} v = { 1, 2};
+
+#include "abitest.h"
+#else
+  ARG(_Decimal32, 1.0df, S0)
+  ARG(__complex__ float, x, S1)
+  ARG(_Decimal32, 2.0df, S3)
+  ARG(_Decimal64, 5.0dd, D4)
+  LAST_ARG(struct y, v, X0)
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_6.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_6.c
new file mode 100644
index 00000000000..7c720c6ee69
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_6.c
@@ -0,0 +1,26 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define TESTFILE "test_dfp_6.c"
+
+__complex__ double x = 1.0+2.0i;
+
+struct y
+{
+  int p;
+  int q;
+  int r;
+  int s;
+} v = { 1, 2, 3, 4 };
+
+#include "abitest.h"
+#else
+  ARG(struct y, v, X0)
+  ARG(_Decimal32, 1.0df, S0)
+  ARG(__complex__ double, x, D1)
+  ARG(_Decimal32, 2.0df, S3)
+  ARG(_Decimal64, 5.0dd, D4)
+  LAST_ARG(int, 3, W2)
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_7.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_7.c
new file mode 100644
index 00000000000..c53e192e704
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_7.c
@@ -0,0 +1,30 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define TESTFILE "test_dfp_7.c"
+
+__complex__ float x = 1.0f + 2.0i;
+
+struct y
+{
+  int p;
+  int q;
+  int r;
+  int s;
+} v = { 1, 2, 3, 4 }, v1 = {5, 6, 7, 8}, v2 = {9, 10, 11, 12};
+
+#include "abitest.h"
+#else
+ARG (struct y, v, X0)
+ARG (struct y, v1, X2)
+ARG (struct y, v2, X4)
+ARG (int, 4, W6)
+ARG (_Decimal32, 1.0df, S0)
+ARG (__complex__ float, x, S1)
+ARG (_Decimal32, 2.0df, S3)
+ARG (_Decimal64, 5.0dd, D4)
+ARG (int, 3, W7)
+LAST_ARG_NONFLAT (int, 5, STACK, i32in64)
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_8.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_8.c
new file mode 100644
index 00000000000..2f48918f8c9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_8.c
@@ -0,0 +1,24 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define TESTFILE "test_dfp_8.c"
+
+struct z
+{
+  _Decimal64 x[4];
+};
+
+struct z a = { 5.0dd, 6.0dd, 7.0dd, 8.0dd };
+struct z b = { 9.0dd, 10.0dd, 11.0dd, 12.0dd };
+
+#include "abitest.h"
+#else
+  ARG(struct z, a, D0)
+  ARG(struct z, b, D4)
+  ARG(_Decimal64, 0.5dd, STACK)
+  ARG(int, 7, W0)
+  LAST_ARG(int, 8, W1) 
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_9.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_9.c
new file mode 100644
index 00000000000..cf080272096
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_9.c
@@ -0,0 +1,32 @@
+/* Test AAPCS layout (VFP variant) */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define VFP
+#define TESTFILE "test_dfp_9.c"
+
+struct y
+{
+  int p;
+  int q;
+  int r;
+  int s;
+} v = { 1, 2, 3, 4 };
+
+struct z
+{
+  _Decimal64 x[4];
+};
+
+struct z a = { 5.0dd, 6.0dd, 7.0dd, 8.0dd };
+struct z b = { 9.0dd, 10.0dd, 11.0dd, 12.0dd };
+
+#include "abitest.h"
+#else
+  ARG(int, 7, W0)
+  ARG(struct y, v, X1)
+  ARG(struct z, a, D0)
+  ARG(struct z, b, D4)
+  LAST_ARG(_Decimal64, 0.5dd, STACK)
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/test_quad_double_dfp.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_quad_double_dfp.c
new file mode 100644
index 00000000000..08d540dccf1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/test_quad_double_dfp.c
@@ -0,0 +1,26 @@
+/* Test AAPCS64 layout.
+
+   Test parameter passing of floating-point quad precision types.  */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define TESTFILE "test_quad_double_dfp.c"
+
+typedef _Decimal128 TDtype;
+typedef _Complex long double CTFtype;
+
+TDtype x = 1.0dl;
+TDtype y = 2.0dl;
+
+CTFtype cx = 3.0 + 4.0i;
+CTFtype cy = 5.0 + 6.0i;
+
+#include "abitest.h"
+#else
+  ARG       ( TDtype,  x, Q0)
+  ARG       (CTFtype, cx, Q1)
+  DOTS
+  ANON      (CTFtype, cy, Q3)
+  LAST_ANON ( TDtype,  y, Q5)
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/type-def.h b/gcc/testsuite/gcc.target/aarch64/aapcs64/type-def.h
index ca1fa5811ff..6452b917788 100644
--- a/gcc/testsuite/gcc.target/aarch64/aapcs64/type-def.h
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/type-def.h
@@ -13,6 +13,15 @@ typedef int vi4_t __attribute__((vector_size (16)));
 /* 128-bit vector of 1 quad precision float.  */
 typedef long double vlf1_t __attribute__((vector_size (16)));
 
+/* 64-bit vector of 2 decimal floats.  */
+typedef _Decimal32 vdf2_t __attribute__((vector_size (8)));
+
+/* 128-bit vector of 4 decimal floats.  */
+typedef _Decimal32 vdf4_t __attribute__((vector_size (16)));
+
+/* 128-bit vector of 1 quad precision decimal float.  */
+typedef _Decimal128 vldf1_t __attribute__((vector_size (16)));
+
 /* signed quad-word (in an union for the convenience of initialization).  */
 union int128_t
 {
@@ -183,3 +192,126 @@ union non_hfa_union_t
   double a;
   float b;
 };
+
+/* Same, with decimal floating-point types.  */
+struct hfa_dfx1_t
+{
+  _Decimal32 a;
+};
+
+struct hfa_dfx2_t
+{
+  _Decimal32 a;
+  _Decimal32 b;
+};
+
+struct hfa_dfx3_t
+{
+  _Decimal32 a;
+  _Decimal32 b;
+  _Decimal32 c;
+};
+
+struct hfa_ddx2_t
+{
+  _Decimal64 a;
+  _Decimal64 b;
+};
+
+struct hfa_ddx4_t
+{
+  _Decimal64 a;
+  _Decimal64 b;
+  _Decimal64 c;
+  _Decimal64 d;
+};
+
+struct hfa_dldx3_t
+{
+  _Decimal128 a;
+  _Decimal128 b;
+  _Decimal128 c;
+};
+
+struct hfa_dffs_t
+{
+  _Decimal32 a;
+  _Decimal32 b;
+  struct hfa_dfx2_t c;
+};
+
+union hfa_dunion_t
+{
+  struct
+    {
+      _Decimal32 a;
+      _Decimal32 b;
+    } s;
+  _Decimal32 c;
+};
+
+struct non_hfa_dfx5_t
+{
+  _Decimal32 a;
+  _Decimal32 b;
+  _Decimal32 c;
+  _Decimal32 d;
+  _Decimal32 e;
+};
+
+struct non_hfa_dffs_t
+{
+  _Decimal32 a;
+  _Decimal32 b;
+  struct hfa_ddx2_t c;
+};
+
+struct non_hfa_dffs_2_t
+{
+  struct
+    {
+      int a;
+      int b;
+    } s;
+  _Decimal32 c;
+  _Decimal32 d;
+};
+
+struct hva_vdf2x1_t
+{
+  vdf2_t a;
+};
+
+struct hva_vdf2x2_t
+{
+  vdf2_t a;
+  vdf2_t b;
+};
+
+struct non_hfa_dffd_t
+{
+  _Decimal32 a;
+  _Decimal32 b;
+  _Decimal64 c;
+};
+
+struct non_hfa_dffvf2_t
+{
+  _Decimal32 a;
+  _Decimal32 b;
+  vdf2_t c;
+};
+
+struct non_hfa_dfffd_t
+{
+  _Decimal32 a;
+  _Decimal32 b;
+  _Decimal32 c;
+  _Decimal64 d;
+};
+
+union non_hfa_dunion_t
+{
+  _Decimal64 a;
+  _Decimal32 b;
+};
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-1.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-1.c
new file mode 100644
index 00000000000..81e78c1268e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-1.c
@@ -0,0 +1,60 @@
+/* Test AAPCS64 layout and __builtin_va_arg.
+
+   This test covers fundamental data types as specified in AAPCS64 \S 4.1.
+   It is focused on unnamed parameter passed in registers.  */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define AAPCS64_TEST_STDARG
+#define TESTFILE "va_arg_dfp-1.c"
+#include "type-def.h"
+
+vf2_t vf2 = (vf2_t){ 17.f, 18.f };
+vi4_t vi4 = (vi4_t){ 0xdeadbabe, 0xbabecafe, 0xcafebeef, 0xbeefdead };
+union int128_t qword;
+signed char sc = 0xed;
+signed int sc_promoted = 0xffffffed;
+signed short ss = 0xcba9;
+signed int ss_promoted = 0xffffcba9;
+_Decimal32 fp = 65432.12345df;
+_Decimal64 fp_promoted = (_Decimal64)65432.12345df;
+__fp16 fp16 = 2.0f;
+__fp16 fp16_promoted = (double)2.0f;
+
+#define HAS_DATA_INIT_FUNC
+void init_data ()
+{
+  /* Init signed quad-word integer.  */
+  qword.l64 = 0xfdb9753102468aceLL;
+  qword.h64 = 0xeca8642013579bdfLL;
+}
+
+#include "abitest.h"
+#else
+  ARG          (         int      , 0xff  ,                            W0, LAST_NAMED_ARG_ID)
+  DOTS
+  ANON_PROMOTED(unsigned char     , 0xfe  , unsigned int, 0xfe       , W1,       1)
+  ANON_PROMOTED(  signed char     , sc    ,   signed int, sc_promoted, W2,       2)
+  ANON_PROMOTED(unsigned short    , 0xdcba, unsigned int, 0xdcba     , W3,       3)
+  ANON_PROMOTED(  signed short    , ss    ,   signed int, ss_promoted, W4,       4)
+  ANON         (unsigned int      , 0xdeadbeef,                        W5,       5)
+  ANON         (  signed int      , 0xcafebabe,                        W6,       6)
+  ANON         (unsigned long long, 0xba98765432101234ULL,             X7,       7)
+  ANON         (  signed long long, 0xa987654321012345LL ,             STACK,    8)
+  ANON         (          __int128, qword.i              ,             STACK+16, 9)
+  ANON_PROMOTED(     _Decimal32   , fp    ,    _Decimal64, fp_promoted, D0,      10)
+  ANON         (     _Decimal64   , 9876543.212345dd,                  D1,      11)
+  ANON         (    _Decimal128   , 98765432123456789.987654321dl,     Q2,      12)
+  ANON         (             vf2_t, vf2   ,                            D3,      13)
+  ANON         (             vi4_t, vi4   ,                            Q4,      14)
+  /* 7.2: For unprototyped (i.e. pre- ANSI or K&R C) and variadic functions,
+     in addition to the normal conversions and promotions, arguments of
+     type __fp16 are converted to type double.  */
+  ANON_PROMOTED(            __fp16, fp16  ,     double, fp16_promoted, D5,      15)
+#ifndef __AAPCS64_BIG_ENDIAN__
+  LAST_ANON    (         int      , 0xeeee,                            STACK+32,16)
+#else
+  LAST_ANON    (         int      , 0xeeee,                            STACK+36,16)
+#endif
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-10.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-10.c
new file mode 100644
index 00000000000..c94f1ce2c09
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-10.c
@@ -0,0 +1,29 @@
+/* Test AAPCS64 layout and __builtin_va_arg.
+
+   Miscellaneous test: Anonymous arguments passed on the stack.  */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define AAPCS64_TEST_STDARG
+#define TESTFILE "va_arg_dfp-10.c"
+
+struct z
+{
+  _Decimal64 x[4];
+};
+
+_Decimal64 d1 = 25.0dd;
+_Decimal64 d2 = 103.0dd;
+struct z a = { 5.0dd, 6.0dd, 7.0dd, 8.0dd };
+struct z b = { 9.0dd, 10.0dd, 11.0dd, 12.0dd };
+
+#include "abitest.h"
+#else
+  ARG(struct z, a, D0, 0)
+  ARG(struct z, b, D4, LAST_NAMED_ARG_ID)
+  DOTS
+  ANON(_Decimal64, d1, STACK, 2)
+  LAST_ANON(_Decimal64, d2, STACK+8, 3)
+
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-11.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-11.c
new file mode 100644
index 00000000000..9ca991138dd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-11.c
@@ -0,0 +1,32 @@
+/* Test AAPCS64 layout and __builtin_va_arg.
+
+   Miscellaneous test: Anonymous arguments passed on the stack.  */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define AAPCS64_TEST_STDARG
+#define TESTFILE "va_arg_dfp-11.c"
+
+struct z
+{
+  _Decimal64 x[2];
+};
+
+_Decimal64 d1 = 25.0dd;
+struct z a = { 5.0dd, 6.0dd };
+
+#include "abitest.h"
+#else
+  ARG(_Decimal64, 1.0dd, D0, 0)
+  ARG(_Decimal64, 2.0dd, D1, 1)
+  ARG(_Decimal64, 3.0dd, D2, 2)
+  ARG(_Decimal64, 4.0dd, D3, 3)
+  ARG(_Decimal64, 5.0dd, D4, 4)
+  ARG(_Decimal64, 6.0dd, D5, 5)
+  ARG(_Decimal64, 7.0dd, D6, LAST_NAMED_ARG_ID)
+  DOTS
+  ANON(struct z, a, STACK, 8)
+  LAST_ANON(_Decimal64, d1, STACK+16, 9)
+
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-12.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-12.c
new file mode 100644
index 00000000000..8e7942f48fc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-12.c
@@ -0,0 +1,64 @@
+/* Test AAPCS64 layout and __builtin_va_arg.
+
+   Pass by reference.  */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define AAPCS64_TEST_STDARG
+#define TESTFILE "va_arg_dfp-12.c"
+
+struct z
+{
+  char c;
+  short s;
+  int ia[4];
+};
+
+struct z a, b, c;
+
+#define HAS_DATA_INIT_FUNC
+void init_data ()
+{
+  a.c = 0x11;
+  a.s = 0x2222;
+  a.ia[0] = 0x33333333;
+  a.ia[1] = 0x44444444;
+  a.ia[2] = 0x55555555;
+  a.ia[3] = 0x66666666;
+
+  b.c = 0x77;
+  b.s = 0x8888;
+  b.ia[0] = 0x99999999;
+  b.ia[1] = 0xaaaaaaaa;
+  b.ia[2] = 0xbbbbbbbb;
+  b.ia[3] = 0xcccccccc;
+
+  c.c = 0xdd;
+  c.s = 0xeeee;
+  c.ia[0] = 0xffffffff;
+  c.ia[1] = 0x12121212;
+  c.ia[2] = 0x23232323;
+  c.ia[3] = 0x34343434;
+}
+
+#include "abitest.h"
+#else
+  PTR(struct z, a, X0, 0)
+  ARG(int, 0xdeadbeef, W1, 1)
+  ARG(int, 0xcafebabe, W2, 2)
+  ARG(int, 0xdeadbabe, W3, 3)
+  ARG(int, 0xcafebeef, W4, 4)
+  ARG(int, 0xbeefdead, W5, 5)
+  ARG(int, 0xbabecafe, W6, LAST_NAMED_ARG_ID)
+  DOTS
+  PTR_ANON(struct z, b, X7, 7)
+  PTR_ANON(struct z, c, STACK, 8)
+#ifndef __AAPCS64_BIG_ENDIAN__
+  ANON(int, 0xbabedead, STACK+8, 9)
+#else
+  ANON(int, 0xbabedead, STACK+12, 9)
+#endif
+  LAST_ANON(_Decimal64, 123.45dd, D0, 10)
+
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-13.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-13.c
new file mode 100644
index 00000000000..59d5d5ebd6d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-13.c
@@ -0,0 +1,59 @@
+/* Test AAPCS64 layout and __builtin_va_start.
+
+   Pass named HFA/HVA argument on stack.  */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define AAPCS64_TEST_STDARG
+#define TESTFILE "va_arg_dfp-13.c"
+
+struct float_float_t
+{
+  _Decimal32 a;
+  _Decimal32 b;
+} float_float;
+
+union float_int_t
+{
+  _Decimal32 b8;
+  int b5;
+} float_int;
+
+#define HAS_DATA_INIT_FUNC
+void
+init_data ()
+{
+  float_float.a = 1.2df;
+  float_float.b = 2.2df;
+
+  float_int.b8 = 4983.80df;
+}
+
+#include "abitest.h"
+#else
+  ARG (_Decimal32, 1.0df, S0, 0)
+  ARG (_Decimal32, 2.0df, S1, 1)
+  ARG (_Decimal32, 3.0df, S2, 2)
+  ARG (_Decimal32, 4.0df, S3, 3)
+  ARG (_Decimal32, 5.0df, S4, 4)
+  ARG (_Decimal32, 6.0df, S5, 5)
+  ARG (_Decimal32, 7.0df, S6, 6)
+  ARG (struct float_float_t, float_float, STACK, 7)
+  ARG (int,  9, W0, 8)
+  ARG (int, 10, W1, 9)
+  ARG (int, 11, W2, 10)
+  ARG (int, 12, W3, 11)
+  ARG (int, 13, W4, 12)
+  ARG (int, 14, W5, 13)
+  ARG (int, 15, W6, LAST_NAMED_ARG_ID)
+  DOTS
+  /* Note on the reason of using 'X7' instead of 'W7' here:
+     Using 'X7' makes sure the test works in the big-endian mode.
+     According to PCS rules B.4 and C.10, the size of float_int is rounded
+     to 8 bytes and prepared in the register X7 as if loaded via LDR from
+     the memory, with the content of the other 4 bytes unspecified.  The
+     test framework will only compare the 4 relavent bytes.  */
+  ANON (union float_int_t, float_int, X7, 15)
+  LAST_ANON (long long, 12683143434LL, STACK + 8, 16)
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-14.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-14.c
new file mode 100644
index 00000000000..b54c66f0115
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-14.c
@@ -0,0 +1,35 @@
+/* Test AAPCS64 layout and __builtin_va_start.
+
+   Pass named HFA/HVA argument on stack.  */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define AAPCS64_TEST_STDARG
+#define TESTFILE "va_arg_dfp-14.c"
+#include "type-def.h"
+
+struct hfa_dfx2_t hfa_dfx2 = {1.2df, 2.2df};
+struct hfa_dfx3_t hfa_dfx3 = {3.2df, 4.2df, 5.2df};
+vf4_t float32x4 = {6.2f, 7.2f, 8.2f, 9.2f};
+vf4_t float32x4_2 = {10.2f, 11.2f, 12.2f, 13.2f};
+
+#include "abitest.h"
+#else
+  ARG (_Decimal32, 1.0df, S0, 0)
+  ARG (_Decimal32, 2.0df, S1, 1)
+  ARG (_Decimal32, 3.0df, S2, 2)
+  ARG (_Decimal32, 4.0df, S3, 3)
+  ARG (_Decimal32, 5.0df, S4, 4)
+  ARG (_Decimal32, 6.0df, S5, 5)
+  ARG (_Decimal32, 7.0df, S6, 6)
+  ARG (struct hfa_dfx3_t, hfa_dfx3, STACK, 7)
+  /* Previous argument size has been rounded up to the nearest multiple of
+     8 bytes.  */
+  ARG (struct hfa_dfx2_t, hfa_dfx2, STACK + 16, 8)
+  /* NSAA is rounded up to the nearest natural alignment of float32x4.  */
+  ARG (vf4_t, float32x4, STACK + 32, 9)
+  ARG (vf4_t, float32x4_2, STACK + 48, LAST_NAMED_ARG_ID)
+  DOTS
+  LAST_ANON (_Decimal64, 123456789.987dd, STACK + 64, 11)
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-16.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-16.c
new file mode 100644
index 00000000000..5e17e6d273d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-16.c
@@ -0,0 +1,28 @@
+/* Test AAPCS64 layout and __builtin_va_arg.
+
+   This test is focused particularly on __fp16 unnamed homogeneous
+   floating-point aggregate types which should be passed in fp/simd
+   registers until we run out of those, then the stack.  */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define AAPCS64_TEST_STDARG
+#define TESTFILE "va_arg_dfp-16.c"
+#include "type-def.h"
+
+struct hfa_f16x1_t hfa_f16x1 = {2.0f};
+struct hfa_f16x2_t hfa_f16x2 = {4.0f, 8.0f};
+struct hfa_f16x3_t hfa_f16x3 = {16.0f, 32.0f, 64.0f};
+
+#include "abitest.h"
+#else
+  ARG      (int, 1, W0, LAST_NAMED_ARG_ID)
+  DOTS
+  ANON     (struct hfa_f16x1_t, hfa_f16x1, H0     , 0)
+  ANON     (struct hfa_f16x2_t, hfa_f16x2, H1     , 1)
+  ANON     (struct hfa_f16x3_t, hfa_f16x3, H3     , 2)
+  ANON     (struct hfa_f16x2_t, hfa_f16x2, H6     , 3)
+  ANON     (struct hfa_f16x1_t, hfa_f16x1, STACK  , 4)
+  LAST_ANON(_Decimal64        , 1.0dd    , STACK+8, 5)
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-2.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-2.c
new file mode 100644
index 00000000000..d14bfb36e1d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-2.c
@@ -0,0 +1,75 @@
+/* Test AAPCS64 layout and __builtin_va_arg.
+
+   This test covers fundamental data types as specified in AAPCS64 \S 4.1.
+   It is focus on unnamed parameter passed on stack.  */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define AAPCS64_TEST_STDARG
+#define TESTFILE "va_arg_dfp-2.c"
+#include "type-def.h"
+
+vf2_t vf2 = (vf2_t){ 17.f, 18.f };
+vi4_t vi4 = (vi4_t){ 0xdeadbabe, 0xbabecafe, 0xcafebeef, 0xbeefdead };
+union int128_t qword;
+signed char sc = 0xed;
+signed int sc_promoted = 0xffffffed;
+signed short ss = 0xcba9;
+signed int ss_promoted = 0xffffcba9;
+_Decimal32 fp = 65432.12345df;
+_Decimal64 fp_promoted = (_Decimal64)65432.12345df;
+__fp16 fp16 = 2.0f;
+__fp16 fp16_promoted = (double)2.0f;
+
+#define HAS_DATA_INIT_FUNC
+void init_data ()
+{
+  /* Init signed quad-word integer.  */
+  qword.l64 = 0xfdb9753102468aceLL;
+  qword.h64 = 0xeca8642013579bdfLL;
+}
+
+#include "abitest.h"
+#else
+  ARG          (         int      , 0xff  ,                            W0,        0)
+  ARG          (    _Decimal32    , 1.0df ,                            S0,        1)
+  ARG          (    _Decimal32    , 1.0df ,                            S1,        2)
+  ARG          (    _Decimal32    , 1.0df ,                            S2,        3)
+  ARG          (    _Decimal32    , 1.0df ,                            S3,        4)
+  ARG          (    _Decimal32    , 1.0df ,                            S4,        5)
+  ARG          (    _Decimal32    , 1.0df ,                            S5,        6)
+  ARG          (    _Decimal32    , 1.0df ,                            S6,        7)
+  ARG          (    _Decimal32    , 1.0df ,                            S7, LAST_NAMED_ARG_ID)
+  DOTS
+  ANON         (          __int128, qword.i              ,             X2,        8)
+  ANON         (  signed long long, 0xa987654321012345LL ,             X4,        9)
+  ANON         (          __int128, qword.i              ,             X6,       10)
+#ifndef __AAPCS64_BIG_ENDIAN__
+  ANON_PROMOTED(unsigned char     , 0xfe  , unsigned int, 0xfe       , STACK,    11)
+  ANON_PROMOTED(  signed char     , sc    ,   signed int, sc_promoted, STACK+8,  12)
+  ANON_PROMOTED(unsigned short    , 0xdcba, unsigned int, 0xdcba     , STACK+16, 13)
+  ANON_PROMOTED(  signed short    , ss    ,   signed int, ss_promoted, STACK+24, 14)
+  ANON         (unsigned int      , 0xdeadbeef,                        STACK+32, 15)
+  ANON         (  signed int      , 0xcafebabe,                        STACK+40, 16)
+#else
+  ANON_PROMOTED(unsigned char     , 0xfe  , unsigned int, 0xfe       , STACK+4,  11)
+  ANON_PROMOTED(  signed char     , sc    ,   signed int, sc_promoted, STACK+12, 12)
+  ANON_PROMOTED(unsigned short    , 0xdcba, unsigned int, 0xdcba     , STACK+20, 13)
+  ANON_PROMOTED(  signed short    , ss    ,   signed int, ss_promoted, STACK+28, 14)
+  ANON         (unsigned int      , 0xdeadbeef,                        STACK+36, 15)
+  ANON         (  signed int      , 0xcafebabe,                        STACK+44, 16)
+#endif
+  ANON         (unsigned long long, 0xba98765432101234ULL,             STACK+48, 17)
+  ANON_PROMOTED(    _Decimal32    , fp    ,       _Decimal64, fp_promoted, STACK+56, 18)
+  ANON         (     _Decimal64   , 9876543.212345dd,                  STACK+64, 19)
+  ANON         (    _Decimal128   , 98765432123456789.987654321dl,     STACK+80, 20)
+  ANON         (             vf2_t, vf2   ,                            STACK+96, 21)
+  ANON         (             vi4_t, vi4   ,                            STACK+112,22)
+  ANON_PROMOTED(         __fp16   , fp16  ,     double, fp16_promoted, STACK+128,23)
+#ifndef __AAPCS64_BIG_ENDIAN__
+  LAST_ANON    (         int      , 0xeeee,                            STACK+136,24)
+#else
+  LAST_ANON    (         int      , 0xeeee,                            STACK+140,24)
+#endif
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-3.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-3.c
new file mode 100644
index 00000000000..9ab386f7a12
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-3.c
@@ -0,0 +1,94 @@
+/* Test AAPCS64 layout and __builtin_va_arg.
+
+   This test covers most composite types as described in AAPCS64 \S 4.3.
+   Homogeneous floating-point aggregate types are covered in other tests.  */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define AAPCS64_TEST_STDARG
+#define TESTFILE "va_arg-3.c"
+#include "type-def.h"
+
+struct x0
+{
+  char ch;
+  int i;
+} y0 = { 'a', 12345 };
+
+struct x1
+{
+  int a;
+  int b;
+  int c;
+  int d;
+} y1 = { 0xdeadbeef, 0xcafebabe, 0x87654321, 0xabcedf975 };
+
+struct x2
+{
+  long long a;
+  long long b;
+  char ch;
+} y2 = { 0x12, 0x34, 0x56 };
+
+union x3
+{
+  char ch;
+  int i;
+  long long ll;
+} y3;
+
+union x4
+{
+  int i;
+  struct x2 y2;
+} y4;
+
+struct x5
+{
+  union int128_t qword;
+} y5;
+
+#define HAS_DATA_INIT_FUNC
+void init_data ()
+{
+  /* Init small union.  */
+  y3.ll = 0xfedcba98LL;
+
+  /* Init big union.  */
+  y4.y2.a = 0x78;
+  y4.y2.b = 0x89;
+  y4.y2.ch= 0x9a;
+
+  /* Init signed quad-word integer.  */
+  y5.qword.l64 = 0xfdb9753102468aceLL;
+  y5.qword.h64 = 0xeca8642013579bdfLL;
+}
+
+#include "abitest.h"
+#else
+  ARG      (_Decimal32 ,1.0df, S0, LAST_NAMED_ARG_ID)
+  DOTS
+  ANON     (struct x0, y0, X0,        1)
+  ANON     (struct x1, y1, X1,        2)
+  PTR_ANON (struct x2, y2, X3,        3)
+  ANON     (union  x3, y3, X4,        4)
+  PTR_ANON (union  x4, y4, X5,        5)
+  ANON     (struct x5, y5, X6,        6)
+  ANON     (struct x0, y0, STACK,     7)
+  ANON     (struct x1, y1, STACK+8,   8)
+  PTR_ANON (struct x2, y2, STACK+24,  9)
+  ANON     (union  x3, y3, STACK+32, 10)
+  PTR_ANON (union  x4, y4, STACK+40, 11)
+#ifndef __AAPCS64_BIG_ENDIAN__
+  ANON     (int      ,  1, STACK+48, 12)
+#else
+  ANON     (int      ,  1, STACK+52, 12)
+#endif
+  ANON     (struct x5, y5, STACK+64, 13)
+#ifndef __AAPCS64_BIG_ENDIAN__
+  LAST_ANON(int      ,  2, STACK+80, 14)
+#else
+  LAST_ANON(int      ,  2, STACK+84, 14)
+#endif
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-4.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-4.c
new file mode 100644
index 00000000000..cf79aaa2c7f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-4.c
@@ -0,0 +1,90 @@
+/* Test AAPCS64 layout and __builtin_va_arg.
+
+   This test covers homogeneous floating-point aggregate types and homogeneous
+   short-vector aggregate types as described in AAPCS64 \S 4.3.5.  */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define AAPCS64_TEST_STDARG
+#define TESTFILE "va_arg-4.c"
+#include "type-def.h"
+
+struct hfa_dfx1_t hfa_dfx1 = {12.345df};
+struct hfa_dfx2_t hfa_dfx2 = {123.456df, 234.456df};
+struct hfa_ddx2_t hfa_ddx2 = {234.567dd, 345.678dd};
+struct hfa_ddx4_t hfa_ddx4 = {1234.123dd, 2345.234dd, 3456.345dd, 4567.456dd};
+struct hfa_dldx3_t hfa_dldx3 = {123456.7890dl, 234567.8901dl, 345678.9012dl};
+struct non_hfa_dfx5_t non_hfa_dfx5 = {456.789df, 567.890df, 678.901df, 789.012df, 890.123df};
+struct hfa_dffs_t hfa_dffs;
+struct non_hfa_dffs_t non_hfa_dffs;
+struct non_hfa_dffs_2_t non_hfa_dffs_2;
+struct hva_vdf2x1_t hva_vdf2x1;
+struct hva_vdf2x2_t hva_vdf2x2;
+struct non_hfa_dffd_t non_hfa_dffd = {23.df, 24.df, 25.0dd};
+struct non_hfa_dffvf2_t non_hfa_dffvf2;
+struct non_hfa_dfffd_t non_hfa_dfffd = {33.df, 34.df, 35.df, 36.0dd};
+union hfa_dunion_t hfa_dunion;
+union non_hfa_union_t non_hfa_union;
+
+#define HAS_DATA_INIT_FUNC
+void init_data ()
+{
+  hva_vdf2x1.a = (vdf2_t){17.df, 18.df};
+  hva_vdf2x2.a = (vdf2_t){19.df, 20.df};
+  hva_vdf2x2.b = (vdf2_t){21.df, 22.df};
+
+  non_hfa_dffvf2.a = 29.df;
+  non_hfa_dffvf2.b = 30.df;
+  non_hfa_dffvf2.c = (vdf2_t){31.df, 32.df};
+
+  hfa_dunion.s.a = 37.df;
+  hfa_dunion.s.b = 38.df;
+  hfa_dunion.c   = 39.df;
+
+  non_hfa_dunion.a = 40.0dd;
+  non_hfa_dunion.b = 41.df;
+
+  hfa_dffs.a = 42.df;
+  hfa_dffs.b = 43.df;
+  hfa_dffs.c.a = 44.df;
+  hfa_dffs.c.b = 45.df;
+
+  non_hfa_dffs.a = 46.df;
+  non_hfa_dffs.b = 47.df;
+  non_hfa_dffs.c.a = 48.0dd;
+  non_hfa_dffs.c.b = 49.0dd;
+
+  non_hfa_dffs_2.s.a = 50;
+  non_hfa_dffs_2.s.b = 51;
+  non_hfa_dffs_2.c = 52.df;
+  non_hfa_dffs_2.d = 53.df;
+}
+
+#include "abitest.h"
+#else
+  ARG      (int   , 1, W0, LAST_NAMED_ARG_ID)
+  DOTS
+  /* HFA or HVA passed in fp/simd registers or on stack.  */
+  ANON     (struct hfa_dfx1_t , hfa_dfx1,  S0      , 0)
+  ANON     (struct hfa_dfx2_t , hfa_dfx2,  S1      , 1)
+  ANON     (struct hfa_ddx2_t , hfa_ddx2,  D3      , 2)
+  ANON     (struct hva_vdf2x1_t, hva_vdf2x1, D5      , 11)
+  ANON     (struct hfa_ddx4_t , hfa_ddx4,  STACK   , 3)
+  ANON     (struct hfa_dffs_t , hfa_dffs , STACK+32, 4)
+  ANON     (union  hfa_dunion_t, hfa_dunion, STACK+48, 5)
+  ANON     (struct hfa_dldx3_t, hfa_dldx3, STACK+64, 6)
+  /* Non-H[FV]A passed in general registers or on stack or via reference.  */
+  PTR_ANON (struct non_hfa_dfx5_t , non_hfa_dfx5 , X1       , 10)
+  ANON     (struct non_hfa_dffd_t , non_hfa_dffd , X2       , 13)
+  ANON     (struct non_hfa_dffvf2_t, non_hfa_dffvf2, X6       , 16)
+  PTR_ANON (struct non_hfa_dfffd_t, non_hfa_dfffd, STACK+112, 17)
+  PTR_ANON (struct non_hfa_dffs_t , non_hfa_dffs , STACK+120, 18)
+  ANON     (struct non_hfa_dffs_2_t, non_hfa_dffs_2, STACK+128, 19)
+  ANON     (union  non_hfa_dunion_t, non_hfa_dunion, STACK+144, 20)
+#ifndef __AAPCS64_BIG_ENDIAN__
+  LAST_ANON(int                   , 2            , STACK+152, 30)
+#else
+  LAST_ANON(int                   , 2            , STACK+156, 30)
+#endif
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-5.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-5.c
new file mode 100644
index 00000000000..57ea87a37d6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-5.c
@@ -0,0 +1,47 @@
+/* Test AAPCS64 layout and __builtin_va_arg.
+
+   This test is focus on certain unnamed homogeneous floating-point aggregate
+   types passed in fp/simd registers.  */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define AAPCS64_TEST_STDARG
+#define TESTFILE "va_arg_dfp-5.c"
+#include "type-def.h"
+
+struct hfa_dfx1_t hfa_dfx1 = {12.345df};
+struct hfa_dfx2_t hfa_dfx2 = {123.456df, 234.456df};
+struct hfa_ddx2_t hfa_ddx2 = {234.567dd, 345.678dd};
+struct hfa_ddx4_t hfa_ddx4 = {1234.123dd, 2345.234dd, 3456.345dd, 4567.456dd};
+struct hfa_dldx3_t hfa_dldx3 = {123456.7890dl, 234567.8901dl, 345678.9012dl};
+struct hfa_dffs_t hfa_dffs;
+union hfa_dunion_t hfa_dunion;
+
+#define HAS_DATA_INIT_FUNC
+void init_data ()
+{
+  hfa_dunion.s.a = 37.df;
+  hfa_dunion.s.b = 38.df;
+  hfa_dunion.c   = 39.df;
+
+  hfa_dffs.a = 42.df;
+  hfa_dffs.b = 43.df;
+  hfa_dffs.c.a = 44.df;
+  hfa_dffs.c.b = 45.df;
+}
+
+#include "abitest.h"
+#else
+  ARG      (int, 1, W0, LAST_NAMED_ARG_ID)
+  DOTS
+  /* HFA passed in fp/simd registers or on stack.  */
+  ANON     (struct hfa_ddx4_t , hfa_ddx4 , D0      , 0)
+  ANON     (struct hfa_dldx3_t, hfa_dldx3, Q4      , 1)
+  ANON     (struct hfa_dffs_t , hfa_dffs , STACK   , 2)
+  ANON     (union  hfa_dunion_t, hfa_dunion, STACK+16, 3)
+  ANON     (struct hfa_dfx1_t , hfa_dfx1 , STACK+24, 4)
+  ANON     (struct hfa_dfx2_t , hfa_dfx2 , STACK+32, 5)
+  ANON     (struct hfa_ddx2_t , hfa_ddx2 , STACK+40, 6)
+  LAST_ANON(_Decimal64        , 1.0dd    , STACK+56, 9)
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-6.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-6.c
new file mode 100644
index 00000000000..c4144be3f4a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-6.c
@@ -0,0 +1,40 @@
+/* Test AAPCS64 layout and __builtin_va_arg.
+
+   This test is focus on certain unnamed homogeneous floating-point aggregate
+   types passed in fp/simd registers.  */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define AAPCS64_TEST_STDARG
+#define TESTFILE "va_arg_dfp-6.c"
+#include "type-def.h"
+
+struct hfa_dfx1_t hfa_dfx1 = {12.345df};
+struct hfa_ddx2_t hfa_ddx2 = {234.567dd, 345.678dd};
+struct hfa_dffs_t hfa_dffs;
+union hfa_dunion_t hfa_dunion;
+
+#define HAS_DATA_INIT_FUNC
+void init_data ()
+{
+  hfa_dunion.s.a = 37.df;
+  hfa_dunion.s.b = 38.df;
+  hfa_dunion.c   = 39.df;
+
+  hfa_ffs.a = 42.f;
+  hfa_ffs.b = 43.f;
+  hfa_ffs.c.a = 44.f;
+  hfa_ffs.c.b = 45.f;
+}
+
+#include "abitest.h"
+#else
+  ARG      (int, 1, W0, LAST_NAMED_ARG_ID)
+  DOTS
+  ANON     (struct hfa_dffs_t , hfa_dffs , S0     , 0)
+  ANON     (union  hfa_dunion_t, hfa_dunion, S4   , 1)
+  ANON     (struct hfa_ddx2_t , hfa_ddx2 , D6     , 2)
+  ANON     (struct hfa_dfx1_t , hfa_dfx1 , STACK  , 3)
+  LAST_ANON(_Decimal64        , 1.0dd    , STACK+8, 4)
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-8.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-8.c
new file mode 100644
index 00000000000..bd4562ff9b0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-8.c
@@ -0,0 +1,25 @@
+/* Test AAPCS64 layout and __builtin_va_arg.
+
+   Miscellaneous test: HFA anonymous parameter passed in SIMD/FP regs.  */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define AAPCS64_TEST_STDARG
+#define TESTFILE "va_arg_dfp-8.c"
+
+struct z
+{
+  _Decimal64 x[4];
+};
+
+struct z a = { 5.0dd, 6.0dd, 7.0dd, 8.0dd };
+
+#include "abitest.h"
+#else
+  ARG(int, 0xdeadbeef, W0, LAST_NAMED_ARG_ID)
+  DOTS
+  ANON(_Decimal64, 4.0dd, D0, 1)
+  LAST_ANON(struct z, a, D1, 2)
+
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-9.c b/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-9.c
new file mode 100644
index 00000000000..d1f95c4ee66
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-9.c
@@ -0,0 +1,31 @@
+/* Test AAPCS64 layout and __builtin_va_arg.
+
+   Miscellaneous test: HFA anonymous parameter passed in SIMD/FP regs.  */
+
+/* { dg-do run { target aarch64*-*-* } } */
+
+#ifndef IN_FRAMEWORK
+#define AAPCS64_TEST_STDARG
+#define TESTFILE "va_arg_dfp-9.c"
+
+struct z
+{
+  _Decimal64 x[4];
+};
+
+_Decimal64 d1 = 25.0dd;
+struct z a = { 5.0dd, 6.0dd, 7.0dd, 8.0dd };
+struct z b = { 9.0dd, 10.0dd, 11.0dd, 12.0dd };
+
+#include "abitest.h"
+#else
+  ARG(_Decimal64, 11.0dd, D0, LAST_NAMED_ARG_ID)
+  DOTS
+  ANON(int, 8, W0, 1)
+  ANON(struct z, a, D1, 2)
+  ANON(struct z, b, STACK, 3)
+  ANON(int, 5, W1, 4)
+  ANON(_Decimal64, d1, STACK+32, 5)
+  LAST_ANON(_Decimal64, 0.5dd, STACK+40, 6)
+
+#endif
-- 
2.25.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 07/10] testsuite: enable more BID DFP tests for AArch64
  2022-05-09 14:34 [PATCH 00/10] Enable Decimal Floating Point (DFP) on AArch64 Christophe Lyon
                   ` (5 preceding siblings ...)
  2022-05-09 14:35 ` [PATCH 06/10] testsuite: Add new tests for DFP under aarch64/aapcs64 Christophe Lyon
@ 2022-05-09 14:35 ` Christophe Lyon
  2022-05-09 14:35 ` [PATCH 08/10] testsuite: Add C++ unwinding tests with Decimal Floating-Point Christophe Lyon
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 33+ messages in thread
From: Christophe Lyon @ 2022-05-09 14:35 UTC (permalink / raw)
  To: gcc-patches

Some tests for the BID format are currently restricted to i?86 and
x86_64, but they also pass on AArch64, so this patch enables them.

Since all these tests are related to the BID format, it seems useful
to introduce a new effective-target (dfp_bid) instead of adding
aarch64 to the current target list.

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

	gcc/doc/
	* sourcebuild.texi (Decimal floating point attributes): Document
	dfp_bid effective-target.

	gcc/testsuite/
	* lib/target-supports.exp (check_effective_target_dfp_bid): New.
	* gcc.dg/dfp/bid-non-canonical-d128-1.c: Use dfp_bid
	effective-target.
	* gcc.dg/dfp/bid-non-canonical-d128-2.c: Likewise.
	* gcc.dg/dfp/bid-non-canonical-d128-3.c: Likewise.
	* gcc.dg/dfp/bid-non-canonical-d128-4.c: Likewise.
	* gcc.dg/dfp/bid-non-canonical-d32-1.c: Likewise.
	* gcc.dg/dfp/bid-non-canonical-d32-2.c: Likewise.
	* gcc.dg/dfp/bid-non-canonical-d64-1.c: Likewise.
	* gcc.dg/dfp/bid-non-canonical-d64-2.c: Likewise.
---
 gcc/doc/sourcebuild.texi                            |  3 +++
 gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-1.c |  3 ++-
 gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-2.c |  3 ++-
 gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-3.c |  3 ++-
 gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-4.c |  3 ++-
 gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d32-1.c  |  3 ++-
 gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d32-2.c  |  3 ++-
 gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d64-1.c  |  3 ++-
 gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d64-2.c  |  3 ++-
 gcc/testsuite/lib/target-supports.exp               | 11 +++++++++++
 10 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index 613ac29967b..8189d9ec8ec 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -1937,6 +1937,9 @@ test system can execute decimal floating point tests.
 
 @item hard_dfp
 Target generates decimal floating point instructions with current options.
+
+@item dfp_bid
+Target uses the BID format for decimal floating point.
 @end table
 
 @subsubsection ARM-specific attributes
diff --git a/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-1.c b/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-1.c
index eee5471cae0..f8da7022213 100644
--- a/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-1.c
+++ b/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-1.c
@@ -1,5 +1,6 @@
 /* Test non-canonical BID significands: _Decimal128.  Bug 91226.  */
-/* { dg-do run { target { { i?86-*-* x86_64-*-* } && lp64 } } } */
+/* { dg-do run { target lp64 } } */
+/* { dg-require-effective-target dfp_bid } */
 /* { dg-options "-std=gnu2x -O2" } */
 
 extern void abort (void);
diff --git a/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-2.c b/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-2.c
index 626712153b4..dade48fcf66 100644
--- a/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-2.c
+++ b/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-2.c
@@ -1,6 +1,7 @@
 /* Test non-canonical BID significands: _Decimal128, case where
    combination field starts 11.  Bug 91226.  */
-/* { dg-do run { target { { i?86-*-* x86_64-*-* } && lp64 } } } */
+/* { dg-do run { target lp64 } } */
+/* { dg-require-effective-target dfp_bid } */
 /* { dg-options "-std=gnu2x -O2" } */
 
 extern void abort (void);
diff --git a/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-3.c b/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-3.c
index 9190daedaf6..77c0941c027 100644
--- a/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-3.c
+++ b/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-3.c
@@ -1,5 +1,6 @@
 /* Test non-canonical BID significands: _Decimal128.  Bug 91226.  */
-/* { dg-do run { target { { i?86-*-* x86_64-*-* } && lp64 } } } */
+/* { dg-do run { target lp64 } } */
+/* { dg-require-effective-target dfp_bid } */
 /* { dg-options "-std=gnu2x -O0" } */
 
 #include "bid-non-canonical-d128-1.c"
diff --git a/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-4.c b/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-4.c
index b148ce445e7..93ff0fc6d57 100644
--- a/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-4.c
+++ b/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-4.c
@@ -1,6 +1,7 @@
 /* Test non-canonical BID significands: _Decimal128, case where
    combination field starts 11.  Bug 91226.  */
-/* { dg-do run { target { { i?86-*-* x86_64-*-* } && lp64 } } } */
+/* { dg-do run { target lp64 } } */
+/* { dg-require-effective-target dfp_bid } */
 /* { dg-options "-std=gnu2x -O0" } */
 
 #include "bid-non-canonical-d128-2.c"
diff --git a/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d32-1.c b/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d32-1.c
index b46b71cc3fc..69d014f68c0 100644
--- a/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d32-1.c
+++ b/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d32-1.c
@@ -1,5 +1,6 @@
 /* Test non-canonical BID significands: _Decimal32.  Bug 91226.  */
-/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-do run } */
+/* { dg-require-effective-target dfp_bid } */
 /* { dg-options "-std=gnu2x -O2" } */
 
 extern void abort (void);
diff --git a/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d32-2.c b/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d32-2.c
index 11d64dce193..874b2fb3633 100644
--- a/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d32-2.c
+++ b/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d32-2.c
@@ -1,5 +1,6 @@
 /* Test non-canonical BID significands: _Decimal32.  Bug 91226.  */
-/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-do run } */
+/* { dg-require-effective-target dfp_bid } */
 /* { dg-options "-std=gnu2x -O0" } */
 
 #include "bid-non-canonical-d32-1.c"
diff --git a/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d64-1.c b/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d64-1.c
index 87b106945d4..4602d34d7cb 100644
--- a/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d64-1.c
+++ b/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d64-1.c
@@ -1,5 +1,6 @@
 /* Test non-canonical BID significands: _Decimal64.  Bug 91226.  */
-/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-do run } */
+/* { dg-require-effective-target dfp_bid } */
 /* { dg-options "-std=gnu2x -O2" } */
 
 extern void abort (void);
diff --git a/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d64-2.c b/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d64-2.c
index 3c10145a314..c2993b6476f 100644
--- a/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d64-2.c
+++ b/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d64-2.c
@@ -1,5 +1,6 @@
 /* Test non-canonical BID significands: _Decimal64.  Bug 91226.  */
-/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-do run } */
+/* { dg-require-effective-target dfp_bid } */
 /* { dg-options "-std=gnu2x -O0" } */
 
 #include "bid-non-canonical-d64-1.c"
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 2d5d0539bb4..c13932e9532 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -3397,6 +3397,17 @@ proc check_effective_target_dfprt { } {
     }]
 }
 
+# Return 1 if the target uses the BID format for Decimal Floating
+# Point, 0 otherwise.
+
+proc check_effective_target_dfp_bid { } {
+    if { [istarget aarch64*-*-*]
+	 || [istarget i?86-*-*] || [istarget x86_64-*-*]} {
+	return 1
+    }
+    return 0
+}
+
 # Return 1 iff target has unsigned plain 'char' by default.
 
 proc check_effective_target_unsigned_char {} {
-- 
2.25.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 08/10] testsuite: Add C++ unwinding tests with Decimal Floating-Point
  2022-05-09 14:34 [PATCH 00/10] Enable Decimal Floating Point (DFP) on AArch64 Christophe Lyon
                   ` (6 preceding siblings ...)
  2022-05-09 14:35 ` [PATCH 07/10] testsuite: enable more BID DFP tests for AArch64 Christophe Lyon
@ 2022-05-09 14:35 ` Christophe Lyon
  2022-05-10  9:27   ` Richard Sandiford
                     ` (2 more replies)
  2022-05-09 14:35 ` [PATCH 09/10] libgcc: Add support for HF mode (aka __fp16) in libbid Christophe Lyon
                   ` (2 subsequent siblings)
  10 siblings, 3 replies; 33+ messages in thread
From: Christophe Lyon @ 2022-05-09 14:35 UTC (permalink / raw)
  To: gcc-patches

These tests exercise exception handling with Decimal Floating-Point
type.

dfp-1.C and dfp-2.C check that thrown objects of such types are
properly caught, whether when using C++ classes (decimalXX) or via GCC
mode attributes.

dfp-saves-aarch64.C checks that such objects are properly restored,
and has to use the mode attribute trick because objects of decimalXX
class type cannot be assigned to a register variable.

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

	gcc/testsuite/
	* g++.dg/eh/dfp-1.C: New test.
	* g++.dg/eh/dfp-2.C: New test.
	* g++.dg/eh/dfp-saves-aarch64.C: New test.
---
 gcc/testsuite/g++.dg/eh/dfp-1.C             | 54 +++++++++++++++++++++
 gcc/testsuite/g++.dg/eh/dfp-2.C             | 54 +++++++++++++++++++++
 gcc/testsuite/g++.dg/eh/dfp-saves-aarch64.C | 49 +++++++++++++++++++
 3 files changed, 157 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/eh/dfp-1.C
 create mode 100644 gcc/testsuite/g++.dg/eh/dfp-2.C
 create mode 100644 gcc/testsuite/g++.dg/eh/dfp-saves-aarch64.C

diff --git a/gcc/testsuite/g++.dg/eh/dfp-1.C b/gcc/testsuite/g++.dg/eh/dfp-1.C
new file mode 100644
index 00000000000..b0da13a4cc5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/eh/dfp-1.C
@@ -0,0 +1,54 @@
+// { dg-do run }
+// { dg-require-effective-target dfp }
+
+extern "C" void abort ();
+
+#include <decimal/decimal>
+
+using namespace std::decimal;
+
+int
+foo (double fp)
+{
+  if (fp < 32.0)
+    throw (decimal32)32;
+  if (fp < 64.0)
+    throw (decimal64)64;
+  if (fp < 128.0)
+    throw (decimal128)128;
+  return 0;
+}
+
+int bar (double fp)
+{
+  try
+    {
+      foo (fp);
+      abort ();
+    }
+  catch (decimal32 df)
+    {
+      if (df != (decimal32)32)
+	abort ();
+    }
+  catch (decimal64 dd)
+    {
+      if (dd != (decimal64)64)
+	abort ();
+    }
+  catch (decimal128 dl)
+    {
+      if (dl != (decimal128)128)
+	abort ();
+    }
+  return 0;
+}
+
+int
+main ()
+{
+  bar (10.0);
+  bar (20.0);
+  bar (100.0);
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/eh/dfp-2.C b/gcc/testsuite/g++.dg/eh/dfp-2.C
new file mode 100644
index 00000000000..aff0e03d1d9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/eh/dfp-2.C
@@ -0,0 +1,54 @@
+// { dg-do run }
+// { dg-require-effective-target dfp }
+
+extern "C" void abort ();
+
+typedef float dec32 __attribute__((mode(SD)));
+typedef float dec64 __attribute__((mode(DD)));
+typedef float dec128 __attribute__((mode(TD)));
+
+int
+foo (double fp)
+{
+  if (fp < 32.0)
+    throw (dec32)32;
+  if (fp < 64.0)
+    throw (dec64)64;
+  if (fp < 128.0)
+    throw (dec128)128;
+  return 0;
+}
+
+int bar (double fp)
+{
+  try
+    {
+      foo (fp);
+      abort ();
+    }
+  catch (dec32 df)
+    {
+      if (df != (dec32)32)
+	abort ();
+    }
+  catch (dec64 dd)
+    {
+      if (dd != (dec64)64)
+	abort ();
+    }
+  catch (dec128 dl)
+    {
+      if (dl != (dec128)128)
+	abort ();
+    }
+  return 0;
+}
+
+int
+main ()
+{
+  bar (10.0);
+  bar (20.0);
+  bar (100.0);
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/eh/dfp-saves-aarch64.C b/gcc/testsuite/g++.dg/eh/dfp-saves-aarch64.C
new file mode 100644
index 00000000000..79f6697dd10
--- /dev/null
+++ b/gcc/testsuite/g++.dg/eh/dfp-saves-aarch64.C
@@ -0,0 +1,49 @@
+// { dg-do run { target aarch64*-*-* } }
+// { dg-require-effective-target dfp }
+
+/* Test unwinding of AArch64 register saves.  */
+/* We cannot use #include <decimal/decimal> because it defines
+   decimal* types as classes, which we cannot be assigned to register
+   variables.  Hence the use the mode attribute trick.  */
+
+#ifdef __aarch64__
+
+typedef float dec64 __attribute__((mode(DD)));
+
+extern "C" void abort (void);
+extern "C" void exit (int);
+
+void
+foo (void)
+{
+  register dec64 v10 asm("v10") = 0;
+  register dec64 v11 asm("v11") = 1;
+  register dec64 v12 asm("v12") = 2;
+  register dec64 v13 asm("v13") = 3;
+  asm volatile ("" : "+w" (v10), "+w" (v11), "+w" (v12), "+w" (v13));
+  throw "";
+}
+
+int
+main (void)
+{
+  register dec64 v10 asm("v10") = 10;
+  register dec64 v11 asm("v11") = 11;
+  register dec64 v12 asm("v12") = 12;
+  register dec64 v13 asm("v13") = 13;
+  asm volatile ("" : "+w" (v10), "+w" (v11), "+w" (v12), "+w" (v13));
+  try {
+    foo ();
+  } catch (...) {
+    asm volatile ("" : "+w" (v10), "+w" (v11), "+w" (v12), "+w" (v13));
+    if (v10 != 10 || v11 != 11 || v12 != 12 || v13 != 13)
+      abort ();
+  }
+  exit (0);
+}
+#else
+int
+main (void)
+{
+}
+#endif
-- 
2.25.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 09/10] libgcc: Add support for HF mode (aka __fp16) in libbid
  2022-05-09 14:34 [PATCH 00/10] Enable Decimal Floating Point (DFP) on AArch64 Christophe Lyon
                   ` (7 preceding siblings ...)
  2022-05-09 14:35 ` [PATCH 08/10] testsuite: Add C++ unwinding tests with Decimal Floating-Point Christophe Lyon
@ 2022-05-09 14:35 ` Christophe Lyon
  2022-05-09 21:27   ` Joseph Myers
                     ` (2 more replies)
  2022-05-09 14:35 ` [PATCH 10/10] libgcc: use __builtin_clz and __builtin_ctz " Christophe Lyon
  2022-05-10  9:37 ` [PATCH 00/10] Enable Decimal Floating Point (DFP) on AArch64 Richard Sandiford
  10 siblings, 3 replies; 33+ messages in thread
From: Christophe Lyon @ 2022-05-09 14:35 UTC (permalink / raw)
  To: gcc-patches

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

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);
-- 
2.25.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH 10/10] libgcc: use __builtin_clz and __builtin_ctz in libbid
  2022-05-09 14:34 [PATCH 00/10] Enable Decimal Floating Point (DFP) on AArch64 Christophe Lyon
                   ` (8 preceding siblings ...)
  2022-05-09 14:35 ` [PATCH 09/10] libgcc: Add support for HF mode (aka __fp16) in libbid Christophe Lyon
@ 2022-05-09 14:35 ` Christophe Lyon
  2022-05-10  9:37 ` [PATCH 00/10] Enable Decimal Floating Point (DFP) on AArch64 Richard Sandiford
  10 siblings, 0 replies; 33+ messages in thread
From: Christophe Lyon @ 2022-05-09 14:35 UTC (permalink / raw)
  To: gcc-patches

This patch replaces libbid's implementations of clz and ctz for 32 and
64 bits inputs which used several masks, and switches to the
corresponding builtins. This will provide a better implementation,
especially on targets with clz/ctz instructions.

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

libgcc/config/libbid/ChangeLog:

	* bid_binarydecimal.c (CLZ32_MASK16): Delete.
	(CLZ32_MASK8): Delete.
	(CLZ32_MASK4): Delete.
	(CLZ32_MASK2): Delete.
	(CLZ32_MASK1): Delete.
	(clz32_nz): Use __builtin_clz.
	(ctz32_1bit): Delete.
	(ctz32): Use __builtin_ctz.
	(CLZ64_MASK32): Delete.
	(CLZ64_MASK16): Delete.
	(CLZ64_MASK8): Delete.
	(CLZ64_MASK4): Delete.
	(CLZ64_MASK2): Delete.
	(CLZ64_MASK1): Delete.
	(clz64_nz): Use __builtin_clzl.
	(ctz64_1bit): Delete.
	(ctz64): Use __builtin_ctzl.
---
 libgcc/config/libbid/bid_binarydecimal.c | 51 ++----------------------
 1 file changed, 4 insertions(+), 47 deletions(-)

diff --git a/libgcc/config/libbid/bid_binarydecimal.c b/libgcc/config/libbid/bid_binarydecimal.c
index e156ea60d11..5413acceeaf 100644
--- a/libgcc/config/libbid/bid_binarydecimal.c
+++ b/libgcc/config/libbid/bid_binarydecimal.c
@@ -26,65 +26,22 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 // Counting leading zeros in an unsigned 32-bit word
 // The "_nz" version will return the wrong answer (31) for zero inputs
 
-#define CLZ32_MASK16 0xFFFF0000ul
-#define CLZ32_MASK8  0xFF00FF00ul
-#define CLZ32_MASK4  0xF0F0F0F0ul
-#define CLZ32_MASK2  0xCCCCCCCCul
-#define CLZ32_MASK1  0xAAAAAAAAul
-
-#define clz32_nz(n)                                             \
- (((((n) & CLZ32_MASK16) <= ((n) & ~CLZ32_MASK16)) ? 16 : 0) +  \
-  ((((n) & CLZ32_MASK8) <= ((n) & ~CLZ32_MASK8)) ? 8 : 0) +     \
-  ((((n) & CLZ32_MASK4) <= ((n) & ~CLZ32_MASK4)) ? 4 : 0) +     \
-  ((((n) & CLZ32_MASK2) <= ((n) & ~CLZ32_MASK2)) ? 2 : 0) +     \
-  ((((n) & CLZ32_MASK1) <= ((n) & ~CLZ32_MASK1)) ? 1 : 0))
-
+#define clz32_nz(n) (__builtin_clz (n))
 #define clz32(n) (((n)==0) ? 32 : clz32_nz(n))
 
 // Counting trailing zeros in an unsigned 32-bit word
-// The ctz32_1bit version is for a single bit
-
-#define ctz32_1bit(n)                                           \
- ((((n) & ~CLZ32_MASK16) ? 0 : 16) +                            \
-  (((n) & ~CLZ32_MASK8) ? 0 : 8) +                              \
-  (((n) & ~CLZ32_MASK4) ? 0 : 4) +                              \
-  (((n) & ~CLZ32_MASK2) ? 0 : 2) +                              \
-  (((n) & ~CLZ32_MASK1) ? 0 : 1))
+#define ctz32(n) (__builtin_ctz (n))
 
-#define ctz32(n) (((n) == 0) ? 32 : ctz32_1bit((n) & -(n)))
 
 // Counting leading zeros in an unsigned 64-bit word
 // The "_nz" version will return the wrong answer (63) for zero inputs
 
-#define CLZ64_MASK32 0xFFFFFFFF00000000ull
-#define CLZ64_MASK16 0xFFFF0000FFFF0000ull
-#define CLZ64_MASK8  0xFF00FF00FF00FF00ull
-#define CLZ64_MASK4  0xF0F0F0F0F0F0F0F0ull
-#define CLZ64_MASK2  0xCCCCCCCCCCCCCCCCull
-#define CLZ64_MASK1  0xAAAAAAAAAAAAAAAAull
-
-#define clz64_nz(n)                                             \
- (((((n) & CLZ64_MASK32) <= ((n) & ~CLZ64_MASK32)) ? 32 : 0) +  \
-  ((((n) & CLZ64_MASK16) <= ((n) & ~CLZ64_MASK16)) ? 16 : 0) +  \
-  ((((n) & CLZ64_MASK8) <= ((n) & ~CLZ64_MASK8)) ? 8 : 0) +     \
-  ((((n) & CLZ64_MASK4) <= ((n) & ~CLZ64_MASK4)) ? 4 : 0) +     \
-  ((((n) & CLZ64_MASK2) <= ((n) & ~CLZ64_MASK2)) ? 2 : 0) +     \
-  ((((n) & CLZ64_MASK1) <= ((n) & ~CLZ64_MASK1)) ? 1 : 0))      \
-
+#define clz64_nz(n) ( (__SIZEOF_LONG__ == 8) ?__builtin_clzl(n) : __builtin_clzll(n) )
 #define clz64(n) (((n)==0) ? 64 : clz64_nz(n))
 
 // Counting trailing zeros in an unsigned 64-bit word
-// The ctz64_1bit version is for a single bit
-
-#define ctz64_1bit(n)                                           \
- ((((n) & ~CLZ64_MASK32) ? 0 : 32) +                            \
-  (((n) & ~CLZ64_MASK16) ? 0 : 16) +                            \
-  (((n) & ~CLZ64_MASK8) ? 0 : 8) +                              \
-  (((n) & ~CLZ64_MASK4) ? 0 : 4) +                              \
-  (((n) & ~CLZ64_MASK2) ? 0 : 2) +                              \
-  (((n) & ~CLZ64_MASK1) ? 0 : 1))
+#define ctz64(n) ( (__SIZEOF_LONG__ == 8) ?__builtin_ctzl(n) : __builtin_ctzll(n) )
 
-#define ctz64(n) (((n) == 0) ? 64 : ctz64_1bit((n) & -(n)))
 
 // Counting leading zeros in an unsigned 2-part 128-bit word
 
-- 
2.25.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 09/10] libgcc: Add support for HF mode (aka __fp16) in libbid
  2022-05-09 14:35 ` [PATCH 09/10] libgcc: Add support for HF mode (aka __fp16) in libbid Christophe Lyon
@ 2022-05-09 21:27   ` Joseph Myers
  2022-05-10  8:08     ` Christophe Lyon
  2022-05-13 16:34   ` [PATCH v2 " Christophe Lyon
  2022-05-13 17:52   ` Christophe Lyon
  2 siblings, 1 reply; 33+ messages in thread
From: Joseph Myers @ 2022-05-09 21:27 UTC (permalink / raw)
  To: Christophe Lyon; +Cc: gcc-patches

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.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 09/10] libgcc: Add support for HF mode (aka __fp16) in libbid
  2022-05-09 21:27   ` Joseph Myers
@ 2022-05-10  8:08     ` Christophe Lyon
  2022-05-10 20:26       ` Joseph Myers
  0 siblings, 1 reply; 33+ messages in thread
From: Christophe Lyon @ 2022-05-10  8:08 UTC (permalink / raw)
  To: Joseph Myers; +Cc: gcc-patches



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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 02/10] aarch64: Add backend support for DFP
  2022-05-09 14:34 ` [PATCH 02/10] aarch64: Add backend support for DFP Christophe Lyon
@ 2022-05-10  9:23   ` Richard Sandiford
  2022-05-10  9:30     ` Richard Sandiford
  2022-05-13 16:08   ` [PATCH v2 " Christophe Lyon
  1 sibling, 1 reply; 33+ messages in thread
From: Richard Sandiford @ 2022-05-10  9:23 UTC (permalink / raw)
  To: Christophe Lyon via Gcc-patches

Christophe Lyon via Gcc-patches <gcc-patches@gcc.gnu.org> writes:
> @@ -8464,10 +8464,18 @@ aarch64_gen_storewb_pair (machine_mode mode, rtx base, rtx reg, rtx reg2,
>        return gen_storewb_pairdf_di (base, base, reg, reg2,
>  				    GEN_INT (-adjustment),
>  				    GEN_INT (UNITS_PER_WORD - adjustment));
> +    case E_DDmode:
> +      return gen_storewb_pairdd_di (base, base, reg, reg2,
> +				    GEN_INT (-adjustment),
> +				    GEN_INT (UNITS_PER_WORD - adjustment));
>      case E_TFmode:
>        return gen_storewb_pairtf_di (base, base, reg, reg2,
>  				    GEN_INT (-adjustment),
>  				    GEN_INT (UNITS_PER_VREG - adjustment));
> +    case E_TDmode:
> +      return gen_storewb_pairtd_di (base, base, reg, reg2,
> +				    GEN_INT (-adjustment),
> +				    GEN_INT (UNITS_PER_VREG - adjustment));
>      default:
>        gcc_unreachable ();
>      }
> @@ -8510,9 +8518,15 @@ aarch64_gen_loadwb_pair (machine_mode mode, rtx base, rtx reg, rtx reg2,
>      case E_DFmode:
>        return gen_loadwb_pairdf_di (base, base, reg, reg2, GEN_INT (adjustment),
>  				   GEN_INT (UNITS_PER_WORD));
> +    case E_DDmode:
> +      return gen_loadwb_pairdd_di (base, base, reg, reg2, GEN_INT (adjustment),
> +				   GEN_INT (UNITS_PER_WORD));
>      case E_TFmode:
>        return gen_loadwb_pairtf_di (base, base, reg, reg2, GEN_INT (adjustment),
>  				   GEN_INT (UNITS_PER_VREG));
> +    case E_TDmode:
> +      return gen_loadwb_pairtd_di (base, base, reg, reg2, GEN_INT (adjustment),
> +				   GEN_INT (UNITS_PER_VREG));
>      default:
>        gcc_unreachable ();
>      }

Are these changes needed?  I would only have expected them to be
used for stack pushes and pops.

> @@ -8561,9 +8575,15 @@ aarch64_gen_store_pair (machine_mode mode, rtx mem1, rtx reg1, rtx mem2,
>      case E_DFmode:
>        return gen_store_pair_dw_dfdf (mem1, reg1, mem2, reg2);
> 
> +    case E_DDmode:
> +      return gen_store_pair_dw_dddd (mem1, reg1, mem2, reg2);
> +
>      case E_TFmode:
>        return gen_store_pair_dw_tftf (mem1, reg1, mem2, reg2);
> 
> +    case E_TDmode:
> +      return gen_store_pair_dw_tdtd (mem1, reg1, mem2, reg2);
> +
>      case E_V4SImode:
>        return gen_vec_store_pairv4siv4si (mem1, reg1, mem2, reg2);
> 
> @@ -8590,9 +8610,15 @@ aarch64_gen_load_pair (machine_mode mode, rtx reg1, rtx mem1, rtx reg2,
>      case E_DFmode:
>        return gen_load_pair_dw_dfdf (reg1, mem1, reg2, mem2);
> 
> +    case E_DDmode:
> +      return gen_load_pair_dw_dddd (reg1, mem1, reg2, mem2);
> +
>      case E_TFmode:
>        return gen_load_pair_dw_tftf (reg1, mem1, reg2, mem2);
> 
> +    case E_TDmode:
> +      return gen_load_pair_dw_tdtd (reg1, mem1, reg2, mem2);
> +
>      case E_V4SImode:
>        return gen_load_pairv4siv4si (reg1, mem1, reg2, mem2);
 
Same idea here, in that I think these would only be used for prologue/epilogue
and block operations.

> @@ -20362,7 +20407,8 @@ aarch64_vfp_is_call_or_return_candidate (machine_mode mode,
>    machine_mode new_mode = VOIDmode;
>    bool composite_p = aarch64_composite_type_p (type, mode);
>  
> -  if ((!composite_p && GET_MODE_CLASS (mode) == MODE_FLOAT)
> +  if ((!composite_p && ((GET_MODE_CLASS (mode) == MODE_FLOAT)
> +			|| GET_MODE_CLASS (mode) == MODE_DECIMAL_FLOAT))

Formatting nit: doubled brackets.  Now that the condition is spread over
multiple lines, the && should start a new line:

  if ((!composite_p
	&& (GET_MODE_CLASS (mode) == MODE_FLOAT)
	    || GET_MODE_CLASS (mode) == MODE_DECIMAL_FLOAT)

> -;; Iterator for all scalar floating point modes (SF, DF and TF)
> -(define_mode_iterator GPF_TF [SF DF TF])
> +;; Iterator for all scalar floating point modes (SF, DF, TF SD, DD, and TD)
> +(define_mode_iterator GPF_TF [SF DF TF SD DD TD])

Missing comma after “TF”.

The patch has some changes to the rtx costs for constants.  What happens
with aarch64_reinterpret_float_as_int?  (Genuine question.)  Do dfp
constants get through and do they get converted to an integer?
If so, I guess we need to handle DDmode like DFmode there.

Related, aarch64_legitimate_constant_p has:

  /* Support CSE and rematerialization of common constants.  */
  if (CONST_INT_P (x)
      || (CONST_DOUBLE_P (x) && GET_MODE_CLASS (mode) == MODE_FLOAT))
    return true;

which looks it would exclude DFP constants.  Perhaps we should
simply remove the MODE_FLOAT condition, since on AArch64 all
CONST_DOUBLEs are/must be FP constants.

The patch changes the scalar handling in aapcs_vfp_sub_candidate,
but not the complex handling.  Is that deliberate?

I wes wondering whether it would be worth adding some abstraction,
since the same checks appear multiple times.  But the only things
I could think of would have made things worse, not better, so I agree
open-coding the mode checks is the way to go.

The other parts of the patch look good.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 08/10] testsuite: Add C++ unwinding tests with Decimal Floating-Point
  2022-05-09 14:35 ` [PATCH 08/10] testsuite: Add C++ unwinding tests with Decimal Floating-Point Christophe Lyon
@ 2022-05-10  9:27   ` Richard Sandiford
  2022-05-13 16:35   ` [PATCH v2 " Christophe Lyon
  2022-05-13 17:52   ` Christophe Lyon
  2 siblings, 0 replies; 33+ messages in thread
From: Richard Sandiford @ 2022-05-10  9:27 UTC (permalink / raw)
  To: Christophe Lyon via Gcc-patches

Christophe Lyon via Gcc-patches <gcc-patches@gcc.gnu.org> writes:
> These tests exercise exception handling with Decimal Floating-Point
> type.
>
> dfp-1.C and dfp-2.C check that thrown objects of such types are
> properly caught, whether when using C++ classes (decimalXX) or via GCC
> mode attributes.
>
> dfp-saves-aarch64.C checks that such objects are properly restored,
> and has to use the mode attribute trick because objects of decimalXX
> class type cannot be assigned to a register variable.
>
> 2022-05-03  Christophe Lyon  <christophe.lyon@arm.com>
>
> 	gcc/testsuite/
> 	* g++.dg/eh/dfp-1.C: New test.
> 	* g++.dg/eh/dfp-2.C: New test.
> 	* g++.dg/eh/dfp-saves-aarch64.C: New test.
> ---
>  gcc/testsuite/g++.dg/eh/dfp-1.C             | 54 +++++++++++++++++++++
>  gcc/testsuite/g++.dg/eh/dfp-2.C             | 54 +++++++++++++++++++++
>  gcc/testsuite/g++.dg/eh/dfp-saves-aarch64.C | 49 +++++++++++++++++++
>  3 files changed, 157 insertions(+)
>  create mode 100644 gcc/testsuite/g++.dg/eh/dfp-1.C
>  create mode 100644 gcc/testsuite/g++.dg/eh/dfp-2.C
>  create mode 100644 gcc/testsuite/g++.dg/eh/dfp-saves-aarch64.C
>
> diff --git a/gcc/testsuite/g++.dg/eh/dfp-1.C b/gcc/testsuite/g++.dg/eh/dfp-1.C
> new file mode 100644
> index 00000000000..b0da13a4cc5
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/eh/dfp-1.C
> @@ -0,0 +1,54 @@
> +// { dg-do run }
> +// { dg-require-effective-target dfp }
> +
> +extern "C" void abort ();
> +
> +#include <decimal/decimal>
> +
> +using namespace std::decimal;
> +
> +int
> +foo (double fp)
> +{
> +  if (fp < 32.0)
> +    throw (decimal32)32;
> +  if (fp < 64.0)
> +    throw (decimal64)64;
> +  if (fp < 128.0)
> +    throw (decimal128)128;
> +  return 0;
> +}
> +
> +int bar (double fp)
> +{
> +  try
> +    {
> +      foo (fp);
> +      abort ();
> +    }
> +  catch (decimal32 df)
> +    {
> +      if (df != (decimal32)32)
> +	abort ();
> +    }
> +  catch (decimal64 dd)
> +    {
> +      if (dd != (decimal64)64)
> +	abort ();
> +    }
> +  catch (decimal128 dl)
> +    {
> +      if (dl != (decimal128)128)
> +	abort ();
> +    }
> +  return 0;
> +}
> +
> +int
> +main ()
> +{
> +  bar (10.0);
> +  bar (20.0);
> +  bar (100.0);
> +  return 0;
> +}
> diff --git a/gcc/testsuite/g++.dg/eh/dfp-2.C b/gcc/testsuite/g++.dg/eh/dfp-2.C
> new file mode 100644
> index 00000000000..aff0e03d1d9
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/eh/dfp-2.C
> @@ -0,0 +1,54 @@
> +// { dg-do run }
> +// { dg-require-effective-target dfp }
> +
> +extern "C" void abort ();
> +
> +typedef float dec32 __attribute__((mode(SD)));
> +typedef float dec64 __attribute__((mode(DD)));
> +typedef float dec128 __attribute__((mode(TD)));
> +
> +int
> +foo (double fp)
> +{
> +  if (fp < 32.0)
> +    throw (dec32)32;
> +  if (fp < 64.0)
> +    throw (dec64)64;
> +  if (fp < 128.0)
> +    throw (dec128)128;
> +  return 0;
> +}
> +
> +int bar (double fp)
> +{
> +  try
> +    {
> +      foo (fp);
> +      abort ();
> +    }
> +  catch (dec32 df)
> +    {
> +      if (df != (dec32)32)
> +	abort ();
> +    }
> +  catch (dec64 dd)
> +    {
> +      if (dd != (dec64)64)
> +	abort ();
> +    }
> +  catch (dec128 dl)
> +    {
> +      if (dl != (dec128)128)
> +	abort ();
> +    }
> +  return 0;
> +}
> +
> +int
> +main ()
> +{
> +  bar (10.0);
> +  bar (20.0);
> +  bar (100.0);
> +  return 0;
> +}
> diff --git a/gcc/testsuite/g++.dg/eh/dfp-saves-aarch64.C b/gcc/testsuite/g++.dg/eh/dfp-saves-aarch64.C
> new file mode 100644
> index 00000000000..79f6697dd10
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/eh/dfp-saves-aarch64.C
> @@ -0,0 +1,49 @@
> +// { dg-do run { target aarch64*-*-* } }
> +// { dg-require-effective-target dfp }
> +
> +/* Test unwinding of AArch64 register saves.  */
> +/* We cannot use #include <decimal/decimal> because it defines
> +   decimal* types as classes, which we cannot be assigned to register

Typo: s/which we cannot/which cannot/.

OK with that change, thanks.

Richard

> +   variables.  Hence the use the mode attribute trick.  */
> +
> +#ifdef __aarch64__
> +
> +typedef float dec64 __attribute__((mode(DD)));
> +
> +extern "C" void abort (void);
> +extern "C" void exit (int);
> +
> +void
> +foo (void)
> +{
> +  register dec64 v10 asm("v10") = 0;
> +  register dec64 v11 asm("v11") = 1;
> +  register dec64 v12 asm("v12") = 2;
> +  register dec64 v13 asm("v13") = 3;
> +  asm volatile ("" : "+w" (v10), "+w" (v11), "+w" (v12), "+w" (v13));
> +  throw "";
> +}
> +
> +int
> +main (void)
> +{
> +  register dec64 v10 asm("v10") = 10;
> +  register dec64 v11 asm("v11") = 11;
> +  register dec64 v12 asm("v12") = 12;
> +  register dec64 v13 asm("v13") = 13;
> +  asm volatile ("" : "+w" (v10), "+w" (v11), "+w" (v12), "+w" (v13));
> +  try {
> +    foo ();
> +  } catch (...) {
> +    asm volatile ("" : "+w" (v10), "+w" (v11), "+w" (v12), "+w" (v13));
> +    if (v10 != 10 || v11 != 11 || v12 != 12 || v13 != 13)
> +      abort ();
> +  }
> +  exit (0);
> +}
> +#else
> +int
> +main (void)
> +{
> +}
> +#endif

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 02/10] aarch64: Add backend support for DFP
  2022-05-10  9:23   ` Richard Sandiford
@ 2022-05-10  9:30     ` Richard Sandiford
  2022-05-10 10:18       ` Christophe Lyon
  0 siblings, 1 reply; 33+ messages in thread
From: Richard Sandiford @ 2022-05-10  9:30 UTC (permalink / raw)
  To: Christophe Lyon via Gcc-patches

Richard Sandiford <richard.sandiford@arm.com> writes:
> The patch changes the scalar handling in aapcs_vfp_sub_candidate,
> but not the complex handling.  Is that deliberate?

TIL: we don't support complex decimal floats.  So never mind that :-)

Richard

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 00/10] Enable Decimal Floating Point (DFP) on AArch64
  2022-05-09 14:34 [PATCH 00/10] Enable Decimal Floating Point (DFP) on AArch64 Christophe Lyon
                   ` (9 preceding siblings ...)
  2022-05-09 14:35 ` [PATCH 10/10] libgcc: use __builtin_clz and __builtin_ctz " Christophe Lyon
@ 2022-05-10  9:37 ` Richard Sandiford
  10 siblings, 0 replies; 33+ messages in thread
From: Richard Sandiford @ 2022-05-10  9:37 UTC (permalink / raw)
  To: Christophe Lyon via Gcc-patches

Christophe Lyon via Gcc-patches <gcc-patches@gcc.gnu.org> writes:
> This patch series enables support of DFP on AArch64, using the BID
> format (Binary Integer Decimal).  There is no HW support for DFP on
> AArch64, and we made a choice similar to x86: BID format using
> libgcc's libbid for software emulation.
>
> This work was done independently from Andrew's patch, which I
> discovered some time after I started [1].  The essence is similar
> although the AArch64 back-end evolved quite a bit since then, and I add
> several tests.
>
> The ABI has been documented a few months ago: _Decimal32 is treated
> like float, _Decimal64 is treated like double and _Decimal128 is
> treated like long double, using the same registers and conventions
> (sN, dN, qN, varargs handling).
>
> I have patches for GDB, which I'll send once this series is committed
> in GCC since the first GDB patch is to merge the libdecnumber updated.
>
> As of testing, I have also used libdfp, which required only a couple
> of minor patches, and its testsuite passes.
>
> I have tested the whole series on aarch64, aarch64_be and x86_64, no
> regression, all the DFP tests pass.
>
> OK?

OK for parts 1, 3-7 and 10.  Joseph should have the final say on part 9.

Thanks,
Richard

>
> Thanks,
> Christophe
>
>
>
> [1] https://gcc.gnu.org/legacy-ml/gcc-patches/2017-07/msg00788.html
>
> Christophe Lyon (10):
>   aarch64: Enable DFP (Decimal Floating-point) (BID format)
>   aarch64: Add backend support for DFP
>   libgcc: Enable XF mode conversions to/from DFP modes only if supported
>   libgcc: enable DFP for AArch64
>   testsuite:: Fix pr39986.c testcase for AArch64
>   testsuite: Add new tests for DFP under aarch64/aapcs64
>   testsuite: enable more BID DFP tests for AArch64
>   testsuite: Add C++ unwinding tests with Decimal Floating-Point
>   libgcc: Add support for HF mode (aka __fp16) in libbid
>   libgcc: use __builtin_clz and __builtin_ctz in libbid
>
>  config/dfp.m4                                 |   3 +-
>  gcc/config/aarch64/aarch64.cc                 |  95 ++++++++++---
>  gcc/config/aarch64/aarch64.md                 |  86 ++++++------
>  gcc/config/aarch64/iterators.md               |  28 +++-
>  gcc/configure                                 |   3 +-
>  gcc/doc/sourcebuild.texi                      |   3 +
>  gcc/testsuite/c-c++-common/dfp/pr39986.c      |  22 +--
>  gcc/testsuite/g++.dg/eh/dfp-1.C               |  54 +++++++
>  gcc/testsuite/g++.dg/eh/dfp-2.C               |  54 +++++++
>  gcc/testsuite/g++.dg/eh/dfp-saves-aarch64.C   |  49 +++++++
>  .../gcc.dg/dfp/bid-non-canonical-d128-1.c     |   3 +-
>  .../gcc.dg/dfp/bid-non-canonical-d128-2.c     |   3 +-
>  .../gcc.dg/dfp/bid-non-canonical-d128-3.c     |   3 +-
>  .../gcc.dg/dfp/bid-non-canonical-d128-4.c     |   3 +-
>  .../gcc.dg/dfp/bid-non-canonical-d32-1.c      |   3 +-
>  .../gcc.dg/dfp/bid-non-canonical-d32-2.c      |   3 +-
>  .../gcc.dg/dfp/bid-non-canonical-d64-1.c      |   3 +-
>  .../gcc.dg/dfp/bid-non-canonical-d64-2.c      |   3 +-
>  .../gcc.target/aarch64/aapcs64/aapcs64.exp    |   8 ++
>  .../gcc.target/aarch64/aapcs64/dfp-1.c        |  24 ++++
>  .../gcc.target/aarch64/aapcs64/func-ret-1.c   |   7 +
>  .../gcc.target/aarch64/aapcs64/func-ret-3.c   |  67 +++++++++
>  .../gcc.target/aarch64/aapcs64/ice_dfp_5.c    |  20 +++
>  .../aarch64/aapcs64/test_align_dfp-1.c        | 126 +++++++++++++++++
>  .../aarch64/aapcs64/test_align_dfp-4.c        |  42 ++++++
>  .../gcc.target/aarch64/aapcs64/test_dfp_1.c   |  31 ++++
>  .../gcc.target/aarch64/aapcs64/test_dfp_10.c  |  26 ++++
>  .../gcc.target/aarch64/aapcs64/test_dfp_11.c  |  34 +++++
>  .../gcc.target/aarch64/aapcs64/test_dfp_12.c  |  44 ++++++
>  .../gcc.target/aarch64/aapcs64/test_dfp_13.c  |  34 +++++
>  .../gcc.target/aarch64/aapcs64/test_dfp_14.c  |  35 +++++
>  .../gcc.target/aarch64/aapcs64/test_dfp_15.c  |  21 +++
>  .../gcc.target/aarch64/aapcs64/test_dfp_16.c  |  32 +++++
>  .../gcc.target/aarch64/aapcs64/test_dfp_17.c  |  37 +++++
>  .../gcc.target/aarch64/aapcs64/test_dfp_18.c  |  34 +++++
>  .../gcc.target/aarch64/aapcs64/test_dfp_19.c  |  35 +++++
>  .../gcc.target/aarch64/aapcs64/test_dfp_2.c   |  17 +++
>  .../gcc.target/aarch64/aapcs64/test_dfp_20.c  |  22 +++
>  .../gcc.target/aarch64/aapcs64/test_dfp_21.c  |  21 +++
>  .../gcc.target/aarch64/aapcs64/test_dfp_22.c  |  19 +++
>  .../gcc.target/aarch64/aapcs64/test_dfp_23.c  |  42 ++++++
>  .../gcc.target/aarch64/aapcs64/test_dfp_24.c  |  22 +++
>  .../gcc.target/aarch64/aapcs64/test_dfp_25.c  |  61 ++++++++
>  .../gcc.target/aarch64/aapcs64/test_dfp_26.c  |  54 +++++++
>  .../gcc.target/aarch64/aapcs64/test_dfp_27.c  |  46 ++++++
>  .../gcc.target/aarch64/aapcs64/test_dfp_3.c   |  18 +++
>  .../gcc.target/aarch64/aapcs64/test_dfp_5.c   |  24 ++++
>  .../gcc.target/aarch64/aapcs64/test_dfp_6.c   |  26 ++++
>  .../gcc.target/aarch64/aapcs64/test_dfp_7.c   |  30 ++++
>  .../gcc.target/aarch64/aapcs64/test_dfp_8.c   |  24 ++++
>  .../gcc.target/aarch64/aapcs64/test_dfp_9.c   |  32 +++++
>  .../aarch64/aapcs64/test_quad_double_dfp.c    |  26 ++++
>  .../gcc.target/aarch64/aapcs64/type-def.h     | 132 ++++++++++++++++++
>  .../gcc.target/aarch64/aapcs64/va_arg_dfp-1.c |  60 ++++++++
>  .../aarch64/aapcs64/va_arg_dfp-10.c           |  29 ++++
>  .../aarch64/aapcs64/va_arg_dfp-11.c           |  32 +++++
>  .../aarch64/aapcs64/va_arg_dfp-12.c           |  64 +++++++++
>  .../aarch64/aapcs64/va_arg_dfp-13.c           |  59 ++++++++
>  .../aarch64/aapcs64/va_arg_dfp-14.c           |  35 +++++
>  .../aarch64/aapcs64/va_arg_dfp-16.c           |  28 ++++
>  .../gcc.target/aarch64/aapcs64/va_arg_dfp-2.c |  75 ++++++++++
>  .../gcc.target/aarch64/aapcs64/va_arg_dfp-3.c |  94 +++++++++++++
>  .../gcc.target/aarch64/aapcs64/va_arg_dfp-4.c |  90 ++++++++++++
>  .../gcc.target/aarch64/aapcs64/va_arg_dfp-5.c |  47 +++++++
>  .../gcc.target/aarch64/aapcs64/va_arg_dfp-6.c |  40 ++++++
>  .../gcc.target/aarch64/aapcs64/va_arg_dfp-8.c |  25 ++++
>  .../gcc.target/aarch64/aapcs64/va_arg_dfp-9.c |  31 ++++
>  .../gcc.target/aarch64/convert-dfp-2.c        |  42 ++++++
>  .../gcc.target/aarch64/convert-dfp.c          |  60 ++++++++
>  gcc/testsuite/lib/target-supports.exp         |  11 ++
>  libdecnumber/configure                        |   3 +-
>  libgcc/Makefile.in                            |   9 +-
>  libgcc/config.host                            |   6 +
>  libgcc/config/libbid/_dd_to_hf.c              |  36 +++++
>  libgcc/config/libbid/_dd_to_xf.c              |   2 +
>  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/_sd_to_xf.c              |   2 +
>  libgcc/config/libbid/_td_to_hf.c              |  36 +++++
>  libgcc/config/libbid/_td_to_xf.c              |   2 +
>  libgcc/config/libbid/_xf_to_dd.c              |   2 +
>  libgcc/config/libbid/_xf_to_sd.c              |   2 +
>  libgcc/config/libbid/_xf_to_td.c              |   2 +
>  libgcc/config/libbid/bid_binarydecimal.c      |  51 +------
>  libgcc/config/libbid/bid_gcc_intrinsics.h     |  30 +++-
>  libgcc/configure                              |   3 +-
>  88 files changed, 2698 insertions(+), 148 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/eh/dfp-1.C
>  create mode 100644 gcc/testsuite/g++.dg/eh/dfp-2.C
>  create mode 100644 gcc/testsuite/g++.dg/eh/dfp-saves-aarch64.C
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/dfp-1.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/ice_dfp_5.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_align_dfp-1.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_align_dfp-4.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_1.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_10.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_11.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_12.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_13.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_14.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_15.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_16.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_17.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_18.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_19.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_2.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_20.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_21.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_22.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_23.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_24.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_25.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_26.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_27.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_3.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_5.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_6.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_7.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_8.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_dfp_9.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/test_quad_double_dfp.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-1.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-10.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-11.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-12.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-13.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-14.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-16.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-2.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-3.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-4.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-5.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-6.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-8.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/aapcs64/va_arg_dfp-9.c
>  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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 02/10] aarch64: Add backend support for DFP
  2022-05-10  9:30     ` Richard Sandiford
@ 2022-05-10 10:18       ` Christophe Lyon
  0 siblings, 0 replies; 33+ messages in thread
From: Christophe Lyon @ 2022-05-10 10:18 UTC (permalink / raw)
  To: Christophe Lyon via Gcc-patches, richard.sandiford



On 5/10/22 11:30, Richard Sandiford wrote:
> Richard Sandiford <richard.sandiford@arm.com> writes:
>> The patch changes the scalar handling in aapcs_vfp_sub_candidate,
>> but not the complex handling.  Is that deliberate?
> 
> TIL: we don't support complex decimal floats.  So never mind that :-)
> 
Indeed. Sorry, maybe I should have made this clear in the commit message.

> Richard

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH 09/10] libgcc: Add support for HF mode (aka __fp16) in libbid
  2022-05-10  8:08     ` Christophe Lyon
@ 2022-05-10 20:26       ` Joseph Myers
  0 siblings, 0 replies; 33+ messages in thread
From: Joseph Myers @ 2022-05-10 20:26 UTC (permalink / raw)
  To: Christophe Lyon; +Cc: gcc-patches

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.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v2 02/10] aarch64: Add backend support for DFP
  2022-05-09 14:34 ` [PATCH 02/10] aarch64: Add backend support for DFP Christophe Lyon
  2022-05-10  9:23   ` Richard Sandiford
@ 2022-05-13 16:08   ` Christophe Lyon
  2022-05-13 16:35     ` Richard Sandiford
  1 sibling, 1 reply; 33+ messages in thread
From: Christophe Lyon @ 2022-05-13 16:08 UTC (permalink / raw)
  To: gcc-patches

This patch updates the aarch64 backend as needed to support DFP modes
(SD, DD and TD).

2022-03-31  Christophe Lyon  <christophe.lyon@arm.com>

	gcc/
	* config/aarch64/aarch64.cc
	(aarch64_split_128bit_move): Handle DFP modes.
	(aarch64_mode_valid_for_sched_fusion_p): Likewise.
	(aarch64_classify_address): Likewise.
	(aarch64_legitimize_address_displacement): Likewise.
	(aarch64_reinterpret_float_as_int): Likewise.
	(aarch64_float_const_zero_rtx_p): Likewise.
	(aarch64_can_const_movi_rtx_p): Likewise.
	(aarch64_anchor_offset): Likewise.
	(aarch64_secondary_reload): Likewise.
	(aarch64_rtx_costs): Likewise.
	(aarch64_legitimate_constant_p): Likewise.
	(aarch64_gimplify_va_arg_expr): Likewise.
	(aapcs_vfp_sub_candidate): Likewise.
	(aarch64_vfp_is_call_or_return_candidate): Likewise.
	(aarch64_output_scalar_simd_mov_immediate): Likewise.
	(aarch64_gen_adjusted_ldpstp): Likewise.
	(aarch64_scalar_mode_supported_p): Accept DFP modes if enabled.
	* config/aarch64/aarch64.md
	(movsf_aarch64): Use SFD iterator and rename into
	mov<mode>_aarch64.
	(movdf_aarch64): Use DFD iterator and rename into
	mov<mode>_aarch64.
	(movtf_aarch64): Use TFD iterator and rename into
	mov<mode>_aarch64.
	(split pattern for move TF mode): Use TFD iterator.
	* config/aarch64/aarch64/iterators.md
	(GPF_TF_F16_MOV): Add DFP modes.
	(SFD, DFD, TFD): New iterators.
	(GPF_TF): Add DFP modes.
	(TX, DX, DX2): Likewise.
---
 gcc/config/aarch64/aarch64.cc   | 85 ++++++++++++++++++++++-----------
 gcc/config/aarch64/aarch64.md   | 34 ++++++-------
 gcc/config/aarch64/iterators.md | 24 +++++++---
 3 files changed, 92 insertions(+), 51 deletions(-)

diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index bd855758778..ca7eb4004bf 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -4828,7 +4828,7 @@ aarch64_split_128bit_move (rtx dst, rtx src)
 
   machine_mode mode = GET_MODE (dst);
 
-  gcc_assert (mode == TImode || mode == TFmode);
+  gcc_assert (mode == TImode || mode == TFmode || mode == TDmode);
   gcc_assert (!(side_effects_p (src) || side_effects_p (dst)));
   gcc_assert (mode == GET_MODE (src) || GET_MODE (src) == VOIDmode);
 
@@ -10568,6 +10568,7 @@ aarch64_mode_valid_for_sched_fusion_p (machine_mode mode)
 {
   return mode == SImode || mode == DImode
 	 || mode == SFmode || mode == DFmode
+	 || mode == SDmode || mode == DDmode
 	 || (aarch64_vector_mode_supported_p (mode)
 	     && (known_eq (GET_MODE_SIZE (mode), 8)
 		 || (known_eq (GET_MODE_SIZE (mode), 16)
@@ -10610,12 +10611,13 @@ aarch64_classify_address (struct aarch64_address_info *info,
   vec_flags &= ~VEC_PARTIAL;
 
   /* On BE, we use load/store pair for all large int mode load/stores.
-     TI/TFmode may also use a load/store pair.  */
+     TI/TF/TDmode may also use a load/store pair.  */
   bool advsimd_struct_p = (vec_flags == (VEC_ADVSIMD | VEC_STRUCT));
   bool load_store_pair_p = (type == ADDR_QUERY_LDP_STP
 			    || type == ADDR_QUERY_LDP_STP_N
 			    || mode == TImode
 			    || mode == TFmode
+			    || mode == TDmode
 			    || (BYTES_BIG_ENDIAN && advsimd_struct_p));
   /* If we are dealing with ADDR_QUERY_LDP_STP_N that means the incoming mode
      corresponds to the actual size of the memory being loaded/stored and the
@@ -10689,7 +10691,7 @@ aarch64_classify_address (struct aarch64_address_info *info,
 	  info->offset = op1;
 	  info->const_offset = offset;
 
-	  /* TImode and TFmode values are allowed in both pairs of X
+	  /* TImode, TFmode and TDmode values are allowed in both pairs of X
 	     registers and individual Q registers.  The available
 	     address modes are:
 	     X,X: 7-bit signed scaled offset
@@ -10698,7 +10700,7 @@ aarch64_classify_address (struct aarch64_address_info *info,
 	     When performing the check for pairs of X registers i.e.  LDP/STP
 	     pass down DImode since that is the natural size of the LDP/STP
 	     instruction memory accesses.  */
-	  if (mode == TImode || mode == TFmode)
+	  if (mode == TImode || mode == TFmode || mode == TDmode)
 	    return (aarch64_offset_7bit_signed_scaled_p (DImode, offset)
 		    && (aarch64_offset_9bit_signed_unscaled_p (mode, offset)
 			|| offset_12bit_unsigned_scaled_p (mode, offset)));
@@ -10821,14 +10823,14 @@ aarch64_classify_address (struct aarch64_address_info *info,
 	  info->offset = XEXP (XEXP (x, 1), 1);
 	  info->const_offset = offset;
 
-	  /* TImode and TFmode values are allowed in both pairs of X
+	  /* TImode, TFmode and TDmode values are allowed in both pairs of X
 	     registers and individual Q registers.  The available
 	     address modes are:
 	     X,X: 7-bit signed scaled offset
 	     Q:   9-bit signed offset
 	     We conservatively require an offset representable in either mode.
 	   */
-	  if (mode == TImode || mode == TFmode)
+	  if (mode == TImode || mode == TFmode || mode == TDmode)
 	    return (aarch64_offset_7bit_signed_scaled_p (mode, offset)
 		    && aarch64_offset_9bit_signed_unscaled_p (mode, offset));
 
@@ -10990,9 +10992,9 @@ aarch64_legitimize_address_displacement (rtx *offset1, rtx *offset2,
 	 offset.  Use 4KB range for 1- and 2-byte accesses and a 16KB
 	 range otherwise to increase opportunities for sharing the base
 	 address of different sizes.  Unaligned accesses use the signed
-	 9-bit range, TImode/TFmode use the intersection of signed
+	 9-bit range, TImode/TFmode/TDmode use the intersection of signed
 	 scaled 7-bit and signed 9-bit offset.  */
-      if (mode == TImode || mode == TFmode)
+      if (mode == TImode || mode == TFmode || mode == TDmode)
 	second_offset = ((const_offset + 0x100) & 0x1f8) - 0x100;
       else if ((const_offset & (size - 1)) != 0)
 	second_offset = ((const_offset + 0x100) & 0x1ff) - 0x100;
@@ -11073,7 +11075,7 @@ aarch64_reinterpret_float_as_int (rtx value, unsigned HOST_WIDE_INT *intval)
 		  CONST_DOUBLE_REAL_VALUE (value),
 		  REAL_MODE_FORMAT (mode));
 
-  if (mode == DFmode)
+  if (mode == DFmode || mode == DDmode)
     {
       int order = BYTES_BIG_ENDIAN ? 1 : 0;
       ival = zext_hwi (res[order], 32);
@@ -11114,11 +11116,16 @@ aarch64_float_const_rtx_p (rtx x)
   return false;
 }
 
-/* Return TRUE if rtx X is immediate constant 0.0 */
+/* Return TRUE if rtx X is immediate constant 0.0 (but not in Decimal
+   Floating Point).  */
 bool
 aarch64_float_const_zero_rtx_p (rtx x)
 {
-  if (GET_MODE (x) == VOIDmode)
+  if (GET_MODE (x) == VOIDmode
+      /* 0.0 in Decimal Floating Point cannot be represented by #0 or
+	 zr as our callers expect, so no need to check the actual
+	 value if X is of Decimal Floating Point type.  */
+      || GET_MODE_CLASS (GET_MODE (x)) == MODE_DECIMAL_FLOAT)
     return false;
 
   if (REAL_VALUE_MINUS_ZERO (*CONST_DOUBLE_REAL_VALUE (x)))
@@ -11156,7 +11163,7 @@ aarch64_can_const_movi_rtx_p (rtx x, machine_mode mode)
   else
     return false;
 
-   /* use a 64 bit mode for everything except for DI/DF mode, where we use
+   /* use a 64 bit mode for everything except for DI/DF/DD mode, where we use
      a 128 bit vector mode.  */
   int width = GET_MODE_BITSIZE (imode) == 64 ? 128 : 64;
 
@@ -12356,7 +12363,7 @@ aarch64_anchor_offset (HOST_WIDE_INT offset, HOST_WIDE_INT size,
   if (IN_RANGE (offset, -256, 0))
     return 0;
 
-  if (mode == TImode || mode == TFmode)
+  if (mode == TImode || mode == TFmode || mode == TDmode)
     return (offset + 0x100) & ~0x1ff;
 
   /* Use 12-bit offset by access size.  */
@@ -12465,7 +12472,9 @@ aarch64_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x,
 
   /* Without the TARGET_SIMD instructions we cannot move a Q register
      to a Q register directly.  We need a scratch.  */
-  if (REG_P (x) && (mode == TFmode || mode == TImode) && mode == GET_MODE (x)
+  if (REG_P (x)
+      && (mode == TFmode || mode == TImode || mode == TDmode)
+      && mode == GET_MODE (x)
       && FP_REGNUM_P (REGNO (x)) && !TARGET_SIMD
       && reg_class_subset_p (rclass, FP_REGS))
     {
@@ -12473,14 +12482,16 @@ aarch64_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x,
       return NO_REGS;
     }
 
-  /* A TFmode or TImode memory access should be handled via an FP_REGS
+  /* A TFmode, TImode or TDmode memory access should be handled via an FP_REGS
      because AArch64 has richer addressing modes for LDR/STR instructions
      than LDP/STP instructions.  */
   if (TARGET_FLOAT && rclass == GENERAL_REGS
       && known_eq (GET_MODE_SIZE (mode), 16) && MEM_P (x))
     return FP_REGS;
 
-  if (rclass == FP_REGS && (mode == TImode || mode == TFmode) && CONSTANT_P(x))
+  if (rclass == FP_REGS
+      && (mode == TImode || mode == TFmode || mode == TDmode)
+      && CONSTANT_P(x))
       return GENERAL_REGS;
 
   return NO_REGS;
@@ -13611,9 +13622,9 @@ aarch64_rtx_costs (rtx x, machine_mode mode, int outer ATTRIBUTE_UNUSED,
 		*cost += extra_cost->ldst.storev;
 	      else if (GET_MODE_CLASS (mode) == MODE_INT)
 		*cost += extra_cost->ldst.store;
-	      else if (mode == SFmode)
+	      else if (mode == SFmode || mode == SDmode)
 		*cost += extra_cost->ldst.storef;
-	      else if (mode == DFmode)
+	      else if (mode == DFmode || mode == DDmode)
 		*cost += extra_cost->ldst.stored;
 
 	      *cost +=
@@ -13737,11 +13748,11 @@ aarch64_rtx_costs (rtx x, machine_mode mode, int outer ATTRIBUTE_UNUSED,
 	  /* mov[df,sf]_aarch64.  */
 	  if (aarch64_float_const_representable_p (x))
 	    /* FMOV (scalar immediate).  */
-	    *cost += extra_cost->fp[mode == DFmode].fpconst;
+	    *cost += extra_cost->fp[mode == DFmode || mode == DDmode].fpconst;
 	  else if (!aarch64_float_const_zero_rtx_p (x))
 	    {
 	      /* This will be a load from memory.  */
-	      if (mode == DFmode)
+	      if (mode == DFmode || mode == DDmode)
 		*cost += extra_cost->ldst.loadd;
 	      else
 		*cost += extra_cost->ldst.loadf;
@@ -13767,9 +13778,9 @@ aarch64_rtx_costs (rtx x, machine_mode mode, int outer ATTRIBUTE_UNUSED,
 	    *cost += extra_cost->ldst.loadv;
 	  else if (GET_MODE_CLASS (mode) == MODE_INT)
 	    *cost += extra_cost->ldst.load;
-	  else if (mode == SFmode)
+	  else if (mode == SFmode || mode == SDmode)
 	    *cost += extra_cost->ldst.loadf;
-	  else if (mode == DFmode)
+	  else if (mode == DFmode || mode == DDmode)
 	    *cost += extra_cost->ldst.loadd;
 
 	  *cost +=
@@ -19352,7 +19363,9 @@ aarch64_legitimate_constant_p (machine_mode mode, rtx x)
 {
   /* Support CSE and rematerialization of common constants.  */
   if (CONST_INT_P (x)
-      || (CONST_DOUBLE_P (x) && GET_MODE_CLASS (mode) == MODE_FLOAT))
+      || (CONST_DOUBLE_P (x)
+	  && (GET_MODE_CLASS (mode) == MODE_FLOAT
+	      || GET_MODE_CLASS (mode) == MODE_DECIMAL_FLOAT)))
     return true;
 
   /* Only accept variable-length vector constants if they can be
@@ -19795,6 +19808,18 @@ aarch64_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
 	  field_t = long_double_type_node;
 	  field_ptr_t = long_double_ptr_type_node;
 	  break;
+	case SDmode:
+	  field_t = dfloat32_type_node;
+	  field_ptr_t = build_pointer_type (dfloat32_type_node);
+	  break;
+	case DDmode:
+	  field_t = dfloat64_type_node;
+	  field_ptr_t = build_pointer_type (dfloat64_type_node);
+	  break;
+	case TDmode:
+	  field_t = dfloat128_type_node;
+	  field_ptr_t = build_pointer_type (dfloat128_type_node);
+	  break;
 	case E_HFmode:
 	  field_t = aarch64_fp16_type_node;
 	  field_ptr_t = aarch64_fp16_ptr_type_node;
@@ -20046,7 +20071,8 @@ aapcs_vfp_sub_candidate (const_tree type, machine_mode *modep,
     case REAL_TYPE:
       mode = TYPE_MODE (type);
       if (mode != DFmode && mode != SFmode
-	  && mode != TFmode && mode != HFmode)
+	  && mode != TFmode && mode != HFmode
+	  && mode != SDmode && mode != DDmode && mode != TDmode)
 	return -1;
 
       if (*modep == VOIDmode)
@@ -20362,7 +20388,9 @@ aarch64_vfp_is_call_or_return_candidate (machine_mode mode,
   machine_mode new_mode = VOIDmode;
   bool composite_p = aarch64_composite_type_p (type, mode);
 
-  if ((!composite_p && GET_MODE_CLASS (mode) == MODE_FLOAT)
+  if ((!composite_p
+       && (GET_MODE_CLASS (mode) == MODE_FLOAT
+	   || GET_MODE_CLASS (mode) == MODE_DECIMAL_FLOAT))
       || aarch64_short_vector_p (type, mode))
     {
       *count = 1;
@@ -23264,7 +23292,7 @@ aarch64_output_scalar_simd_mov_immediate (rtx immediate, scalar_int_mode mode)
     }
 
   machine_mode vmode;
-  /* use a 64 bit mode for everything except for DI/DF mode, where we use
+  /* use a 64 bit mode for everything except for DI/DF/DD mode, where we use
      a 128 bit vector mode.  */
   int width = GET_MODE_BITSIZE (mode) == 64 ? 128 : 64;
 
@@ -26082,7 +26110,7 @@ aarch64_gen_adjusted_ldpstp (rtx *operands, bool load,
     base_off = (off_val_1 + off_val_3) / 2;
   else
     /* However, due to issues with negative LDP/STP offset generation for
-       larger modes, for DF, DI and vector modes. we must not use negative
+       larger modes, for DF, DD, DI and vector modes. we must not use negative
        addresses smaller than 9 signed unadjusted bits can store.  This
        provides the most range in this case.  */
     base_off = off_val_1;
@@ -26360,6 +26388,9 @@ aarch64_libgcc_floating_mode_supported_p (scalar_float_mode mode)
 static bool
 aarch64_scalar_mode_supported_p (scalar_mode mode)
 {
+  if (DECIMAL_FLOAT_MODE_P (mode))
+    return default_decimal_float_supported_p ();
+
   return (mode == HFmode
 	  ? true
 	  : default_scalar_mode_supported_p (mode));
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index f5c635938ad..2ac8d564762 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -1477,11 +1477,11 @@ (define_insn "*mov<mode>_aarch64"
    (set_attr "arch" "simd,fp16,simd,simd,simd,fp16,simd,*,*,*,*,*")]
 )
 
-(define_insn "*movsf_aarch64"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=w,w  ,?r,w,w  ,w  ,w,m,r,m ,r,r")
-	(match_operand:SF 1 "general_operand"      "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r,M"))]
-  "TARGET_FLOAT && (register_operand (operands[0], SFmode)
-    || aarch64_reg_or_fp_zero (operands[1], SFmode))"
+(define_insn "*mov<mode>_aarch64"
+  [(set (match_operand:SFD 0 "nonimmediate_operand" "=w,w  ,?r,w,w  ,w  ,w,m,r,m ,r,r")
+	(match_operand:SFD 1 "general_operand"      "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r,M"))]
+  "TARGET_FLOAT && (register_operand (operands[0], <MODE>mode)
+    || aarch64_reg_or_fp_zero (operands[1], <MODE>mode))"
   "@
    movi\\t%0.2s, #0
    fmov\\t%s0, %w1
@@ -1501,11 +1501,11 @@ (define_insn "*movsf_aarch64"
    (set_attr "arch" "simd,*,*,*,*,simd,*,*,*,*,*,*")]
 )
 
-(define_insn "*movdf_aarch64"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=w, w  ,?r,w,w  ,w  ,w,m,r,m ,r,r")
-	(match_operand:DF 1 "general_operand"      "Y , ?rY, w,w,Ufc,Uvi,m,w,m,rY,r,N"))]
-  "TARGET_FLOAT && (register_operand (operands[0], DFmode)
-    || aarch64_reg_or_fp_zero (operands[1], DFmode))"
+(define_insn "*mov<mode>_aarch64"
+  [(set (match_operand:DFD 0 "nonimmediate_operand" "=w, w  ,?r,w,w  ,w  ,w,m,r,m ,r,r")
+	(match_operand:DFD 1 "general_operand"      "Y , ?rY, w,w,Ufc,Uvi,m,w,m,rY,r,N"))]
+  "TARGET_FLOAT && (register_operand (operands[0], <MODE>mode)
+    || aarch64_reg_or_fp_zero (operands[1], <MODE>mode))"
   "@
    movi\\t%d0, #0
    fmov\\t%d0, %x1
@@ -1545,13 +1545,13 @@ (define_split
   }
 )
 
-(define_insn "*movtf_aarch64"
-  [(set (match_operand:TF 0
+(define_insn "*mov<mode>_aarch64"
+  [(set (match_operand:TFD 0
 	 "nonimmediate_operand" "=w,?r ,w ,?r,w,?w,w,m,?r,m ,m")
-	(match_operand:TF 1
+	(match_operand:TFD 1
 	 "general_operand"      " w,?rY,?r,w ,Y,Y ,m,w,m ,?r,Y"))]
-  "TARGET_FLOAT && (register_operand (operands[0], TFmode)
-    || aarch64_reg_or_fp_zero (operands[1], TFmode))"
+  "TARGET_FLOAT && (register_operand (operands[0], <MODE>mode)
+    || aarch64_reg_or_fp_zero (operands[1], <MODE>mode))"
   "@
    mov\\t%0.16b, %1.16b
    #
@@ -1571,8 +1571,8 @@ (define_insn "*movtf_aarch64"
 )
 
 (define_split
-   [(set (match_operand:TF 0 "register_operand" "")
-	 (match_operand:TF 1 "nonmemory_operand" ""))]
+   [(set (match_operand:TFD 0 "register_operand" "")
+	 (match_operand:TFD 1 "nonmemory_operand" ""))]
   "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
   [(const_int 0)]
   {
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index 88af964de7e..1c1048368f0 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -64,14 +64,24 @@ (define_mode_iterator GPF_HF [HF SF DF])
 (define_mode_iterator HFBF [HF BF])
 
 ;; Iterator for all scalar floating point modes suitable for moving, including
-;; special BF type (HF, SF, DF, TF and BF)
-(define_mode_iterator GPF_TF_F16_MOV [HF BF SF DF TF])
+;; special BF type and decimal floating point types (HF, SF, DF, TF, BF,
+;; SD, DD and TD)
+(define_mode_iterator GPF_TF_F16_MOV [HF BF SF DF TF SD DD TD])
+
+;; Iterator for scalar 32bit fp modes (SF, SD)
+(define_mode_iterator SFD [SD SF])
+
+;; Iterator for scalar 64bit fp modes (DF, DD)
+(define_mode_iterator DFD [DD DF])
+
+;; Iterator for scalar 128bit fp modes (TF, TD)
+(define_mode_iterator TFD [TD TF])
 
 ;; Double vector modes.
 (define_mode_iterator VDF [V2SF V4HF])
 
-;; Iterator for all scalar floating point modes (SF, DF and TF)
-(define_mode_iterator GPF_TF [SF DF TF])
+;; Iterator for all scalar floating point modes (SF, DF, TF, SD, DD, and TD)
+(define_mode_iterator GPF_TF [SF DF TF SD DD TD])
 
 ;; Integer Advanced SIMD modes.
 (define_mode_iterator VDQ_I [V8QI V16QI V4HI V8HI V2SI V4SI V2DI])
@@ -298,7 +308,7 @@ (define_mode_iterator VB [V8QI V16QI])
 ;; 2 and 4 lane SI modes.
 (define_mode_iterator VS [V2SI V4SI])
 
-(define_mode_iterator TX [TI TF])
+(define_mode_iterator TX [TI TF TD])
 
 ;; Advanced SIMD opaque structure modes.
 (define_mode_iterator VSTRUCT [OI CI XI])
@@ -400,10 +410,10 @@ (define_mode_iterator VSTRUCT_QD [V2x8QI V2x4HI V2x2SI V2x1DI
 				  V4x8HF V4x4SF V4x2DF V4x8BF])
 
 ;; Double scalar modes
-(define_mode_iterator DX [DI DF])
+(define_mode_iterator DX [DI DF DD])
 
 ;; Duplicate of the above
-(define_mode_iterator DX2 [DI DF])
+(define_mode_iterator DX2 [DI DF DD])
 
 ;; Single scalar modes
 (define_mode_iterator SX [SI SF])
-- 
2.25.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v2 09/10] libgcc: Add support for HF mode (aka __fp16) in libbid
  2022-05-09 14:35 ` [PATCH 09/10] libgcc: Add support for HF mode (aka __fp16) in libbid Christophe Lyon
  2022-05-09 21:27   ` Joseph Myers
@ 2022-05-13 16:34   ` Christophe Lyon
  2022-05-13 17:52   ` Christophe Lyon
  2 siblings, 0 replies; 33+ messages in thread
From: Christophe Lyon @ 2022-05-13 16:34 UTC (permalink / raw)
  To: gcc-patches

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              | 38 ++++++++++++
 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              | 38 ++++++++++++
 libgcc/config/libbid/_td_to_hf.c              | 38 ++++++++++++
 libgcc/config/libbid/bid_gcc_intrinsics.h     | 30 +++++++++-
 10 files changed, 358 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

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..5e58288391e
--- /dev/null
+++ b/libgcc/config/libbid/_dd_to_hf.c
@@ -0,0 +1,38 @@
+/* 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
+HFtype
+__bid_truncddhf (_Decimal64 x) {
+  HFtype res;
+  union decimal64 ux;
+
+  ux.d = x;
+  res = __bid64_to_binary32 (ux.i);
+  return (res);
+}
+#endif
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..e4e3125d49b
--- /dev/null
+++ b/libgcc/config/libbid/_sd_to_hf.c
@@ -0,0 +1,38 @@
+/* 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
+HFtype
+__bid_truncsdhf (_Decimal32 x) {
+  HFtype res;
+  union decimal32 ux;
+
+  ux.d = x;
+  res = __bid32_to_binary32 (ux.i);
+  return (res);
+}
+#endif
diff --git a/libgcc/config/libbid/_td_to_hf.c b/libgcc/config/libbid/_td_to_hf.c
new file mode 100644
index 00000000000..c4ebe586db0
--- /dev/null
+++ b/libgcc/config/libbid/_td_to_hf.c
@@ -0,0 +1,38 @@
+/* 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
+HFtype
+__bid_trunctdhf (_Decimal128 x) {
+  HFtype res;
+  union decimal128 ux;
+
+  ux.d = x;
+  res = __bid128_to_binary32 (ux.i);
+  return (res);
+}
+#endif
diff --git a/libgcc/config/libbid/bid_gcc_intrinsics.h b/libgcc/config/libbid/bid_gcc_intrinsics.h
index b0a23debc15..f1fd90e18d7 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 __float16
+#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);
-- 
2.25.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v2 02/10] aarch64: Add backend support for DFP
  2022-05-13 16:08   ` [PATCH v2 " Christophe Lyon
@ 2022-05-13 16:35     ` Richard Sandiford
  2022-05-16 12:17       ` Christophe Lyon
  0 siblings, 1 reply; 33+ messages in thread
From: Richard Sandiford @ 2022-05-13 16:35 UTC (permalink / raw)
  To: Christophe Lyon via Gcc-patches

Christophe Lyon via Gcc-patches <gcc-patches@gcc.gnu.org> writes:
> @@ -19352,7 +19363,9 @@ aarch64_legitimate_constant_p (machine_mode mode, rtx x)
>  {
>    /* Support CSE and rematerialization of common constants.  */
>    if (CONST_INT_P (x)
> -      || (CONST_DOUBLE_P (x) && GET_MODE_CLASS (mode) == MODE_FLOAT))
> +      || (CONST_DOUBLE_P (x)
> +	  && (GET_MODE_CLASS (mode) == MODE_FLOAT
> +	      || GET_MODE_CLASS (mode) == MODE_DECIMAL_FLOAT)))
>      return true;
>  
>    /* Only accept variable-length vector constants if they can be

I'd prefer to remove the mode check here, rather than extend it.
If we see a CONST_DOUBLE that doesn't have a scalar float mode
then something has gone wrong.  (No need to assert for that though.
It's a fundamental assumption when TARGET_SUPPORTS_WIDE_INT.)

For consistency…

> @@ -11114,11 +11116,16 @@ aarch64_float_const_rtx_p (rtx x)
>    return false;
>  }
>  
> -/* Return TRUE if rtx X is immediate constant 0.0 */
> +/* Return TRUE if rtx X is immediate constant 0.0 (but not in Decimal
> +   Floating Point).  */
>  bool
>  aarch64_float_const_zero_rtx_p (rtx x)
>  {
> -  if (GET_MODE (x) == VOIDmode)
> +  if (GET_MODE (x) == VOIDmode
> +      /* 0.0 in Decimal Floating Point cannot be represented by #0 or
> +	 zr as our callers expect, so no need to check the actual
> +	 value if X is of Decimal Floating Point type.  */
> +      || GET_MODE_CLASS (GET_MODE (x)) == MODE_DECIMAL_FLOAT)

…it would be good to drop the VOIDmode check here at the same time.

OK with those changes, thanks.

Richard

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v2 08/10] testsuite: Add C++ unwinding tests with Decimal Floating-Point
  2022-05-09 14:35 ` [PATCH 08/10] testsuite: Add C++ unwinding tests with Decimal Floating-Point Christophe Lyon
  2022-05-10  9:27   ` Richard Sandiford
@ 2022-05-13 16:35   ` Christophe Lyon
  2022-05-13 17:52   ` Christophe Lyon
  2 siblings, 0 replies; 33+ messages in thread
From: Christophe Lyon @ 2022-05-13 16:35 UTC (permalink / raw)
  To: gcc-patches

These tests exercise exception handling with Decimal Floating-Point
type.

dfp-1.C and dfp-2.C check that thrown objects of such types are
properly caught, whether when using C++ classes (decimalXX) or via GCC
mode attributes.

dfp-saves-aarch64.C checks that such objects are properly restored,
and has to use the mode attribute trick because objects of decimalXX
class type cannot be assigned to a register variable.

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

	gcc/testsuite/
	* g++.dg/eh/dfp-1.C: New test.
	* g++.dg/eh/dfp-2.C: New test.
	* g++.dg/eh/dfp-saves-aarch64.C: New test.
---
 gcc/testsuite/g++.dg/eh/dfp-1.C             | 54 +++++++++++++++++++++
 gcc/testsuite/g++.dg/eh/dfp-2.C             | 54 +++++++++++++++++++++
 gcc/testsuite/g++.dg/eh/dfp-saves-aarch64.C | 49 +++++++++++++++++++
 3 files changed, 157 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/eh/dfp-1.C
 create mode 100644 gcc/testsuite/g++.dg/eh/dfp-2.C
 create mode 100644 gcc/testsuite/g++.dg/eh/dfp-saves-aarch64.C

diff --git a/gcc/testsuite/g++.dg/eh/dfp-1.C b/gcc/testsuite/g++.dg/eh/dfp-1.C
new file mode 100644
index 00000000000..b0da13a4cc5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/eh/dfp-1.C
@@ -0,0 +1,54 @@
+// { dg-do run }
+// { dg-require-effective-target dfp }
+
+extern "C" void abort ();
+
+#include <decimal/decimal>
+
+using namespace std::decimal;
+
+int
+foo (double fp)
+{
+  if (fp < 32.0)
+    throw (decimal32)32;
+  if (fp < 64.0)
+    throw (decimal64)64;
+  if (fp < 128.0)
+    throw (decimal128)128;
+  return 0;
+}
+
+int bar (double fp)
+{
+  try
+    {
+      foo (fp);
+      abort ();
+    }
+  catch (decimal32 df)
+    {
+      if (df != (decimal32)32)
+	abort ();
+    }
+  catch (decimal64 dd)
+    {
+      if (dd != (decimal64)64)
+	abort ();
+    }
+  catch (decimal128 dl)
+    {
+      if (dl != (decimal128)128)
+	abort ();
+    }
+  return 0;
+}
+
+int
+main ()
+{
+  bar (10.0);
+  bar (20.0);
+  bar (100.0);
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/eh/dfp-2.C b/gcc/testsuite/g++.dg/eh/dfp-2.C
new file mode 100644
index 00000000000..aff0e03d1d9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/eh/dfp-2.C
@@ -0,0 +1,54 @@
+// { dg-do run }
+// { dg-require-effective-target dfp }
+
+extern "C" void abort ();
+
+typedef float dec32 __attribute__((mode(SD)));
+typedef float dec64 __attribute__((mode(DD)));
+typedef float dec128 __attribute__((mode(TD)));
+
+int
+foo (double fp)
+{
+  if (fp < 32.0)
+    throw (dec32)32;
+  if (fp < 64.0)
+    throw (dec64)64;
+  if (fp < 128.0)
+    throw (dec128)128;
+  return 0;
+}
+
+int bar (double fp)
+{
+  try
+    {
+      foo (fp);
+      abort ();
+    }
+  catch (dec32 df)
+    {
+      if (df != (dec32)32)
+	abort ();
+    }
+  catch (dec64 dd)
+    {
+      if (dd != (dec64)64)
+	abort ();
+    }
+  catch (dec128 dl)
+    {
+      if (dl != (dec128)128)
+	abort ();
+    }
+  return 0;
+}
+
+int
+main ()
+{
+  bar (10.0);
+  bar (20.0);
+  bar (100.0);
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/eh/dfp-saves-aarch64.C b/gcc/testsuite/g++.dg/eh/dfp-saves-aarch64.C
new file mode 100644
index 00000000000..79f6697dd10
--- /dev/null
+++ b/gcc/testsuite/g++.dg/eh/dfp-saves-aarch64.C
@@ -0,0 +1,49 @@
+// { dg-do run { target aarch64*-*-* } }
+// { dg-require-effective-target dfp }
+
+/* Test unwinding of AArch64 register saves.  */
+/* We cannot use #include <decimal/decimal> because it defines
+   decimal* types as classes, which we cannot be assigned to register
+   variables.  Hence the use the mode attribute trick.  */
+
+#ifdef __aarch64__
+
+typedef float dec64 __attribute__((mode(DD)));
+
+extern "C" void abort (void);
+extern "C" void exit (int);
+
+void
+foo (void)
+{
+  register dec64 v10 asm("v10") = 0;
+  register dec64 v11 asm("v11") = 1;
+  register dec64 v12 asm("v12") = 2;
+  register dec64 v13 asm("v13") = 3;
+  asm volatile ("" : "+w" (v10), "+w" (v11), "+w" (v12), "+w" (v13));
+  throw "";
+}
+
+int
+main (void)
+{
+  register dec64 v10 asm("v10") = 10;
+  register dec64 v11 asm("v11") = 11;
+  register dec64 v12 asm("v12") = 12;
+  register dec64 v13 asm("v13") = 13;
+  asm volatile ("" : "+w" (v10), "+w" (v11), "+w" (v12), "+w" (v13));
+  try {
+    foo ();
+  } catch (...) {
+    asm volatile ("" : "+w" (v10), "+w" (v11), "+w" (v12), "+w" (v13));
+    if (v10 != 10 || v11 != 11 || v12 != 12 || v13 != 13)
+      abort ();
+  }
+  exit (0);
+}
+#else
+int
+main (void)
+{
+}
+#endif
-- 
2.25.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v2 08/10] testsuite: Add C++ unwinding tests with Decimal Floating-Point
  2022-05-09 14:35 ` [PATCH 08/10] testsuite: Add C++ unwinding tests with Decimal Floating-Point Christophe Lyon
  2022-05-10  9:27   ` Richard Sandiford
  2022-05-13 16:35   ` [PATCH v2 " Christophe Lyon
@ 2022-05-13 17:52   ` Christophe Lyon
  2022-05-16 10:33     ` Richard Sandiford
  2 siblings, 1 reply; 33+ messages in thread
From: Christophe Lyon @ 2022-05-13 17:52 UTC (permalink / raw)
  To: gcc-patches

These tests exercise exception handling with Decimal Floating-Point
type.

dfp-1.C and dfp-2.C check that thrown objects of such types are
properly caught, whether when using C++ classes (decimalXX) or via GCC
mode attributes.

dfp-saves-aarch64.C checks that such objects are properly restored,
and has to use the mode attribute trick because objects of decimalXX
class type cannot be assigned to a register variable.

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

	gcc/testsuite/
	* g++.dg/eh/dfp-1.C: New test.
	* g++.dg/eh/dfp-2.C: New test.
	* g++.dg/eh/dfp-saves-aarch64.C: New test.
---
 gcc/testsuite/g++.dg/eh/dfp-1.C             | 54 +++++++++++++++++++++
 gcc/testsuite/g++.dg/eh/dfp-2.C             | 54 +++++++++++++++++++++
 gcc/testsuite/g++.dg/eh/dfp-saves-aarch64.C | 49 +++++++++++++++++++
 3 files changed, 157 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/eh/dfp-1.C
 create mode 100644 gcc/testsuite/g++.dg/eh/dfp-2.C
 create mode 100644 gcc/testsuite/g++.dg/eh/dfp-saves-aarch64.C

diff --git a/gcc/testsuite/g++.dg/eh/dfp-1.C b/gcc/testsuite/g++.dg/eh/dfp-1.C
new file mode 100644
index 00000000000..b0da13a4cc5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/eh/dfp-1.C
@@ -0,0 +1,54 @@
+// { dg-do run }
+// { dg-require-effective-target dfp }
+
+extern "C" void abort ();
+
+#include <decimal/decimal>
+
+using namespace std::decimal;
+
+int
+foo (double fp)
+{
+  if (fp < 32.0)
+    throw (decimal32)32;
+  if (fp < 64.0)
+    throw (decimal64)64;
+  if (fp < 128.0)
+    throw (decimal128)128;
+  return 0;
+}
+
+int bar (double fp)
+{
+  try
+    {
+      foo (fp);
+      abort ();
+    }
+  catch (decimal32 df)
+    {
+      if (df != (decimal32)32)
+	abort ();
+    }
+  catch (decimal64 dd)
+    {
+      if (dd != (decimal64)64)
+	abort ();
+    }
+  catch (decimal128 dl)
+    {
+      if (dl != (decimal128)128)
+	abort ();
+    }
+  return 0;
+}
+
+int
+main ()
+{
+  bar (10.0);
+  bar (20.0);
+  bar (100.0);
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/eh/dfp-2.C b/gcc/testsuite/g++.dg/eh/dfp-2.C
new file mode 100644
index 00000000000..aff0e03d1d9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/eh/dfp-2.C
@@ -0,0 +1,54 @@
+// { dg-do run }
+// { dg-require-effective-target dfp }
+
+extern "C" void abort ();
+
+typedef float dec32 __attribute__((mode(SD)));
+typedef float dec64 __attribute__((mode(DD)));
+typedef float dec128 __attribute__((mode(TD)));
+
+int
+foo (double fp)
+{
+  if (fp < 32.0)
+    throw (dec32)32;
+  if (fp < 64.0)
+    throw (dec64)64;
+  if (fp < 128.0)
+    throw (dec128)128;
+  return 0;
+}
+
+int bar (double fp)
+{
+  try
+    {
+      foo (fp);
+      abort ();
+    }
+  catch (dec32 df)
+    {
+      if (df != (dec32)32)
+	abort ();
+    }
+  catch (dec64 dd)
+    {
+      if (dd != (dec64)64)
+	abort ();
+    }
+  catch (dec128 dl)
+    {
+      if (dl != (dec128)128)
+	abort ();
+    }
+  return 0;
+}
+
+int
+main ()
+{
+  bar (10.0);
+  bar (20.0);
+  bar (100.0);
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/eh/dfp-saves-aarch64.C b/gcc/testsuite/g++.dg/eh/dfp-saves-aarch64.C
new file mode 100644
index 00000000000..06203410500
--- /dev/null
+++ b/gcc/testsuite/g++.dg/eh/dfp-saves-aarch64.C
@@ -0,0 +1,49 @@
+// { dg-do run { target aarch64*-*-* } }
+// { dg-require-effective-target dfp }
+
+/* Test unwinding of AArch64 register saves.  */
+/* We cannot use #include <decimal/decimal> because it defines
+   decimal* types as classes, which cannot be assigned to register
+   variables.  Hence the use the mode attribute trick.  */
+
+#ifdef __aarch64__
+
+typedef float dec64 __attribute__((mode(DD)));
+
+extern "C" void abort (void);
+extern "C" void exit (int);
+
+void
+foo (void)
+{
+  register dec64 v10 asm("v10") = 0;
+  register dec64 v11 asm("v11") = 1;
+  register dec64 v12 asm("v12") = 2;
+  register dec64 v13 asm("v13") = 3;
+  asm volatile ("" : "+w" (v10), "+w" (v11), "+w" (v12), "+w" (v13));
+  throw "";
+}
+
+int
+main (void)
+{
+  register dec64 v10 asm("v10") = 10;
+  register dec64 v11 asm("v11") = 11;
+  register dec64 v12 asm("v12") = 12;
+  register dec64 v13 asm("v13") = 13;
+  asm volatile ("" : "+w" (v10), "+w" (v11), "+w" (v12), "+w" (v13));
+  try {
+    foo ();
+  } catch (...) {
+    asm volatile ("" : "+w" (v10), "+w" (v11), "+w" (v12), "+w" (v13));
+    if (v10 != 10 || v11 != 11 || v12 != 12 || v13 != 13)
+      abort ();
+  }
+  exit (0);
+}
+#else
+int
+main (void)
+{
+}
+#endif
-- 
2.25.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v2 09/10] libgcc: Add support for HF mode (aka __fp16) in libbid
  2022-05-09 14:35 ` [PATCH 09/10] libgcc: Add support for HF mode (aka __fp16) in libbid Christophe Lyon
  2022-05-09 21:27   ` Joseph Myers
  2022-05-13 16:34   ` [PATCH v2 " Christophe Lyon
@ 2022-05-13 17:52   ` Christophe Lyon
  2022-05-13 18:23     ` Joseph Myers
  2 siblings, 1 reply; 33+ messages in thread
From: Christophe Lyon @ 2022-05-13 17:52 UTC (permalink / raw)
  To: gcc-patches

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              | 38 ++++++++++++
 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              | 38 ++++++++++++
 libgcc/config/libbid/_td_to_hf.c              | 38 ++++++++++++
 libgcc/config/libbid/bid_gcc_intrinsics.h     | 30 +++++++++-
 10 files changed, 358 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

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..5e58288391e
--- /dev/null
+++ b/libgcc/config/libbid/_dd_to_hf.c
@@ -0,0 +1,38 @@
+/* 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
+HFtype
+__bid_truncddhf (_Decimal64 x) {
+  HFtype res;
+  union decimal64 ux;
+
+  ux.d = x;
+  res = __bid64_to_binary32 (ux.i);
+  return (res);
+}
+#endif
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..e4e3125d49b
--- /dev/null
+++ b/libgcc/config/libbid/_sd_to_hf.c
@@ -0,0 +1,38 @@
+/* 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
+HFtype
+__bid_truncsdhf (_Decimal32 x) {
+  HFtype res;
+  union decimal32 ux;
+
+  ux.d = x;
+  res = __bid32_to_binary32 (ux.i);
+  return (res);
+}
+#endif
diff --git a/libgcc/config/libbid/_td_to_hf.c b/libgcc/config/libbid/_td_to_hf.c
new file mode 100644
index 00000000000..c4ebe586db0
--- /dev/null
+++ b/libgcc/config/libbid/_td_to_hf.c
@@ -0,0 +1,38 @@
+/* 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
+HFtype
+__bid_trunctdhf (_Decimal128 x) {
+  HFtype res;
+  union decimal128 ux;
+
+  ux.d = x;
+  res = __bid128_to_binary32 (ux.i);
+  return (res);
+}
+#endif
diff --git a/libgcc/config/libbid/bid_gcc_intrinsics.h b/libgcc/config/libbid/bid_gcc_intrinsics.h
index b0a23debc15..15c050764ac 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 _Float16
+#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);
-- 
2.25.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v2 09/10] libgcc: Add support for HF mode (aka __fp16) in libbid
  2022-05-13 17:52   ` Christophe Lyon
@ 2022-05-13 18:23     ` Joseph Myers
  2022-05-13 18:30       ` Christophe Lyon
  2022-05-16 13:47       ` [PATCH v3 09/10] libgcc: Add support for HF mode (aka _Float16) " Christophe Lyon
  0 siblings, 2 replies; 33+ messages in thread
From: Joseph Myers @ 2022-05-13 18:23 UTC (permalink / raw)
  To: Christophe Lyon; +Cc: gcc-patches

On Fri, 13 May 2022, Christophe Lyon via Gcc-patches wrote:

> diff --git a/gcc/testsuite/gcc.target/aarch64/convert-dfp-2.c b/gcc/testsuite/gcc.target/aarch64/convert-dfp-2.c

I still think the tests should run for x86 as well - that is, for any 
target supporting both DFP and _Float16 (with appropriate effective-target 
conditionals; only the scan-assembler tests need be specific to BID).

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v2 09/10] libgcc: Add support for HF mode (aka __fp16) in libbid
  2022-05-13 18:23     ` Joseph Myers
@ 2022-05-13 18:30       ` Christophe Lyon
  2022-05-16 13:47       ` [PATCH v3 09/10] libgcc: Add support for HF mode (aka _Float16) " Christophe Lyon
  1 sibling, 0 replies; 33+ messages in thread
From: Christophe Lyon @ 2022-05-13 18:30 UTC (permalink / raw)
  To: Joseph Myers; +Cc: gcc-patches



On 5/13/22 20:23, Joseph Myers wrote:
> On Fri, 13 May 2022, Christophe Lyon via Gcc-patches wrote:
> 
>> diff --git a/gcc/testsuite/gcc.target/aarch64/convert-dfp-2.c b/gcc/testsuite/gcc.target/aarch64/convert-dfp-2.c
> 
> I still think the tests should run for x86 as well - that is, for any
> target supporting both DFP and _Float16 (with appropriate effective-target
> conditionals; only the scan-assembler tests need be specific to BID).
> 
Yes, thanks, I shouldn't have rushed to send the updated patches before 
the end of the week :-(

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v2 08/10] testsuite: Add C++ unwinding tests with Decimal Floating-Point
  2022-05-13 17:52   ` Christophe Lyon
@ 2022-05-16 10:33     ` Richard Sandiford
  0 siblings, 0 replies; 33+ messages in thread
From: Richard Sandiford @ 2022-05-16 10:33 UTC (permalink / raw)
  To: Christophe Lyon via Gcc-patches

Christophe Lyon via Gcc-patches <gcc-patches@gcc.gnu.org> writes:
> These tests exercise exception handling with Decimal Floating-Point
> type.
>
> dfp-1.C and dfp-2.C check that thrown objects of such types are
> properly caught, whether when using C++ classes (decimalXX) or via GCC
> mode attributes.
>
> dfp-saves-aarch64.C checks that such objects are properly restored,
> and has to use the mode attribute trick because objects of decimalXX
> class type cannot be assigned to a register variable.
>
> 2022-05-03  Christophe Lyon  <christophe.lyon@arm.com>
>
> 	gcc/testsuite/
> 	* g++.dg/eh/dfp-1.C: New test.
> 	* g++.dg/eh/dfp-2.C: New test.
> 	* g++.dg/eh/dfp-saves-aarch64.C: New test.

OK, thanks.

Richard

> ---
>  gcc/testsuite/g++.dg/eh/dfp-1.C             | 54 +++++++++++++++++++++
>  gcc/testsuite/g++.dg/eh/dfp-2.C             | 54 +++++++++++++++++++++
>  gcc/testsuite/g++.dg/eh/dfp-saves-aarch64.C | 49 +++++++++++++++++++
>  3 files changed, 157 insertions(+)
>  create mode 100644 gcc/testsuite/g++.dg/eh/dfp-1.C
>  create mode 100644 gcc/testsuite/g++.dg/eh/dfp-2.C
>  create mode 100644 gcc/testsuite/g++.dg/eh/dfp-saves-aarch64.C
>
> diff --git a/gcc/testsuite/g++.dg/eh/dfp-1.C b/gcc/testsuite/g++.dg/eh/dfp-1.C
> new file mode 100644
> index 00000000000..b0da13a4cc5
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/eh/dfp-1.C
> @@ -0,0 +1,54 @@
> +// { dg-do run }
> +// { dg-require-effective-target dfp }
> +
> +extern "C" void abort ();
> +
> +#include <decimal/decimal>
> +
> +using namespace std::decimal;
> +
> +int
> +foo (double fp)
> +{
> +  if (fp < 32.0)
> +    throw (decimal32)32;
> +  if (fp < 64.0)
> +    throw (decimal64)64;
> +  if (fp < 128.0)
> +    throw (decimal128)128;
> +  return 0;
> +}
> +
> +int bar (double fp)
> +{
> +  try
> +    {
> +      foo (fp);
> +      abort ();
> +    }
> +  catch (decimal32 df)
> +    {
> +      if (df != (decimal32)32)
> +	abort ();
> +    }
> +  catch (decimal64 dd)
> +    {
> +      if (dd != (decimal64)64)
> +	abort ();
> +    }
> +  catch (decimal128 dl)
> +    {
> +      if (dl != (decimal128)128)
> +	abort ();
> +    }
> +  return 0;
> +}
> +
> +int
> +main ()
> +{
> +  bar (10.0);
> +  bar (20.0);
> +  bar (100.0);
> +  return 0;
> +}
> diff --git a/gcc/testsuite/g++.dg/eh/dfp-2.C b/gcc/testsuite/g++.dg/eh/dfp-2.C
> new file mode 100644
> index 00000000000..aff0e03d1d9
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/eh/dfp-2.C
> @@ -0,0 +1,54 @@
> +// { dg-do run }
> +// { dg-require-effective-target dfp }
> +
> +extern "C" void abort ();
> +
> +typedef float dec32 __attribute__((mode(SD)));
> +typedef float dec64 __attribute__((mode(DD)));
> +typedef float dec128 __attribute__((mode(TD)));
> +
> +int
> +foo (double fp)
> +{
> +  if (fp < 32.0)
> +    throw (dec32)32;
> +  if (fp < 64.0)
> +    throw (dec64)64;
> +  if (fp < 128.0)
> +    throw (dec128)128;
> +  return 0;
> +}
> +
> +int bar (double fp)
> +{
> +  try
> +    {
> +      foo (fp);
> +      abort ();
> +    }
> +  catch (dec32 df)
> +    {
> +      if (df != (dec32)32)
> +	abort ();
> +    }
> +  catch (dec64 dd)
> +    {
> +      if (dd != (dec64)64)
> +	abort ();
> +    }
> +  catch (dec128 dl)
> +    {
> +      if (dl != (dec128)128)
> +	abort ();
> +    }
> +  return 0;
> +}
> +
> +int
> +main ()
> +{
> +  bar (10.0);
> +  bar (20.0);
> +  bar (100.0);
> +  return 0;
> +}
> diff --git a/gcc/testsuite/g++.dg/eh/dfp-saves-aarch64.C b/gcc/testsuite/g++.dg/eh/dfp-saves-aarch64.C
> new file mode 100644
> index 00000000000..06203410500
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/eh/dfp-saves-aarch64.C
> @@ -0,0 +1,49 @@
> +// { dg-do run { target aarch64*-*-* } }
> +// { dg-require-effective-target dfp }
> +
> +/* Test unwinding of AArch64 register saves.  */
> +/* We cannot use #include <decimal/decimal> because it defines
> +   decimal* types as classes, which cannot be assigned to register
> +   variables.  Hence the use the mode attribute trick.  */
> +
> +#ifdef __aarch64__
> +
> +typedef float dec64 __attribute__((mode(DD)));
> +
> +extern "C" void abort (void);
> +extern "C" void exit (int);
> +
> +void
> +foo (void)
> +{
> +  register dec64 v10 asm("v10") = 0;
> +  register dec64 v11 asm("v11") = 1;
> +  register dec64 v12 asm("v12") = 2;
> +  register dec64 v13 asm("v13") = 3;
> +  asm volatile ("" : "+w" (v10), "+w" (v11), "+w" (v12), "+w" (v13));
> +  throw "";
> +}
> +
> +int
> +main (void)
> +{
> +  register dec64 v10 asm("v10") = 10;
> +  register dec64 v11 asm("v11") = 11;
> +  register dec64 v12 asm("v12") = 12;
> +  register dec64 v13 asm("v13") = 13;
> +  asm volatile ("" : "+w" (v10), "+w" (v11), "+w" (v12), "+w" (v13));
> +  try {
> +    foo ();
> +  } catch (...) {
> +    asm volatile ("" : "+w" (v10), "+w" (v11), "+w" (v12), "+w" (v13));
> +    if (v10 != 10 || v11 != 11 || v12 != 12 || v13 != 13)
> +      abort ();
> +  }
> +  exit (0);
> +}
> +#else
> +int
> +main (void)
> +{
> +}
> +#endif

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v2 02/10] aarch64: Add backend support for DFP
  2022-05-13 16:35     ` Richard Sandiford
@ 2022-05-16 12:17       ` Christophe Lyon
  0 siblings, 0 replies; 33+ messages in thread
From: Christophe Lyon @ 2022-05-16 12:17 UTC (permalink / raw)
  To: Christophe Lyon via Gcc-patches, richard.sandiford

[-- Attachment #1: Type: text/plain, Size: 1745 bytes --]



On 5/13/22 18:35, Richard Sandiford wrote:
> Christophe Lyon via Gcc-patches <gcc-patches@gcc.gnu.org> writes:
>> @@ -19352,7 +19363,9 @@ aarch64_legitimate_constant_p (machine_mode mode, rtx x)
>>   {
>>     /* Support CSE and rematerialization of common constants.  */
>>     if (CONST_INT_P (x)
>> -      || (CONST_DOUBLE_P (x) && GET_MODE_CLASS (mode) == MODE_FLOAT))
>> +      || (CONST_DOUBLE_P (x)
>> +	  && (GET_MODE_CLASS (mode) == MODE_FLOAT
>> +	      || GET_MODE_CLASS (mode) == MODE_DECIMAL_FLOAT)))
>>       return true;
>>   
>>     /* Only accept variable-length vector constants if they can be
> 
> I'd prefer to remove the mode check here, rather than extend it.
> If we see a CONST_DOUBLE that doesn't have a scalar float mode
> then something has gone wrong.  (No need to assert for that though.
> It's a fundamental assumption when TARGET_SUPPORTS_WIDE_INT.)
> 
> For consistency…
> 
>> @@ -11114,11 +11116,16 @@ aarch64_float_const_rtx_p (rtx x)
>>     return false;
>>   }
>>   
>> -/* Return TRUE if rtx X is immediate constant 0.0 */
>> +/* Return TRUE if rtx X is immediate constant 0.0 (but not in Decimal
>> +   Floating Point).  */
>>   bool
>>   aarch64_float_const_zero_rtx_p (rtx x)
>>   {
>> -  if (GET_MODE (x) == VOIDmode)
>> +  if (GET_MODE (x) == VOIDmode
>> +      /* 0.0 in Decimal Floating Point cannot be represented by #0 or
>> +	 zr as our callers expect, so no need to check the actual
>> +	 value if X is of Decimal Floating Point type.  */
>> +      || GET_MODE_CLASS (GET_MODE (x)) == MODE_DECIMAL_FLOAT)
> 
> …it would be good to drop the VOIDmode check here at the same time.
> 
> OK with those changes, thanks.
> 

Thanks, here is what I will commit once patch 9/10 is approved.

> Richard

[-- Attachment #2: v3-0002-aarch64-Add-backend-support-for-DFP.patch --]
[-- Type: text/x-patch, Size: 19046 bytes --]

From 8dbef6d38700b252551309bfd657c0402a7e339a Mon Sep 17 00:00:00 2001
From: Christophe Lyon <christophe.lyon@arm.com>
Date: Fri, 11 Mar 2022 16:21:02 +0000
Subject: [PATCH v3 02/10] aarch64: Add backend support for DFP

This patch updates the aarch64 backend as needed to support DFP modes
(SD, DD and TD).

Changes	v1->v2:

* Drop	support	for DFP	modes in
  aarch64_gen_{load||store}[wb]_pair as these are only used in
  prologue/epilogue where DFP modes are not used.  Drop	the
  changes to the corresponding patterns in aarch64.md, and
  useless GPF_PAIR iterator.

* In aarch64_reinterpret_float_as_int, handle DDmode the same way
  as DFmode (needed in case the representation of the
  floating-point value can be loaded using mov/movk.

* In aarch64_float_const_zero_rtx_p, reject constants with DFP
  mode: when X is zero, the callers want to emit either '0' or
  'zr' depending on the context, which is not the way 0.0 is
  represented in DFP mode (in particular fmov d0, #0 is not right
  for DFP).

* In aarch64_legitimate_constant_p, accept DFP

2022-03-31  Christophe Lyon  <christophe.lyon@arm.com>

	gcc/
	* config/aarch64/aarch64.cc
	(aarch64_split_128bit_move): Handle DFP modes.
	(aarch64_mode_valid_for_sched_fusion_p): Likewise.
	(aarch64_classify_address): Likewise.
	(aarch64_legitimize_address_displacement): Likewise.
	(aarch64_reinterpret_float_as_int): Likewise.
	(aarch64_float_const_zero_rtx_p): Likewise.
	(aarch64_can_const_movi_rtx_p): Likewise.
	(aarch64_anchor_offset): Likewise.
	(aarch64_secondary_reload): Likewise.
	(aarch64_rtx_costs): Likewise.
	(aarch64_legitimate_constant_p): Likewise.
	(aarch64_gimplify_va_arg_expr): Likewise.
	(aapcs_vfp_sub_candidate): Likewise.
	(aarch64_vfp_is_call_or_return_candidate): Likewise.
	(aarch64_output_scalar_simd_mov_immediate): Likewise.
	(aarch64_gen_adjusted_ldpstp): Likewise.
	(aarch64_scalar_mode_supported_p): Accept DFP modes if enabled.
	* config/aarch64/aarch64.md
	(movsf_aarch64): Use SFD iterator and rename into
	mov<mode>_aarch64.
	(movdf_aarch64): Use DFD iterator and rename into
	mov<mode>_aarch64.
	(movtf_aarch64): Use TFD iterator and rename into
	mov<mode>_aarch64.
	(split pattern for move TF mode): Use TFD iterator.
	* config/aarch64/aarch64/iterators.md
	(GPF_TF_F16_MOV): Add DFP modes.
	(SFD, DFD, TFD): New iterators.
	(GPF_TF): Add DFP modes.
	(TX, DX, DX2): Likewise.
---
 gcc/config/aarch64/aarch64.cc   | 82 ++++++++++++++++++++++-----------
 gcc/config/aarch64/aarch64.md   | 34 +++++++-------
 gcc/config/aarch64/iterators.md | 24 +++++++---
 3 files changed, 89 insertions(+), 51 deletions(-)

diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index bd855758778..9489c2fcaf9 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -4828,7 +4828,7 @@ aarch64_split_128bit_move (rtx dst, rtx src)
 
   machine_mode mode = GET_MODE (dst);
 
-  gcc_assert (mode == TImode || mode == TFmode);
+  gcc_assert (mode == TImode || mode == TFmode || mode == TDmode);
   gcc_assert (!(side_effects_p (src) || side_effects_p (dst)));
   gcc_assert (mode == GET_MODE (src) || GET_MODE (src) == VOIDmode);
 
@@ -10568,6 +10568,7 @@ aarch64_mode_valid_for_sched_fusion_p (machine_mode mode)
 {
   return mode == SImode || mode == DImode
 	 || mode == SFmode || mode == DFmode
+	 || mode == SDmode || mode == DDmode
 	 || (aarch64_vector_mode_supported_p (mode)
 	     && (known_eq (GET_MODE_SIZE (mode), 8)
 		 || (known_eq (GET_MODE_SIZE (mode), 16)
@@ -10610,12 +10611,13 @@ aarch64_classify_address (struct aarch64_address_info *info,
   vec_flags &= ~VEC_PARTIAL;
 
   /* On BE, we use load/store pair for all large int mode load/stores.
-     TI/TFmode may also use a load/store pair.  */
+     TI/TF/TDmode may also use a load/store pair.  */
   bool advsimd_struct_p = (vec_flags == (VEC_ADVSIMD | VEC_STRUCT));
   bool load_store_pair_p = (type == ADDR_QUERY_LDP_STP
 			    || type == ADDR_QUERY_LDP_STP_N
 			    || mode == TImode
 			    || mode == TFmode
+			    || mode == TDmode
 			    || (BYTES_BIG_ENDIAN && advsimd_struct_p));
   /* If we are dealing with ADDR_QUERY_LDP_STP_N that means the incoming mode
      corresponds to the actual size of the memory being loaded/stored and the
@@ -10689,7 +10691,7 @@ aarch64_classify_address (struct aarch64_address_info *info,
 	  info->offset = op1;
 	  info->const_offset = offset;
 
-	  /* TImode and TFmode values are allowed in both pairs of X
+	  /* TImode, TFmode and TDmode values are allowed in both pairs of X
 	     registers and individual Q registers.  The available
 	     address modes are:
 	     X,X: 7-bit signed scaled offset
@@ -10698,7 +10700,7 @@ aarch64_classify_address (struct aarch64_address_info *info,
 	     When performing the check for pairs of X registers i.e.  LDP/STP
 	     pass down DImode since that is the natural size of the LDP/STP
 	     instruction memory accesses.  */
-	  if (mode == TImode || mode == TFmode)
+	  if (mode == TImode || mode == TFmode || mode == TDmode)
 	    return (aarch64_offset_7bit_signed_scaled_p (DImode, offset)
 		    && (aarch64_offset_9bit_signed_unscaled_p (mode, offset)
 			|| offset_12bit_unsigned_scaled_p (mode, offset)));
@@ -10821,14 +10823,14 @@ aarch64_classify_address (struct aarch64_address_info *info,
 	  info->offset = XEXP (XEXP (x, 1), 1);
 	  info->const_offset = offset;
 
-	  /* TImode and TFmode values are allowed in both pairs of X
+	  /* TImode, TFmode and TDmode values are allowed in both pairs of X
 	     registers and individual Q registers.  The available
 	     address modes are:
 	     X,X: 7-bit signed scaled offset
 	     Q:   9-bit signed offset
 	     We conservatively require an offset representable in either mode.
 	   */
-	  if (mode == TImode || mode == TFmode)
+	  if (mode == TImode || mode == TFmode || mode == TDmode)
 	    return (aarch64_offset_7bit_signed_scaled_p (mode, offset)
 		    && aarch64_offset_9bit_signed_unscaled_p (mode, offset));
 
@@ -10990,9 +10992,9 @@ aarch64_legitimize_address_displacement (rtx *offset1, rtx *offset2,
 	 offset.  Use 4KB range for 1- and 2-byte accesses and a 16KB
 	 range otherwise to increase opportunities for sharing the base
 	 address of different sizes.  Unaligned accesses use the signed
-	 9-bit range, TImode/TFmode use the intersection of signed
+	 9-bit range, TImode/TFmode/TDmode use the intersection of signed
 	 scaled 7-bit and signed 9-bit offset.  */
-      if (mode == TImode || mode == TFmode)
+      if (mode == TImode || mode == TFmode || mode == TDmode)
 	second_offset = ((const_offset + 0x100) & 0x1f8) - 0x100;
       else if ((const_offset & (size - 1)) != 0)
 	second_offset = ((const_offset + 0x100) & 0x1ff) - 0x100;
@@ -11073,7 +11075,7 @@ aarch64_reinterpret_float_as_int (rtx value, unsigned HOST_WIDE_INT *intval)
 		  CONST_DOUBLE_REAL_VALUE (value),
 		  REAL_MODE_FORMAT (mode));
 
-  if (mode == DFmode)
+  if (mode == DFmode || mode == DDmode)
     {
       int order = BYTES_BIG_ENDIAN ? 1 : 0;
       ival = zext_hwi (res[order], 32);
@@ -11114,11 +11116,15 @@ aarch64_float_const_rtx_p (rtx x)
   return false;
 }
 
-/* Return TRUE if rtx X is immediate constant 0.0 */
+/* Return TRUE if rtx X is immediate constant 0.0 (but not in Decimal
+   Floating Point).  */
 bool
 aarch64_float_const_zero_rtx_p (rtx x)
 {
-  if (GET_MODE (x) == VOIDmode)
+  /* 0.0 in Decimal Floating Point cannot be represented by #0 or
+     zr as our callers expect, so no need to check the actual
+     value if X is of Decimal Floating Point type.  */
+  if (GET_MODE_CLASS (GET_MODE (x)) == MODE_DECIMAL_FLOAT)
     return false;
 
   if (REAL_VALUE_MINUS_ZERO (*CONST_DOUBLE_REAL_VALUE (x)))
@@ -11156,7 +11162,7 @@ aarch64_can_const_movi_rtx_p (rtx x, machine_mode mode)
   else
     return false;
 
-   /* use a 64 bit mode for everything except for DI/DF mode, where we use
+   /* use a 64 bit mode for everything except for DI/DF/DD mode, where we use
      a 128 bit vector mode.  */
   int width = GET_MODE_BITSIZE (imode) == 64 ? 128 : 64;
 
@@ -12356,7 +12362,7 @@ aarch64_anchor_offset (HOST_WIDE_INT offset, HOST_WIDE_INT size,
   if (IN_RANGE (offset, -256, 0))
     return 0;
 
-  if (mode == TImode || mode == TFmode)
+  if (mode == TImode || mode == TFmode || mode == TDmode)
     return (offset + 0x100) & ~0x1ff;
 
   /* Use 12-bit offset by access size.  */
@@ -12465,7 +12471,9 @@ aarch64_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x,
 
   /* Without the TARGET_SIMD instructions we cannot move a Q register
      to a Q register directly.  We need a scratch.  */
-  if (REG_P (x) && (mode == TFmode || mode == TImode) && mode == GET_MODE (x)
+  if (REG_P (x)
+      && (mode == TFmode || mode == TImode || mode == TDmode)
+      && mode == GET_MODE (x)
       && FP_REGNUM_P (REGNO (x)) && !TARGET_SIMD
       && reg_class_subset_p (rclass, FP_REGS))
     {
@@ -12473,14 +12481,16 @@ aarch64_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x,
       return NO_REGS;
     }
 
-  /* A TFmode or TImode memory access should be handled via an FP_REGS
+  /* A TFmode, TImode or TDmode memory access should be handled via an FP_REGS
      because AArch64 has richer addressing modes for LDR/STR instructions
      than LDP/STP instructions.  */
   if (TARGET_FLOAT && rclass == GENERAL_REGS
       && known_eq (GET_MODE_SIZE (mode), 16) && MEM_P (x))
     return FP_REGS;
 
-  if (rclass == FP_REGS && (mode == TImode || mode == TFmode) && CONSTANT_P(x))
+  if (rclass == FP_REGS
+      && (mode == TImode || mode == TFmode || mode == TDmode)
+      && CONSTANT_P(x))
       return GENERAL_REGS;
 
   return NO_REGS;
@@ -13611,9 +13621,9 @@ aarch64_rtx_costs (rtx x, machine_mode mode, int outer ATTRIBUTE_UNUSED,
 		*cost += extra_cost->ldst.storev;
 	      else if (GET_MODE_CLASS (mode) == MODE_INT)
 		*cost += extra_cost->ldst.store;
-	      else if (mode == SFmode)
+	      else if (mode == SFmode || mode == SDmode)
 		*cost += extra_cost->ldst.storef;
-	      else if (mode == DFmode)
+	      else if (mode == DFmode || mode == DDmode)
 		*cost += extra_cost->ldst.stored;
 
 	      *cost +=
@@ -13737,11 +13747,11 @@ aarch64_rtx_costs (rtx x, machine_mode mode, int outer ATTRIBUTE_UNUSED,
 	  /* mov[df,sf]_aarch64.  */
 	  if (aarch64_float_const_representable_p (x))
 	    /* FMOV (scalar immediate).  */
-	    *cost += extra_cost->fp[mode == DFmode].fpconst;
+	    *cost += extra_cost->fp[mode == DFmode || mode == DDmode].fpconst;
 	  else if (!aarch64_float_const_zero_rtx_p (x))
 	    {
 	      /* This will be a load from memory.  */
-	      if (mode == DFmode)
+	      if (mode == DFmode || mode == DDmode)
 		*cost += extra_cost->ldst.loadd;
 	      else
 		*cost += extra_cost->ldst.loadf;
@@ -13767,9 +13777,9 @@ aarch64_rtx_costs (rtx x, machine_mode mode, int outer ATTRIBUTE_UNUSED,
 	    *cost += extra_cost->ldst.loadv;
 	  else if (GET_MODE_CLASS (mode) == MODE_INT)
 	    *cost += extra_cost->ldst.load;
-	  else if (mode == SFmode)
+	  else if (mode == SFmode || mode == SDmode)
 	    *cost += extra_cost->ldst.loadf;
-	  else if (mode == DFmode)
+	  else if (mode == DFmode || mode == DDmode)
 	    *cost += extra_cost->ldst.loadd;
 
 	  *cost +=
@@ -19352,7 +19362,7 @@ aarch64_legitimate_constant_p (machine_mode mode, rtx x)
 {
   /* Support CSE and rematerialization of common constants.  */
   if (CONST_INT_P (x)
-      || (CONST_DOUBLE_P (x) && GET_MODE_CLASS (mode) == MODE_FLOAT))
+      || CONST_DOUBLE_P (x))
     return true;
 
   /* Only accept variable-length vector constants if they can be
@@ -19795,6 +19805,18 @@ aarch64_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
 	  field_t = long_double_type_node;
 	  field_ptr_t = long_double_ptr_type_node;
 	  break;
+	case SDmode:
+	  field_t = dfloat32_type_node;
+	  field_ptr_t = build_pointer_type (dfloat32_type_node);
+	  break;
+	case DDmode:
+	  field_t = dfloat64_type_node;
+	  field_ptr_t = build_pointer_type (dfloat64_type_node);
+	  break;
+	case TDmode:
+	  field_t = dfloat128_type_node;
+	  field_ptr_t = build_pointer_type (dfloat128_type_node);
+	  break;
 	case E_HFmode:
 	  field_t = aarch64_fp16_type_node;
 	  field_ptr_t = aarch64_fp16_ptr_type_node;
@@ -20046,7 +20068,8 @@ aapcs_vfp_sub_candidate (const_tree type, machine_mode *modep,
     case REAL_TYPE:
       mode = TYPE_MODE (type);
       if (mode != DFmode && mode != SFmode
-	  && mode != TFmode && mode != HFmode)
+	  && mode != TFmode && mode != HFmode
+	  && mode != SDmode && mode != DDmode && mode != TDmode)
 	return -1;
 
       if (*modep == VOIDmode)
@@ -20362,7 +20385,9 @@ aarch64_vfp_is_call_or_return_candidate (machine_mode mode,
   machine_mode new_mode = VOIDmode;
   bool composite_p = aarch64_composite_type_p (type, mode);
 
-  if ((!composite_p && GET_MODE_CLASS (mode) == MODE_FLOAT)
+  if ((!composite_p
+       && (GET_MODE_CLASS (mode) == MODE_FLOAT
+	   || GET_MODE_CLASS (mode) == MODE_DECIMAL_FLOAT))
       || aarch64_short_vector_p (type, mode))
     {
       *count = 1;
@@ -23264,7 +23289,7 @@ aarch64_output_scalar_simd_mov_immediate (rtx immediate, scalar_int_mode mode)
     }
 
   machine_mode vmode;
-  /* use a 64 bit mode for everything except for DI/DF mode, where we use
+  /* use a 64 bit mode for everything except for DI/DF/DD mode, where we use
      a 128 bit vector mode.  */
   int width = GET_MODE_BITSIZE (mode) == 64 ? 128 : 64;
 
@@ -26082,7 +26107,7 @@ aarch64_gen_adjusted_ldpstp (rtx *operands, bool load,
     base_off = (off_val_1 + off_val_3) / 2;
   else
     /* However, due to issues with negative LDP/STP offset generation for
-       larger modes, for DF, DI and vector modes. we must not use negative
+       larger modes, for DF, DD, DI and vector modes. we must not use negative
        addresses smaller than 9 signed unadjusted bits can store.  This
        provides the most range in this case.  */
     base_off = off_val_1;
@@ -26360,6 +26385,9 @@ aarch64_libgcc_floating_mode_supported_p (scalar_float_mode mode)
 static bool
 aarch64_scalar_mode_supported_p (scalar_mode mode)
 {
+  if (DECIMAL_FLOAT_MODE_P (mode))
+    return default_decimal_float_supported_p ();
+
   return (mode == HFmode
 	  ? true
 	  : default_scalar_mode_supported_p (mode));
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index f5c635938ad..2ac8d564762 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -1477,11 +1477,11 @@ (define_insn "*mov<mode>_aarch64"
    (set_attr "arch" "simd,fp16,simd,simd,simd,fp16,simd,*,*,*,*,*")]
 )
 
-(define_insn "*movsf_aarch64"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=w,w  ,?r,w,w  ,w  ,w,m,r,m ,r,r")
-	(match_operand:SF 1 "general_operand"      "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r,M"))]
-  "TARGET_FLOAT && (register_operand (operands[0], SFmode)
-    || aarch64_reg_or_fp_zero (operands[1], SFmode))"
+(define_insn "*mov<mode>_aarch64"
+  [(set (match_operand:SFD 0 "nonimmediate_operand" "=w,w  ,?r,w,w  ,w  ,w,m,r,m ,r,r")
+	(match_operand:SFD 1 "general_operand"      "Y ,?rY, w,w,Ufc,Uvi,m,w,m,rY,r,M"))]
+  "TARGET_FLOAT && (register_operand (operands[0], <MODE>mode)
+    || aarch64_reg_or_fp_zero (operands[1], <MODE>mode))"
   "@
    movi\\t%0.2s, #0
    fmov\\t%s0, %w1
@@ -1501,11 +1501,11 @@ (define_insn "*movsf_aarch64"
    (set_attr "arch" "simd,*,*,*,*,simd,*,*,*,*,*,*")]
 )
 
-(define_insn "*movdf_aarch64"
-  [(set (match_operand:DF 0 "nonimmediate_operand" "=w, w  ,?r,w,w  ,w  ,w,m,r,m ,r,r")
-	(match_operand:DF 1 "general_operand"      "Y , ?rY, w,w,Ufc,Uvi,m,w,m,rY,r,N"))]
-  "TARGET_FLOAT && (register_operand (operands[0], DFmode)
-    || aarch64_reg_or_fp_zero (operands[1], DFmode))"
+(define_insn "*mov<mode>_aarch64"
+  [(set (match_operand:DFD 0 "nonimmediate_operand" "=w, w  ,?r,w,w  ,w  ,w,m,r,m ,r,r")
+	(match_operand:DFD 1 "general_operand"      "Y , ?rY, w,w,Ufc,Uvi,m,w,m,rY,r,N"))]
+  "TARGET_FLOAT && (register_operand (operands[0], <MODE>mode)
+    || aarch64_reg_or_fp_zero (operands[1], <MODE>mode))"
   "@
    movi\\t%d0, #0
    fmov\\t%d0, %x1
@@ -1545,13 +1545,13 @@ (define_split
   }
 )
 
-(define_insn "*movtf_aarch64"
-  [(set (match_operand:TF 0
+(define_insn "*mov<mode>_aarch64"
+  [(set (match_operand:TFD 0
 	 "nonimmediate_operand" "=w,?r ,w ,?r,w,?w,w,m,?r,m ,m")
-	(match_operand:TF 1
+	(match_operand:TFD 1
 	 "general_operand"      " w,?rY,?r,w ,Y,Y ,m,w,m ,?r,Y"))]
-  "TARGET_FLOAT && (register_operand (operands[0], TFmode)
-    || aarch64_reg_or_fp_zero (operands[1], TFmode))"
+  "TARGET_FLOAT && (register_operand (operands[0], <MODE>mode)
+    || aarch64_reg_or_fp_zero (operands[1], <MODE>mode))"
   "@
    mov\\t%0.16b, %1.16b
    #
@@ -1571,8 +1571,8 @@ (define_insn "*movtf_aarch64"
 )
 
 (define_split
-   [(set (match_operand:TF 0 "register_operand" "")
-	 (match_operand:TF 1 "nonmemory_operand" ""))]
+   [(set (match_operand:TFD 0 "register_operand" "")
+	 (match_operand:TFD 1 "nonmemory_operand" ""))]
   "reload_completed && aarch64_split_128bit_move_p (operands[0], operands[1])"
   [(const_int 0)]
   {
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index 88af964de7e..1c1048368f0 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -64,14 +64,24 @@ (define_mode_iterator GPF_HF [HF SF DF])
 (define_mode_iterator HFBF [HF BF])
 
 ;; Iterator for all scalar floating point modes suitable for moving, including
-;; special BF type (HF, SF, DF, TF and BF)
-(define_mode_iterator GPF_TF_F16_MOV [HF BF SF DF TF])
+;; special BF type and decimal floating point types (HF, SF, DF, TF, BF,
+;; SD, DD and TD)
+(define_mode_iterator GPF_TF_F16_MOV [HF BF SF DF TF SD DD TD])
+
+;; Iterator for scalar 32bit fp modes (SF, SD)
+(define_mode_iterator SFD [SD SF])
+
+;; Iterator for scalar 64bit fp modes (DF, DD)
+(define_mode_iterator DFD [DD DF])
+
+;; Iterator for scalar 128bit fp modes (TF, TD)
+(define_mode_iterator TFD [TD TF])
 
 ;; Double vector modes.
 (define_mode_iterator VDF [V2SF V4HF])
 
-;; Iterator for all scalar floating point modes (SF, DF and TF)
-(define_mode_iterator GPF_TF [SF DF TF])
+;; Iterator for all scalar floating point modes (SF, DF, TF, SD, DD, and TD)
+(define_mode_iterator GPF_TF [SF DF TF SD DD TD])
 
 ;; Integer Advanced SIMD modes.
 (define_mode_iterator VDQ_I [V8QI V16QI V4HI V8HI V2SI V4SI V2DI])
@@ -298,7 +308,7 @@ (define_mode_iterator VB [V8QI V16QI])
 ;; 2 and 4 lane SI modes.
 (define_mode_iterator VS [V2SI V4SI])
 
-(define_mode_iterator TX [TI TF])
+(define_mode_iterator TX [TI TF TD])
 
 ;; Advanced SIMD opaque structure modes.
 (define_mode_iterator VSTRUCT [OI CI XI])
@@ -400,10 +410,10 @@ (define_mode_iterator VSTRUCT_QD [V2x8QI V2x4HI V2x2SI V2x1DI
 				  V4x8HF V4x4SF V4x2DF V4x8BF])
 
 ;; Double scalar modes
-(define_mode_iterator DX [DI DF])
+(define_mode_iterator DX [DI DF DD])
 
 ;; Duplicate of the above
-(define_mode_iterator DX2 [DI DF])
+(define_mode_iterator DX2 [DI DF DD])
 
 ;; Single scalar modes
 (define_mode_iterator SX [SI SF])
-- 
2.25.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v3 09/10] libgcc: Add support for HF mode (aka _Float16) in libbid
  2022-05-13 18:23     ` Joseph Myers
  2022-05-13 18:30       ` Christophe Lyon
@ 2022-05-16 13:47       ` Christophe Lyon
  2022-05-19 13:03         ` Christophe Lyon
  1 sibling, 1 reply; 33+ messages in thread
From: Christophe Lyon @ 2022-05-16 13:47 UTC (permalink / raw)
  To: gcc-patches

This patch adds support for trunc and extend operations between HF
mode (_Float16) 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 _Float16
and _Decimal* formats.

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

Tested on aarch64 and x86_86. The number of symbol matches in the
testcases includes the .global XXX to avoid having to match different
call instructions for different targets.

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.dg/torture/convert-dfp-2.c: New test.
	* gcc.dg/torture/convert-dfp.c: New test.
---
 gcc/testsuite/gcc.dg/torture/convert-dfp-2.c | 45 ++++++++++++++
 gcc/testsuite/gcc.dg/torture/convert-dfp.c   | 63 ++++++++++++++++++++
 libgcc/Makefile.in                           |  9 ++-
 libgcc/config/libbid/_dd_to_hf.c             | 38 ++++++++++++
 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             | 38 ++++++++++++
 libgcc/config/libbid/_td_to_hf.c             | 38 ++++++++++++
 libgcc/config/libbid/bid_gcc_intrinsics.h    | 30 +++++++++-
 10 files changed, 364 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/torture/convert-dfp-2.c
 create mode 100644 gcc/testsuite/gcc.dg/torture/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

diff --git a/gcc/testsuite/gcc.dg/torture/convert-dfp-2.c b/gcc/testsuite/gcc.dg/torture/convert-dfp-2.c
new file mode 100644
index 00000000000..3e4ecb57ba6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/convert-dfp-2.c
@@ -0,0 +1,45 @@
+/* { dg-do run } */
+/* { dg-require-effective-target float16_runtime } */
+/* { dg-require-effective-target dfprt } */
+/* { dg-options "-save-temps" } */
+/* { dg-add-options float16 } */
+
+/* Test conversions from DFP to smaller types.  */
+
+_Decimal32 var32;
+_Decimal64 var64;
+_Decimal128 var128;
+_Float16 var16;
+
+void __attribute__ ((__noinline__)) foo32 (_Decimal32 param32)
+{
+  var16 = param32;
+}
+
+void __attribute__ ((__noinline__)) foo64 (_Decimal64 param64)
+{
+  var16 = param64;
+  var32 = param64;
+}
+
+void __attribute__ ((__noinline__)) foo128 (_Decimal128 param128)
+{
+  var16 = param128;
+  var32 = param128;
+  var64 = param128;
+}
+
+int main ()
+{
+  foo32 (var32);
+  foo64 (var64);
+  foo128 (var128);
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times {\t__bid_truncsdhf} 2 { target { dfp_bid } } } } */
+/* { dg-final { scan-assembler-times {\t__bid_truncddhf} 2 { target { dfp_bid } } } } */
+/* { dg-final { scan-assembler-times {\t__bid_truncddsd2} 2 { target { dfp_bid } } } } */
+/* { dg-final { scan-assembler-times {\t__bid_trunctdhf} 2 { target { dfp_bid } } } } */
+/* { dg-final { scan-assembler-times {\t__bid_trunctdsd2} 2 { target { dfp_bid } } } } */
+/* { dg-final { scan-assembler-times {\t__bid_trunctddd2} 2 { target { dfp_bid } } } } */
diff --git a/gcc/testsuite/gcc.dg/torture/convert-dfp.c b/gcc/testsuite/gcc.dg/torture/convert-dfp.c
new file mode 100644
index 00000000000..ec136896ca7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/convert-dfp.c
@@ -0,0 +1,63 @@
+/* { dg-do run } */
+/* { dg-require-effective-target float16_runtime } */
+/* { dg-require-effective-target dfprt } */
+/* { dg-options "-save-temps" } */
+/* { dg-add-options float16 } */
+
+/* Test conversions to/from DFP values.  */
+
+extern void abort ();
+
+_Decimal32 var32 = 1.2df;
+
+int __attribute__ ((__noinline__)) foo32 (_Decimal32 param32, _Decimal64 param64, _Decimal128 param128, _Float16 param16)
+{
+  return (param32 == var32)
+    + (param64 == var32)
+    + (param128 == var32)
+    /* Small enough relative difference?  */
+    + ((((_Decimal32)param16 - var32) / var32) < 0.002df);
+}
+
+_Decimal64 var64 = 1.2dd;
+
+int __attribute__ ((__noinline__)) foo64 (_Decimal32 param32, _Decimal64 param64, _Decimal128 param128, _Float16 param16)
+{
+  return (param32 == var64)
+    + (param64 == var64)
+    + (param128 == var64)
+    /* Small enough relative difference?  */
+    + ((((_Decimal64)param16 - var64) / var64) < 0.002dd);
+}
+
+_Decimal128 var128 = 1.2dl;
+
+int __attribute__ ((__noinline__)) foo128 (_Decimal32 param32, _Decimal64 param64, _Decimal128 param128, _Float16 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, (_Float16)1.2) != 4)
+    abort ();
+
+  if (foo64 (1.2df, 1.2dd, 1.2dl, (_Float16)1.2) != 4)
+    abort ();
+
+  if (foo128 (1.2df, 1.2dd, 1.2dl, (_Float16)1.2) != 4)
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-times {\t__bid_extendsddd2} 3 { target { dfp_bid } } } } */
+/* { dg-final { scan-assembler-times {\t__bid_extendsdtd2} 3 { target { dfp_bid } } } } */
+/* { dg-final { scan-assembler-times {\t__bid_extendddtd2} 3 { target { dfp_bid } } } } */
+/* { dg-final { scan-assembler-times {\t__bid_extendhfsd} 2 { target { dfp_bid } } } } */
+/* { dg-final { scan-assembler-times {\t__bid_extendhfdd} 2 { target { dfp_bid } } } } */
+/* { dg-final { scan-assembler-times {\t__bid_extendhftd} 2 { target { dfp_bid } } } } */
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..5e58288391e
--- /dev/null
+++ b/libgcc/config/libbid/_dd_to_hf.c
@@ -0,0 +1,38 @@
+/* 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
+HFtype
+__bid_truncddhf (_Decimal64 x) {
+  HFtype res;
+  union decimal64 ux;
+
+  ux.d = x;
+  res = __bid64_to_binary32 (ux.i);
+  return (res);
+}
+#endif
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..e4e3125d49b
--- /dev/null
+++ b/libgcc/config/libbid/_sd_to_hf.c
@@ -0,0 +1,38 @@
+/* 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
+HFtype
+__bid_truncsdhf (_Decimal32 x) {
+  HFtype res;
+  union decimal32 ux;
+
+  ux.d = x;
+  res = __bid32_to_binary32 (ux.i);
+  return (res);
+}
+#endif
diff --git a/libgcc/config/libbid/_td_to_hf.c b/libgcc/config/libbid/_td_to_hf.c
new file mode 100644
index 00000000000..c4ebe586db0
--- /dev/null
+++ b/libgcc/config/libbid/_td_to_hf.c
@@ -0,0 +1,38 @@
+/* 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
+HFtype
+__bid_trunctdhf (_Decimal128 x) {
+  HFtype res;
+  union decimal128 ux;
+
+  ux.d = x;
+  res = __bid128_to_binary32 (ux.i);
+  return (res);
+}
+#endif
diff --git a/libgcc/config/libbid/bid_gcc_intrinsics.h b/libgcc/config/libbid/bid_gcc_intrinsics.h
index b0a23debc15..15c050764ac 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 _Float16
+#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);
-- 
2.25.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v3 09/10] libgcc: Add support for HF mode (aka _Float16) in libbid
  2022-05-16 13:47       ` [PATCH v3 09/10] libgcc: Add support for HF mode (aka _Float16) " Christophe Lyon
@ 2022-05-19 13:03         ` Christophe Lyon
  2022-05-19 19:35           ` Joseph Myers
  0 siblings, 1 reply; 33+ messages in thread
From: Christophe Lyon @ 2022-05-19 13:03 UTC (permalink / raw)
  To: gcc-patches, Joseph Myers

Hi Joseph,

May I ping you on this version? (I've moved the tests to gcc.dg/torture/ 
and checked they work on aarch64 and x86_64.

Thanks,

Christophe

On 5/16/22 15:47, Christophe Lyon wrote:
> This patch adds support for trunc and extend operations between HF
> mode (_Float16) 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 _Float16
> and _Decimal* formats.
> 
> The patch also adds two executable tests, to make sure the right
> functions are called, available (link phase) and functional.
> 
> Tested on aarch64 and x86_86. The number of symbol matches in the
> testcases includes the .global XXX to avoid having to match different
> call instructions for different targets.
> 
> 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.dg/torture/convert-dfp-2.c: New test.
> 	* gcc.dg/torture/convert-dfp.c: New test.
> ---
>   gcc/testsuite/gcc.dg/torture/convert-dfp-2.c | 45 ++++++++++++++
>   gcc/testsuite/gcc.dg/torture/convert-dfp.c   | 63 ++++++++++++++++++++
>   libgcc/Makefile.in                           |  9 ++-
>   libgcc/config/libbid/_dd_to_hf.c             | 38 ++++++++++++
>   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             | 38 ++++++++++++
>   libgcc/config/libbid/_td_to_hf.c             | 38 ++++++++++++
>   libgcc/config/libbid/bid_gcc_intrinsics.h    | 30 +++++++++-
>   10 files changed, 364 insertions(+), 5 deletions(-)
>   create mode 100644 gcc/testsuite/gcc.dg/torture/convert-dfp-2.c
>   create mode 100644 gcc/testsuite/gcc.dg/torture/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
> 
> diff --git a/gcc/testsuite/gcc.dg/torture/convert-dfp-2.c b/gcc/testsuite/gcc.dg/torture/convert-dfp-2.c
> new file mode 100644
> index 00000000000..3e4ecb57ba6
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/torture/convert-dfp-2.c
> @@ -0,0 +1,45 @@
> +/* { dg-do run } */
> +/* { dg-require-effective-target float16_runtime } */
> +/* { dg-require-effective-target dfprt } */
> +/* { dg-options "-save-temps" } */
> +/* { dg-add-options float16 } */
> +
> +/* Test conversions from DFP to smaller types.  */
> +
> +_Decimal32 var32;
> +_Decimal64 var64;
> +_Decimal128 var128;
> +_Float16 var16;
> +
> +void __attribute__ ((__noinline__)) foo32 (_Decimal32 param32)
> +{
> +  var16 = param32;
> +}
> +
> +void __attribute__ ((__noinline__)) foo64 (_Decimal64 param64)
> +{
> +  var16 = param64;
> +  var32 = param64;
> +}
> +
> +void __attribute__ ((__noinline__)) foo128 (_Decimal128 param128)
> +{
> +  var16 = param128;
> +  var32 = param128;
> +  var64 = param128;
> +}
> +
> +int main ()
> +{
> +  foo32 (var32);
> +  foo64 (var64);
> +  foo128 (var128);
> +  return 0;
> +}
> +
> +/* { dg-final { scan-assembler-times {\t__bid_truncsdhf} 2 { target { dfp_bid } } } } */
> +/* { dg-final { scan-assembler-times {\t__bid_truncddhf} 2 { target { dfp_bid } } } } */
> +/* { dg-final { scan-assembler-times {\t__bid_truncddsd2} 2 { target { dfp_bid } } } } */
> +/* { dg-final { scan-assembler-times {\t__bid_trunctdhf} 2 { target { dfp_bid } } } } */
> +/* { dg-final { scan-assembler-times {\t__bid_trunctdsd2} 2 { target { dfp_bid } } } } */
> +/* { dg-final { scan-assembler-times {\t__bid_trunctddd2} 2 { target { dfp_bid } } } } */
> diff --git a/gcc/testsuite/gcc.dg/torture/convert-dfp.c b/gcc/testsuite/gcc.dg/torture/convert-dfp.c
> new file mode 100644
> index 00000000000..ec136896ca7
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/torture/convert-dfp.c
> @@ -0,0 +1,63 @@
> +/* { dg-do run } */
> +/* { dg-require-effective-target float16_runtime } */
> +/* { dg-require-effective-target dfprt } */
> +/* { dg-options "-save-temps" } */
> +/* { dg-add-options float16 } */
> +
> +/* Test conversions to/from DFP values.  */
> +
> +extern void abort ();
> +
> +_Decimal32 var32 = 1.2df;
> +
> +int __attribute__ ((__noinline__)) foo32 (_Decimal32 param32, _Decimal64 param64, _Decimal128 param128, _Float16 param16)
> +{
> +  return (param32 == var32)
> +    + (param64 == var32)
> +    + (param128 == var32)
> +    /* Small enough relative difference?  */
> +    + ((((_Decimal32)param16 - var32) / var32) < 0.002df);
> +}
> +
> +_Decimal64 var64 = 1.2dd;
> +
> +int __attribute__ ((__noinline__)) foo64 (_Decimal32 param32, _Decimal64 param64, _Decimal128 param128, _Float16 param16)
> +{
> +  return (param32 == var64)
> +    + (param64 == var64)
> +    + (param128 == var64)
> +    /* Small enough relative difference?  */
> +    + ((((_Decimal64)param16 - var64) / var64) < 0.002dd);
> +}
> +
> +_Decimal128 var128 = 1.2dl;
> +
> +int __attribute__ ((__noinline__)) foo128 (_Decimal32 param32, _Decimal64 param64, _Decimal128 param128, _Float16 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, (_Float16)1.2) != 4)
> +    abort ();
> +
> +  if (foo64 (1.2df, 1.2dd, 1.2dl, (_Float16)1.2) != 4)
> +    abort ();
> +
> +  if (foo128 (1.2df, 1.2dd, 1.2dl, (_Float16)1.2) != 4)
> +    abort ();
> +
> +  return 0;
> +}
> +
> +/* { dg-final { scan-assembler-times {\t__bid_extendsddd2} 3 { target { dfp_bid } } } } */
> +/* { dg-final { scan-assembler-times {\t__bid_extendsdtd2} 3 { target { dfp_bid } } } } */
> +/* { dg-final { scan-assembler-times {\t__bid_extendddtd2} 3 { target { dfp_bid } } } } */
> +/* { dg-final { scan-assembler-times {\t__bid_extendhfsd} 2 { target { dfp_bid } } } } */
> +/* { dg-final { scan-assembler-times {\t__bid_extendhfdd} 2 { target { dfp_bid } } } } */
> +/* { dg-final { scan-assembler-times {\t__bid_extendhftd} 2 { target { dfp_bid } } } } */
> 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..5e58288391e
> --- /dev/null
> +++ b/libgcc/config/libbid/_dd_to_hf.c
> @@ -0,0 +1,38 @@
> +/* 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
> +HFtype
> +__bid_truncddhf (_Decimal64 x) {
> +  HFtype res;
> +  union decimal64 ux;
> +
> +  ux.d = x;
> +  res = __bid64_to_binary32 (ux.i);
> +  return (res);
> +}
> +#endif
> 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..e4e3125d49b
> --- /dev/null
> +++ b/libgcc/config/libbid/_sd_to_hf.c
> @@ -0,0 +1,38 @@
> +/* 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
> +HFtype
> +__bid_truncsdhf (_Decimal32 x) {
> +  HFtype res;
> +  union decimal32 ux;
> +
> +  ux.d = x;
> +  res = __bid32_to_binary32 (ux.i);
> +  return (res);
> +}
> +#endif
> diff --git a/libgcc/config/libbid/_td_to_hf.c b/libgcc/config/libbid/_td_to_hf.c
> new file mode 100644
> index 00000000000..c4ebe586db0
> --- /dev/null
> +++ b/libgcc/config/libbid/_td_to_hf.c
> @@ -0,0 +1,38 @@
> +/* 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
> +HFtype
> +__bid_trunctdhf (_Decimal128 x) {
> +  HFtype res;
> +  union decimal128 ux;
> +
> +  ux.d = x;
> +  res = __bid128_to_binary32 (ux.i);
> +  return (res);
> +}
> +#endif
> diff --git a/libgcc/config/libbid/bid_gcc_intrinsics.h b/libgcc/config/libbid/bid_gcc_intrinsics.h
> index b0a23debc15..15c050764ac 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 _Float16
> +#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);

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v3 09/10] libgcc: Add support for HF mode (aka _Float16) in libbid
  2022-05-19 13:03         ` Christophe Lyon
@ 2022-05-19 19:35           ` Joseph Myers
  2022-05-20  7:47             ` Christophe Lyon
  0 siblings, 1 reply; 33+ messages in thread
From: Joseph Myers @ 2022-05-19 19:35 UTC (permalink / raw)
  To: Christophe Lyon; +Cc: gcc-patches

On Thu, 19 May 2022, Christophe Lyon via Gcc-patches wrote:

> Hi Joseph,
> 
> May I ping you on this version? (I've moved the tests to gcc.dg/torture/ and
> checked they work on aarch64 and x86_64.

This version is OK, given a bug report filed in Bugzilla for the 
double-rounding issues with conversions from DFP modes to HFmode.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v3 09/10] libgcc: Add support for HF mode (aka _Float16) in libbid
  2022-05-19 19:35           ` Joseph Myers
@ 2022-05-20  7:47             ` Christophe Lyon
  0 siblings, 0 replies; 33+ messages in thread
From: Christophe Lyon @ 2022-05-20  7:47 UTC (permalink / raw)
  To: Joseph Myers; +Cc: gcc-patches



On 5/19/22 21:35, Joseph Myers wrote:
> On Thu, 19 May 2022, Christophe Lyon via Gcc-patches wrote:
> 
>> Hi Joseph,
>>
>> May I ping you on this version? (I've moved the tests to gcc.dg/torture/ and
>> checked they work on aarch64 and x86_64.
> 
> This version is OK, given a bug report filed in Bugzilla for the
> double-rounding issues with conversions from DFP modes to HFmode.
> 

Thanks!

I've filed PR 105669.

Christophe

^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2022-05-20  7:47 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-09 14:34 [PATCH 00/10] Enable Decimal Floating Point (DFP) on AArch64 Christophe Lyon
2022-05-09 14:34 ` [PATCH 01/10] aarch64: Enable DFP (Decimal Floating-point) (BID format) Christophe Lyon
2022-05-09 14:34 ` [PATCH 02/10] aarch64: Add backend support for DFP Christophe Lyon
2022-05-10  9:23   ` Richard Sandiford
2022-05-10  9:30     ` Richard Sandiford
2022-05-10 10:18       ` Christophe Lyon
2022-05-13 16:08   ` [PATCH v2 " Christophe Lyon
2022-05-13 16:35     ` Richard Sandiford
2022-05-16 12:17       ` Christophe Lyon
2022-05-09 14:35 ` [PATCH 03/10] libgcc: Enable XF mode conversions to/from DFP modes only if supported Christophe Lyon
2022-05-09 14:35 ` [PATCH 04/10] libgcc: enable DFP for AArch64 Christophe Lyon
2022-05-09 14:35 ` [PATCH 05/10] testsuite:: Fix pr39986.c testcase " Christophe Lyon
2022-05-09 14:35 ` [PATCH 06/10] testsuite: Add new tests for DFP under aarch64/aapcs64 Christophe Lyon
2022-05-09 14:35 ` [PATCH 07/10] testsuite: enable more BID DFP tests for AArch64 Christophe Lyon
2022-05-09 14:35 ` [PATCH 08/10] testsuite: Add C++ unwinding tests with Decimal Floating-Point Christophe Lyon
2022-05-10  9:27   ` Richard Sandiford
2022-05-13 16:35   ` [PATCH v2 " Christophe Lyon
2022-05-13 17:52   ` Christophe Lyon
2022-05-16 10:33     ` Richard Sandiford
2022-05-09 14:35 ` [PATCH 09/10] libgcc: Add support for HF mode (aka __fp16) in libbid Christophe Lyon
2022-05-09 21:27   ` Joseph Myers
2022-05-10  8:08     ` Christophe Lyon
2022-05-10 20:26       ` Joseph Myers
2022-05-13 16:34   ` [PATCH v2 " Christophe Lyon
2022-05-13 17:52   ` Christophe Lyon
2022-05-13 18:23     ` Joseph Myers
2022-05-13 18:30       ` Christophe Lyon
2022-05-16 13:47       ` [PATCH v3 09/10] libgcc: Add support for HF mode (aka _Float16) " Christophe Lyon
2022-05-19 13:03         ` Christophe Lyon
2022-05-19 19:35           ` Joseph Myers
2022-05-20  7:47             ` Christophe Lyon
2022-05-09 14:35 ` [PATCH 10/10] libgcc: use __builtin_clz and __builtin_ctz " Christophe Lyon
2022-05-10  9:37 ` [PATCH 00/10] Enable Decimal Floating Point (DFP) on AArch64 Richard Sandiford

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).