Re: [Patch 16/17 libgcc ARM] Half to double precision conversions

2016-11-23 Thread James Greenhalgh
On Wed, Nov 16, 2016 at 04:00:12PM +, 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 

Re: [Patch 16/17 libgcc ARM] Half to double precision conversions

2016-11-16 Thread Kyrill Tkachov


On 11/11/16 15:42, James Greenhalgh wrote:

Hi,

This patch adds the half-to-double conversions, both as library functions,
or when supported in hardware, using the appropriate instructions.

That means adding support for the __gnu_d2h_{ieee/alternative} library calls
added in patch 2/4, and providing a more aggressive truncdfhf2 where we can.

This also lets us remove the implementation of TARGET_CONVERT_TO_TYPE.

Bootstrapped on an ARMv8-A machine,and crosstested with no issues.

OK?

Thanks,
James

---
gcc/

2016-11-09  James Greenhalgh  

* config/arm/arm.c (arm_convert_to_type): Delete.
(TARGET_CONVERT_TO_TYPE): Delete.
(arm_init_libfuncs): Enable trunc_optab from DFmode to HFmode.
(arm_libcall_uses_aapcs_base): Add trunc_optab from DF- to HFmode.
* config/arm/arm.h (TARGET_FP16_TO_DOUBLE): New.
* config/arm/arm.md (truncdfhf2): Only convert through SFmode if we
are in fast math mode, and have no single step hardware instruction.
(extendhfdf2): Only expand through SFmode if we don't have a
single-step hardware instruction.
* config/arm/vfp.md (*truncdfhf2): New.
(extendhfdf2): Likewise.

gcc/testsuite/

2016-11-09  James Greenhalgh  

* gcc.target/arm/fp16-rounding-alt-1.c (ROUNDED): Change expected
result.
* gcc.target/arm/fp16-rounding-ieee-1.c (ROUNDED): Change expected
result.


<...>

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,
Kyrill



[Patch 16/17 libgcc ARM] Half to double precision conversions

2016-11-11 Thread James Greenhalgh

Hi,

This patch adds the half-to-double conversions, both as library functions,
or when supported in hardware, using the appropriate instructions.

That means adding support for the __gnu_d2h_{ieee/alternative} library calls
added in patch 2/4, and providing a more aggressive truncdfhf2 where we can.

This also lets us remove the implementation of TARGET_CONVERT_TO_TYPE.

Bootstrapped on an ARMv8-A machine,and crosstested with no issues.

OK?

Thanks,
James

---
gcc/

2016-11-09  James Greenhalgh  

* config/arm/arm.c (arm_convert_to_type): Delete.
(TARGET_CONVERT_TO_TYPE): Delete.
(arm_init_libfuncs): Enable trunc_optab from DFmode to HFmode.
(arm_libcall_uses_aapcs_base): Add trunc_optab from DF- to HFmode.
* config/arm/arm.h (TARGET_FP16_TO_DOUBLE): New.
* config/arm/arm.md (truncdfhf2): Only convert through SFmode if we
are in fast math mode, and have no single step hardware instruction.
(extendhfdf2): Only expand through SFmode if we don't have a
single-step hardware instruction.
* config/arm/vfp.md (*truncdfhf2): New.
(extendhfdf2): Likewise.

gcc/testsuite/

2016-11-09  James Greenhalgh  

* gcc.target/arm/fp16-rounding-alt-1.c (ROUNDED): Change expected
result.
* gcc.target/arm/fp16-rounding-ieee-1.c (ROUNDED): Change expected
result.

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 239117f..b9097c5 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);
@@ -5262,6 +5263,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;
@@ -22517,23 +22520,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 c8d7462..e759720 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 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