public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: James Greenhalgh <james.greenhalgh@arm.com>
To: Kyrill Tkachov <kyrylo.tkachov@foss.arm.com>
Cc: <gcc-patches@gcc.gnu.org>, <richard.earnshaw@arm.com>,
	<kyrtka01@arm.com>,	<ramana.radhakrishnan@arm.com>,
	<joseph@codesourcery.com>, <nd@arm.com>
Subject: Re: [Patch 16/17 libgcc ARM] Half to double precision conversions
Date: Wed, 23 Nov 2016 18:20:00 -0000	[thread overview]
Message-ID: <20161123181957.GA37057@arm.com> (raw)
In-Reply-To: <582C828C.2080003@foss.arm.com>

On Wed, Nov 16, 2016 at 04:00:12PM +0000, Kyrill Tkachov wrote:
> <...>
> 
> diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
> index 8393f65..4074773 100644
> --- a/gcc/config/arm/arm.md
> +++ b/gcc/config/arm/arm.md
> @@ -5177,20 +5177,35 @@
>    ""
>  )
> -;; DFmode to HFmode conversions have to go through SFmode.
> +;; DFmode to HFmode conversions on targets without a single-step hardware
> +;; instruction for it would have to go through SFmode.  This is dangerous
> +;; as it introduces double rounding.
> +;;
> +;; Disable this pattern unless we are in an unsafe math mode, or we have
> +;; a single-step instruction.
> +
>  (define_expand "truncdfhf2"
> -  [(set (match_operand:HF  0 "general_operand" "")
> +  [(set (match_operand:HF  0 "s_register_operand" "")
>  	(float_truncate:HF
> - 	 (match_operand:DF 1 "general_operand" "")))]
> -  "TARGET_EITHER"
> -  "
> -  {
> -    rtx op1;
> -    op1 = convert_to_mode (SFmode, operands[1], 0);
> -    op1 = convert_to_mode (HFmode, op1, 0);
> -    emit_move_insn (operands[0], op1);
> -    DONE;
> -  }"
> +	 (match_operand:DF 1 "s_register_operand" "")))]
> +  "(TARGET_EITHER && flag_unsafe_math_optimizations)
> +   || (TARGET_32BIT && TARGET_FP16_TO_DOUBLE)"
> +{
> +  /* We don't have a direct instruction for this, so we must be in
> +     an unsafe math mode, and going via SFmode.  */
> +
> +  if (!(TARGET_32BIT && TARGET_FP16_TO_DOUBLE))
> +    {
> +      rtx op1;
> +      gcc_assert (flag_unsafe_math_optimizations);
> 
> I'd remove this assert. From the condition of the expander it is obvious
> that if !(TARGET_32BIT && TARGET_FP16_TO_DOUBLE) then
> flag_unsafe_math_optimizations is true.
> 
> 
> Ok with this change.

Thanks.

In the end, this is what I committed.

Thanks,
James

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index abd3276..118b93b 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -245,7 +245,6 @@ static bool arm_output_addr_const_extra (FILE *, rtx);
 static bool arm_allocate_stack_slots_for_args (void);
 static bool arm_warn_func_return (tree);
 static tree arm_promoted_type (const_tree t);
-static tree arm_convert_to_type (tree type, tree expr);
 static bool arm_scalar_mode_supported_p (machine_mode);
 static bool arm_frame_pointer_required (void);
 static bool arm_can_eliminate (const int, const int);
@@ -654,9 +653,6 @@ static const struct attribute_spec arm_attribute_table[] =
 #undef TARGET_PROMOTED_TYPE
 #define TARGET_PROMOTED_TYPE arm_promoted_type
 
-#undef TARGET_CONVERT_TO_TYPE
-#define TARGET_CONVERT_TO_TYPE arm_convert_to_type
-
 #undef TARGET_SCALAR_MODE_SUPPORTED_P
 #define TARGET_SCALAR_MODE_SUPPORTED_P arm_scalar_mode_supported_p
 
@@ -2535,6 +2531,11 @@ arm_init_libfuncs (void)
 			 ? "__gnu_h2f_ieee"
 			 : "__gnu_h2f_alternative"));
 
+      set_conv_libfunc (trunc_optab, HFmode, DFmode,
+			(arm_fp16_format == ARM_FP16_FORMAT_IEEE
+			 ? "__gnu_d2h_ieee"
+			 : "__gnu_d2h_alternative"));
+
       /* Arithmetic.  */
       set_optab_libfunc (add_optab, HFmode, NULL);
       set_optab_libfunc (sdiv_optab, HFmode, NULL);
@@ -5259,6 +5260,8 @@ arm_libcall_uses_aapcs_base (const_rtx libcall)
 							SFmode));
       add_libcall (libcall_htab, convert_optab_libfunc (trunc_optab, SFmode,
 							DFmode));
+      add_libcall (libcall_htab,
+		   convert_optab_libfunc (trunc_optab, HFmode, DFmode));
     }
 
   return libcall && libcall_htab->find (libcall) != NULL;
@@ -22514,23 +22517,6 @@ arm_promoted_type (const_tree t)
   return NULL_TREE;
 }
 
-/* Implement TARGET_CONVERT_TO_TYPE.
-   Specifically, this hook implements the peculiarity of the ARM
-   half-precision floating-point C semantics that requires conversions between
-   __fp16 to or from double to do an intermediate conversion to float.  */
-
-static tree
-arm_convert_to_type (tree type, tree expr)
-{
-  tree fromtype = TREE_TYPE (expr);
-  if (!SCALAR_FLOAT_TYPE_P (fromtype) || !SCALAR_FLOAT_TYPE_P (type))
-    return NULL_TREE;
-  if ((TYPE_PRECISION (fromtype) == 16 && TYPE_PRECISION (type) > 32)
-      || (TYPE_PRECISION (type) == 16 && TYPE_PRECISION (fromtype) > 32))
-    return convert (type, convert (float_type_node, expr));
-  return NULL_TREE;
-}
-
 /* Implement TARGET_SCALAR_MODE_SUPPORTED_P.
    This simply adds HFmode as a supported mode; even though we don't
    implement arithmetic on this type directly, it's supported by
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 7ad0fbf..15930f0 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -179,6 +179,11 @@ extern void (*arm_lang_output_object_attributes_hook)(void);
 #define TARGET_FP16							\
   (ARM_FPU_FSET_HAS (TARGET_FPU_FEATURES, FPU_FL_FP16))
 
+/* FPU supports converting between HFmode and DFmode in a single hardware
+   step.  */
+#define TARGET_FP16_TO_DOUBLE						\
+  (TARGET_HARD_FLOAT && (TARGET_FP16 && TARGET_VFP5))
+
 /* FPU supports fused-multiply-add operations.  */
 #define TARGET_FMA (TARGET_FPU_REV >= 4)
 
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index ccae728b..5523baf 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -5182,20 +5182,34 @@
   ""
 )
 
-;; DFmode to HFmode conversions have to go through SFmode.
+;; DFmode to HFmode conversions on targets without a single-step hardware
+;; instruction for it would have to go through SFmode.  This is dangerous
+;; as it introduces double rounding.
+;;
+;; Disable this pattern unless we are in an unsafe math mode, or we have
+;; a single-step instruction.
+
 (define_expand "truncdfhf2"
-  [(set (match_operand:HF  0 "general_operand" "")
+  [(set (match_operand:HF  0 "s_register_operand" "")
 	(float_truncate:HF
- 	 (match_operand:DF 1 "general_operand" "")))]
-  "TARGET_EITHER"
-  "
-  {
-    rtx op1;
-    op1 = convert_to_mode (SFmode, operands[1], 0);
-    op1 = convert_to_mode (HFmode, op1, 0);
-    emit_move_insn (operands[0], op1);
-    DONE;
-  }"
+	 (match_operand:DF 1 "s_register_operand" "")))]
+  "(TARGET_EITHER && flag_unsafe_math_optimizations)
+   || (TARGET_32BIT && TARGET_FP16_TO_DOUBLE)"
+{
+  /* We don't have a direct instruction for this, so we must be in
+     an unsafe math mode, and going via SFmode.  */
+
+  if (!(TARGET_32BIT && TARGET_FP16_TO_DOUBLE))
+    {
+      rtx op1;
+      op1 = convert_to_mode (SFmode, operands[1], 0);
+      op1 = convert_to_mode (HFmode, op1, 0);
+      emit_move_insn (operands[0], op1);
+      DONE;
+    }
+  /* Otherwise, we will pick this up as a single instruction with
+     no intermediary rounding.  */
+}
 )
 \f
 ;; Zero and sign extension instructions.
@@ -5689,19 +5703,28 @@
   ""
 )
 
-;; HFmode -> DFmode conversions have to go through SFmode.
+;; HFmode -> DFmode conversions where we don't have an instruction for it
+;; must go through SFmode.
+;;
+;; This is always safe for an extend.
+
 (define_expand "extendhfdf2"
-  [(set (match_operand:DF                  0 "general_operand" "")
-	(float_extend:DF (match_operand:HF 1 "general_operand"  "")))]
+  [(set (match_operand:DF		   0 "s_register_operand" "")
+	(float_extend:DF (match_operand:HF 1 "s_register_operand" "")))]
   "TARGET_EITHER"
-  "
-  {
-    rtx op1;
-    op1 = convert_to_mode (SFmode, operands[1], 0);
-    op1 = convert_to_mode (DFmode, op1, 0);
-    emit_insn (gen_movdf (operands[0], op1));
-    DONE;
-  }"
+{
+  /* We don't have a direct instruction for this, so go via SFmode.  */
+  if (!(TARGET_32BIT && TARGET_FP16_TO_DOUBLE))
+    {
+      rtx op1;
+      op1 = convert_to_mode (SFmode, operands[1], 0);
+      op1 = convert_to_mode (DFmode, op1, 0);
+      emit_insn (gen_movdf (operands[0], op1));
+      DONE;
+    }
+  /* Otherwise, we're done producing RTL and will pick up the correct
+     pattern to do this with one rounding-step in a single instruction.  */
+}
 )
 \f
 ;; Move insns (including loads and stores)
diff --git a/gcc/config/arm/vfp.md b/gcc/config/arm/vfp.md
index ce56e16..f83dc9b 100644
--- a/gcc/config/arm/vfp.md
+++ b/gcc/config/arm/vfp.md
@@ -1507,6 +1507,26 @@
    (set_attr "type" "f_cvt")]
 )
 
+(define_insn "*truncdfhf2"
+  [(set (match_operand:HF		   0 "s_register_operand" "=t")
+	(float_truncate:HF (match_operand:DF 1 "s_register_operand" "w")))]
+  "TARGET_32BIT && TARGET_FP16_TO_DOUBLE"
+  "vcvtb%?.f16.f64\\t%0, %P1"
+  [(set_attr "predicable" "yes")
+   (set_attr "predicable_short_it" "no")
+   (set_attr "type" "f_cvt")]
+)
+
+(define_insn "*extendhfdf2"
+  [(set (match_operand:DF		   0 "s_register_operand" "=w")
+	(float_extend:DF (match_operand:HF 1 "s_register_operand" "t")))]
+  "TARGET_32BIT && TARGET_FP16_TO_DOUBLE"
+  "vcvtb%?.f64.f16\\t%P0, %1"
+  [(set_attr "predicable" "yes")
+   (set_attr "predicable_short_it" "no")
+   (set_attr "type" "f_cvt")]
+)
+
 (define_insn "truncsfhf2"
   [(set (match_operand:HF		   0 "s_register_operand" "=t")
 	(float_truncate:HF (match_operand:SF 1 "s_register_operand" "t")))]
diff --git a/gcc/testsuite/gcc.target/arm/fp16-rounding-alt-1.c b/gcc/testsuite/gcc.target/arm/fp16-rounding-alt-1.c
index 1c15b61..27bb40d 100644
--- a/gcc/testsuite/gcc.target/arm/fp16-rounding-alt-1.c
+++ b/gcc/testsuite/gcc.target/arm/fp16-rounding-alt-1.c
@@ -1,6 +1,6 @@
-/* Test intermediate rounding of double to float and then to __fp16, using
-   an example of a number that would round differently if it went directly
-   from double to __fp16.  */
+/* Test that rounding double to __fp16 happens directly, using an example
+   of a number that would round differently if it went from double to
+   __fp16 via float.  */
 
 /* { dg-do run } */
 /* { dg-require-effective-target arm_fp16_alternative_ok } */
@@ -11,8 +11,8 @@
 /* The original double value.  */
 #define ORIG 0x1.0020008p0
 
-/* The expected (double)((__fp16)((float)ORIG)) value.  */
-#define ROUNDED 0x1.0000000p0
+/* The expected (double)((__fp16)ORIG) value.  */
+#define ROUNDED 0x1.0040000p0
 
 typedef union u {
   __fp16 f;
diff --git a/gcc/testsuite/gcc.target/arm/fp16-rounding-ieee-1.c b/gcc/testsuite/gcc.target/arm/fp16-rounding-ieee-1.c
index 866d4d8..194dc9d 100644
--- a/gcc/testsuite/gcc.target/arm/fp16-rounding-ieee-1.c
+++ b/gcc/testsuite/gcc.target/arm/fp16-rounding-ieee-1.c
@@ -1,6 +1,6 @@
-/* Test intermediate rounding of double to float and then to __fp16, using
-   an example of a number that would round differently if it went directly
-   from double to __fp16.  */
+/* Test that rounding double to __fp16 happens directly, using an example
+   of a number that would round differently if it went from double to
+   __fp16 via float.  */
 
 /* { dg-do run } */
 /* { dg-options "-mfp16-format=ieee" } */
@@ -10,8 +10,8 @@
 /* The original double value.  */
 #define ORIG 0x1.0020008p0
 
-/* The expected (double)((__fp16)((float)ORIG)) value.  */
-#define ROUNDED 0x1.0000000p0
+/* The expected (double)((__fp16)ORIG) value.  */
+#define ROUNDED 0x1.0040000p0
 
 typedef union u {
   __fp16 f;

  reply	other threads:[~2016-11-23 18:20 UTC|newest]

Thread overview: 95+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-09-30 16:58 [Patch 0/11] Add support for _Float16 to AArch64 James Greenhalgh
2016-09-30 16:58 ` [Patch 8/11] Make _Float16 available if HFmode is available James Greenhalgh
2016-09-30 17:34   ` Jeff Law
2016-09-30 16:59 ` [Patch 2/11] Implement TARGET_C_EXCESS_PRECISION for i386 James Greenhalgh
2016-10-01 11:55   ` Uros Bizjak
2016-09-30 16:59 ` [Patch 6/11] Migrate excess precision logic to use TARGET_EXCESS_PRECISION James Greenhalgh
2016-09-30 17:34   ` Joseph Myers
2016-10-14 16:56     ` James Greenhalgh
2016-10-28 21:10       ` Joseph Myers
2016-11-02 17:38         ` James Greenhalgh
2016-11-09  2:47           ` Joseph Myers
2016-09-30 16:59 ` [Patch 7/11] Delete TARGET_FLT_EVAL_METHOD and poison it James Greenhalgh
2016-09-30 17:29   ` Jeff Law
2016-09-30 17:01 ` [Patch 1/11] Add a new target hook for describing excess precision intentions James Greenhalgh
2016-10-14 16:50   ` James Greenhalgh
2016-10-28 21:12     ` Joseph Myers
2016-11-02 17:36       ` James Greenhalgh
2016-11-09  2:34         ` Joseph Myers
2016-09-30 17:01 ` [Patch 5/11] Add -fpermitted-flt-eval-methods=[c11|ts-18661-3] James Greenhalgh
2016-09-30 17:40   ` Jeff Law
2016-09-30 22:07     ` Mike Stump
2016-10-05 23:00   ` Joseph Myers
2016-09-30 17:03 ` [Patch 3/11] Implement TARGET_C_EXCESS_PRECISION for s390 James Greenhalgh
2016-09-30 17:41   ` Joseph Myers
2016-09-30 17:54     ` Jeff Law
2016-09-30 18:10       ` Joseph Myers
2016-10-03  8:31         ` James Greenhalgh
2016-10-04 13:40         ` Andreas Krebbel
2016-10-04 13:43           ` Joseph Myers
2016-10-07  8:34             ` Andreas Krebbel
2016-10-07 13:11               ` Joseph Myers
2016-10-12  8:40                 ` Andreas Krebbel
2016-10-12 10:14                   ` Joseph Myers
2016-10-14 16:53               ` James Greenhalgh
2016-10-17 19:30                 ` Andreas Krebbel1
2016-10-19 15:20                   ` Andreas Krebbel
2016-09-30 17:04 ` [Patch libgcc 9/11] Update soft-fp from glibc James Greenhalgh
2016-09-30 17:04 ` [Patch 4/11] Implement TARGET_C_EXCESS_PRECISION for m68k James Greenhalgh
2016-09-30 17:32   ` Jeff Law
2016-09-30 18:25   ` Andreas Schwab
2016-10-14 16:55     ` James Greenhalgh
2016-09-30 17:05 ` [Patch libgcc 9/11] Update soft-fp from glibc James Greenhalgh
2016-09-30 17:04   ` [Patch libgcc AArch64 10/11] Enable hfmode soft-float conversions and truncations James Greenhalgh
2016-09-30 17:14   ` [Patch AArch64 11/11] Enable _Float16 James Greenhalgh
2016-10-14 17:02     ` James Greenhalgh
2016-10-24 13:45 ` [Patch 0/4] [ARM] Enable _Float16 on ARM James Greenhalgh
2016-10-24 13:45   ` [Patch 2/4] [libgcc] Add double to half conversions James Greenhalgh
2016-10-24 22:24     ` Joseph Myers
2016-11-02 17:41       ` [Patch 3/4] Half to double precision conversions James Greenhalgh
2016-10-24 13:45   ` [Patch 1/4] [libgcc, ARM] Generalise float-to-half conversion function James Greenhalgh
2016-11-08 11:58     ` James Greenhalgh
2016-10-24 13:45   ` [Patch ARM 4/4] Enable _Float16 James Greenhalgh
2016-10-24 22:29     ` Joseph Myers
2016-11-02 17:43       ` James Greenhalgh
2016-11-02 18:42         ` Joseph Myers
2016-10-24 13:45   ` [Patch 3/4] Half to double precision conversions James Greenhalgh
2016-11-11 15:38 ` [Patch v4 0/17] Add support for _Float16 to AArch64 and ARM James Greenhalgh
2016-11-11 15:38   ` [Patch 1/17] Add a new target hook for describing excess precision intentions James Greenhalgh
2016-11-11 15:38   ` [Patch 2/17] Implement TARGET_C_EXCESS_PRECISION for i386 James Greenhalgh
2016-11-11 15:38   ` [Patch 3/17] Implement TARGET_C_EXCESS_PRECISION for s390 James Greenhalgh
2016-11-11 15:38   ` [Patch 6/17] Migrate excess precision logic to use TARGET_EXCESS_PRECISION James Greenhalgh
2016-11-11 15:38   ` [Patch 4/17] Implement TARGET_C_EXCESS_PRECISION for m68k James Greenhalgh
2016-11-11 15:38   ` [Patch 5/17] Add -fpermitted-flt-eval-methods=[c11|ts-18661-3] James Greenhalgh
2016-11-12  4:42     ` Sandra Loosemore
2016-11-14  9:56       ` James Greenhalgh
2016-11-14 23:43         ` Sandra Loosemore
2016-11-11 15:38   ` [Patch 7/17] Delete TARGET_FLT_EVAL_METHOD and poison it James Greenhalgh
2016-11-11 15:39   ` [Patch libgcc 9/17] Update soft-fp from glibc James Greenhalgh
2016-11-11 15:39   ` [Patch testsuite patch 10/17] Add options for floatN when checking effective target for support James Greenhalgh
2016-11-11 15:59     ` Joseph Myers
2016-11-11 15:39   ` [Patch 8/17] Make _Float16 available if HFmode is available James Greenhalgh
2016-11-11 15:41   ` [Patch AArch64 11/17] Add floatdihf2 and floatunsdihf2 patterns James Greenhalgh
2016-11-11 15:41     ` [Patch libgcc AArch64 12/17] Enable hfmode soft-float conversions and truncations James Greenhalgh
2016-11-24  9:47       ` James Greenhalgh
2016-11-24 13:23       ` Richard Earnshaw (lists)
2016-11-11 15:41     ` [Patch AArch64 13/17] Enable _Float16 for AArch64 James Greenhalgh
2016-11-11 16:33       ` Joseph Myers
2016-11-24  9:47       ` James Greenhalgh
2016-11-24 14:40       ` Richard Earnshaw (lists)
2016-11-24  9:46     ` Ping^8 Re: [Patch AArch64 11/17] Add floatdihf2 and floatunsdihf2 patterns James Greenhalgh
2016-11-24 13:20     ` Richard Earnshaw (lists)
2016-11-11 15:43   ` [Patch 14/17] [libgcc, ARM] Generalise float-to-half conversion function James Greenhalgh
2016-11-11 15:43     ` [Patch 16/17 libgcc ARM] Half to double precision conversions James Greenhalgh
2016-11-16 16:00       ` Kyrill Tkachov
2016-11-23 18:20         ` James Greenhalgh [this message]
2016-11-11 15:43     ` [Patch ARM 17/17] Enable _Float16 for ARM James Greenhalgh
2016-11-16 14:15       ` Kyrill Tkachov
2016-11-25  8:55         ` Christophe Lyon
2016-11-11 15:43     ` [Patch 15/17 libgcc ARM] Add double to half conversions James Greenhalgh
2016-11-16 14:46       ` Kyrill Tkachov
2016-11-16 16:38     ` [Patch 14/17] [libgcc, ARM] Generalise float-to-half conversion function Kyrill Tkachov
2016-11-23 18:18       ` James Greenhalgh
2016-11-18 18:19   ` [Patch v4 0/17] Add support for _Float16 to AArch64 and ARM James Greenhalgh
2016-11-21  9:19     ` Kyrill Tkachov
2016-11-23 17:05       ` James Greenhalgh

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20161123181957.GA37057@arm.com \
    --to=james.greenhalgh@arm.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=joseph@codesourcery.com \
    --cc=kyrtka01@arm.com \
    --cc=kyrylo.tkachov@foss.arm.com \
    --cc=nd@arm.com \
    --cc=ramana.radhakrishnan@arm.com \
    --cc=richard.earnshaw@arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).