public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [Patch 8/11] Make _Float16 available if HFmode is available
  2016-09-30 16:58 [Patch 0/11] Add support for _Float16 to AArch64 James Greenhalgh
@ 2016-09-30 16:58 ` 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
                   ` (10 subsequent siblings)
  11 siblings, 1 reply; 95+ messages in thread
From: James Greenhalgh @ 2016-09-30 16:58 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd

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


Hi,

Now that we've worked on -fexcess-precision, the comment in targhooks.c
no longer holds. We can now permit _Float16 on any target which provides
HFmode and supports HFmode in libgcc.

Bootstrapped and tested on x86-64, and in series on AArch64.

OK?

Thanks,
James

---
2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>

	* targhooks.c (default_floatn_mode): Enable _Float16 if a target
	provides HFmode.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0008-Patch-8-11-Make-_Float16-available-if-HFmode-is-avai.patch --]
[-- Type: text/x-patch;  name=0008-Patch-8-11-Make-_Float16-available-if-HFmode-is-avai.patch, Size: 727 bytes --]

diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index 08d0b35..bf94b2a 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -513,10 +513,12 @@ default_floatn_mode (int n, bool extended)
       switch (n)
 	{
 	case 16:
-	  /* We do not use HFmode for _Float16 by default because the
-	     required excess precision support is not present and the
-	     interactions with promotion of the older __fp16 need to
-	     be worked out.  */
+	  /* Always enable _Float16 if we have basic support for the mode.
+	     Targets can control the range and precision of operations on
+	     the _Float16 type using TARGET_C_EXCESS_PRECISION.  */
+#ifdef HAVE_HFmode
+	  cand = HFmode;
+#endif
 	  break;
 
 	case 32:

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

* [Patch 0/11] Add support for _Float16 to AArch64
@ 2016-09-30 16:58 James Greenhalgh
  2016-09-30 16:58 ` [Patch 8/11] Make _Float16 available if HFmode is available James Greenhalgh
                   ` (11 more replies)
  0 siblings, 12 replies; 95+ messages in thread
From: James Greenhalgh @ 2016-09-30 16:58 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd

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

Hi,

This patch set enables the _Float16 type specified in ISO/IEC TS 18661-3
for AArch64.

To do this, we first need to update the excess precision logic to support
possibly computing _Float16 values in 16-bit range and precision, and to
set the FLT_EVAL_METHOD macro to "16" as appropriate. That requires some
more expressiveness than we currently get with TARGET_FLT_EVAL_METHOD, so
we first need a new target hook - TARGET_C_EXCESS_PRECISION (patch 1/11),
which we implement in the i386, s390 and m68k back-ends in patches 2-4/11.

However, the meaning of the new value "16" for FLT_EVAL_METHOD is not
specified under C99/C11, and conforming code may have been written assuming
that the only possible values for FLT_EVAL_METHOD were negative values and
{ 0, 1, 2 }. In [patch 5/11] we work around that with a new option -
-fpermitted-flt-eval-methods=[c11|ts-18661-3]. This option will restrict
the compiler to only using the C99/C11 values for FLT_EVAL_METHOD, and is
set to -fpermitted-flt-eval-methods=c11 by default when in a standards
compliant mode like -std=c11.

Patch 6/11 does the work of rewriting the excess precision logic along
the guidelines given in https://gcc.gnu.org/ml/gcc-patches/2016-09/msg00410.html

Patch 7/11 finishes the hookization of TARGET_FLT_EVAL_METHOD by poisoning
the old macro.

Patch 8/11 removes the restriction in targhooks.c:default_floatn_mode that
currently disables HFmode support. This patch is not strictly necessary,
and an alternative route to the same goal would override TARGET_FLOATN_MODE
in AArch64. However, now we've cleaned up the excess precision logic,
I don't believe there is any reason this patch would not be correct.

Patch 9/11 imports the soft-fp changes from
https://sourceware.org/ml/libc-alpha/2016-09/msg00310.html to libgcc.

Patch 10/11 enables these conversion routines for AArch64.

And finally patch 11/11 adds support for the various hooks that the AArch64
back-end requires to turn _Float16 support on.

The patch series as a whole passes a bootstrap and test cycle on x86_64
and AArch64. I've bootstrapped and tested each patch individually on x86_64.
All new tests added and enabled pass as appropriate.

The AArch64 enablement requires
https://gcc.gnu.org/ml/gcc-patches/2016-09/msg00268.html

OK?

Thanks,
James

ChangeLogs:

[Patch 1/11] Add a new target hook for describing excess precision intentions

  gcc/

  2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>

	* target.def (excess_precision): New hook.
	* target.h (flt_eval_method): New.
	(excess_precision_type): Likewise.
	* targhooks.c (default_excess_precision): New.
	* targhooks.h (default_excess_precision): New.
	* doc/tm.texi.in (TARGET_EXCESS_PRECISION): New.
	* doc/tm.texi: Regenerate.

[Patch 2/11] Implement TARGET_C_EXCESS_PRECISION for i386

  gcc/

  2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>

	* config/i386/i386.c (ix86_excess_precision): New.
	(TARGET_C_EXCESS_PRECISION): Define.

[Patch 3/11] Implement TARGET_C_EXCESS_PRECISION for s390

  gcc/

  2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>

	* config/s390/s390.c (s390_excess_precision): New.
	(TARGET_C_EXCESS_PRECISION): Define.

[Patch 4/11] Implement TARGET_C_EXCESS_PRECISION for m68k

  gcc/

  2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>

	* config/m68k/m68k.c (m68k_excess_precision): New.
	(TARGET_C_EXCESS_PRECISION): Define.

[Patch 5/11] Add -fpermitted-flt-eval-methods=[c11|ts-18661-3]

  gcc/c-family/

  2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>

	* c-opts.c (c_common_post_options): Add logic to handle the default
	case for -fpermitted-flt-eval-methods.

  gcc/

  2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>

	* common.opt (fpermitted-flt-eval-methods): New.
	* doc/invoke.texi (-fpermitted-flt-eval-methods): Document it.
	* flag_types.h (permitted_flt_eval_methods): New.

  gcc/testsuite/

  2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>

	* gcc.dg/fpermitted-flt-eval-methods_1.c: New.
	* gcc.dg/fpermitted-flt-eval-methods_2.c: New.

[Patch 6/11] Migrate excess precision logic to use TARGET_EXCESS_PRECISION

  gcc/

  2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>

	* toplev.c (init_excess_precision): Delete most logic.
	* tree.c (excess_precision_type): Rewrite to use
	TARGET_EXCESS_PRECISION.
	* doc/invoke.texi (-fexcess-precision): Document behaviour in a
	more generic fashion.

  gcc/c-family/

  2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>

	* c-common.c (excess_precision_mode_join): New.
	(c_ts18661_flt_eval_method): New.
	(c_c11_flt_eval_method): Likewise.
	(c_flt_eval_method): Likewise.
	* c-common.h (excess_precision_mode_join): New.
	(c_flt_eval_method): Likewise.
	* c-cppbuiltin.c (c_cpp_flt_eval_method_iec_559): New.
	(cpp_iec_559_value): Call it.
	(c_cpp_builtins): Modify logic for __LIBGCC_*_EXCESS_PRECISION__,
	call c_flt_eval_method to set __FLT_EVAL_METHOD__ and
	__FLT_EVAL_METHOD_C99__.

[Patch 7/11] Delete TARGET_FLT_EVAL_METHOD and poison it.

  gcc/

  2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>

	* config/s390/s390.h (TARGET_FLT_EVAL_METHOD): Delete.
	* config/m68k/m68k.h (TARGET_FLT_EVAL_METHOD): Delete.
	* config/i386/i386.h (TARGET_FLT_EVAL_METHOD): Delete.
	* defaults.h (TARGET_FLT_EVAL_METHOD): Delete.
	* doc/tm.texi.in (TARGET_FLT_EVAL_METHOD): Delete.
	* doc/tm.texi: Regenerate.
	* system.h (TARGET_FLT_EVAL_METHOD): Poison.

[Patch 8/11] Make _Float16 available if HFmode is available

  gcc/

  2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>

	* targhooks.c (default_floatn_mode): Enable _Float16 if a target
	provides HFmode.

[Patch libgcc 9/11] Update soft-fp from glibc

  libgcc/

  2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>

	* soft-fp/extendhftf2.c: New.
	* soft-fp/fixhfti.c: Likewise.
	* soft-fp/fixunshfti.c: Likewise.
	* soft-fp/floattihf.c: Likewise.
	* soft-fp/floatuntihf.c: Likewise.
	* soft-fp/half.h: Likewise.
	* soft-fp/trunctfhf2.c: Likewise.

[Patch libgcc AArch64 10/11] Enable hfmode soft-float conversions and truncations

  gcc/

  2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>

	* config/aarch64/aarch64-c.c (aarch64_scalar_mode_supported_p): New.
	(TARGET_SCALAR_MODE_SUPPORTED_P): Define.

  libgcc/

  2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>

	* config/aarch64/sfp-machine.h (_FP_NANFRAC_H): Define.
	(_FP_NANSIGN_H): Likewise.
	* config/aarch64/t-softfp (softfp_extensions): Add hftf.
	(softfp_truncations): Add tfhf.
	(softfp_extras): Add required conversion functions.

[Patch AArch64 11/11] Enable _Float16

  gcc/

  2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>

	* config/aarch64/aarch64-c.c (aarch64_update_cpp_builtins): Update
	__FLT_EVAL_METHOD__ and __FLT_EVAL_METHOD_C99__ when we switch
	architecture levels.
	* config/aarch64/aarch64.c (aarch64_promoted_type): Only promote
	the aarch64_fp16_type_node, not all HFmode types.
	(aarch64_libgcc_floating_mode_supported_p): Support HFmode.
	(aarch64_scalar_mode_supported_p): Likewise.
	(aarch64_excess_precision): New.
	(TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P): Define.
	(TARGET_SCALAR_MODE_SUPPORTED_P): Likewise.
	(TARGET_C_EXCESS_PRECISION): Likewise.

  gcc/testsuite/

  2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>

	* gcc.target/aarch64/_Float16_1.c: New.
	* gcc.target/aarch64/_Float16_2.c: Likewise.
	* gcc.target/aarch64/_Float16_3.c: Likewise.


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

* [Patch 2/11] Implement TARGET_C_EXCESS_PRECISION for i386
  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 16:59 ` James Greenhalgh
  2016-10-01 11:55   ` Uros Bizjak
  2016-09-30 16:59 ` [Patch 7/11] Delete TARGET_FLT_EVAL_METHOD and poison it James Greenhalgh
                   ` (9 subsequent siblings)
  11 siblings, 1 reply; 95+ messages in thread
From: James Greenhalgh @ 2016-09-30 16:59 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, hubicka, ubizjak, joseph, rth

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


Hi,

This patch ports the logic from i386's TARGET_FLT_EVAL_METHOD to the new
target hook TARGET_C_EXCESS_PRECISION.

Bootstrapped and tested with no issues.

OK?

Thanks,
James

---
gcc/

2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>

	* config/i386/i386.c (ix86_excess_precision): New.
	(TARGET_C_EXCESS_PRECISION): Define.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0002-Patch-2-11-Implement-TARGET_C_EXCESS_PRECISION-for-i.patch --]
[-- Type: text/x-patch;  name=0002-Patch-2-11-Implement-TARGET_C_EXCESS_PRECISION-for-i.patch, Size: 2172 bytes --]

diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index e0b2d57..3c801c2 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -50359,6 +50359,45 @@ ix86_addr_space_zero_address_valid (addr_space_t as)
 {
   return as != ADDR_SPACE_GENERIC;
 }
+
+/* Set the value of FLT_EVAL_METHOD in float.h.  When using only the
+   FPU, assume that the fpcw is set to extended precision; when using
+   only SSE, rounding is correct; when using both SSE and the FPU,
+   the rounding precision is indeterminate, since either may be chosen
+   apparently at random.  */
+
+static enum flt_eval_method
+ix86_excess_precision (enum excess_precision_type type)
+{
+  switch (type)
+    {
+      case EXCESS_PRECISION_TYPE_FAST:
+	/* The fastest type to promote to will always be the native type,
+	   whether that occurs with implicit excess precision or
+	   otherwise.  */
+	return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT;
+      case EXCESS_PRECISION_TYPE_STANDARD:
+      case EXCESS_PRECISION_TYPE_IMPLICIT:
+	/* Otherwise, the excess precision we want when we are
+	   in a standards compliant mode, and the implicit precision we
+	   provide can be identical.  */
+	if (!TARGET_80387)
+	  return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT;
+	else if (TARGET_MIX_SSE_I387)
+	  return FLT_EVAL_METHOD_UNPREDICTABLE;
+	else if (!TARGET_SSE_MATH)
+	  return FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE;
+	else if (TARGET_SSE2)
+	  return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT;
+	else
+	  return FLT_EVAL_METHOD_UNPREDICTABLE;
+      default:
+	gcc_unreachable ();
+    }
+
+  return FLT_EVAL_METHOD_UNPREDICTABLE;
+}
+
 #undef TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID
 #define TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID ix86_addr_space_zero_address_valid
 
@@ -50563,6 +50602,8 @@ ix86_addr_space_zero_address_valid (addr_space_t as)
 #undef TARGET_MD_ASM_ADJUST
 #define TARGET_MD_ASM_ADJUST ix86_md_asm_adjust
 
+#undef TARGET_C_EXCESS_PRECISION
+#define TARGET_C_EXCESS_PRECISION ix86_excess_precision
 #undef TARGET_PROMOTE_PROTOTYPES
 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
 #undef TARGET_SETUP_INCOMING_VARARGS

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

* [Patch 6/11] Migrate excess precision logic to use TARGET_EXCESS_PRECISION
  2016-09-30 16:58 [Patch 0/11] Add support for _Float16 to AArch64 James Greenhalgh
                   ` (2 preceding siblings ...)
  2016-09-30 16:59 ` [Patch 7/11] Delete TARGET_FLT_EVAL_METHOD and poison it James Greenhalgh
@ 2016-09-30 16:59 ` James Greenhalgh
  2016-09-30 17:34   ` Joseph Myers
  2016-09-30 17:01 ` [Patch 1/11] Add a new target hook for describing excess precision intentions James Greenhalgh
                   ` (7 subsequent siblings)
  11 siblings, 1 reply; 95+ messages in thread
From: James Greenhalgh @ 2016-09-30 16:59 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd

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


Hi,

This patch moves the logic for excess precision from using the
TARGET_FLT_EVAL_METHOD macro to the TARGET_EXCESS_PRECISION hook
introduced earlier in the patch series.

These logic changes follow Joseph's comments at
https://gcc.gnu.org/ml/gcc-patches/2016-09/msg00410.html

Briefly; we have four things to change.

  1) The logic in tree.c::excess_precision_type .
  Here we want to ask the target which excess preicion it would like for
  whichever of -fexcess-precision=standard or -fexcess-precision=fast is
  in use, then apply that.

  2) The logic in c-family/c-cppbuiltin.c::c_cpp_flt_eval_method_iec_559 .
  We want to update this to ensure that the target claims the same excess
  precision to be implicitly added to operations that it reports in
  -fexcess-precision=standard mode. We take the join of these two reported
  values, and only if the join is equal to the excess precision requested
  for -fexcess-precision=standard can we set the IEC_559 macro.

  3) The logic in c-family/c-cppbuiltin.c::c_cpp_builtin for setting
  __FLT_EVAL_METHOD__ .
  Which is now little more complicated, and makes use of
  -fpermitted-flt-eval-methods from patch 5.

  4) The logic in c-family/c-cppbuiltin.c::c_cpp_builtin for setting
  __LIBGCC_*_EXCESS_PRECISION__ .
  This can just be the implicit precision reported by the target.

Having moved the logic in to those areas, we can simplify
toplev.c::init_excess_precision , which now only retains the assert that
-fexcess-precision=default has been rewritten by the language front-end, and
the set from the command-line variable to the internal variable.

The documentation in invoke.texi is not quite right for the impact of
-fexcess-precision, so I've rewritten the text to read a little more
generic.

Bootstrapped on x86_64 and aarch64 with no issues.

Thanks,
James

---
gcc/

2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>

	* toplev.c (init_excess_precision): Delete most logic.
	* tree.c (excess_precision_type): Rewrite to use
	TARGET_EXCESS_PRECISION.
	* doc/invoke.texi (-fexcess-precision): Document behaviour in a
	more generic fashion.

gcc/c-family/

2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>

	* c-common.c (excess_precision_mode_join): New.
	(c_ts18661_flt_eval_method): New.
	(c_c11_flt_eval_method): Likewise.
	(c_flt_eval_method): Likewise.
	* c-common.h (excess_precision_mode_join): New.
	(c_flt_eval_method): Likewise.
	* c-cppbuiltin.c (c_cpp_flt_eval_method_iec_559): New.
	(cpp_iec_559_value): Call it.
	(c_cpp_builtins): Modify logic for __LIBGCC_*_EXCESS_PRECISION__,
	call c_flt_eval_method to set __FLT_EVAL_METHOD__ and
	__FLT_EVAL_METHOD_C99__.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0006-Patch-6-11-Migrate-excess-precision-logic-to-use-TAR.patch --]
[-- Type: text/x-patch;  name=0006-Patch-6-11-Migrate-excess-precision-logic-to-use-TAR.patch, Size: 16737 bytes --]

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 2652259..983f71a 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -13145,4 +13145,83 @@ diagnose_mismatched_attributes (tree olddecl, tree newdecl)
   return warned;
 }
 
+/* Return the latice point which is the wider of the two FLT_EVAL_METHOD
+   modes X, Y.  This isn't just  >, as the FLT_EVAL_METHOD values added
+   by C TS 18661-3 for interchange  types that are computed in their
+   native precision are larger than the C11 values for evaluating in the
+   precision of float/double/long double.  If either mode is
+   FLT_EVAL_METHOD_UNPREDICTABLE, return that.  */
+
+enum flt_eval_method
+excess_precision_mode_join (enum flt_eval_method x,
+			    enum flt_eval_method y)
+{
+  if (x == FLT_EVAL_METHOD_UNPREDICTABLE
+      || y == FLT_EVAL_METHOD_UNPREDICTABLE)
+    return FLT_EVAL_METHOD_UNPREDICTABLE;
+
+  /* GCC only supports one interchange type right now, _Float16.  If
+     we're evaluating _Float16 in 16-bit precision, then flt_eval_method
+     will be FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16.  */
+  if (x == FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16)
+    return y;
+  if (y == FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16)
+    return x;
+
+  /* Other values for flt_eval_method are directly comparable, and we want
+     the maximum.  */
+  return MAX (x, y);
+}
+
+/* Return the value that should be set for FLT_EVAL_METHOD in the
+   context of ISO/IEC TS 18861-3.
+
+   This should relate to the effective excess precision seen by the user,
+   which is the join point of the precision the target requests for
+   -fexcess-precision={standard,fast} and the implicit excess precision
+   the target uses.  */
+
+static enum flt_eval_method
+c_ts18661_flt_eval_method (void)
+{
+  enum flt_eval_method implicit
+    = targetm.c.excess_precision (EXCESS_PRECISION_TYPE_IMPLICIT);
+
+  enum excess_precision_type flag_type
+    = (flag_excess_precision_cmdline == EXCESS_PRECISION_STANDARD
+       ? EXCESS_PRECISION_TYPE_STANDARD
+       : EXCESS_PRECISION_TYPE_FAST);
+
+  enum flt_eval_method requested
+    = targetm.c.excess_precision (flag_type);
+
+  return excess_precision_mode_join (implicit, requested);
+}
+
+/* As c_cpp_ts18661_flt_eval_method, but clamps the expected values to
+   those that were permitted by C11.  That is to say, eliminates
+   FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16.  */
+
+static enum flt_eval_method
+c_c11_flt_eval_method (void)
+{
+  return excess_precision_mode_join (c_ts18661_flt_eval_method (),
+				     FLT_EVAL_METHOD_PROMOTE_TO_FLOAT);
+}
+
+/* Return the value that should be set for FLT_EVAL_METHOD.  TS18661_P
+   is TRUE if we are in a context where values from ISO/IEEC TS 18861-3
+   are permitted, and FALSE otherwise.  See the comments on
+   c_ts18661_flt_eval_method for what value we choose to set here.  */
+
+int
+c_flt_eval_method (bool ts18661_p)
+{
+  if (ts18661_p && flag_permitted_flt_eval_methods
+		== PERMITTED_FLT_EVAL_METHODS_TS_18661)
+    return c_ts18661_flt_eval_method ();
+  else
+    return c_c11_flt_eval_method ();
+}
+
 #include "gt-c-family-c-common.h"
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index c88619b..0c94207 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1532,6 +1532,11 @@ extern bool valid_array_size_p (location_t, tree, tree);
 extern bool cilk_ignorable_spawn_rhs_op (tree);
 extern bool cilk_recognize_spawn (tree, tree *);
 
+extern enum flt_eval_method
+excess_precision_mode_join (enum flt_eval_method, enum flt_eval_method);
+
+extern int c_flt_eval_method (bool ts18661_p);
+
 #if CHECKING_P
 namespace selftest {
   extern void c_format_c_tests (void);
diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
index b860c21..c8d5290 100644
--- a/gcc/c-family/c-cppbuiltin.c
+++ b/gcc/c-family/c-cppbuiltin.c
@@ -727,6 +727,32 @@ cpp_atomic_builtins (cpp_reader *pfile)
 			(have_swap[psize]? 2 : 1));
 }
 
+/* If the join of the implicit precision in which the target will compute
+   floating-point values and the standard precision in which the target will
+   compute values is not equal to the standard precision, then the target
+   is either unpredictable, or is a broken configuration in which it claims
+   standards compliance, but doesn't honor that.
+
+   Effective predictability for __GCC_IEC_559 in flag_iso_mode, means that
+   the implicit precision is not wider, or less predictable than the
+   standard precision.
+
+   Return TRUE if we have been asked to compile with
+   -fexcess-precision=standard, and following the rules above we are able
+   to guarantee the standards mode.  */
+
+static bool
+c_cpp_flt_eval_method_iec_559 (void)
+{
+  enum flt_eval_method implicit
+    = targetm.c.excess_precision (EXCESS_PRECISION_TYPE_IMPLICIT);
+  enum flt_eval_method standard
+    = targetm.c.excess_precision (EXCESS_PRECISION_TYPE_STANDARD);
+
+  return (excess_precision_mode_join (implicit, standard) == standard
+	  && flag_excess_precision_cmdline == EXCESS_PRECISION_STANDARD);
+}
+
 /* Return the value for __GCC_IEC_559.  */
 static int
 cpp_iec_559_value (void)
@@ -774,11 +800,12 @@ cpp_iec_559_value (void)
      applies to unpredictable contraction.  For C++, and outside
      strict conformance mode, do not consider these options to mean
      lack of IEEE 754 support.  */
+
   if (flag_iso
       && !c_dialect_cxx ()
-      && TARGET_FLT_EVAL_METHOD != 0
-      && flag_excess_precision_cmdline != EXCESS_PRECISION_STANDARD)
+      && !c_cpp_flt_eval_method_iec_559 ())
     ret = 0;
+
   if (flag_iso
       && !c_dialect_cxx ()
       && flag_fp_contract_mode == FP_CONTRACT_FAST)
@@ -1038,8 +1065,18 @@ c_cpp_builtins (cpp_reader *pfile)
 				 cpp_iec_559_complex_value ());
 
   /* float.h needs to know this.  */
+  /* We already have the option -fno-fp-int-builtin-inexact to ensure
+     certain built-in functions follow TS 18661-1 semantics.  It might be
+     reasonable to have a new option to enable FLT_EVAL_METHOD using new
+     values.  However, I'd be inclined to think that such an option should
+     be on by default for -std=gnu*, only off for strict conformance modes.
+     (There would be both __FLT_EVAL_METHOD__ and __FLT_EVAL_METHOD_C99__,
+     say, predefined macros, so that <float.h> could also always use the
+     new value if __STDC_WANT_IEC_60559_TYPES_EXT__ is defined.)  */
   builtin_define_with_int_value ("__FLT_EVAL_METHOD__",
-				 TARGET_FLT_EVAL_METHOD);
+				 c_flt_eval_method (true));
+  builtin_define_with_int_value ("__FLT_EVAL_METHOD_C99__",
+				 c_flt_eval_method (false));
 
   /* And decfloat.h needs this.  */
   builtin_define_with_int_value ("__DEC_EVAL_METHOD__",
@@ -1180,25 +1217,38 @@ c_cpp_builtins (cpp_reader *pfile)
 	      gcc_assert (found_suffix);
 	    }
 	  builtin_define_with_value (macro_name, suffix, 0);
+
+	  /* The way __LIBGCC_*_EXCESS_PRECISION__ is used is about
+	     eliminating excess precision from results assigned to
+	     variables - meaning it should be about the implicit excess
+	     precision only.  */
 	  bool excess_precision = false;
-	  if (TARGET_FLT_EVAL_METHOD != 0
-	      && mode != TYPE_MODE (long_double_type_node)
-	      && (mode == TYPE_MODE (float_type_node)
-		  || mode == TYPE_MODE (double_type_node)))
-	    switch (TARGET_FLT_EVAL_METHOD)
-	      {
-	      case -1:
-	      case 2:
-		excess_precision = true;
-		break;
-
-	      case 1:
-		excess_precision = mode == TYPE_MODE (float_type_node);
-		break;
-
-	      default:
-		gcc_unreachable ();
-	      }
+	  machine_mode float16_type_mode = (float16_type_node
+					    ? TYPE_MODE (float16_type_node)
+					    : VOIDmode);
+	  switch (targetm.c.excess_precision
+		    (EXCESS_PRECISION_TYPE_IMPLICIT))
+	    {
+	    case FLT_EVAL_METHOD_UNPREDICTABLE:
+	    case FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE:
+	      excess_precision = (mode == float16_type_mode
+				  || mode == TYPE_MODE (float_type_node)
+				  || mode == TYPE_MODE (double_type_node));
+	      break;
+
+	    case FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE:
+	      excess_precision = (mode == float16_type_mode
+				  || mode == TYPE_MODE (float_type_node));
+	      break;
+	    case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT:
+	      excess_precision = mode == float16_type_mode;
+	      break;
+	    case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16:
+	      excess_precision = false;
+	      break;
+	    default:
+	      gcc_unreachable ();
+	    }
 	  macro_name = (char *) alloca (strlen (name)
 					+ sizeof ("__LIBGCC__EXCESS_"
 						  "PRECISION__"));
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 9cb0b54..ba6dc93 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -8723,15 +8723,14 @@ them to store all pertinent intermediate computations into variables.
 @item -fexcess-precision=@var{style}
 @opindex fexcess-precision
 This option allows further control over excess precision on machines
-where floating-point registers have more precision than the IEEE
-@code{float} and @code{double} types and the processor does not
-support operations rounding to those types.  By default,
-@option{-fexcess-precision=fast} is in effect; this means that
-operations are carried out in the precision of the registers and that
-it is unpredictable when rounding to the types specified in the source
-code takes place.  When compiling C, if
-@option{-fexcess-precision=standard} is specified then excess
-precision follows the rules specified in ISO C99; in particular,
+where floating-point operations occur in a format with more precision or
+range than the IEEE standard and interchange floating-point types.  By
+default, @option{-fexcess-precision=fast} is in effect; this means that
+operations may be carried out in a wider precision than the types specified
+in the source if that would result in faster code, and it is unpredictable
+when rounding to the types specified in the source code takes place.
+When compiling C, if @option{-fexcess-precision=standard} is specified then
+excess precision follows the rules specified in ISO C99; in particular,
 both casts and assignments cause values to be rounded to their
 semantic types (whereas @option{-ffloat-store} only affects
 assignments).  This option is enabled by default for C if a strict
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 5f80763..9b3abab 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -1684,41 +1684,17 @@ backend_init (void)
   init_regs ();
 }
 
-/* Initialize excess precision settings.  */
+/* Initialize excess precision settings.
+
+   We have no need to modify anything here, just keep track of what the
+   user requested.  We'll figure out any appropriate relaxations
+   later.  */
+
 static void
 init_excess_precision (void)
 {
-  /* Adjust excess precision handling based on the target options.  If
-     the front end cannot handle it, flag_excess_precision_cmdline
-     will already have been set accordingly in the post_options
-     hook.  */
   gcc_assert (flag_excess_precision_cmdline != EXCESS_PRECISION_DEFAULT);
   flag_excess_precision = flag_excess_precision_cmdline;
-  if (flag_unsafe_math_optimizations)
-    flag_excess_precision = EXCESS_PRECISION_FAST;
-  if (flag_excess_precision == EXCESS_PRECISION_STANDARD)
-    {
-      int flt_eval_method = TARGET_FLT_EVAL_METHOD;
-      switch (flt_eval_method)
-	{
-	case -1:
-	case 0:
-	  /* Either the target acts unpredictably (-1) or has all the
-	     operations required not to have excess precision (0).  */
-	  flag_excess_precision = EXCESS_PRECISION_FAST;
-	  break;
-	case 1:
-	case 2:
-	  /* In these cases, predictable excess precision makes
-	     sense.  */
-	  break;
-	default:
-	  /* Any other implementation-defined FLT_EVAL_METHOD values
-	     require the compiler to handle the associated excess
-	     precision rules in excess_precision_type.  */
-	  gcc_unreachable ();
-	}
-    }
 }
 
 /* Initialize things that are both lang-dependent and target-dependent.
diff --git a/gcc/tree.c b/gcc/tree.c
index 33e6f97..678e244 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -8836,50 +8836,94 @@ build_complex_type (tree component_type)
 tree
 excess_precision_type (tree type)
 {
-  if (flag_excess_precision != EXCESS_PRECISION_FAST)
+  /* The target can give two different responses to the question of
+     which excess precision mode it would like depending on whether we
+     are in -fexcess-precision=standard or -fexcess-precision=fast.  */
+
+  enum excess_precision_type requested_type
+    = (flag_excess_precision == EXCESS_PRECISION_FAST
+       ? EXCESS_PRECISION_TYPE_FAST
+       : EXCESS_PRECISION_TYPE_STANDARD);
+
+  enum flt_eval_method target_flt_eval_method
+    = targetm.c.excess_precision (requested_type);
+
+  /* The target should not ask for unpredictable float evaluation (though
+     it might advertise that implicitly the evaluation is unpredictable,
+     but we don't care about that here, it will have been reported
+     elsewhere).  If it does ask for unpredictable evaluation, we have
+     nothing to do here.  */
+  gcc_assert (target_flt_eval_method != FLT_EVAL_METHOD_UNPREDICTABLE);
+
+  /* Nothing to do.  The target has asked for all types we know about
+     to be computed with their native precision and range.  */
+  if (target_flt_eval_method == FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16)
+    return NULL_TREE;
+
+  machine_mode float16_type_mode = (float16_type_node
+				    ? TYPE_MODE (float16_type_node)
+				    : VOIDmode);
+  machine_mode float_type_mode = TYPE_MODE (float_type_node);
+  machine_mode double_type_mode = TYPE_MODE (double_type_node);
+
+  switch (TREE_CODE (type))
     {
-      int flt_eval_method = TARGET_FLT_EVAL_METHOD;
-      switch (TREE_CODE (type))
-	{
-	case REAL_TYPE:
-	  switch (flt_eval_method)
-	    {
-	    case 1:
-	      if (TYPE_MODE (type) == TYPE_MODE (float_type_node))
-		return double_type_node;
-	      break;
-	    case 2:
-	      if (TYPE_MODE (type) == TYPE_MODE (float_type_node)
-		  || TYPE_MODE (type) == TYPE_MODE (double_type_node))
-		return long_double_type_node;
-	      break;
-	    default:
-	      gcc_unreachable ();
-	    }
-	  break;
-	case COMPLEX_TYPE:
-	  if (TREE_CODE (TREE_TYPE (type)) != REAL_TYPE)
-	    return NULL_TREE;
-	  switch (flt_eval_method)
-	    {
-	    case 1:
-	      if (TYPE_MODE (TREE_TYPE (type)) == TYPE_MODE (float_type_node))
-		return complex_double_type_node;
-	      break;
-	    case 2:
-	      if (TYPE_MODE (TREE_TYPE (type)) == TYPE_MODE (float_type_node)
-		  || (TYPE_MODE (TREE_TYPE (type))
-		      == TYPE_MODE (double_type_node)))
-		return complex_long_double_type_node;
-	      break;
-	    default:
-	      gcc_unreachable ();
-	    }
-	  break;
-	default:
-	  break;
-	}
+    case REAL_TYPE:
+      {
+	machine_mode type_mode = TYPE_MODE (type);
+	switch (target_flt_eval_method)
+	  {
+	  case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT:
+	    if (type_mode == float16_type_mode)
+	      return float_type_node;
+	    break;
+	  case FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE:
+	    if (type_mode == float16_type_mode
+		|| type_mode == float_type_mode)
+	      return double_type_node;
+	    break;
+	  case FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE:
+	    if (type_mode == float16_type_mode
+		|| type_mode == float_type_mode
+		|| type_mode == double_type_mode)
+	      return long_double_type_node;
+	    break;
+	  default:
+	    gcc_unreachable ();
+	  }
+	break;
+      }
+    case COMPLEX_TYPE:
+      {
+	if (TREE_CODE (TREE_TYPE (type)) != REAL_TYPE)
+	  return NULL_TREE;
+	machine_mode type_mode = TYPE_MODE (TREE_TYPE (type));
+	switch (target_flt_eval_method)
+	  {
+	  case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT:
+	    if (type_mode == float16_type_mode)
+	      return complex_float_type_node;
+	    break;
+	  case FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE:
+	    if (type_mode == float16_type_mode
+		|| type_mode == float_type_mode)
+	      return complex_double_type_node;
+	    break;
+	  case FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE:
+	    if (type_mode == float16_type_mode
+		|| type_mode == float_type_mode
+		|| type_mode == double_type_mode)
+	      return complex_long_double_type_node;
+	    break;
+	  default:
+	    gcc_unreachable ();
+	  }
+	break;
+      }
+    default:
+      break;
     }
+
   return NULL_TREE;
 }
 \f

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

* [Patch 7/11] Delete TARGET_FLT_EVAL_METHOD and poison it.
  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 16:59 ` [Patch 2/11] Implement TARGET_C_EXCESS_PRECISION for i386 James Greenhalgh
@ 2016-09-30 16:59 ` James Greenhalgh
  2016-09-30 17:29   ` Jeff Law
  2016-09-30 16:59 ` [Patch 6/11] Migrate excess precision logic to use TARGET_EXCESS_PRECISION James Greenhalgh
                   ` (8 subsequent siblings)
  11 siblings, 1 reply; 95+ messages in thread
From: James Greenhalgh @ 2016-09-30 16:59 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd

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


Hi,

We've removed all uses of TARGET_FLT_EVAL_METHOD, so we can remove it
and poison it.

Bootstrapped and tested on x86-64 and AArch64. Tested on s390 and m68k
to the best of my ability (no execute tests).

OK?

Thanks,
James

---
gcc/

2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>

	* config/s390/s390.h (TARGET_FLT_EVAL_METHOD): Delete.
	* config/m68k/m68k.h (TARGET_FLT_EVAL_METHOD): Delete.
	* config/i386/i386.h (TARGET_FLT_EVAL_METHOD): Delete.
	* defaults.h (TARGET_FLT_EVAL_METHOD): Delete.
	* doc/tm.texi.in (TARGET_FLT_EVAL_METHOD): Delete.
	* doc/tm.texi: Regenerate.
	* system.h (TARGET_FLT_EVAL_METHOD): Poison.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0007-Patch-7-11-Delete-TARGET_FLT_EVAL_METHOD-and-poison-.patch --]
[-- Type: text/x-patch;  name=0007-Patch-7-11-Delete-TARGET_FLT_EVAL_METHOD-and-poison-.patch, Size: 4767 bytes --]

diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 8751143..b5e4d61 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -690,17 +690,6 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
   SUBTARGET_EXTRA_SPECS
 \f
 
-/* Set the value of FLT_EVAL_METHOD in float.h.  When using only the
-   FPU, assume that the fpcw is set to extended precision; when using
-   only SSE, rounding is correct; when using both SSE and the FPU,
-   the rounding precision is indeterminate, since either may be chosen
-   apparently at random.  */
-#define TARGET_FLT_EVAL_METHOD						\
-  (TARGET_80387								\
-   ? (TARGET_MIX_SSE_I387 ? -1						\
-      : (TARGET_SSE_MATH ? (TARGET_SSE2 ? 0 : -1) : 2))			\
-   : 0)
-
 /* Whether to allow x87 floating-point arithmetic on MODE (one of
    SFmode, DFmode and XFmode) in the current excess precision
    configuration.  */
diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h
index 2aa858f..2021e9d 100644
--- a/gcc/config/m68k/m68k.h
+++ b/gcc/config/m68k/m68k.h
@@ -281,11 +281,6 @@ along with GCC; see the file COPYING3.  If not see
 #define LONG_DOUBLE_TYPE_SIZE			\
   ((TARGET_COLDFIRE || TARGET_FIDOA) ? 64 : 80)
 
-/* Set the value of FLT_EVAL_METHOD in float.h.  When using 68040 fp
-   instructions, we get proper intermediate rounding, otherwise we
-   get extended precision results.  */
-#define TARGET_FLT_EVAL_METHOD ((TARGET_68040 || ! TARGET_68881) ? 0 : 2)
-
 #define BITS_BIG_ENDIAN 1
 #define BYTES_BIG_ENDIAN 1
 #define WORDS_BIG_ENDIAN 1
diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h
index 3a7be1a..1a2c150 100644
--- a/gcc/config/s390/s390.h
+++ b/gcc/config/s390/s390.h
@@ -247,11 +247,6 @@ extern const char *s390_host_detect_local_cpu (int argc, const char **argv);
 #define S390_TDC_INFINITY (S390_TDC_POSITIVE_INFINITY \
 			  | S390_TDC_NEGATIVE_INFINITY )
 
-/* This is used by float.h to define the float_t and double_t data
-   types.  For historical reasons both are double on s390 what cannot
-   be changed anymore.  */
-#define TARGET_FLT_EVAL_METHOD 1
-
 /* Target machine storage layout.  */
 
 /* Everything is big-endian.  */
diff --git a/gcc/defaults.h b/gcc/defaults.h
index c62c844..210a3c5 100644
--- a/gcc/defaults.h
+++ b/gcc/defaults.h
@@ -963,9 +963,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #define REG_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
 #endif
 
-#ifndef TARGET_FLT_EVAL_METHOD
-#define TARGET_FLT_EVAL_METHOD 0
-#endif
 
 #ifndef TARGET_DEC_EVAL_METHOD
 #define TARGET_DEC_EVAL_METHOD 2
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 0bdae58..9c10ea8 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -1566,13 +1566,6 @@ uses this macro should also arrange to use @file{t-gnu-prefix} in
 the libgcc @file{config.host}.
 @end defmac
 
-@defmac TARGET_FLT_EVAL_METHOD
-A C expression for the value for @code{FLT_EVAL_METHOD} in @file{float.h},
-assuming, if applicable, that the floating-point control word is in its
-default state.  If you do not define this macro the value of
-@code{FLT_EVAL_METHOD} will be zero.
-@end defmac
-
 @defmac WIDEST_HARDWARE_FP_SIZE
 A C expression for the size in bits of the widest floating-point format
 supported by the hardware.  If you define this macro, you must specify a
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 7c7af33..0a4d19b 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -1402,13 +1402,6 @@ uses this macro should also arrange to use @file{t-gnu-prefix} in
 the libgcc @file{config.host}.
 @end defmac
 
-@defmac TARGET_FLT_EVAL_METHOD
-A C expression for the value for @code{FLT_EVAL_METHOD} in @file{float.h},
-assuming, if applicable, that the floating-point control word is in its
-default state.  If you do not define this macro the value of
-@code{FLT_EVAL_METHOD} will be zero.
-@end defmac
-
 @defmac WIDEST_HARDWARE_FP_SIZE
 A C expression for the size in bits of the widest floating-point format
 supported by the hardware.  If you define this macro, you must specify a
diff --git a/gcc/system.h b/gcc/system.h
index cc353f5..df7a398 100644
--- a/gcc/system.h
+++ b/gcc/system.h
@@ -896,7 +896,7 @@ extern void fancy_abort (const char *, int, const char *) ATTRIBUTE_NORETURN;
 	ASM_BYTE_OP MEMBER_TYPE_FORCES_BLK LIBGCC2_HAS_SF_MODE		\
 	LIBGCC2_HAS_DF_MODE LIBGCC2_HAS_XF_MODE LIBGCC2_HAS_TF_MODE	\
 	CLEAR_BY_PIECES_P MOVE_BY_PIECES_P SET_BY_PIECES_P		\
-	STORE_BY_PIECES_P
+	STORE_BY_PIECES_P TARGET_FLT_EVAL_METHOD
 
 /* Target macros only used for code built for the target, that have
    moved to libgcc-tm.h or have never been present elsewhere.  */

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

* [Patch 5/11] Add -fpermitted-flt-eval-methods=[c11|ts-18661-3]
  2016-09-30 16:58 [Patch 0/11] Add support for _Float16 to AArch64 James Greenhalgh
                   ` (4 preceding siblings ...)
  2016-09-30 17:01 ` [Patch 1/11] Add a new target hook for describing excess precision intentions James Greenhalgh
@ 2016-09-30 17:01 ` James Greenhalgh
  2016-09-30 17:40   ` Jeff Law
  2016-10-05 23:00   ` Joseph Myers
  2016-09-30 17:03 ` [Patch 3/11] Implement TARGET_C_EXCESS_PRECISION for s390 James Greenhalgh
                   ` (5 subsequent siblings)
  11 siblings, 2 replies; 95+ messages in thread
From: James Greenhalgh @ 2016-09-30 17:01 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd

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


Hi,

This option is added to control which values of FLT_EVAL_METHOD the
compiler is allowed to set.

ISO/IEC TS 18661-3 defines new permissible values for
FLT_EVAL_METHOD that indicate that operations and constants with
a semantic type that is an interchange or extended format should be
evaluated to the precision and range of that type.  These new values are
a superset of those permitted under C99/C11, which does not specify the
meaning of other positive values of FLT_EVAL_METHOD.  As such, code
conforming to C11 may not have been written expecting the possibility of
the new values.

-fpermitted-flt-eval-methods specifies whether the compiler
should allow only the values of FLT_EVAL_METHOD specified in C99/C11,
or the extended set of values specified in ISO/IEC TS 18661-3.

The two possible values this option can take are "c11" or "ts-18661-3".

The default when in a standards compliant mode (-std=c11 or similar)
is -fpermitted-flt-eval-methods=c11.  The default when in a GNU
dialect (-std=gnu11 or similar) is -fpermitted-flt-eval-methods=ts-18661-3.

I've added two testcases which test that when this option, or a C standards
dialect, would restrict the range of values to {-1, 0, 1, 2}, those are
the only values we see. At this stage in the patch series this trivially
holds for all targets.

Bootstrapped on x86_64 with no issues and tested in series on AArch64.

OK?

Thanks,
James

---
gcc/c-family/

2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>

	* c-opts.c (c_common_post_options): Add logic to handle the default
	case for -fpermitted-flt-eval-methods.

gcc/

2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>

	* common.opt (fpermitted-flt-eval-methods): New.
	* doc/invoke.texi (-fpermitted-flt-eval-methods): Document it.
	* flag_types.h (permitted_flt_eval_methods): New.

gcc/testsuite/

2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>

	* gcc.dg/fpermitted-flt-eval-methods_1.c: New.
	* gcc.dg/fpermitted-flt-eval-methods_2.c: New.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0005-Patch-5-11-Add-fpermitted-flt-eval-methods-c11-ts-18.patch --]
[-- Type: text/x-patch;  name=0005-Patch-5-11-Add-fpermitted-flt-eval-methods-c11-ts-18.patch, Size: 6467 bytes --]

diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
index c5a699d..af8d7fe 100644
--- a/gcc/c-family/c-opts.c
+++ b/gcc/c-family/c-opts.c
@@ -789,6 +789,18 @@ c_common_post_options (const char **pfilename)
       && flag_unsafe_math_optimizations == 0)
     flag_fp_contract_mode = FP_CONTRACT_OFF;
 
+  /* If we are compiling C, and we are outside of a standards mode,
+     we can permit the new values from ISO/IEC TS 18661-3 for
+     FLT_EVAL_METHOD.  Otherwise, we must restrict the possible values to
+     the set specified in ISO C99/C11.  */
+  if (!flag_iso
+      && !c_dialect_cxx ()
+      && (global_options_set.x_flag_permitted_flt_eval_methods
+	  == PERMITTED_FLT_EVAL_METHODS_DEFAULT))
+    flag_permitted_flt_eval_methods = PERMITTED_FLT_EVAL_METHODS_TS_18661;
+  else
+    flag_permitted_flt_eval_methods = PERMITTED_FLT_EVAL_METHODS_C11;
+
   /* By default we use C99 inline semantics in GNU99 or C99 mode.  C99
      inline semantics are not supported in GNU89 or C89 mode.  */
   if (flag_gnu89_inline == -1)
diff --git a/gcc/common.opt b/gcc/common.opt
index 0e01577..3a22aa0 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1305,6 +1305,21 @@ Enum(excess_precision) String(fast) Value(EXCESS_PRECISION_FAST)
 EnumValue
 Enum(excess_precision) String(standard) Value(EXCESS_PRECISION_STANDARD)
 
+; Whether we permit the extended set of values for FLT_EVAL_METHOD
+; introduced in ISO/IEC TS 18661-3, or limit ourselves to those in C99/C11.
+fpermitted-flt-eval-methods=
+Common Joined RejectNegative Enum(permitted_flt_eval_methods) Var(flag_permitted_flt_eval_methods) Init(PERMITTED_FLT_EVAL_METHODS_DEFAULT)
+-fpermitted-flt-eval-methods=[c11|ts-18661]	Specify which values of FLT_EVAL_METHOD are permitted.
+
+Enum
+Name(permitted_flt_eval_methods) Type(enum permitted_flt_eval_methods) UnknownError(unknown specification for the set of FLT_EVAL_METHOD values to permit %qs)
+
+EnumValue
+Enum(permitted_flt_eval_methods) String(c11) Value(PERMITTED_FLT_EVAL_METHODS_C11)
+
+EnumValue
+Enum(permitted_flt_eval_methods) String(ts-18661-3) Value(PERMITTED_FLT_EVAL_METHODS_TS_18661)
+
 ffast-math
 Common Optimization
 
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 8a84e4f..9cb0b54 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -375,7 +375,8 @@ Objective-C and Objective-C++ Dialects}.
 -flto-partition=@var{alg} -fmerge-all-constants @gol
 -fmerge-constants -fmodulo-sched -fmodulo-sched-allow-regmoves @gol
 -fmove-loop-invariants -fno-branch-count-reg @gol
--fno-defer-pop -fno-fp-int-builtin-inexact -fno-function-cse @gol
+-fno-defer-pop -fno-fp-int-builtin-inexact @gol
+-fpermitted-flt-eval-methods=@var{standard} -fno-function-cse @gol
 -fno-guess-branch-probability -fno-inline -fno-math-errno -fno-peephole @gol
 -fno-peephole2 -fno-sched-interblock -fno-sched-spec -fno-signed-zeros @gol
 -fno-toplevel-reorder -fno-trapping-math -fno-zero-initialized-in-bss @gol
@@ -8917,6 +8918,30 @@ Even if @option{-fno-fp-int-builtin-inexact} is used, if the functions
 generate a call to a library function then the ``inexact'' exception
 may be raised if the library implementation does not follow TS 18661.
 
+@item -fpermitted-flt-eval-methods=@var{style}
+@opindex fpermitted-flt-eval-methods
+@opindex fpermitted-flt-eval-methods=c11
+@opindex fpermitted-flt-eval-methods=ts-18661-3
+ISO/IEC TS 18661-3 defines new permissible values for
+@code{FLT_EVAL_METHOD} that indicate that operations and constants with
+a semantic type that is an interchange or extended format should be
+evaluated to the precision and range of that type.  These new values are
+a superset of those permitted under C99/C11, which does not specify the
+meaning of other positive values of @code{FLT_EVAL_METHOD}.  As such, code
+conforming to C11 may not have been written expecting the possibility of
+the new values.
+
+@option{-fpermitted-flt-eval-methods} specifies whether the compiler
+should allow only the values of @code{FLT_EVAL_METHOD} specified in C99/C11,
+or the extended set of values specified in ISO/IEC TS 18661-3.
+
+@var{style} is either @code{c11} or @code{ts-18661-3} as appropriate.
+
+The default when in a standards compliant mode (@option{-std=c11} or similar)
+is @option{-fpermitted-flt-eval-methods=c11}.  The default when in a GNU
+dialect (@option{-std=gnu11} or similar) is
+@option{-fpermitted-flt-eval-methods=ts-18661-3}.
+
 @item -fsingle-precision-constant
 @opindex fsingle-precision-constant
 Treat floating-point constants as single precision instead of
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index 816df6b..ac3075b 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -158,6 +158,14 @@ enum excess_precision
   EXCESS_PRECISION_STANDARD
 };
 
+/* The options for which values of FLT_EVAL_METHOD are permissible.  */
+enum permitted_flt_eval_methods
+{
+  PERMITTED_FLT_EVAL_METHODS_DEFAULT,
+  PERMITTED_FLT_EVAL_METHODS_TS_18661,
+  PERMITTED_FLT_EVAL_METHODS_C11
+};
+
 /* Type of stack check.  */
 enum stack_check_type
 {
diff --git a/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_1.c b/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_1.c
new file mode 100644
index 0000000..c022f86
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_1.c
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+/* { dg-options "-std=c11" } */
+
+/* Test that we only see the C99/C11 values for __FLT_EVAL_METHOD__ if
+   we are compiling with -std=c11.  */
+
+int main (int argc, char** argv)
+{
+  switch (__FLT_EVAL_METHOD__)
+    {
+      case 0:
+      case 1:
+      case 2:
+      case -1:
+	return 0;
+      default:
+	return 1;
+    }
+}
diff --git a/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_2.c b/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_2.c
new file mode 100644
index 0000000..a76ea7e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_2.c
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+/* { dg-options "-fpermitted-flt-eval-methods=c11" } */
+
+/* Test that we only see the C99/C11 values for __FLT_EVAL_METHOD__ if
+   we are compiling with -fpermitted-flt-eval-methods=c11.  */
+
+int main (int argc, char** argv)
+{
+  switch (__FLT_EVAL_METHOD__)
+    {
+      case 0:
+      case 1:
+      case 2:
+      case -1:
+	return 0;
+      default:
+	return 1;
+    }
+}

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

* [Patch 1/11] Add a new target hook for describing excess precision intentions
  2016-09-30 16:58 [Patch 0/11] Add support for _Float16 to AArch64 James Greenhalgh
                   ` (3 preceding siblings ...)
  2016-09-30 16:59 ` [Patch 6/11] Migrate excess precision logic to use TARGET_EXCESS_PRECISION James Greenhalgh
@ 2016-09-30 17:01 ` James Greenhalgh
  2016-10-14 16:50   ` James Greenhalgh
  2016-09-30 17:01 ` [Patch 5/11] Add -fpermitted-flt-eval-methods=[c11|ts-18661-3] James Greenhalgh
                   ` (6 subsequent siblings)
  11 siblings, 1 reply; 95+ messages in thread
From: James Greenhalgh @ 2016-09-30 17:01 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd

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


Hi,

This patch introduces TARGET_C_EXCESS_PRECISION. This hook takes a tri-state
argument, one of EXCESS_PRECISION_TYPE_IMPLICIT,
EXCESS_PRECISION_TYPE_STANDARD, EXCESS_PRECISION_TYPE_FAST. Which relate to
the implicit extra precision added by the target, the excess precision that
should be guaranteed for -fexcess-precision=standard, and the excess
precision that should be added for performance under -fexcess-precision=fast .

Bootstrapped and tested in sequence with the other patches in this series
on Arch64, and as a standalone patch on x86_64.

OK?

Thanks
James

---
gcc/

2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>

	* target.def (excess_precision): New hook.
	* target.h (flt_eval_method): New.
	(excess_precision_type): Likewise.
	* targhooks.c (default_excess_precision): New.
	* targhooks.h (default_excess_precision): New.
	* doc/tm.texi.in (TARGET_EXCESS_PRECISION): New.
	* doc/tm.texi: Regenerate.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Patch-1-11-Add-a-new-target-hook-for-describing-exce.patch --]
[-- Type: text/x-patch;  name=0001-Patch-1-11-Add-a-new-target-hook-for-describing-exce.patch, Size: 4790 bytes --]

diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index fe1e984..26b0fa3 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -359,6 +359,24 @@ enum memmodel
   MEMMODEL_SYNC_SEQ_CST = MEMMODEL_SEQ_CST | MEMMODEL_SYNC
 };
 
+/* enums used by the targetm.excess_precision hook.  */
+
+enum flt_eval_method
+{
+  FLT_EVAL_METHOD_UNPREDICTABLE = -1,
+  FLT_EVAL_METHOD_PROMOTE_TO_FLOAT = 0,
+  FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE = 1,
+  FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE = 2,
+  FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16 = 16
+};
+
+enum excess_precision_type
+{
+  EXCESS_PRECISION_TYPE_IMPLICIT,
+  EXCESS_PRECISION_TYPE_STANDARD,
+  EXCESS_PRECISION_TYPE_FAST
+};
+
 /* Support for user-provided GGC and PCH markers.  The first parameter
    is a pointer to a pointer, the second a cookie.  */
 typedef void (*gt_pointer_operator) (void *, void *);
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 8a98ba4..0bdae58 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -947,6 +947,10 @@ sign-extend the result to 64 bits.  On such machines, set
 Do not define this macro if it would never modify @var{m}.
 @end defmac
 
+@deftypefn {Target Hook} {enum flt_eval_method} TARGET_C_EXCESS_PRECISION (enum excess_precision_type @var{type})
+Return a value, with the same meaning as @code{FLT_EVAL_METHOD} C that describes which excess precision should be applied.  @var{type} is either @code{EXCESS_PRECISION_TYPE_IMPLICIT}, @code{EXCESS_PRECISION_TYPE_FAST}, or @code{EXCESS_PRECISION_TYPE_STANDARD}.  For @code{EXCESS_PRECISION_TYPE_IMPLICIT}, the target should return which precision and range operations will be implictly evaluated in regardless of the excess precision explicitly added.  For @code{EXCESS_PRECISION_TYPE_STANDARD} and @code{EXCESS_PRECISION_TYPE_FAST}, the target should return the explicit excess precision that should be added depending on the value set for @code{-fexcess-precision=[standard|fast]}.
+@end deftypefn
+
 @deftypefn {Target Hook} machine_mode TARGET_PROMOTE_FUNCTION_MODE (const_tree @var{type}, machine_mode @var{mode}, int *@var{punsignedp}, const_tree @var{funtype}, int @var{for_return})
 Like @code{PROMOTE_MODE}, but it is applied to outgoing function arguments or
 function return values.  The target hook should return the new mode
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index f1cfc86..7c7af33 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -921,6 +921,8 @@ sign-extend the result to 64 bits.  On such machines, set
 Do not define this macro if it would never modify @var{m}.
 @end defmac
 
+@hook TARGET_C_EXCESS_PRECISION
+
 @hook TARGET_PROMOTE_FUNCTION_MODE
 
 @defmac PARM_BOUNDARY
diff --git a/gcc/target.def b/gcc/target.def
index 83373a5..1542692 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -5402,6 +5402,23 @@ DEFHOOK_UNDOC
  machine_mode, (char c),
  default_mode_for_suffix)
 
+DEFHOOK
+(excess_precision,
+ "Return a value, with the same meaning as @code{FLT_EVAL_METHOD} C that\
+ describes which excess precision should be applied.  @var{type} is\
+ either @code{EXCESS_PRECISION_TYPE_IMPLICIT},\
+ @code{EXCESS_PRECISION_TYPE_FAST}, or\
+ @code{EXCESS_PRECISION_TYPE_STANDARD}.  For\
+ @code{EXCESS_PRECISION_TYPE_IMPLICIT}, the target should return which\
+ precision and range operations will be implictly evaluated in regardless\
+ of the excess precision explicitly added.  For\
+ @code{EXCESS_PRECISION_TYPE_STANDARD} and\
+ @code{EXCESS_PRECISION_TYPE_FAST}, the target should return the\
+ explicit excess precision that should be added depending on the\
+ value set for @code{-fexcess-precision=[standard|fast]}.",
+ enum flt_eval_method, (enum excess_precision_type type),
+ default_excess_precision)
+
 HOOK_VECTOR_END (c)
 
 /* Functions specific to the C++ frontend.  */
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index d75650f..08d0b35 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -2110,4 +2110,12 @@ default_max_noce_ifcvt_seq_cost (edge e)
     return BRANCH_COST (true, predictable_p) * COSTS_N_INSNS (3);
 }
 
+/* Default implementation of TARGET_EXCESS_PRECISION.  */
+
+enum flt_eval_method
+default_excess_precision (enum excess_precision_type ATTRIBUTE_UNUSED)
+{
+  return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT;
+}
+
 #include "gt-targhooks.h"
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index 3356f0a..3fabde7 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -263,4 +263,7 @@ extern bool default_optab_supported_p (int, machine_mode, machine_mode,
 
 extern unsigned int default_max_noce_ifcvt_seq_cost (edge);
 
+extern enum flt_eval_method
+default_excess_precision (enum excess_precision_type ATTRIBUTE_UNUSED);
+
 #endif /* GCC_TARGHOOKS_H */

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

* [Patch 3/11] Implement TARGET_C_EXCESS_PRECISION for s390
  2016-09-30 16:58 [Patch 0/11] Add support for _Float16 to AArch64 James Greenhalgh
                   ` (5 preceding siblings ...)
  2016-09-30 17:01 ` [Patch 5/11] Add -fpermitted-flt-eval-methods=[c11|ts-18661-3] James Greenhalgh
@ 2016-09-30 17:03 ` James Greenhalgh
  2016-09-30 17:41   ` Joseph Myers
  2016-09-30 17:04 ` [Patch libgcc 9/11] Update soft-fp from glibc James Greenhalgh
                   ` (4 subsequent siblings)
  11 siblings, 1 reply; 95+ messages in thread
From: James Greenhalgh @ 2016-09-30 17:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, hpenner, uweigand, Andreas.Krebbel, joseph

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


Hi,

This patch ports the logic from s390's TARGET_FLT_EVAL_METHOD to the new
target hook TARGET_C_EXCESS_PRECISION.

Patch tested by building an s390-none-linux toolchain and running
s390.exp (without the ability to execute) with no regressions, and manually
inspecting the output assembly code when compiling
testsuite/gcc.target/i386/excess-precision* to show no difference in
code-generation.

OK?

Thanks,
James

---
gcc/

2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>

	* config/s390/s390.c (s390_excess_precision): New.
	(TARGET_C_EXCESS_PRECISION): Define.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0003-Patch-3-11-Implement-TARGET_C_EXCESS_PRECISION-for-s.patch --]
[-- Type: text/x-patch;  name=0003-Patch-3-11-Implement-TARGET_C_EXCESS_PRECISION-for-s.patch, Size: 1789 bytes --]

diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 3bdb648..b704d46 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -15106,6 +15106,34 @@ s390_invalid_binary_op (int op ATTRIBUTE_UNUSED, const_tree type1, const_tree ty
   return NULL;
 }
 
+/* Implement TARGET_EXCESS_PRECISION.
+
+   This is used by float.h to define the float_t and double_t data
+   types.  For historical reasons both are double on s390 what cannot
+   be changed anymore.  */
+
+static enum flt_eval_method
+s390_excess_precision (enum excess_precision_type type)
+{
+  switch (type)
+    {
+      case EXCESS_PRECISION_TYPE_FAST:
+	/* The fastest type to promote to will always be the native type,
+	   whether that occurs with implicit excess precision or
+	   otherwise.  */
+	return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT;
+      case EXCESS_PRECISION_TYPE_STANDARD:
+      case EXCESS_PRECISION_TYPE_IMPLICIT:
+	/* Otherwise, the excess precision we want when we are
+	   in a standards compliant mode, and the implicit precision we
+	   provide can be identical.  */
+	return FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE;
+      default:
+	gcc_unreachable ();
+    }
+  return FLT_EVAL_METHOD_UNPREDICTABLE;
+}
+
 /* Initialize GCC target structure.  */
 
 #undef  TARGET_ASM_ALIGNED_HI_OP
@@ -15161,6 +15189,9 @@ s390_invalid_binary_op (int op ATTRIBUTE_UNUSED, const_tree type1, const_tree ty
 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
 
+#undef TARGET_C_EXCESS_PRECISION
+#define TARGET_C_EXCESS_PRECISION s390_excess_precision
+
 #undef  TARGET_SCHED_ADJUST_PRIORITY
 #define TARGET_SCHED_ADJUST_PRIORITY s390_adjust_priority
 #undef TARGET_SCHED_ISSUE_RATE

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

* [Patch libgcc 9/11] Update soft-fp from glibc
  2016-09-30 16:58 [Patch 0/11] Add support for _Float16 to AArch64 James Greenhalgh
                   ` (6 preceding siblings ...)
  2016-09-30 17:03 ` [Patch 3/11] Implement TARGET_C_EXCESS_PRECISION for s390 James Greenhalgh
@ 2016-09-30 17:04 ` James Greenhalgh
  2016-09-30 17:04 ` [Patch 4/11] Implement TARGET_C_EXCESS_PRECISION for m68k James Greenhalgh
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 95+ messages in thread
From: James Greenhalgh @ 2016-09-30 17:04 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, joseph

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


Hi,

This patch merges in the support added to glibc for HFmode conversions in
this patch:

    commit 87ab10d6524fe4faabd7eb3eac5868165ecfb323
    Author: James Greenhalgh <james.greenhalgh@arm.com>
    Date:   Wed Sep 21 21:02:54 2016 +0000

        [soft-fp] Add support for various half-precision conversion routines.

        This patch adds conversion routines required for _Float16 support in
        AArch64.

        These are one-step conversions to and from TImode and TFmode. We need
        these on AArch64 regardless of presence of the ARMv8.2-A 16-bit
        floating-point extensions.

        In the patch, soft-fp/half.h is derived from soft-fp/single.h .  The
        conversion routines are derivatives of their respective SFmode
        variants.

            * soft-fp/extendhftf2.c: New.
            * soft-fp/fixhfti.c: Likewise.
            * soft-fp/fixunshfti.c: Likewise.
            * soft-fp/floattihf.c: Likewise.
            * soft-fp/floatuntihf.c: Likewise.
            * soft-fp/half.h: Likewise.
            * soft-fp/trunctfhf2.c: Likewise.

Any patch merging from upstream is preapproved acording to our commit
policies, but I'll hold off on committing it until the others in this
series have been approved.

Thanks,
James

---
libgcc/

2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>

	* soft-fp/extendhftf2.c: New.
	* soft-fp/fixhfti.c: Likewise.
	* soft-fp/fixunshfti.c: Likewise.
	* soft-fp/floattihf.c: Likewise.
	* soft-fp/floatuntihf.c: Likewise.
	* soft-fp/half.h: Likewise.
	* soft-fp/trunctfhf2.c: Likewise.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0009-Patch-libgcc-9-11-Update-soft-fp-from-glibc.patch --]
[-- Type: text/x-patch;  name=0009-Patch-libgcc-9-11-Update-soft-fp-from-glibc.patch, Size: 17566 bytes --]

diff --git a/libgcc/soft-fp/extendhftf2.c b/libgcc/soft-fp/extendhftf2.c
new file mode 100644
index 0000000..6ff6438
--- /dev/null
+++ b/libgcc/soft-fp/extendhftf2.c
@@ -0,0 +1,53 @@
+/* Software floating-point emulation.
+   Return an IEEE half converted to IEEE quad
+   Copyright (C) 1997-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define FP_NO_EXACT_UNDERFLOW
+#include "soft-fp.h"
+#include "half.h"
+#include "quad.h"
+
+TFtype
+__extendhftf2 (HFtype a)
+{
+  FP_DECL_EX;
+  FP_DECL_H (A);
+  FP_DECL_Q (R);
+  TFtype r;
+
+  FP_INIT_EXCEPTIONS;
+  FP_UNPACK_RAW_H (A, a);
+#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
+  FP_EXTEND (Q, H, 4, 1, R, A);
+#else
+  FP_EXTEND (Q, H, 2, 1, R, A);
+#endif
+  FP_PACK_RAW_Q (r, R);
+  FP_HANDLE_EXCEPTIONS;
+
+  return r;
+}
diff --git a/libgcc/soft-fp/fixhfti.c b/libgcc/soft-fp/fixhfti.c
new file mode 100644
index 0000000..3610f4c
--- /dev/null
+++ b/libgcc/soft-fp/fixhfti.c
@@ -0,0 +1,45 @@
+/* Software floating-point emulation.
+   Convert IEEE half to 128bit signed integer
+   Copyright (C) 2007-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "soft-fp.h"
+#include "half.h"
+
+TItype
+__fixhfti (HFtype a)
+{
+  FP_DECL_EX;
+  FP_DECL_H (A);
+  UTItype r;
+
+  FP_INIT_EXCEPTIONS;
+  FP_UNPACK_RAW_H (A, a);
+  FP_TO_INT_H (r, A, TI_BITS, 1);
+  FP_HANDLE_EXCEPTIONS;
+
+  return r;
+}
diff --git a/libgcc/soft-fp/fixunshfti.c b/libgcc/soft-fp/fixunshfti.c
new file mode 100644
index 0000000..30edbfe
--- /dev/null
+++ b/libgcc/soft-fp/fixunshfti.c
@@ -0,0 +1,45 @@
+/* Software floating-point emulation.
+   Convert IEEE half to 128bit unsigned integer
+   Copyright (C) 2007-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "soft-fp.h"
+#include "half.h"
+
+UTItype
+__fixunshfti (HFtype a)
+{
+  FP_DECL_EX;
+  FP_DECL_H (A);
+  UTItype r;
+
+  FP_INIT_EXCEPTIONS;
+  FP_UNPACK_RAW_H (A, a);
+  FP_TO_INT_H (r, A, TI_BITS, 0);
+  FP_HANDLE_EXCEPTIONS;
+
+  return r;
+}
diff --git a/libgcc/soft-fp/floattihf.c b/libgcc/soft-fp/floattihf.c
new file mode 100644
index 0000000..74ac83a
--- /dev/null
+++ b/libgcc/soft-fp/floattihf.c
@@ -0,0 +1,45 @@
+/* Software floating-point emulation.
+   Convert a 128bit signed integer to IEEE half
+   Copyright (C) 2007-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "soft-fp.h"
+#include "half.h"
+
+HFtype
+__floattihf (TItype i)
+{
+  FP_DECL_EX;
+  FP_DECL_H (A);
+  HFtype a;
+
+  FP_INIT_ROUNDMODE;
+  FP_FROM_INT_H (A, i, TI_BITS, UTItype);
+  FP_PACK_RAW_H (a, A);
+  FP_HANDLE_EXCEPTIONS;
+
+  return a;
+}
diff --git a/libgcc/soft-fp/floatuntihf.c b/libgcc/soft-fp/floatuntihf.c
new file mode 100644
index 0000000..90e77c2
--- /dev/null
+++ b/libgcc/soft-fp/floatuntihf.c
@@ -0,0 +1,45 @@
+/* Software floating-point emulation.
+   Convert a 128bit unsigned integer to IEEE half.
+   Copyright (C) 2007-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "soft-fp.h"
+#include "half.h"
+
+HFtype
+__floatuntihf (UTItype i)
+{
+  FP_DECL_EX;
+  FP_DECL_H (A);
+  HFtype a;
+
+  FP_INIT_ROUNDMODE;
+  FP_FROM_INT_H (A, i, TI_BITS, UTItype);
+  FP_PACK_RAW_H (a, A);
+  FP_HANDLE_EXCEPTIONS;
+
+  return a;
+}
diff --git a/libgcc/soft-fp/half.h b/libgcc/soft-fp/half.h
new file mode 100644
index 0000000..ba75297
--- /dev/null
+++ b/libgcc/soft-fp/half.h
@@ -0,0 +1,170 @@
+/* Software floating-point emulation.
+   Definitions for IEEE Half Precision.
+   Copyright (C) 1997-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef SOFT_FP_HALF_H
+#define SOFT_FP_HALF_H	1
+
+#if _FP_W_TYPE_SIZE < 32
+# error "Here's a nickel kid.  Go buy yourself a real computer."
+#endif
+
+#define _FP_FRACTBITS_H		(_FP_W_TYPE_SIZE)
+
+#define _FP_FRACTBITS_DW_H	(_FP_W_TYPE_SIZE)
+
+#define _FP_FRACBITS_H		11
+#define _FP_FRACXBITS_H		(_FP_FRACTBITS_H - _FP_FRACBITS_H)
+#define _FP_WFRACBITS_H		(_FP_WORKBITS + _FP_FRACBITS_H)
+#define _FP_WFRACXBITS_H	(_FP_FRACTBITS_H - _FP_WFRACBITS_H)
+#define _FP_EXPBITS_H		5
+#define _FP_EXPBIAS_H		15
+#define _FP_EXPMAX_H		31
+
+#define _FP_QNANBIT_H		((_FP_W_TYPE) 1 << (_FP_FRACBITS_H-2))
+#define _FP_QNANBIT_SH_H	((_FP_W_TYPE) 1 << (_FP_FRACBITS_H-2+_FP_WORKBITS))
+#define _FP_IMPLBIT_H		((_FP_W_TYPE) 1 << (_FP_FRACBITS_H-1))
+#define _FP_IMPLBIT_SH_H	((_FP_W_TYPE) 1 << (_FP_FRACBITS_H-1+_FP_WORKBITS))
+#define _FP_OVERFLOW_H		((_FP_W_TYPE) 1 << (_FP_WFRACBITS_H))
+
+#define _FP_WFRACBITS_DW_H	(2 * _FP_WFRACBITS_H)
+#define _FP_WFRACXBITS_DW_H	(_FP_FRACTBITS_DW_H - _FP_WFRACBITS_DW_H)
+#define _FP_HIGHBIT_DW_H	\
+  ((_FP_W_TYPE) 1 << (_FP_WFRACBITS_DW_H - 1) % _FP_W_TYPE_SIZE)
+
+/* The implementation of _FP_MUL_MEAT_H and _FP_DIV_MEAT_H should be
+   chosen by the target machine.  */
+
+typedef float HFtype __attribute__ ((mode (HF)));
+
+union _FP_UNION_H
+{
+  HFtype flt;
+  struct _FP_STRUCT_LAYOUT
+  {
+#if __BYTE_ORDER == __BIG_ENDIAN
+    unsigned sign : 1;
+    unsigned exp  : _FP_EXPBITS_H;
+    unsigned frac : _FP_FRACBITS_H - (_FP_IMPLBIT_H != 0);
+#else
+    unsigned frac : _FP_FRACBITS_H - (_FP_IMPLBIT_H != 0);
+    unsigned exp  : _FP_EXPBITS_H;
+    unsigned sign : 1;
+#endif
+  } bits __attribute__ ((packed));
+};
+
+#define FP_DECL_H(X)		_FP_DECL (1, X)
+#define FP_UNPACK_RAW_H(X, val)	_FP_UNPACK_RAW_1 (H, X, (val))
+#define FP_UNPACK_RAW_HP(X, val)	_FP_UNPACK_RAW_1_P (H, X, (val))
+#define FP_PACK_RAW_H(val, X)	_FP_PACK_RAW_1 (H, (val), X)
+#define FP_PACK_RAW_HP(val, X)			\
+  do						\
+    {						\
+      if (!FP_INHIBIT_RESULTS)			\
+	_FP_PACK_RAW_1_P (H, (val), X);		\
+    }						\
+  while (0)
+
+#define FP_UNPACK_H(X, val)			\
+  do						\
+    {						\
+      _FP_UNPACK_RAW_1 (H, X, (val));		\
+      _FP_UNPACK_CANONICAL (H, 1, X);		\
+    }						\
+  while (0)
+
+#define FP_UNPACK_HP(X, val)			\
+  do						\
+    {						\
+      _FP_UNPACK_RAW_1_P (H, X, (val));		\
+      _FP_UNPACK_CANONICAL (H, 1, X);		\
+    }						\
+  while (0)
+
+#define FP_UNPACK_SEMIRAW_H(X, val)		\
+  do						\
+    {						\
+      _FP_UNPACK_RAW_1 (H, X, (val));		\
+      _FP_UNPACK_SEMIRAW (H, 1, X);		\
+    }						\
+  while (0)
+
+#define FP_UNPACK_SEMIRAW_HP(X, val)		\
+  do						\
+    {						\
+      _FP_UNPACK_RAW_1_P (H, X, (val));		\
+      _FP_UNPACK_SEMIRAW (H, 1, X);		\
+    }						\
+  while (0)
+
+#define FP_PACK_H(val, X)			\
+  do						\
+    {						\
+      _FP_PACK_CANONICAL (H, 1, X);		\
+      _FP_PACK_RAW_1 (H, (val), X);		\
+    }						\
+  while (0)
+
+#define FP_PACK_HP(val, X)			\
+  do						\
+    {						\
+      _FP_PACK_CANONICAL (H, 1, X);		\
+      if (!FP_INHIBIT_RESULTS)			\
+	_FP_PACK_RAW_1_P (H, (val), X);		\
+    }						\
+  while (0)
+
+#define FP_PACK_SEMIRAW_H(val, X)		\
+  do						\
+    {						\
+      _FP_PACK_SEMIRAW (H, 1, X);		\
+      _FP_PACK_RAW_1 (H, (val), X);		\
+    }						\
+  while (0)
+
+#define FP_PACK_SEMIRAW_HP(val, X)		\
+  do						\
+    {						\
+      _FP_PACK_SEMIRAW (H, 1, X);		\
+      if (!FP_INHIBIT_RESULTS)			\
+	_FP_PACK_RAW_1_P (H, (val), X);		\
+    }						\
+  while (0)
+
+#define FP_TO_INT_H(r, X, rsz, rsg)	_FP_TO_INT (H, 1, (r), X, (rsz), (rsg))
+#define FP_TO_INT_ROUND_H(r, X, rsz, rsg)	\
+  _FP_TO_INT_ROUND (H, 1, (r), X, (rsz), (rsg))
+#define FP_FROM_INT_H(X, r, rs, rt)	_FP_FROM_INT (H, 1, X, (r), (rs), rt)
+
+/* HFmode arithmetic is not implemented.  */
+
+#define _FP_FRAC_HIGH_H(X)	_FP_FRAC_HIGH_1 (X)
+#define _FP_FRAC_HIGH_RAW_H(X)	_FP_FRAC_HIGH_1 (X)
+#define _FP_FRAC_HIGH_DW_H(X)	_FP_FRAC_HIGH_1 (X)
+
+#endif /* !SOFT_FP_HALF_H */
diff --git a/libgcc/soft-fp/trunctfhf2.c b/libgcc/soft-fp/trunctfhf2.c
new file mode 100644
index 0000000..0500b14
--- /dev/null
+++ b/libgcc/soft-fp/trunctfhf2.c
@@ -0,0 +1,52 @@
+/* Software floating-point emulation.
+   Truncate IEEE quad into IEEE half.
+   Copyright (C) 1997-2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "soft-fp.h"
+#include "half.h"
+#include "quad.h"
+
+HFtype
+__trunctfhf2 (TFtype a)
+{
+  FP_DECL_EX;
+  FP_DECL_Q (A);
+  FP_DECL_H (R);
+  HFtype r;
+
+  FP_INIT_ROUNDMODE;
+  FP_UNPACK_SEMIRAW_Q (A, a);
+#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
+  FP_TRUNC (H, Q, 1, 4, R, A);
+#else
+  FP_TRUNC (H, Q, 1, 2, R, A);
+#endif
+  FP_PACK_SEMIRAW_H (r, R);
+  FP_HANDLE_EXCEPTIONS;
+
+  return r;
+}

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

* [Patch libgcc AArch64 10/11] Enable hfmode soft-float conversions and truncations
  2016-09-30 17:05 ` [Patch libgcc 9/11] Update soft-fp from glibc James Greenhalgh
@ 2016-09-30 17:04   ` James Greenhalgh
  2016-09-30 17:14   ` [Patch AArch64 11/11] Enable _Float16 James Greenhalgh
  1 sibling, 0 replies; 95+ messages in thread
From: James Greenhalgh @ 2016-09-30 17:04 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, joseph, richard.earnshaw, marcus.shawcroft

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


Hi,

This patch enables the conversion functions we need for AArch64's _Float16
support. To do that we need to implement TARGET_SCALAR_MODE_SUPPORTED_P,
so do that now.

OK?

Thanks,
James

---
gcc/

2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>

	* config/aarch64/aarch64-c.c (aarch64_scalar_mode_supported_p): New.
	(TARGET_SCALAR_MODE_SUPPORTED_P): Define.

libgcc/

2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>

	* config/aarch64/sfp-machine.h (_FP_NANFRAC_H): Define.
	(_FP_NANSIGN_H): Likewise.
	* config/aarch64/t-softfp (softfp_extensions): Add hftf.
	(softfp_truncations): Add tfhf.
	(softfp_extras): Add required conversion functions.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0010-Patch-libgcc-AArch64-10-11-Enable-hfmode-soft-float-.patch --]
[-- Type: text/x-patch;  name=0010-Patch-libgcc-AArch64-10-11-Enable-hfmode-soft-float-.patch, Size: 2301 bytes --]

diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index df6514d..cda85de 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -14054,6 +14054,17 @@ aarch64_optab_supported_p (int op, machine_mode mode1, machine_mode,
     }
 }
 
+/* Implement TARGET_SCALAR_MODE_SUPPORTED_P - return TRUE
+   if MODE is HFmode, and punt to the generic implementation otherwise.  */
+
+static bool
+aarch64_scalar_mode_supported_p (machine_mode mode)
+{
+  return (mode == HFmode
+	  ? true
+	  : default_scalar_mode_supported_p (mode));
+}
+
 #undef TARGET_ADDRESS_COST
 #define TARGET_ADDRESS_COST aarch64_address_cost
 
@@ -14264,6 +14275,9 @@ aarch64_optab_supported_p (int op, machine_mode mode1, machine_mode,
 #undef TARGET_RTX_COSTS
 #define TARGET_RTX_COSTS aarch64_rtx_costs_wrapper
 
+#undef TARGET_SCALAR_MODE_SUPPORTED_P
+#define TARGET_SCALAR_MODE_SUPPORTED_P aarch64_scalar_mode_supported_p
+
 #undef TARGET_SCHED_ISSUE_RATE
 #define TARGET_SCHED_ISSUE_RATE aarch64_sched_issue_rate
 
diff --git a/libgcc/config/aarch64/sfp-machine.h b/libgcc/config/aarch64/sfp-machine.h
index 5efa245..da154dd 100644
--- a/libgcc/config/aarch64/sfp-machine.h
+++ b/libgcc/config/aarch64/sfp-machine.h
@@ -42,9 +42,11 @@ typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__)));
 
 #define _FP_DIV_MEAT_Q(R,X,Y)	_FP_DIV_MEAT_2_udiv(Q,R,X,Y)
 
+#define _FP_NANFRAC_H		((_FP_QNANBIT_H << 1) - 1)
 #define _FP_NANFRAC_S		((_FP_QNANBIT_S << 1) - 1)
 #define _FP_NANFRAC_D		((_FP_QNANBIT_D << 1) - 1)
 #define _FP_NANFRAC_Q		((_FP_QNANBIT_Q << 1) - 1), -1
+#define _FP_NANSIGN_H		0
 #define _FP_NANSIGN_S		0
 #define _FP_NANSIGN_D		0
 #define _FP_NANSIGN_Q		0
diff --git a/libgcc/config/aarch64/t-softfp b/libgcc/config/aarch64/t-softfp
index 586dca2..c4ce0dc 100644
--- a/libgcc/config/aarch64/t-softfp
+++ b/libgcc/config/aarch64/t-softfp
@@ -1,8 +1,9 @@
 softfp_float_modes := tf
 softfp_int_modes := si di ti
-softfp_extensions := sftf dftf
-softfp_truncations := tfsf tfdf
+softfp_extensions := sftf dftf hftf
+softfp_truncations := tfsf tfdf tfhf
 softfp_exclude_libgcc2 := n
+softfp_extras := fixhfti fixunshfti floattihf floatuntihf
 
 TARGET_LIBGCC2_CFLAGS += -Wno-missing-prototypes
 

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

* [Patch 4/11] Implement TARGET_C_EXCESS_PRECISION for m68k
  2016-09-30 16:58 [Patch 0/11] Add support for _Float16 to AArch64 James Greenhalgh
                   ` (7 preceding siblings ...)
  2016-09-30 17:04 ` [Patch libgcc 9/11] Update soft-fp from glibc James Greenhalgh
@ 2016-09-30 17:04 ` James Greenhalgh
  2016-09-30 17:32   ` Jeff Law
  2016-09-30 18:25   ` Andreas Schwab
  2016-09-30 17:05 ` [Patch libgcc 9/11] Update soft-fp from glibc James Greenhalgh
                   ` (2 subsequent siblings)
  11 siblings, 2 replies; 95+ messages in thread
From: James Greenhalgh @ 2016-09-30 17:04 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, joseph, law, schwab

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


Hi,

This patch ports the logic from m68k's TARGET_FLT_EVAL_METHOD to the new
target hook TARGET_C_EXCESS_PRECISION.

Patch tested by building an m68k-none-elf toolchain and running
m68k.exp (without the ability to execute) with no regressions, and manually
inspecting the output assembly code when compiling
testsuite/gcc.target/i386/excess-precision* to show no difference in
code-generation.

OK?

Thanks,
James

---
gcc/

2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>

	* config/m68k/m68k.c (m68k_excess_precision): New.
	(TARGET_C_EXCESS_PRECISION): Define.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0004-Patch-4-11-Implement-TARGET_C_EXCESS_PRECISION-for-m.patch --]
[-- Type: text/x-patch;  name=0004-Patch-4-11-Implement-TARGET_C_EXCESS_PRECISION-for-m.patch, Size: 2199 bytes --]

diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
index a104193..c858d7e 100644
--- a/gcc/config/m68k/m68k.c
+++ b/gcc/config/m68k/m68k.c
@@ -182,6 +182,8 @@ static rtx m68k_function_arg (cumulative_args_t, machine_mode,
 static bool m68k_cannot_force_const_mem (machine_mode mode, rtx x);
 static bool m68k_output_addr_const_extra (FILE *, rtx);
 static void m68k_init_sync_libfuncs (void) ATTRIBUTE_UNUSED;
+static enum flt_eval_method
+m68k_excess_precision (enum excess_precision_type);
 \f
 /* Initialize the GCC target structure.  */
 
@@ -322,6 +324,9 @@ static void m68k_init_sync_libfuncs (void) ATTRIBUTE_UNUSED;
 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA m68k_output_addr_const_extra
 
+#undef TARGET_EXCESS_PRECISION
+#define TARGET_EXCESS_PRECISION m68k_excess_precision
+
 /* The value stored by TAS.  */
 #undef TARGET_ATOMIC_TEST_AND_SET_TRUEVAL
 #define TARGET_ATOMIC_TEST_AND_SET_TRUEVAL 128
@@ -6528,4 +6533,36 @@ m68k_epilogue_uses (int regno ATTRIBUTE_UNUSED)
 	      == m68k_fk_interrupt_handler));
 }
 
+
+/* Implement TARGET_EXCESS_PRECISION.
+
+   Set the value of FLT_EVAL_METHOD in float.h.  When using 68040 fp
+   instructions, we get proper intermediate rounding, otherwise we
+   get extended precision results.  */
+
+static enum flt_eval_method
+m68k_excess_precision (enum excess_precision_type type)
+{
+  switch (type)
+    {
+      case EXCESS_PRECISION_TYPE_FAST:
+	/* The fastest type to promote to will always be the native type,
+	   whether that occurs with implicit excess precision or
+	   otherwise.  */
+	return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT;
+      case EXCESS_PRECISION_TYPE_STANDARD:
+      case EXCESS_PRECISION_TYPE_IMPLICIT:
+	/* Otherwise, the excess precision we want when we are
+	   in a standards compliant mode, and the implicit precision we
+	   provide can be identical.  */
+	if (TARGET_68040 || ! TARGET_68881)
+	  return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT;
+
+	return FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE;
+      default:
+	gcc_unreachable ();
+    }
+  return FLT_EVAL_METHOD_UNPREDICTABLE;
+}
+
 #include "gt-m68k.h"

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

* [Patch libgcc 9/11] Update soft-fp from glibc
  2016-09-30 16:58 [Patch 0/11] Add support for _Float16 to AArch64 James Greenhalgh
                   ` (8 preceding siblings ...)
  2016-09-30 17:04 ` [Patch 4/11] Implement TARGET_C_EXCESS_PRECISION for m68k James Greenhalgh
@ 2016-09-30 17:05 ` 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-24 13:45 ` [Patch 0/4] [ARM] Enable _Float16 on ARM James Greenhalgh
  2016-11-11 15:38 ` [Patch v4 0/17] Add support for _Float16 to AArch64 and ARM James Greenhalgh
  11 siblings, 2 replies; 95+ messages in thread
From: James Greenhalgh @ 2016-09-30 17:05 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, joseph, richard.earnshaw, marcus.shawcroft

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


Hi,

This patch merges in the support added to glibc for HFmode conversions in
this patch:

    commit 87ab10d6524fe4faabd7eb3eac5868165ecfb323
    Author: James Greenhalgh <james.greenhalgh@arm.com>
    Date:   Wed Sep 21 21:02:54 2016 +0000

        [soft-fp] Add support for various half-precision conversion routines.

        This patch adds conversion routines required for _Float16 support in
        AArch64.

        These are one-step conversions to and from TImode and TFmode. We need
        these on AArch64 regardless of presence of the ARMv8.2-A 16-bit
        floating-point extensions.

        In the patch, soft-fp/half.h is derived from soft-fp/single.h .  The
        conversion routines are derivatives of their respective SFmode
        variants.

            * soft-fp/extendhftf2.c: New.
            * soft-fp/fixhfti.c: Likewise.
            * soft-fp/fixunshfti.c: Likewise.
            * soft-fp/floattihf.c: Likewise.
            * soft-fp/floatuntihf.c: Likewise.
            * soft-fp/half.h: Likewise.
            * soft-fp/trunctfhf2.c: Likewise.

Any patch merging from upstream is preapproved acording to our commit
policies, but I'll hold off on committing it until the others in this
series have been approved.

Thanks,
James

---
libgcc/

2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>

	* soft-fp/extendhftf2.c: New.
	* soft-fp/fixhfti.c: Likewise.
	* soft-fp/fixunshfti.c: Likewise.
	* soft-fp/floattihf.c: Likewise.
	* soft-fp/floatuntihf.c: Likewise.
	* soft-fp/half.h: Likewise.
	* soft-fp/trunctfhf2.c: Likewise.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0009-Patch-libgcc-9-11-Update-soft-fp-from-glibc.patch --]
[-- Type: text/x-patch;  name=0009-Patch-libgcc-9-11-Update-soft-fp-from-glibc.patch, Size: 17566 bytes --]

diff --git a/libgcc/soft-fp/extendhftf2.c b/libgcc/soft-fp/extendhftf2.c
new file mode 100644
index 0000000..6ff6438
--- /dev/null
+++ b/libgcc/soft-fp/extendhftf2.c
@@ -0,0 +1,53 @@
+/* Software floating-point emulation.
+   Return an IEEE half converted to IEEE quad
+   Copyright (C) 1997-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define FP_NO_EXACT_UNDERFLOW
+#include "soft-fp.h"
+#include "half.h"
+#include "quad.h"
+
+TFtype
+__extendhftf2 (HFtype a)
+{
+  FP_DECL_EX;
+  FP_DECL_H (A);
+  FP_DECL_Q (R);
+  TFtype r;
+
+  FP_INIT_EXCEPTIONS;
+  FP_UNPACK_RAW_H (A, a);
+#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
+  FP_EXTEND (Q, H, 4, 1, R, A);
+#else
+  FP_EXTEND (Q, H, 2, 1, R, A);
+#endif
+  FP_PACK_RAW_Q (r, R);
+  FP_HANDLE_EXCEPTIONS;
+
+  return r;
+}
diff --git a/libgcc/soft-fp/fixhfti.c b/libgcc/soft-fp/fixhfti.c
new file mode 100644
index 0000000..3610f4c
--- /dev/null
+++ b/libgcc/soft-fp/fixhfti.c
@@ -0,0 +1,45 @@
+/* Software floating-point emulation.
+   Convert IEEE half to 128bit signed integer
+   Copyright (C) 2007-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "soft-fp.h"
+#include "half.h"
+
+TItype
+__fixhfti (HFtype a)
+{
+  FP_DECL_EX;
+  FP_DECL_H (A);
+  UTItype r;
+
+  FP_INIT_EXCEPTIONS;
+  FP_UNPACK_RAW_H (A, a);
+  FP_TO_INT_H (r, A, TI_BITS, 1);
+  FP_HANDLE_EXCEPTIONS;
+
+  return r;
+}
diff --git a/libgcc/soft-fp/fixunshfti.c b/libgcc/soft-fp/fixunshfti.c
new file mode 100644
index 0000000..30edbfe
--- /dev/null
+++ b/libgcc/soft-fp/fixunshfti.c
@@ -0,0 +1,45 @@
+/* Software floating-point emulation.
+   Convert IEEE half to 128bit unsigned integer
+   Copyright (C) 2007-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "soft-fp.h"
+#include "half.h"
+
+UTItype
+__fixunshfti (HFtype a)
+{
+  FP_DECL_EX;
+  FP_DECL_H (A);
+  UTItype r;
+
+  FP_INIT_EXCEPTIONS;
+  FP_UNPACK_RAW_H (A, a);
+  FP_TO_INT_H (r, A, TI_BITS, 0);
+  FP_HANDLE_EXCEPTIONS;
+
+  return r;
+}
diff --git a/libgcc/soft-fp/floattihf.c b/libgcc/soft-fp/floattihf.c
new file mode 100644
index 0000000..74ac83a
--- /dev/null
+++ b/libgcc/soft-fp/floattihf.c
@@ -0,0 +1,45 @@
+/* Software floating-point emulation.
+   Convert a 128bit signed integer to IEEE half
+   Copyright (C) 2007-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "soft-fp.h"
+#include "half.h"
+
+HFtype
+__floattihf (TItype i)
+{
+  FP_DECL_EX;
+  FP_DECL_H (A);
+  HFtype a;
+
+  FP_INIT_ROUNDMODE;
+  FP_FROM_INT_H (A, i, TI_BITS, UTItype);
+  FP_PACK_RAW_H (a, A);
+  FP_HANDLE_EXCEPTIONS;
+
+  return a;
+}
diff --git a/libgcc/soft-fp/floatuntihf.c b/libgcc/soft-fp/floatuntihf.c
new file mode 100644
index 0000000..90e77c2
--- /dev/null
+++ b/libgcc/soft-fp/floatuntihf.c
@@ -0,0 +1,45 @@
+/* Software floating-point emulation.
+   Convert a 128bit unsigned integer to IEEE half.
+   Copyright (C) 2007-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "soft-fp.h"
+#include "half.h"
+
+HFtype
+__floatuntihf (UTItype i)
+{
+  FP_DECL_EX;
+  FP_DECL_H (A);
+  HFtype a;
+
+  FP_INIT_ROUNDMODE;
+  FP_FROM_INT_H (A, i, TI_BITS, UTItype);
+  FP_PACK_RAW_H (a, A);
+  FP_HANDLE_EXCEPTIONS;
+
+  return a;
+}
diff --git a/libgcc/soft-fp/half.h b/libgcc/soft-fp/half.h
new file mode 100644
index 0000000..ba75297
--- /dev/null
+++ b/libgcc/soft-fp/half.h
@@ -0,0 +1,170 @@
+/* Software floating-point emulation.
+   Definitions for IEEE Half Precision.
+   Copyright (C) 1997-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef SOFT_FP_HALF_H
+#define SOFT_FP_HALF_H	1
+
+#if _FP_W_TYPE_SIZE < 32
+# error "Here's a nickel kid.  Go buy yourself a real computer."
+#endif
+
+#define _FP_FRACTBITS_H		(_FP_W_TYPE_SIZE)
+
+#define _FP_FRACTBITS_DW_H	(_FP_W_TYPE_SIZE)
+
+#define _FP_FRACBITS_H		11
+#define _FP_FRACXBITS_H		(_FP_FRACTBITS_H - _FP_FRACBITS_H)
+#define _FP_WFRACBITS_H		(_FP_WORKBITS + _FP_FRACBITS_H)
+#define _FP_WFRACXBITS_H	(_FP_FRACTBITS_H - _FP_WFRACBITS_H)
+#define _FP_EXPBITS_H		5
+#define _FP_EXPBIAS_H		15
+#define _FP_EXPMAX_H		31
+
+#define _FP_QNANBIT_H		((_FP_W_TYPE) 1 << (_FP_FRACBITS_H-2))
+#define _FP_QNANBIT_SH_H	((_FP_W_TYPE) 1 << (_FP_FRACBITS_H-2+_FP_WORKBITS))
+#define _FP_IMPLBIT_H		((_FP_W_TYPE) 1 << (_FP_FRACBITS_H-1))
+#define _FP_IMPLBIT_SH_H	((_FP_W_TYPE) 1 << (_FP_FRACBITS_H-1+_FP_WORKBITS))
+#define _FP_OVERFLOW_H		((_FP_W_TYPE) 1 << (_FP_WFRACBITS_H))
+
+#define _FP_WFRACBITS_DW_H	(2 * _FP_WFRACBITS_H)
+#define _FP_WFRACXBITS_DW_H	(_FP_FRACTBITS_DW_H - _FP_WFRACBITS_DW_H)
+#define _FP_HIGHBIT_DW_H	\
+  ((_FP_W_TYPE) 1 << (_FP_WFRACBITS_DW_H - 1) % _FP_W_TYPE_SIZE)
+
+/* The implementation of _FP_MUL_MEAT_H and _FP_DIV_MEAT_H should be
+   chosen by the target machine.  */
+
+typedef float HFtype __attribute__ ((mode (HF)));
+
+union _FP_UNION_H
+{
+  HFtype flt;
+  struct _FP_STRUCT_LAYOUT
+  {
+#if __BYTE_ORDER == __BIG_ENDIAN
+    unsigned sign : 1;
+    unsigned exp  : _FP_EXPBITS_H;
+    unsigned frac : _FP_FRACBITS_H - (_FP_IMPLBIT_H != 0);
+#else
+    unsigned frac : _FP_FRACBITS_H - (_FP_IMPLBIT_H != 0);
+    unsigned exp  : _FP_EXPBITS_H;
+    unsigned sign : 1;
+#endif
+  } bits __attribute__ ((packed));
+};
+
+#define FP_DECL_H(X)		_FP_DECL (1, X)
+#define FP_UNPACK_RAW_H(X, val)	_FP_UNPACK_RAW_1 (H, X, (val))
+#define FP_UNPACK_RAW_HP(X, val)	_FP_UNPACK_RAW_1_P (H, X, (val))
+#define FP_PACK_RAW_H(val, X)	_FP_PACK_RAW_1 (H, (val), X)
+#define FP_PACK_RAW_HP(val, X)			\
+  do						\
+    {						\
+      if (!FP_INHIBIT_RESULTS)			\
+	_FP_PACK_RAW_1_P (H, (val), X);		\
+    }						\
+  while (0)
+
+#define FP_UNPACK_H(X, val)			\
+  do						\
+    {						\
+      _FP_UNPACK_RAW_1 (H, X, (val));		\
+      _FP_UNPACK_CANONICAL (H, 1, X);		\
+    }						\
+  while (0)
+
+#define FP_UNPACK_HP(X, val)			\
+  do						\
+    {						\
+      _FP_UNPACK_RAW_1_P (H, X, (val));		\
+      _FP_UNPACK_CANONICAL (H, 1, X);		\
+    }						\
+  while (0)
+
+#define FP_UNPACK_SEMIRAW_H(X, val)		\
+  do						\
+    {						\
+      _FP_UNPACK_RAW_1 (H, X, (val));		\
+      _FP_UNPACK_SEMIRAW (H, 1, X);		\
+    }						\
+  while (0)
+
+#define FP_UNPACK_SEMIRAW_HP(X, val)		\
+  do						\
+    {						\
+      _FP_UNPACK_RAW_1_P (H, X, (val));		\
+      _FP_UNPACK_SEMIRAW (H, 1, X);		\
+    }						\
+  while (0)
+
+#define FP_PACK_H(val, X)			\
+  do						\
+    {						\
+      _FP_PACK_CANONICAL (H, 1, X);		\
+      _FP_PACK_RAW_1 (H, (val), X);		\
+    }						\
+  while (0)
+
+#define FP_PACK_HP(val, X)			\
+  do						\
+    {						\
+      _FP_PACK_CANONICAL (H, 1, X);		\
+      if (!FP_INHIBIT_RESULTS)			\
+	_FP_PACK_RAW_1_P (H, (val), X);		\
+    }						\
+  while (0)
+
+#define FP_PACK_SEMIRAW_H(val, X)		\
+  do						\
+    {						\
+      _FP_PACK_SEMIRAW (H, 1, X);		\
+      _FP_PACK_RAW_1 (H, (val), X);		\
+    }						\
+  while (0)
+
+#define FP_PACK_SEMIRAW_HP(val, X)		\
+  do						\
+    {						\
+      _FP_PACK_SEMIRAW (H, 1, X);		\
+      if (!FP_INHIBIT_RESULTS)			\
+	_FP_PACK_RAW_1_P (H, (val), X);		\
+    }						\
+  while (0)
+
+#define FP_TO_INT_H(r, X, rsz, rsg)	_FP_TO_INT (H, 1, (r), X, (rsz), (rsg))
+#define FP_TO_INT_ROUND_H(r, X, rsz, rsg)	\
+  _FP_TO_INT_ROUND (H, 1, (r), X, (rsz), (rsg))
+#define FP_FROM_INT_H(X, r, rs, rt)	_FP_FROM_INT (H, 1, X, (r), (rs), rt)
+
+/* HFmode arithmetic is not implemented.  */
+
+#define _FP_FRAC_HIGH_H(X)	_FP_FRAC_HIGH_1 (X)
+#define _FP_FRAC_HIGH_RAW_H(X)	_FP_FRAC_HIGH_1 (X)
+#define _FP_FRAC_HIGH_DW_H(X)	_FP_FRAC_HIGH_1 (X)
+
+#endif /* !SOFT_FP_HALF_H */
diff --git a/libgcc/soft-fp/trunctfhf2.c b/libgcc/soft-fp/trunctfhf2.c
new file mode 100644
index 0000000..0500b14
--- /dev/null
+++ b/libgcc/soft-fp/trunctfhf2.c
@@ -0,0 +1,52 @@
+/* Software floating-point emulation.
+   Truncate IEEE quad into IEEE half.
+   Copyright (C) 1997-2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "soft-fp.h"
+#include "half.h"
+#include "quad.h"
+
+HFtype
+__trunctfhf2 (TFtype a)
+{
+  FP_DECL_EX;
+  FP_DECL_Q (A);
+  FP_DECL_H (R);
+  HFtype r;
+
+  FP_INIT_ROUNDMODE;
+  FP_UNPACK_SEMIRAW_Q (A, a);
+#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
+  FP_TRUNC (H, Q, 1, 4, R, A);
+#else
+  FP_TRUNC (H, Q, 1, 2, R, A);
+#endif
+  FP_PACK_SEMIRAW_H (r, R);
+  FP_HANDLE_EXCEPTIONS;
+
+  return r;
+}

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

* [Patch AArch64 11/11] Enable _Float16
  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   ` James Greenhalgh
  2016-10-14 17:02     ` James Greenhalgh
  1 sibling, 1 reply; 95+ messages in thread
From: James Greenhalgh @ 2016-09-30 17:14 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, joseph, richard.earnshaw, marcus.shawcroft

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


Hi,

Finally, this patch adds the back-end wiring to get AArch64 support for
the _Float16 type working.

Bootstrapped on AArch64 with no issues.

OK?

Thanks,
James

---
2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>

	* config/aarch64/aarch64-c.c (aarch64_update_cpp_builtins): Update
	__FLT_EVAL_METHOD__ and __FLT_EVAL_METHOD_C99__ when we switch
	architecture levels.
	* config/aarch64/aarch64.c (aarch64_promoted_type): Only promote
	the aarch64_fp16_type_node, not all HFmode types.
	(aarch64_libgcc_floating_mode_supported_p): Support HFmode.
	(aarch64_scalar_mode_supported_p): Likewise.
	(aarch64_excess_precision): New.
	(TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P): Define.
	(TARGET_SCALAR_MODE_SUPPORTED_P): Likewise.
	(TARGET_C_EXCESS_PRECISION): Likewise.

2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>

	* gcc.target/aarch64/_Float16_1.c: New.
	* gcc.target/aarch64/_Float16_2.c: Likewise.
	* gcc.target/aarch64/_Float16_3.c: Likewise.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0011-Patch-AArch64-11-11-Enable-_Float16.patch --]
[-- Type: text/x-patch;  name=0011-Patch-AArch64-11-11-Enable-_Float16.patch, Size: 9716 bytes --]

diff --git a/gcc/config/aarch64/aarch64-c.c b/gcc/config/aarch64/aarch64-c.c
index 3380ed6..9982512 100644
--- a/gcc/config/aarch64/aarch64-c.c
+++ b/gcc/config/aarch64/aarch64-c.c
@@ -132,6 +132,16 @@ aarch64_update_cpp_builtins (cpp_reader *pfile)
 
   aarch64_def_or_undef (TARGET_CRYPTO, "__ARM_FEATURE_CRYPTO", pfile);
   aarch64_def_or_undef (TARGET_SIMD_RDMA, "__ARM_FEATURE_QRDMX", pfile);
+
+  /* Not for ACLE, but required to keep "float.h" correct if we switch
+     target between implementations that do or do not support ARMv8.2-A
+     16-bit floating-point extensions.  */
+  cpp_undef (pfile, "__FLT_EVAL_METHOD__");
+  builtin_define_with_int_value ("__FLT_EVAL_METHOD__",
+				 c_flt_eval_method (true));
+  cpp_undef (pfile, "__FLT_EVAL_METHOD_C99__");
+  builtin_define_with_int_value ("__FLT_EVAL_METHOD_C99__",
+				 c_flt_eval_method (false));
 }
 
 /* Implement TARGET_CPU_CPP_BUILTINS.  */
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index cda85de..01e1ca0 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -14029,12 +14029,19 @@ aarch64_vec_fpconst_pow_of_2 (rtx x)
   return firstval;
 }
 
-/* Implement TARGET_PROMOTED_TYPE to promote __fp16 to float.  */
+/* Implement TARGET_PROMOTED_TYPE to promote 16-bit floating point types
+   to float.
+
+   __fp16 always promotes through this hook.
+   _Float16 may promote if TARGET_FLT_EVAL_METHOD is 16, but we do that
+   through the generic excess precision logic rather than here.  */
+
 static tree
 aarch64_promoted_type (const_tree t)
 {
-  if (SCALAR_FLOAT_TYPE_P (t) && TYPE_PRECISION (t) == 16)
+  if (t == aarch64_fp16_type_node)
     return float_type_node;
+
   return NULL_TREE;
 }
 
@@ -14054,6 +14061,17 @@ aarch64_optab_supported_p (int op, machine_mode mode1, machine_mode,
     }
 }
 
+/* Implement TARGET_LIBGCC_FLOATING_POINT_MODE_SUPPORTED_P - return TRUE
+   if MODE is HFmode, and punt to the generic implementation otherwise.  */
+
+static bool
+aarch64_libgcc_floating_mode_supported_p (machine_mode mode)
+{
+  return (mode == HFmode
+	  ? true
+	  : default_libgcc_floating_mode_supported_p (mode));
+}
+
 /* Implement TARGET_SCALAR_MODE_SUPPORTED_P - return TRUE
    if MODE is HFmode, and punt to the generic implementation otherwise.  */
 
@@ -14065,6 +14083,47 @@ aarch64_scalar_mode_supported_p (machine_mode mode)
 	  : default_scalar_mode_supported_p (mode));
 }
 
+/* Set the value of FLT_EVAL_METHOD.
+   ISO/IEC TS 18661-3 defines two values that we'd like to make use of:
+
+    0: evaluate all operations and constants, whose semantic type has at
+       most the range and precision of type float, to the range and
+       precision of float; evaluate all other operations and constants to
+       the range and precision of the semantic type;
+
+    N, where _FloatN is a supported interchange floating type
+       evaluate all operations and constants, whose semantic type has at
+       most the range and precision of _FloatN type, to the range and
+       precision of the _FloatN type; evaluate all other operations and
+       constants to the range and precision of the semantic type;
+
+   If we have the ARMv8.2-A extensions then we support _Float16 in native
+   precision, so we should set this to 16.  Otherwise, we support the type,
+   but want to evaluate expressions in float precision, so set this to
+   0.  */
+
+static enum flt_eval_method
+aarch64_excess_precision (enum excess_precision_type type)
+{
+  switch (type)
+    {
+      case EXCESS_PRECISION_TYPE_FAST:
+      case EXCESS_PRECISION_TYPE_STANDARD:
+	/* We can calculate either in 16-bit range and precision or
+	   32-bit range and precision.  Make that decision based on whether
+	   we have native support for the ARMv8.2-A 16-bit floating-point
+	   instructions or not.  */
+	return (TARGET_FP_F16INST
+		? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16
+		: FLT_EVAL_METHOD_PROMOTE_TO_FLOAT);
+      case EXCESS_PRECISION_TYPE_IMPLICIT:
+	return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16;
+      default:
+	gcc_unreachable ();
+    }
+  return FLT_EVAL_METHOD_UNPREDICTABLE;
+}
+
 #undef TARGET_ADDRESS_COST
 #define TARGET_ADDRESS_COST aarch64_address_cost
 
@@ -14143,6 +14202,9 @@ aarch64_scalar_mode_supported_p (machine_mode mode)
 #undef TARGET_BUILTIN_RECIPROCAL
 #define TARGET_BUILTIN_RECIPROCAL aarch64_builtin_reciprocal
 
+#undef TARGET_C_EXCESS_PRECISION
+#define TARGET_C_EXCESS_PRECISION aarch64_excess_precision
+
 #undef  TARGET_EXPAND_BUILTIN
 #define TARGET_EXPAND_BUILTIN aarch64_expand_builtin
 
@@ -14199,6 +14261,10 @@ aarch64_scalar_mode_supported_p (machine_mode mode)
 #undef TARGET_LIBGCC_CMP_RETURN_MODE
 #define TARGET_LIBGCC_CMP_RETURN_MODE aarch64_libgcc_cmp_return_mode
 
+#undef TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P
+#define TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P \
+aarch64_libgcc_floating_mode_supported_p
+
 #undef TARGET_MANGLE_TYPE
 #define TARGET_MANGLE_TYPE aarch64_mangle_type
 
diff --git a/gcc/testsuite/gcc.target/aarch64/_Float16_1.c b/gcc/testsuite/gcc.target/aarch64/_Float16_1.c
new file mode 100644
index 0000000..320f154
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/_Float16_1.c
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=armv8.2-a+nofp16" } */
+
+#pragma GCC target ("arch=armv8.2-a+nofp16")
+
+_Float16
+foo_v8 (_Float16 x, _Float16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+__fp16
+bar_v8 (__fp16 x, __fp16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+#pragma GCC target ("arch=armv8.2-a+fp16")
+
+_Float16
+foo_v82 (_Float16 x, _Float16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+__fp16
+bar_v82 (__fp16 x, __fp16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+/* Test that we merge to FMA operations.  This indicates that we are not
+   making extraneous conversions between modes.  */
+
+/* Three FMA operations in 32-bit precision, from foo_v8, bar_v8, bar_v82.  */
+/* { dg-final { scan-assembler-times "fmadd\ts\[0-9\]\+" 3 } } */
+
+/* One FMA operation in 16-bit precision, from foo_v82.  */
+/* { dg-final { scan-assembler-times "fmadd\th\[0-9\]\+" 1 } } */
+
+/* Test that we are resetting the __FLT_EVAL_METHOD__.  */
+/* { dg-final { scan-assembler-times "mov\tw\[0-9\]\+, 16" 2 } } */
+/* { dg-final { scan-assembler-times "str\twzr" 2 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/_Float16_2.c b/gcc/testsuite/gcc.target/aarch64/_Float16_2.c
new file mode 100644
index 0000000..8b2aa1e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/_Float16_2.c
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=armv8.2-a+nofp16 -fpermitted-flt-eval-methods=c11" } */
+
+#pragma GCC target ("arch=armv8.2-a+nofp16")
+
+_Float16
+foo_v8 (_Float16 x, _Float16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+__fp16
+bar_v8 (__fp16 x, __fp16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+#pragma GCC target ("arch=armv8.2-a+fp16")
+
+_Float16
+foo_v82 (_Float16 x, _Float16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+__fp16
+bar_v82 (__fp16 x, __fp16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+/* Test that we merge to FMA operations.  This indicates that we are not
+   making extraneous conversions between modes.  */
+
+/* Three FMA operations in 32-bit precision, from foo_v8, bar_v8, bar_v82.  */
+/* { dg-final { scan-assembler-times "fmadd\ts\[0-9\]\+" 3 } } */
+
+/* One FMA operation in 16-bit precision, from foo_v82.  */
+/* { dg-final { scan-assembler-times "fmadd\th\[0-9\]\+" 1 } } */
+
+/* Test that in -fpermitted-flt-eval-methods=c11 we don't set the
+   __FLT_EVAL_METHOD__ to anything other than 0.  */
+/* { dg-final { scan-assembler-times "str\twzr" 4 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/_Float16_3.c b/gcc/testsuite/gcc.target/aarch64/_Float16_3.c
new file mode 100644
index 0000000..2d20250
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/_Float16_3.c
@@ -0,0 +1,46 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=armv8.2-a+nofp16 -std=c11 -ffp-contract=fast" } */
+
+#pragma GCC target ("arch=armv8.2-a+nofp16")
+
+_Float16
+foo_v8 (_Float16 x, _Float16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+__fp16
+bar_v8 (__fp16 x, __fp16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+#pragma GCC target ("arch=armv8.2-a+fp16")
+
+_Float16
+foo_v82 (_Float16 x, _Float16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+__fp16
+bar_v82 (__fp16 x, __fp16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+/* Test that we merge to FMA operations.  This indicates that we are not
+   making extraneous conversions between modes.  */
+
+/* Three FMA operations in 32-bit precision, from foo_v8, bar_v8, bar_v82.  */
+/* { dg-final { scan-assembler-times "fmadd\ts\[0-9\]\+" 3 } } */
+
+/* One FMA operation in 16-bit precision, from foo_v82.  */
+/* { dg-final { scan-assembler-times "fmadd\th\[0-9\]\+" 1 } } */
+
+/* Test that in C11 mode, we don't reset __FLT_EVAL_METHOD__.  */
+/* { dg-final { scan-assembler-times "str\twzr" 4 } } */

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

* Re: [Patch 7/11] Delete TARGET_FLT_EVAL_METHOD and poison it.
  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
  0 siblings, 0 replies; 95+ messages in thread
From: Jeff Law @ 2016-09-30 17:29 UTC (permalink / raw)
  To: James Greenhalgh, gcc-patches; +Cc: nd

On 09/30/2016 10:56 AM, James Greenhalgh wrote:
>
> Hi,
>
> We've removed all uses of TARGET_FLT_EVAL_METHOD, so we can remove it
> and poison it.
>
> Bootstrapped and tested on x86-64 and AArch64. Tested on s390 and m68k
> to the best of my ability (no execute tests).
>
> OK?
>
> Thanks,
> James
>
> ---
> gcc/
>
> 2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>
>
> 	* config/s390/s390.h (TARGET_FLT_EVAL_METHOD): Delete.
> 	* config/m68k/m68k.h (TARGET_FLT_EVAL_METHOD): Delete.
> 	* config/i386/i386.h (TARGET_FLT_EVAL_METHOD): Delete.
> 	* defaults.h (TARGET_FLT_EVAL_METHOD): Delete.
> 	* doc/tm.texi.in (TARGET_FLT_EVAL_METHOD): Delete.
> 	* doc/tm.texi: Regenerate.
> 	* system.h (TARGET_FLT_EVAL_METHOD): Poison.
OK when prereqs are approved.
jeff

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

* Re: [Patch 4/11] Implement TARGET_C_EXCESS_PRECISION for m68k
  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
  1 sibling, 0 replies; 95+ messages in thread
From: Jeff Law @ 2016-09-30 17:32 UTC (permalink / raw)
  To: James Greenhalgh, gcc-patches; +Cc: nd, joseph, schwab

On 09/30/2016 11:01 AM, James Greenhalgh wrote:
>
> Hi,
>
> This patch ports the logic from m68k's TARGET_FLT_EVAL_METHOD to the new
> target hook TARGET_C_EXCESS_PRECISION.
>
> Patch tested by building an m68k-none-elf toolchain and running
> m68k.exp (without the ability to execute) with no regressions, and manually
> inspecting the output assembly code when compiling
> testsuite/gcc.target/i386/excess-precision* to show no difference in
> code-generation.
>
> OK?
>
> Thanks,
> James
>
> ---
> gcc/
>
> 2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>
>
> 	* config/m68k/m68k.c (m68k_excess_precision): New.
> 	(TARGET_C_EXCESS_PRECISION): Define.
OK when prereqs are approved.  Similarly for other targets where you 
needed to add this hook.

jeff

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

* Re: [Patch 8/11] Make _Float16 available if HFmode is available
  2016-09-30 16:58 ` [Patch 8/11] Make _Float16 available if HFmode is available James Greenhalgh
@ 2016-09-30 17:34   ` Jeff Law
  0 siblings, 0 replies; 95+ messages in thread
From: Jeff Law @ 2016-09-30 17:34 UTC (permalink / raw)
  To: James Greenhalgh, gcc-patches; +Cc: nd

On 09/30/2016 10:56 AM, James Greenhalgh wrote:
>
> Hi,
>
> Now that we've worked on -fexcess-precision, the comment in targhooks.c
> no longer holds. We can now permit _Float16 on any target which provides
> HFmode and supports HFmode in libgcc.
>
> Bootstrapped and tested on x86-64, and in series on AArch64.
>
> OK?
>
> Thanks,
> James
>
> ---
> 2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>
>
> 	* targhooks.c (default_floatn_mode): Enable _Float16 if a target
> 	provides HFmode.
OK when prereqs are approved.

jeff

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

* Re: [Patch 6/11] Migrate excess precision logic to use TARGET_EXCESS_PRECISION
  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
  0 siblings, 1 reply; 95+ messages in thread
From: Joseph Myers @ 2016-09-30 17:34 UTC (permalink / raw)
  To: James Greenhalgh; +Cc: gcc-patches, nd

On Fri, 30 Sep 2016, James Greenhalgh wrote:

>    /* float.h needs to know this.  */
> +  /* We already have the option -fno-fp-int-builtin-inexact to ensure
> +     certain built-in functions follow TS 18661-1 semantics.  It might be
> +     reasonable to have a new option to enable FLT_EVAL_METHOD using new
> +     values.  However, I'd be inclined to think that such an option should
> +     be on by default for -std=gnu*, only off for strict conformance modes.
> +     (There would be both __FLT_EVAL_METHOD__ and __FLT_EVAL_METHOD_C99__,
> +     say, predefined macros, so that <float.h> could also always use the
> +     new value if __STDC_WANT_IEC_60559_TYPES_EXT__ is defined.)  */

This comment makes no sense in the context.  The comment should not be 
talking about some other option for a different issue, or about 
half-thought-out ideas for how something might be implemented; comments 
need to relate to the actual code (which in this case is obvious and not 
in need of comments beyond saying what the macro semantics are).  In any 
case, this patch does not achieve the proposed semantics, since there is 
no change to ginclude/float.h.

The goal is: if the user's options imply new FLT_EVAL_METHOD values are 
OK, *or* they defined __STDC_WANT_IEC_60559_TYPES_EXT__ before including 
<float.h>, it should use the appropriate TS 18661-3 value.  Otherwise 
(strict standards modes for existing standards, no 
__STDC_WANT_IEC_60559_TYPES_EXT__) it should use a C11 value.

So in a strict standards mode you need to predefine macros with both 
choices of values and let <float.h> choose between them.  One possibility 
is: __FLT_EVAL_METHOD_C99__ is the value to use when 
__STDC_WANT_IEC_60559_TYPES_EXT__ is not defined, __FLT_EVAL_METHOD__ is 
the value to use when it is defined.  Or some other arrangement, with or 
without a macro saying what setting you have for the new option.  But you 
can't avoid changing <float.h>.

Tests then should be testing the value of FLT_EVAL_METHOD from <float.h>, 
*not* the internal macros predefined by the compiler.

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [Patch 5/11] Add -fpermitted-flt-eval-methods=[c11|ts-18661-3]
  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
  1 sibling, 1 reply; 95+ messages in thread
From: Jeff Law @ 2016-09-30 17:40 UTC (permalink / raw)
  To: James Greenhalgh, gcc-patches; +Cc: nd

On 09/30/2016 10:56 AM, James Greenhalgh wrote:
>
> Hi,
>
> This option is added to control which values of FLT_EVAL_METHOD the
> compiler is allowed to set.
>
> ISO/IEC TS 18661-3 defines new permissible values for
> FLT_EVAL_METHOD that indicate that operations and constants with
> a semantic type that is an interchange or extended format should be
> evaluated to the precision and range of that type.  These new values are
> a superset of those permitted under C99/C11, which does not specify the
> meaning of other positive values of FLT_EVAL_METHOD.  As such, code
> conforming to C11 may not have been written expecting the possibility of
> the new values.
>
> -fpermitted-flt-eval-methods specifies whether the compiler
> should allow only the values of FLT_EVAL_METHOD specified in C99/C11,
> or the extended set of values specified in ISO/IEC TS 18661-3.
>
> The two possible values this option can take are "c11" or "ts-18661-3".
>
> The default when in a standards compliant mode (-std=c11 or similar)
> is -fpermitted-flt-eval-methods=c11.  The default when in a GNU
> dialect (-std=gnu11 or similar) is -fpermitted-flt-eval-methods=ts-18661-3.
>
> I've added two testcases which test that when this option, or a C standards
> dialect, would restrict the range of values to {-1, 0, 1, 2}, those are
> the only values we see. At this stage in the patch series this trivially
> holds for all targets.
>
> Bootstrapped on x86_64 with no issues and tested in series on AArch64.
>
> OK?
>
> Thanks,
> James
>
> ---
> gcc/c-family/
>
> 2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>
>
> 	* c-opts.c (c_common_post_options): Add logic to handle the default
> 	case for -fpermitted-flt-eval-methods.
>
> gcc/
>
> 2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>
>
> 	* common.opt (fpermitted-flt-eval-methods): New.
> 	* doc/invoke.texi (-fpermitted-flt-eval-methods): Document it.
> 	* flag_types.h (permitted_flt_eval_methods): New.
>
> gcc/testsuite/
>
> 2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>
>
> 	* gcc.dg/fpermitted-flt-eval-methods_1.c: New.
> 	* gcc.dg/fpermitted-flt-eval-methods_2.c: New.
OK.    Are you going to need to do something for C++ (or gasp ObjC) in 
the future, or do you expect this to be C only indefinitely?

jeff
>

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

* Re: [Patch 3/11] Implement TARGET_C_EXCESS_PRECISION for s390
  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
  0 siblings, 1 reply; 95+ messages in thread
From: Joseph Myers @ 2016-09-30 17:41 UTC (permalink / raw)
  To: James Greenhalgh; +Cc: gcc-patches, nd, hpenner, uweigand, Andreas.Krebbel

On Fri, 30 Sep 2016, James Greenhalgh wrote:

> +      case EXCESS_PRECISION_TYPE_STANDARD:
> +      case EXCESS_PRECISION_TYPE_IMPLICIT:
> +	/* Otherwise, the excess precision we want when we are
> +	   in a standards compliant mode, and the implicit precision we
> +	   provide can be identical.  */
> +	return FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE;

That's wrong for EXCESS_PRECISION_TYPE_IMPLICIT.  There is no implicit 
promotion in the back end (and really there shouldn't be any excess 
precision here at all, and double_t in glibc should be fixed along with a 
GCC change to remove this mistake).

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [Patch 3/11] Implement TARGET_C_EXCESS_PRECISION for s390
  2016-09-30 17:41   ` Joseph Myers
@ 2016-09-30 17:54     ` Jeff Law
  2016-09-30 18:10       ` Joseph Myers
  0 siblings, 1 reply; 95+ messages in thread
From: Jeff Law @ 2016-09-30 17:54 UTC (permalink / raw)
  To: Joseph Myers, James Greenhalgh
  Cc: gcc-patches, nd, hpenner, uweigand, Andreas.Krebbel

On 09/30/2016 11:34 AM, Joseph Myers wrote:
> On Fri, 30 Sep 2016, James Greenhalgh wrote:
>
>> +      case EXCESS_PRECISION_TYPE_STANDARD:
>> +      case EXCESS_PRECISION_TYPE_IMPLICIT:
>> +	/* Otherwise, the excess precision we want when we are
>> +	   in a standards compliant mode, and the implicit precision we
>> +	   provide can be identical.  */
>> +	return FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE;
>
> That's wrong for EXCESS_PRECISION_TYPE_IMPLICIT.  There is no implicit
> promotion in the back end (and really there shouldn't be any excess
> precision here at all, and double_t in glibc should be fixed along with a
> GCC change to remove this mistake).
Sorry, change to a NAK.

Joseph, what's the right thing to do here?

jeff

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

* Re: [Patch 3/11] Implement TARGET_C_EXCESS_PRECISION for s390
  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
  0 siblings, 2 replies; 95+ messages in thread
From: Joseph Myers @ 2016-09-30 18:10 UTC (permalink / raw)
  To: Jeff Law
  Cc: James Greenhalgh, gcc-patches, nd, hpenner, uweigand, Andreas.Krebbel

On Fri, 30 Sep 2016, Jeff Law wrote:

> On 09/30/2016 11:34 AM, Joseph Myers wrote:
> > On Fri, 30 Sep 2016, James Greenhalgh wrote:
> > 
> > > +      case EXCESS_PRECISION_TYPE_STANDARD:
> > > +      case EXCESS_PRECISION_TYPE_IMPLICIT:
> > > +	/* Otherwise, the excess precision we want when we are
> > > +	   in a standards compliant mode, and the implicit precision we
> > > +	   provide can be identical.  */
> > > +	return FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE;
> > 
> > That's wrong for EXCESS_PRECISION_TYPE_IMPLICIT.  There is no implicit
> > promotion in the back end (and really there shouldn't be any excess
> > precision here at all, and double_t in glibc should be fixed along with a
> > GCC change to remove this mistake).
> Sorry, change to a NAK.
> 
> Joseph, what's the right thing to do here?

(a) The present patch would keep the existing value of FLT_EVAL_METHOD.  
But the existing value is inaccurate for the default compilation mode, 
when there is no implicit promotion in the back end, and doing so means 
suboptimal code in libgcc and glibc because it does things to handle 
excess precision that isn't actually there (and quite possibly in code 
elsewhere that looks at FLT_EVAL_METHOD).

(b) Handling EXCESS_PRECISION_TYPE_IMPLICIT like 
EXCESS_PRECISION_TYPE_FAST would accurately describe what the back end 
does.  It would mean that the default FLT_EVAL_METHOD is 0, which is a 
more accurate description of how the compiler actually behaves, and would 
avoid the suboptimal code in libgcc and glibc.  It would however mean that 
unless -fexcess-precision=standard is used, FLT_EVAL_METHOD (accurate) is 
out of synx with float_t in math.h (inaccurate).

(c) Removing all special excess precision for S/390 from GCC, and changing 
float_t to float in glibc, is logically correct and produces optimal code.  
float_t does not appear in the ABI of any glibc function; in principle it 
could affect the ABIs of other libraries, but I don't think that's 
particularly likely.

The only argument for (a) is that's it's semantics-preserving - it's just 
that the preserved semantics are nonsensical and involve an inaccurate 
value of FLT_EVAL_METHOD in the default compilation mode.

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [Patch 4/11] Implement TARGET_C_EXCESS_PRECISION for m68k
  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
  1 sibling, 1 reply; 95+ messages in thread
From: Andreas Schwab @ 2016-09-30 18:25 UTC (permalink / raw)
  To: James Greenhalgh; +Cc: gcc-patches, nd, joseph, law

On Sep 30 2016, James Greenhalgh <james.greenhalgh@arm.com> wrote:

> 	* config/m68k/m68k.c (m68k_excess_precision): New.
> 	(TARGET_C_EXCESS_PRECISION): Define.

Ok.

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

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

* Re: [Patch 5/11] Add -fpermitted-flt-eval-methods=[c11|ts-18661-3]
  2016-09-30 17:40   ` Jeff Law
@ 2016-09-30 22:07     ` Mike Stump
  0 siblings, 0 replies; 95+ messages in thread
From: Mike Stump @ 2016-09-30 22:07 UTC (permalink / raw)
  To: Jeff Law; +Cc: James Greenhalgh, gcc-patches, nd

On Sep 30, 2016, at 10:34 AM, Jeff Law <law@redhat.com> wrote:
>> 2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>
>> 
>> 	* gcc.dg/fpermitted-flt-eval-methods_1.c: New.
>> 	* gcc.dg/fpermitted-flt-eval-methods_2.c: New.
> OK.    Are you going to need to do something for C++ (or gasp ObjC) in the future

ObjC should come along for free as long as major rules of ettiquite aren't broken.

As test that says, make this work only for C, would be wrong.  Conditionalizing a flag as only for C would be wrong.  I glanced around and didn't see anything that would make it not work for ObjC.

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

* Re: [Patch 2/11] Implement TARGET_C_EXCESS_PRECISION for i386
  2016-09-30 16:59 ` [Patch 2/11] Implement TARGET_C_EXCESS_PRECISION for i386 James Greenhalgh
@ 2016-10-01 11:55   ` Uros Bizjak
  0 siblings, 0 replies; 95+ messages in thread
From: Uros Bizjak @ 2016-10-01 11:55 UTC (permalink / raw)
  To: James Greenhalgh
  Cc: gcc-patches, nd, Jan Hubicka, Joseph S. Myers, Richard Henderson

On Fri, Sep 30, 2016 at 6:59 PM, James Greenhalgh
<james.greenhalgh@arm.com> wrote:
>
> Hi,
>
> This patch ports the logic from i386's TARGET_FLT_EVAL_METHOD to the new
> target hook TARGET_C_EXCESS_PRECISION.
>
> Bootstrapped and tested with no issues.
>
> OK?
>
> Thanks,
> James
>
> ---
> gcc/
>
> 2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>
>
>         * config/i386/i386.c (ix86_excess_precision): New.
>         (TARGET_C_EXCESS_PRECISION): Define.
>

OK for mainline.

Thanks,
Uros.

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

* Re: [Patch 3/11] Implement TARGET_C_EXCESS_PRECISION for s390
  2016-09-30 18:10       ` Joseph Myers
@ 2016-10-03  8:31         ` James Greenhalgh
  2016-10-04 13:40         ` Andreas Krebbel
  1 sibling, 0 replies; 95+ messages in thread
From: James Greenhalgh @ 2016-10-03  8:31 UTC (permalink / raw)
  To: Joseph Myers
  Cc: Jeff Law, gcc-patches, nd, hpenner, uweigand, Andreas.Krebbel

On Fri, Sep 30, 2016 at 05:57:45PM +0000, Joseph Myers wrote:
> On Fri, 30 Sep 2016, Jeff Law wrote:
> 
> > On 09/30/2016 11:34 AM, Joseph Myers wrote:
> > > On Fri, 30 Sep 2016, James Greenhalgh wrote:
> > > 
> > > > +      case EXCESS_PRECISION_TYPE_STANDARD:
> > > > +      case EXCESS_PRECISION_TYPE_IMPLICIT:
> > > > +	/* Otherwise, the excess precision we want when we are
> > > > +	   in a standards compliant mode, and the implicit precision we
> > > > +	   provide can be identical.  */
> > > > +	return FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE;
> > > 
> > > That's wrong for EXCESS_PRECISION_TYPE_IMPLICIT.  There is no implicit
> > > promotion in the back end (and really there shouldn't be any excess
> > > precision here at all, and double_t in glibc should be fixed along with a
> > > GCC change to remove this mistake).
> > Sorry, change to a NAK.
> > 
> > Joseph, what's the right thing to do here?
> 
> (a) The present patch would keep the existing value of FLT_EVAL_METHOD.  
> But the existing value is inaccurate for the default compilation mode, 
> when there is no implicit promotion in the back end, and doing so means 
> suboptimal code in libgcc and glibc because it does things to handle 
> excess precision that isn't actually there (and quite possibly in code 
> elsewhere that looks at FLT_EVAL_METHOD).
> 
> (b) Handling EXCESS_PRECISION_TYPE_IMPLICIT like 
> EXCESS_PRECISION_TYPE_FAST would accurately describe what the back end 
> does.  It would mean that the default FLT_EVAL_METHOD is 0, which is a 
> more accurate description of how the compiler actually behaves, and would 
> avoid the suboptimal code in libgcc and glibc.  It would however mean that 
> unless -fexcess-precision=standard is used, FLT_EVAL_METHOD (accurate) is 
> out of synx with float_t in math.h (inaccurate).
> 
> (c) Removing all special excess precision for S/390 from GCC, and changing 
> float_t to float in glibc, is logically correct and produces optimal code.  
> float_t does not appear in the ABI of any glibc function; in principle it 
> could affect the ABIs of other libraries, but I don't think that's 
> particularly likely.
> 
> The only argument for (a) is that's it's semantics-preserving - it's just 
> that the preserved semantics are nonsensical and involve an inaccurate 
> value of FLT_EVAL_METHOD in the default compilation mode.

I'm happy progressing whichever of a) or b) would be preferred by the
the s390 maintainers. But I'd be uncomfortable making the wider changes
in c) as I've got no access to an s390 build and test environment in which
I have any confidence, nor do I know the s390 port history that led to the
'typedef double float_t' in glibc.

Regardless of which approach is chosen, I'll be sure to update the patch
with a comment paraphrasing your suggestions above.

Thanks,
James

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

* Re: [Patch 3/11] Implement TARGET_C_EXCESS_PRECISION for s390
  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
  1 sibling, 1 reply; 95+ messages in thread
From: Andreas Krebbel @ 2016-10-04 13:40 UTC (permalink / raw)
  To: Joseph Myers, Jeff Law
  Cc: James Greenhalgh, gcc-patches, nd, hpenner, uweigand, Andreas.Krebbel

On 09/30/2016 07:57 PM, Joseph Myers wrote:
> On Fri, 30 Sep 2016, Jeff Law wrote:
> 
>> On 09/30/2016 11:34 AM, Joseph Myers wrote:
>>> On Fri, 30 Sep 2016, James Greenhalgh wrote:
>>>
>>>> +      case EXCESS_PRECISION_TYPE_STANDARD:
>>>> +      case EXCESS_PRECISION_TYPE_IMPLICIT:
>>>> +	/* Otherwise, the excess precision we want when we are
>>>> +	   in a standards compliant mode, and the implicit precision we
>>>> +	   provide can be identical.  */
>>>> +	return FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE;
>>>
>>> That's wrong for EXCESS_PRECISION_TYPE_IMPLICIT.  There is no implicit
>>> promotion in the back end (and really there shouldn't be any excess
>>> precision here at all, and double_t in glibc should be fixed along with a
>>> GCC change to remove this mistake).
>> Sorry, change to a NAK.
>>
>> Joseph, what's the right thing to do here?
> 
> (a) The present patch would keep the existing value of FLT_EVAL_METHOD.  
> But the existing value is inaccurate for the default compilation mode, 
> when there is no implicit promotion in the back end, and doing so means 
> suboptimal code in libgcc and glibc because it does things to handle 
> excess precision that isn't actually there (and quite possibly in code 
> elsewhere that looks at FLT_EVAL_METHOD).
> 
> (b) Handling EXCESS_PRECISION_TYPE_IMPLICIT like 
> EXCESS_PRECISION_TYPE_FAST would accurately describe what the back end 
> does.  It would mean that the default FLT_EVAL_METHOD is 0, which is a 
> more accurate description of how the compiler actually behaves, and would 
> avoid the suboptimal code in libgcc and glibc.  It would however mean that 
> unless -fexcess-precision=standard is used, FLT_EVAL_METHOD (accurate) is 
> out of synx with float_t in math.h (inaccurate).

With (b) we would violate the C standard which explicitly states that the definition of float_t
needs to be float if FLT_EVAL_METHOD is 0. I've no idea how much code really relies on that. So far
I only know about the Plum Hall testsuite ;) So this probably would still be a safe change. Actually
it was like that for many years without any problems ... until I've changed it due to the Plum Hall
finding :(  https://gcc.gnu.org/ml/gcc-patches/2013-03/msg01124.html

> (c) Removing all special excess precision for S/390 from GCC, and changing 
> float_t to float in glibc, is logically correct and produces optimal code.  
> float_t does not appear in the ABI of any glibc function; in principle it 
> could affect the ABIs of other libraries, but I don't think that's 
> particularly likely.

I really would like to do this.  The idea came up several times already but we always were concerned
about the potential ABI break.

> The only argument for (a) is that's it's semantics-preserving - it's just 
> that the preserved semantics are nonsensical and involve an inaccurate 
> value of FLT_EVAL_METHOD in the default compilation mode.

I'll try to set up some scans on src packages to get a better feel about where it would potentially
break. I'll come back with the results. I do not want to block the patchset with this though. So if
you would like to go on quickly feel free to commit (a).

-Andreas-

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

* Re: [Patch 3/11] Implement TARGET_C_EXCESS_PRECISION for s390
  2016-10-04 13:40         ` Andreas Krebbel
@ 2016-10-04 13:43           ` Joseph Myers
  2016-10-07  8:34             ` Andreas Krebbel
  0 siblings, 1 reply; 95+ messages in thread
From: Joseph Myers @ 2016-10-04 13:43 UTC (permalink / raw)
  To: Andreas Krebbel
  Cc: Jeff Law, James Greenhalgh, gcc-patches, nd, hpenner, uweigand,
	Andreas.Krebbel

On Tue, 4 Oct 2016, Andreas Krebbel wrote:

> > (b) Handling EXCESS_PRECISION_TYPE_IMPLICIT like 
> > EXCESS_PRECISION_TYPE_FAST would accurately describe what the back end 
> > does.  It would mean that the default FLT_EVAL_METHOD is 0, which is a 
> > more accurate description of how the compiler actually behaves, and would 
> > avoid the suboptimal code in libgcc and glibc.  It would however mean that 
> > unless -fexcess-precision=standard is used, FLT_EVAL_METHOD (accurate) is 
> > out of synx with float_t in math.h (inaccurate).
> 
> With (b) we would violate the C standard which explicitly states that 
> the definition of float_t needs to be float if FLT_EVAL_METHOD is 0. 
> I've no idea how much code really relies on that. So far I only know 
> about the Plum Hall testsuite ;) So this probably would still be a safe 
> change. Actually it was like that for many years without any problems 
> ... until I've changed it due to the Plum Hall finding :( 
> https://gcc.gnu.org/ml/gcc-patches/2013-03/msg01124.html

You'd only violate it outside standards conformance modes (which you 
should be using for running conformance testsuites); with -std=c11 etc. 
-fexcess-precision=standard would be implied, meaning FLT_EVAL_METHOD 
remains as 1 in that case.

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [Patch 5/11] Add -fpermitted-flt-eval-methods=[c11|ts-18661-3]
  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-10-05 23:00   ` Joseph Myers
  1 sibling, 0 replies; 95+ messages in thread
From: Joseph Myers @ 2016-10-05 23:00 UTC (permalink / raw)
  To: James Greenhalgh; +Cc: gcc-patches, nd

On Fri, 30 Sep 2016, James Greenhalgh wrote:

> I've added two testcases which test that when this option, or a C standards
> dialect, would restrict the range of values to {-1, 0, 1, 2}, those are
> the only values we see. At this stage in the patch series this trivially
> holds for all targets.

As noted in my comments on patch 6, the tests should check FLT_EVAL_METHOD 
from <float.h>, not the internal __FLT_EVAL_METHOD__ macro (and <float.h> 
will need to contain conditionals so that the -std=c11 
-D__STDC_WANT_IEC_60559_TYPES_EXT__ case uses the new values when 
appropriate).

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [Patch 3/11] Implement TARGET_C_EXCESS_PRECISION for s390
  2016-10-04 13:43           ` Joseph Myers
@ 2016-10-07  8:34             ` Andreas Krebbel
  2016-10-07 13:11               ` Joseph Myers
  2016-10-14 16:53               ` James Greenhalgh
  0 siblings, 2 replies; 95+ messages in thread
From: Andreas Krebbel @ 2016-10-07  8:34 UTC (permalink / raw)
  To: Joseph Myers
  Cc: Jeff Law, James Greenhalgh, gcc-patches, nd, uweigand, Andreas.Krebbel

On 10/04/2016 03:42 PM, Joseph Myers wrote:
> On Tue, 4 Oct 2016, Andreas Krebbel wrote:
> 
>>> (b) Handling EXCESS_PRECISION_TYPE_IMPLICIT like 
>>> EXCESS_PRECISION_TYPE_FAST would accurately describe what the back end 
>>> does.  It would mean that the default FLT_EVAL_METHOD is 0, which is a 
>>> more accurate description of how the compiler actually behaves, and would 
>>> avoid the suboptimal code in libgcc and glibc.  It would however mean that 
>>> unless -fexcess-precision=standard is used, FLT_EVAL_METHOD (accurate) is 
>>> out of synx with float_t in math.h (inaccurate).
>>
>> With (b) we would violate the C standard which explicitly states that 
>> the definition of float_t needs to be float if FLT_EVAL_METHOD is 0. 
>> I've no idea how much code really relies on that. So far I only know 
>> about the Plum Hall testsuite ;) So this probably would still be a safe 
>> change. Actually it was like that for many years without any problems 
>> ... until I've changed it due to the Plum Hall finding :( 
>> https://gcc.gnu.org/ml/gcc-patches/2013-03/msg01124.html
> 
> You'd only violate it outside standards conformance modes (which you 
> should be using for running conformance testsuites); with -std=c11 etc. 
> -fexcess-precision=standard would be implied, meaning FLT_EVAL_METHOD 
> remains as 1 in that case.

wrt (b): Agreed. I was more concerned about all the other code which might accidently be built
without a strict standard compliance option. I did some searches in the source package repos. The
only snippet where the definition of FLT_EVAL_METHOD might affect code generation is in musl libc
but that one is being built with -std=c99. So I don't see anything speaking against (b). I'm ok with
going that way.

wrt (c): float_t appears to be more widely used than I expected. But the only hits which might
indicate potential ABI problems where in clucene and libassa. (I've scanned the header files of
about 25k Ubuntu source packages).
I'm also not sure about script language interfaces with C. There might be potential problems out
there which I wasn't able to catch with my scan.
While I fully agree with you that the float_t type definition for S/390 in Glibc is plain wrong I do
not really feel comfortable with changing it.

An interesting case is imagemagick. They define their ABI-relevant MagickRealType based on the size
of float_t in recent versions but excplicitly without depending on FLT_EVAL_METHOD
(http://www.imagemagick.org/discourse-server/viewtopic.php?t=22136). They build with -std=gnu99 so
this helps us with (b) I think. To my understanding MagickRealType would stay double not affected by
FLT_EVAL_METHOD changes.

-Andreas-

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

* Re: [Patch 3/11] Implement TARGET_C_EXCESS_PRECISION for s390
  2016-10-07  8:34             ` Andreas Krebbel
@ 2016-10-07 13:11               ` Joseph Myers
  2016-10-12  8:40                 ` Andreas Krebbel
  2016-10-14 16:53               ` James Greenhalgh
  1 sibling, 1 reply; 95+ messages in thread
From: Joseph Myers @ 2016-10-07 13:11 UTC (permalink / raw)
  To: Andreas Krebbel
  Cc: Jeff Law, James Greenhalgh, gcc-patches, nd, uweigand, Andreas.Krebbel

On Fri, 7 Oct 2016, Andreas Krebbel wrote:

> wrt (c): float_t appears to be more widely used than I expected. But the 
> only hits which might indicate potential ABI problems where in clucene 
> and libassa. (I've scanned the header files of about 25k Ubuntu source 
> packages).

If it's two out of 25000 source packages whose ABIs might be affected, I 
think that shows it's much safer as a change in glibc than moving to 
_FILE_OFFSET_BITS=64 as a default (which I expect will happen when someone 
puts the work in).  And probably safer than many past changes done through 
symbol versioning.

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [Patch 3/11] Implement TARGET_C_EXCESS_PRECISION for s390
  2016-10-07 13:11               ` Joseph Myers
@ 2016-10-12  8:40                 ` Andreas Krebbel
  2016-10-12 10:14                   ` Joseph Myers
  0 siblings, 1 reply; 95+ messages in thread
From: Andreas Krebbel @ 2016-10-12  8:40 UTC (permalink / raw)
  To: Joseph Myers
  Cc: Jeff Law, James Greenhalgh, gcc-patches, nd, uweigand, Andreas.Krebbel

On 10/07/2016 03:11 PM, Joseph Myers wrote:
> On Fri, 7 Oct 2016, Andreas Krebbel wrote:
> 
>> wrt (c): float_t appears to be more widely used than I expected. But the 
>> only hits which might indicate potential ABI problems where in clucene 
>> and libassa. (I've scanned the header files of about 25k Ubuntu source 
>> packages).
> 
> If it's two out of 25000 source packages whose ABIs might be affected, I 
> think that shows it's much safer as a change in glibc than moving to 
> _FILE_OFFSET_BITS=64 as a default (which I expect will happen when someone 
> puts the work in).  And probably safer than many past changes done through 
> symbol versioning.

Regarding (c) imagemagick is also affected (it wasn't really clear from my last email). Since it is
a widely used lib I think this counts as a blocker. The ABI relevant MagickRealType depends on the
size of float_t:

/*
  Float_t is not an ABI type.
*/
#if MAGICKCORE_SIZEOF_FLOAT_T == 0
typedef float MagickRealType;
#elif (MAGICKCORE_SIZEOF_FLOAT_T == MAGICKCORE_SIZEOF_FLOAT)
typedef float MagickRealType;
#elif (MAGICKCORE_SIZEOF_FLOAT_T == MAGICKCORE_SIZEOF_DOUBLE)
typedef double MagickRealType;
#elif (MAGICKCORE_SIZEOF_FLOAT_T == MAGICKCORE_SIZEOF_LONG_DOUBLE)
typedef long double MagickRealType;
#else
# error Your float_t type is neither a float, nor a double, nor a long double
#endif

So I would prefer (b) which looks like a good compromise to me.

-Andreas-

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

* Re: [Patch 3/11] Implement TARGET_C_EXCESS_PRECISION for s390
  2016-10-12  8:40                 ` Andreas Krebbel
@ 2016-10-12 10:14                   ` Joseph Myers
  0 siblings, 0 replies; 95+ messages in thread
From: Joseph Myers @ 2016-10-12 10:14 UTC (permalink / raw)
  To: Andreas Krebbel
  Cc: Jeff Law, James Greenhalgh, gcc-patches, nd, uweigand, Andreas.Krebbel

On Wed, 12 Oct 2016, Andreas Krebbel wrote:

> Regarding (c) imagemagick is also affected (it wasn't really clear from 
> my last email). Since it is a widely used lib I think this counts as a 
> blocker. The ABI relevant MagickRealType depends on the size of float_t:

I think distributions manage ABI transitions for such libraries all the 
time (and could well choose to patch it locally to defer the change until 
it next changes SONAME upstream anyway).

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [Patch 1/11] Add a new target hook for describing excess precision intentions
  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
  0 siblings, 1 reply; 95+ messages in thread
From: James Greenhalgh @ 2016-10-14 16:50 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, joseph

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


On Fri, Sep 30, 2016 at 05:56:53PM +0100, James Greenhalgh wrote:
>
> This patch introduces TARGET_C_EXCESS_PRECISION. This hook takes a tri-state
> argument, one of EXCESS_PRECISION_TYPE_IMPLICIT,
> EXCESS_PRECISION_TYPE_STANDARD, EXCESS_PRECISION_TYPE_FAST. Which relate to
> the implicit extra precision added by the target, the excess precision that
> should be guaranteed for -fexcess-precision=standard, and the excess
> precision that should be added for performance under -fexcess-precision=fast .
>
> Bootstrapped and tested in sequence with the other patches in this series
> on Arch64, and as a standalone patch on x86_64.
>

Hi,

This version of this patch has no major changes, simply updating the
comment above default_excess_precision to use the newer
TARGET_C_EXCESS_PRECISION name for this target hook, rather than
TARGET_EXCESS_PRECISION as it was in an earlier patch revision.

Bootstrapped and tested in sequence with the other patches in this series
on Arch64, and as a standalone patch on x86_64.

OK?

Thanks
James

---
gcc/

2016-10-14  James Greenhalgh  <james.greenhalgh@arm.com>

	* target.def (excess_precision): New hook.
	* target.h (flt_eval_method): New.
	(excess_precision_type): Likewise.
	* targhooks.c (default_excess_precision): New.
	* targhooks.h (default_excess_precision): New.
	* doc/tm.texi.in (TARGET_C_EXCESS_PRECISION): New.
	* doc/tm.texi: Regenerate.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Re-Patch-1-11-Add-a-new-target-hook-for-describing-e.patch --]
[-- Type: text/x-patch;  name=0001-Re-Patch-1-11-Add-a-new-target-hook-for-describing-e.patch, Size: 4764 bytes --]

diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index 70f909d..c4b00b0 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -331,6 +331,24 @@ enum symbol_visibility
   VISIBILITY_INTERNAL
 };
 
+/* enums used by the targetm.excess_precision hook.  */
+
+enum flt_eval_method
+{
+  FLT_EVAL_METHOD_UNPREDICTABLE = -1,
+  FLT_EVAL_METHOD_PROMOTE_TO_FLOAT = 0,
+  FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE = 1,
+  FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE = 2,
+  FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16 = 16
+};
+
+enum excess_precision_type
+{
+  EXCESS_PRECISION_TYPE_IMPLICIT,
+  EXCESS_PRECISION_TYPE_STANDARD,
+  EXCESS_PRECISION_TYPE_FAST
+};
+
 /* Support for user-provided GGC and PCH markers.  The first parameter
    is a pointer to a pointer, the second a cookie.  */
 typedef void (*gt_pointer_operator) (void *, void *);
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index a4a8e49..c21a772 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -947,6 +947,10 @@ sign-extend the result to 64 bits.  On such machines, set
 Do not define this macro if it would never modify @var{m}.
 @end defmac
 
+@deftypefn {Target Hook} {enum flt_eval_method} TARGET_C_EXCESS_PRECISION (enum excess_precision_type @var{type})
+Return a value, with the same meaning as @code{FLT_EVAL_METHOD} C that describes which excess precision should be applied.  @var{type} is either @code{EXCESS_PRECISION_TYPE_IMPLICIT}, @code{EXCESS_PRECISION_TYPE_FAST}, or @code{EXCESS_PRECISION_TYPE_STANDARD}.  For @code{EXCESS_PRECISION_TYPE_IMPLICIT}, the target should return which precision and range operations will be implictly evaluated in regardless of the excess precision explicitly added.  For @code{EXCESS_PRECISION_TYPE_STANDARD} and @code{EXCESS_PRECISION_TYPE_FAST}, the target should return the explicit excess precision that should be added depending on the value set for @code{-fexcess-precision=[standard|fast]}.
+@end deftypefn
+
 @deftypefn {Target Hook} machine_mode TARGET_PROMOTE_FUNCTION_MODE (const_tree @var{type}, machine_mode @var{mode}, int *@var{punsignedp}, const_tree @var{funtype}, int @var{for_return})
 Like @code{PROMOTE_MODE}, but it is applied to outgoing function arguments or
 function return values.  The target hook should return the new mode
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 265f1be..19b381b 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -921,6 +921,8 @@ sign-extend the result to 64 bits.  On such machines, set
 Do not define this macro if it would never modify @var{m}.
 @end defmac
 
+@hook TARGET_C_EXCESS_PRECISION
+
 @hook TARGET_PROMOTE_FUNCTION_MODE
 
 @defmac PARM_BOUNDARY
diff --git a/gcc/target.def b/gcc/target.def
index b6968f7..3b17c62 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -5402,6 +5402,23 @@ DEFHOOK_UNDOC
  machine_mode, (char c),
  default_mode_for_suffix)
 
+DEFHOOK
+(excess_precision,
+ "Return a value, with the same meaning as @code{FLT_EVAL_METHOD} C that\
+ describes which excess precision should be applied.  @var{type} is\
+ either @code{EXCESS_PRECISION_TYPE_IMPLICIT},\
+ @code{EXCESS_PRECISION_TYPE_FAST}, or\
+ @code{EXCESS_PRECISION_TYPE_STANDARD}.  For\
+ @code{EXCESS_PRECISION_TYPE_IMPLICIT}, the target should return which\
+ precision and range operations will be implictly evaluated in regardless\
+ of the excess precision explicitly added.  For\
+ @code{EXCESS_PRECISION_TYPE_STANDARD} and\
+ @code{EXCESS_PRECISION_TYPE_FAST}, the target should return the\
+ explicit excess precision that should be added depending on the\
+ value set for @code{-fexcess-precision=[standard|fast]}.",
+ enum flt_eval_method, (enum excess_precision_type type),
+ default_excess_precision)
+
 HOOK_VECTOR_END (c)
 
 /* Functions specific to the C++ frontend.  */
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index d6fd8b8..486e727 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -2127,4 +2127,12 @@ default_max_noce_ifcvt_seq_cost (edge e)
     return BRANCH_COST (true, predictable_p) * COSTS_N_INSNS (3);
 }
 
+/* Default implementation of TARGET_C_EXCESS_PRECISION.  */
+
+enum flt_eval_method
+default_excess_precision (enum excess_precision_type ATTRIBUTE_UNUSED)
+{
+  return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT;
+}
+
 #include "gt-targhooks.h"
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index afb1c00..e372257 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -263,4 +263,7 @@ extern bool default_optab_supported_p (int, machine_mode, machine_mode,
 
 extern unsigned int default_max_noce_ifcvt_seq_cost (edge);
 
+extern enum flt_eval_method
+default_excess_precision (enum excess_precision_type ATTRIBUTE_UNUSED);
+
 #endif /* GCC_TARGHOOKS_H */

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

* Re: [Patch 3/11] Implement TARGET_C_EXCESS_PRECISION for s390
  2016-10-07  8:34             ` Andreas Krebbel
  2016-10-07 13:11               ` Joseph Myers
@ 2016-10-14 16:53               ` James Greenhalgh
  2016-10-17 19:30                 ` Andreas Krebbel1
  1 sibling, 1 reply; 95+ messages in thread
From: James Greenhalgh @ 2016-10-14 16:53 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, joseph, law, uweigand, Andreas.Krebbel

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


Hi,

On Fri, Oct 07, 2016 at 10:34:25AM +0200, Andreas Krebbel wrote:
> On 10/04/2016 03:42 PM, Joseph Myers wrote:
> > On Tue, 4 Oct 2016, Andreas Krebbel wrote:
> >
> >>> (b) Handling EXCESS_PRECISION_TYPE_IMPLICIT like
> >>> EXCESS_PRECISION_TYPE_FAST would accurately describe what the back end
> >>> does.  It would mean that the default FLT_EVAL_METHOD is 0, which is a
> >>> more accurate description of how the compiler actually behaves, and would
> >>> avoid the suboptimal code in libgcc and glibc.  It would however mean that
> >>> unless -fexcess-precision=standard is used, FLT_EVAL_METHOD (accurate) is
> >>> out of synx with float_t in math.h (inaccurate).
> >>
> >> With (b) we would violate the C standard which explicitly states that
> >> the definition of float_t needs to be float if FLT_EVAL_METHOD is 0.
> >> I've no idea how much code really relies on that. So far I only know
> >> about the Plum Hall testsuite ;) So this probably would still be a safe
> >> change. Actually it was like that for many years without any problems
> >> ... until I've changed it due to the Plum Hall finding :(
> >> https://gcc.gnu.org/ml/gcc-patches/2013-03/msg01124.html
> >
> > You'd only violate it outside standards conformance modes (which you
> > should be using for running conformance testsuites); with -std=c11 etc.
> > -fexcess-precision=standard would be implied, meaning FLT_EVAL_METHOD
> > remains as 1 in that case.
>
> wrt (b): Agreed. I was more concerned about all the other code which might accidently be built
> without a strict standard compliance option. I did some searches in the source package repos. The
> only snippet where the definition of FLT_EVAL_METHOD might affect code generation is in musl libc
> but that one is being built with -std=c99. So I don't see anything speaking against (b). I'm ok with
> going that way.
>
> wrt (c): float_t appears to be more widely used than I expected. But the only hits which might
> indicate potential ABI problems where in clucene and libassa. (I've scanned the header files of
> about 25k Ubuntu source packages).
> I'm also not sure about script language interfaces with C. There might be potential problems out
> there which I wasn't able to catch with my scan.
> While I fully agree with you that the float_t type definition for S/390 in Glibc is plain wrong I do
> not really feel comfortable with changing it.
>
> An interesting case is imagemagick. They define their ABI-relevant MagickRealType based on the size
> of float_t in recent versions but excplicitly without depending on FLT_EVAL_METHOD
> (http://www.imagemagick.org/discourse-server/viewtopic.php?t=22136). They build with -std=gnu99 so
> this helps us with (b) I think. To my understanding MagickRealType would stay double not affected by
> FLT_EVAL_METHOD changes.

Here is a patch implementing what I think has been discussed in this thread.

OK?

Thanks,
James

---
gcc/

2016-10-14  James Greenhalgh  <james.greenhalgh@arm.com>

	* config/s390/s390.c (s390_excess_precision): New.
	(TARGET_C_EXCESS_PRECISION): Define.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Re-Patch-3-11-Implement-TARGET_C_EXCESS_PRECISION-fo.patch --]
[-- Type: text/x-patch;  name=0001-Re-Patch-3-11-Implement-TARGET_C_EXCESS_PRECISION-fo.patch, Size: 2384 bytes --]

diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index f69b470..8f6f199 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -15107,6 +15107,43 @@ s390_invalid_binary_op (int op ATTRIBUTE_UNUSED, const_tree type1, const_tree ty
   return NULL;
 }
 
+/* Implement TARGET_C_EXCESS_PRECISION.
+
+   FIXME: For historical reasons, float_t and double_t are typedef'ed to
+   double on s390, causing operations on float_t to operate in a higher
+   precision than is necessary.  However, it is not the case that SFmode
+   operations have implicit excess precision, and we generate more optimal
+   code if we let the compiler know no implicit extra precision is added.
+
+   That means when we are compiling with -fexcess-precision=fast, the value
+   we set for FLT_EVAL_METHOD will be out of line with the actual precision of
+   float_t (though they would be correct for -fexcess-precision=standard).
+
+   A complete fix would modify glibc to remove the unnecessary typedef
+   of float_t to double.  */
+
+static enum flt_eval_method
+s390_excess_precision (enum excess_precision_type type)
+{
+  switch (type)
+    {
+      case EXCESS_PRECISION_TYPE_IMPLICIT:
+      case EXCESS_PRECISION_TYPE_FAST:
+	/* The fastest type to promote to will always be the native type,
+	   whether that occurs with implicit excess precision or
+	   otherwise.  */
+	return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT;
+      case EXCESS_PRECISION_TYPE_STANDARD:
+	/* Otherwise, when we are in a standards compliant mode, to
+	   ensure consistency with the implementation in glibc, report that
+	   float is evaluated to the range and precision of double.  */
+	return FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE;
+      default:
+	gcc_unreachable ();
+    }
+  return FLT_EVAL_METHOD_UNPREDICTABLE;
+}
+
 /* Initialize GCC target structure.  */
 
 #undef  TARGET_ASM_ALIGNED_HI_OP
@@ -15167,6 +15204,9 @@ s390_invalid_binary_op (int op ATTRIBUTE_UNUSED, const_tree type1, const_tree ty
 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
 
+#undef TARGET_C_EXCESS_PRECISION
+#define TARGET_C_EXCESS_PRECISION s390_excess_precision
+
 #undef  TARGET_SCHED_ADJUST_PRIORITY
 #define TARGET_SCHED_ADJUST_PRIORITY s390_adjust_priority
 #undef TARGET_SCHED_ISSUE_RATE

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

* Re: [Patch 4/11] Implement TARGET_C_EXCESS_PRECISION for m68k
  2016-09-30 18:25   ` Andreas Schwab
@ 2016-10-14 16:55     ` James Greenhalgh
  0 siblings, 0 replies; 95+ messages in thread
From: James Greenhalgh @ 2016-10-14 16:55 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, law, schwab

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


On Fri, Sep 30, 2016 at 11:28:28AM -0600, Jeff Law wrote:
> On 09/30/2016 11:01 AM, James Greenhalgh wrote:
> >
> >Hi,
> >
> >This patch ports the logic from m68k's TARGET_FLT_EVAL_METHOD to the new
> >target hook TARGET_C_EXCESS_PRECISION.
> >
> >Patch tested by building an m68k-none-elf toolchain and running
> >m68k.exp (without the ability to execute) with no regressions, and manually
> >inspecting the output assembly code when compiling
> >testsuite/gcc.target/i386/excess-precision* to show no difference in
> >code-generation.
> >
> >OK?
> >
> >Thanks,
> >James
> >
> >---
> >gcc/
> >
> >2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>
> >
> >	* config/m68k/m68k.c (m68k_excess_precision): New.
> >	(TARGET_C_EXCESS_PRECISION): Define.
> OK when prereqs are approved.  Similarly for other targets where you
> needed to add this hook.

Thanks Jeff, Andreas,

I spotted a very silly bug when I was retesting this patch set - when I
swapped the namespace for the new traget macro it changed from
TARGET_EXCESS_PRECISION to TARGET_C_EXCESS_PRECISION but I failed to
update the m68k patch to reflect that.

This second revision fixes that (obvious) oversight.

OK?

Thanks,
James

---
gcc/

2016-10-14  James Greenhalgh  <james.greenhalgh@arm.com>

	* config/m68k/m68k.c (m68k_excess_precision): New.
	(TARGET_C_EXCESS_PRECISION): Define.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Re-Patch-4-11-Implement-TARGET_C_EXCESS_PRECISION-fo.patch --]
[-- Type: text/x-patch;  name=0001-Re-Patch-4-11-Implement-TARGET_C_EXCESS_PRECISION-fo.patch, Size: 2205 bytes --]

diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
index b152ca8..3edeb71 100644
--- a/gcc/config/m68k/m68k.c
+++ b/gcc/config/m68k/m68k.c
@@ -183,6 +183,8 @@ static rtx m68k_function_arg (cumulative_args_t, machine_mode,
 static bool m68k_cannot_force_const_mem (machine_mode mode, rtx x);
 static bool m68k_output_addr_const_extra (FILE *, rtx);
 static void m68k_init_sync_libfuncs (void) ATTRIBUTE_UNUSED;
+static enum flt_eval_method
+m68k_excess_precision (enum excess_precision_type);
 \f
 /* Initialize the GCC target structure.  */
 
@@ -323,6 +325,9 @@ static void m68k_init_sync_libfuncs (void) ATTRIBUTE_UNUSED;
 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA m68k_output_addr_const_extra
 
+#undef TARGET_C_EXCESS_PRECISION
+#define TARGET_C_EXCESS_PRECISION m68k_excess_precision
+
 /* The value stored by TAS.  */
 #undef TARGET_ATOMIC_TEST_AND_SET_TRUEVAL
 #define TARGET_ATOMIC_TEST_AND_SET_TRUEVAL 128
@@ -6531,4 +6536,36 @@ m68k_epilogue_uses (int regno ATTRIBUTE_UNUSED)
 	      == m68k_fk_interrupt_handler));
 }
 
+
+/* Implement TARGET_C_EXCESS_PRECISION.
+
+   Set the value of FLT_EVAL_METHOD in float.h.  When using 68040 fp
+   instructions, we get proper intermediate rounding, otherwise we
+   get extended precision results.  */
+
+static enum flt_eval_method
+m68k_excess_precision (enum excess_precision_type type)
+{
+  switch (type)
+    {
+      case EXCESS_PRECISION_TYPE_FAST:
+	/* The fastest type to promote to will always be the native type,
+	   whether that occurs with implicit excess precision or
+	   otherwise.  */
+	return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT;
+      case EXCESS_PRECISION_TYPE_STANDARD:
+      case EXCESS_PRECISION_TYPE_IMPLICIT:
+	/* Otherwise, the excess precision we want when we are
+	   in a standards compliant mode, and the implicit precision we
+	   provide can be identical.  */
+	if (TARGET_68040 || ! TARGET_68881)
+	  return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT;
+
+	return FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE;
+      default:
+	gcc_unreachable ();
+    }
+  return FLT_EVAL_METHOD_UNPREDICTABLE;
+}
+
 #include "gt-m68k.h"

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

* Re: [Patch 6/11] Migrate excess precision logic to use TARGET_EXCESS_PRECISION
  2016-09-30 17:34   ` Joseph Myers
@ 2016-10-14 16:56     ` James Greenhalgh
  2016-10-28 21:10       ` Joseph Myers
  0 siblings, 1 reply; 95+ messages in thread
From: James Greenhalgh @ 2016-10-14 16:56 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, joseph

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


On Fri, Sep 30, 2016 at 05:32:01PM +0000, Joseph Myers wrote:
> On Fri, 30 Sep 2016, James Greenhalgh wrote:
>
> >    /* float.h needs to know this.  */
> > +  /* We already have the option -fno-fp-int-builtin-inexact to ensure
> > +     certain built-in functions follow TS 18661-1 semantics.  It might be
> > +     reasonable to have a new option to enable FLT_EVAL_METHOD using new
> > +     values.  However, I'd be inclined to think that such an option should
> > +     be on by default for -std=gnu*, only off for strict conformance modes.
> > +     (There would be both __FLT_EVAL_METHOD__ and __FLT_EVAL_METHOD_C99__,
> > +     say, predefined macros, so that <float.h> could also always use the
> > +     new value if __STDC_WANT_IEC_60559_TYPES_EXT__ is defined.)  */
>
> This comment makes no sense in the context.  The comment should not be
> talking about some other option for a different issue, or about
> half-thought-out ideas for how something might be implemented; comments
> need to relate to the actual code (which in this case is obvious and not
> in need of comments beyond saying what the macro semantics are).

Yes, that was a particularly useless comment. Modified in this revision.

> In any case, this patch does not achieve the proposed semantics, since
> there is no change to ginclude/float.h.

Ah, I thought float.h was outside the project. My mistake.

> The goal is: if the user's options imply new FLT_EVAL_METHOD values are
> OK, *or* they defined __STDC_WANT_IEC_60559_TYPES_EXT__ before including
> <float.h>, it should use the appropriate TS 18661-3 value.  Otherwise
> (strict standards modes for existing standards, no
> __STDC_WANT_IEC_60559_TYPES_EXT__) it should use a C11 value.
>
> So in a strict standards mode you need to predefine macros with both
> choices of values and let <float.h> choose between them.  One possibility
> is: __FLT_EVAL_METHOD_C99__ is the value to use when
> __STDC_WANT_IEC_60559_TYPES_EXT__ is not defined, __FLT_EVAL_METHOD__ is
> the value to use when it is defined.  Or some other arrangement, with or
> without a macro saying what setting you have for the new option.  But you
> can't avoid changing <float.h>.
>
> Tests then should be testing the value of FLT_EVAL_METHOD from <float.h>,
> *not* the internal macros predefined by the compiler.

I've added tests testing the float.h behaviour in this patch, and I'll
leave those testing __FLT_EVAL_METHOD__ in patch [5/11]. For all
the difference the extra testing makes, I'd rather test both, as explicit
testing that the clamping from -fpermitted-eval-methods works, and the
value is correctly set in float.h, but I can certainly drop the tests in
5/11 if you'd prefer.

I've also fixed a bug I noticed with the legacy __fp16 type. Excess
precision should leave this alone, so we need to check with
targetm.promoted_type before applying the rules in excess_precision_type.

Thanks,
James

---
gcc/

2016-10-14  James Greenhalgh  <james.greenhalgh@arm.com>

	* toplev.c (init_excess_precision): Delete most logic.
	* tree.c (excess_precision_type): Rewrite to use
	TARGET_EXCESS_PRECISION.
	* doc/invoke.texi (-fexcess-precision): Document behaviour in a
	more generic fashion.
	* ginclude/float.h: Wrap definition of FLT_EVAL_METHOD in
	__STDC_WANT_IEC_60559_TYPES_EXT__.

gcc/c-family/

2016-10-14  James Greenhalgh  <james.greenhalgh@arm.com>

	* c-common.c (excess_precision_mode_join): New.
	(c_ts18661_flt_eval_method): New.
	(c_c11_flt_eval_method): Likewise.
	(c_flt_eval_method): Likewise.
	* c-common.h (excess_precision_mode_join): New.
	(c_flt_eval_method): Likewise.
	* c-cppbuiltin.c (c_cpp_flt_eval_method_iec_559): New.
	(cpp_iec_559_value): Call it.
	(c_cpp_builtins): Modify logic for __LIBGCC_*_EXCESS_PRECISION__,
	call c_flt_eval_method to set __FLT_EVAL_METHOD__ and
	__FLT_EVAL_METHOD_TS_18661_3__.

gcc/testsuite/

2016-10-14  James Greenhalgh  <james.greenhalgh@arm.com>

	* gcc.dg/fpermitted-flt-eval-methods_3.c: New.
	* gcc.dg/fpermitted-flt-eval-methods_4.c: Likewise.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Re-Patch-6-11-Migrate-excess-precision-logic-to-use-.patch --]
[-- Type: text/x-patch;  name=0001-Re-Patch-6-11-Migrate-excess-precision-logic-to-use-.patch, Size: 22792 bytes --]

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index c4a0ce8..2a4add5 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -11043,4 +11043,86 @@ cb_get_suggestion (cpp_reader *, const char *goal,
   return bm.get_best_meaningful_candidate ();
 }
 
+/* Return the latice point which is the wider of the two FLT_EVAL_METHOD
+   modes X, Y.  This isn't just  >, as the FLT_EVAL_METHOD values added
+   by C TS 18661-3 for interchange  types that are computed in their
+   native precision are larger than the C11 values for evaluating in the
+   precision of float/double/long double.  If either mode is
+   FLT_EVAL_METHOD_UNPREDICTABLE, return that.  */
+
+enum flt_eval_method
+excess_precision_mode_join (enum flt_eval_method x,
+			    enum flt_eval_method y)
+{
+  if (x == FLT_EVAL_METHOD_UNPREDICTABLE
+      || y == FLT_EVAL_METHOD_UNPREDICTABLE)
+    return FLT_EVAL_METHOD_UNPREDICTABLE;
+
+  /* GCC only supports one interchange type right now, _Float16.  If
+     we're evaluating _Float16 in 16-bit precision, then flt_eval_method
+     will be FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16.  */
+  if (x == FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16)
+    return y;
+  if (y == FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16)
+    return x;
+
+  /* Other values for flt_eval_method are directly comparable, and we want
+     the maximum.  */
+  return MAX (x, y);
+}
+
+/* Return the value that should be set for FLT_EVAL_METHOD in the
+   context of ISO/IEC TS 18861-3.
+
+   This relates to the effective excess precision seen by the user,
+   which is the join point of the precision the target requests for
+   -fexcess-precision={standard,fast} and the implicit excess precision
+   the target uses.  */
+
+static enum flt_eval_method
+c_ts18661_flt_eval_method (void)
+{
+  enum flt_eval_method implicit
+    = targetm.c.excess_precision (EXCESS_PRECISION_TYPE_IMPLICIT);
+
+  enum excess_precision_type flag_type
+    = (flag_excess_precision_cmdline == EXCESS_PRECISION_STANDARD
+       ? EXCESS_PRECISION_TYPE_STANDARD
+       : EXCESS_PRECISION_TYPE_FAST);
+
+  enum flt_eval_method requested
+    = targetm.c.excess_precision (flag_type);
+
+  return excess_precision_mode_join (implicit, requested);
+}
+
+/* As c_cpp_ts18661_flt_eval_method, but clamps the expected values to
+   those that were permitted by C11.  That is to say, eliminates
+   FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16.  */
+
+static enum flt_eval_method
+c_c11_flt_eval_method (void)
+{
+  return excess_precision_mode_join (c_ts18661_flt_eval_method (),
+				     FLT_EVAL_METHOD_PROMOTE_TO_FLOAT);
+}
+
+/* Return the value that should be set for FLT_EVAL_METHOD.
+   MAYBE_C11_ONLY_P is TRUE if we should check
+   FLAG_PERMITTED_EVAL_METHODS as to whether we should limit the possible
+   values we can return to those from C99/C11, and FALSE otherwise.
+   See the comments on c_ts18661_flt_eval_method for what value we choose
+   to set here.  */
+
+int
+c_flt_eval_method (bool maybe_c11_only_p)
+{
+  if (maybe_c11_only_p
+      && flag_permitted_flt_eval_methods
+	  == PERMITTED_FLT_EVAL_METHODS_C11)
+    return c_c11_flt_eval_method ();
+  else
+    return c_ts18661_flt_eval_method ();
+}
+
 #include "gt-c-family-c-common.h"
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 8ef1d74..bb28784 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1538,6 +1538,11 @@ extern bool maybe_warn_shift_overflow (location_t, tree, tree);
 extern void warn_duplicated_cond_add_or_warn (location_t, tree, vec<tree> **);
 extern bool diagnose_mismatched_attributes (tree, tree);
 
+extern enum flt_eval_method
+excess_precision_mode_join (enum flt_eval_method, enum flt_eval_method);
+
+extern int c_flt_eval_method (bool ts18661_p);
+
 #if CHECKING_P
 namespace selftest {
   extern void c_format_c_tests (void);
diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
index 06b5aa3..d11d115 100644
--- a/gcc/c-family/c-cppbuiltin.c
+++ b/gcc/c-family/c-cppbuiltin.c
@@ -728,6 +728,32 @@ cpp_atomic_builtins (cpp_reader *pfile)
 			(have_swap[psize]? 2 : 1));
 }
 
+/* If the join of the implicit precision in which the target will compute
+   floating-point values and the standard precision in which the target will
+   compute values is not equal to the standard precision, then the target
+   is either unpredictable, or is a broken configuration in which it claims
+   standards compliance, but doesn't honor that.
+
+   Effective predictability for __GCC_IEC_559 in flag_iso_mode, means that
+   the implicit precision is not wider, or less predictable than the
+   standard precision.
+
+   Return TRUE if we have been asked to compile with
+   -fexcess-precision=standard, and following the rules above we are able
+   to guarantee the standards mode.  */
+
+static bool
+c_cpp_flt_eval_method_iec_559 (void)
+{
+  enum flt_eval_method implicit
+    = targetm.c.excess_precision (EXCESS_PRECISION_TYPE_IMPLICIT);
+  enum flt_eval_method standard
+    = targetm.c.excess_precision (EXCESS_PRECISION_TYPE_STANDARD);
+
+  return (excess_precision_mode_join (implicit, standard) == standard
+	  && flag_excess_precision_cmdline == EXCESS_PRECISION_STANDARD);
+}
+
 /* Return the value for __GCC_IEC_559.  */
 static int
 cpp_iec_559_value (void)
@@ -775,11 +801,12 @@ cpp_iec_559_value (void)
      applies to unpredictable contraction.  For C++, and outside
      strict conformance mode, do not consider these options to mean
      lack of IEEE 754 support.  */
+
   if (flag_iso
       && !c_dialect_cxx ()
-      && TARGET_FLT_EVAL_METHOD != 0
-      && flag_excess_precision_cmdline != EXCESS_PRECISION_STANDARD)
+      && !c_cpp_flt_eval_method_iec_559 ())
     ret = 0;
+
   if (flag_iso
       && !c_dialect_cxx ()
       && flag_fp_contract_mode == FP_CONTRACT_FAST)
@@ -1039,9 +1066,22 @@ c_cpp_builtins (cpp_reader *pfile)
   builtin_define_with_int_value ("__GCC_IEC_559_COMPLEX",
 				 cpp_iec_559_complex_value ());
 
-  /* float.h needs to know this.  */
+  /* float.h needs these to correctly set FLT_EVAL_METHOD
+
+     We define two values:
+
+     __FLT_EVAL_METHOD__
+       Which, depending on the value given for
+       -fpermitted-flt-eval-methods, may be limited to only those values
+       for FLT_EVAL_METHOD defined in C99/C11.
+
+     __FLT_EVAL_METHOD_TS_18661_3__
+       Which always permits the values for FLT_EVAL_METHOD defined in
+       ISO/IEC TS 18661-3.  */
   builtin_define_with_int_value ("__FLT_EVAL_METHOD__",
-				 TARGET_FLT_EVAL_METHOD);
+				 c_flt_eval_method (true));
+  builtin_define_with_int_value ("__FLT_EVAL_METHOD_TS_18661_3__",
+				 c_flt_eval_method (false));
 
   /* And decfloat.h needs this.  */
   builtin_define_with_int_value ("__DEC_EVAL_METHOD__",
@@ -1182,25 +1222,38 @@ c_cpp_builtins (cpp_reader *pfile)
 	      gcc_assert (found_suffix);
 	    }
 	  builtin_define_with_value (macro_name, suffix, 0);
+
+	  /* The way __LIBGCC_*_EXCESS_PRECISION__ is used is about
+	     eliminating excess precision from results assigned to
+	     variables - meaning it should be about the implicit excess
+	     precision only.  */
 	  bool excess_precision = false;
-	  if (TARGET_FLT_EVAL_METHOD != 0
-	      && mode != TYPE_MODE (long_double_type_node)
-	      && (mode == TYPE_MODE (float_type_node)
-		  || mode == TYPE_MODE (double_type_node)))
-	    switch (TARGET_FLT_EVAL_METHOD)
-	      {
-	      case -1:
-	      case 2:
-		excess_precision = true;
-		break;
-
-	      case 1:
-		excess_precision = mode == TYPE_MODE (float_type_node);
-		break;
-
-	      default:
-		gcc_unreachable ();
-	      }
+	  machine_mode float16_type_mode = (float16_type_node
+					    ? TYPE_MODE (float16_type_node)
+					    : VOIDmode);
+	  switch (targetm.c.excess_precision
+		    (EXCESS_PRECISION_TYPE_IMPLICIT))
+	    {
+	    case FLT_EVAL_METHOD_UNPREDICTABLE:
+	    case FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE:
+	      excess_precision = (mode == float16_type_mode
+				  || mode == TYPE_MODE (float_type_node)
+				  || mode == TYPE_MODE (double_type_node));
+	      break;
+
+	    case FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE:
+	      excess_precision = (mode == float16_type_mode
+				  || mode == TYPE_MODE (float_type_node));
+	      break;
+	    case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT:
+	      excess_precision = mode == float16_type_mode;
+	      break;
+	    case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16:
+	      excess_precision = false;
+	      break;
+	    default:
+	      gcc_unreachable ();
+	    }
 	  macro_name = (char *) alloca (strlen (name)
 					+ sizeof ("__LIBGCC__EXCESS_"
 						  "PRECISION__"));
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index e788565..2b6b653 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -8805,15 +8805,14 @@ them to store all pertinent intermediate computations into variables.
 @item -fexcess-precision=@var{style}
 @opindex fexcess-precision
 This option allows further control over excess precision on machines
-where floating-point registers have more precision than the IEEE
-@code{float} and @code{double} types and the processor does not
-support operations rounding to those types.  By default,
-@option{-fexcess-precision=fast} is in effect; this means that
-operations are carried out in the precision of the registers and that
-it is unpredictable when rounding to the types specified in the source
-code takes place.  When compiling C, if
-@option{-fexcess-precision=standard} is specified then excess
-precision follows the rules specified in ISO C99; in particular,
+where floating-point operations occur in a format with more precision or
+range than the IEEE standard and interchange floating-point types.  By
+default, @option{-fexcess-precision=fast} is in effect; this means that
+operations may be carried out in a wider precision than the types specified
+in the source if that would result in faster code, and it is unpredictable
+when rounding to the types specified in the source code takes place.
+When compiling C, if @option{-fexcess-precision=standard} is specified then
+excess precision follows the rules specified in ISO C99; in particular,
 both casts and assignments cause values to be rounded to their
 semantic types (whereas @option{-ffloat-store} only affects
 assignments).  This option is enabled by default for C if a strict
diff --git a/gcc/ginclude/float.h b/gcc/ginclude/float.h
index 421f735..3df2889 100644
--- a/gcc/ginclude/float.h
+++ b/gcc/ginclude/float.h
@@ -129,21 +129,73 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
 #if (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) \
      || (defined (__cplusplus) && __cplusplus >= 201103L)
-/* The floating-point expression evaluation method.
-        -1  indeterminate
-         0  evaluate all operations and constants just to the range and
-            precision of the type
-         1  evaluate operations and constants of type float and double
-            to the range and precision of the double type, evaluate
-            long double operations and constants to the range and
-            precision of the long double type
-         2  evaluate all operations and constants to the range and
-            precision of the long double type
+/* The floating-point expression evaluation method.  The precise
+   definitions of these values are generalised to include support for
+   the interchange and extended types defined in ISO/IEC TS 18661-3.
+   Prior to this (for C99/C11) the definitions were:
+
+	-1  indeterminate
+	 0  evaluate all operations and constants just to the range and
+	    precision of the type
+	 1  evaluate operations and constants of type float and double
+	    to the range and precision of the double type, evaluate
+	    long double operations and constants to the range and
+	    precision of the long double type
+	 2  evaluate all operations and constants to the range and
+	    precision of the long double type
+
+   The TS 18661-3 definitions are:
+
+	-1  indeterminate
+	 0  evaluate all operations and constants, whose semantic type has
+	    at most the range and precision of float, to the range and
+	    precision of float; evaluate all other operations and constants
+	    to the range and precision of the semantic type.
+	 1  evaluate all operations and constants, whose semantic type has
+	    at most the range and precision of double, to the range and
+	    precision of double; evaluate all other operations and constants
+	    to the range and precision of the semantic type.
+	 2  evaluate all operations and constants, whose semantic type has
+	    at most the range and precision of long double, to the range and
+	    precision of long double; evaluate all other operations and
+	    constants to the range and precision of the semantic type.
+	 N  where _FloatN  is a supported interchange floating type
+	    evaluate all operations and constants, whose semantic type has
+	    at most the range and precision of the _FloatN type, to the
+	    range and precision of the _FloatN type; evaluate all other
+	    operations and constants to the range and precision of the
+	    semantic type.
+	 N + 1, where _FloatNx is a supported extended floating type
+	    evaluate operations and constants, whose semantic type has at
+	    most the range and precision of the _FloatNx type, to the range
+	    and precision of the _FloatNx type; evaluate all other
+	    operations and constants to the range and precision of the
+	    semantic type.
+
+   The compiler predefines two macros:
+
+      __FLT_EVAL_METHOD__
+      Which, depending on the value given for
+      -fpermitted-flt-eval-methods, may be limited to only those values
+      for FLT_EVAL_METHOD defined in C99/C11.
+
+     __FLT_EVAL_METHOD_TS_18661_3__
+      Which always permits the values for FLT_EVAL_METHOD defined in
+      ISO/IEC TS 18661-3.
+
+     Here we want to use __FLT_EVAL_METHOD__, unless
+     __STDC_WANT_IEC_60559_TYPES_EXT__ is defined, in which case the user
+     is specifically asking for the ISO/IEC TS 18661-3 types, so we use
+     __FLT_EVAL_METHOD_TS_18661_3__.
 
    ??? This ought to change with the setting of the fp control word;
    the value provided by the compiler assumes the widest setting.  */
 #undef FLT_EVAL_METHOD
+#ifdef __STDC_WANT_IEC_60559_TYPES_EXT__
+#define FLT_EVAL_METHOD __FLT_EVAL_METHOD_TS_18661_3__
+#else
 #define FLT_EVAL_METHOD	__FLT_EVAL_METHOD__
+#endif
 
 /* Number of decimal digits, n, such that any floating-point number in the
    widest supported floating type with pmax radix b digits can be rounded
diff --git a/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_3.c b/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_3.c
new file mode 100644
index 0000000..c7bd756
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_3.c
@@ -0,0 +1,21 @@
+/* { dg-do run } */
+/* { dg-options "-std=c11" } */
+
+/* Test that when compiling with -std=c11, we only see the C99/C11 values
+   for FLT_EVAL_METHOD.  */
+
+#include <float.h>
+
+int main (int argc, char** argv)
+{
+  switch (FLT_EVAL_METHOD)
+    {
+      case 0:
+      case 1:
+      case 2:
+      case -1:
+	return 0;
+      default:
+	return 1;
+    }
+}
diff --git a/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_4.c b/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_4.c
new file mode 100644
index 0000000..a7bbb65
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_4.c
@@ -0,0 +1,25 @@
+/* { dg-do run } */
+/* { dg-options "-std=c11" } */
+
+/* Test that when compiling with -std=c11 and defining
+   __STDC_WANT_IEC_60559_TYPES_EXT__, we only see the ISO/IEC TS
+   18661-3 values for FLT_EVAL_METHOD.  */
+
+#define __STDC_WANT_IEC_60559_TYPES_EXT__
+
+#include <float.h>
+
+int main (int argc, char** argv)
+{
+  switch (__FLT_EVAL_METHOD__)
+    {
+      case 0:
+      case 1:
+      case 2:
+      case 16:
+      case -1:
+	return 0;
+      default:
+	return 1;
+    }
+}
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 1df80d0..526f02c 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -1685,41 +1685,17 @@ backend_init (void)
   init_regs ();
 }
 
-/* Initialize excess precision settings.  */
+/* Initialize excess precision settings.
+
+   We have no need to modify anything here, just keep track of what the
+   user requested.  We'll figure out any appropriate relaxations
+   later.  */
+
 static void
 init_excess_precision (void)
 {
-  /* Adjust excess precision handling based on the target options.  If
-     the front end cannot handle it, flag_excess_precision_cmdline
-     will already have been set accordingly in the post_options
-     hook.  */
   gcc_assert (flag_excess_precision_cmdline != EXCESS_PRECISION_DEFAULT);
   flag_excess_precision = flag_excess_precision_cmdline;
-  if (flag_unsafe_math_optimizations)
-    flag_excess_precision = EXCESS_PRECISION_FAST;
-  if (flag_excess_precision == EXCESS_PRECISION_STANDARD)
-    {
-      int flt_eval_method = TARGET_FLT_EVAL_METHOD;
-      switch (flt_eval_method)
-	{
-	case -1:
-	case 0:
-	  /* Either the target acts unpredictably (-1) or has all the
-	     operations required not to have excess precision (0).  */
-	  flag_excess_precision = EXCESS_PRECISION_FAST;
-	  break;
-	case 1:
-	case 2:
-	  /* In these cases, predictable excess precision makes
-	     sense.  */
-	  break;
-	default:
-	  /* Any other implementation-defined FLT_EVAL_METHOD values
-	     require the compiler to handle the associated excess
-	     precision rules in excess_precision_type.  */
-	  gcc_unreachable ();
-	}
-    }
 }
 
 /* Initialize things that are both lang-dependent and target-dependent.
diff --git a/gcc/tree.c b/gcc/tree.c
index a3a8f0a..c20b758 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -8835,50 +8835,99 @@ build_complex_type (tree component_type, bool named)
 tree
 excess_precision_type (tree type)
 {
-  if (flag_excess_precision != EXCESS_PRECISION_FAST)
+  /* The target can give two different responses to the question of
+     which excess precision mode it would like depending on whether we
+     are in -fexcess-precision=standard or -fexcess-precision=fast.  */
+
+  enum excess_precision_type requested_type
+    = (flag_excess_precision == EXCESS_PRECISION_FAST
+       ? EXCESS_PRECISION_TYPE_FAST
+       : EXCESS_PRECISION_TYPE_STANDARD);
+
+  enum flt_eval_method target_flt_eval_method
+    = targetm.c.excess_precision (requested_type);
+
+  /* The target should not ask for unpredictable float evaluation (though
+     it might advertise that implicitly the evaluation is unpredictable,
+     but we don't care about that here, it will have been reported
+     elsewhere).  If it does ask for unpredictable evaluation, we have
+     nothing to do here.  */
+  gcc_assert (target_flt_eval_method != FLT_EVAL_METHOD_UNPREDICTABLE);
+
+  /* Nothing to do.  The target has asked for all types we know about
+     to be computed with their native precision and range.  */
+  if (target_flt_eval_method == FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16)
+    return NULL_TREE;
+
+  /* The target will promote this type in a target-dependent way, so excess
+     precision ought to leave it alone.  */
+  if (targetm.promoted_type (type) != NULL_TREE)
+    return NULL_TREE;
+
+  machine_mode float16_type_mode = (float16_type_node
+				    ? TYPE_MODE (float16_type_node)
+				    : VOIDmode);
+  machine_mode float_type_mode = TYPE_MODE (float_type_node);
+  machine_mode double_type_mode = TYPE_MODE (double_type_node);
+
+  switch (TREE_CODE (type))
     {
-      int flt_eval_method = TARGET_FLT_EVAL_METHOD;
-      switch (TREE_CODE (type))
-	{
-	case REAL_TYPE:
-	  switch (flt_eval_method)
-	    {
-	    case 1:
-	      if (TYPE_MODE (type) == TYPE_MODE (float_type_node))
-		return double_type_node;
-	      break;
-	    case 2:
-	      if (TYPE_MODE (type) == TYPE_MODE (float_type_node)
-		  || TYPE_MODE (type) == TYPE_MODE (double_type_node))
-		return long_double_type_node;
-	      break;
-	    default:
-	      gcc_unreachable ();
-	    }
-	  break;
-	case COMPLEX_TYPE:
-	  if (TREE_CODE (TREE_TYPE (type)) != REAL_TYPE)
-	    return NULL_TREE;
-	  switch (flt_eval_method)
-	    {
-	    case 1:
-	      if (TYPE_MODE (TREE_TYPE (type)) == TYPE_MODE (float_type_node))
-		return complex_double_type_node;
-	      break;
-	    case 2:
-	      if (TYPE_MODE (TREE_TYPE (type)) == TYPE_MODE (float_type_node)
-		  || (TYPE_MODE (TREE_TYPE (type))
-		      == TYPE_MODE (double_type_node)))
-		return complex_long_double_type_node;
-	      break;
-	    default:
-	      gcc_unreachable ();
-	    }
-	  break;
-	default:
-	  break;
-	}
+    case REAL_TYPE:
+      {
+	machine_mode type_mode = TYPE_MODE (type);
+	switch (target_flt_eval_method)
+	  {
+	  case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT:
+	    if (type_mode == float16_type_mode)
+	      return float_type_node;
+	    break;
+	  case FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE:
+	    if (type_mode == float16_type_mode
+		|| type_mode == float_type_mode)
+	      return double_type_node;
+	    break;
+	  case FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE:
+	    if (type_mode == float16_type_mode
+		|| type_mode == float_type_mode
+		|| type_mode == double_type_mode)
+	      return long_double_type_node;
+	    break;
+	  default:
+	    gcc_unreachable ();
+	  }
+	break;
+      }
+    case COMPLEX_TYPE:
+      {
+	if (TREE_CODE (TREE_TYPE (type)) != REAL_TYPE)
+	  return NULL_TREE;
+	machine_mode type_mode = TYPE_MODE (TREE_TYPE (type));
+	switch (target_flt_eval_method)
+	  {
+	  case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT:
+	    if (type_mode == float16_type_mode)
+	      return complex_float_type_node;
+	    break;
+	  case FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE:
+	    if (type_mode == float16_type_mode
+		|| type_mode == float_type_mode)
+	      return complex_double_type_node;
+	    break;
+	  case FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE:
+	    if (type_mode == float16_type_mode
+		|| type_mode == float_type_mode
+		|| type_mode == double_type_mode)
+	      return complex_long_double_type_node;
+	    break;
+	  default:
+	    gcc_unreachable ();
+	  }
+	break;
+      }
+    default:
+      break;
     }
+
   return NULL_TREE;
 }
 \f

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

* Re: [Patch AArch64 11/11] Enable _Float16
  2016-09-30 17:14   ` [Patch AArch64 11/11] Enable _Float16 James Greenhalgh
@ 2016-10-14 17:02     ` James Greenhalgh
  0 siblings, 0 replies; 95+ messages in thread
From: James Greenhalgh @ 2016-10-14 17:02 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, joseph, marcus.shawcroft, richard.earnshaw

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


On Fri, Sep 30, 2016 at 06:03:57PM +0100, James Greenhalgh wrote:
> Hi,
>
> Finally, this patch adds the back-end wiring to get AArch64 support for
> the _Float16 type working.
>
> Bootstrapped on AArch64 with no issues.
>
> OK?

I spotted a bug in the way I'd written aarch64_promoted_type. We were not
taking the TYPE_MAIN_VARIANT before comparing with aarch64_fp16_type, so we
would fail to promote "volatile __fp16" correctly.

That's fixed in this revision, which has been through a new round of
bootstrap and cross-testing.

OK?

Thanks,
James

---
2016-10-14  James Greenhalgh  <james.greenhalgh@arm.com>

	* config/aarch64/aarch64-c.c (aarch64_update_cpp_builtins): Update
	__FLT_EVAL_METHOD__ and __FLT_EVAL_METHOD_C99__ when we switch
	architecture levels.
	* config/aarch64/aarch64.c (aarch64_promoted_type): Only promote
	the aarch64_fp16_type_node, not all HFmode types.
	(aarch64_libgcc_floating_mode_supported_p): Support HFmode.
	(aarch64_scalar_mode_supported_p): Likewise.
	(aarch64_excess_precision): New.
	(TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P): Define.
	(TARGET_SCALAR_MODE_SUPPORTED_P): Likewise.
	(TARGET_C_EXCESS_PRECISION): Likewise.

2016-10-14  James Greenhalgh  <james.greenhalgh@arm.com>

	* gcc.target/aarch64/_Float16_1.c: New.
	* gcc.target/aarch64/_Float16_2.c: Likewise.
	* gcc.target/aarch64/_Float16_3.c: Likewise.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Re-Patch-AArch64-11-11-Enable-_Float16.patch --]
[-- Type: text/x-patch;  name=0001-Re-Patch-AArch64-11-11-Enable-_Float16.patch, Size: 9753 bytes --]

diff --git a/gcc/config/aarch64/aarch64-c.c b/gcc/config/aarch64/aarch64-c.c
index 422e322..320b912 100644
--- a/gcc/config/aarch64/aarch64-c.c
+++ b/gcc/config/aarch64/aarch64-c.c
@@ -133,6 +133,16 @@ aarch64_update_cpp_builtins (cpp_reader *pfile)
 
   aarch64_def_or_undef (TARGET_CRYPTO, "__ARM_FEATURE_CRYPTO", pfile);
   aarch64_def_or_undef (TARGET_SIMD_RDMA, "__ARM_FEATURE_QRDMX", pfile);
+
+  /* Not for ACLE, but required to keep "float.h" correct if we switch
+     target between implementations that do or do not support ARMv8.2-A
+     16-bit floating-point extensions.  */
+  cpp_undef (pfile, "__FLT_EVAL_METHOD__");
+  builtin_define_with_int_value ("__FLT_EVAL_METHOD__",
+				 c_flt_eval_method (true));
+  cpp_undef (pfile, "__FLT_EVAL_METHOD_C99__");
+  builtin_define_with_int_value ("__FLT_EVAL_METHOD_C99__",
+				 c_flt_eval_method (false));
 }
 
 /* Implement TARGET_CPU_CPP_BUILTINS.  */
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index f32eb5f..4f9191b 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -14025,12 +14025,20 @@ aarch64_vec_fpconst_pow_of_2 (rtx x)
   return firstval;
 }
 
-/* Implement TARGET_PROMOTED_TYPE to promote __fp16 to float.  */
+/* Implement TARGET_PROMOTED_TYPE to promote 16-bit floating point types
+   to float.
+
+   __fp16 always promotes through this hook.
+   _Float16 may promote if TARGET_FLT_EVAL_METHOD is 16, but we do that
+   through the generic excess precision logic rather than here.  */
+
 static tree
 aarch64_promoted_type (const_tree t)
 {
-  if (SCALAR_FLOAT_TYPE_P (t) && TYPE_PRECISION (t) == 16)
+
+  if (TYPE_P (t) && TYPE_MAIN_VARIANT (t) == aarch64_fp16_type_node)
     return float_type_node;
+
   return NULL_TREE;
 }
 
@@ -14050,6 +14058,17 @@ aarch64_optab_supported_p (int op, machine_mode mode1, machine_mode,
     }
 }
 
+/* Implement TARGET_LIBGCC_FLOATING_POINT_MODE_SUPPORTED_P - return TRUE
+   if MODE is HFmode, and punt to the generic implementation otherwise.  */
+
+static bool
+aarch64_libgcc_floating_mode_supported_p (machine_mode mode)
+{
+  return (mode == HFmode
+	  ? true
+	  : default_libgcc_floating_mode_supported_p (mode));
+}
+
 /* Implement TARGET_SCALAR_MODE_SUPPORTED_P - return TRUE
    if MODE is HFmode, and punt to the generic implementation otherwise.  */
 
@@ -14061,6 +14080,47 @@ aarch64_scalar_mode_supported_p (machine_mode mode)
 	  : default_scalar_mode_supported_p (mode));
 }
 
+/* Set the value of FLT_EVAL_METHOD.
+   ISO/IEC TS 18661-3 defines two values that we'd like to make use of:
+
+    0: evaluate all operations and constants, whose semantic type has at
+       most the range and precision of type float, to the range and
+       precision of float; evaluate all other operations and constants to
+       the range and precision of the semantic type;
+
+    N, where _FloatN is a supported interchange floating type
+       evaluate all operations and constants, whose semantic type has at
+       most the range and precision of _FloatN type, to the range and
+       precision of the _FloatN type; evaluate all other operations and
+       constants to the range and precision of the semantic type;
+
+   If we have the ARMv8.2-A extensions then we support _Float16 in native
+   precision, so we should set this to 16.  Otherwise, we support the type,
+   but want to evaluate expressions in float precision, so set this to
+   0.  */
+
+static enum flt_eval_method
+aarch64_excess_precision (enum excess_precision_type type)
+{
+  switch (type)
+    {
+      case EXCESS_PRECISION_TYPE_FAST:
+      case EXCESS_PRECISION_TYPE_STANDARD:
+	/* We can calculate either in 16-bit range and precision or
+	   32-bit range and precision.  Make that decision based on whether
+	   we have native support for the ARMv8.2-A 16-bit floating-point
+	   instructions or not.  */
+	return (TARGET_FP_F16INST
+		? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16
+		: FLT_EVAL_METHOD_PROMOTE_TO_FLOAT);
+      case EXCESS_PRECISION_TYPE_IMPLICIT:
+	return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16;
+      default:
+	gcc_unreachable ();
+    }
+  return FLT_EVAL_METHOD_UNPREDICTABLE;
+}
+
 #undef TARGET_ADDRESS_COST
 #define TARGET_ADDRESS_COST aarch64_address_cost
 
@@ -14139,6 +14199,9 @@ aarch64_scalar_mode_supported_p (machine_mode mode)
 #undef TARGET_BUILTIN_RECIPROCAL
 #define TARGET_BUILTIN_RECIPROCAL aarch64_builtin_reciprocal
 
+#undef TARGET_C_EXCESS_PRECISION
+#define TARGET_C_EXCESS_PRECISION aarch64_excess_precision
+
 #undef  TARGET_EXPAND_BUILTIN
 #define TARGET_EXPAND_BUILTIN aarch64_expand_builtin
 
@@ -14195,6 +14258,10 @@ aarch64_scalar_mode_supported_p (machine_mode mode)
 #undef TARGET_LIBGCC_CMP_RETURN_MODE
 #define TARGET_LIBGCC_CMP_RETURN_MODE aarch64_libgcc_cmp_return_mode
 
+#undef TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P
+#define TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P \
+aarch64_libgcc_floating_mode_supported_p
+
 #undef TARGET_MANGLE_TYPE
 #define TARGET_MANGLE_TYPE aarch64_mangle_type
 
diff --git a/gcc/testsuite/gcc.target/aarch64/_Float16_1.c b/gcc/testsuite/gcc.target/aarch64/_Float16_1.c
new file mode 100644
index 0000000..320f154
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/_Float16_1.c
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=armv8.2-a+nofp16" } */
+
+#pragma GCC target ("arch=armv8.2-a+nofp16")
+
+_Float16
+foo_v8 (_Float16 x, _Float16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+__fp16
+bar_v8 (__fp16 x, __fp16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+#pragma GCC target ("arch=armv8.2-a+fp16")
+
+_Float16
+foo_v82 (_Float16 x, _Float16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+__fp16
+bar_v82 (__fp16 x, __fp16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+/* Test that we merge to FMA operations.  This indicates that we are not
+   making extraneous conversions between modes.  */
+
+/* Three FMA operations in 32-bit precision, from foo_v8, bar_v8, bar_v82.  */
+/* { dg-final { scan-assembler-times "fmadd\ts\[0-9\]\+" 3 } } */
+
+/* One FMA operation in 16-bit precision, from foo_v82.  */
+/* { dg-final { scan-assembler-times "fmadd\th\[0-9\]\+" 1 } } */
+
+/* Test that we are resetting the __FLT_EVAL_METHOD__.  */
+/* { dg-final { scan-assembler-times "mov\tw\[0-9\]\+, 16" 2 } } */
+/* { dg-final { scan-assembler-times "str\twzr" 2 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/_Float16_2.c b/gcc/testsuite/gcc.target/aarch64/_Float16_2.c
new file mode 100644
index 0000000..8b2aa1e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/_Float16_2.c
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=armv8.2-a+nofp16 -fpermitted-flt-eval-methods=c11" } */
+
+#pragma GCC target ("arch=armv8.2-a+nofp16")
+
+_Float16
+foo_v8 (_Float16 x, _Float16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+__fp16
+bar_v8 (__fp16 x, __fp16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+#pragma GCC target ("arch=armv8.2-a+fp16")
+
+_Float16
+foo_v82 (_Float16 x, _Float16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+__fp16
+bar_v82 (__fp16 x, __fp16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+/* Test that we merge to FMA operations.  This indicates that we are not
+   making extraneous conversions between modes.  */
+
+/* Three FMA operations in 32-bit precision, from foo_v8, bar_v8, bar_v82.  */
+/* { dg-final { scan-assembler-times "fmadd\ts\[0-9\]\+" 3 } } */
+
+/* One FMA operation in 16-bit precision, from foo_v82.  */
+/* { dg-final { scan-assembler-times "fmadd\th\[0-9\]\+" 1 } } */
+
+/* Test that in -fpermitted-flt-eval-methods=c11 we don't set the
+   __FLT_EVAL_METHOD__ to anything other than 0.  */
+/* { dg-final { scan-assembler-times "str\twzr" 4 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/_Float16_3.c b/gcc/testsuite/gcc.target/aarch64/_Float16_3.c
new file mode 100644
index 0000000..2d20250
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/_Float16_3.c
@@ -0,0 +1,46 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=armv8.2-a+nofp16 -std=c11 -ffp-contract=fast" } */
+
+#pragma GCC target ("arch=armv8.2-a+nofp16")
+
+_Float16
+foo_v8 (_Float16 x, _Float16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+__fp16
+bar_v8 (__fp16 x, __fp16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+#pragma GCC target ("arch=armv8.2-a+fp16")
+
+_Float16
+foo_v82 (_Float16 x, _Float16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+__fp16
+bar_v82 (__fp16 x, __fp16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+/* Test that we merge to FMA operations.  This indicates that we are not
+   making extraneous conversions between modes.  */
+
+/* Three FMA operations in 32-bit precision, from foo_v8, bar_v8, bar_v82.  */
+/* { dg-final { scan-assembler-times "fmadd\ts\[0-9\]\+" 3 } } */
+
+/* One FMA operation in 16-bit precision, from foo_v82.  */
+/* { dg-final { scan-assembler-times "fmadd\th\[0-9\]\+" 1 } } */
+
+/* Test that in C11 mode, we don't reset __FLT_EVAL_METHOD__.  */
+/* { dg-final { scan-assembler-times "str\twzr" 4 } } */

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

* Re: [Patch 3/11] Implement TARGET_C_EXCESS_PRECISION for s390
  2016-10-14 16:53               ` James Greenhalgh
@ 2016-10-17 19:30                 ` Andreas Krebbel1
  2016-10-19 15:20                   ` Andreas Krebbel
  0 siblings, 1 reply; 95+ messages in thread
From: Andreas Krebbel1 @ 2016-10-17 19:30 UTC (permalink / raw)
  To: James Greenhalgh, Ulrich Weigand; +Cc: gcc-patches, joseph, law, nd

> Here is a patch implementing what I think has been discussed in this 
thread.
> 
> OK?

Looks good to me.

Uli, do you agree with that change for S/390 or would you rather see us 
fixing the float_t type definition in Glibc?

-Andreas-


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

* Re: [Patch 3/11] Implement TARGET_C_EXCESS_PRECISION for s390
  2016-10-17 19:30                 ` Andreas Krebbel1
@ 2016-10-19 15:20                   ` Andreas Krebbel
  0 siblings, 0 replies; 95+ messages in thread
From: Andreas Krebbel @ 2016-10-19 15:20 UTC (permalink / raw)
  To: James Greenhalgh, Ulrich Weigand
  Cc: gcc-patches, joseph, law, nd, gcc-patches

On 10/17/2016 09:29 PM, Andreas Krebbel1 wrote:
>> Here is a patch implementing what I think has been discussed in this 
> thread.
>>
>> OK?
> 
> Looks good to me.
> 
> Uli, do you agree with that change for S/390 or would you rather see us 
> fixing the float_t type definition in Glibc?

I had a discussion with Ulrich. He agrees with the current patch. So the patch is ok to apply.
Thanks for taking care of this (and being patient with me).

Also I will try to push forward changing float_t to float. Your patch does not make things worse and
should not make it harder to do the float_t switch in the future. For the float_t switch I will have
to check with the distro maintainers.

-Andreas-

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

* [Patch 3/4] Half to double precision conversions
  2016-10-24 13:45 ` [Patch 0/4] [ARM] Enable _Float16 on ARM James Greenhalgh
  2016-10-24 13:45   ` [Patch ARM 4/4] Enable _Float16 James Greenhalgh
@ 2016-10-24 13:45   ` James Greenhalgh
  2016-10-24 13:45   ` [Patch 2/4] [libgcc] Add double to half conversions James Greenhalgh
  2016-10-24 13:45   ` [Patch 1/4] [libgcc, ARM] Generalise float-to-half conversion function James Greenhalgh
  3 siblings, 0 replies; 95+ messages in thread
From: James Greenhalgh @ 2016-10-24 13:45 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, richard.earnshaw, ramana.radhakrishnan, kyrtka01, joseph

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


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

---
2016-10-24  James Greenhalgh  <james.greenhalgh@arm.com>

	* 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.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0003-Patch-3-4-Half-to-double-precision-conversions.patch --]
[-- Type: text/x-patch;  name=0003-Patch-3-4-Half-to-double-precision-conversions.patch, Size: 7390 bytes --]

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index c1a5627..1822cd6 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -250,7 +250,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);
@@ -658,9 +657,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
 
@@ -2560,6 +2556,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);
@@ -5309,6 +5310,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;
@@ -23737,23 +23740,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 dbb8e13..a5267c4 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -194,6 +194,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 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);
+      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.
@@ -5684,19 +5699,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 45ce5c9..cb23c7f 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")))]

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

* [Patch 0/4] [ARM] Enable _Float16 on ARM
  2016-09-30 16:58 [Patch 0/11] Add support for _Float16 to AArch64 James Greenhalgh
                   ` (9 preceding siblings ...)
  2016-09-30 17:05 ` [Patch libgcc 9/11] Update soft-fp from glibc James Greenhalgh
@ 2016-10-24 13:45 ` James Greenhalgh
  2016-10-24 13:45   ` [Patch ARM 4/4] Enable _Float16 James Greenhalgh
                     ` (3 more replies)
  2016-11-11 15:38 ` [Patch v4 0/17] Add support for _Float16 to AArch64 and ARM James Greenhalgh
  11 siblings, 4 replies; 95+ messages in thread
From: James Greenhalgh @ 2016-10-24 13:45 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, richard.earnshaw, ramana.radhakrishnan, kyrtka01, joseph

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

Hi,

This patch set builds on the AArch64 support for _Float16 that will be added
once the patch set starting at
https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02383.html is accepted.

Unlike the AArch64 support, we've not got too much to do, outside of setting
up a single step conversions between HFmode and DFmode.

Patches 1-3 (co-authored with Matthew Wahab) add this support, by refactoring
__gnu_f2h_internal, then expanding it to support 16-bit to 64-bit conversions,
then removing TARGET_CONVERT_TO_TYPE and wiring up truncdfhf2 and
extendhfdf2 for ARM.

Patch 4 adds the requisite wiring to enable the _Float16 type on ARM.

I've bootstrapped the patch set on ARMv8-A hardware, and cross-tested it
with appropriate multilibs.

OK once the AArch64 support is in?

Thanks,
James



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

* [Patch 2/4] [libgcc] Add double to half conversions.
  2016-10-24 13:45 ` [Patch 0/4] [ARM] Enable _Float16 on ARM James Greenhalgh
  2016-10-24 13:45   ` [Patch ARM 4/4] Enable _Float16 James Greenhalgh
  2016-10-24 13:45   ` [Patch 3/4] Half to double precision conversions James Greenhalgh
@ 2016-10-24 13:45   ` James Greenhalgh
  2016-10-24 22:24     ` Joseph Myers
  2016-10-24 13:45   ` [Patch 1/4] [libgcc, ARM] Generalise float-to-half conversion function James Greenhalgh
  3 siblings, 1 reply; 95+ messages in thread
From: James Greenhalgh @ 2016-10-24 13:45 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, richard.earnshaw, ramana.radhakrishnan, kyrtka01, joseph

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


Hi,

Conversions from double precision floats to the ARM __fp16 are required
to round only once.

This patch adds a functions named __gnu_d2h_ieee and
__gnu_d2h_alternative for double to __fp16 conversions in IEEE and ARM
alternative format. The make use of the existing __gnu_float2h_internal
conversion function which rounds once only.

Bootstrapped on an ARMv8-A machine with no issues, and cross-tested with
a range of multilibs.

OK?

Thanks,
James
---

libgcc/

2016-10-24  James Greenhalgh  <james.greenhalgh@arm.com>
	    Matthew Wahab  <matthew.wahab@arm.com>

	* config/arm/fp16.c (binary64): New.
	(__gnu_d2h_internal): New.
	(__gnu_d2h_ieee): New.
	(__gnu_d2h_alternative): New.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0002-Patch-2-4-libgcc-Add-double-to-half-conversions.patch --]
[-- Type: text/x-patch;  name=0002-Patch-2-4-libgcc-Add-double-to-half-conversions.patch, Size: 1209 bytes --]

diff --git a/libgcc/config/arm/fp16.c b/libgcc/config/arm/fp16.c
index 8d02a24..48c4f9c 100644
--- a/libgcc/config/arm/fp16.c
+++ b/libgcc/config/arm/fp16.c
@@ -43,6 +43,15 @@ binary32 =
   23    /* significand.  */
 };
 
+static const struct format
+binary64 =
+{
+  64,    /* size.  */
+  1023,  /* bias.  */
+  11,    /* exponent.  */
+  52     /* significand.  */
+};
+
 static inline unsigned short
 __gnu_float2h_internal (const struct format* fmt,
 			unsigned long long a, int ieee)
@@ -136,6 +145,12 @@ __gnu_f2h_internal (unsigned int a, int ieee)
   return __gnu_float2h_internal (&binary32, (unsigned long long) a, ieee);
 }
 
+static inline unsigned short
+__gnu_d2h_internal (unsigned long long a, int ieee)
+{
+  return __gnu_float2h_internal (&binary64, a, ieee);
+}
+
 unsigned int
 __gnu_h2f_internal(unsigned short a, int ieee)
 {
@@ -184,3 +199,15 @@ __gnu_h2f_alternative(unsigned short a)
 {
   return __gnu_h2f_internal(a, 0);
 }
+
+unsigned short
+__gnu_d2h_ieee (unsigned long long a)
+{
+  return __gnu_d2h_internal (a, 1);
+}
+
+unsigned short
+__gnu_d2h_alternative (unsigned long long x)
+{
+  return __gnu_d2h_internal (x, 0);
+}

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

* [Patch 1/4] [libgcc, ARM] Generalise float-to-half conversion function.
  2016-10-24 13:45 ` [Patch 0/4] [ARM] Enable _Float16 on ARM James Greenhalgh
                     ` (2 preceding siblings ...)
  2016-10-24 13:45   ` [Patch 2/4] [libgcc] Add double to half conversions James Greenhalgh
@ 2016-10-24 13:45   ` James Greenhalgh
  2016-11-08 11:58     ` James Greenhalgh
  3 siblings, 1 reply; 95+ messages in thread
From: James Greenhalgh @ 2016-10-24 13:45 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, richard.earnshaw, ramana.radhakrishnan, kyrtka01, joseph

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


Hi,

I'm adapting this patch from work started by Matthew Wahab.

Conversions from double precision floats to the ARM __fp16 are required
to round only once. A conversion function for double to __fp16 to
support this on soft-fp targets. This and the following patch add this
conversion function by reusing the exising float to __fp16 function
config/arm/fp16.c:__gnu_f2h_internal.

This patch generalizes __gnu_f2h_internal by adding a specification of
the source format and reworking the code to make use of it. Initially,
only the binary32 format is supported.

Bootstrapped on an ARMv8-A machine with no issues, and cross-tested with
a reasonable multi-lib range.

OK?

Thanks,
James

---
libgcc/

2016-10-24  James Greenhalgh  <james.greenhalgh@arm.com>
	    Matthew Wahab  <matthew.wahab@arm.com>

	* config/arm/fp16.c (struct format): New.
	(binary32): New.
	(__gnu_float2h_internal): New.  Body moved from
	__gnu_f2h_internal and generalize.
	(_gnu_f2h_internal): Move body to function __gnu_float2h_internal.
	Call it with binary32.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Patch-1-4-libgcc-ARM-Generalise-float-to-half-conver.patch --]
[-- Type: text/x-patch;  name=0001-Patch-1-4-libgcc-ARM-Generalise-float-to-half-conver.patch, Size: 3301 bytes --]

diff --git a/libgcc/config/arm/fp16.c b/libgcc/config/arm/fp16.c
index 39c863c..8d02a24 100644
--- a/libgcc/config/arm/fp16.c
+++ b/libgcc/config/arm/fp16.c
@@ -22,35 +22,69 @@
    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
+struct format
+{
+  /* Number of bits.  */
+  unsigned long long size;
+  /* Exponent bias.  */
+  unsigned long long bias;
+  /* Exponent width in bits.  */
+  unsigned long long exponent;
+  /* Significand precision in explicitly stored bits.  */
+  unsigned long long significand;
+};
+
+static const struct format
+binary32 =
+{
+  32,   /* size.  */
+  127,  /* bias.  */
+  8,    /* exponent.  */
+  23    /* significand.  */
+};
+
 static inline unsigned short
-__gnu_f2h_internal(unsigned int a, int ieee)
+__gnu_float2h_internal (const struct format* fmt,
+			unsigned long long a, int ieee)
 {
-  unsigned short sign = (a >> 16) & 0x8000;
-  int aexp = (a >> 23) & 0xff;
-  unsigned int mantissa = a & 0x007fffff;
-  unsigned int mask;
-  unsigned int increment;
+  unsigned long long point = 1ULL << fmt->significand;;
+  unsigned short sign = (a >> (fmt->size - 16)) & 0x8000;
+  int aexp;
+  unsigned long long mantissa;
+  unsigned long long mask;
+  unsigned long long increment;
+
+  /* Get the exponent and mantissa encodings.  */
+  mantissa = a & (point - 1);
+
+  mask = (1 << fmt->exponent) - 1;
+  aexp = (a >> fmt->significand) & mask;
 
-  if (aexp == 0xff)
+  /* Infinity, NaN and alternative format special case.  */
+  if (((unsigned int) aexp) == mask)
     {
       if (!ieee)
 	return sign;
       if (mantissa == 0)
 	return sign | 0x7c00;	/* Infinity.  */
       /* Remaining cases are NaNs.  Convert SNaN to QNaN.  */
-      return sign | 0x7e00 | (mantissa >> 13);
+      return sign | 0x7e00 | (mantissa >> (fmt->significand - 10));
     }
 
+  /* Zero.  */
   if (aexp == 0 && mantissa == 0)
     return sign;
 
-  aexp -= 127;
+  /* Construct the exponent and mantissa.  */
+  aexp -= fmt->bias;
+
+  /* Decimal point is immediately after the significand.  */
+  mantissa |= point;
 
-  /* Decimal point between bits 22 and 23.  */
-  mantissa |= 0x00800000;
   if (aexp < -14)
     {
-      mask = 0x00ffffff;
+      mask = point | (point - 1);
+      /* Minimum exponent for half-precision is 2^-24.  */
       if (aexp >= -25)
 	mask >>= 25 + aexp;
     }
@@ -64,8 +98,8 @@ __gnu_f2h_internal(unsigned int a, int ieee)
       if ((mantissa & mask) == increment)
 	increment = mantissa & (increment << 1);
       mantissa += increment;
-      if (mantissa >= 0x01000000)
-       	{
+      if (mantissa >= (point << 1))
+	{
 	  mantissa >>= 1;
 	  aexp++;
 	}
@@ -93,7 +127,13 @@ __gnu_f2h_internal(unsigned int a, int ieee)
 
   /* We leave the leading 1 in the mantissa, and subtract one
      from the exponent bias to compensate.  */
-  return sign | (((aexp + 14) << 10) + (mantissa >> 13));
+  return sign | (((aexp + 14) << 10) + (mantissa >> (fmt->significand - 10)));
+}
+
+static inline unsigned short
+__gnu_f2h_internal (unsigned int a, int ieee)
+{
+  return __gnu_float2h_internal (&binary32, (unsigned long long) a, ieee);
 }
 
 unsigned int

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

* [Patch ARM 4/4] Enable _Float16
  2016-10-24 13:45 ` [Patch 0/4] [ARM] Enable _Float16 on ARM James Greenhalgh
@ 2016-10-24 13:45   ` James Greenhalgh
  2016-10-24 22:29     ` Joseph Myers
  2016-10-24 13:45   ` [Patch 3/4] Half to double precision conversions James Greenhalgh
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 95+ messages in thread
From: James Greenhalgh @ 2016-10-24 13:45 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, richard.earnshaw, ramana.radhakrishnan, kyrtka01, joseph

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


Hi,

Finally, having added support for single-step DFmode to HFmode conversions,
this patch adds support for _Float16 to the ARM back-end.

That means making sure that only __fp16 promotes and adding similar hooks to
those used in the AArch64 port giving the excess precision rules, and
marking HFmode as supported in libgcc.

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

OK?

Thanks,
James

---
2016-10-24  James Greenhalgh  <james.greenhalgh@arm.com>

	* config/arm/arm-builtins.c (arm_simd_floatHF_type_node): Rename to...
	(arm_fp16_type_node): ...This, make visibile.
	(arm_simd_builtin_std_type): Rename arm_simd_floatHF_type_node to
	arm_fp16_type_node.
	(arm_init_simd_builtin_types): Likewise.
	(arm_init_fp16_builtins): Likewise.
	* config/arm/arm.c (arm_excess_precision): New.
	(arm_floatn_mode): Likewise.
	(TARGET_C_EXCESS_PRECISION): Likewise.
	(TARGET_FLOATN_MODE): Likewise.
	(arm_promoted_type): Only promote arm_fp16_type_node.
	* config/arm/arm.h (arm_fp16_type_node): Declare.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0004-Patch-ARM-4-4-Enable-_Float16.patch --]
[-- Type: text/x-patch; name=0004-Patch-ARM-4-4-Enable-_Float16.patch, Size: 7271 bytes --]

diff --git a/gcc/config/arm/arm-builtins.c b/gcc/config/arm/arm-builtins.c
index e73043d..5ed38d1 100644
--- a/gcc/config/arm/arm-builtins.c
+++ b/gcc/config/arm/arm-builtins.c
@@ -652,7 +652,8 @@ static struct arm_simd_type_info arm_simd_types [] = {
 };
 #undef ENTRY
 
-static tree arm_simd_floatHF_type_node = NULL_TREE;
+/* The user-visible __fp16 type.  */
+tree arm_fp16_type_node = NULL_TREE;
 static tree arm_simd_intOI_type_node = NULL_TREE;
 static tree arm_simd_intEI_type_node = NULL_TREE;
 static tree arm_simd_intCI_type_node = NULL_TREE;
@@ -739,7 +740,7 @@ arm_simd_builtin_std_type (enum machine_mode mode,
     case XImode:
       return arm_simd_intXI_type_node;
     case HFmode:
-      return arm_simd_floatHF_type_node;
+      return arm_fp16_type_node;
     case SFmode:
       return float_type_node;
     case DFmode:
@@ -840,8 +841,8 @@ arm_init_simd_builtin_types (void)
   /* Continue with standard types.  */
   /* The __builtin_simd{64,128}_float16 types are kept private unless
      we have a scalar __fp16 type.  */
-  arm_simd_types[Float16x4_t].eltype = arm_simd_floatHF_type_node;
-  arm_simd_types[Float16x8_t].eltype = arm_simd_floatHF_type_node;
+  arm_simd_types[Float16x4_t].eltype = arm_fp16_type_node;
+  arm_simd_types[Float16x8_t].eltype = arm_fp16_type_node;
   arm_simd_types[Float32x2_t].eltype = float_type_node;
   arm_simd_types[Float32x4_t].eltype = float_type_node;
 
@@ -1754,11 +1755,11 @@ arm_init_iwmmxt_builtins (void)
 static void
 arm_init_fp16_builtins (void)
 {
-  arm_simd_floatHF_type_node = make_node (REAL_TYPE);
-  TYPE_PRECISION (arm_simd_floatHF_type_node) = GET_MODE_PRECISION (HFmode);
-  layout_type (arm_simd_floatHF_type_node);
+  arm_fp16_type_node = make_node (REAL_TYPE);
+  TYPE_PRECISION (arm_fp16_type_node) = GET_MODE_PRECISION (HFmode);
+  layout_type (arm_fp16_type_node);
   if (arm_fp16_format)
-    (*lang_hooks.types.register_builtin_type) (arm_simd_floatHF_type_node,
+    (*lang_hooks.types.register_builtin_type) (arm_fp16_type_node,
 					       "__fp16");
 }
 
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 1822cd6..bfe6195 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -271,6 +271,7 @@ static bool arm_builtin_support_vector_misalignment (machine_mode mode,
 						     int misalignment,
 						     bool is_packed);
 static void arm_conditional_register_usage (void);
+static enum flt_eval_method arm_excess_precision (enum excess_precision_type);
 static reg_class_t arm_preferred_rename_class (reg_class_t rclass);
 static unsigned int arm_autovectorize_vector_sizes (void);
 static int arm_default_branch_cost (bool, bool);
@@ -303,6 +304,7 @@ static section *arm_function_section (tree, enum node_frequency, bool, bool);
 static bool arm_asm_elf_flags_numeric (unsigned int flags, unsigned int *num);
 static unsigned int arm_elf_section_type_flags (tree decl, const char *name,
 						int reloc);
+static machine_mode arm_floatn_mode (int, bool);
 \f
 /* Table of machine attributes.  */
 static const struct attribute_spec arm_attribute_table[] =
@@ -448,6 +450,9 @@ static const struct attribute_spec arm_attribute_table[] =
 #undef  TARGET_ASM_INTERNAL_LABEL
 #define TARGET_ASM_INTERNAL_LABEL arm_internal_label
 
+#undef TARGET_FLOATN_MODE
+#define TARGET_FLOATN_MODE arm_floatn_mode
+
 #undef  TARGET_FUNCTION_OK_FOR_SIBCALL
 #define TARGET_FUNCTION_OK_FOR_SIBCALL arm_function_ok_for_sibcall
 
@@ -735,6 +740,9 @@ static const struct attribute_spec arm_attribute_table[] =
 #undef TARGET_SECTION_TYPE_FLAGS
 #define TARGET_SECTION_TYPE_FLAGS arm_elf_section_type_flags
 
+#undef TARGET_C_EXCESS_PRECISION
+#define TARGET_C_EXCESS_PRECISION arm_excess_precision
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
 /* Obstack for minipool constant handling.  */
@@ -23735,7 +23743,7 @@ arm_debugger_arg_offset (int value, rtx addr)
 static tree
 arm_promoted_type (const_tree t)
 {
-  if (SCALAR_FLOAT_TYPE_P (t) && TYPE_PRECISION (t) == 16)
+  if (TREE_TYPE (t) && TYPE_MAIN_VARIANT (t) == arm_fp16_type_node)
     return float_type_node;
   return NULL_TREE;
 }
@@ -23757,6 +23765,61 @@ arm_scalar_mode_supported_p (machine_mode mode)
     return default_scalar_mode_supported_p (mode);
 }
 
+/* Set the value of FLT_EVAL_METHOD.
+   ISO/IEC TS 18661-3 defines two values that we'd like to make use of:
+
+    0: evaluate all operations and constants, whose semantic type has at
+       most the range and precision of type float, to the range and
+       precision of float; evaluate all other operations and constants to
+       the range and precision of the semantic type;
+
+    N, where _FloatN is a supported interchange floating type
+       evaluate all operations and constants, whose semantic type has at
+       most the range and precision of _FloatN type, to the range and
+       precision of the _FloatN type; evaluate all other operations and
+       constants to the range and precision of the semantic type;
+
+   If we have the ARMv8.2-A extensions then we support _Float16 in native
+   precision, so we should set this to 16.  Otherwise, we support the type,
+   but want to evaluate expressions in float precision, so set this to
+   0.  */
+
+static enum flt_eval_method
+arm_excess_precision (enum excess_precision_type type)
+{
+  switch (type)
+    {
+      case EXCESS_PRECISION_TYPE_FAST:
+      case EXCESS_PRECISION_TYPE_STANDARD:
+	/* We can calculate either in 16-bit range and precision or
+	   32-bit range and precision.  Make that decision based on whether
+	   we have native support for the ARMv8.2-A 16-bit floating-point
+	   instructions or not.  */
+	return (TARGET_VFP_FP16INST
+		? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16
+		: FLT_EVAL_METHOD_PROMOTE_TO_FLOAT);
+      case EXCESS_PRECISION_TYPE_IMPLICIT:
+	return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16;
+      default:
+	gcc_unreachable ();
+    }
+  return FLT_EVAL_METHOD_UNPREDICTABLE;
+}
+
+
+/* Implement TARGET_FLOATN_MODE.  Make very sure that we don't provide
+   _Float16 if we are using anything other than ieee format for 16-bit
+   floating point.  Otherwise, punt to the default implementation.  */
+static machine_mode
+arm_floatn_mode (int n, bool extended)
+{
+  if (!extended && n == 16)
+    return arm_fp16_format == ARM_FP16_FORMAT_IEEE ? HFmode : VOIDmode;
+
+  return default_floatn_mode (n, extended);
+}
+
+
 /* Set up OPERANDS for a register copy from SRC to DEST, taking care
    not to early-clobber SRC registers in the process.
 
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index a5267c4..f319c6d 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -82,6 +82,11 @@ extern int arm_ccfsm_state;
 extern GTY(()) rtx arm_target_insn;
 /* Callback to output language specific object attributes.  */
 extern void (*arm_lang_output_object_attributes_hook)(void);
+
+/* This type is the user-visible __fp16.  We need it in a few places in
+   the backend.  Defined in arm-builtins.c.  */
+extern tree arm_fp16_type_node;
+
 \f
 /* Just in case configure has failed to define anything.  */
 #ifndef TARGET_CPU_DEFAULT

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

* Re: [Patch 2/4] [libgcc] Add double to half conversions.
  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
  0 siblings, 1 reply; 95+ messages in thread
From: Joseph Myers @ 2016-10-24 22:24 UTC (permalink / raw)
  To: James Greenhalgh
  Cc: gcc-patches, nd, richard.earnshaw, ramana.radhakrishnan, kyrtka01

On Mon, 24 Oct 2016, James Greenhalgh wrote:

> Conversions from double precision floats to the ARM __fp16 are required
> to round only once.

I'd expect that when fixing this you need to update 
gcc.target/arm/fp16-rounding-ieee-1.c (and fp16-rounding-alt-1.c, I 
suppose) to expect rounding once.  But I don't see such a testsuite change 
anywhere in this patch series.

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [Patch ARM 4/4] Enable _Float16
  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
  0 siblings, 1 reply; 95+ messages in thread
From: Joseph Myers @ 2016-10-24 22:29 UTC (permalink / raw)
  To: James Greenhalgh
  Cc: gcc-patches, nd, richard.earnshaw, ramana.radhakrishnan, kyrtka01

On Mon, 24 Oct 2016, James Greenhalgh wrote:

> Hi,
> 
> Finally, having added support for single-step DFmode to HFmode conversions,
> this patch adds support for _Float16 to the ARM back-end.

Given the need for -mfp16-format=ieee (on some processors), you should be 
updating target-supports.exp:add_options_for_float16 to add that option in 
the ARM case, and make sure that the tests run in cases where the option 
is needed to enable support for this format.

> That means making sure that only __fp16 promotes and adding similar hooks to
> those used in the AArch64 port giving the excess precision rules, and
> marking HFmode as supported in libgcc.

Does "supported in libgcc" mean this patch completes fixing bug 63250?

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [Patch 6/11] Migrate excess precision logic to use TARGET_EXCESS_PRECISION
  2016-10-14 16:56     ` James Greenhalgh
@ 2016-10-28 21:10       ` Joseph Myers
  2016-11-02 17:38         ` James Greenhalgh
  0 siblings, 1 reply; 95+ messages in thread
From: Joseph Myers @ 2016-10-28 21:10 UTC (permalink / raw)
  To: James Greenhalgh; +Cc: gcc-patches, nd

On Fri, 14 Oct 2016, James Greenhalgh wrote:

> +/* If the join of the implicit precision in which the target will compute
> +   floating-point values and the standard precision in which the target will
> +   compute values is not equal to the standard precision, then the target
> +   is either unpredictable, or is a broken configuration in which it claims
> +   standards compliance, but doesn't honor that.
> +
> +   Effective predictability for __GCC_IEC_559 in flag_iso_mode, means that
> +   the implicit precision is not wider, or less predictable than the
> +   standard precision.
> +
> +   Return TRUE if we have been asked to compile with
> +   -fexcess-precision=standard, and following the rules above we are able
> +   to guarantee the standards mode.  */
> +
> +static bool
> +c_cpp_flt_eval_method_iec_559 (void)
> +{
> +  enum flt_eval_method implicit
> +    = targetm.c.excess_precision (EXCESS_PRECISION_TYPE_IMPLICIT);
> +  enum flt_eval_method standard
> +    = targetm.c.excess_precision (EXCESS_PRECISION_TYPE_STANDARD);
> +
> +  return (excess_precision_mode_join (implicit, standard) == standard
> +	  && flag_excess_precision_cmdline == EXCESS_PRECISION_STANDARD);
> +}
> +
>  /* Return the value for __GCC_IEC_559.  */
>  static int
>  cpp_iec_559_value (void)
> @@ -775,11 +801,12 @@ cpp_iec_559_value (void)
>       applies to unpredictable contraction.  For C++, and outside
>       strict conformance mode, do not consider these options to mean
>       lack of IEEE 754 support.  */
> +
>    if (flag_iso
>        && !c_dialect_cxx ()
> -      && TARGET_FLT_EVAL_METHOD != 0
> -      && flag_excess_precision_cmdline != EXCESS_PRECISION_STANDARD)
> +      && !c_cpp_flt_eval_method_iec_559 ())
>      ret = 0;

I'm not convinced by the logic you have here.  At least, it seems 
different from what we have at present, where -std=c11 
-fexcess-precision=fast is not considered unpredictable if the target 
doesn't have any implicit excess precision.

That is: I think the right question is whether the combination (front-end 
excess precision, implicit back-end excess precision) does the same thing 
as just front-end excess precision, regardless of the -fexcess-precision= 
option.

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [Patch 1/11] Add a new target hook for describing excess precision intentions
  2016-10-14 16:50   ` James Greenhalgh
@ 2016-10-28 21:12     ` Joseph Myers
  2016-11-02 17:36       ` James Greenhalgh
  0 siblings, 1 reply; 95+ messages in thread
From: Joseph Myers @ 2016-10-28 21:12 UTC (permalink / raw)
  To: James Greenhalgh; +Cc: gcc-patches, nd

On Fri, 14 Oct 2016, James Greenhalgh wrote:

> + value set for @code{-fexcess-precision=[standard|fast]}.",

I think the correct markup for the option here is:

@option{-fexcess-precision=@r{[}standard@r{|}fast@r{]}}

(that is, using @option not @code, and with the [ | ] not in a fixed-width 
font because they aren't part of the option name).

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [Patch 1/11] Add a new target hook for describing excess precision intentions
  2016-10-28 21:12     ` Joseph Myers
@ 2016-11-02 17:36       ` James Greenhalgh
  2016-11-09  2:34         ` Joseph Myers
  0 siblings, 1 reply; 95+ messages in thread
From: James Greenhalgh @ 2016-11-02 17:36 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, joseph

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


On Fri, Oct 28, 2016 at 09:12:11PM +0000, Joseph Myers wrote:
> On Fri, 14 Oct 2016, James Greenhalgh wrote:
>
> > + value set for @code{-fexcess-precision=[standard|fast]}.",
>
> I think the correct markup for the option here is:
>
> @option{-fexcess-precision=@r{[}standard@r{|}fast@r{]}}
>
> (that is, using @option not @code, and with the [ | ] not in a fixed-width
> font because they aren't part of the option name).
>

Thanks, I've updated that line in this revision of the patch following
your suggestion.

James

---
gcc/

2016-11-02  James Greenhalgh  <james.greenhalgh@arm.com>

	* target.def (excess_precision): New hook.
	* target.h (flt_eval_method): New.
	(excess_precision_type): Likewise.
	* targhooks.c (default_excess_precision): New.
	* targhooks.h (default_excess_precision): New.
	* doc/tm.texi.in (TARGET_C_EXCESS_PRECISION): New.
	* doc/tm.texi: Regenerate.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Re-Patch-1-11-Add-a-new-target-hook-for-describing-e.patch --]
[-- Type: text/x-patch; name="0001-Re-Patch-1-11-Add-a-new-target-hook-for-describing-e.patch", Size: 4738 bytes --]

diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index 869f858..09f8213 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -331,6 +331,24 @@ enum symbol_visibility
   VISIBILITY_INTERNAL
 };
 
+/* enums used by the targetm.excess_precision hook.  */
+
+enum flt_eval_method
+{
+  FLT_EVAL_METHOD_UNPREDICTABLE = -1,
+  FLT_EVAL_METHOD_PROMOTE_TO_FLOAT = 0,
+  FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE = 1,
+  FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE = 2,
+  FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16 = 16
+};
+
+enum excess_precision_type
+{
+  EXCESS_PRECISION_TYPE_IMPLICIT,
+  EXCESS_PRECISION_TYPE_STANDARD,
+  EXCESS_PRECISION_TYPE_FAST
+};
+
 /* Support for user-provided GGC and PCH markers.  The first parameter
    is a pointer to a pointer, the second a cookie.  */
 typedef void (*gt_pointer_operator) (void *, void *);
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 0aed3d4..d1d1e76 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -947,6 +947,10 @@ sign-extend the result to 64 bits.  On such machines, set
 Do not define this macro if it would never modify @var{m}.
 @end defmac
 
+@deftypefn {Target Hook} {enum flt_eval_method} TARGET_C_EXCESS_PRECISION (enum excess_precision_type @var{type})
+Return a value, with the same meaning as @code{FLT_EVAL_METHOD} C that describes which excess precision should be applied.  @var{type} is either @code{EXCESS_PRECISION_TYPE_IMPLICIT}, @code{EXCESS_PRECISION_TYPE_FAST}, or @code{EXCESS_PRECISION_TYPE_STANDARD}.  For @code{EXCESS_PRECISION_TYPE_IMPLICIT}, the target should return which precision and range operations will be implictly evaluated in regardless of the excess precision explicitly added.  For @code{EXCESS_PRECISION_TYPE_STANDARD} and @code{EXCESS_PRECISION_TYPE_FAST}, the target should return the explicit excess precision that should be added depending on the value set for @option{-fexcess-precision=@r{[}standard@r{|}fast@r{]}}.
+@end deftypefn
+
 @deftypefn {Target Hook} machine_mode TARGET_PROMOTE_FUNCTION_MODE (const_tree @var{type}, machine_mode @var{mode}, int *@var{punsignedp}, const_tree @var{funtype}, int @var{for_return})
 Like @code{PROMOTE_MODE}, but it is applied to outgoing function arguments or
 function return values.  The target hook should return the new mode
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 9e5b456..12f6bc0 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -921,6 +921,8 @@ sign-extend the result to 64 bits.  On such machines, set
 Do not define this macro if it would never modify @var{m}.
 @end defmac
 
+@hook TARGET_C_EXCESS_PRECISION
+
 @hook TARGET_PROMOTE_FUNCTION_MODE
 
 @defmac PARM_BOUNDARY
diff --git a/gcc/target.def b/gcc/target.def
index c3c87b0..9fc31b3 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -5430,6 +5430,23 @@ DEFHOOK_UNDOC
  machine_mode, (char c),
  default_mode_for_suffix)
 
+DEFHOOK
+(excess_precision,
+ "Return a value, with the same meaning as @code{FLT_EVAL_METHOD} C that\
+ describes which excess precision should be applied.  @var{type} is\
+ either @code{EXCESS_PRECISION_TYPE_IMPLICIT},\
+ @code{EXCESS_PRECISION_TYPE_FAST}, or\
+ @code{EXCESS_PRECISION_TYPE_STANDARD}.  For\
+ @code{EXCESS_PRECISION_TYPE_IMPLICIT}, the target should return which\
+ precision and range operations will be implictly evaluated in regardless\
+ of the excess precision explicitly added.  For\
+ @code{EXCESS_PRECISION_TYPE_STANDARD} and\
+ @code{EXCESS_PRECISION_TYPE_FAST}, the target should return the\
+ explicit excess precision that should be added depending on the\
+ value set for @option{-fexcess-precision=@r{[}standard@r{|}fast@r{]}}.",
+ enum flt_eval_method, (enum excess_precision_type type),
+ default_excess_precision)
+
 HOOK_VECTOR_END (c)
 
 /* Functions specific to the C++ frontend.  */
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index 866747a..73e1c25 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -2135,4 +2135,12 @@ default_min_arithmetic_precision (void)
   return WORD_REGISTER_OPERATIONS ? BITS_PER_WORD : BITS_PER_UNIT;
 }
 
+/* Default implementation of TARGET_C_EXCESS_PRECISION.  */
+
+enum flt_eval_method
+default_excess_precision (enum excess_precision_type ATTRIBUTE_UNUSED)
+{
+  return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT;
+}
+
 #include "gt-targhooks.h"
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index 94f5e31..e00da60 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -263,4 +263,7 @@ extern bool default_optab_supported_p (int, machine_mode, machine_mode,
 extern unsigned int default_max_noce_ifcvt_seq_cost (edge);
 extern unsigned int default_min_arithmetic_precision (void);
 
+extern enum flt_eval_method
+default_excess_precision (enum excess_precision_type ATTRIBUTE_UNUSED);
+
 #endif /* GCC_TARGHOOKS_H */

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

* Re: [Patch 6/11] Migrate excess precision logic to use TARGET_EXCESS_PRECISION
  2016-10-28 21:10       ` Joseph Myers
@ 2016-11-02 17:38         ` James Greenhalgh
  2016-11-09  2:47           ` Joseph Myers
  0 siblings, 1 reply; 95+ messages in thread
From: James Greenhalgh @ 2016-11-02 17:38 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, joseph

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


On Fri, Oct 28, 2016 at 09:09:55PM +0000, Joseph Myers wrote:
> On Fri, 14 Oct 2016, James Greenhalgh wrote:
>
> > +/* If the join of the implicit precision in which the target will compute
> > +   floating-point values and the standard precision in which the target will
> > +   compute values is not equal to the standard precision, then the target
> > +   is either unpredictable, or is a broken configuration in which it claims
> > +   standards compliance, but doesn't honor that.
> > +
> > +   Effective predictability for __GCC_IEC_559 in flag_iso_mode, means that
> > +   the implicit precision is not wider, or less predictable than the
> > +   standard precision.
> > +
> > +   Return TRUE if we have been asked to compile with
> > +   -fexcess-precision=standard, and following the rules above we are able
> > +   to guarantee the standards mode.  */
> > +
>
> I'm not convinced by the logic you have here.  At least, it seems
> different from what we have at present, where -std=c11
> -fexcess-precision=fast is not considered unpredictable if the target
> doesn't have any implicit excess precision.
>
> That is: I think the right question is whether the combination (front-end
> excess precision, implicit back-end excess precision) does the same thing
> as just front-end excess precision, regardless of the -fexcess-precision=
> option.

OK, I've reworked the patch along those lines. I noticed that the original
logic looked for

      && TARGET_FLT_EVAL_METHOD != 0

And I no longer make that check. Is that something I need to reinstate?
I didn't find any reference to excess precision in Annex F, so I'd guess
not?

Thanks,
James

---
gcc/

2016-11-02  James Greenhalgh  <james.greenhalgh@arm.com>

	* toplev.c (init_excess_precision): Delete most logic.
	* tree.c (excess_precision_type): Rewrite to use
	TARGET_EXCESS_PRECISION.
	* doc/invoke.texi (-fexcess-precision): Document behaviour in a
	more generic fashion.
	* ginclude/float.h: Wrap definition of FLT_EVAL_METHOD in
	__STDC_WANT_IEC_60559_TYPES_EXT__.

gcc/c-family/

2016-11-02  James Greenhalgh  <james.greenhalgh@arm.com>

	* c-common.c (excess_precision_mode_join): New.
	(c_ts18661_flt_eval_method): New.
	(c_c11_flt_eval_method): Likewise.
	(c_flt_eval_method): Likewise.
	* c-common.h (excess_precision_mode_join): New.
	(c_flt_eval_method): Likewise.
	* c-cppbuiltin.c (c_cpp_flt_eval_method_iec_559): New.
	(cpp_iec_559_value): Call it.
	(c_cpp_builtins): Modify logic for __LIBGCC_*_EXCESS_PRECISION__,
	call c_flt_eval_method to set __FLT_EVAL_METHOD__ and
	__FLT_EVAL_METHOD_TS_18661_3__.

gcc/testsuite/

2016-11-02  James Greenhalgh  <james.greenhalgh@arm.com>

	* gcc.dg/fpermitted-flt-eval-methods_3.c: New.
	* gcc.dg/fpermitted-flt-eval-methods_4.c: Likewise.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Re-Patch-6-11-Migrate-excess-precision-logic-to-use-.patch --]
[-- Type: text/x-patch; name="0001-Re-Patch-6-11-Migrate-excess-precision-logic-to-use-.patch", Size: 23147 bytes --]

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 307862b..9f0b4a6 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -7944,4 +7944,86 @@ cb_get_suggestion (cpp_reader *, const char *goal,
   return bm.get_best_meaningful_candidate ();
 }
 
+/* Return the latice point which is the wider of the two FLT_EVAL_METHOD
+   modes X, Y.  This isn't just  >, as the FLT_EVAL_METHOD values added
+   by C TS 18661-3 for interchange  types that are computed in their
+   native precision are larger than the C11 values for evaluating in the
+   precision of float/double/long double.  If either mode is
+   FLT_EVAL_METHOD_UNPREDICTABLE, return that.  */
+
+enum flt_eval_method
+excess_precision_mode_join (enum flt_eval_method x,
+			    enum flt_eval_method y)
+{
+  if (x == FLT_EVAL_METHOD_UNPREDICTABLE
+      || y == FLT_EVAL_METHOD_UNPREDICTABLE)
+    return FLT_EVAL_METHOD_UNPREDICTABLE;
+
+  /* GCC only supports one interchange type right now, _Float16.  If
+     we're evaluating _Float16 in 16-bit precision, then flt_eval_method
+     will be FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16.  */
+  if (x == FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16)
+    return y;
+  if (y == FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16)
+    return x;
+
+  /* Other values for flt_eval_method are directly comparable, and we want
+     the maximum.  */
+  return MAX (x, y);
+}
+
+/* Return the value that should be set for FLT_EVAL_METHOD in the
+   context of ISO/IEC TS 18861-3.
+
+   This relates to the effective excess precision seen by the user,
+   which is the join point of the precision the target requests for
+   -fexcess-precision={standard,fast} and the implicit excess precision
+   the target uses.  */
+
+static enum flt_eval_method
+c_ts18661_flt_eval_method (void)
+{
+  enum flt_eval_method implicit
+    = targetm.c.excess_precision (EXCESS_PRECISION_TYPE_IMPLICIT);
+
+  enum excess_precision_type flag_type
+    = (flag_excess_precision_cmdline == EXCESS_PRECISION_STANDARD
+       ? EXCESS_PRECISION_TYPE_STANDARD
+       : EXCESS_PRECISION_TYPE_FAST);
+
+  enum flt_eval_method requested
+    = targetm.c.excess_precision (flag_type);
+
+  return excess_precision_mode_join (implicit, requested);
+}
+
+/* As c_cpp_ts18661_flt_eval_method, but clamps the expected values to
+   those that were permitted by C11.  That is to say, eliminates
+   FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16.  */
+
+static enum flt_eval_method
+c_c11_flt_eval_method (void)
+{
+  return excess_precision_mode_join (c_ts18661_flt_eval_method (),
+				     FLT_EVAL_METHOD_PROMOTE_TO_FLOAT);
+}
+
+/* Return the value that should be set for FLT_EVAL_METHOD.
+   MAYBE_C11_ONLY_P is TRUE if we should check
+   FLAG_PERMITTED_EVAL_METHODS as to whether we should limit the possible
+   values we can return to those from C99/C11, and FALSE otherwise.
+   See the comments on c_ts18661_flt_eval_method for what value we choose
+   to set here.  */
+
+int
+c_flt_eval_method (bool maybe_c11_only_p)
+{
+  if (maybe_c11_only_p
+      && flag_permitted_flt_eval_methods
+	  == PERMITTED_FLT_EVAL_METHODS_C11)
+    return c_c11_flt_eval_method ();
+  else
+    return c_ts18661_flt_eval_method ();
+}
+
 #include "gt-c-family-c-common.h"
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 547bab2..507967d 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1314,6 +1314,8 @@ c_tree_chain_next (tree t)
 #define TM_STMT_ATTR_ATOMIC	4
 #define TM_STMT_ATTR_RELAXED	8
 
+extern int parse_tm_stmt_attr (tree, int);
+
 /* Mask used by tm_attr_to_mask and tm_mask_to_attr.  Note that these
    are ordered specifically such that more restrictive attributes are
    at lower bit positions.  This fact is known by the C++ tm attribute
@@ -1325,6 +1327,10 @@ c_tree_chain_next (tree t)
 #define TM_ATTR_IRREVOCABLE		8
 #define TM_ATTR_MAY_CANCEL_OUTER	16
 
+extern int tm_attr_to_mask (tree);
+extern tree tm_mask_to_attr (int);
+extern tree find_tm_attribute (tree);
+
 /* A suffix-identifier value doublet that represents user-defined literals
    for C++-0x.  */
 enum overflow_type {
@@ -1539,6 +1545,11 @@ extern int tm_attr_to_mask (tree);
 extern tree tm_mask_to_attr (int);
 extern tree find_tm_attribute (tree);
 
+extern enum flt_eval_method
+excess_precision_mode_join (enum flt_eval_method, enum flt_eval_method);
+
+extern int c_flt_eval_method (bool ts18661_p);
+
 #if CHECKING_P
 namespace selftest {
   extern void c_format_c_tests (void);
diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
index 7d689a9..cbe7284 100644
--- a/gcc/c-family/c-cppbuiltin.c
+++ b/gcc/c-family/c-cppbuiltin.c
@@ -728,6 +728,32 @@ cpp_atomic_builtins (cpp_reader *pfile)
 			(have_swap[psize]? 2 : 1));
 }
 
+/* Return TRUE if the implicit excess precision in which the back-end will
+   compute floating-point calculations is not more than the explicit
+   excess precision that the front-end will apply under
+   -fexcess-precision=[standard|fast].
+
+   More intuitively, return TRUE if the excess precision proposed by the
+   front-end is the excess precision that will actually be used.
+ */
+
+static bool
+c_cpp_flt_eval_method_iec_559 (void)
+{
+  enum excess_precision_type front_end_ept
+    = (flag_excess_precision_cmdline == EXCESS_PRECISION_STANDARD
+       ? EXCESS_PRECISION_TYPE_STANDARD
+       : EXCESS_PRECISION_TYPE_FAST);
+
+  enum flt_eval_method back_end
+    = targetm.c.excess_precision (EXCESS_PRECISION_TYPE_IMPLICIT);
+
+  enum flt_eval_method front_end
+    = targetm.c.excess_precision (front_end_ept);
+
+  return excess_precision_mode_join (front_end, back_end) == front_end;
+}
+
 /* Return the value for __GCC_IEC_559.  */
 static int
 cpp_iec_559_value (void)
@@ -770,16 +796,17 @@ cpp_iec_559_value (void)
       || !dfmt->has_signed_zero)
     ret = 0;
 
-  /* In strict C standards conformance mode, consider unpredictable
-     excess precision to mean lack of IEEE 754 support.  The same
-     applies to unpredictable contraction.  For C++, and outside
-     strict conformance mode, do not consider these options to mean
-     lack of IEEE 754 support.  */
+  /* In strict C standards conformance mode, consider a back-end providing
+     more implicit excess precision than the explicit excess precision
+     the front-end options would require to mean a lack of IEEE 754
+     support.  For C++, and outside strict conformance mode, do not consider
+     this to mean a lack of IEEE 754 support.  */
+
   if (flag_iso
       && !c_dialect_cxx ()
-      && TARGET_FLT_EVAL_METHOD != 0
-      && flag_excess_precision_cmdline != EXCESS_PRECISION_STANDARD)
+      && !c_cpp_flt_eval_method_iec_559 ())
     ret = 0;
+
   if (flag_iso
       && !c_dialect_cxx ()
       && flag_fp_contract_mode == FP_CONTRACT_FAST)
@@ -1039,9 +1066,22 @@ c_cpp_builtins (cpp_reader *pfile)
   builtin_define_with_int_value ("__GCC_IEC_559_COMPLEX",
 				 cpp_iec_559_complex_value ());
 
-  /* float.h needs to know this.  */
+  /* float.h needs these to correctly set FLT_EVAL_METHOD
+
+     We define two values:
+
+     __FLT_EVAL_METHOD__
+       Which, depending on the value given for
+       -fpermitted-flt-eval-methods, may be limited to only those values
+       for FLT_EVAL_METHOD defined in C99/C11.
+
+     __FLT_EVAL_METHOD_TS_18661_3__
+       Which always permits the values for FLT_EVAL_METHOD defined in
+       ISO/IEC TS 18661-3.  */
   builtin_define_with_int_value ("__FLT_EVAL_METHOD__",
-				 TARGET_FLT_EVAL_METHOD);
+				 c_flt_eval_method (true));
+  builtin_define_with_int_value ("__FLT_EVAL_METHOD_TS_18661_3__",
+				 c_flt_eval_method (false));
 
   /* And decfloat.h needs this.  */
   builtin_define_with_int_value ("__DEC_EVAL_METHOD__",
@@ -1182,25 +1222,38 @@ c_cpp_builtins (cpp_reader *pfile)
 	      gcc_assert (found_suffix);
 	    }
 	  builtin_define_with_value (macro_name, suffix, 0);
+
+	  /* The way __LIBGCC_*_EXCESS_PRECISION__ is used is about
+	     eliminating excess precision from results assigned to
+	     variables - meaning it should be about the implicit excess
+	     precision only.  */
 	  bool excess_precision = false;
-	  if (TARGET_FLT_EVAL_METHOD != 0
-	      && mode != TYPE_MODE (long_double_type_node)
-	      && (mode == TYPE_MODE (float_type_node)
-		  || mode == TYPE_MODE (double_type_node)))
-	    switch (TARGET_FLT_EVAL_METHOD)
-	      {
-	      case -1:
-	      case 2:
-		excess_precision = true;
-		break;
-
-	      case 1:
-		excess_precision = mode == TYPE_MODE (float_type_node);
-		break;
-
-	      default:
-		gcc_unreachable ();
-	      }
+	  machine_mode float16_type_mode = (float16_type_node
+					    ? TYPE_MODE (float16_type_node)
+					    : VOIDmode);
+	  switch (targetm.c.excess_precision
+		    (EXCESS_PRECISION_TYPE_IMPLICIT))
+	    {
+	    case FLT_EVAL_METHOD_UNPREDICTABLE:
+	    case FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE:
+	      excess_precision = (mode == float16_type_mode
+				  || mode == TYPE_MODE (float_type_node)
+				  || mode == TYPE_MODE (double_type_node));
+	      break;
+
+	    case FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE:
+	      excess_precision = (mode == float16_type_mode
+				  || mode == TYPE_MODE (float_type_node));
+	      break;
+	    case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT:
+	      excess_precision = mode == float16_type_mode;
+	      break;
+	    case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16:
+	      excess_precision = false;
+	      break;
+	    default:
+	      gcc_unreachable ();
+	    }
 	  macro_name = (char *) alloca (strlen (name)
 					+ sizeof ("__LIBGCC__EXCESS_"
 						  "PRECISION__"));
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index cbfa479..4461865 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -8942,15 +8942,14 @@ them to store all pertinent intermediate computations into variables.
 @item -fexcess-precision=@var{style}
 @opindex fexcess-precision
 This option allows further control over excess precision on machines
-where floating-point registers have more precision than the IEEE
-@code{float} and @code{double} types and the processor does not
-support operations rounding to those types.  By default,
-@option{-fexcess-precision=fast} is in effect; this means that
-operations are carried out in the precision of the registers and that
-it is unpredictable when rounding to the types specified in the source
-code takes place.  When compiling C, if
-@option{-fexcess-precision=standard} is specified then excess
-precision follows the rules specified in ISO C99; in particular,
+where floating-point operations occur in a format with more precision or
+range than the IEEE standard and interchange floating-point types.  By
+default, @option{-fexcess-precision=fast} is in effect; this means that
+operations may be carried out in a wider precision than the types specified
+in the source if that would result in faster code, and it is unpredictable
+when rounding to the types specified in the source code takes place.
+When compiling C, if @option{-fexcess-precision=standard} is specified then
+excess precision follows the rules specified in ISO C99; in particular,
 both casts and assignments cause values to be rounded to their
 semantic types (whereas @option{-ffloat-store} only affects
 assignments).  This option is enabled by default for C if a strict
diff --git a/gcc/ginclude/float.h b/gcc/ginclude/float.h
index 421f735..3df2889 100644
--- a/gcc/ginclude/float.h
+++ b/gcc/ginclude/float.h
@@ -129,21 +129,73 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
 #if (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) \
      || (defined (__cplusplus) && __cplusplus >= 201103L)
-/* The floating-point expression evaluation method.
-        -1  indeterminate
-         0  evaluate all operations and constants just to the range and
-            precision of the type
-         1  evaluate operations and constants of type float and double
-            to the range and precision of the double type, evaluate
-            long double operations and constants to the range and
-            precision of the long double type
-         2  evaluate all operations and constants to the range and
-            precision of the long double type
+/* The floating-point expression evaluation method.  The precise
+   definitions of these values are generalised to include support for
+   the interchange and extended types defined in ISO/IEC TS 18661-3.
+   Prior to this (for C99/C11) the definitions were:
+
+	-1  indeterminate
+	 0  evaluate all operations and constants just to the range and
+	    precision of the type
+	 1  evaluate operations and constants of type float and double
+	    to the range and precision of the double type, evaluate
+	    long double operations and constants to the range and
+	    precision of the long double type
+	 2  evaluate all operations and constants to the range and
+	    precision of the long double type
+
+   The TS 18661-3 definitions are:
+
+	-1  indeterminate
+	 0  evaluate all operations and constants, whose semantic type has
+	    at most the range and precision of float, to the range and
+	    precision of float; evaluate all other operations and constants
+	    to the range and precision of the semantic type.
+	 1  evaluate all operations and constants, whose semantic type has
+	    at most the range and precision of double, to the range and
+	    precision of double; evaluate all other operations and constants
+	    to the range and precision of the semantic type.
+	 2  evaluate all operations and constants, whose semantic type has
+	    at most the range and precision of long double, to the range and
+	    precision of long double; evaluate all other operations and
+	    constants to the range and precision of the semantic type.
+	 N  where _FloatN  is a supported interchange floating type
+	    evaluate all operations and constants, whose semantic type has
+	    at most the range and precision of the _FloatN type, to the
+	    range and precision of the _FloatN type; evaluate all other
+	    operations and constants to the range and precision of the
+	    semantic type.
+	 N + 1, where _FloatNx is a supported extended floating type
+	    evaluate operations and constants, whose semantic type has at
+	    most the range and precision of the _FloatNx type, to the range
+	    and precision of the _FloatNx type; evaluate all other
+	    operations and constants to the range and precision of the
+	    semantic type.
+
+   The compiler predefines two macros:
+
+      __FLT_EVAL_METHOD__
+      Which, depending on the value given for
+      -fpermitted-flt-eval-methods, may be limited to only those values
+      for FLT_EVAL_METHOD defined in C99/C11.
+
+     __FLT_EVAL_METHOD_TS_18661_3__
+      Which always permits the values for FLT_EVAL_METHOD defined in
+      ISO/IEC TS 18661-3.
+
+     Here we want to use __FLT_EVAL_METHOD__, unless
+     __STDC_WANT_IEC_60559_TYPES_EXT__ is defined, in which case the user
+     is specifically asking for the ISO/IEC TS 18661-3 types, so we use
+     __FLT_EVAL_METHOD_TS_18661_3__.
 
    ??? This ought to change with the setting of the fp control word;
    the value provided by the compiler assumes the widest setting.  */
 #undef FLT_EVAL_METHOD
+#ifdef __STDC_WANT_IEC_60559_TYPES_EXT__
+#define FLT_EVAL_METHOD __FLT_EVAL_METHOD_TS_18661_3__
+#else
 #define FLT_EVAL_METHOD	__FLT_EVAL_METHOD__
+#endif
 
 /* Number of decimal digits, n, such that any floating-point number in the
    widest supported floating type with pmax radix b digits can be rounded
diff --git a/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_3.c b/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_3.c
new file mode 100644
index 0000000..c7bd756
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_3.c
@@ -0,0 +1,21 @@
+/* { dg-do run } */
+/* { dg-options "-std=c11" } */
+
+/* Test that when compiling with -std=c11, we only see the C99/C11 values
+   for FLT_EVAL_METHOD.  */
+
+#include <float.h>
+
+int main (int argc, char** argv)
+{
+  switch (FLT_EVAL_METHOD)
+    {
+      case 0:
+      case 1:
+      case 2:
+      case -1:
+	return 0;
+      default:
+	return 1;
+    }
+}
diff --git a/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_4.c b/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_4.c
new file mode 100644
index 0000000..a7bbb65
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_4.c
@@ -0,0 +1,25 @@
+/* { dg-do run } */
+/* { dg-options "-std=c11" } */
+
+/* Test that when compiling with -std=c11 and defining
+   __STDC_WANT_IEC_60559_TYPES_EXT__, we only see the ISO/IEC TS
+   18661-3 values for FLT_EVAL_METHOD.  */
+
+#define __STDC_WANT_IEC_60559_TYPES_EXT__
+
+#include <float.h>
+
+int main (int argc, char** argv)
+{
+  switch (__FLT_EVAL_METHOD__)
+    {
+      case 0:
+      case 1:
+      case 2:
+      case 16:
+      case -1:
+	return 0;
+      default:
+	return 1;
+    }
+}
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 59b84eb..d02ca6c 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -1685,41 +1685,17 @@ backend_init (void)
   init_regs ();
 }
 
-/* Initialize excess precision settings.  */
+/* Initialize excess precision settings.
+
+   We have no need to modify anything here, just keep track of what the
+   user requested.  We'll figure out any appropriate relaxations
+   later.  */
+
 static void
 init_excess_precision (void)
 {
-  /* Adjust excess precision handling based on the target options.  If
-     the front end cannot handle it, flag_excess_precision_cmdline
-     will already have been set accordingly in the post_options
-     hook.  */
   gcc_assert (flag_excess_precision_cmdline != EXCESS_PRECISION_DEFAULT);
   flag_excess_precision = flag_excess_precision_cmdline;
-  if (flag_unsafe_math_optimizations)
-    flag_excess_precision = EXCESS_PRECISION_FAST;
-  if (flag_excess_precision == EXCESS_PRECISION_STANDARD)
-    {
-      int flt_eval_method = TARGET_FLT_EVAL_METHOD;
-      switch (flt_eval_method)
-	{
-	case -1:
-	case 0:
-	  /* Either the target acts unpredictably (-1) or has all the
-	     operations required not to have excess precision (0).  */
-	  flag_excess_precision = EXCESS_PRECISION_FAST;
-	  break;
-	case 1:
-	case 2:
-	  /* In these cases, predictable excess precision makes
-	     sense.  */
-	  break;
-	default:
-	  /* Any other implementation-defined FLT_EVAL_METHOD values
-	     require the compiler to handle the associated excess
-	     precision rules in excess_precision_type.  */
-	  gcc_unreachable ();
-	}
-    }
 }
 
 /* Initialize things that are both lang-dependent and target-dependent.
diff --git a/gcc/tree.c b/gcc/tree.c
index 56cc653..7d2dd90 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -8835,50 +8835,99 @@ build_complex_type (tree component_type, bool named)
 tree
 excess_precision_type (tree type)
 {
-  if (flag_excess_precision != EXCESS_PRECISION_FAST)
+  /* The target can give two different responses to the question of
+     which excess precision mode it would like depending on whether we
+     are in -fexcess-precision=standard or -fexcess-precision=fast.  */
+
+  enum excess_precision_type requested_type
+    = (flag_excess_precision == EXCESS_PRECISION_FAST
+       ? EXCESS_PRECISION_TYPE_FAST
+       : EXCESS_PRECISION_TYPE_STANDARD);
+
+  enum flt_eval_method target_flt_eval_method
+    = targetm.c.excess_precision (requested_type);
+
+  /* The target should not ask for unpredictable float evaluation (though
+     it might advertise that implicitly the evaluation is unpredictable,
+     but we don't care about that here, it will have been reported
+     elsewhere).  If it does ask for unpredictable evaluation, we have
+     nothing to do here.  */
+  gcc_assert (target_flt_eval_method != FLT_EVAL_METHOD_UNPREDICTABLE);
+
+  /* Nothing to do.  The target has asked for all types we know about
+     to be computed with their native precision and range.  */
+  if (target_flt_eval_method == FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16)
+    return NULL_TREE;
+
+  /* The target will promote this type in a target-dependent way, so excess
+     precision ought to leave it alone.  */
+  if (targetm.promoted_type (type) != NULL_TREE)
+    return NULL_TREE;
+
+  machine_mode float16_type_mode = (float16_type_node
+				    ? TYPE_MODE (float16_type_node)
+				    : VOIDmode);
+  machine_mode float_type_mode = TYPE_MODE (float_type_node);
+  machine_mode double_type_mode = TYPE_MODE (double_type_node);
+
+  switch (TREE_CODE (type))
     {
-      int flt_eval_method = TARGET_FLT_EVAL_METHOD;
-      switch (TREE_CODE (type))
-	{
-	case REAL_TYPE:
-	  switch (flt_eval_method)
-	    {
-	    case 1:
-	      if (TYPE_MODE (type) == TYPE_MODE (float_type_node))
-		return double_type_node;
-	      break;
-	    case 2:
-	      if (TYPE_MODE (type) == TYPE_MODE (float_type_node)
-		  || TYPE_MODE (type) == TYPE_MODE (double_type_node))
-		return long_double_type_node;
-	      break;
-	    default:
-	      gcc_unreachable ();
-	    }
-	  break;
-	case COMPLEX_TYPE:
-	  if (TREE_CODE (TREE_TYPE (type)) != REAL_TYPE)
-	    return NULL_TREE;
-	  switch (flt_eval_method)
-	    {
-	    case 1:
-	      if (TYPE_MODE (TREE_TYPE (type)) == TYPE_MODE (float_type_node))
-		return complex_double_type_node;
-	      break;
-	    case 2:
-	      if (TYPE_MODE (TREE_TYPE (type)) == TYPE_MODE (float_type_node)
-		  || (TYPE_MODE (TREE_TYPE (type))
-		      == TYPE_MODE (double_type_node)))
-		return complex_long_double_type_node;
-	      break;
-	    default:
-	      gcc_unreachable ();
-	    }
-	  break;
-	default:
-	  break;
-	}
+    case REAL_TYPE:
+      {
+	machine_mode type_mode = TYPE_MODE (type);
+	switch (target_flt_eval_method)
+	  {
+	  case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT:
+	    if (type_mode == float16_type_mode)
+	      return float_type_node;
+	    break;
+	  case FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE:
+	    if (type_mode == float16_type_mode
+		|| type_mode == float_type_mode)
+	      return double_type_node;
+	    break;
+	  case FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE:
+	    if (type_mode == float16_type_mode
+		|| type_mode == float_type_mode
+		|| type_mode == double_type_mode)
+	      return long_double_type_node;
+	    break;
+	  default:
+	    gcc_unreachable ();
+	  }
+	break;
+      }
+    case COMPLEX_TYPE:
+      {
+	if (TREE_CODE (TREE_TYPE (type)) != REAL_TYPE)
+	  return NULL_TREE;
+	machine_mode type_mode = TYPE_MODE (TREE_TYPE (type));
+	switch (target_flt_eval_method)
+	  {
+	  case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT:
+	    if (type_mode == float16_type_mode)
+	      return complex_float_type_node;
+	    break;
+	  case FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE:
+	    if (type_mode == float16_type_mode
+		|| type_mode == float_type_mode)
+	      return complex_double_type_node;
+	    break;
+	  case FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE:
+	    if (type_mode == float16_type_mode
+		|| type_mode == float_type_mode
+		|| type_mode == double_type_mode)
+	      return complex_long_double_type_node;
+	    break;
+	  default:
+	    gcc_unreachable ();
+	  }
+	break;
+      }
+    default:
+      break;
     }
+
   return NULL_TREE;
 }
 \f

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

* Re: [Patch 3/4] Half to double precision conversions
  2016-10-24 22:24     ` Joseph Myers
@ 2016-11-02 17:41       ` James Greenhalgh
  0 siblings, 0 replies; 95+ messages in thread
From: James Greenhalgh @ 2016-11-02 17:41 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, joseph, ramrad01, richard.earnshaw, kyrtka01

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


On Mon, Oct 24, 2016 at 10:24:27PM +0000, Joseph Myers wrote:
> On Mon, 24 Oct 2016, James Greenhalgh wrote:
>
> > Conversions from double precision floats to the ARM __fp16 are required
> > to round only once.
>
> I'd expect that when fixing this you need to update
> gcc.target/arm/fp16-rounding-ieee-1.c (and fp16-rounding-alt-1.c, I
> suppose) to expect rounding once.  But I don't see such a testsuite change
> anywhere in this patch series.

Right, I went back and checked my ARM test environment. Sure enough it was
producing nonsense results. I've fixed my build system issue, which causes
these tests to start failing as you predicted. I've now fixed them in this
patch revision to use the value they would return if rounding happened
directly rather than first through SFmode.

Thanks,
James

---
gcc/

2016-11-02  James Greenhalgh  <james.greenhalgh@arm.com>

	* 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-02  James Greenhalgh  <james.greenhalgh@arm.com>

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


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Patch-3-4-Half-to-double-precision-conversions.patch --]
[-- Type: text/x-patch; name="0001-Patch-3-4-Half-to-double-precision-conversions.patch", Size: 9184 bytes --]

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 8ce4e4e..524c474 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -251,7 +251,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);
@@ -660,9 +659,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
 
@@ -2565,6 +2561,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);
@@ -5314,6 +5315,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;
@@ -23742,23 +23745,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 fa8e84c..0f9a679 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -194,6 +194,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 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);
+      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.
@@ -5684,19 +5699,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 45ce5c9..cb23c7f 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;

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

* Re: [Patch ARM 4/4] Enable _Float16
  2016-10-24 22:29     ` Joseph Myers
@ 2016-11-02 17:43       ` James Greenhalgh
  2016-11-02 18:42         ` Joseph Myers
  0 siblings, 1 reply; 95+ messages in thread
From: James Greenhalgh @ 2016-11-02 17:43 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, joseph, ramrad01, richard.earnshaw, kyrtka01

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


On Mon, Oct 24, 2016 at 10:28:42PM +0000, Joseph Myers wrote:
> On Mon, 24 Oct 2016, James Greenhalgh wrote:
>
> > Hi,
> >
> > Finally, having added support for single-step DFmode to HFmode conversions,
> > this patch adds support for _Float16 to the ARM back-end.
>
> Given the need for -mfp16-format=ieee (on some processors), you should be
> updating target-supports.exp:add_options_for_float16 to add that option in
> the ARM case, and make sure that the tests run in cases where the option
> is needed to enable support for this format.

Done in this revision, though this makes no difference to what gets tested
as these options are not added when compiling the probe functions
(check_effective_target_float16). These would need a patch like:

diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index abc4ac0..36573cc 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -2485,7 +2485,7 @@ proc check_effective_target_has_q_floating_suffix { } {
 proc check_effective_target_float16 {} {
     return [check_no_compiler_messages_nocache float16 object {
         _Float16 x;
-    }]
+    } [add_options_for_float16 {}]]
 }

 proc check_effective_target_float32 {} {

To actually enable the tests.

> > That means making sure that only __fp16 promotes and adding similar hooks to
> > those used in the AArch64 port giving the excess precision rules, and
> > marking HFmode as supported in libgcc.
>
> Does "supported in libgcc" mean this patch completes fixing bug 63250?

From my reading of the bug. Yes. I'll tag the gcc ChangeLog as a fix, so it
is recorded against the PR.

Thanks,
James

---
gcc/

2016-11-02  James Greenhalgh  <james.greenhalgh@arm.com>

	PR target/63250
	* config/arm/arm-builtins.c (arm_simd_floatHF_type_node): Rename to...
	(arm_fp16_type_node): ...This, make visibile.
	(arm_simd_builtin_std_type): Rename arm_simd_floatHF_type_node to
	arm_fp16_type_node.
	(arm_init_simd_builtin_types): Likewise.
	(arm_init_fp16_builtins): Likewise.
	* config/arm/arm.c (arm_excess_precision): New.
	(arm_floatn_mode): Likewise.
	(TARGET_C_EXCESS_PRECISION): Likewise.
	(TARGET_FLOATN_MODE): Likewise.
	(arm_promoted_type): Only promote arm_fp16_type_node.
	* config/arm/arm.h (arm_fp16_type_node): Declare.

gcc/testsuite/

2016-11-02  James Greenhalgh  <james.greenhalgh@arm.com>

	* lib/target-supports.exp (add_options_for_float16): Add
	-mfp16-format=ieee when testign arm*-*-*.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Re-Patch-ARM-4-4-Enable-_Float16.patch --]
[-- Type: text/x-patch; name="0001-Re-Patch-ARM-4-4-Enable-_Float16.patch", Size: 7553 bytes --]

diff --git a/gcc/config/arm/arm-builtins.c b/gcc/config/arm/arm-builtins.c
index e73043d..5ed38d1 100644
--- a/gcc/config/arm/arm-builtins.c
+++ b/gcc/config/arm/arm-builtins.c
@@ -652,7 +652,8 @@ static struct arm_simd_type_info arm_simd_types [] = {
 };
 #undef ENTRY
 
-static tree arm_simd_floatHF_type_node = NULL_TREE;
+/* The user-visible __fp16 type.  */
+tree arm_fp16_type_node = NULL_TREE;
 static tree arm_simd_intOI_type_node = NULL_TREE;
 static tree arm_simd_intEI_type_node = NULL_TREE;
 static tree arm_simd_intCI_type_node = NULL_TREE;
@@ -739,7 +740,7 @@ arm_simd_builtin_std_type (enum machine_mode mode,
     case XImode:
       return arm_simd_intXI_type_node;
     case HFmode:
-      return arm_simd_floatHF_type_node;
+      return arm_fp16_type_node;
     case SFmode:
       return float_type_node;
     case DFmode:
@@ -840,8 +841,8 @@ arm_init_simd_builtin_types (void)
   /* Continue with standard types.  */
   /* The __builtin_simd{64,128}_float16 types are kept private unless
      we have a scalar __fp16 type.  */
-  arm_simd_types[Float16x4_t].eltype = arm_simd_floatHF_type_node;
-  arm_simd_types[Float16x8_t].eltype = arm_simd_floatHF_type_node;
+  arm_simd_types[Float16x4_t].eltype = arm_fp16_type_node;
+  arm_simd_types[Float16x8_t].eltype = arm_fp16_type_node;
   arm_simd_types[Float32x2_t].eltype = float_type_node;
   arm_simd_types[Float32x4_t].eltype = float_type_node;
 
@@ -1754,11 +1755,11 @@ arm_init_iwmmxt_builtins (void)
 static void
 arm_init_fp16_builtins (void)
 {
-  arm_simd_floatHF_type_node = make_node (REAL_TYPE);
-  TYPE_PRECISION (arm_simd_floatHF_type_node) = GET_MODE_PRECISION (HFmode);
-  layout_type (arm_simd_floatHF_type_node);
+  arm_fp16_type_node = make_node (REAL_TYPE);
+  TYPE_PRECISION (arm_fp16_type_node) = GET_MODE_PRECISION (HFmode);
+  layout_type (arm_fp16_type_node);
   if (arm_fp16_format)
-    (*lang_hooks.types.register_builtin_type) (arm_simd_floatHF_type_node,
+    (*lang_hooks.types.register_builtin_type) (arm_fp16_type_node,
 					       "__fp16");
 }
 
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 524c474..5695548 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -272,6 +272,7 @@ static bool arm_builtin_support_vector_misalignment (machine_mode mode,
 						     int misalignment,
 						     bool is_packed);
 static void arm_conditional_register_usage (void);
+static enum flt_eval_method arm_excess_precision (enum excess_precision_type);
 static reg_class_t arm_preferred_rename_class (reg_class_t rclass);
 static unsigned int arm_autovectorize_vector_sizes (void);
 static int arm_default_branch_cost (bool, bool);
@@ -305,6 +306,7 @@ static bool arm_asm_elf_flags_numeric (unsigned int flags, unsigned int *num);
 static unsigned int arm_elf_section_type_flags (tree decl, const char *name,
 						int reloc);
 static void arm_expand_divmod_libfunc (rtx, machine_mode, rtx, rtx, rtx *, rtx *);
+static machine_mode arm_floatn_mode (int, bool);
 \f
 /* Table of machine attributes.  */
 static const struct attribute_spec arm_attribute_table[] =
@@ -450,6 +452,9 @@ static const struct attribute_spec arm_attribute_table[] =
 #undef  TARGET_ASM_INTERNAL_LABEL
 #define TARGET_ASM_INTERNAL_LABEL arm_internal_label
 
+#undef TARGET_FLOATN_MODE
+#define TARGET_FLOATN_MODE arm_floatn_mode
+
 #undef  TARGET_FUNCTION_OK_FOR_SIBCALL
 #define TARGET_FUNCTION_OK_FOR_SIBCALL arm_function_ok_for_sibcall
 
@@ -740,6 +745,9 @@ static const struct attribute_spec arm_attribute_table[] =
 #undef TARGET_EXPAND_DIVMOD_LIBFUNC
 #define TARGET_EXPAND_DIVMOD_LIBFUNC arm_expand_divmod_libfunc
 
+#undef TARGET_C_EXCESS_PRECISION
+#define TARGET_C_EXCESS_PRECISION arm_excess_precision
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
 /* Obstack for minipool constant handling.  */
@@ -23740,7 +23748,7 @@ arm_debugger_arg_offset (int value, rtx addr)
 static tree
 arm_promoted_type (const_tree t)
 {
-  if (SCALAR_FLOAT_TYPE_P (t) && TYPE_PRECISION (t) == 16)
+  if (TYPE_P (t) && TYPE_MAIN_VARIANT (t) == arm_fp16_type_node)
     return float_type_node;
   return NULL_TREE;
 }
@@ -23762,6 +23770,61 @@ arm_scalar_mode_supported_p (machine_mode mode)
     return default_scalar_mode_supported_p (mode);
 }
 
+/* Set the value of FLT_EVAL_METHOD.
+   ISO/IEC TS 18661-3 defines two values that we'd like to make use of:
+
+    0: evaluate all operations and constants, whose semantic type has at
+       most the range and precision of type float, to the range and
+       precision of float; evaluate all other operations and constants to
+       the range and precision of the semantic type;
+
+    N, where _FloatN is a supported interchange floating type
+       evaluate all operations and constants, whose semantic type has at
+       most the range and precision of _FloatN type, to the range and
+       precision of the _FloatN type; evaluate all other operations and
+       constants to the range and precision of the semantic type;
+
+   If we have the ARMv8.2-A extensions then we support _Float16 in native
+   precision, so we should set this to 16.  Otherwise, we support the type,
+   but want to evaluate expressions in float precision, so set this to
+   0.  */
+
+static enum flt_eval_method
+arm_excess_precision (enum excess_precision_type type)
+{
+  switch (type)
+    {
+      case EXCESS_PRECISION_TYPE_FAST:
+      case EXCESS_PRECISION_TYPE_STANDARD:
+	/* We can calculate either in 16-bit range and precision or
+	   32-bit range and precision.  Make that decision based on whether
+	   we have native support for the ARMv8.2-A 16-bit floating-point
+	   instructions or not.  */
+	return (TARGET_VFP_FP16INST
+		? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16
+		: FLT_EVAL_METHOD_PROMOTE_TO_FLOAT);
+      case EXCESS_PRECISION_TYPE_IMPLICIT:
+	return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16;
+      default:
+	gcc_unreachable ();
+    }
+  return FLT_EVAL_METHOD_UNPREDICTABLE;
+}
+
+
+/* Implement TARGET_FLOATN_MODE.  Make very sure that we don't provide
+   _Float16 if we are using anything other than ieee format for 16-bit
+   floating point.  Otherwise, punt to the default implementation.  */
+static machine_mode
+arm_floatn_mode (int n, bool extended)
+{
+  if (!extended && n == 16)
+    return arm_fp16_format == ARM_FP16_FORMAT_IEEE ? HFmode : VOIDmode;
+
+  return default_floatn_mode (n, extended);
+}
+
+
 /* Set up OPERANDS for a register copy from SRC to DEST, taking care
    not to early-clobber SRC registers in the process.
 
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 0f9a679..f7aa155 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -82,6 +82,11 @@ extern int arm_ccfsm_state;
 extern GTY(()) rtx arm_target_insn;
 /* Callback to output language specific object attributes.  */
 extern void (*arm_lang_output_object_attributes_hook)(void);
+
+/* This type is the user-visible __fp16.  We need it in a few places in
+   the backend.  Defined in arm-builtins.c.  */
+extern tree arm_fp16_type_node;
+
 \f
 /* Just in case configure has failed to define anything.  */
 #ifndef TARGET_CPU_DEFAULT
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 722955a..3b3459c 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -2584,6 +2584,9 @@ proc check_effective_target_floatn_nx_runtime {} {
 # the function name.
 
 proc add_options_for_float16 { flags } {
+    if { [istarget arm*-*-*] } {
+	return "$flags -mfp16-format=ieee"
+    }
     return "$flags"
 }
 

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

* Re: [Patch ARM 4/4] Enable _Float16
  2016-11-02 17:43       ` James Greenhalgh
@ 2016-11-02 18:42         ` Joseph Myers
  0 siblings, 0 replies; 95+ messages in thread
From: Joseph Myers @ 2016-11-02 18:42 UTC (permalink / raw)
  To: James Greenhalgh; +Cc: gcc-patches, nd, ramrad01, richard.earnshaw, kyrtka01

On Wed, 2 Nov 2016, James Greenhalgh wrote:

> Done in this revision, though this makes no difference to what gets tested
> as these options are not added when compiling the probe functions
> (check_effective_target_float16). These would need a patch like:
> 
> diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
> index abc4ac0..36573cc 100644
> --- a/gcc/testsuite/lib/target-supports.exp
> +++ b/gcc/testsuite/lib/target-supports.exp
> @@ -2485,7 +2485,7 @@ proc check_effective_target_has_q_floating_suffix { } {
>  proc check_effective_target_float16 {} {
>      return [check_no_compiler_messages_nocache float16 object {
>          _Float16 x;
> -    }]
> +    } [add_options_for_float16 {}]]
>  }
> 
>  proc check_effective_target_float32 {} {
> 
> To actually enable the tests.

Then I think such a change should be made (for all these functions, 
probably separately from the ARM patch) so we have proper test coverage 
for _Float16 on ARM.  (I noted when adding the dg-add-options to these 
tests that I hadn't tested this properly enabled the _Float64x / _Float128 
tests on powerpc64le and that that could do with powerpc maintainer 
testing.)

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [Patch 1/4] [libgcc, ARM] Generalise float-to-half conversion function.
  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
  0 siblings, 0 replies; 95+ messages in thread
From: James Greenhalgh @ 2016-11-08 11:58 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, richard.earnshaw, ramana.radhakrishnan, kyrtka01, joseph

On Mon, Oct 24, 2016 at 02:44:37PM +0100, James Greenhalgh wrote:
> 
> Hi,
> 
> I'm adapting this patch from work started by Matthew Wahab.
> 
> Conversions from double precision floats to the ARM __fp16 are required
> to round only once. A conversion function for double to __fp16 to
> support this on soft-fp targets. This and the following patch add this
> conversion function by reusing the exising float to __fp16 function
> config/arm/fp16.c:__gnu_f2h_internal.
> 
> This patch generalizes __gnu_f2h_internal by adding a specification of
> the source format and reworking the code to make use of it. Initially,
> only the binary32 format is supported.
> 
> Bootstrapped on an ARMv8-A machine with no issues, and cross-tested with
> a reasonable multi-lib range.
> 
> 2016-10-24  James Greenhalgh  <james.greenhalgh@arm.com>
> 	    Matthew Wahab  <matthew.wahab@arm.com>
> 
> 	* config/arm/fp16.c (struct format): New.
> 	(binary32): New.
> 	(__gnu_float2h_internal): New.  Body moved from
> 	__gnu_f2h_internal and generalize.
> 	(_gnu_f2h_internal): Move body to function __gnu_float2h_internal.
> 	Call it with binary32.

Looking at it carefully, this patch has a bug in the way it handles
rounding for doubles. The relevant code looks like this:

  if (aexp < -14)
    {
      mask = point | (point - 1);
      /* Minimum exponent for half-precision is 2^-24.  */
      if (aexp >= -25)
	mask >>= 25 + aexp;
    }
  else
    mask = 0x00001fff;

  /* Round.  */
  if (mantissa & mask)
    {
      increment = (mask + 1) >> 1;
      if ((mantissa & mask) == increment)
	increment = mantissa & (increment << 1);
      mantissa += increment;
      if (mantissa >= (point << 1))
	{
	  mantissa >>= 1;
	  aexp++;
	}
    }

But clearly that mask is not going to be sufficient when we are deciding
whether we ought to round a double or not as there are many more bits for
us to look at.

I'll work on a new spin of this patch.

I'm still hopeful that both this and the AArch64 (and generic bits and
pieces) support for _Float16 will make it for GCC 7.

Thanks,
James

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

* Re: [Patch 1/11] Add a new target hook for describing excess precision intentions
  2016-11-02 17:36       ` James Greenhalgh
@ 2016-11-09  2:34         ` Joseph Myers
  0 siblings, 0 replies; 95+ messages in thread
From: Joseph Myers @ 2016-11-09  2:34 UTC (permalink / raw)
  To: James Greenhalgh; +Cc: gcc-patches, nd

On Wed, 2 Nov 2016, James Greenhalgh wrote:

> 2016-11-02  James Greenhalgh  <james.greenhalgh@arm.com>
> 
> 	* target.def (excess_precision): New hook.
> 	* target.h (flt_eval_method): New.
> 	(excess_precision_type): Likewise.
> 	* targhooks.c (default_excess_precision): New.
> 	* targhooks.h (default_excess_precision): New.
> 	* doc/tm.texi.in (TARGET_C_EXCESS_PRECISION): New.
> 	* doc/tm.texi: Regenerate.

OK.

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [Patch 6/11] Migrate excess precision logic to use TARGET_EXCESS_PRECISION
  2016-11-02 17:38         ` James Greenhalgh
@ 2016-11-09  2:47           ` Joseph Myers
  0 siblings, 0 replies; 95+ messages in thread
From: Joseph Myers @ 2016-11-09  2:47 UTC (permalink / raw)
  To: James Greenhalgh; +Cc: gcc-patches, nd

On Wed, 2 Nov 2016, James Greenhalgh wrote:

> OK, I've reworked the patch along those lines. I noticed that the original
> logic looked for
> 
>       && TARGET_FLT_EVAL_METHOD != 0
> 
> And I no longer make that check. Is that something I need to reinstate?

No, the replacement logic should imply that previously supported cases 
with TARGET_FLT_EVAL_METHOD == 0 will pass as being IEEE-compatible.

> I didn't find any reference to excess precision in Annex F, so I'd guess
> not?

There are references, e.g. F.6 requiring that the return statement removes 
excess precision (but that's something done in the front end, nothing to 
do with this patch).

> diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
> index 547bab2..507967d 100644
> --- a/gcc/c-family/c-common.h
> +++ b/gcc/c-family/c-common.h
> @@ -1314,6 +1314,8 @@ c_tree_chain_next (tree t)
>  #define TM_STMT_ATTR_ATOMIC	4
>  #define TM_STMT_ATTR_RELAXED	8
>  
> +extern int parse_tm_stmt_attr (tree, int);
> +
>  /* Mask used by tm_attr_to_mask and tm_mask_to_attr.  Note that these
>     are ordered specifically such that more restrictive attributes are
>     at lower bit positions.  This fact is known by the C++ tm attribute
> @@ -1325,6 +1327,10 @@ c_tree_chain_next (tree t)
>  #define TM_ATTR_IRREVOCABLE		8
>  #define TM_ATTR_MAY_CANCEL_OUTER	16
>  
> +extern int tm_attr_to_mask (tree);
> +extern tree tm_mask_to_attr (int);
> +extern tree find_tm_attribute (tree);
> +
>  /* A suffix-identifier value doublet that represents user-defined literals
>     for C++-0x.  */
>  enum overflow_type {

These changes to c-common.h are nothing to do with the subject of the 
patch.

The patch is OK with those changes removed.  If there are other changes in 
this series still needing review, please repost the whole series 
identifying what patches still need review.  (I think the ARM _Float16 
support still needs the testsuite changes to ensure that 
architecture-specific options to enable _FloatN / _FloatNx support are 
used when testing if the types are supported, so that the _Float16 tests 
are actually run in that case.)

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* [Patch 5/17] Add -fpermitted-flt-eval-methods=[c11|ts-18661-3]
  2016-11-11 15:38 ` [Patch v4 0/17] Add support for _Float16 to AArch64 and ARM James Greenhalgh
@ 2016-11-11 15:38   ` James Greenhalgh
  2016-11-12  4:42     ` Sandra Loosemore
  2016-11-11 15:38   ` [Patch 4/17] Implement TARGET_C_EXCESS_PRECISION for m68k James Greenhalgh
                     ` (11 subsequent siblings)
  12 siblings, 1 reply; 95+ messages in thread
From: James Greenhalgh @ 2016-11-11 15:38 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, joseph, law

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


---
This patch was approved here:
  https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02405.html

Joseph had a comment in
https://gcc.gnu.org/ml/gcc-patches/2016-10/msg00335.html that the tests
should check FLT_EVAL_METHOD from <float.h> rather than
__FLT_EVAL_METHOD__. Rather than implement that suggestion, I added tests
to patch 6 which tested the <float.h> macro, and left the tests in this
patch testing the internal macro.
---

Hi,

This option is added to control which values of FLT_EVAL_METHOD the
compiler is allowed to set.

ISO/IEC TS 18661-3 defines new permissible values for
FLT_EVAL_METHOD that indicate that operations and constants with
a semantic type that is an interchange or extended format should be
evaluated to the precision and range of that type.  These new values are
a superset of those permitted under C99/C11, which does not specify the
meaning of other positive values of FLT_EVAL_METHOD.  As such, code
conforming to C11 may not have been written expecting the possibility of
the new values.

-fpermitted-flt-eval-methods specifies whether the compiler
should allow only the values of FLT_EVAL_METHOD specified in C99/C11,
or the extended set of values specified in ISO/IEC TS 18661-3.

The two possible values this option can take are "c11" or "ts-18661-3".

The default when in a standards compliant mode (-std=c11 or similar)
is -fpermitted-flt-eval-methods=c11.  The default when in a GNU
dialect (-std=gnu11 or similar) is -fpermitted-flt-eval-methods=ts-18661-3.

I've added two testcases which test that when this option, or a C standards
dialect, would restrict the range of values to {-1, 0, 1, 2}, those are
the only values we see. At this stage in the patch series this trivially
holds for all targets.

Bootstrapped on x86_64 with no issues.

Thanks,
James

---
gcc/c-family/

2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>

	* c-opts.c (c_common_post_options): Add logic to handle the default
	case for -fpermitted-flt-eval-methods.

gcc/

2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>

	* common.opt (fpermitted-flt-eval-methods): New.
	* doc/invoke.texi (-fpermitted-flt-eval-methods): Document it.
	* flag_types.h (permitted_flt_eval_methods): New.

gcc/testsuite/

2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>

	* gcc.dg/fpermitted-flt-eval-methods_1.c: New.
	* gcc.dg/fpermitted-flt-eval-methods_2.c: New.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0005-Patch-5-17-Add-fpermitted-flt-eval-methods-c11-ts-18.patch --]
[-- Type: text/x-patch; name="0005-Patch-5-17-Add-fpermitted-flt-eval-methods-c11-ts-18.patch", Size: 6304 bytes --]

diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
index de260e7..57717ff 100644
--- a/gcc/c-family/c-opts.c
+++ b/gcc/c-family/c-opts.c
@@ -788,6 +788,18 @@ c_common_post_options (const char **pfilename)
       && flag_unsafe_math_optimizations == 0)
     flag_fp_contract_mode = FP_CONTRACT_OFF;
 
+  /* If we are compiling C, and we are outside of a standards mode,
+     we can permit the new values from ISO/IEC TS 18661-3 for
+     FLT_EVAL_METHOD.  Otherwise, we must restrict the possible values to
+     the set specified in ISO C99/C11.  */
+  if (!flag_iso
+      && !c_dialect_cxx ()
+      && (global_options_set.x_flag_permitted_flt_eval_methods
+	  == PERMITTED_FLT_EVAL_METHODS_DEFAULT))
+    flag_permitted_flt_eval_methods = PERMITTED_FLT_EVAL_METHODS_TS_18661;
+  else
+    flag_permitted_flt_eval_methods = PERMITTED_FLT_EVAL_METHODS_C11;
+
   /* By default we use C99 inline semantics in GNU99 or C99 mode.  C99
      inline semantics are not supported in GNU89 or C89 mode.  */
   if (flag_gnu89_inline == -1)
diff --git a/gcc/common.opt b/gcc/common.opt
index 314145a..915c406 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1326,6 +1326,21 @@ Enum(excess_precision) String(fast) Value(EXCESS_PRECISION_FAST)
 EnumValue
 Enum(excess_precision) String(standard) Value(EXCESS_PRECISION_STANDARD)
 
+; Whether we permit the extended set of values for FLT_EVAL_METHOD
+; introduced in ISO/IEC TS 18661-3, or limit ourselves to those in C99/C11.
+fpermitted-flt-eval-methods=
+Common Joined RejectNegative Enum(permitted_flt_eval_methods) Var(flag_permitted_flt_eval_methods) Init(PERMITTED_FLT_EVAL_METHODS_DEFAULT)
+-fpermitted-flt-eval-methods=[c11|ts-18661]	Specify which values of FLT_EVAL_METHOD are permitted.
+
+Enum
+Name(permitted_flt_eval_methods) Type(enum permitted_flt_eval_methods) UnknownError(unknown specification for the set of FLT_EVAL_METHOD values to permit %qs)
+
+EnumValue
+Enum(permitted_flt_eval_methods) String(c11) Value(PERMITTED_FLT_EVAL_METHODS_C11)
+
+EnumValue
+Enum(permitted_flt_eval_methods) String(ts-18661-3) Value(PERMITTED_FLT_EVAL_METHODS_TS_18661)
+
 ffast-math
 Common Optimization
 
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index f133b3a..75ff8ec 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -378,7 +378,8 @@ Objective-C and Objective-C++ Dialects}.
 -flto-partition=@var{alg} -fmerge-all-constants @gol
 -fmerge-constants -fmodulo-sched -fmodulo-sched-allow-regmoves @gol
 -fmove-loop-invariants -fno-branch-count-reg @gol
--fno-defer-pop -fno-fp-int-builtin-inexact -fno-function-cse @gol
+-fno-defer-pop -fno-fp-int-builtin-inexact @gol
+-fpermitted-flt-eval-methods=@var{standard} -fno-function-cse @gol
 -fno-guess-branch-probability -fno-inline -fno-math-errno -fno-peephole @gol
 -fno-peephole2 -fno-sched-interblock -fno-sched-spec -fno-signed-zeros @gol
 -fno-toplevel-reorder -fno-trapping-math -fno-zero-initialized-in-bss @gol
@@ -9155,6 +9156,30 @@ Even if @option{-fno-fp-int-builtin-inexact} is used, if the functions
 generate a call to a library function then the ``inexact'' exception
 may be raised if the library implementation does not follow TS 18661.
 
+@item -fpermitted-flt-eval-methods=@var{style}
+@opindex fpermitted-flt-eval-methods
+@opindex fpermitted-flt-eval-methods=c11
+@opindex fpermitted-flt-eval-methods=ts-18661-3
+ISO/IEC TS 18661-3 defines new permissible values for
+@code{FLT_EVAL_METHOD} that indicate that operations and constants with
+a semantic type that is an interchange or extended format should be
+evaluated to the precision and range of that type.  These new values are
+a superset of those permitted under C99/C11, which does not specify the
+meaning of other positive values of @code{FLT_EVAL_METHOD}.  As such, code
+conforming to C11 may not have been written expecting the possibility of
+the new values.
+
+@option{-fpermitted-flt-eval-methods} specifies whether the compiler
+should allow only the values of @code{FLT_EVAL_METHOD} specified in C99/C11,
+or the extended set of values specified in ISO/IEC TS 18661-3.
+
+@var{style} is either @code{c11} or @code{ts-18661-3} as appropriate.
+
+The default when in a standards compliant mode (@option{-std=c11} or similar)
+is @option{-fpermitted-flt-eval-methods=c11}.  The default when in a GNU
+dialect (@option{-std=gnu11} or similar) is
+@option{-fpermitted-flt-eval-methods=ts-18661-3}.
+
 @item -fsingle-precision-constant
 @opindex fsingle-precision-constant
 Treat floating-point constants as single precision instead of
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index 6c5a4cc..d69f8f4 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -158,6 +158,14 @@ enum excess_precision
   EXCESS_PRECISION_STANDARD
 };
 
+/* The options for which values of FLT_EVAL_METHOD are permissible.  */
+enum permitted_flt_eval_methods
+{
+  PERMITTED_FLT_EVAL_METHODS_DEFAULT,
+  PERMITTED_FLT_EVAL_METHODS_TS_18661,
+  PERMITTED_FLT_EVAL_METHODS_C11
+};
+
 /* Type of stack check.  */
 enum stack_check_type
 {
diff --git a/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_1.c b/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_1.c
new file mode 100644
index 0000000..c022f86
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_1.c
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+/* { dg-options "-std=c11" } */
+
+/* Test that we only see the C99/C11 values for __FLT_EVAL_METHOD__ if
+   we are compiling with -std=c11.  */
+
+int main (int argc, char** argv)
+{
+  switch (__FLT_EVAL_METHOD__)
+    {
+      case 0:
+      case 1:
+      case 2:
+      case -1:
+	return 0;
+      default:
+	return 1;
+    }
+}
diff --git a/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_2.c b/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_2.c
new file mode 100644
index 0000000..a76ea7e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_2.c
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+/* { dg-options "-fpermitted-flt-eval-methods=c11" } */
+
+/* Test that we only see the C99/C11 values for __FLT_EVAL_METHOD__ if
+   we are compiling with -fpermitted-flt-eval-methods=c11.  */
+
+int main (int argc, char** argv)
+{
+  switch (__FLT_EVAL_METHOD__)
+    {
+      case 0:
+      case 1:
+      case 2:
+      case -1:
+	return 0;
+      default:
+	return 1;
+    }
+}

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

* [Patch 2/17] Implement TARGET_C_EXCESS_PRECISION for i386
  2016-11-11 15:38 ` [Patch v4 0/17] Add support for _Float16 to AArch64 and ARM James Greenhalgh
                     ` (2 preceding siblings ...)
  2016-11-11 15:38   ` [Patch 6/17] Migrate excess precision logic to use TARGET_EXCESS_PRECISION James Greenhalgh
@ 2016-11-11 15:38   ` James Greenhalgh
  2016-11-11 15:38   ` [Patch 3/17] Implement TARGET_C_EXCESS_PRECISION for s390 James Greenhalgh
                     ` (8 subsequent siblings)
  12 siblings, 0 replies; 95+ messages in thread
From: James Greenhalgh @ 2016-11-11 15:38 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, joseph, law

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


---
This patch has been approved:
  https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02402.html
---

This patch ports the logic from i386's TARGET_FLT_EVAL_METHOD to the new
target hook TARGET_C_EXCESS_PRECISION.

Bootstrapped and tested with no issues.

OK?

Thanks,
James

---
gcc/

2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>

	* config/i386/i386.c (ix86_excess_precision): New.
	(TARGET_C_EXCESS_PRECISION): Define.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0002-Patch-2-17-Implement-TARGET_C_EXCESS_PRECISION-for-i.patch --]
[-- Type: text/x-patch; name="0002-Patch-2-17-Implement-TARGET_C_EXCESS_PRECISION-for-i.patch", Size: 1996 bytes --]

diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index a5c4ba7..794b149 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -50634,6 +50634,44 @@ ix86_expand_divmod_libfunc (rtx libfunc, machine_mode mode,
   *rem_p = rem;
 }
 
+/* Set the value of FLT_EVAL_METHOD in float.h.  When using only the
+   FPU, assume that the fpcw is set to extended precision; when using
+   only SSE, rounding is correct; when using both SSE and the FPU,
+   the rounding precision is indeterminate, since either may be chosen
+   apparently at random.  */
+
+static enum flt_eval_method
+ix86_excess_precision (enum excess_precision_type type)
+{
+  switch (type)
+    {
+      case EXCESS_PRECISION_TYPE_FAST:
+	/* The fastest type to promote to will always be the native type,
+	   whether that occurs with implicit excess precision or
+	   otherwise.  */
+	return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT;
+      case EXCESS_PRECISION_TYPE_STANDARD:
+      case EXCESS_PRECISION_TYPE_IMPLICIT:
+	/* Otherwise, the excess precision we want when we are
+	   in a standards compliant mode, and the implicit precision we
+	   provide can be identical.  */
+	if (!TARGET_80387)
+	  return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT;
+	else if (TARGET_MIX_SSE_I387)
+	  return FLT_EVAL_METHOD_UNPREDICTABLE;
+	else if (!TARGET_SSE_MATH)
+	  return FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE;
+	else if (TARGET_SSE2)
+	  return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT;
+	else
+	  return FLT_EVAL_METHOD_UNPREDICTABLE;
+      default:
+	gcc_unreachable ();
+    }
+
+  return FLT_EVAL_METHOD_UNPREDICTABLE;
+}
+
 /* Target-specific selftests.  */
 
 #if CHECKING_P
@@ -50865,6 +50903,8 @@ ix86_run_selftests (void)
 #undef TARGET_MD_ASM_ADJUST
 #define TARGET_MD_ASM_ADJUST ix86_md_asm_adjust
 
+#undef TARGET_C_EXCESS_PRECISION
+#define TARGET_C_EXCESS_PRECISION ix86_excess_precision
 #undef TARGET_PROMOTE_PROTOTYPES
 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
 #undef TARGET_SETUP_INCOMING_VARARGS

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

* [Patch 3/17] Implement TARGET_C_EXCESS_PRECISION for s390
  2016-11-11 15:38 ` [Patch v4 0/17] Add support for _Float16 to AArch64 and ARM James Greenhalgh
                     ` (3 preceding siblings ...)
  2016-11-11 15:38   ` [Patch 2/17] Implement TARGET_C_EXCESS_PRECISION for i386 James Greenhalgh
@ 2016-11-11 15:38   ` James Greenhalgh
  2016-11-11 15:38   ` [Patch 1/17] Add a new target hook for describing excess precision intentions James Greenhalgh
                     ` (7 subsequent siblings)
  12 siblings, 0 replies; 95+ messages in thread
From: James Greenhalgh @ 2016-11-11 15:38 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, joseph, law

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


---
This patch has already been approved:
  https://gcc.gnu.org/ml/gcc-patches/2016-10/msg01554.html
---

This patch ports the logic from s390's TARGET_FLT_EVAL_METHOD to the new
target hook TARGET_C_EXCESS_PRECISION, following the guidance in this thread
https://gcc.gnu.org/ml/gcc-patches/2016-10/msg01172.html

In this patch we handle EXCESS_PRECISION_TYPE_IMPLICIT like
EXCESS_PRECISION_TYPE_FAST. This has the consequence of meaning float_t in
glibc is calculated in a different precision (double) to that indicated by
FLT_EVAL_METHOD.

---
gcc/

2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>

	* config/s390/s390.c (s390_excess_precision): New.
	(TARGET_C_EXCESS_PRECISION): Define.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0003-Patch-3-17-Implement-TARGET_C_EXCESS_PRECISION-for-s.patch --]
[-- Type: text/x-patch; name="0003-Patch-3-17-Implement-TARGET_C_EXCESS_PRECISION-for-s.patch", Size: 2326 bytes --]

diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 3f98cd8..311a7f2 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -15260,6 +15260,43 @@ s390_invalid_binary_op (int op ATTRIBUTE_UNUSED, const_tree type1, const_tree ty
   return NULL;
 }
 
+/* Implement TARGET_C_EXCESS_PRECISION.
+
+   FIXME: For historical reasons, float_t and double_t are typedef'ed to
+   double on s390, causing operations on float_t to operate in a higher
+   precision than is necessary.  However, it is not the case that SFmode
+   operations have implicit excess precision, and we generate more optimal
+   code if we let the compiler know no implicit extra precision is added.
+
+   That means when we are compiling with -fexcess-precision=fast, the value
+   we set for FLT_EVAL_METHOD will be out of line with the actual precision of
+   float_t (though they would be correct for -fexcess-precision=standard).
+
+   A complete fix would modify glibc to remove the unnecessary typedef
+   of float_t to double.  */
+
+static enum flt_eval_method
+s390_excess_precision (enum excess_precision_type type)
+{
+  switch (type)
+    {
+      case EXCESS_PRECISION_TYPE_IMPLICIT:
+      case EXCESS_PRECISION_TYPE_FAST:
+	/* The fastest type to promote to will always be the native type,
+	   whether that occurs with implicit excess precision or
+	   otherwise.  */
+	return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT;
+      case EXCESS_PRECISION_TYPE_STANDARD:
+	/* Otherwise, when we are in a standards compliant mode, to
+	   ensure consistency with the implementation in glibc, report that
+	   float is evaluated to the range and precision of double.  */
+	return FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE;
+      default:
+	gcc_unreachable ();
+    }
+  return FLT_EVAL_METHOD_UNPREDICTABLE;
+}
+
 /* Initialize GCC target structure.  */
 
 #undef  TARGET_ASM_ALIGNED_HI_OP
@@ -15320,6 +15357,9 @@ s390_invalid_binary_op (int op ATTRIBUTE_UNUSED, const_tree type1, const_tree ty
 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
 
+#undef TARGET_C_EXCESS_PRECISION
+#define TARGET_C_EXCESS_PRECISION s390_excess_precision
+
 #undef  TARGET_SCHED_ADJUST_PRIORITY
 #define TARGET_SCHED_ADJUST_PRIORITY s390_adjust_priority
 #undef TARGET_SCHED_ISSUE_RATE

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

* [Patch 1/17] Add a new target hook for describing excess precision intentions
  2016-11-11 15:38 ` [Patch v4 0/17] Add support for _Float16 to AArch64 and ARM James Greenhalgh
                     ` (4 preceding siblings ...)
  2016-11-11 15:38   ` [Patch 3/17] Implement TARGET_C_EXCESS_PRECISION for s390 James Greenhalgh
@ 2016-11-11 15:38   ` James Greenhalgh
  2016-11-11 15:38   ` [Patch 7/17] Delete TARGET_FLT_EVAL_METHOD and poison it James Greenhalgh
                     ` (6 subsequent siblings)
  12 siblings, 0 replies; 95+ messages in thread
From: James Greenhalgh @ 2016-11-11 15:38 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, joseph, law

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


---
This patch has already been approved:

  https://gcc.gnu.org/ml/gcc-patches/2016-11/msg00781.html
---

This patch introduces TARGET_C_EXCESS_PRECISION. This hook takes a tri-state
argument, one of EXCESS_PRECISION_TYPE_IMPLICIT,
EXCESS_PRECISION_TYPE_STANDARD, EXCESS_PRECISION_TYPE_FAST. Which relate to
the implicit extra precision added by the target, the excess precision that
should be guaranteed for -fexcess-precision=standard, and the excess
precision that should be added for performance under -fexcess-precision=fast .

Thanks
James

---
gcc/

2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>

	* target.def (excess_precision): New hook.
	* target.h (flt_eval_method): New.
	(excess_precision_type): Likewise.
	* targhooks.c (default_excess_precision): New.
	* targhooks.h (default_excess_precision): New.
	* doc/tm.texi.in (TARGET_C_EXCESS_PRECISION): New.
	* doc/tm.texi: Regenerate.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Patch-1-17-Add-a-new-target-hook-for-describing-exce.patch --]
[-- Type: text/x-patch; name="0001-Patch-1-17-Add-a-new-target-hook-for-describing-exce.patch", Size: 4738 bytes --]

diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index 869f858..09f8213 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -331,6 +331,24 @@ enum symbol_visibility
   VISIBILITY_INTERNAL
 };
 
+/* enums used by the targetm.excess_precision hook.  */
+
+enum flt_eval_method
+{
+  FLT_EVAL_METHOD_UNPREDICTABLE = -1,
+  FLT_EVAL_METHOD_PROMOTE_TO_FLOAT = 0,
+  FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE = 1,
+  FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE = 2,
+  FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16 = 16
+};
+
+enum excess_precision_type
+{
+  EXCESS_PRECISION_TYPE_IMPLICIT,
+  EXCESS_PRECISION_TYPE_STANDARD,
+  EXCESS_PRECISION_TYPE_FAST
+};
+
 /* Support for user-provided GGC and PCH markers.  The first parameter
    is a pointer to a pointer, the second a cookie.  */
 typedef void (*gt_pointer_operator) (void *, void *);
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 85341ae..fecb08c 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -947,6 +947,10 @@ sign-extend the result to 64 bits.  On such machines, set
 Do not define this macro if it would never modify @var{m}.
 @end defmac
 
+@deftypefn {Target Hook} {enum flt_eval_method} TARGET_C_EXCESS_PRECISION (enum excess_precision_type @var{type})
+Return a value, with the same meaning as @code{FLT_EVAL_METHOD} C that describes which excess precision should be applied.  @var{type} is either @code{EXCESS_PRECISION_TYPE_IMPLICIT}, @code{EXCESS_PRECISION_TYPE_FAST}, or @code{EXCESS_PRECISION_TYPE_STANDARD}.  For @code{EXCESS_PRECISION_TYPE_IMPLICIT}, the target should return which precision and range operations will be implictly evaluated in regardless of the excess precision explicitly added.  For @code{EXCESS_PRECISION_TYPE_STANDARD} and @code{EXCESS_PRECISION_TYPE_FAST}, the target should return the explicit excess precision that should be added depending on the value set for @option{-fexcess-precision=@r{[}standard@r{|}fast@r{]}}.
+@end deftypefn
+
 @deftypefn {Target Hook} machine_mode TARGET_PROMOTE_FUNCTION_MODE (const_tree @var{type}, machine_mode @var{mode}, int *@var{punsignedp}, const_tree @var{funtype}, int @var{for_return})
 Like @code{PROMOTE_MODE}, but it is applied to outgoing function arguments or
 function return values.  The target hook should return the new mode
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 400d574..03758b5 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -921,6 +921,8 @@ sign-extend the result to 64 bits.  On such machines, set
 Do not define this macro if it would never modify @var{m}.
 @end defmac
 
+@hook TARGET_C_EXCESS_PRECISION
+
 @hook TARGET_PROMOTE_FUNCTION_MODE
 
 @defmac PARM_BOUNDARY
diff --git a/gcc/target.def b/gcc/target.def
index caeeff9..bf4fb29 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -5452,6 +5452,23 @@ DEFHOOK_UNDOC
  machine_mode, (char c),
  default_mode_for_suffix)
 
+DEFHOOK
+(excess_precision,
+ "Return a value, with the same meaning as @code{FLT_EVAL_METHOD} C that\
+ describes which excess precision should be applied.  @var{type} is\
+ either @code{EXCESS_PRECISION_TYPE_IMPLICIT},\
+ @code{EXCESS_PRECISION_TYPE_FAST}, or\
+ @code{EXCESS_PRECISION_TYPE_STANDARD}.  For\
+ @code{EXCESS_PRECISION_TYPE_IMPLICIT}, the target should return which\
+ precision and range operations will be implictly evaluated in regardless\
+ of the excess precision explicitly added.  For\
+ @code{EXCESS_PRECISION_TYPE_STANDARD} and\
+ @code{EXCESS_PRECISION_TYPE_FAST}, the target should return the\
+ explicit excess precision that should be added depending on the\
+ value set for @option{-fexcess-precision=@r{[}standard@r{|}fast@r{]}}.",
+ enum flt_eval_method, (enum excess_precision_type type),
+ default_excess_precision)
+
 HOOK_VECTOR_END (c)
 
 /* Functions specific to the C++ frontend.  */
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index 866747a..73e1c25 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -2135,4 +2135,12 @@ default_min_arithmetic_precision (void)
   return WORD_REGISTER_OPERATIONS ? BITS_PER_WORD : BITS_PER_UNIT;
 }
 
+/* Default implementation of TARGET_C_EXCESS_PRECISION.  */
+
+enum flt_eval_method
+default_excess_precision (enum excess_precision_type ATTRIBUTE_UNUSED)
+{
+  return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT;
+}
+
 #include "gt-targhooks.h"
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index 94f5e31..e00da60 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -263,4 +263,7 @@ extern bool default_optab_supported_p (int, machine_mode, machine_mode,
 extern unsigned int default_max_noce_ifcvt_seq_cost (edge);
 extern unsigned int default_min_arithmetic_precision (void);
 
+extern enum flt_eval_method
+default_excess_precision (enum excess_precision_type ATTRIBUTE_UNUSED);
+
 #endif /* GCC_TARGHOOKS_H */

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

* [Patch 6/17] Migrate excess precision logic to use TARGET_EXCESS_PRECISION
  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 5/17] Add -fpermitted-flt-eval-methods=[c11|ts-18661-3] James Greenhalgh
  2016-11-11 15:38   ` [Patch 4/17] Implement TARGET_C_EXCESS_PRECISION for m68k James Greenhalgh
@ 2016-11-11 15:38   ` James Greenhalgh
  2016-11-11 15:38   ` [Patch 2/17] Implement TARGET_C_EXCESS_PRECISION for i386 James Greenhalgh
                     ` (9 subsequent siblings)
  12 siblings, 0 replies; 95+ messages in thread
From: James Greenhalgh @ 2016-11-11 15:38 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, joseph, law

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


---
This patch has already been approved:
  https://gcc.gnu.org/ml/gcc-patches/2016-11/msg00784.html
---

This patch moves the logic for excess precision from using the
TARGET_FLT_EVAL_METHOD macro to the TARGET_EXCESS_PRECISION hook
introduced earlier in the patch series.

Briefly; we have four things to change.

  1) The logic in tree.c::excess_precision_type .
  Here we want to ask the target which excess preicion it would like for
  whichever of -fexcess-precision=standard or -fexcess-precision=fast is
  in use, then apply that.

  2) The logic in c-family/c-cppbuiltin.c::c_cpp_flt_eval_method_iec_559 .
  We want to update this to return TRUE if the excess precision proposed
  by the front-end is the excess precision that will actually be used.

  3) The logic in c-family/c-cppbuiltin.c::c_cpp_builtin for setting
  __FLT_EVAL_METHOD__ .
  Which is now little more complicated, and makes use of
  -fpermitted-flt-eval-methods from patch 5. We also set
  __FLT_EVAL_METHOD_TS_18661_3__.

  4) The logic in c-family/c-cppbuiltin.c::c_cpp_builtin for setting
  __LIBGCC_*_EXCESS_PRECISION__ .

Having moved the logic in to those areas, we can simplify
toplev.c::init_excess_precision , which now only retains the assert that
-fexcess-precision=default has been rewritten by the language front-end, and
the set from the command-line variable to the internal variable.

Finally we need to update <float.h> to return the appropriate value for
FLT_EVAL_METHOD based on the new macros we add.

The documentation in invoke.texi is not quite right for the impact of
-fexcess-precision, so I've rewritten the text to read a little more
generic.

Thanks,
James

---
gcc/

2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>

	* toplev.c (init_excess_precision): Delete most logic.
	* tree.c (excess_precision_type): Rewrite to use
	TARGET_EXCESS_PRECISION.
	* doc/invoke.texi (-fexcess-precision): Document behaviour in a
	more generic fashion.
	* ginclude/float.h: Wrap definition of FLT_EVAL_METHOD in
	__STDC_WANT_IEC_60559_TYPES_EXT__.

gcc/c-family/

2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>

	* c-common.c (excess_precision_mode_join): New.
	(c_ts18661_flt_eval_method): New.
	(c_c11_flt_eval_method): Likewise.
	(c_flt_eval_method): Likewise.
	* c-common.h (excess_precision_mode_join): New.
	(c_flt_eval_method): Likewise.
	* c-cppbuiltin.c (c_cpp_flt_eval_method_iec_559): New.
	(cpp_iec_559_value): Call it.
	(c_cpp_builtins): Modify logic for __LIBGCC_*_EXCESS_PRECISION__,
	call c_flt_eval_method to set __FLT_EVAL_METHOD__ and
	__FLT_EVAL_METHOD_TS_18661_3__.

gcc/testsuite/

2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>

	* gcc.dg/fpermitted-flt-eval-methods_3.c: New.
	* gcc.dg/fpermitted-flt-eval-methods_4.c: Likewise.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0006-Patch-6-17-Migrate-excess-precision-logic-to-use-TAR.patch --]
[-- Type: text/x-patch; name="0006-Patch-6-17-Migrate-excess-precision-logic-to-use-TAR.patch", Size: 22420 bytes --]

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 307862b..9f0b4a6 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -7944,4 +7944,86 @@ cb_get_suggestion (cpp_reader *, const char *goal,
   return bm.get_best_meaningful_candidate ();
 }
 
+/* Return the latice point which is the wider of the two FLT_EVAL_METHOD
+   modes X, Y.  This isn't just  >, as the FLT_EVAL_METHOD values added
+   by C TS 18661-3 for interchange  types that are computed in their
+   native precision are larger than the C11 values for evaluating in the
+   precision of float/double/long double.  If either mode is
+   FLT_EVAL_METHOD_UNPREDICTABLE, return that.  */
+
+enum flt_eval_method
+excess_precision_mode_join (enum flt_eval_method x,
+			    enum flt_eval_method y)
+{
+  if (x == FLT_EVAL_METHOD_UNPREDICTABLE
+      || y == FLT_EVAL_METHOD_UNPREDICTABLE)
+    return FLT_EVAL_METHOD_UNPREDICTABLE;
+
+  /* GCC only supports one interchange type right now, _Float16.  If
+     we're evaluating _Float16 in 16-bit precision, then flt_eval_method
+     will be FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16.  */
+  if (x == FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16)
+    return y;
+  if (y == FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16)
+    return x;
+
+  /* Other values for flt_eval_method are directly comparable, and we want
+     the maximum.  */
+  return MAX (x, y);
+}
+
+/* Return the value that should be set for FLT_EVAL_METHOD in the
+   context of ISO/IEC TS 18861-3.
+
+   This relates to the effective excess precision seen by the user,
+   which is the join point of the precision the target requests for
+   -fexcess-precision={standard,fast} and the implicit excess precision
+   the target uses.  */
+
+static enum flt_eval_method
+c_ts18661_flt_eval_method (void)
+{
+  enum flt_eval_method implicit
+    = targetm.c.excess_precision (EXCESS_PRECISION_TYPE_IMPLICIT);
+
+  enum excess_precision_type flag_type
+    = (flag_excess_precision_cmdline == EXCESS_PRECISION_STANDARD
+       ? EXCESS_PRECISION_TYPE_STANDARD
+       : EXCESS_PRECISION_TYPE_FAST);
+
+  enum flt_eval_method requested
+    = targetm.c.excess_precision (flag_type);
+
+  return excess_precision_mode_join (implicit, requested);
+}
+
+/* As c_cpp_ts18661_flt_eval_method, but clamps the expected values to
+   those that were permitted by C11.  That is to say, eliminates
+   FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16.  */
+
+static enum flt_eval_method
+c_c11_flt_eval_method (void)
+{
+  return excess_precision_mode_join (c_ts18661_flt_eval_method (),
+				     FLT_EVAL_METHOD_PROMOTE_TO_FLOAT);
+}
+
+/* Return the value that should be set for FLT_EVAL_METHOD.
+   MAYBE_C11_ONLY_P is TRUE if we should check
+   FLAG_PERMITTED_EVAL_METHODS as to whether we should limit the possible
+   values we can return to those from C99/C11, and FALSE otherwise.
+   See the comments on c_ts18661_flt_eval_method for what value we choose
+   to set here.  */
+
+int
+c_flt_eval_method (bool maybe_c11_only_p)
+{
+  if (maybe_c11_only_p
+      && flag_permitted_flt_eval_methods
+	  == PERMITTED_FLT_EVAL_METHODS_C11)
+    return c_c11_flt_eval_method ();
+  else
+    return c_ts18661_flt_eval_method ();
+}
+
 #include "gt-c-family-c-common.h"
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 547bab2..602a07e 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1539,6 +1539,11 @@ extern int tm_attr_to_mask (tree);
 extern tree tm_mask_to_attr (int);
 extern tree find_tm_attribute (tree);
 
+extern enum flt_eval_method
+excess_precision_mode_join (enum flt_eval_method, enum flt_eval_method);
+
+extern int c_flt_eval_method (bool ts18661_p);
+
 #if CHECKING_P
 namespace selftest {
   extern void c_format_c_tests (void);
diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
index 70eade1..a735ca0 100644
--- a/gcc/c-family/c-cppbuiltin.c
+++ b/gcc/c-family/c-cppbuiltin.c
@@ -728,6 +728,31 @@ cpp_atomic_builtins (cpp_reader *pfile)
 			(have_swap[psize]? 2 : 1));
 }
 
+/* Return TRUE if the implicit excess precision in which the back-end will
+   compute floating-point calculations is not more than the explicit
+   excess precision that the front-end will apply under
+   -fexcess-precision=[standard|fast].
+
+   More intuitively, return TRUE if the excess precision proposed by the
+   front-end is the excess precision that will actually be used.  */
+
+static bool
+c_cpp_flt_eval_method_iec_559 (void)
+{
+  enum excess_precision_type front_end_ept
+    = (flag_excess_precision_cmdline == EXCESS_PRECISION_STANDARD
+       ? EXCESS_PRECISION_TYPE_STANDARD
+       : EXCESS_PRECISION_TYPE_FAST);
+
+  enum flt_eval_method back_end
+    = targetm.c.excess_precision (EXCESS_PRECISION_TYPE_IMPLICIT);
+
+  enum flt_eval_method front_end
+    = targetm.c.excess_precision (front_end_ept);
+
+  return excess_precision_mode_join (front_end, back_end) == front_end;
+}
+
 /* Return the value for __GCC_IEC_559.  */
 static int
 cpp_iec_559_value (void)
@@ -770,16 +795,17 @@ cpp_iec_559_value (void)
       || !dfmt->has_signed_zero)
     ret = 0;
 
-  /* In strict C standards conformance mode, consider unpredictable
-     excess precision to mean lack of IEEE 754 support.  The same
-     applies to unpredictable contraction.  For C++, and outside
-     strict conformance mode, do not consider these options to mean
-     lack of IEEE 754 support.  */
+  /* In strict C standards conformance mode, consider a back-end providing
+     more implicit excess precision than the explicit excess precision
+     the front-end options would require to mean a lack of IEEE 754
+     support.  For C++, and outside strict conformance mode, do not consider
+     this to mean a lack of IEEE 754 support.  */
+
   if (flag_iso
       && !c_dialect_cxx ()
-      && TARGET_FLT_EVAL_METHOD != 0
-      && flag_excess_precision_cmdline != EXCESS_PRECISION_STANDARD)
+      && !c_cpp_flt_eval_method_iec_559 ())
     ret = 0;
+
   if (flag_iso
       && !c_dialect_cxx ()
       && flag_fp_contract_mode == FP_CONTRACT_FAST)
@@ -1044,9 +1070,22 @@ c_cpp_builtins (cpp_reader *pfile)
   builtin_define_with_int_value ("__GCC_IEC_559_COMPLEX",
 				 cpp_iec_559_complex_value ());
 
-  /* float.h needs to know this.  */
+  /* float.h needs these to correctly set FLT_EVAL_METHOD
+
+     We define two values:
+
+     __FLT_EVAL_METHOD__
+       Which, depending on the value given for
+       -fpermitted-flt-eval-methods, may be limited to only those values
+       for FLT_EVAL_METHOD defined in C99/C11.
+
+     __FLT_EVAL_METHOD_TS_18661_3__
+       Which always permits the values for FLT_EVAL_METHOD defined in
+       ISO/IEC TS 18661-3.  */
   builtin_define_with_int_value ("__FLT_EVAL_METHOD__",
-				 TARGET_FLT_EVAL_METHOD);
+				 c_flt_eval_method (true));
+  builtin_define_with_int_value ("__FLT_EVAL_METHOD_TS_18661_3__",
+				 c_flt_eval_method (false));
 
   /* And decfloat.h needs this.  */
   builtin_define_with_int_value ("__DEC_EVAL_METHOD__",
@@ -1187,25 +1226,38 @@ c_cpp_builtins (cpp_reader *pfile)
 	      gcc_assert (found_suffix);
 	    }
 	  builtin_define_with_value (macro_name, suffix, 0);
+
+	  /* The way __LIBGCC_*_EXCESS_PRECISION__ is used is about
+	     eliminating excess precision from results assigned to
+	     variables - meaning it should be about the implicit excess
+	     precision only.  */
 	  bool excess_precision = false;
-	  if (TARGET_FLT_EVAL_METHOD != 0
-	      && mode != TYPE_MODE (long_double_type_node)
-	      && (mode == TYPE_MODE (float_type_node)
-		  || mode == TYPE_MODE (double_type_node)))
-	    switch (TARGET_FLT_EVAL_METHOD)
-	      {
-	      case -1:
-	      case 2:
-		excess_precision = true;
-		break;
-
-	      case 1:
-		excess_precision = mode == TYPE_MODE (float_type_node);
-		break;
-
-	      default:
-		gcc_unreachable ();
-	      }
+	  machine_mode float16_type_mode = (float16_type_node
+					    ? TYPE_MODE (float16_type_node)
+					    : VOIDmode);
+	  switch (targetm.c.excess_precision
+		    (EXCESS_PRECISION_TYPE_IMPLICIT))
+	    {
+	    case FLT_EVAL_METHOD_UNPREDICTABLE:
+	    case FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE:
+	      excess_precision = (mode == float16_type_mode
+				  || mode == TYPE_MODE (float_type_node)
+				  || mode == TYPE_MODE (double_type_node));
+	      break;
+
+	    case FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE:
+	      excess_precision = (mode == float16_type_mode
+				  || mode == TYPE_MODE (float_type_node));
+	      break;
+	    case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT:
+	      excess_precision = mode == float16_type_mode;
+	      break;
+	    case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16:
+	      excess_precision = false;
+	      break;
+	    default:
+	      gcc_unreachable ();
+	    }
 	  macro_name = (char *) alloca (strlen (name)
 					+ sizeof ("__LIBGCC__EXCESS_"
 						  "PRECISION__"));
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 75ff8ec..a1eb168 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -8961,15 +8961,14 @@ them to store all pertinent intermediate computations into variables.
 @item -fexcess-precision=@var{style}
 @opindex fexcess-precision
 This option allows further control over excess precision on machines
-where floating-point registers have more precision than the IEEE
-@code{float} and @code{double} types and the processor does not
-support operations rounding to those types.  By default,
-@option{-fexcess-precision=fast} is in effect; this means that
-operations are carried out in the precision of the registers and that
-it is unpredictable when rounding to the types specified in the source
-code takes place.  When compiling C, if
-@option{-fexcess-precision=standard} is specified then excess
-precision follows the rules specified in ISO C99; in particular,
+where floating-point operations occur in a format with more precision or
+range than the IEEE standard and interchange floating-point types.  By
+default, @option{-fexcess-precision=fast} is in effect; this means that
+operations may be carried out in a wider precision than the types specified
+in the source if that would result in faster code, and it is unpredictable
+when rounding to the types specified in the source code takes place.
+When compiling C, if @option{-fexcess-precision=standard} is specified then
+excess precision follows the rules specified in ISO C99; in particular,
 both casts and assignments cause values to be rounded to their
 semantic types (whereas @option{-ffloat-store} only affects
 assignments).  This option is enabled by default for C if a strict
diff --git a/gcc/ginclude/float.h b/gcc/ginclude/float.h
index 421f735..3df2889 100644
--- a/gcc/ginclude/float.h
+++ b/gcc/ginclude/float.h
@@ -129,21 +129,73 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
 #if (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) \
      || (defined (__cplusplus) && __cplusplus >= 201103L)
-/* The floating-point expression evaluation method.
-        -1  indeterminate
-         0  evaluate all operations and constants just to the range and
-            precision of the type
-         1  evaluate operations and constants of type float and double
-            to the range and precision of the double type, evaluate
-            long double operations and constants to the range and
-            precision of the long double type
-         2  evaluate all operations and constants to the range and
-            precision of the long double type
+/* The floating-point expression evaluation method.  The precise
+   definitions of these values are generalised to include support for
+   the interchange and extended types defined in ISO/IEC TS 18661-3.
+   Prior to this (for C99/C11) the definitions were:
+
+	-1  indeterminate
+	 0  evaluate all operations and constants just to the range and
+	    precision of the type
+	 1  evaluate operations and constants of type float and double
+	    to the range and precision of the double type, evaluate
+	    long double operations and constants to the range and
+	    precision of the long double type
+	 2  evaluate all operations and constants to the range and
+	    precision of the long double type
+
+   The TS 18661-3 definitions are:
+
+	-1  indeterminate
+	 0  evaluate all operations and constants, whose semantic type has
+	    at most the range and precision of float, to the range and
+	    precision of float; evaluate all other operations and constants
+	    to the range and precision of the semantic type.
+	 1  evaluate all operations and constants, whose semantic type has
+	    at most the range and precision of double, to the range and
+	    precision of double; evaluate all other operations and constants
+	    to the range and precision of the semantic type.
+	 2  evaluate all operations and constants, whose semantic type has
+	    at most the range and precision of long double, to the range and
+	    precision of long double; evaluate all other operations and
+	    constants to the range and precision of the semantic type.
+	 N  where _FloatN  is a supported interchange floating type
+	    evaluate all operations and constants, whose semantic type has
+	    at most the range and precision of the _FloatN type, to the
+	    range and precision of the _FloatN type; evaluate all other
+	    operations and constants to the range and precision of the
+	    semantic type.
+	 N + 1, where _FloatNx is a supported extended floating type
+	    evaluate operations and constants, whose semantic type has at
+	    most the range and precision of the _FloatNx type, to the range
+	    and precision of the _FloatNx type; evaluate all other
+	    operations and constants to the range and precision of the
+	    semantic type.
+
+   The compiler predefines two macros:
+
+      __FLT_EVAL_METHOD__
+      Which, depending on the value given for
+      -fpermitted-flt-eval-methods, may be limited to only those values
+      for FLT_EVAL_METHOD defined in C99/C11.
+
+     __FLT_EVAL_METHOD_TS_18661_3__
+      Which always permits the values for FLT_EVAL_METHOD defined in
+      ISO/IEC TS 18661-3.
+
+     Here we want to use __FLT_EVAL_METHOD__, unless
+     __STDC_WANT_IEC_60559_TYPES_EXT__ is defined, in which case the user
+     is specifically asking for the ISO/IEC TS 18661-3 types, so we use
+     __FLT_EVAL_METHOD_TS_18661_3__.
 
    ??? This ought to change with the setting of the fp control word;
    the value provided by the compiler assumes the widest setting.  */
 #undef FLT_EVAL_METHOD
+#ifdef __STDC_WANT_IEC_60559_TYPES_EXT__
+#define FLT_EVAL_METHOD __FLT_EVAL_METHOD_TS_18661_3__
+#else
 #define FLT_EVAL_METHOD	__FLT_EVAL_METHOD__
+#endif
 
 /* Number of decimal digits, n, such that any floating-point number in the
    widest supported floating type with pmax radix b digits can be rounded
diff --git a/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_3.c b/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_3.c
new file mode 100644
index 0000000..c7bd756
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_3.c
@@ -0,0 +1,21 @@
+/* { dg-do run } */
+/* { dg-options "-std=c11" } */
+
+/* Test that when compiling with -std=c11, we only see the C99/C11 values
+   for FLT_EVAL_METHOD.  */
+
+#include <float.h>
+
+int main (int argc, char** argv)
+{
+  switch (FLT_EVAL_METHOD)
+    {
+      case 0:
+      case 1:
+      case 2:
+      case -1:
+	return 0;
+      default:
+	return 1;
+    }
+}
diff --git a/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_4.c b/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_4.c
new file mode 100644
index 0000000..a7bbb65
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_4.c
@@ -0,0 +1,25 @@
+/* { dg-do run } */
+/* { dg-options "-std=c11" } */
+
+/* Test that when compiling with -std=c11 and defining
+   __STDC_WANT_IEC_60559_TYPES_EXT__, we only see the ISO/IEC TS
+   18661-3 values for FLT_EVAL_METHOD.  */
+
+#define __STDC_WANT_IEC_60559_TYPES_EXT__
+
+#include <float.h>
+
+int main (int argc, char** argv)
+{
+  switch (__FLT_EVAL_METHOD__)
+    {
+      case 0:
+      case 1:
+      case 2:
+      case 16:
+      case -1:
+	return 0;
+      default:
+	return 1;
+    }
+}
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 59b84eb..d02ca6c 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -1685,41 +1685,17 @@ backend_init (void)
   init_regs ();
 }
 
-/* Initialize excess precision settings.  */
+/* Initialize excess precision settings.
+
+   We have no need to modify anything here, just keep track of what the
+   user requested.  We'll figure out any appropriate relaxations
+   later.  */
+
 static void
 init_excess_precision (void)
 {
-  /* Adjust excess precision handling based on the target options.  If
-     the front end cannot handle it, flag_excess_precision_cmdline
-     will already have been set accordingly in the post_options
-     hook.  */
   gcc_assert (flag_excess_precision_cmdline != EXCESS_PRECISION_DEFAULT);
   flag_excess_precision = flag_excess_precision_cmdline;
-  if (flag_unsafe_math_optimizations)
-    flag_excess_precision = EXCESS_PRECISION_FAST;
-  if (flag_excess_precision == EXCESS_PRECISION_STANDARD)
-    {
-      int flt_eval_method = TARGET_FLT_EVAL_METHOD;
-      switch (flt_eval_method)
-	{
-	case -1:
-	case 0:
-	  /* Either the target acts unpredictably (-1) or has all the
-	     operations required not to have excess precision (0).  */
-	  flag_excess_precision = EXCESS_PRECISION_FAST;
-	  break;
-	case 1:
-	case 2:
-	  /* In these cases, predictable excess precision makes
-	     sense.  */
-	  break;
-	default:
-	  /* Any other implementation-defined FLT_EVAL_METHOD values
-	     require the compiler to handle the associated excess
-	     precision rules in excess_precision_type.  */
-	  gcc_unreachable ();
-	}
-    }
 }
 
 /* Initialize things that are both lang-dependent and target-dependent.
diff --git a/gcc/tree.c b/gcc/tree.c
index c155d56..0e497fd 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -8852,50 +8852,99 @@ build_complex_type (tree component_type, bool named)
 tree
 excess_precision_type (tree type)
 {
-  if (flag_excess_precision != EXCESS_PRECISION_FAST)
+  /* The target can give two different responses to the question of
+     which excess precision mode it would like depending on whether we
+     are in -fexcess-precision=standard or -fexcess-precision=fast.  */
+
+  enum excess_precision_type requested_type
+    = (flag_excess_precision == EXCESS_PRECISION_FAST
+       ? EXCESS_PRECISION_TYPE_FAST
+       : EXCESS_PRECISION_TYPE_STANDARD);
+
+  enum flt_eval_method target_flt_eval_method
+    = targetm.c.excess_precision (requested_type);
+
+  /* The target should not ask for unpredictable float evaluation (though
+     it might advertise that implicitly the evaluation is unpredictable,
+     but we don't care about that here, it will have been reported
+     elsewhere).  If it does ask for unpredictable evaluation, we have
+     nothing to do here.  */
+  gcc_assert (target_flt_eval_method != FLT_EVAL_METHOD_UNPREDICTABLE);
+
+  /* Nothing to do.  The target has asked for all types we know about
+     to be computed with their native precision and range.  */
+  if (target_flt_eval_method == FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16)
+    return NULL_TREE;
+
+  /* The target will promote this type in a target-dependent way, so excess
+     precision ought to leave it alone.  */
+  if (targetm.promoted_type (type) != NULL_TREE)
+    return NULL_TREE;
+
+  machine_mode float16_type_mode = (float16_type_node
+				    ? TYPE_MODE (float16_type_node)
+				    : VOIDmode);
+  machine_mode float_type_mode = TYPE_MODE (float_type_node);
+  machine_mode double_type_mode = TYPE_MODE (double_type_node);
+
+  switch (TREE_CODE (type))
     {
-      int flt_eval_method = TARGET_FLT_EVAL_METHOD;
-      switch (TREE_CODE (type))
-	{
-	case REAL_TYPE:
-	  switch (flt_eval_method)
-	    {
-	    case 1:
-	      if (TYPE_MODE (type) == TYPE_MODE (float_type_node))
-		return double_type_node;
-	      break;
-	    case 2:
-	      if (TYPE_MODE (type) == TYPE_MODE (float_type_node)
-		  || TYPE_MODE (type) == TYPE_MODE (double_type_node))
-		return long_double_type_node;
-	      break;
-	    default:
-	      gcc_unreachable ();
-	    }
-	  break;
-	case COMPLEX_TYPE:
-	  if (TREE_CODE (TREE_TYPE (type)) != REAL_TYPE)
-	    return NULL_TREE;
-	  switch (flt_eval_method)
-	    {
-	    case 1:
-	      if (TYPE_MODE (TREE_TYPE (type)) == TYPE_MODE (float_type_node))
-		return complex_double_type_node;
-	      break;
-	    case 2:
-	      if (TYPE_MODE (TREE_TYPE (type)) == TYPE_MODE (float_type_node)
-		  || (TYPE_MODE (TREE_TYPE (type))
-		      == TYPE_MODE (double_type_node)))
-		return complex_long_double_type_node;
-	      break;
-	    default:
-	      gcc_unreachable ();
-	    }
-	  break;
-	default:
-	  break;
-	}
+    case REAL_TYPE:
+      {
+	machine_mode type_mode = TYPE_MODE (type);
+	switch (target_flt_eval_method)
+	  {
+	  case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT:
+	    if (type_mode == float16_type_mode)
+	      return float_type_node;
+	    break;
+	  case FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE:
+	    if (type_mode == float16_type_mode
+		|| type_mode == float_type_mode)
+	      return double_type_node;
+	    break;
+	  case FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE:
+	    if (type_mode == float16_type_mode
+		|| type_mode == float_type_mode
+		|| type_mode == double_type_mode)
+	      return long_double_type_node;
+	    break;
+	  default:
+	    gcc_unreachable ();
+	  }
+	break;
+      }
+    case COMPLEX_TYPE:
+      {
+	if (TREE_CODE (TREE_TYPE (type)) != REAL_TYPE)
+	  return NULL_TREE;
+	machine_mode type_mode = TYPE_MODE (TREE_TYPE (type));
+	switch (target_flt_eval_method)
+	  {
+	  case FLT_EVAL_METHOD_PROMOTE_TO_FLOAT:
+	    if (type_mode == float16_type_mode)
+	      return complex_float_type_node;
+	    break;
+	  case FLT_EVAL_METHOD_PROMOTE_TO_DOUBLE:
+	    if (type_mode == float16_type_mode
+		|| type_mode == float_type_mode)
+	      return complex_double_type_node;
+	    break;
+	  case FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE:
+	    if (type_mode == float16_type_mode
+		|| type_mode == float_type_mode
+		|| type_mode == double_type_mode)
+	      return complex_long_double_type_node;
+	    break;
+	  default:
+	    gcc_unreachable ();
+	  }
+	break;
+      }
+    default:
+      break;
     }
+
   return NULL_TREE;
 }
 \f

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

* [Patch 4/17] Implement TARGET_C_EXCESS_PRECISION for m68k
  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 5/17] Add -fpermitted-flt-eval-methods=[c11|ts-18661-3] James Greenhalgh
@ 2016-11-11 15:38   ` James Greenhalgh
  2016-11-11 15:38   ` [Patch 6/17] Migrate excess precision logic to use TARGET_EXCESS_PRECISION James Greenhalgh
                     ` (10 subsequent siblings)
  12 siblings, 0 replies; 95+ messages in thread
From: James Greenhalgh @ 2016-11-11 15:38 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, joseph, law

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


---
This patch was approved in the original form, and the delta to here would
apply under the obvious rule:
  https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02414.html
---

On Fri, Sep 30, 2016 at 11:28:28AM -0600, Jeff Law wrote:
> On 09/30/2016 11:01 AM, James Greenhalgh wrote:
> >
> >Hi,
> >
> >This patch ports the logic from m68k's TARGET_FLT_EVAL_METHOD to the new
> >target hook TARGET_C_EXCESS_PRECISION.
> >
> >Patch tested by building an m68k-none-elf toolchain and running
> >m68k.exp (without the ability to execute) with no regressions, and manually
> >inspecting the output assembly code when compiling
> >testsuite/gcc.target/i386/excess-precision* to show no difference in
> >code-generation.
> >
> >OK?
> >
> >Thanks,
> >James
> >
> >---
> >gcc/
> >
> >2016-09-30  James Greenhalgh  <james.greenhalgh@arm.com>
> >
> >	* config/m68k/m68k.c (m68k_excess_precision): New.
> >	(TARGET_C_EXCESS_PRECISION): Define.
> OK when prereqs are approved.  Similarly for other targets where you
> needed to add this hook.

Thanks Jeff, Andreas,

I spotted a very silly bug when I was retesting this patch set - when I
swapped the namespace for the new traget macro it changed from
TARGET_EXCESS_PRECISION to TARGET_C_EXCESS_PRECISION but I failed to
update the m68k patch to reflect that.

This second revision fixes that (obvious) oversight.

Thanks,
James

---
gcc/

2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>

	* config/m68k/m68k.c (m68k_excess_precision): New.
	(TARGET_C_EXCESS_PRECISION): Define.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0004-Patch-4-17-Implement-TARGET_C_EXCESS_PRECISION-for-m.patch --]
[-- Type: text/x-patch; name="0004-Patch-4-17-Implement-TARGET_C_EXCESS_PRECISION-for-m.patch", Size: 2145 bytes --]

diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
index ce56692..22165d6 100644
--- a/gcc/config/m68k/m68k.c
+++ b/gcc/config/m68k/m68k.c
@@ -183,6 +183,8 @@ static rtx m68k_function_arg (cumulative_args_t, machine_mode,
 static bool m68k_cannot_force_const_mem (machine_mode mode, rtx x);
 static bool m68k_output_addr_const_extra (FILE *, rtx);
 static void m68k_init_sync_libfuncs (void) ATTRIBUTE_UNUSED;
+static enum flt_eval_method
+m68k_excess_precision (enum excess_precision_type);
 \f
 /* Initialize the GCC target structure.  */
 
@@ -323,6 +325,9 @@ static void m68k_init_sync_libfuncs (void) ATTRIBUTE_UNUSED;
 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA m68k_output_addr_const_extra
 
+#undef TARGET_C_EXCESS_PRECISION
+#define TARGET_C_EXCESS_PRECISION m68k_excess_precision
+
 /* The value stored by TAS.  */
 #undef TARGET_ATOMIC_TEST_AND_SET_TRUEVAL
 #define TARGET_ATOMIC_TEST_AND_SET_TRUEVAL 128
@@ -6532,4 +6537,36 @@ m68k_epilogue_uses (int regno ATTRIBUTE_UNUSED)
 	      == m68k_fk_interrupt_handler));
 }
 
+
+/* Implement TARGET_C_EXCESS_PRECISION.
+
+   Set the value of FLT_EVAL_METHOD in float.h.  When using 68040 fp
+   instructions, we get proper intermediate rounding, otherwise we
+   get extended precision results.  */
+
+static enum flt_eval_method
+m68k_excess_precision (enum excess_precision_type type)
+{
+  switch (type)
+    {
+      case EXCESS_PRECISION_TYPE_FAST:
+	/* The fastest type to promote to will always be the native type,
+	   whether that occurs with implicit excess precision or
+	   otherwise.  */
+	return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT;
+      case EXCESS_PRECISION_TYPE_STANDARD:
+      case EXCESS_PRECISION_TYPE_IMPLICIT:
+	/* Otherwise, the excess precision we want when we are
+	   in a standards compliant mode, and the implicit precision we
+	   provide can be identical.  */
+	if (TARGET_68040 || ! TARGET_68881)
+	  return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT;
+
+	return FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE;
+      default:
+	gcc_unreachable ();
+    }
+  return FLT_EVAL_METHOD_UNPREDICTABLE;
+}
+
 #include "gt-m68k.h"

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

* [Patch 7/17] Delete TARGET_FLT_EVAL_METHOD and poison it.
  2016-11-11 15:38 ` [Patch v4 0/17] Add support for _Float16 to AArch64 and ARM James Greenhalgh
                     ` (5 preceding siblings ...)
  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   ` James Greenhalgh
  2016-11-11 15:39   ` [Patch 8/17] Make _Float16 available if HFmode is available James Greenhalgh
                     ` (5 subsequent siblings)
  12 siblings, 0 replies; 95+ messages in thread
From: James Greenhalgh @ 2016-11-11 15:38 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, joseph, law

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


---
This patch was approved:

  https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02401.html
---

Hi,

We've removed all uses of TARGET_FLT_EVAL_METHOD, so we can remove it
and poison it.

Bootstrapped and tested on x86-64 and AArch64. Tested on s390 and m68k
to the best of my ability (no execute tests).

Thanks,
James

---
gcc/

2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>

	* config/s390/s390.h (TARGET_FLT_EVAL_METHOD): Delete.
	* config/m68k/m68k.h (TARGET_FLT_EVAL_METHOD): Delete.
	* config/i386/i386.h (TARGET_FLT_EVAL_METHOD): Delete.
	* defaults.h (TARGET_FLT_EVAL_METHOD): Delete.
	* doc/tm.texi.in (TARGET_FLT_EVAL_METHOD): Delete.
	* doc/tm.texi: Regenerate.
	* system.h (TARGET_FLT_EVAL_METHOD): Poison.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0007-Patch-7-17-Delete-TARGET_FLT_EVAL_METHOD-and-poison-.patch --]
[-- Type: text/x-patch; name="0007-Patch-7-17-Delete-TARGET_FLT_EVAL_METHOD-and-poison-.patch", Size: 4650 bytes --]

diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index add7a64..a2fcdcc 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -686,17 +686,6 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
   SUBTARGET_EXTRA_SPECS
 \f
 
-/* Set the value of FLT_EVAL_METHOD in float.h.  When using only the
-   FPU, assume that the fpcw is set to extended precision; when using
-   only SSE, rounding is correct; when using both SSE and the FPU,
-   the rounding precision is indeterminate, since either may be chosen
-   apparently at random.  */
-#define TARGET_FLT_EVAL_METHOD						\
-  (TARGET_80387								\
-   ? (TARGET_MIX_SSE_I387 ? -1						\
-      : (TARGET_SSE_MATH ? (TARGET_SSE2 ? 0 : -1) : 2))			\
-   : 0)
-
 /* Whether to allow x87 floating-point arithmetic on MODE (one of
    SFmode, DFmode and XFmode) in the current excess precision
    configuration.  */
diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h
index 2aa858f..2021e9d 100644
--- a/gcc/config/m68k/m68k.h
+++ b/gcc/config/m68k/m68k.h
@@ -281,11 +281,6 @@ along with GCC; see the file COPYING3.  If not see
 #define LONG_DOUBLE_TYPE_SIZE			\
   ((TARGET_COLDFIRE || TARGET_FIDOA) ? 64 : 80)
 
-/* Set the value of FLT_EVAL_METHOD in float.h.  When using 68040 fp
-   instructions, we get proper intermediate rounding, otherwise we
-   get extended precision results.  */
-#define TARGET_FLT_EVAL_METHOD ((TARGET_68040 || ! TARGET_68881) ? 0 : 2)
-
 #define BITS_BIG_ENDIAN 1
 #define BYTES_BIG_ENDIAN 1
 #define WORDS_BIG_ENDIAN 1
diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h
index 501c8e4..6be4d34 100644
--- a/gcc/config/s390/s390.h
+++ b/gcc/config/s390/s390.h
@@ -247,11 +247,6 @@ extern const char *s390_host_detect_local_cpu (int argc, const char **argv);
 #define S390_TDC_INFINITY (S390_TDC_POSITIVE_INFINITY \
 			  | S390_TDC_NEGATIVE_INFINITY )
 
-/* This is used by float.h to define the float_t and double_t data
-   types.  For historical reasons both are double on s390 what cannot
-   be changed anymore.  */
-#define TARGET_FLT_EVAL_METHOD 1
-
 /* Target machine storage layout.  */
 
 /* Everything is big-endian.  */
diff --git a/gcc/defaults.h b/gcc/defaults.h
index 9c40002..2536f76 100644
--- a/gcc/defaults.h
+++ b/gcc/defaults.h
@@ -942,9 +942,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #define REG_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
 #endif
 
-#ifndef TARGET_FLT_EVAL_METHOD
-#define TARGET_FLT_EVAL_METHOD 0
-#endif
 
 #ifndef TARGET_DEC_EVAL_METHOD
 #define TARGET_DEC_EVAL_METHOD 2
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index fecb08c..13e66f7 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -1566,13 +1566,6 @@ uses this macro should also arrange to use @file{t-gnu-prefix} in
 the libgcc @file{config.host}.
 @end defmac
 
-@defmac TARGET_FLT_EVAL_METHOD
-A C expression for the value for @code{FLT_EVAL_METHOD} in @file{float.h},
-assuming, if applicable, that the floating-point control word is in its
-default state.  If you do not define this macro the value of
-@code{FLT_EVAL_METHOD} will be zero.
-@end defmac
-
 @defmac WIDEST_HARDWARE_FP_SIZE
 A C expression for the size in bits of the widest floating-point format
 supported by the hardware.  If you define this macro, you must specify a
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 03758b5..7f75a44 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -1402,13 +1402,6 @@ uses this macro should also arrange to use @file{t-gnu-prefix} in
 the libgcc @file{config.host}.
 @end defmac
 
-@defmac TARGET_FLT_EVAL_METHOD
-A C expression for the value for @code{FLT_EVAL_METHOD} in @file{float.h},
-assuming, if applicable, that the floating-point control word is in its
-default state.  If you do not define this macro the value of
-@code{FLT_EVAL_METHOD} will be zero.
-@end defmac
-
 @defmac WIDEST_HARDWARE_FP_SIZE
 A C expression for the size in bits of the widest floating-point format
 supported by the hardware.  If you define this macro, you must specify a
diff --git a/gcc/system.h b/gcc/system.h
index 8c6127c..6319f57 100644
--- a/gcc/system.h
+++ b/gcc/system.h
@@ -896,7 +896,7 @@ extern void fancy_abort (const char *, int, const char *) ATTRIBUTE_NORETURN;
 	ASM_BYTE_OP MEMBER_TYPE_FORCES_BLK LIBGCC2_HAS_SF_MODE		\
 	LIBGCC2_HAS_DF_MODE LIBGCC2_HAS_XF_MODE LIBGCC2_HAS_TF_MODE	\
 	CLEAR_BY_PIECES_P MOVE_BY_PIECES_P SET_BY_PIECES_P		\
-	STORE_BY_PIECES_P
+	STORE_BY_PIECES_P TARGET_FLT_EVAL_METHOD
 
 /* Target macros only used for code built for the target, that have
    moved to libgcc-tm.h or have never been present elsewhere.  */

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

* [Patch v4 0/17] Add support for _Float16 to AArch64 and ARM
  2016-09-30 16:58 [Patch 0/11] Add support for _Float16 to AArch64 James Greenhalgh
                   ` (10 preceding siblings ...)
  2016-10-24 13:45 ` [Patch 0/4] [ARM] Enable _Float16 on ARM James Greenhalgh
@ 2016-11-11 15:38 ` James Greenhalgh
  2016-11-11 15:38   ` [Patch 5/17] Add -fpermitted-flt-eval-methods=[c11|ts-18661-3] James Greenhalgh
                     ` (12 more replies)
  11 siblings, 13 replies; 95+ messages in thread
From: James Greenhalgh @ 2016-11-11 15:38 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, joseph, law

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


Hi,

This patch set enables the _Float16 type specified in ISO/IEC TS 18661-3
for AArch64 and ARM. The patch set has been posted over the past two months,
with many of the target-independent changes approved. I'm reposting it in
entirity in the form I hope to commit it to trunk.

The patch set can be roughly split in three; first, hookization of
TARGET_FLT_EVAL_METHOD, and changes to the excess precision logic in the
compiler to handle the new values for FLT_EVAL_METHOD defined in
ISO/IEC TS-18661-3. Second, the AArch64 changes required to enable _Float16,
and finally the ARM changes required to enable _Float16.

The broad goals and an outline of each patch in the patch set were
described in https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02383.html .
As compared to the original submission, the patch set has grown an ARM
port, and has had several rounds of technical review on the target
independent aspects.

This has resulted in many of the patches already being approved, a full
summary of the status of each ticket is immediately below.

Clearly the focus for review of this patch set now needs to be the AArch64
and ARM ports, I hope the appropriate maintainers will be able to do so in
time for the patch set to be accepted for GCC 7.

I've built and tested the full patch set on ARM (cross and native),
AArch64 (cross and native) and x86_64 (native) with no identified issues.

Thanks,
James

------------------
Target independent changes

10 patches, 9 previously approved, 1 New implementing testsuite
changes to enable _Float16 tests in more circumstances on ARM.
------------------

[Patch 1/17] Add a new target hook for describing excess precision intentions

  Approved: https://gcc.gnu.org/ml/gcc-patches/2016-11/msg00781.html

[Patch 2/17] Implement TARGET_C_EXCESS_PRECISION for i386

  Blanket approved by Jeff in:
    https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02402.html

[Patch 3/17] Implement TARGET_C_EXCESS_PRECISION for s390

  Approved: https://gcc.gnu.org/ml/gcc-patches/2016-10/msg01554.html

[Patch 4/17] Implement TARGET_C_EXCESS_PRECISION for m68k

  Blanket approved by Jeff in:
    https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02402.html
  And by Andreas: https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02414.html

  There was a typo in the original patch, fixed in:
    https://gcc.gnu.org/ml/gcc-patches/2016-10/msg01173.html
  which I would apply as an "obvious" fix to the original patch.

[Patch 5/17] Add -fpermitted-flt-eval-methods=[c11|ts-18661-3]

  Approved: https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02405.html

  Joseph had a comment in
  https://gcc.gnu.org/ml/gcc-patches/2016-10/msg00335.html that the tests
  should check FLT_EVAL_METHOD from <float.h> rather than
  __FLT_EVAL_METHOD__. Rather than implement that suggestion, I added tests
  to patch 6 which tested the <float.h> macro, and left the tests in this
  patch testing the internal macro.

[Patch 6/17] Migrate excess precision logic to use TARGET_EXCESS_PRECISION

  Approved (after removing a rebase bug):
  https://gcc.gnu.org/ml/gcc-patches/2016-11/msg00231.html

[Patch 7/17] Delete TARGET_FLT_EVAL_METHOD and poison it.

  Approved: https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02401.html

[Patch 8/17] Make _Float16 available if HFmode is available

  Approved: https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02403.html

[Patch libgcc 9/17] Update soft-fp from glibc

  Self approved under policy that we can update libraries which GCC mirrors
  without further approval.

[Patch testsuite patch 10/17] Add options for floatN when checking effective target for support

  NEW!

----------------
AArch64 changes

3 patches, none reviewed
----------------

[Patch AArch64 11/17] Add floatdihf2 and floatunsdihf2 patterns

  Not reviewed, last pinged (^6):
  https://gcc.gnu.org/ml/gcc-patches/2016-11/msg00584.html

[Patch libgcc AArch64 12/17] Enable hfmode soft-float conversions and truncations

  Not reviewed:
  https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02395.html

[Patch AArch64 13/17] Enable _Float16 for AArch64

  Not reviewed:
  https://gcc.gnu.org/ml/gcc-patches/2016-10/msg01176.html

----------------
ARM changes

4 patches, none OK'ed
----------------
[Patch 14/17] [libgcc, ARM] Generalise float-to-half conversion function.

  Respun in this submission to avoid a bug identified during extended
  multilib testing, original submission here:
  https://gcc.gnu.org/ml/gcc-patches/2016-11/msg00714.html

[Patch 15/17 libgcc] Add double to half conversions.

  Reviewed, but not approved:
  https://gcc.gnu.org/ml/gcc-patches/2016-10/msg01975.html

  Changes were required to patch 16/17, and patch 10/17 was introduced to
  implement the suggested testsuite patch. The original patch still stands,
  and needs reviewed:
  https://gcc.gnu.org/ml/gcc-patches/2016-10/msg01914.html

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

  Resubmitted: https://gcc.gnu.org/ml/gcc-patches/2016-11/msg00233.html
  Needs review.

[Patch ARM 17/17] Enable _Float16 for ARM.

  Resubmitted: https://gcc.gnu.org/ml/gcc-patches/2016-11/msg00234.html
  Needs review.




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

* [Patch 8/17] Make _Float16 available if HFmode is available
  2016-11-11 15:38 ` [Patch v4 0/17] Add support for _Float16 to AArch64 and ARM James Greenhalgh
                     ` (6 preceding siblings ...)
  2016-11-11 15:38   ` [Patch 7/17] Delete TARGET_FLT_EVAL_METHOD and poison it James Greenhalgh
@ 2016-11-11 15:39   ` James Greenhalgh
  2016-11-11 15:39   ` [Patch testsuite patch 10/17] Add options for floatN when checking effective target for support James Greenhalgh
                     ` (4 subsequent siblings)
  12 siblings, 0 replies; 95+ messages in thread
From: James Greenhalgh @ 2016-11-11 15:39 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, joseph, law

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


---
This patch was approved:
  https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02403.html
---

Hi,

Now that we've worked on -fexcess-precision, the comment in targhooks.c
no longer holds. We can now permit _Float16 on any target which provides
HFmode and supports HFmode in libgcc.

Bootstrapped and tested on x86-64, and in series on AArch64.

Thanks,
James

---
2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>

	* targhooks.c (default_floatn_mode): Enable _Float16 if a target
	provides HFmode.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0008-Patch-8-17-Make-_Float16-available-if-HFmode-is-avai.patch --]
[-- Type: text/x-patch; name="0008-Patch-8-17-Make-_Float16-available-if-HFmode-is-avai.patch", Size: 706 bytes --]

diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index 73e1c25..a80b301 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -514,10 +514,12 @@ default_floatn_mode (int n, bool extended)
       switch (n)
 	{
 	case 16:
-	  /* We do not use HFmode for _Float16 by default because the
-	     required excess precision support is not present and the
-	     interactions with promotion of the older __fp16 need to
-	     be worked out.  */
+	  /* Always enable _Float16 if we have basic support for the mode.
+	     Targets can control the range and precision of operations on
+	     the _Float16 type using TARGET_C_EXCESS_PRECISION.  */
+#ifdef HAVE_HFmode
+	  cand = HFmode;
+#endif
 	  break;
 
 	case 32:

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

* [Patch testsuite patch 10/17] Add options for floatN when checking effective target for support
  2016-11-11 15:38 ` [Patch v4 0/17] Add support for _Float16 to AArch64 and ARM James Greenhalgh
                     ` (7 preceding siblings ...)
  2016-11-11 15:39   ` [Patch 8/17] Make _Float16 available if HFmode is available James Greenhalgh
@ 2016-11-11 15:39   ` James Greenhalgh
  2016-11-11 15:59     ` Joseph Myers
  2016-11-11 15:39   ` [Patch libgcc 9/17] Update soft-fp from glibc James Greenhalgh
                     ` (3 subsequent siblings)
  12 siblings, 1 reply; 95+ messages in thread
From: James Greenhalgh @ 2016-11-11 15:39 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, joseph, law

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


Hi,

As Joseph and I discussed in
https://gcc.gnu.org/ml/gcc-patches/2016-11/msg00239.html the
check_effective_target_float<N><x> tests should add any options which the
target requires to enable those float types (add_options_for_float<N><x>.

This patch ensures those options get added, which presently only changes
the testsuite behaviour for the (out-of-tree but submitted for review)
ARM support for _Float16.

Tested on arm-none-linux-gnueabihf with those patches applied, to show that
the _Float16 tests now run.

OK?

Thanks,
James

---

gcc/testsuite/

2016-11-07  James Greenhalgh  <james.greenhalgh@arm.com>

	* lib/target-supports.exp (check_effective_target_float16): Add
	options for _Float16.
	(check_effective_target_float32): Add options for _Float32.
	(check_effective_target_float64): Add options for _Float64.
	(check_effective_target_float128): Add options for _Float128.
	(check_effective_target_float32x): Add options for _Float32x.
	(check_effective_target_float64x): Add options for _Float64x.
	(check_effective_target_float128x): Add options for _Float128x.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0010-Patch-testsuite-patch-10-17-Add-options-for-floatN-w.patch --]
[-- Type: text/x-patch; name="0010-Patch-testsuite-patch-10-17-Add-options-for-floatN-w.patch", Size: 1625 bytes --]

diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index b683c09..b917250 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -2483,43 +2483,43 @@ proc check_effective_target_has_q_floating_suffix { } {
 proc check_effective_target_float16 {} {
     return [check_no_compiler_messages_nocache float16 object {
         _Float16 x;
-    }]
+    } [add_options_for_float16 ""]]
 }
 
 proc check_effective_target_float32 {} {
     return [check_no_compiler_messages_nocache float32 object {
         _Float32 x;
-    }]
+    } [add_options_for_float32 ""]]
 }
 
 proc check_effective_target_float64 {} {
     return [check_no_compiler_messages_nocache float64 object {
         _Float64 x;
-    }]
+    } [add_options_for_float64 ""]]
 }
 
 proc check_effective_target_float128 {} {
     return [check_no_compiler_messages_nocache float128 object {
         _Float128 x;
-    }]
+    } [add_options_for_float128 ""]]
 }
 
 proc check_effective_target_float32x {} {
     return [check_no_compiler_messages_nocache float32x object {
         _Float32x x;
-    }]
+    } [add_options_for_float32x ""]]
 }
 
 proc check_effective_target_float64x {} {
     return [check_no_compiler_messages_nocache float64x object {
         _Float64x x;
-    }]
+    } [add_options_for_float64x ""]]
 }
 
 proc check_effective_target_float128x {} {
     return [check_no_compiler_messages_nocache float128x object {
         _Float128x x;
-    }]
+    } [add_options_for_float128x ""]]
 }
 
 # Likewise, but runtime support for any special options used as well

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

* [Patch libgcc 9/17] Update soft-fp from glibc
  2016-11-11 15:38 ` [Patch v4 0/17] Add support for _Float16 to AArch64 and ARM James Greenhalgh
                     ` (8 preceding siblings ...)
  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:39   ` James Greenhalgh
  2016-11-11 15:41   ` [Patch AArch64 11/17] Add floatdihf2 and floatunsdihf2 patterns James Greenhalgh
                     ` (2 subsequent siblings)
  12 siblings, 0 replies; 95+ messages in thread
From: James Greenhalgh @ 2016-11-11 15:39 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, joseph, law

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


---
This patch can be self approved
---

Hi,

This patch merges in the support added to glibc for HFmode conversions in
this patch:

    commit 87ab10d6524fe4faabd7eb3eac5868165ecfb323
    Author: James Greenhalgh <james.greenhalgh@arm.com>
    Date:   Wed Sep 21 21:02:54 2016 +0000

        [soft-fp] Add support for various half-precision conversion routines.

        This patch adds conversion routines required for _Float16 support in
        AArch64.

        These are one-step conversions to and from TImode and TFmode. We need
        these on AArch64 regardless of presence of the ARMv8.2-A 16-bit
        floating-point extensions.

        In the patch, soft-fp/half.h is derived from soft-fp/single.h .  The
        conversion routines are derivatives of their respective SFmode
        variants.

            * soft-fp/extendhftf2.c: New.
            * soft-fp/fixhfti.c: Likewise.
            * soft-fp/fixunshfti.c: Likewise.
            * soft-fp/floattihf.c: Likewise.
            * soft-fp/floatuntihf.c: Likewise.
            * soft-fp/half.h: Likewise.
            * soft-fp/trunctfhf2.c: Likewise.

Any patch merging from upstream is preapproved acording to our commit
policies, but I'll hold off on committing it until the others in this
series have been approved.

Thanks,
James

---
libgcc/

2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>

	* soft-fp/extendhftf2.c: New.
	* soft-fp/fixhfti.c: Likewise.
	* soft-fp/fixunshfti.c: Likewise.
	* soft-fp/floattihf.c: Likewise.
	* soft-fp/floatuntihf.c: Likewise.
	* soft-fp/half.h: Likewise.
	* soft-fp/trunctfhf2.c: Likewise.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0009-Patch-libgcc-9-17-Update-soft-fp-from-glibc.patch --]
[-- Type: text/x-patch; name="0009-Patch-libgcc-9-17-Update-soft-fp-from-glibc.patch", Size: 17069 bytes --]

diff --git a/libgcc/soft-fp/extendhftf2.c b/libgcc/soft-fp/extendhftf2.c
new file mode 100644
index 0000000..6ff6438
--- /dev/null
+++ b/libgcc/soft-fp/extendhftf2.c
@@ -0,0 +1,53 @@
+/* Software floating-point emulation.
+   Return an IEEE half converted to IEEE quad
+   Copyright (C) 1997-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define FP_NO_EXACT_UNDERFLOW
+#include "soft-fp.h"
+#include "half.h"
+#include "quad.h"
+
+TFtype
+__extendhftf2 (HFtype a)
+{
+  FP_DECL_EX;
+  FP_DECL_H (A);
+  FP_DECL_Q (R);
+  TFtype r;
+
+  FP_INIT_EXCEPTIONS;
+  FP_UNPACK_RAW_H (A, a);
+#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
+  FP_EXTEND (Q, H, 4, 1, R, A);
+#else
+  FP_EXTEND (Q, H, 2, 1, R, A);
+#endif
+  FP_PACK_RAW_Q (r, R);
+  FP_HANDLE_EXCEPTIONS;
+
+  return r;
+}
diff --git a/libgcc/soft-fp/fixhfti.c b/libgcc/soft-fp/fixhfti.c
new file mode 100644
index 0000000..3610f4c
--- /dev/null
+++ b/libgcc/soft-fp/fixhfti.c
@@ -0,0 +1,45 @@
+/* Software floating-point emulation.
+   Convert IEEE half to 128bit signed integer
+   Copyright (C) 2007-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "soft-fp.h"
+#include "half.h"
+
+TItype
+__fixhfti (HFtype a)
+{
+  FP_DECL_EX;
+  FP_DECL_H (A);
+  UTItype r;
+
+  FP_INIT_EXCEPTIONS;
+  FP_UNPACK_RAW_H (A, a);
+  FP_TO_INT_H (r, A, TI_BITS, 1);
+  FP_HANDLE_EXCEPTIONS;
+
+  return r;
+}
diff --git a/libgcc/soft-fp/fixunshfti.c b/libgcc/soft-fp/fixunshfti.c
new file mode 100644
index 0000000..30edbfe
--- /dev/null
+++ b/libgcc/soft-fp/fixunshfti.c
@@ -0,0 +1,45 @@
+/* Software floating-point emulation.
+   Convert IEEE half to 128bit unsigned integer
+   Copyright (C) 2007-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "soft-fp.h"
+#include "half.h"
+
+UTItype
+__fixunshfti (HFtype a)
+{
+  FP_DECL_EX;
+  FP_DECL_H (A);
+  UTItype r;
+
+  FP_INIT_EXCEPTIONS;
+  FP_UNPACK_RAW_H (A, a);
+  FP_TO_INT_H (r, A, TI_BITS, 0);
+  FP_HANDLE_EXCEPTIONS;
+
+  return r;
+}
diff --git a/libgcc/soft-fp/floattihf.c b/libgcc/soft-fp/floattihf.c
new file mode 100644
index 0000000..74ac83a
--- /dev/null
+++ b/libgcc/soft-fp/floattihf.c
@@ -0,0 +1,45 @@
+/* Software floating-point emulation.
+   Convert a 128bit signed integer to IEEE half
+   Copyright (C) 2007-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "soft-fp.h"
+#include "half.h"
+
+HFtype
+__floattihf (TItype i)
+{
+  FP_DECL_EX;
+  FP_DECL_H (A);
+  HFtype a;
+
+  FP_INIT_ROUNDMODE;
+  FP_FROM_INT_H (A, i, TI_BITS, UTItype);
+  FP_PACK_RAW_H (a, A);
+  FP_HANDLE_EXCEPTIONS;
+
+  return a;
+}
diff --git a/libgcc/soft-fp/floatuntihf.c b/libgcc/soft-fp/floatuntihf.c
new file mode 100644
index 0000000..90e77c2
--- /dev/null
+++ b/libgcc/soft-fp/floatuntihf.c
@@ -0,0 +1,45 @@
+/* Software floating-point emulation.
+   Convert a 128bit unsigned integer to IEEE half.
+   Copyright (C) 2007-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "soft-fp.h"
+#include "half.h"
+
+HFtype
+__floatuntihf (UTItype i)
+{
+  FP_DECL_EX;
+  FP_DECL_H (A);
+  HFtype a;
+
+  FP_INIT_ROUNDMODE;
+  FP_FROM_INT_H (A, i, TI_BITS, UTItype);
+  FP_PACK_RAW_H (a, A);
+  FP_HANDLE_EXCEPTIONS;
+
+  return a;
+}
diff --git a/libgcc/soft-fp/half.h b/libgcc/soft-fp/half.h
new file mode 100644
index 0000000..ba75297
--- /dev/null
+++ b/libgcc/soft-fp/half.h
@@ -0,0 +1,170 @@
+/* Software floating-point emulation.
+   Definitions for IEEE Half Precision.
+   Copyright (C) 1997-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef SOFT_FP_HALF_H
+#define SOFT_FP_HALF_H	1
+
+#if _FP_W_TYPE_SIZE < 32
+# error "Here's a nickel kid.  Go buy yourself a real computer."
+#endif
+
+#define _FP_FRACTBITS_H		(_FP_W_TYPE_SIZE)
+
+#define _FP_FRACTBITS_DW_H	(_FP_W_TYPE_SIZE)
+
+#define _FP_FRACBITS_H		11
+#define _FP_FRACXBITS_H		(_FP_FRACTBITS_H - _FP_FRACBITS_H)
+#define _FP_WFRACBITS_H		(_FP_WORKBITS + _FP_FRACBITS_H)
+#define _FP_WFRACXBITS_H	(_FP_FRACTBITS_H - _FP_WFRACBITS_H)
+#define _FP_EXPBITS_H		5
+#define _FP_EXPBIAS_H		15
+#define _FP_EXPMAX_H		31
+
+#define _FP_QNANBIT_H		((_FP_W_TYPE) 1 << (_FP_FRACBITS_H-2))
+#define _FP_QNANBIT_SH_H	((_FP_W_TYPE) 1 << (_FP_FRACBITS_H-2+_FP_WORKBITS))
+#define _FP_IMPLBIT_H		((_FP_W_TYPE) 1 << (_FP_FRACBITS_H-1))
+#define _FP_IMPLBIT_SH_H	((_FP_W_TYPE) 1 << (_FP_FRACBITS_H-1+_FP_WORKBITS))
+#define _FP_OVERFLOW_H		((_FP_W_TYPE) 1 << (_FP_WFRACBITS_H))
+
+#define _FP_WFRACBITS_DW_H	(2 * _FP_WFRACBITS_H)
+#define _FP_WFRACXBITS_DW_H	(_FP_FRACTBITS_DW_H - _FP_WFRACBITS_DW_H)
+#define _FP_HIGHBIT_DW_H	\
+  ((_FP_W_TYPE) 1 << (_FP_WFRACBITS_DW_H - 1) % _FP_W_TYPE_SIZE)
+
+/* The implementation of _FP_MUL_MEAT_H and _FP_DIV_MEAT_H should be
+   chosen by the target machine.  */
+
+typedef float HFtype __attribute__ ((mode (HF)));
+
+union _FP_UNION_H
+{
+  HFtype flt;
+  struct _FP_STRUCT_LAYOUT
+  {
+#if __BYTE_ORDER == __BIG_ENDIAN
+    unsigned sign : 1;
+    unsigned exp  : _FP_EXPBITS_H;
+    unsigned frac : _FP_FRACBITS_H - (_FP_IMPLBIT_H != 0);
+#else
+    unsigned frac : _FP_FRACBITS_H - (_FP_IMPLBIT_H != 0);
+    unsigned exp  : _FP_EXPBITS_H;
+    unsigned sign : 1;
+#endif
+  } bits __attribute__ ((packed));
+};
+
+#define FP_DECL_H(X)		_FP_DECL (1, X)
+#define FP_UNPACK_RAW_H(X, val)	_FP_UNPACK_RAW_1 (H, X, (val))
+#define FP_UNPACK_RAW_HP(X, val)	_FP_UNPACK_RAW_1_P (H, X, (val))
+#define FP_PACK_RAW_H(val, X)	_FP_PACK_RAW_1 (H, (val), X)
+#define FP_PACK_RAW_HP(val, X)			\
+  do						\
+    {						\
+      if (!FP_INHIBIT_RESULTS)			\
+	_FP_PACK_RAW_1_P (H, (val), X);		\
+    }						\
+  while (0)
+
+#define FP_UNPACK_H(X, val)			\
+  do						\
+    {						\
+      _FP_UNPACK_RAW_1 (H, X, (val));		\
+      _FP_UNPACK_CANONICAL (H, 1, X);		\
+    }						\
+  while (0)
+
+#define FP_UNPACK_HP(X, val)			\
+  do						\
+    {						\
+      _FP_UNPACK_RAW_1_P (H, X, (val));		\
+      _FP_UNPACK_CANONICAL (H, 1, X);		\
+    }						\
+  while (0)
+
+#define FP_UNPACK_SEMIRAW_H(X, val)		\
+  do						\
+    {						\
+      _FP_UNPACK_RAW_1 (H, X, (val));		\
+      _FP_UNPACK_SEMIRAW (H, 1, X);		\
+    }						\
+  while (0)
+
+#define FP_UNPACK_SEMIRAW_HP(X, val)		\
+  do						\
+    {						\
+      _FP_UNPACK_RAW_1_P (H, X, (val));		\
+      _FP_UNPACK_SEMIRAW (H, 1, X);		\
+    }						\
+  while (0)
+
+#define FP_PACK_H(val, X)			\
+  do						\
+    {						\
+      _FP_PACK_CANONICAL (H, 1, X);		\
+      _FP_PACK_RAW_1 (H, (val), X);		\
+    }						\
+  while (0)
+
+#define FP_PACK_HP(val, X)			\
+  do						\
+    {						\
+      _FP_PACK_CANONICAL (H, 1, X);		\
+      if (!FP_INHIBIT_RESULTS)			\
+	_FP_PACK_RAW_1_P (H, (val), X);		\
+    }						\
+  while (0)
+
+#define FP_PACK_SEMIRAW_H(val, X)		\
+  do						\
+    {						\
+      _FP_PACK_SEMIRAW (H, 1, X);		\
+      _FP_PACK_RAW_1 (H, (val), X);		\
+    }						\
+  while (0)
+
+#define FP_PACK_SEMIRAW_HP(val, X)		\
+  do						\
+    {						\
+      _FP_PACK_SEMIRAW (H, 1, X);		\
+      if (!FP_INHIBIT_RESULTS)			\
+	_FP_PACK_RAW_1_P (H, (val), X);		\
+    }						\
+  while (0)
+
+#define FP_TO_INT_H(r, X, rsz, rsg)	_FP_TO_INT (H, 1, (r), X, (rsz), (rsg))
+#define FP_TO_INT_ROUND_H(r, X, rsz, rsg)	\
+  _FP_TO_INT_ROUND (H, 1, (r), X, (rsz), (rsg))
+#define FP_FROM_INT_H(X, r, rs, rt)	_FP_FROM_INT (H, 1, X, (r), (rs), rt)
+
+/* HFmode arithmetic is not implemented.  */
+
+#define _FP_FRAC_HIGH_H(X)	_FP_FRAC_HIGH_1 (X)
+#define _FP_FRAC_HIGH_RAW_H(X)	_FP_FRAC_HIGH_1 (X)
+#define _FP_FRAC_HIGH_DW_H(X)	_FP_FRAC_HIGH_1 (X)
+
+#endif /* !SOFT_FP_HALF_H */
diff --git a/libgcc/soft-fp/trunctfhf2.c b/libgcc/soft-fp/trunctfhf2.c
new file mode 100644
index 0000000..0500b14
--- /dev/null
+++ b/libgcc/soft-fp/trunctfhf2.c
@@ -0,0 +1,52 @@
+/* Software floating-point emulation.
+   Truncate IEEE quad into IEEE half.
+   Copyright (C) 1997-2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   In addition to the permissions in the GNU Lesser General Public
+   License, the Free Software Foundation gives you unlimited
+   permission to link the compiled version of this file into
+   combinations with other programs, and to distribute those
+   combinations without any restriction coming from the use of this
+   file.  (The Lesser General Public License restrictions do apply in
+   other respects; for example, they cover modification of the file,
+   and distribution when not linked into a combine executable.)
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "soft-fp.h"
+#include "half.h"
+#include "quad.h"
+
+HFtype
+__trunctfhf2 (TFtype a)
+{
+  FP_DECL_EX;
+  FP_DECL_Q (A);
+  FP_DECL_H (R);
+  HFtype r;
+
+  FP_INIT_ROUNDMODE;
+  FP_UNPACK_SEMIRAW_Q (A, a);
+#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
+  FP_TRUNC (H, Q, 1, 4, R, A);
+#else
+  FP_TRUNC (H, Q, 1, 2, R, A);
+#endif
+  FP_PACK_SEMIRAW_H (r, R);
+  FP_HANDLE_EXCEPTIONS;
+
+  return r;
+}

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

* [Patch AArch64 13/17] Enable _Float16 for AArch64
  2016-11-11 15:41   ` [Patch AArch64 11/17] Add floatdihf2 and floatunsdihf2 patterns James Greenhalgh
@ 2016-11-11 15:41     ` James Greenhalgh
  2016-11-11 16:33       ` Joseph Myers
                         ` (2 more replies)
  2016-11-11 15:41     ` [Patch libgcc AArch64 12/17] Enable hfmode soft-float conversions and truncations James Greenhalgh
                       ` (2 subsequent siblings)
  3 siblings, 3 replies; 95+ messages in thread
From: James Greenhalgh @ 2016-11-11 15:41 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, richard.earnshaw, marcus.shawcroft, joseph

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


 Hi,

This patch adds the back-end wiring to get AArch64 support for
the _Float16 type working.

Bootstrapped on AArch64 with no issues.

OK?

Thanks,
James

---
2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>

	* config/aarch64/aarch64-c.c (aarch64_update_cpp_builtins): Update
	__FLT_EVAL_METHOD__ and __FLT_EVAL_METHOD_C99__ when we switch
	architecture levels.
	* config/aarch64/aarch64.c (aarch64_promoted_type): Only promote
	the aarch64_fp16_type_node, not all HFmode types.
	(aarch64_libgcc_floating_mode_supported_p): Support HFmode.
	(aarch64_scalar_mode_supported_p): Likewise.
	(aarch64_excess_precision): New.
	(TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P): Define.
	(TARGET_SCALAR_MODE_SUPPORTED_P): Likewise.
	(TARGET_C_EXCESS_PRECISION): Likewise.

2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>

	* gcc.target/aarch64/_Float16_1.c: New.
	* gcc.target/aarch64/_Float16_2.c: Likewise.
	* gcc.target/aarch64/_Float16_3.c: Likewise.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0013-Patch-AArch64-13-17-Enable-_Float16-for-AArch64.patch --]
[-- Type: text/x-patch; name="0013-Patch-AArch64-13-17-Enable-_Float16-for-AArch64.patch", Size: 9460 bytes --]

diff --git a/gcc/config/aarch64/aarch64-c.c b/gcc/config/aarch64/aarch64-c.c
index 422e322..320b912 100644
--- a/gcc/config/aarch64/aarch64-c.c
+++ b/gcc/config/aarch64/aarch64-c.c
@@ -133,6 +133,16 @@ aarch64_update_cpp_builtins (cpp_reader *pfile)
 
   aarch64_def_or_undef (TARGET_CRYPTO, "__ARM_FEATURE_CRYPTO", pfile);
   aarch64_def_or_undef (TARGET_SIMD_RDMA, "__ARM_FEATURE_QRDMX", pfile);
+
+  /* Not for ACLE, but required to keep "float.h" correct if we switch
+     target between implementations that do or do not support ARMv8.2-A
+     16-bit floating-point extensions.  */
+  cpp_undef (pfile, "__FLT_EVAL_METHOD__");
+  builtin_define_with_int_value ("__FLT_EVAL_METHOD__",
+				 c_flt_eval_method (true));
+  cpp_undef (pfile, "__FLT_EVAL_METHOD_C99__");
+  builtin_define_with_int_value ("__FLT_EVAL_METHOD_C99__",
+				 c_flt_eval_method (false));
 }
 
 /* Implement TARGET_CPU_CPP_BUILTINS.  */
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index ec17af4..824b27c 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -14143,12 +14143,20 @@ aarch64_vec_fpconst_pow_of_2 (rtx x)
   return firstval;
 }
 
-/* Implement TARGET_PROMOTED_TYPE to promote __fp16 to float.  */
+/* Implement TARGET_PROMOTED_TYPE to promote 16-bit floating point types
+   to float.
+
+   __fp16 always promotes through this hook.
+   _Float16 may promote if TARGET_FLT_EVAL_METHOD is 16, but we do that
+   through the generic excess precision logic rather than here.  */
+
 static tree
 aarch64_promoted_type (const_tree t)
 {
-  if (SCALAR_FLOAT_TYPE_P (t) && TYPE_PRECISION (t) == 16)
+
+  if (TYPE_P (t) && TYPE_MAIN_VARIANT (t) == aarch64_fp16_type_node)
     return float_type_node;
+
   return NULL_TREE;
 }
 
@@ -14168,6 +14176,17 @@ aarch64_optab_supported_p (int op, machine_mode mode1, machine_mode,
     }
 }
 
+/* Implement TARGET_LIBGCC_FLOATING_POINT_MODE_SUPPORTED_P - return TRUE
+   if MODE is HFmode, and punt to the generic implementation otherwise.  */
+
+static bool
+aarch64_libgcc_floating_mode_supported_p (machine_mode mode)
+{
+  return (mode == HFmode
+	  ? true
+	  : default_libgcc_floating_mode_supported_p (mode));
+}
+
 /* Implement TARGET_SCALAR_MODE_SUPPORTED_P - return TRUE
    if MODE is HFmode, and punt to the generic implementation otherwise.  */
 
@@ -14179,6 +14198,47 @@ aarch64_scalar_mode_supported_p (machine_mode mode)
 	  : default_scalar_mode_supported_p (mode));
 }
 
+/* Set the value of FLT_EVAL_METHOD.
+   ISO/IEC TS 18661-3 defines two values that we'd like to make use of:
+
+    0: evaluate all operations and constants, whose semantic type has at
+       most the range and precision of type float, to the range and
+       precision of float; evaluate all other operations and constants to
+       the range and precision of the semantic type;
+
+    N, where _FloatN is a supported interchange floating type
+       evaluate all operations and constants, whose semantic type has at
+       most the range and precision of _FloatN type, to the range and
+       precision of the _FloatN type; evaluate all other operations and
+       constants to the range and precision of the semantic type;
+
+   If we have the ARMv8.2-A extensions then we support _Float16 in native
+   precision, so we should set this to 16.  Otherwise, we support the type,
+   but want to evaluate expressions in float precision, so set this to
+   0.  */
+
+static enum flt_eval_method
+aarch64_excess_precision (enum excess_precision_type type)
+{
+  switch (type)
+    {
+      case EXCESS_PRECISION_TYPE_FAST:
+      case EXCESS_PRECISION_TYPE_STANDARD:
+	/* We can calculate either in 16-bit range and precision or
+	   32-bit range and precision.  Make that decision based on whether
+	   we have native support for the ARMv8.2-A 16-bit floating-point
+	   instructions or not.  */
+	return (TARGET_FP_F16INST
+		? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16
+		: FLT_EVAL_METHOD_PROMOTE_TO_FLOAT);
+      case EXCESS_PRECISION_TYPE_IMPLICIT:
+	return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16;
+      default:
+	gcc_unreachable ();
+    }
+  return FLT_EVAL_METHOD_UNPREDICTABLE;
+}
+
 #undef TARGET_ADDRESS_COST
 #define TARGET_ADDRESS_COST aarch64_address_cost
 
@@ -14257,6 +14317,9 @@ aarch64_scalar_mode_supported_p (machine_mode mode)
 #undef TARGET_BUILTIN_RECIPROCAL
 #define TARGET_BUILTIN_RECIPROCAL aarch64_builtin_reciprocal
 
+#undef TARGET_C_EXCESS_PRECISION
+#define TARGET_C_EXCESS_PRECISION aarch64_excess_precision
+
 #undef  TARGET_EXPAND_BUILTIN
 #define TARGET_EXPAND_BUILTIN aarch64_expand_builtin
 
@@ -14313,6 +14376,10 @@ aarch64_scalar_mode_supported_p (machine_mode mode)
 #undef TARGET_LIBGCC_CMP_RETURN_MODE
 #define TARGET_LIBGCC_CMP_RETURN_MODE aarch64_libgcc_cmp_return_mode
 
+#undef TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P
+#define TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P \
+aarch64_libgcc_floating_mode_supported_p
+
 #undef TARGET_MANGLE_TYPE
 #define TARGET_MANGLE_TYPE aarch64_mangle_type
 
diff --git a/gcc/testsuite/gcc.target/aarch64/_Float16_1.c b/gcc/testsuite/gcc.target/aarch64/_Float16_1.c
new file mode 100644
index 0000000..320f154
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/_Float16_1.c
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=armv8.2-a+nofp16" } */
+
+#pragma GCC target ("arch=armv8.2-a+nofp16")
+
+_Float16
+foo_v8 (_Float16 x, _Float16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+__fp16
+bar_v8 (__fp16 x, __fp16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+#pragma GCC target ("arch=armv8.2-a+fp16")
+
+_Float16
+foo_v82 (_Float16 x, _Float16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+__fp16
+bar_v82 (__fp16 x, __fp16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+/* Test that we merge to FMA operations.  This indicates that we are not
+   making extraneous conversions between modes.  */
+
+/* Three FMA operations in 32-bit precision, from foo_v8, bar_v8, bar_v82.  */
+/* { dg-final { scan-assembler-times "fmadd\ts\[0-9\]\+" 3 } } */
+
+/* One FMA operation in 16-bit precision, from foo_v82.  */
+/* { dg-final { scan-assembler-times "fmadd\th\[0-9\]\+" 1 } } */
+
+/* Test that we are resetting the __FLT_EVAL_METHOD__.  */
+/* { dg-final { scan-assembler-times "mov\tw\[0-9\]\+, 16" 2 } } */
+/* { dg-final { scan-assembler-times "str\twzr" 2 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/_Float16_2.c b/gcc/testsuite/gcc.target/aarch64/_Float16_2.c
new file mode 100644
index 0000000..8b2aa1e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/_Float16_2.c
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=armv8.2-a+nofp16 -fpermitted-flt-eval-methods=c11" } */
+
+#pragma GCC target ("arch=armv8.2-a+nofp16")
+
+_Float16
+foo_v8 (_Float16 x, _Float16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+__fp16
+bar_v8 (__fp16 x, __fp16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+#pragma GCC target ("arch=armv8.2-a+fp16")
+
+_Float16
+foo_v82 (_Float16 x, _Float16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+__fp16
+bar_v82 (__fp16 x, __fp16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+/* Test that we merge to FMA operations.  This indicates that we are not
+   making extraneous conversions between modes.  */
+
+/* Three FMA operations in 32-bit precision, from foo_v8, bar_v8, bar_v82.  */
+/* { dg-final { scan-assembler-times "fmadd\ts\[0-9\]\+" 3 } } */
+
+/* One FMA operation in 16-bit precision, from foo_v82.  */
+/* { dg-final { scan-assembler-times "fmadd\th\[0-9\]\+" 1 } } */
+
+/* Test that in -fpermitted-flt-eval-methods=c11 we don't set the
+   __FLT_EVAL_METHOD__ to anything other than 0.  */
+/* { dg-final { scan-assembler-times "str\twzr" 4 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/_Float16_3.c b/gcc/testsuite/gcc.target/aarch64/_Float16_3.c
new file mode 100644
index 0000000..2d20250
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/_Float16_3.c
@@ -0,0 +1,46 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=armv8.2-a+nofp16 -std=c11 -ffp-contract=fast" } */
+
+#pragma GCC target ("arch=armv8.2-a+nofp16")
+
+_Float16
+foo_v8 (_Float16 x, _Float16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+__fp16
+bar_v8 (__fp16 x, __fp16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+#pragma GCC target ("arch=armv8.2-a+fp16")
+
+_Float16
+foo_v82 (_Float16 x, _Float16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+__fp16
+bar_v82 (__fp16 x, __fp16 y, unsigned int *eval)
+{
+  *eval = __FLT_EVAL_METHOD__;
+  return x * x + y;
+}
+
+/* Test that we merge to FMA operations.  This indicates that we are not
+   making extraneous conversions between modes.  */
+
+/* Three FMA operations in 32-bit precision, from foo_v8, bar_v8, bar_v82.  */
+/* { dg-final { scan-assembler-times "fmadd\ts\[0-9\]\+" 3 } } */
+
+/* One FMA operation in 16-bit precision, from foo_v82.  */
+/* { dg-final { scan-assembler-times "fmadd\th\[0-9\]\+" 1 } } */
+
+/* Test that in C11 mode, we don't reset __FLT_EVAL_METHOD__.  */
+/* { dg-final { scan-assembler-times "str\twzr" 4 } } */

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

* [Patch libgcc AArch64 12/17] Enable hfmode soft-float conversions and truncations
  2016-11-11 15:41   ` [Patch AArch64 11/17] Add floatdihf2 and floatunsdihf2 patterns James Greenhalgh
  2016-11-11 15:41     ` [Patch AArch64 13/17] Enable _Float16 for AArch64 James Greenhalgh
@ 2016-11-11 15:41     ` James Greenhalgh
  2016-11-24  9:47       ` James Greenhalgh
  2016-11-24 13:23       ` 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)
  3 siblings, 2 replies; 95+ messages in thread
From: James Greenhalgh @ 2016-11-11 15:41 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, richard.earnshaw, marcus.shawcroft, joseph

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


Hi,

This patch enables the conversion functions we need for AArch64's _Float16
support. To do that we need to implement TARGET_SCALAR_MODE_SUPPORTED_P,
so do that now.

OK?

Thanks,
James

---
gcc/

2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>

	* config/aarch64/aarch64-c.c (aarch64_scalar_mode_supported_p): New.
	(TARGET_SCALAR_MODE_SUPPORTED_P): Define.

libgcc/

2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>

	* config/aarch64/sfp-machine.h (_FP_NANFRAC_H): Define.
	(_FP_NANSIGN_H): Likewise.
	* config/aarch64/t-softfp (softfp_extensions): Add hftf.
	(softfp_truncations): Add tfhf.
	(softfp_extras): Add required conversion functions.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0012-Patch-libgcc-AArch64-12-17-Enable-hfmode-soft-float-.patch --]
[-- Type: text/x-patch; name="0012-Patch-libgcc-AArch64-12-17-Enable-hfmode-soft-float-.patch", Size: 2237 bytes --]

diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index b7d4640..ec17af4 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -14168,6 +14168,17 @@ aarch64_optab_supported_p (int op, machine_mode mode1, machine_mode,
     }
 }
 
+/* Implement TARGET_SCALAR_MODE_SUPPORTED_P - return TRUE
+   if MODE is HFmode, and punt to the generic implementation otherwise.  */
+
+static bool
+aarch64_scalar_mode_supported_p (machine_mode mode)
+{
+  return (mode == HFmode
+	  ? true
+	  : default_scalar_mode_supported_p (mode));
+}
+
 #undef TARGET_ADDRESS_COST
 #define TARGET_ADDRESS_COST aarch64_address_cost
 
@@ -14378,6 +14389,9 @@ aarch64_optab_supported_p (int op, machine_mode mode1, machine_mode,
 #undef TARGET_RTX_COSTS
 #define TARGET_RTX_COSTS aarch64_rtx_costs_wrapper
 
+#undef TARGET_SCALAR_MODE_SUPPORTED_P
+#define TARGET_SCALAR_MODE_SUPPORTED_P aarch64_scalar_mode_supported_p
+
 #undef TARGET_SCHED_ISSUE_RATE
 #define TARGET_SCHED_ISSUE_RATE aarch64_sched_issue_rate
 
diff --git a/libgcc/config/aarch64/sfp-machine.h b/libgcc/config/aarch64/sfp-machine.h
index 5efa245..da154dd 100644
--- a/libgcc/config/aarch64/sfp-machine.h
+++ b/libgcc/config/aarch64/sfp-machine.h
@@ -42,9 +42,11 @@ typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__)));
 
 #define _FP_DIV_MEAT_Q(R,X,Y)	_FP_DIV_MEAT_2_udiv(Q,R,X,Y)
 
+#define _FP_NANFRAC_H		((_FP_QNANBIT_H << 1) - 1)
 #define _FP_NANFRAC_S		((_FP_QNANBIT_S << 1) - 1)
 #define _FP_NANFRAC_D		((_FP_QNANBIT_D << 1) - 1)
 #define _FP_NANFRAC_Q		((_FP_QNANBIT_Q << 1) - 1), -1
+#define _FP_NANSIGN_H		0
 #define _FP_NANSIGN_S		0
 #define _FP_NANSIGN_D		0
 #define _FP_NANSIGN_Q		0
diff --git a/libgcc/config/aarch64/t-softfp b/libgcc/config/aarch64/t-softfp
index 586dca2..c4ce0dc 100644
--- a/libgcc/config/aarch64/t-softfp
+++ b/libgcc/config/aarch64/t-softfp
@@ -1,8 +1,9 @@
 softfp_float_modes := tf
 softfp_int_modes := si di ti
-softfp_extensions := sftf dftf
-softfp_truncations := tfsf tfdf
+softfp_extensions := sftf dftf hftf
+softfp_truncations := tfsf tfdf tfhf
 softfp_exclude_libgcc2 := n
+softfp_extras := fixhfti fixunshfti floattihf floatuntihf
 
 TARGET_LIBGCC2_CFLAGS += -Wno-missing-prototypes
 

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

* [Patch AArch64 11/17] Add floatdihf2 and floatunsdihf2 patterns
  2016-11-11 15:38 ` [Patch v4 0/17] Add support for _Float16 to AArch64 and ARM James Greenhalgh
                     ` (9 preceding siblings ...)
  2016-11-11 15:39   ` [Patch libgcc 9/17] Update soft-fp from glibc James Greenhalgh
@ 2016-11-11 15:41   ` James Greenhalgh
  2016-11-11 15:41     ` [Patch AArch64 13/17] Enable _Float16 for AArch64 James Greenhalgh
                       ` (3 more replies)
  2016-11-11 15:43   ` [Patch 14/17] [libgcc, ARM] Generalise float-to-half conversion function James Greenhalgh
  2016-11-18 18:19   ` [Patch v4 0/17] Add support for _Float16 to AArch64 and ARM James Greenhalgh
  12 siblings, 4 replies; 95+ messages in thread
From: James Greenhalgh @ 2016-11-11 15:41 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, richard.earnshaw, marcus.shawcroft, joseph

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


Hi,

This patch adds patterns for conversion from 64-bit integer to 16-bit
floating-point values under AArch64 targets which don't have support for
the ARMv8.2-A 16-bit floating point extensions.

We implement these by first saturating to a SImode (we know that any
values >= 65504 will round to infinity after conversion to HFmode), then
converting to a DFmode (unsigned conversions could go to SFmode, but there
is no performance benefit to this). Then converting to HFmode.

Having added these patterns, the expansion path in "expand_float" will
now try to use them for conversions from SImode to HFmode as there is no
floatsihf2 pattern. expand_float first tries widening the integer size and
looking for a match, so it will try SImode -> DImode. But our DI mode
pattern is going to then saturate us back to SImode which is wasteful.

Better, would be for us to provide float(uns)sihf2 patterns directly.
So that's what this patch does.

The testcase add in this patch would fail on trunk for AArch64. There is
no libgcc routine to make the conversion, and we don't provide appropriate
patterns in the backend, so we get a link-time error.

Bootstrapped and tested on aarch64-none-linux-gnu

OK for trunk?

James

---
2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>

	* config/aarch64/aarch64.md (<optab>sihf2): Convert to expand.
	(<optab>dihf2): Likewise.
	(aarch64_fp16_<optab><mode>hf2): New.

2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>

	* gcc.target/aarch64/floatdihf2_1.c: New.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0011-Patch-AArch64-11-17-Add-floatdihf2-and-floatunsdihf2.patch --]
[-- Type: text/x-patch; name="0011-Patch-AArch64-11-17-Add-floatdihf2-and-floatunsdihf2.patch", Size: 3443 bytes --]

diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 46eaa30..b818968 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -4627,7 +4627,14 @@
   [(set_attr "type" "f_cvti2f")]
 )
 
-(define_insn "<optab><mode>hf2"
+;; If we do not have ARMv8.2-A 16-bit floating point extensions, the
+;; midend will arrange for an SImode conversion to HFmode to first go
+;; through DFmode, then to HFmode.  But first it will try converting
+;; to DImode then down, which would match our DImode pattern below and
+;; give very poor code-generation.  So, we must provide our own emulation
+;; of the mid-end logic.
+
+(define_insn "aarch64_fp16_<optab><mode>hf2"
   [(set (match_operand:HF 0 "register_operand" "=w")
 	(FLOATUORS:HF (match_operand:GPI 1 "register_operand" "r")))]
   "TARGET_FP_F16INST"
@@ -4635,6 +4642,53 @@
   [(set_attr "type" "f_cvti2f")]
 )
 
+(define_expand "<optab>sihf2"
+  [(set (match_operand:HF 0 "register_operand")
+	(FLOATUORS:HF (match_operand:SI 1 "register_operand")))]
+  "TARGET_FLOAT"
+{
+  if (TARGET_FP_F16INST)
+    emit_insn (gen_aarch64_fp16_<optab>sihf2 (operands[0], operands[1]));
+  else
+    {
+      rtx convert_target = gen_reg_rtx (DFmode);
+      emit_insn (gen_<optab>sidf2 (convert_target, operands[1]));
+      emit_insn (gen_truncdfhf2 (operands[0], convert_target));
+    }
+  DONE;
+}
+)
+
+;; For DImode there is no wide enough floating-point mode that we
+;; can convert through natively (TFmode would work, but requires a library
+;; call).  However, we know that any value >= 65504 will be rounded
+;; to infinity on conversion.  This is well within the range of SImode, so
+;; we can:
+;;   Saturate to SImode.
+;;   Convert from that to DFmode
+;;   Convert from that to HFmode (phew!).
+;; Note that the saturation to SImode requires the SIMD extensions.  If
+;; we ever need to provide this pattern where the SIMD extensions are not
+;; available, we would need a different approach.
+
+(define_expand "<optab>dihf2"
+  [(set (match_operand:HF 0 "register_operand")
+	(FLOATUORS:HF (match_operand:DI 1 "register_operand")))]
+  "TARGET_FLOAT && (TARGET_FP_F16INST || TARGET_SIMD)"
+{
+  if (TARGET_FP_F16INST)
+    emit_insn (gen_aarch64_fp16_<optab>dihf2 (operands[0], operands[1]));
+  else
+    {
+      rtx sat_target = gen_reg_rtx (SImode);
+      emit_insn (gen_aarch64_<su_optab>qmovndi (sat_target, operands[1]));
+      emit_insn (gen_<optab>sihf2 (operands[0], sat_target));
+    }
+
+  DONE;
+}
+)
+
 ;; Convert between fixed-point and floating-point (scalar modes)
 
 (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn><GPF:mode>3"
diff --git a/gcc/testsuite/gcc.target/aarch64/floatdihf2_1.c b/gcc/testsuite/gcc.target/aarch64/floatdihf2_1.c
new file mode 100644
index 0000000..9eaa4ba
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/floatdihf2_1.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+/* Test that conversion from 32-bit and 64-bit integers can be done
+   without a call to the support library.  */
+
+#pragma GCC target ("arch=armv8.2-a+nofp16")
+
+__fp16
+foo (int x)
+{
+  return x;
+}
+
+__fp16
+bar (unsigned int x)
+{
+  return x;
+}
+
+__fp16
+fool (long long x)
+{
+  return x;
+}
+
+__fp16
+barl (unsigned long long x)
+{
+  return x;
+}
+
+
+/* { dg-final { scan-assembler-not "__float\\\[ds\\\]ihf2" } } */
+/* { dg-final { scan-assembler-not "__floatun\\\[ds\\\]ihf2" } } */

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

* [Patch 15/17 libgcc ARM] Add double to half conversions.
  2016-11-11 15:43   ` [Patch 14/17] [libgcc, ARM] Generalise float-to-half conversion function James Greenhalgh
  2016-11-11 15:43     ` [Patch ARM 17/17] Enable _Float16 for ARM James Greenhalgh
  2016-11-11 15:43     ` [Patch 16/17 libgcc ARM] Half to double precision conversions James Greenhalgh
@ 2016-11-11 15:43     ` 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
  3 siblings, 1 reply; 95+ messages in thread
From: James Greenhalgh @ 2016-11-11 15:43 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, richard.earnshaw, kyrtka01, ramana.radhakrishnan, joseph

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


Hi,

Conversions from double precision floats to the ARM __fp16 are required
to round only once.

This patch adds a functions named __gnu_d2h_ieee and
__gnu_d2h_alternative for double to __fp16 conversions in IEEE and ARM
alternative format. The make use of the existing __gnu_float2h_internal
conversion function which rounds once only.

Bootstrapped on an ARMv8-A machine with no issues, and cross-tested with
a range of multilibs.

OK?

Thanks,
James
---

libgcc/

2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>
	    Matthew Wahab  <matthew.wahab@arm.com>

	* config/arm/fp16.c (binary64): New.
	(__gnu_d2h_internal): New.
	(__gnu_d2h_ieee): New.
	(__gnu_d2h_alternative): New.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0015-Patch-15-17-libgcc-ARM-Add-double-to-half-conversion.patch --]
[-- Type: text/x-patch; name="0015-Patch-15-17-libgcc-ARM-Add-double-to-half-conversion.patch", Size: 1160 bytes --]

diff --git a/libgcc/config/arm/fp16.c b/libgcc/config/arm/fp16.c
index ba89796..a656988 100644
--- a/libgcc/config/arm/fp16.c
+++ b/libgcc/config/arm/fp16.c
@@ -43,6 +43,15 @@ binary32 =
   23    /* significand.  */
 };
 
+static const struct format
+binary64 =
+{
+  64,    /* size.  */
+  1023,  /* bias.  */
+  11,    /* exponent.  */
+  52     /* significand.  */
+};
+
 static inline unsigned short
 __gnu_float2h_internal (const struct format* fmt,
 			unsigned long long a, int ieee)
@@ -136,6 +145,12 @@ __gnu_f2h_internal (unsigned int a, int ieee)
   return __gnu_float2h_internal (&binary32, (unsigned long long) a, ieee);
 }
 
+static inline unsigned short
+__gnu_d2h_internal (unsigned long long a, int ieee)
+{
+  return __gnu_float2h_internal (&binary64, a, ieee);
+}
+
 unsigned int
 __gnu_h2f_internal(unsigned short a, int ieee)
 {
@@ -184,3 +199,15 @@ __gnu_h2f_alternative(unsigned short a)
 {
   return __gnu_h2f_internal(a, 0);
 }
+
+unsigned short
+__gnu_d2h_ieee (unsigned long long a)
+{
+  return __gnu_d2h_internal (a, 1);
+}
+
+unsigned short
+__gnu_d2h_alternative (unsigned long long x)
+{
+  return __gnu_d2h_internal (x, 0);
+}

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

* [Patch 16/17 libgcc ARM] Half to double precision conversions
  2016-11-11 15:43   ` [Patch 14/17] [libgcc, ARM] Generalise float-to-half conversion function James Greenhalgh
  2016-11-11 15:43     ` [Patch ARM 17/17] Enable _Float16 for ARM James Greenhalgh
@ 2016-11-11 15:43     ` James Greenhalgh
  2016-11-16 16:00       ` Kyrill Tkachov
  2016-11-11 15:43     ` [Patch 15/17 libgcc ARM] Add double to half conversions James Greenhalgh
  2016-11-16 16:38     ` [Patch 14/17] [libgcc, ARM] Generalise float-to-half conversion function Kyrill Tkachov
  3 siblings, 1 reply; 95+ messages in thread
From: James Greenhalgh @ 2016-11-11 15:43 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, richard.earnshaw, kyrtka01, ramana.radhakrishnan, joseph

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


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  <james.greenhalgh@arm.com>

	* 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  <james.greenhalgh@arm.com>

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


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0016-Patch-16-17-libgcc-ARM-Half-to-double-precision-conv.patch --]
[-- Type: text/x-patch; name="0016-Patch-16-17-libgcc-ARM-Half-to-double-precision-conv.patch", Size: 9184 bytes --]

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 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);
+      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.
@@ -5684,19 +5699,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 2051f10..d417e92 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;

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

* [Patch 14/17] [libgcc, ARM] Generalise float-to-half conversion function.
  2016-11-11 15:38 ` [Patch v4 0/17] Add support for _Float16 to AArch64 and ARM James Greenhalgh
                     ` (10 preceding siblings ...)
  2016-11-11 15:41   ` [Patch AArch64 11/17] Add floatdihf2 and floatunsdihf2 patterns James Greenhalgh
@ 2016-11-11 15:43   ` James Greenhalgh
  2016-11-11 15:43     ` [Patch ARM 17/17] Enable _Float16 for ARM James Greenhalgh
                       ` (3 more replies)
  2016-11-18 18:19   ` [Patch v4 0/17] Add support for _Float16 to AArch64 and ARM James Greenhalgh
  12 siblings, 4 replies; 95+ messages in thread
From: James Greenhalgh @ 2016-11-11 15:43 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, richard.earnshaw, kyrtka01, ramana.radhakrishnan, joseph

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


Hi,

I'm adapting this patch from work started by Matthew Wahab.

Conversions from double precision floats to the ARM __fp16 are required
to round only once. A conversion function for double to __fp16 to
support this on soft-fp targets. This and the following patch add this
conversion function by reusing the exising float to __fp16 function
config/arm/fp16.c:__gnu_f2h_internal.

This patch generalizes __gnu_f2h_internal by adding a specification of
the source format and reworking the code to make use of it. Initially,
only the binary32 format is supported.

A previous version of this patch had a bug handling rounding, the update
in this patch should be sufficient to fix the bug,

replacing:

>   else
>     mask = 0x00001fff;

With:

     mask = (point - 1) >> 10;

I've tested that fix throwing semi-random bit-patterns at the conversion
function to confirm that the software implementation now matches the
hardware behaviour for this routine.

Additionally, bootstrapped again, and cross-tested with no issues.

OK?

Thanks,
James

----

libgcc/

2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>
	    Matthew Wahab  <matthew.wahab@arm.com>

	* config/arm/fp16.c (struct format): New.
	(binary32): New.
	(__gnu_float2h_internal): New.  Body moved from
	__gnu_f2h_internal and generalize.
	(_gnu_f2h_internal): Move body to function __gnu_float2h_internal.
	Call it with binary32.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0014-Patch-14-17-libgcc-ARM-Generalise-float-to-half-conv.patch --]
[-- Type: text/x-patch; name="0014-Patch-14-17-libgcc-ARM-Generalise-float-to-half-conv.patch", Size: 3295 bytes --]

diff --git a/libgcc/config/arm/fp16.c b/libgcc/config/arm/fp16.c
index 39c863c..ba89796 100644
--- a/libgcc/config/arm/fp16.c
+++ b/libgcc/config/arm/fp16.c
@@ -22,40 +22,74 @@
    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
+struct format
+{
+  /* Number of bits.  */
+  unsigned long long size;
+  /* Exponent bias.  */
+  unsigned long long bias;
+  /* Exponent width in bits.  */
+  unsigned long long exponent;
+  /* Significand precision in explicitly stored bits.  */
+  unsigned long long significand;
+};
+
+static const struct format
+binary32 =
+{
+  32,   /* size.  */
+  127,  /* bias.  */
+  8,    /* exponent.  */
+  23    /* significand.  */
+};
+
 static inline unsigned short
-__gnu_f2h_internal(unsigned int a, int ieee)
+__gnu_float2h_internal (const struct format* fmt,
+			unsigned long long a, int ieee)
 {
-  unsigned short sign = (a >> 16) & 0x8000;
-  int aexp = (a >> 23) & 0xff;
-  unsigned int mantissa = a & 0x007fffff;
-  unsigned int mask;
-  unsigned int increment;
+  unsigned long long point = 1ULL << fmt->significand;;
+  unsigned short sign = (a >> (fmt->size - 16)) & 0x8000;
+  int aexp;
+  unsigned long long mantissa;
+  unsigned long long mask;
+  unsigned long long increment;
+
+  /* Get the exponent and mantissa encodings.  */
+  mantissa = a & (point - 1);
+
+  mask = (1 << fmt->exponent) - 1;
+  aexp = (a >> fmt->significand) & mask;
 
-  if (aexp == 0xff)
+  /* Infinity, NaN and alternative format special case.  */
+  if (((unsigned int) aexp) == mask)
     {
       if (!ieee)
 	return sign;
       if (mantissa == 0)
 	return sign | 0x7c00;	/* Infinity.  */
       /* Remaining cases are NaNs.  Convert SNaN to QNaN.  */
-      return sign | 0x7e00 | (mantissa >> 13);
+      return sign | 0x7e00 | (mantissa >> (fmt->significand - 10));
     }
 
+  /* Zero.  */
   if (aexp == 0 && mantissa == 0)
     return sign;
 
-  aexp -= 127;
+  /* Construct the exponent and mantissa.  */
+  aexp -= fmt->bias;
+
+  /* Decimal point is immediately after the significand.  */
+  mantissa |= point;
 
-  /* Decimal point between bits 22 and 23.  */
-  mantissa |= 0x00800000;
   if (aexp < -14)
     {
-      mask = 0x00ffffff;
+      mask = point | (point - 1);
+      /* Minimum exponent for half-precision is 2^-24.  */
       if (aexp >= -25)
 	mask >>= 25 + aexp;
     }
   else
-    mask = 0x00001fff;
+    mask = (point - 1) >> 10;
 
   /* Round.  */
   if (mantissa & mask)
@@ -64,8 +98,8 @@ __gnu_f2h_internal(unsigned int a, int ieee)
       if ((mantissa & mask) == increment)
 	increment = mantissa & (increment << 1);
       mantissa += increment;
-      if (mantissa >= 0x01000000)
-       	{
+      if (mantissa >= (point << 1))
+	{
 	  mantissa >>= 1;
 	  aexp++;
 	}
@@ -93,7 +127,13 @@ __gnu_f2h_internal(unsigned int a, int ieee)
 
   /* We leave the leading 1 in the mantissa, and subtract one
      from the exponent bias to compensate.  */
-  return sign | (((aexp + 14) << 10) + (mantissa >> 13));
+  return sign | (((aexp + 14) << 10) + (mantissa >> (fmt->significand - 10)));
+}
+
+static inline unsigned short
+__gnu_f2h_internal (unsigned int a, int ieee)
+{
+  return __gnu_float2h_internal (&binary32, (unsigned long long) a, ieee);
 }
 
 unsigned int

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

* [Patch ARM 17/17] Enable _Float16 for ARM.
  2016-11-11 15:43   ` [Patch 14/17] [libgcc, ARM] Generalise float-to-half conversion function James Greenhalgh
@ 2016-11-11 15:43     ` James Greenhalgh
  2016-11-16 14:15       ` Kyrill Tkachov
  2016-11-11 15:43     ` [Patch 16/17 libgcc ARM] Half to double precision conversions James Greenhalgh
                       ` (2 subsequent siblings)
  3 siblings, 1 reply; 95+ messages in thread
From: James Greenhalgh @ 2016-11-11 15:43 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, richard.earnshaw, kyrtka01, ramana.radhakrishnan, joseph

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


Hi,

Finally, having added support for single-step DFmode to HFmode conversions,
this patch adds support for _Float16 to the ARM back-end.

That means making sure that only __fp16 promotes and adding similar hooks to
those used in the AArch64 port giving the excess precision rules, and
marking HFmode as supported in libgcc.

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

OK?

Thanks,
James

---
gcc/

2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>

	PR target/63250
	* config/arm/arm-builtins.c (arm_simd_floatHF_type_node): Rename to...
	(arm_fp16_type_node): ...This, make visibile.
	(arm_simd_builtin_std_type): Rename arm_simd_floatHF_type_node to
	arm_fp16_type_node.
	(arm_init_simd_builtin_types): Likewise.
	(arm_init_fp16_builtins): Likewise.
	* config/arm/arm.c (arm_excess_precision): New.
	(arm_floatn_mode): Likewise.
	(TARGET_C_EXCESS_PRECISION): Likewise.
	(TARGET_FLOATN_MODE): Likewise.
	(arm_promoted_type): Only promote arm_fp16_type_node.
	* config/arm/arm.h (arm_fp16_type_node): Declare.

gcc/testsuite/

2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>

	* lib/target-supports.exp (add_options_for_float16): Add
	-mfp16-format=ieee when testign arm*-*-*.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0017-Patch-ARM-17-17-Enable-_Float16-for-ARM.patch --]
[-- Type: text/x-patch; name="0017-Patch-ARM-17-17-Enable-_Float16-for-ARM.patch", Size: 7583 bytes --]

diff --git a/gcc/config/arm/arm-builtins.c b/gcc/config/arm/arm-builtins.c
index e73043d..5ed38d1 100644
--- a/gcc/config/arm/arm-builtins.c
+++ b/gcc/config/arm/arm-builtins.c
@@ -652,7 +652,8 @@ static struct arm_simd_type_info arm_simd_types [] = {
 };
 #undef ENTRY
 
-static tree arm_simd_floatHF_type_node = NULL_TREE;
+/* The user-visible __fp16 type.  */
+tree arm_fp16_type_node = NULL_TREE;
 static tree arm_simd_intOI_type_node = NULL_TREE;
 static tree arm_simd_intEI_type_node = NULL_TREE;
 static tree arm_simd_intCI_type_node = NULL_TREE;
@@ -739,7 +740,7 @@ arm_simd_builtin_std_type (enum machine_mode mode,
     case XImode:
       return arm_simd_intXI_type_node;
     case HFmode:
-      return arm_simd_floatHF_type_node;
+      return arm_fp16_type_node;
     case SFmode:
       return float_type_node;
     case DFmode:
@@ -840,8 +841,8 @@ arm_init_simd_builtin_types (void)
   /* Continue with standard types.  */
   /* The __builtin_simd{64,128}_float16 types are kept private unless
      we have a scalar __fp16 type.  */
-  arm_simd_types[Float16x4_t].eltype = arm_simd_floatHF_type_node;
-  arm_simd_types[Float16x8_t].eltype = arm_simd_floatHF_type_node;
+  arm_simd_types[Float16x4_t].eltype = arm_fp16_type_node;
+  arm_simd_types[Float16x8_t].eltype = arm_fp16_type_node;
   arm_simd_types[Float32x2_t].eltype = float_type_node;
   arm_simd_types[Float32x4_t].eltype = float_type_node;
 
@@ -1754,11 +1755,11 @@ arm_init_iwmmxt_builtins (void)
 static void
 arm_init_fp16_builtins (void)
 {
-  arm_simd_floatHF_type_node = make_node (REAL_TYPE);
-  TYPE_PRECISION (arm_simd_floatHF_type_node) = GET_MODE_PRECISION (HFmode);
-  layout_type (arm_simd_floatHF_type_node);
+  arm_fp16_type_node = make_node (REAL_TYPE);
+  TYPE_PRECISION (arm_fp16_type_node) = GET_MODE_PRECISION (HFmode);
+  layout_type (arm_fp16_type_node);
   if (arm_fp16_format)
-    (*lang_hooks.types.register_builtin_type) (arm_simd_floatHF_type_node,
+    (*lang_hooks.types.register_builtin_type) (arm_fp16_type_node,
 					       "__fp16");
 }
 
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index b9097c5..4e1d47b 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -266,6 +266,7 @@ static bool arm_builtin_support_vector_misalignment (machine_mode mode,
 						     int misalignment,
 						     bool is_packed);
 static void arm_conditional_register_usage (void);
+static enum flt_eval_method arm_excess_precision (enum excess_precision_type);
 static reg_class_t arm_preferred_rename_class (reg_class_t rclass);
 static unsigned int arm_autovectorize_vector_sizes (void);
 static int arm_default_branch_cost (bool, bool);
@@ -299,6 +300,7 @@ static bool arm_asm_elf_flags_numeric (unsigned int flags, unsigned int *num);
 static unsigned int arm_elf_section_type_flags (tree decl, const char *name,
 						int reloc);
 static void arm_expand_divmod_libfunc (rtx, machine_mode, rtx, rtx, rtx *, rtx *);
+static machine_mode arm_floatn_mode (int, bool);
 \f
 /* Table of machine attributes.  */
 static const struct attribute_spec arm_attribute_table[] =
@@ -444,6 +446,9 @@ static const struct attribute_spec arm_attribute_table[] =
 #undef  TARGET_ASM_INTERNAL_LABEL
 #define TARGET_ASM_INTERNAL_LABEL arm_internal_label
 
+#undef TARGET_FLOATN_MODE
+#define TARGET_FLOATN_MODE arm_floatn_mode
+
 #undef  TARGET_FUNCTION_OK_FOR_SIBCALL
 #define TARGET_FUNCTION_OK_FOR_SIBCALL arm_function_ok_for_sibcall
 
@@ -734,6 +739,9 @@ static const struct attribute_spec arm_attribute_table[] =
 #undef TARGET_EXPAND_DIVMOD_LIBFUNC
 #define TARGET_EXPAND_DIVMOD_LIBFUNC arm_expand_divmod_libfunc
 
+#undef TARGET_C_EXCESS_PRECISION
+#define TARGET_C_EXCESS_PRECISION arm_excess_precision
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
 /* Obstack for minipool constant handling.  */
@@ -22515,7 +22523,9 @@ arm_debugger_arg_offset (int value, rtx addr)
 static tree
 arm_promoted_type (const_tree t)
 {
-  if (SCALAR_FLOAT_TYPE_P (t) && TYPE_PRECISION (t) == 16)
+  if (SCALAR_FLOAT_TYPE_P (t)
+      && TYPE_PRECISION (t) == 16
+      && TYPE_MAIN_VARIANT (t) == arm_fp16_type_node)
     return float_type_node;
   return NULL_TREE;
 }
@@ -22537,6 +22547,61 @@ arm_scalar_mode_supported_p (machine_mode mode)
     return default_scalar_mode_supported_p (mode);
 }
 
+/* Set the value of FLT_EVAL_METHOD.
+   ISO/IEC TS 18661-3 defines two values that we'd like to make use of:
+
+    0: evaluate all operations and constants, whose semantic type has at
+       most the range and precision of type float, to the range and
+       precision of float; evaluate all other operations and constants to
+       the range and precision of the semantic type;
+
+    N, where _FloatN is a supported interchange floating type
+       evaluate all operations and constants, whose semantic type has at
+       most the range and precision of _FloatN type, to the range and
+       precision of the _FloatN type; evaluate all other operations and
+       constants to the range and precision of the semantic type;
+
+   If we have the ARMv8.2-A extensions then we support _Float16 in native
+   precision, so we should set this to 16.  Otherwise, we support the type,
+   but want to evaluate expressions in float precision, so set this to
+   0.  */
+
+static enum flt_eval_method
+arm_excess_precision (enum excess_precision_type type)
+{
+  switch (type)
+    {
+      case EXCESS_PRECISION_TYPE_FAST:
+      case EXCESS_PRECISION_TYPE_STANDARD:
+	/* We can calculate either in 16-bit range and precision or
+	   32-bit range and precision.  Make that decision based on whether
+	   we have native support for the ARMv8.2-A 16-bit floating-point
+	   instructions or not.  */
+	return (TARGET_VFP_FP16INST
+		? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16
+		: FLT_EVAL_METHOD_PROMOTE_TO_FLOAT);
+      case EXCESS_PRECISION_TYPE_IMPLICIT:
+	return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16;
+      default:
+	gcc_unreachable ();
+    }
+  return FLT_EVAL_METHOD_UNPREDICTABLE;
+}
+
+
+/* Implement TARGET_FLOATN_MODE.  Make very sure that we don't provide
+   _Float16 if we are using anything other than ieee format for 16-bit
+   floating point.  Otherwise, punt to the default implementation.  */
+static machine_mode
+arm_floatn_mode (int n, bool extended)
+{
+  if (!extended && n == 16)
+    return arm_fp16_format == ARM_FP16_FORMAT_IEEE ? HFmode : VOIDmode;
+
+  return default_floatn_mode (n, extended);
+}
+
+
 /* Set up OPERANDS for a register copy from SRC to DEST, taking care
    not to early-clobber SRC registers in the process.
 
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index e759720..744e91d 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -73,6 +73,11 @@ extern int arm_ccfsm_state;
 extern GTY(()) rtx arm_target_insn;
 /* Callback to output language specific object attributes.  */
 extern void (*arm_lang_output_object_attributes_hook)(void);
+
+/* This type is the user-visible __fp16.  We need it in a few places in
+   the backend.  Defined in arm-builtins.c.  */
+extern tree arm_fp16_type_node;
+
 \f
 #undef  CPP_SPEC
 #define CPP_SPEC "%(subtarget_cpp_spec)					\
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index b917250..e5f033c 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -2582,6 +2582,9 @@ proc check_effective_target_floatn_nx_runtime {} {
 # the function name.
 
 proc add_options_for_float16 { flags } {
+    if { [istarget arm*-*-*] } {
+	return "$flags -mfp16-format=ieee"
+    }
     return "$flags"
 }
 

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

* Re: [Patch testsuite patch 10/17] Add options for floatN when checking effective target for support
  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
  0 siblings, 0 replies; 95+ messages in thread
From: Joseph Myers @ 2016-11-11 15:59 UTC (permalink / raw)
  To: James Greenhalgh; +Cc: gcc-patches, nd, law

On Fri, 11 Nov 2016, James Greenhalgh wrote:

> 
> Hi,
> 
> As Joseph and I discussed in
> https://gcc.gnu.org/ml/gcc-patches/2016-11/msg00239.html the
> check_effective_target_float<N><x> tests should add any options which the
> target requires to enable those float types (add_options_for_float<N><x>.
> 
> This patch ensures those options get added, which presently only changes
> the testsuite behaviour for the (out-of-tree but submitted for review)
> ARM support for _Float16.
> 
> Tested on arm-none-linux-gnueabihf with those patches applied, to show that
> the _Float16 tests now run.
> 
> OK?

OK, but watch out for any issues reported by people testing on powerpc 
(where I expect this to have the effect of causing the _Float128 / 
_Float64x tests to start running).

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [Patch AArch64 13/17] Enable _Float16 for AArch64
  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)
  2 siblings, 0 replies; 95+ messages in thread
From: Joseph Myers @ 2016-11-11 16:33 UTC (permalink / raw)
  To: James Greenhalgh; +Cc: gcc-patches, nd, richard.earnshaw, marcus.shawcroft

The patches enabling _Float16 should update the paragraph in extend.texi 
about where _Float* types are supported, as it currently says "GCC does 
not currently support @code{_Float16} or @code{_Float128x} on any 
systems.".  (The release notes gcc-7/changes.html will also need 
updating.)

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [Patch 5/17] Add -fpermitted-flt-eval-methods=[c11|ts-18661-3]
  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
  0 siblings, 1 reply; 95+ messages in thread
From: Sandra Loosemore @ 2016-11-12  4:42 UTC (permalink / raw)
  To: James Greenhalgh, gcc-patches; +Cc: nd, joseph, law

On 11/11/2016 08:37 AM, James Greenhalgh wrote:

> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index f133b3a..75ff8ec 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -378,7 +378,8 @@ Objective-C and Objective-C++ Dialects}.
>  -flto-partition=@var{alg} -fmerge-all-constants @gol
>  -fmerge-constants -fmodulo-sched -fmodulo-sched-allow-regmoves @gol
>  -fmove-loop-invariants -fno-branch-count-reg @gol
> --fno-defer-pop -fno-fp-int-builtin-inexact -fno-function-cse @gol
> +-fno-defer-pop -fno-fp-int-builtin-inexact @gol
> +-fpermitted-flt-eval-methods=@var{standard} -fno-function-cse @gol
>  -fno-guess-branch-probability -fno-inline -fno-math-errno -fno-peephole @gol
>  -fno-peephole2 -fno-sched-interblock -fno-sched-spec -fno-signed-zeros @gol
>  -fno-toplevel-reorder -fno-trapping-math -fno-zero-initialized-in-bss @gol

This seems like totally the wrong place to document this.  The new 
option seems more like a code generation option than an optimization 
option, which is what the context of the above patch hunk is.  Moreover, 
the list above is alphabetized and you're sticking the new option in a 
totally random place within the list.

-Sandra

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

* Re: [Patch 5/17] Add -fpermitted-flt-eval-methods=[c11|ts-18661-3]
  2016-11-12  4:42     ` Sandra Loosemore
@ 2016-11-14  9:56       ` James Greenhalgh
  2016-11-14 23:43         ` Sandra Loosemore
  0 siblings, 1 reply; 95+ messages in thread
From: James Greenhalgh @ 2016-11-14  9:56 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, joseph, sandra

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


On Fri, Nov 11, 2016 at 09:42:32PM -0700, Sandra Loosemore wrote:
> On 11/11/2016 08:37 AM, James Greenhalgh wrote:
>
> >diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> >index f133b3a..75ff8ec 100644
> >--- a/gcc/doc/invoke.texi
> >+++ b/gcc/doc/invoke.texi
> >@@ -378,7 +378,8 @@ Objective-C and Objective-C++ Dialects}.
> > -flto-partition=@var{alg} -fmerge-all-constants @gol
> > -fmerge-constants -fmodulo-sched -fmodulo-sched-allow-regmoves @gol
> > -fmove-loop-invariants -fno-branch-count-reg @gol
> >--fno-defer-pop -fno-fp-int-builtin-inexact -fno-function-cse @gol
> >+-fno-defer-pop -fno-fp-int-builtin-inexact @gol
> >+-fpermitted-flt-eval-methods=@var{standard} -fno-function-cse @gol
> > -fno-guess-branch-probability -fno-inline -fno-math-errno -fno-peephole @gol
> > -fno-peephole2 -fno-sched-interblock -fno-sched-spec -fno-signed-zeros @gol
> > -fno-toplevel-reorder -fno-trapping-math -fno-zero-initialized-in-bss @gol
>
> This seems like totally the wrong place to document this.  The new
> option seems more like a code generation option than an optimization
> option, which is what the context of the above patch hunk is.
> Moreover, the list above is alphabetized and you're sticking the new
> option in a totally random place within the list.

Oh! Definitely a case of not seeing the wood for the trees there. All
I knew was that the option was a little bit like -fexcess-precision, but
I completely failed to spot that this list was alpahbetised, or even to
see that the list related to optimisation options!

Sorry for that, I've moved it now to "C Language Options" - which as far as
I can tell is not in alphabetical order, I slotted it in after gnu89-inline
as that made sense to me, but I can move it again if you like. Is that
placement more acceptable?

Thanks,
James

---

gcc/c-family/

2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>

	* c-opts.c (c_common_post_options): Add logic to handle the default
	case for -fpermitted-flt-eval-methods.

gcc/

2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>

	* common.opt (fpermitted-flt-eval-methods): New.
	* doc/invoke.texi (-fpermitted-flt-eval-methods): Document it.
	* flag_types.h (permitted_flt_eval_methods): New.

gcc/testsuite/

2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>

	* gcc.dg/fpermitted-flt-eval-methods_1.c: New.
	* gcc.dg/fpermitted-flt-eval-methods_2.c: New.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Re-Patch-5-17-Add-fpermitted-flt-eval-methods-c11-ts.patch --]
[-- Type: text/x-patch; name="0001-Re-Patch-5-17-Add-fpermitted-flt-eval-methods-c11-ts.patch", Size: 6021 bytes --]

diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
index de260e7..57717ff 100644
--- a/gcc/c-family/c-opts.c
+++ b/gcc/c-family/c-opts.c
@@ -788,6 +788,18 @@ c_common_post_options (const char **pfilename)
       && flag_unsafe_math_optimizations == 0)
     flag_fp_contract_mode = FP_CONTRACT_OFF;
 
+  /* If we are compiling C, and we are outside of a standards mode,
+     we can permit the new values from ISO/IEC TS 18661-3 for
+     FLT_EVAL_METHOD.  Otherwise, we must restrict the possible values to
+     the set specified in ISO C99/C11.  */
+  if (!flag_iso
+      && !c_dialect_cxx ()
+      && (global_options_set.x_flag_permitted_flt_eval_methods
+	  == PERMITTED_FLT_EVAL_METHODS_DEFAULT))
+    flag_permitted_flt_eval_methods = PERMITTED_FLT_EVAL_METHODS_TS_18661;
+  else
+    flag_permitted_flt_eval_methods = PERMITTED_FLT_EVAL_METHODS_C11;
+
   /* By default we use C99 inline semantics in GNU99 or C99 mode.  C99
      inline semantics are not supported in GNU89 or C89 mode.  */
   if (flag_gnu89_inline == -1)
diff --git a/gcc/common.opt b/gcc/common.opt
index 314145a..915c406 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1326,6 +1326,21 @@ Enum(excess_precision) String(fast) Value(EXCESS_PRECISION_FAST)
 EnumValue
 Enum(excess_precision) String(standard) Value(EXCESS_PRECISION_STANDARD)
 
+; Whether we permit the extended set of values for FLT_EVAL_METHOD
+; introduced in ISO/IEC TS 18661-3, or limit ourselves to those in C99/C11.
+fpermitted-flt-eval-methods=
+Common Joined RejectNegative Enum(permitted_flt_eval_methods) Var(flag_permitted_flt_eval_methods) Init(PERMITTED_FLT_EVAL_METHODS_DEFAULT)
+-fpermitted-flt-eval-methods=[c11|ts-18661]	Specify which values of FLT_EVAL_METHOD are permitted.
+
+Enum
+Name(permitted_flt_eval_methods) Type(enum permitted_flt_eval_methods) UnknownError(unknown specification for the set of FLT_EVAL_METHOD values to permit %qs)
+
+EnumValue
+Enum(permitted_flt_eval_methods) String(c11) Value(PERMITTED_FLT_EVAL_METHODS_C11)
+
+EnumValue
+Enum(permitted_flt_eval_methods) String(ts-18661-3) Value(PERMITTED_FLT_EVAL_METHODS_TS_18661)
+
 ffast-math
 Common Optimization
 
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index eb89804..0ec10ba 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -178,6 +178,7 @@ in the following sections.
 @item C Language Options
 @xref{C Dialect Options,,Options Controlling C Dialect}.
 @gccoptlist{-ansi  -std=@var{standard}  -fgnu89-inline @gol
+-fpermitted-flt-eval-methods=@var{standard} @gol
 -aux-info @var{filename} -fallow-parameterless-variadic-functions @gol
 -fno-asm  -fno-builtin  -fno-builtin-@var{function} @gol
 -fhosted  -ffreestanding -fopenacc -fopenmp -fopenmp-simd @gol
@@ -1872,6 +1873,30 @@ The preprocessor macros @code{__GNUC_GNU_INLINE__} and
 in effect for @code{inline} functions.  @xref{Common Predefined
 Macros,,,cpp,The C Preprocessor}.
 
+@item -fpermitted-flt-eval-methods=@var{style}
+@opindex fpermitted-flt-eval-methods
+@opindex fpermitted-flt-eval-methods=c11
+@opindex fpermitted-flt-eval-methods=ts-18661-3
+ISO/IEC TS 18661-3 defines new permissible values for
+@code{FLT_EVAL_METHOD} that indicate that operations and constants with
+a semantic type that is an interchange or extended format should be
+evaluated to the precision and range of that type.  These new values are
+a superset of those permitted under C99/C11, which does not specify the
+meaning of other positive values of @code{FLT_EVAL_METHOD}.  As such, code
+conforming to C11 may not have been written expecting the possibility of
+the new values.
+
+@option{-fpermitted-flt-eval-methods} specifies whether the compiler
+should allow only the values of @code{FLT_EVAL_METHOD} specified in C99/C11,
+or the extended set of values specified in ISO/IEC TS 18661-3.
+
+@var{style} is either @code{c11} or @code{ts-18661-3} as appropriate.
+
+The default when in a standards compliant mode (@option{-std=c11} or similar)
+is @option{-fpermitted-flt-eval-methods=c11}.  The default when in a GNU
+dialect (@option{-std=gnu11} or similar) is
+@option{-fpermitted-flt-eval-methods=ts-18661-3}.
+
 @item -aux-info @var{filename}
 @opindex aux-info
 Output to the given filename prototyped declarations for all functions
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index 6c5a4cc..d69f8f4 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -158,6 +158,14 @@ enum excess_precision
   EXCESS_PRECISION_STANDARD
 };
 
+/* The options for which values of FLT_EVAL_METHOD are permissible.  */
+enum permitted_flt_eval_methods
+{
+  PERMITTED_FLT_EVAL_METHODS_DEFAULT,
+  PERMITTED_FLT_EVAL_METHODS_TS_18661,
+  PERMITTED_FLT_EVAL_METHODS_C11
+};
+
 /* Type of stack check.  */
 enum stack_check_type
 {
diff --git a/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_1.c b/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_1.c
new file mode 100644
index 0000000..c022f86
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_1.c
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+/* { dg-options "-std=c11" } */
+
+/* Test that we only see the C99/C11 values for __FLT_EVAL_METHOD__ if
+   we are compiling with -std=c11.  */
+
+int main (int argc, char** argv)
+{
+  switch (__FLT_EVAL_METHOD__)
+    {
+      case 0:
+      case 1:
+      case 2:
+      case -1:
+	return 0;
+      default:
+	return 1;
+    }
+}
diff --git a/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_2.c b/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_2.c
new file mode 100644
index 0000000..a76ea7e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/fpermitted-flt-eval-methods_2.c
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+/* { dg-options "-fpermitted-flt-eval-methods=c11" } */
+
+/* Test that we only see the C99/C11 values for __FLT_EVAL_METHOD__ if
+   we are compiling with -fpermitted-flt-eval-methods=c11.  */
+
+int main (int argc, char** argv)
+{
+  switch (__FLT_EVAL_METHOD__)
+    {
+      case 0:
+      case 1:
+      case 2:
+      case -1:
+	return 0;
+      default:
+	return 1;
+    }
+}

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

* Re: [Patch 5/17] Add -fpermitted-flt-eval-methods=[c11|ts-18661-3]
  2016-11-14  9:56       ` James Greenhalgh
@ 2016-11-14 23:43         ` Sandra Loosemore
  0 siblings, 0 replies; 95+ messages in thread
From: Sandra Loosemore @ 2016-11-14 23:43 UTC (permalink / raw)
  To: James Greenhalgh, gcc-patches; +Cc: nd, joseph

On 11/14/2016 02:55 AM, James Greenhalgh wrote:
>
> On Fri, Nov 11, 2016 at 09:42:32PM -0700, Sandra Loosemore wrote:
>> On 11/11/2016 08:37 AM, James Greenhalgh wrote:
>>
>>> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
>>> index f133b3a..75ff8ec 100644
>>> --- a/gcc/doc/invoke.texi
>>> +++ b/gcc/doc/invoke.texi
>>> @@ -378,7 +378,8 @@ Objective-C and Objective-C++ Dialects}.
>>> -flto-partition=@var{alg} -fmerge-all-constants @gol
>>> -fmerge-constants -fmodulo-sched -fmodulo-sched-allow-regmoves @gol
>>> -fmove-loop-invariants -fno-branch-count-reg @gol
>>> --fno-defer-pop -fno-fp-int-builtin-inexact -fno-function-cse @gol
>>> +-fno-defer-pop -fno-fp-int-builtin-inexact @gol
>>> +-fpermitted-flt-eval-methods=@var{standard} -fno-function-cse @gol
>>> -fno-guess-branch-probability -fno-inline -fno-math-errno -fno-peephole @gol
>>> -fno-peephole2 -fno-sched-interblock -fno-sched-spec -fno-signed-zeros @gol
>>> -fno-toplevel-reorder -fno-trapping-math -fno-zero-initialized-in-bss @gol
>>
>> This seems like totally the wrong place to document this.  The new
>> option seems more like a code generation option than an optimization
>> option, which is what the context of the above patch hunk is.
>> Moreover, the list above is alphabetized and you're sticking the new
>> option in a totally random place within the list.
>
> Oh! Definitely a case of not seeing the wood for the trees there. All
> I knew was that the option was a little bit like -fexcess-precision, but
> I completely failed to spot that this list was alpahbetised, or even to
> see that the list related to optimisation options!
>
> Sorry for that, I've moved it now to "C Language Options" - which as far as
> I can tell is not in alphabetical order, I slotted it in after gnu89-inline
> as that made sense to me, but I can move it again if you like. Is that
> placement more acceptable?

Yes, this version of the doc patch looks fine.  Thank you!

-Sandra

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

* Re: [Patch ARM 17/17] Enable _Float16 for ARM.
  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
  0 siblings, 1 reply; 95+ messages in thread
From: Kyrill Tkachov @ 2016-11-16 14:15 UTC (permalink / raw)
  To: James Greenhalgh, gcc-patches
  Cc: richard.earnshaw, ramana.radhakrishnan, joseph


On 11/11/16 15:42, James Greenhalgh wrote:
> Hi,
>
> Finally, having added support for single-step DFmode to HFmode conversions,
> this patch adds support for _Float16 to the ARM back-end.
>
> That means making sure that only __fp16 promotes and adding similar hooks to
> those used in the AArch64 port giving the excess precision rules, and
> marking HFmode as supported in libgcc.
>
> Bootstrapped on an ARMv8-A machine, and crosstested with no issues.
>
> OK?

This looks ok to me once the prerequisites are approved.

Thanks,
Kyrill

> Thanks,
> James
>
> ---
> gcc/
>
> 2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>
>
> 	PR target/63250
> 	* config/arm/arm-builtins.c (arm_simd_floatHF_type_node): Rename to...
> 	(arm_fp16_type_node): ...This, make visibile.
> 	(arm_simd_builtin_std_type): Rename arm_simd_floatHF_type_node to
> 	arm_fp16_type_node.
> 	(arm_init_simd_builtin_types): Likewise.
> 	(arm_init_fp16_builtins): Likewise.
> 	* config/arm/arm.c (arm_excess_precision): New.
> 	(arm_floatn_mode): Likewise.
> 	(TARGET_C_EXCESS_PRECISION): Likewise.
> 	(TARGET_FLOATN_MODE): Likewise.
> 	(arm_promoted_type): Only promote arm_fp16_type_node.
> 	* config/arm/arm.h (arm_fp16_type_node): Declare.
>
> gcc/testsuite/
>
> 2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>
>
> 	* lib/target-supports.exp (add_options_for_float16): Add
> 	-mfp16-format=ieee when testign arm*-*-*.
>

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

* Re: [Patch 15/17 libgcc ARM] Add double to half conversions.
  2016-11-11 15:43     ` [Patch 15/17 libgcc ARM] Add double to half conversions James Greenhalgh
@ 2016-11-16 14:46       ` Kyrill Tkachov
  0 siblings, 0 replies; 95+ messages in thread
From: Kyrill Tkachov @ 2016-11-16 14:46 UTC (permalink / raw)
  To: James Greenhalgh, gcc-patches
  Cc: nd, richard.earnshaw, kyrtka01, ramana.radhakrishnan, joseph


On 11/11/16 15:42, James Greenhalgh wrote:
> Hi,
>
> Conversions from double precision floats to the ARM __fp16 are required
> to round only once.
>
> This patch adds a functions named __gnu_d2h_ieee and
> __gnu_d2h_alternative for double to __fp16 conversions in IEEE and ARM
> alternative format. The make use of the existing __gnu_float2h_internal
> conversion function which rounds once only.
>
> Bootstrapped on an ARMv8-A machine with no issues, and cross-tested with
> a range of multilibs.
>
> OK?

Ok.
Thanks,
Kyrill

> Thanks,
> James
> ---
>
> libgcc/
>
> 2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>
> 	    Matthew Wahab  <matthew.wahab@arm.com>
>
> 	* config/arm/fp16.c (binary64): New.
> 	(__gnu_d2h_internal): New.
> 	(__gnu_d2h_ieee): New.
> 	(__gnu_d2h_alternative): New.
>

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

* Re: [Patch 16/17 libgcc ARM] Half to double precision conversions
  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
  0 siblings, 1 reply; 95+ messages in thread
From: Kyrill Tkachov @ 2016-11-16 16:00 UTC (permalink / raw)
  To: James Greenhalgh, gcc-patches
  Cc: richard.earnshaw, kyrtka01, ramana.radhakrishnan, joseph


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  <james.greenhalgh@arm.com>
>
> 	* 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  <james.greenhalgh@arm.com>
>
> 	* 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

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

* Re: [Patch 14/17] [libgcc, ARM] Generalise float-to-half conversion function.
  2016-11-11 15:43   ` [Patch 14/17] [libgcc, ARM] Generalise float-to-half conversion function James Greenhalgh
                       ` (2 preceding siblings ...)
  2016-11-11 15:43     ` [Patch 15/17 libgcc ARM] Add double to half conversions James Greenhalgh
@ 2016-11-16 16:38     ` Kyrill Tkachov
  2016-11-23 18:18       ` James Greenhalgh
  3 siblings, 1 reply; 95+ messages in thread
From: Kyrill Tkachov @ 2016-11-16 16:38 UTC (permalink / raw)
  To: James Greenhalgh, gcc-patches
  Cc: richard.earnshaw, ramana.radhakrishnan, joseph

Hi James,

On 11/11/16 15:42, James Greenhalgh wrote:
> Hi,
>
> I'm adapting this patch from work started by Matthew Wahab.
>
> Conversions from double precision floats to the ARM __fp16 are required
> to round only once. A conversion function for double to __fp16 to
> support this on soft-fp targets. This and the following patch add this
> conversion function by reusing the exising float to __fp16 function
> config/arm/fp16.c:__gnu_f2h_internal.
>
> This patch generalizes __gnu_f2h_internal by adding a specification of
> the source format and reworking the code to make use of it. Initially,
> only the binary32 format is supported.
>
> A previous version of this patch had a bug handling rounding, the update
> in this patch should be sufficient to fix the bug,
>
> replacing:
>
>>    else
>>      mask = 0x00001fff;
> With:
>
>       mask = (point - 1) >> 10;
>
> I've tested that fix throwing semi-random bit-patterns at the conversion
> function to confirm that the software implementation now matches the
> hardware behaviour for this routine.
>
> Additionally, bootstrapped again, and cross-tested with no issues.
>
> OK?
>
> Thanks,
> James
>
> ----
>
> libgcc/
>
> 2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>
> 	    Matthew Wahab  <matthew.wahab@arm.com>
>
> 	* config/arm/fp16.c (struct format): New.
> 	(binary32): New.
> 	(__gnu_float2h_internal): New.  Body moved from
> 	__gnu_f2h_internal and generalize.
> 	(_gnu_f2h_internal): Move body to function __gnu_float2h_internal.
> 	Call it with binary32.
>

diff --git a/libgcc/config/arm/fp16.c b/libgcc/config/arm/fp16.c
index 39c863c..ba89796 100644
--- a/libgcc/config/arm/fp16.c
+++ b/libgcc/config/arm/fp16.c
@@ -22,40 +22,74 @@
     see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     <http://www.gnu.org/licenses/>.  */
  
+struct format
+{
+  /* Number of bits.  */
+  unsigned long long size;
+  /* Exponent bias.  */
+  unsigned long long bias;
+  /* Exponent width in bits.  */
+  unsigned long long exponent;
+  /* Significand precision in explicitly stored bits.  */
+  unsigned long long significand;
+};
+
+static const struct format
+binary32 =
+{
+  32,   /* size.  */
+  127,  /* bias.  */
+  8,    /* exponent.  */
+  23    /* significand.  */
+};
+
  static inline unsigned short
-__gnu_f2h_internal(unsigned int a, int ieee)
+__gnu_float2h_internal (const struct format* fmt,
+			unsigned long long a, int ieee)
  {
-  unsigned short sign = (a >> 16) & 0x8000;
-  int aexp = (a >> 23) & 0xff;
-  unsigned int mantissa = a & 0x007fffff;
-  unsigned int mask;
-  unsigned int increment;
+  unsigned long long point = 1ULL << fmt->significand;;

Trailing ';'.

<...>
@@ -93,7 +127,13 @@ __gnu_f2h_internal(unsigned int a, int ieee)
  
    /* We leave the leading 1 in the mantissa, and subtract one
       from the exponent bias to compensate.  */
-  return sign | (((aexp + 14) << 10) + (mantissa >> 13));
+  return sign | (((aexp + 14) << 10) + (mantissa >> (fmt->significand - 10)));
+}

I suppose I'm not very familiar with the soft-fp code but I don't see at a glance how
the comment relates to the operation it's above of (where is the 'one' being subtracted
from the bias?). If you want to improve that comment or give me a quick explanation of why
the code does what it says it does it would be appreciated.

I've gone through the generalisation and it looks correct to me.
So given that you have put this through the testing you say you did this is ok with the nits
above addressed.

Thanks,
Kyrill


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

* Re: [Patch v4 0/17] Add support for _Float16 to AArch64 and ARM
  2016-11-11 15:38 ` [Patch v4 0/17] Add support for _Float16 to AArch64 and ARM James Greenhalgh
                     ` (11 preceding siblings ...)
  2016-11-11 15:43   ` [Patch 14/17] [libgcc, ARM] Generalise float-to-half conversion function James Greenhalgh
@ 2016-11-18 18:19   ` James Greenhalgh
  2016-11-21  9:19     ` Kyrill Tkachov
  12 siblings, 1 reply; 95+ messages in thread
From: James Greenhalgh @ 2016-11-18 18:19 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, joseph, law

On Fri, Nov 11, 2016 at 03:37:17PM +0000, James Greenhalgh wrote:
> 
> Hi,
> 
> This patch set enables the _Float16 type specified in ISO/IEC TS 18661-3
> for AArch64 and ARM. The patch set has been posted over the past two months,
> with many of the target-independent changes approved. I'm reposting it in
> entirity in the form I hope to commit it to trunk.
> 
> The patch set can be roughly split in three; first, hookization of
> TARGET_FLT_EVAL_METHOD, and changes to the excess precision logic in the
> compiler to handle the new values for FLT_EVAL_METHOD defined in
> ISO/IEC TS-18661-3. Second, the AArch64 changes required to enable _Float16,
> and finally the ARM changes required to enable _Float16.
> 
> The broad goals and an outline of each patch in the patch set were
> described in https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02383.html .
> As compared to the original submission, the patch set has grown an ARM
> port, and has had several rounds of technical review on the target
> independent aspects.
> 
> This has resulted in many of the patches already being approved, a full
> summary of the status of each ticket is immediately below.
> 
> Clearly the focus for review of this patch set now needs to be the AArch64
> and ARM ports, I hope the appropriate maintainers will be able to do so in
> time for the patch set to be accepted for GCC 7.
> 
> I've built and tested the full patch set on ARM (cross and native),
> AArch64 (cross and native) and x86_64 (native) with no identified issues.

All the target independent changes are now approved, and all the ARM patches
have been approved (two are conditional on minor changes).

I'd like to apply the target independent and ARM changes to trunk, while I
wait for approval of the AArch64 changes. The changes for the two ports should
be independent. Would that be acceptable, or would you prefer me to wait
for review of the AArch64 changes?

I will then send a follow-up patch for doc/extend.texi detailing the
availability of _Float16 on ARM (I'm holding off on doing this until I know
which order the ARM and AArch64 parts will go in).

Thanks,
James

> ------------------
> Target independent changes
> 
> 10 patches, 9 previously approved, 1 New implementing testsuite
> changes to enable _Float16 tests in more circumstances on ARM.
> ------------------
> 
> [Patch 1/17] Add a new target hook for describing excess precision intentions
> 
>   Approved: https://gcc.gnu.org/ml/gcc-patches/2016-11/msg00781.html
> 
> [Patch 2/17] Implement TARGET_C_EXCESS_PRECISION for i386
> 
>   Blanket approved by Jeff in:
>     https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02402.html
> 
> [Patch 3/17] Implement TARGET_C_EXCESS_PRECISION for s390
> 
>   Approved: https://gcc.gnu.org/ml/gcc-patches/2016-10/msg01554.html
> 
> [Patch 4/17] Implement TARGET_C_EXCESS_PRECISION for m68k
> 
>   Blanket approved by Jeff in:
>     https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02402.html
>   And by Andreas: https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02414.html
> 
>   There was a typo in the original patch, fixed in:
>     https://gcc.gnu.org/ml/gcc-patches/2016-10/msg01173.html
>   which I would apply as an "obvious" fix to the original patch.
> 
> [Patch 5/17] Add -fpermitted-flt-eval-methods=[c11|ts-18661-3]
> 
>   Approved: https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02405.html
> 
>   Joseph had a comment in
>   https://gcc.gnu.org/ml/gcc-patches/2016-10/msg00335.html that the tests
>   should check FLT_EVAL_METHOD from <float.h> rather than
>   __FLT_EVAL_METHOD__. Rather than implement that suggestion, I added tests
>   to patch 6 which tested the <float.h> macro, and left the tests in this
>   patch testing the internal macro.
> 
> [Patch 6/17] Migrate excess precision logic to use TARGET_EXCESS_PRECISION
> 
>   Approved (after removing a rebase bug):
>   https://gcc.gnu.org/ml/gcc-patches/2016-11/msg00231.html
> 
> [Patch 7/17] Delete TARGET_FLT_EVAL_METHOD and poison it.
> 
>   Approved: https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02401.html
> 
> [Patch 8/17] Make _Float16 available if HFmode is available
> 
>   Approved: https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02403.html
> 
> [Patch libgcc 9/17] Update soft-fp from glibc
> 
>   Self approved under policy that we can update libraries which GCC mirrors
>   without further approval.
> 
> [Patch testsuite patch 10/17] Add options for floatN when checking effective target for support
> 
>   NEW!
> 
> ----------------
> AArch64 changes
> 
> 3 patches, none reviewed
> ----------------
> 
> [Patch AArch64 11/17] Add floatdihf2 and floatunsdihf2 patterns
> 
>   Not reviewed, last pinged (^6):
>   https://gcc.gnu.org/ml/gcc-patches/2016-11/msg00584.html
> 
> [Patch libgcc AArch64 12/17] Enable hfmode soft-float conversions and truncations
> 
>   Not reviewed:
>   https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02395.html
> 
> [Patch AArch64 13/17] Enable _Float16 for AArch64
> 
>   Not reviewed:
>   https://gcc.gnu.org/ml/gcc-patches/2016-10/msg01176.html
> 
> ----------------
> ARM changes
> 
> 4 patches, none OK'ed
> ----------------
> [Patch 14/17] [libgcc, ARM] Generalise float-to-half conversion function.
> 
>   Respun in this submission to avoid a bug identified during extended
>   multilib testing, original submission here:
>   https://gcc.gnu.org/ml/gcc-patches/2016-11/msg00714.html
> 
> [Patch 15/17 libgcc] Add double to half conversions.
> 
>   Reviewed, but not approved:
>   https://gcc.gnu.org/ml/gcc-patches/2016-10/msg01975.html
> 
>   Changes were required to patch 16/17, and patch 10/17 was introduced to
>   implement the suggested testsuite patch. The original patch still stands,
>   and needs reviewed:
>   https://gcc.gnu.org/ml/gcc-patches/2016-10/msg01914.html
> 
> [Patch 16/17 ARM] Half to double precision conversions
> 
>   Resubmitted: https://gcc.gnu.org/ml/gcc-patches/2016-11/msg00233.html
>   Needs review.
> 
> [Patch ARM 17/17] Enable _Float16 for ARM.
> 
>   Resubmitted: https://gcc.gnu.org/ml/gcc-patches/2016-11/msg00234.html
>   Needs review.
> 
> 
> 

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

* Re: [Patch v4 0/17] Add support for _Float16 to AArch64 and ARM
  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
  0 siblings, 1 reply; 95+ messages in thread
From: Kyrill Tkachov @ 2016-11-21  9:19 UTC (permalink / raw)
  To: James Greenhalgh, gcc-patches; +Cc: joseph, law


On 18/11/16 18:19, James Greenhalgh wrote:
> On Fri, Nov 11, 2016 at 03:37:17PM +0000, James Greenhalgh wrote:
>> Hi,
>>
>> This patch set enables the _Float16 type specified in ISO/IEC TS 18661-3
>> for AArch64 and ARM. The patch set has been posted over the past two months,
>> with many of the target-independent changes approved. I'm reposting it in
>> entirity in the form I hope to commit it to trunk.
>>
>> The patch set can be roughly split in three; first, hookization of
>> TARGET_FLT_EVAL_METHOD, and changes to the excess precision logic in the
>> compiler to handle the new values for FLT_EVAL_METHOD defined in
>> ISO/IEC TS-18661-3. Second, the AArch64 changes required to enable _Float16,
>> and finally the ARM changes required to enable _Float16.
>>
>> The broad goals and an outline of each patch in the patch set were
>> described in https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02383.html .
>> As compared to the original submission, the patch set has grown an ARM
>> port, and has had several rounds of technical review on the target
>> independent aspects.
>>
>> This has resulted in many of the patches already being approved, a full
>> summary of the status of each ticket is immediately below.
>>
>> Clearly the focus for review of this patch set now needs to be the AArch64
>> and ARM ports, I hope the appropriate maintainers will be able to do so in
>> time for the patch set to be accepted for GCC 7.
>>
>> I've built and tested the full patch set on ARM (cross and native),
>> AArch64 (cross and native) and x86_64 (native) with no identified issues.
> All the target independent changes are now approved, and all the ARM patches
> have been approved (two are conditional on minor changes).
>
> I'd like to apply the target independent and ARM changes to trunk, while I
> wait for approval of the AArch64 changes. The changes for the two ports should
> be independent. Would that be acceptable, or would you prefer me to wait
> for review of the AArch64 changes?

That's fine with me (I'd like to start getting the new features in to trunk so
they can start getting the stage 3 testing).

Kyrill

> I will then send a follow-up patch for doc/extend.texi detailing the
> availability of _Float16 on ARM (I'm holding off on doing this until I know
> which order the ARM and AArch64 parts will go in).
>
> Thanks,
> James
>
>> ------------------
>> Target independent changes
>>
>> 10 patches, 9 previously approved, 1 New implementing testsuite
>> changes to enable _Float16 tests in more circumstances on ARM.
>> ------------------
>>
>> [Patch 1/17] Add a new target hook for describing excess precision intentions
>>
>>    Approved: https://gcc.gnu.org/ml/gcc-patches/2016-11/msg00781.html
>>
>> [Patch 2/17] Implement TARGET_C_EXCESS_PRECISION for i386
>>
>>    Blanket approved by Jeff in:
>>      https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02402.html
>>
>> [Patch 3/17] Implement TARGET_C_EXCESS_PRECISION for s390
>>
>>    Approved: https://gcc.gnu.org/ml/gcc-patches/2016-10/msg01554.html
>>
>> [Patch 4/17] Implement TARGET_C_EXCESS_PRECISION for m68k
>>
>>    Blanket approved by Jeff in:
>>      https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02402.html
>>    And by Andreas: https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02414.html
>>
>>    There was a typo in the original patch, fixed in:
>>      https://gcc.gnu.org/ml/gcc-patches/2016-10/msg01173.html
>>    which I would apply as an "obvious" fix to the original patch.
>>
>> [Patch 5/17] Add -fpermitted-flt-eval-methods=[c11|ts-18661-3]
>>
>>    Approved: https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02405.html
>>
>>    Joseph had a comment in
>>    https://gcc.gnu.org/ml/gcc-patches/2016-10/msg00335.html that the tests
>>    should check FLT_EVAL_METHOD from <float.h> rather than
>>    __FLT_EVAL_METHOD__. Rather than implement that suggestion, I added tests
>>    to patch 6 which tested the <float.h> macro, and left the tests in this
>>    patch testing the internal macro.
>>
>> [Patch 6/17] Migrate excess precision logic to use TARGET_EXCESS_PRECISION
>>
>>    Approved (after removing a rebase bug):
>>    https://gcc.gnu.org/ml/gcc-patches/2016-11/msg00231.html
>>
>> [Patch 7/17] Delete TARGET_FLT_EVAL_METHOD and poison it.
>>
>>    Approved: https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02401.html
>>
>> [Patch 8/17] Make _Float16 available if HFmode is available
>>
>>    Approved: https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02403.html
>>
>> [Patch libgcc 9/17] Update soft-fp from glibc
>>
>>    Self approved under policy that we can update libraries which GCC mirrors
>>    without further approval.
>>
>> [Patch testsuite patch 10/17] Add options for floatN when checking effective target for support
>>
>>    NEW!
>>
>> ----------------
>> AArch64 changes
>>
>> 3 patches, none reviewed
>> ----------------
>>
>> [Patch AArch64 11/17] Add floatdihf2 and floatunsdihf2 patterns
>>
>>    Not reviewed, last pinged (^6):
>>    https://gcc.gnu.org/ml/gcc-patches/2016-11/msg00584.html
>>
>> [Patch libgcc AArch64 12/17] Enable hfmode soft-float conversions and truncations
>>
>>    Not reviewed:
>>    https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02395.html
>>
>> [Patch AArch64 13/17] Enable _Float16 for AArch64
>>
>>    Not reviewed:
>>    https://gcc.gnu.org/ml/gcc-patches/2016-10/msg01176.html
>>
>> ----------------
>> ARM changes
>>
>> 4 patches, none OK'ed
>> ----------------
>> [Patch 14/17] [libgcc, ARM] Generalise float-to-half conversion function.
>>
>>    Respun in this submission to avoid a bug identified during extended
>>    multilib testing, original submission here:
>>    https://gcc.gnu.org/ml/gcc-patches/2016-11/msg00714.html
>>
>> [Patch 15/17 libgcc] Add double to half conversions.
>>
>>    Reviewed, but not approved:
>>    https://gcc.gnu.org/ml/gcc-patches/2016-10/msg01975.html
>>
>>    Changes were required to patch 16/17, and patch 10/17 was introduced to
>>    implement the suggested testsuite patch. The original patch still stands,
>>    and needs reviewed:
>>    https://gcc.gnu.org/ml/gcc-patches/2016-10/msg01914.html
>>
>> [Patch 16/17 ARM] Half to double precision conversions
>>
>>    Resubmitted: https://gcc.gnu.org/ml/gcc-patches/2016-11/msg00233.html
>>    Needs review.
>>
>> [Patch ARM 17/17] Enable _Float16 for ARM.
>>
>>    Resubmitted: https://gcc.gnu.org/ml/gcc-patches/2016-11/msg00234.html
>>    Needs review.
>>
>>
>>

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

* Re: [Patch v4 0/17] Add support for _Float16 to AArch64 and ARM
  2016-11-21  9:19     ` Kyrill Tkachov
@ 2016-11-23 17:05       ` James Greenhalgh
  0 siblings, 0 replies; 95+ messages in thread
From: James Greenhalgh @ 2016-11-23 17:05 UTC (permalink / raw)
  To: Kyrill Tkachov
  Cc: gcc-patches, joseph, law, nd, richard.earnshaw, ramana.radhakrishnan

On Mon, Nov 21, 2016 at 09:19:35AM +0000, Kyrill Tkachov wrote:
> 
> On 18/11/16 18:19, James Greenhalgh wrote:
> >On Fri, Nov 11, 2016 at 03:37:17PM +0000, James Greenhalgh wrote:
> >>Hi,
> >>
> >>This patch set enables the _Float16 type specified in ISO/IEC TS 18661-3
> >>for AArch64 and ARM. The patch set has been posted over the past two months,
> >>with many of the target-independent changes approved. I'm reposting it in
> >>entirity in the form I hope to commit it to trunk.
> >>
> >>The patch set can be roughly split in three; first, hookization of
> >>TARGET_FLT_EVAL_METHOD, and changes to the excess precision logic in the
> >>compiler to handle the new values for FLT_EVAL_METHOD defined in
> >>ISO/IEC TS-18661-3. Second, the AArch64 changes required to enable _Float16,
> >>and finally the ARM changes required to enable _Float16.
> >>
> >>The broad goals and an outline of each patch in the patch set were
> >>described in https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02383.html .
> >>As compared to the original submission, the patch set has grown an ARM
> >>port, and has had several rounds of technical review on the target
> >>independent aspects.
> >>
> >>This has resulted in many of the patches already being approved, a full
> >>summary of the status of each ticket is immediately below.
> >>
> >>Clearly the focus for review of this patch set now needs to be the AArch64
> >>and ARM ports, I hope the appropriate maintainers will be able to do so in
> >>time for the patch set to be accepted for GCC 7.
> >>
> >>I've built and tested the full patch set on ARM (cross and native),
> >>AArch64 (cross and native) and x86_64 (native) with no identified issues.
> >All the target independent changes are now approved, and all the ARM patches
> >have been approved (two are conditional on minor changes).
> >
> >I'd like to apply the target independent and ARM changes to trunk, while I
> >wait for approval of the AArch64 changes. The changes for the two ports should
> >be independent. Would that be acceptable, or would you prefer me to wait
> >for review of the AArch64 changes?
> 
> That's fine with me (I'd like to start getting the new features in to trunk so
> they can start getting the stage 3 testing).

I haven't seen any other objections to this, and I too would like to ensure
that the changes get as much Stage 3 testing across multiple architectures
as I can.

As the three AArch64 patches can be considered independent, I'll push the
target independent changes and the ARM changes now.

I've rerun a bootstrap on x86-64 and ARM before doing so, and there are
still no regressions.

That leaves these patches outstanding for AArch64 (which I'd like to ping).

----------------
AArch64 changes

3 patches, none reviewed
----------------

[Patch AArch64 11/17] Add floatdihf2 and floatunsdihf2 patterns

   Not reviewed, last pinged (^6):
   https://gcc.gnu.org/ml/gcc-patches/2016-11/msg00584.html

[Patch libgcc AArch64 12/17] Enable hfmode soft-float conversions and truncations

   Not reviewed:
   https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02395.html

[Patch AArch64 13/17] Enable _Float16 for AArch64

   Not reviewed:
   https://gcc.gnu.org/ml/gcc-patches/2016-10/msg01176.html

Thanks,
James

> 
> Kyrill
> 
> >I will then send a follow-up patch for doc/extend.texi detailing the
> >availability of _Float16 on ARM (I'm holding off on doing this until I know
> >which order the ARM and AArch64 parts will go in).
> >
> >Thanks,
> >James
> >
> >>------------------
> >>Target independent changes
> >>
> >>10 patches, 9 previously approved, 1 New implementing testsuite
> >>changes to enable _Float16 tests in more circumstances on ARM.
> >>------------------
> >>
> >>[Patch 1/17] Add a new target hook for describing excess precision intentions
> >>
> >>   Approved: https://gcc.gnu.org/ml/gcc-patches/2016-11/msg00781.html
> >>
> >>[Patch 2/17] Implement TARGET_C_EXCESS_PRECISION for i386
> >>
> >>   Blanket approved by Jeff in:
> >>     https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02402.html
> >>
> >>[Patch 3/17] Implement TARGET_C_EXCESS_PRECISION for s390
> >>
> >>   Approved: https://gcc.gnu.org/ml/gcc-patches/2016-10/msg01554.html
> >>
> >>[Patch 4/17] Implement TARGET_C_EXCESS_PRECISION for m68k
> >>
> >>   Blanket approved by Jeff in:
> >>     https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02402.html
> >>   And by Andreas: https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02414.html
> >>
> >>   There was a typo in the original patch, fixed in:
> >>     https://gcc.gnu.org/ml/gcc-patches/2016-10/msg01173.html
> >>   which I would apply as an "obvious" fix to the original patch.
> >>
> >>[Patch 5/17] Add -fpermitted-flt-eval-methods=[c11|ts-18661-3]
> >>
> >>   Approved: https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02405.html
> >>
> >>   Joseph had a comment in
> >>   https://gcc.gnu.org/ml/gcc-patches/2016-10/msg00335.html that the tests
> >>   should check FLT_EVAL_METHOD from <float.h> rather than
> >>   __FLT_EVAL_METHOD__. Rather than implement that suggestion, I added tests
> >>   to patch 6 which tested the <float.h> macro, and left the tests in this
> >>   patch testing the internal macro.
> >>
> >>[Patch 6/17] Migrate excess precision logic to use TARGET_EXCESS_PRECISION
> >>
> >>   Approved (after removing a rebase bug):
> >>   https://gcc.gnu.org/ml/gcc-patches/2016-11/msg00231.html
> >>
> >>[Patch 7/17] Delete TARGET_FLT_EVAL_METHOD and poison it.
> >>
> >>   Approved: https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02401.html
> >>
> >>[Patch 8/17] Make _Float16 available if HFmode is available
> >>
> >>   Approved: https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02403.html
> >>
> >>[Patch libgcc 9/17] Update soft-fp from glibc
> >>
> >>   Self approved under policy that we can update libraries which GCC mirrors
> >>   without further approval.
> >>
> >>[Patch testsuite patch 10/17] Add options for floatN when checking effective target for support
> >>
> >>   NEW!
> >>
> >>----------------
> >>AArch64 changes
> >>
> >>3 patches, none reviewed
> >>----------------
> >>
> >>[Patch AArch64 11/17] Add floatdihf2 and floatunsdihf2 patterns
> >>
> >>   Not reviewed, last pinged (^6):
> >>   https://gcc.gnu.org/ml/gcc-patches/2016-11/msg00584.html
> >>
> >>[Patch libgcc AArch64 12/17] Enable hfmode soft-float conversions and truncations
> >>
> >>   Not reviewed:
> >>   https://gcc.gnu.org/ml/gcc-patches/2016-09/msg02395.html
> >>
> >>[Patch AArch64 13/17] Enable _Float16 for AArch64
> >>
> >>   Not reviewed:
> >>   https://gcc.gnu.org/ml/gcc-patches/2016-10/msg01176.html
> >>
> >>----------------
> >>ARM changes
> >>
> >>4 patches, none OK'ed
> >>----------------
> >>[Patch 14/17] [libgcc, ARM] Generalise float-to-half conversion function.
> >>
> >>   Respun in this submission to avoid a bug identified during extended
> >>   multilib testing, original submission here:
> >>   https://gcc.gnu.org/ml/gcc-patches/2016-11/msg00714.html
> >>
> >>[Patch 15/17 libgcc] Add double to half conversions.
> >>
> >>   Reviewed, but not approved:
> >>   https://gcc.gnu.org/ml/gcc-patches/2016-10/msg01975.html
> >>
> >>   Changes were required to patch 16/17, and patch 10/17 was introduced to
> >>   implement the suggested testsuite patch. The original patch still stands,
> >>   and needs reviewed:
> >>   https://gcc.gnu.org/ml/gcc-patches/2016-10/msg01914.html
> >>
> >>[Patch 16/17 ARM] Half to double precision conversions
> >>
> >>   Resubmitted: https://gcc.gnu.org/ml/gcc-patches/2016-11/msg00233.html
> >>   Needs review.
> >>
> >>[Patch ARM 17/17] Enable _Float16 for ARM.
> >>
> >>   Resubmitted: https://gcc.gnu.org/ml/gcc-patches/2016-11/msg00234.html
> >>   Needs review.
> >>
> >>
> >>
> 

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

* Re: [Patch 14/17] [libgcc, ARM] Generalise float-to-half conversion function.
  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
  0 siblings, 0 replies; 95+ messages in thread
From: James Greenhalgh @ 2016-11-23 18:18 UTC (permalink / raw)
  To: Kyrill Tkachov
  Cc: gcc-patches, richard.earnshaw, ramana.radhakrishnan, joseph, nd

On Wed, Nov 16, 2016 at 04:38:17PM +0000, Kyrill Tkachov wrote:
> Hi James,
> diff --git a/libgcc/config/arm/fp16.c b/libgcc/config/arm/fp16.c
> index 39c863c..ba89796 100644
> --- a/libgcc/config/arm/fp16.c
> +++ b/libgcc/config/arm/fp16.c
> @@ -22,40 +22,74 @@
>     see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
>     <http://www.gnu.org/licenses/>.  */
> +struct format
> +{
> +  /* Number of bits.  */
> +  unsigned long long size;
> +  /* Exponent bias.  */
> +  unsigned long long bias;
> +  /* Exponent width in bits.  */
> +  unsigned long long exponent;
> +  /* Significand precision in explicitly stored bits.  */
> +  unsigned long long significand;
> +};
> +
> +static const struct format
> +binary32 =
> +{
> +  32,   /* size.  */
> +  127,  /* bias.  */
> +  8,    /* exponent.  */
> +  23    /* significand.  */
> +};
> +
>  static inline unsigned short
> -__gnu_f2h_internal(unsigned int a, int ieee)
> +__gnu_float2h_internal (const struct format* fmt,
> +			unsigned long long a, int ieee)
>  {
> -  unsigned short sign = (a >> 16) & 0x8000;
> -  int aexp = (a >> 23) & 0xff;
> -  unsigned int mantissa = a & 0x007fffff;
> -  unsigned int mask;
> -  unsigned int increment;
> +  unsigned long long point = 1ULL << fmt->significand;;
> 
> Trailing ';'.
> 
> <...>
> @@ -93,7 +127,13 @@ __gnu_f2h_internal(unsigned int a, int ieee)
>    /* We leave the leading 1 in the mantissa, and subtract one
>       from the exponent bias to compensate.  */
> -  return sign | (((aexp + 14) << 10) + (mantissa >> 13));
> +  return sign | (((aexp + 14) << 10) + (mantissa >> (fmt->significand - 10)));
> +}
> 
> I suppose I'm not very familiar with the soft-fp code but I don't see at a glance how
> the comment relates to the operation it's above of (where is the 'one' being subtracted
> from the bias?). If you want to improve that comment or give me a quick explanation of why
> the code does what it says it does it would be appreciated.
> 
> I've gone through the generalisation and it looks correct to me.
> So given that you have put this through the testing you say you did this is ok with the nits
> above addressed.

Hi Kyrill,

Thanks. In the end this is what I committed.

James

diff --git a/libgcc/config/arm/fp16.c b/libgcc/config/arm/fp16.c
index 39c863c..76f7327 100644
--- a/libgcc/config/arm/fp16.c
+++ b/libgcc/config/arm/fp16.c
@@ -22,40 +22,74 @@
    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
+struct format
+{
+  /* Number of bits.  */
+  unsigned long long size;
+  /* Exponent bias.  */
+  unsigned long long bias;
+  /* Exponent width in bits.  */
+  unsigned long long exponent;
+  /* Significand precision in explicitly stored bits.  */
+  unsigned long long significand;
+};
+
+static const struct format
+binary32 =
+{
+  32,   /* size.  */
+  127,  /* bias.  */
+  8,    /* exponent.  */
+  23    /* significand.  */
+};
+
 static inline unsigned short
-__gnu_f2h_internal(unsigned int a, int ieee)
+__gnu_float2h_internal (const struct format* fmt,
+			unsigned long long a, int ieee)
 {
-  unsigned short sign = (a >> 16) & 0x8000;
-  int aexp = (a >> 23) & 0xff;
-  unsigned int mantissa = a & 0x007fffff;
-  unsigned int mask;
-  unsigned int increment;
+  unsigned long long point = 1ULL << fmt->significand;
+  unsigned short sign = (a >> (fmt->size - 16)) & 0x8000;
+  int aexp;
+  unsigned long long mantissa;
+  unsigned long long mask;
+  unsigned long long increment;
+
+  /* Get the exponent and mantissa encodings.  */
+  mantissa = a & (point - 1);
 
-  if (aexp == 0xff)
+  mask = (1 << fmt->exponent) - 1;
+  aexp = (a >> fmt->significand) & mask;
+
+  /* Infinity, NaN and alternative format special case.  */
+  if (((unsigned int) aexp) == mask)
     {
       if (!ieee)
 	return sign;
       if (mantissa == 0)
 	return sign | 0x7c00;	/* Infinity.  */
       /* Remaining cases are NaNs.  Convert SNaN to QNaN.  */
-      return sign | 0x7e00 | (mantissa >> 13);
+      return sign | 0x7e00 | (mantissa >> (fmt->significand - 10));
     }
 
+  /* Zero.  */
   if (aexp == 0 && mantissa == 0)
     return sign;
 
-  aexp -= 127;
+  /* Construct the exponent and mantissa.  */
+  aexp -= fmt->bias;
+
+  /* Decimal point is immediately after the significand.  */
+  mantissa |= point;
 
-  /* Decimal point between bits 22 and 23.  */
-  mantissa |= 0x00800000;
   if (aexp < -14)
     {
-      mask = 0x00ffffff;
+      mask = point | (point - 1);
+      /* Minimum exponent for half-precision is 2^-24.  */
       if (aexp >= -25)
 	mask >>= 25 + aexp;
     }
   else
-    mask = 0x00001fff;
+    mask = (point - 1) >> 10;
 
   /* Round.  */
   if (mantissa & mask)
@@ -64,8 +98,8 @@ __gnu_f2h_internal(unsigned int a, int ieee)
       if ((mantissa & mask) == increment)
 	increment = mantissa & (increment << 1);
       mantissa += increment;
-      if (mantissa >= 0x01000000)
-       	{
+      if (mantissa >= (point << 1))
+	{
 	  mantissa >>= 1;
 	  aexp++;
 	}
@@ -91,9 +125,29 @@ __gnu_f2h_internal(unsigned int a, int ieee)
       aexp = -14;
     }
 
-  /* We leave the leading 1 in the mantissa, and subtract one
-     from the exponent bias to compensate.  */
-  return sign | (((aexp + 14) << 10) + (mantissa >> 13));
+  /* Encode the final 16-bit floating-point value.
+
+     This is formed of the sign bit, the bias-adjusted exponent, and the
+     calculated mantissa, with the following caveats:
+
+     1.  The mantissa calculated after rounding could have a leading 1.
+	 To compensate for this, subtract one from the exponent bias (15)
+	 before adding it to the calculated exponent.
+     2.  When we were calculating rounding, we left the mantissa with the
+	 number of bits of the source operand, it needs reduced to ten
+	 bits (+1 for the afforementioned leading 1) by shifting right by
+	 the number of bits in the source mantissa - 10.
+     3.  To ensure the leading 1 in the mantissa is applied to the exponent
+	 we need to add the mantissa rather than apply an arithmetic "or"
+	 to it.  */
+
+  return sign | (((aexp + 14) << 10) + (mantissa >> (fmt->significand - 10)));
+}
+
+static inline unsigned short
+__gnu_f2h_internal (unsigned int a, int ieee)
+{
+  return __gnu_float2h_internal (&binary32, (unsigned long long) a, ieee);
 }
 
 unsigned int

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

* Re: [Patch 16/17 libgcc ARM] Half to double precision conversions
  2016-11-16 16:00       ` Kyrill Tkachov
@ 2016-11-23 18:20         ` James Greenhalgh
  0 siblings, 0 replies; 95+ messages in thread
From: James Greenhalgh @ 2016-11-23 18:20 UTC (permalink / raw)
  To: Kyrill Tkachov
  Cc: gcc-patches, richard.earnshaw, kyrtka01, ramana.radhakrishnan,
	joseph, nd

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;

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

* Ping^8 Re: [Patch AArch64 11/17] Add floatdihf2 and floatunsdihf2 patterns
  2016-11-11 15:41   ` [Patch AArch64 11/17] Add floatdihf2 and floatunsdihf2 patterns James Greenhalgh
  2016-11-11 15:41     ` [Patch AArch64 13/17] Enable _Float16 for AArch64 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:46     ` James Greenhalgh
  2016-11-24 13:20     ` Richard Earnshaw (lists)
  3 siblings, 0 replies; 95+ messages in thread
From: James Greenhalgh @ 2016-11-24  9:46 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, richard.earnshaw, marcus.shawcroft, joseph

On Fri, Nov 11, 2016 at 03:40:49PM +0000, James Greenhalgh wrote:
> 
> Hi,
> 
> This patch adds patterns for conversion from 64-bit integer to 16-bit
> floating-point values under AArch64 targets which don't have support for
> the ARMv8.2-A 16-bit floating point extensions.
> 
> We implement these by first saturating to a SImode (we know that any
> values >= 65504 will round to infinity after conversion to HFmode), then
> converting to a DFmode (unsigned conversions could go to SFmode, but there
> is no performance benefit to this). Then converting to HFmode.
> 
> Having added these patterns, the expansion path in "expand_float" will
> now try to use them for conversions from SImode to HFmode as there is no
> floatsihf2 pattern. expand_float first tries widening the integer size and
> looking for a match, so it will try SImode -> DImode. But our DI mode
> pattern is going to then saturate us back to SImode which is wasteful.
> 
> Better, would be for us to provide float(uns)sihf2 patterns directly.
> So that's what this patch does.
> 
> The testcase add in this patch would fail on trunk for AArch64. There is
> no libgcc routine to make the conversion, and we don't provide appropriate
> patterns in the backend, so we get a link-time error.
> 
> Bootstrapped and tested on aarch64-none-linux-gnu

Ping ^8

Thanks,
James

> 
> OK for trunk?
> 
> James
> 

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

* Re: [Patch AArch64 13/17] Enable _Float16 for AArch64
  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)
  2 siblings, 0 replies; 95+ messages in thread
From: James Greenhalgh @ 2016-11-24  9:47 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, richard.earnshaw, marcus.shawcroft, joseph

On Fri, Nov 11, 2016 at 03:40:51PM +0000, James Greenhalgh wrote:
> 
>  Hi,
> 
> This patch adds the back-end wiring to get AArch64 support for
> the _Float16 type working.
> 
> Bootstrapped on AArch64 with no issues.
> 
> OK?

Ping.

Thanks,
James


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

* Re: [Patch libgcc AArch64 12/17] Enable hfmode soft-float conversions and truncations
  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)
  1 sibling, 0 replies; 95+ messages in thread
From: James Greenhalgh @ 2016-11-24  9:47 UTC (permalink / raw)
  To: gcc-patches; +Cc: nd, richard.earnshaw, marcus.shawcroft, joseph

On Fri, Nov 11, 2016 at 03:40:50PM +0000, James Greenhalgh wrote:
> 
> Hi,
> 
> This patch enables the conversion functions we need for AArch64's _Float16
> support. To do that we need to implement TARGET_SCALAR_MODE_SUPPORTED_P,
> so do that now.

Ping.

Thanks,
James

> 
> OK?
> 
> Thanks,
> James
> 
> ---
> gcc/
> 
> 2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>
> 
> 	* config/aarch64/aarch64-c.c (aarch64_scalar_mode_supported_p): New.
> 	(TARGET_SCALAR_MODE_SUPPORTED_P): Define.
> 
> libgcc/
> 
> 2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>
> 
> 	* config/aarch64/sfp-machine.h (_FP_NANFRAC_H): Define.
> 	(_FP_NANSIGN_H): Likewise.
> 	* config/aarch64/t-softfp (softfp_extensions): Add hftf.
> 	(softfp_truncations): Add tfhf.
> 	(softfp_extras): Add required conversion functions.
> 

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

* Re: [Patch AArch64 11/17] Add floatdihf2 and floatunsdihf2 patterns
  2016-11-11 15:41   ` [Patch AArch64 11/17] Add floatdihf2 and floatunsdihf2 patterns James Greenhalgh
                       ` (2 preceding siblings ...)
  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)
  3 siblings, 0 replies; 95+ messages in thread
From: Richard Earnshaw (lists) @ 2016-11-24 13:20 UTC (permalink / raw)
  To: James Greenhalgh, gcc-patches; +Cc: nd, marcus.shawcroft, joseph

On 11/11/16 15:40, James Greenhalgh wrote:
> 
> Hi,
> 
> This patch adds patterns for conversion from 64-bit integer to 16-bit
> floating-point values under AArch64 targets which don't have support for
> the ARMv8.2-A 16-bit floating point extensions.
> 
> We implement these by first saturating to a SImode (we know that any
> values >= 65504 will round to infinity after conversion to HFmode), then
> converting to a DFmode (unsigned conversions could go to SFmode, but there
> is no performance benefit to this). Then converting to HFmode.
> 
> Having added these patterns, the expansion path in "expand_float" will
> now try to use them for conversions from SImode to HFmode as there is no
> floatsihf2 pattern. expand_float first tries widening the integer size and
> looking for a match, so it will try SImode -> DImode. But our DI mode
> pattern is going to then saturate us back to SImode which is wasteful.
> 
> Better, would be for us to provide float(uns)sihf2 patterns directly.
> So that's what this patch does.
> 
> The testcase add in this patch would fail on trunk for AArch64. There is
> no libgcc routine to make the conversion, and we don't provide appropriate
> patterns in the backend, so we get a link-time error.
> 
> Bootstrapped and tested on aarch64-none-linux-gnu
> 
> OK for trunk?
> 
> James
> 
> ---
> 2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>
> 
> 	* config/aarch64/aarch64.md (<optab>sihf2): Convert to expand.
> 	(<optab>dihf2): Likewise.
> 	(aarch64_fp16_<optab><mode>hf2): New.
> 
> 2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>
> 
> 	* gcc.target/aarch64/floatdihf2_1.c: New.
> 

OK.

R.

> 
> 0011-Patch-AArch64-11-17-Add-floatdihf2-and-floatunsdihf2.patch
> 
> 
> diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
> index 46eaa30..b818968 100644
> --- a/gcc/config/aarch64/aarch64.md
> +++ b/gcc/config/aarch64/aarch64.md
> @@ -4627,7 +4627,14 @@
>    [(set_attr "type" "f_cvti2f")]
>  )
>  
> -(define_insn "<optab><mode>hf2"
> +;; If we do not have ARMv8.2-A 16-bit floating point extensions, the
> +;; midend will arrange for an SImode conversion to HFmode to first go
> +;; through DFmode, then to HFmode.  But first it will try converting
> +;; to DImode then down, which would match our DImode pattern below and
> +;; give very poor code-generation.  So, we must provide our own emulation
> +;; of the mid-end logic.
> +
> +(define_insn "aarch64_fp16_<optab><mode>hf2"
>    [(set (match_operand:HF 0 "register_operand" "=w")
>  	(FLOATUORS:HF (match_operand:GPI 1 "register_operand" "r")))]
>    "TARGET_FP_F16INST"
> @@ -4635,6 +4642,53 @@
>    [(set_attr "type" "f_cvti2f")]
>  )
>  
> +(define_expand "<optab>sihf2"
> +  [(set (match_operand:HF 0 "register_operand")
> +	(FLOATUORS:HF (match_operand:SI 1 "register_operand")))]
> +  "TARGET_FLOAT"
> +{
> +  if (TARGET_FP_F16INST)
> +    emit_insn (gen_aarch64_fp16_<optab>sihf2 (operands[0], operands[1]));
> +  else
> +    {
> +      rtx convert_target = gen_reg_rtx (DFmode);
> +      emit_insn (gen_<optab>sidf2 (convert_target, operands[1]));
> +      emit_insn (gen_truncdfhf2 (operands[0], convert_target));
> +    }
> +  DONE;
> +}
> +)
> +
> +;; For DImode there is no wide enough floating-point mode that we
> +;; can convert through natively (TFmode would work, but requires a library
> +;; call).  However, we know that any value >= 65504 will be rounded
> +;; to infinity on conversion.  This is well within the range of SImode, so
> +;; we can:
> +;;   Saturate to SImode.
> +;;   Convert from that to DFmode
> +;;   Convert from that to HFmode (phew!).
> +;; Note that the saturation to SImode requires the SIMD extensions.  If
> +;; we ever need to provide this pattern where the SIMD extensions are not
> +;; available, we would need a different approach.
> +
> +(define_expand "<optab>dihf2"
> +  [(set (match_operand:HF 0 "register_operand")
> +	(FLOATUORS:HF (match_operand:DI 1 "register_operand")))]
> +  "TARGET_FLOAT && (TARGET_FP_F16INST || TARGET_SIMD)"
> +{
> +  if (TARGET_FP_F16INST)
> +    emit_insn (gen_aarch64_fp16_<optab>dihf2 (operands[0], operands[1]));
> +  else
> +    {
> +      rtx sat_target = gen_reg_rtx (SImode);
> +      emit_insn (gen_aarch64_<su_optab>qmovndi (sat_target, operands[1]));
> +      emit_insn (gen_<optab>sihf2 (operands[0], sat_target));
> +    }
> +
> +  DONE;
> +}
> +)
> +
>  ;; Convert between fixed-point and floating-point (scalar modes)
>  
>  (define_insn "<FCVT_F2FIXED:fcvt_fixed_insn><GPF:mode>3"
> diff --git a/gcc/testsuite/gcc.target/aarch64/floatdihf2_1.c b/gcc/testsuite/gcc.target/aarch64/floatdihf2_1.c
> new file mode 100644
> index 0000000..9eaa4ba
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/floatdihf2_1.c
> @@ -0,0 +1,35 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2" } */
> +
> +/* Test that conversion from 32-bit and 64-bit integers can be done
> +   without a call to the support library.  */
> +
> +#pragma GCC target ("arch=armv8.2-a+nofp16")
> +
> +__fp16
> +foo (int x)
> +{
> +  return x;
> +}
> +
> +__fp16
> +bar (unsigned int x)
> +{
> +  return x;
> +}
> +
> +__fp16
> +fool (long long x)
> +{
> +  return x;
> +}
> +
> +__fp16
> +barl (unsigned long long x)
> +{
> +  return x;
> +}
> +
> +
> +/* { dg-final { scan-assembler-not "__float\\\[ds\\\]ihf2" } } */
> +/* { dg-final { scan-assembler-not "__floatun\\\[ds\\\]ihf2" } } */
> 

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

* Re: [Patch libgcc AArch64 12/17] Enable hfmode soft-float conversions and truncations
  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)
  1 sibling, 0 replies; 95+ messages in thread
From: Richard Earnshaw (lists) @ 2016-11-24 13:23 UTC (permalink / raw)
  To: James Greenhalgh, gcc-patches; +Cc: nd, marcus.shawcroft, joseph

On 11/11/16 15:40, James Greenhalgh wrote:
> 
> Hi,
> 
> This patch enables the conversion functions we need for AArch64's _Float16
> support. To do that we need to implement TARGET_SCALAR_MODE_SUPPORTED_P,
> so do that now.
> 
> OK?
> 
> Thanks,
> James
> 
> ---
> gcc/
> 
> 2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>
> 
> 	* config/aarch64/aarch64-c.c (aarch64_scalar_mode_supported_p): New.
> 	(TARGET_SCALAR_MODE_SUPPORTED_P): Define.
> 
> libgcc/
> 
> 2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>
> 
> 	* config/aarch64/sfp-machine.h (_FP_NANFRAC_H): Define.
> 	(_FP_NANSIGN_H): Likewise.
> 	* config/aarch64/t-softfp (softfp_extensions): Add hftf.
> 	(softfp_truncations): Add tfhf.
> 	(softfp_extras): Add required conversion functions.
> 
> 

OK.


R.

> 0012-Patch-libgcc-AArch64-12-17-Enable-hfmode-soft-float-.patch
> 
> 
> diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
> index b7d4640..ec17af4 100644
> --- a/gcc/config/aarch64/aarch64.c
> +++ b/gcc/config/aarch64/aarch64.c
> @@ -14168,6 +14168,17 @@ aarch64_optab_supported_p (int op, machine_mode mode1, machine_mode,
>      }
>  }
>  
> +/* Implement TARGET_SCALAR_MODE_SUPPORTED_P - return TRUE
> +   if MODE is HFmode, and punt to the generic implementation otherwise.  */
> +
> +static bool
> +aarch64_scalar_mode_supported_p (machine_mode mode)
> +{
> +  return (mode == HFmode
> +	  ? true
> +	  : default_scalar_mode_supported_p (mode));
> +}
> +
>  #undef TARGET_ADDRESS_COST
>  #define TARGET_ADDRESS_COST aarch64_address_cost
>  
> @@ -14378,6 +14389,9 @@ aarch64_optab_supported_p (int op, machine_mode mode1, machine_mode,
>  #undef TARGET_RTX_COSTS
>  #define TARGET_RTX_COSTS aarch64_rtx_costs_wrapper
>  
> +#undef TARGET_SCALAR_MODE_SUPPORTED_P
> +#define TARGET_SCALAR_MODE_SUPPORTED_P aarch64_scalar_mode_supported_p
> +
>  #undef TARGET_SCHED_ISSUE_RATE
>  #define TARGET_SCHED_ISSUE_RATE aarch64_sched_issue_rate
>  
> diff --git a/libgcc/config/aarch64/sfp-machine.h b/libgcc/config/aarch64/sfp-machine.h
> index 5efa245..da154dd 100644
> --- a/libgcc/config/aarch64/sfp-machine.h
> +++ b/libgcc/config/aarch64/sfp-machine.h
> @@ -42,9 +42,11 @@ typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__)));
>  
>  #define _FP_DIV_MEAT_Q(R,X,Y)	_FP_DIV_MEAT_2_udiv(Q,R,X,Y)
>  
> +#define _FP_NANFRAC_H		((_FP_QNANBIT_H << 1) - 1)
>  #define _FP_NANFRAC_S		((_FP_QNANBIT_S << 1) - 1)
>  #define _FP_NANFRAC_D		((_FP_QNANBIT_D << 1) - 1)
>  #define _FP_NANFRAC_Q		((_FP_QNANBIT_Q << 1) - 1), -1
> +#define _FP_NANSIGN_H		0
>  #define _FP_NANSIGN_S		0
>  #define _FP_NANSIGN_D		0
>  #define _FP_NANSIGN_Q		0
> diff --git a/libgcc/config/aarch64/t-softfp b/libgcc/config/aarch64/t-softfp
> index 586dca2..c4ce0dc 100644
> --- a/libgcc/config/aarch64/t-softfp
> +++ b/libgcc/config/aarch64/t-softfp
> @@ -1,8 +1,9 @@
>  softfp_float_modes := tf
>  softfp_int_modes := si di ti
> -softfp_extensions := sftf dftf
> -softfp_truncations := tfsf tfdf
> +softfp_extensions := sftf dftf hftf
> +softfp_truncations := tfsf tfdf tfhf
>  softfp_exclude_libgcc2 := n
> +softfp_extras := fixhfti fixunshfti floattihf floatuntihf
>  
>  TARGET_LIBGCC2_CFLAGS += -Wno-missing-prototypes
>  
> 

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

* Re: [Patch AArch64 13/17] Enable _Float16 for AArch64
  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)
  2 siblings, 0 replies; 95+ messages in thread
From: Richard Earnshaw (lists) @ 2016-11-24 14:40 UTC (permalink / raw)
  To: James Greenhalgh, gcc-patches; +Cc: nd, marcus.shawcroft, joseph

On 11/11/16 15:40, James Greenhalgh wrote:
> 
>  Hi,
> 
> This patch adds the back-end wiring to get AArch64 support for
> the _Float16 type working.
> 
> Bootstrapped on AArch64 with no issues.
> 
> OK?
> 
> Thanks,
> James
> 
> ---
> 2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>
> 
> 	* config/aarch64/aarch64-c.c (aarch64_update_cpp_builtins): Update
> 	__FLT_EVAL_METHOD__ and __FLT_EVAL_METHOD_C99__ when we switch
> 	architecture levels.
> 	* config/aarch64/aarch64.c (aarch64_promoted_type): Only promote
> 	the aarch64_fp16_type_node, not all HFmode types.
> 	(aarch64_libgcc_floating_mode_supported_p): Support HFmode.
> 	(aarch64_scalar_mode_supported_p): Likewise.
> 	(aarch64_excess_precision): New.
> 	(TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P): Define.
> 	(TARGET_SCALAR_MODE_SUPPORTED_P): Likewise.
> 	(TARGET_C_EXCESS_PRECISION): Likewise.
> 
> 2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>
> 
> 	* gcc.target/aarch64/_Float16_1.c: New.
> 	* gcc.target/aarch64/_Float16_2.c: Likewise.
> 	* gcc.target/aarch64/_Float16_3.c: Likewise.
> 
> 

> -  if (SCALAR_FLOAT_TYPE_P (t) && TYPE_PRECISION (t) == 16)
> +
> +  if (TYPE_P (t) && TYPE_MAIN_VARIANT (t) == aarch64_fp16_type_node)


Hmm, SCALAR_FLOAT_TYPE_P is a bit more efficient that TYPE_P in that it
avoids an indirection.  It also avoids the second indirection for
TYPE_MAIN_VARIANT in all the cases where we don't have a real type.

So I think
   if (SCALAR_FLOAT_TYPE_P (t)
       && TYPE_MAIN_VARIANT (t) == aarch64_fp16_type_node)

would be preferable here.

OK with that change.

R.

> 0013-Patch-AArch64-13-17-Enable-_Float16-for-AArch64.patch
> 
> 
> diff --git a/gcc/config/aarch64/aarch64-c.c b/gcc/config/aarch64/aarch64-c.c
> index 422e322..320b912 100644
> --- a/gcc/config/aarch64/aarch64-c.c
> +++ b/gcc/config/aarch64/aarch64-c.c
> @@ -133,6 +133,16 @@ aarch64_update_cpp_builtins (cpp_reader *pfile)
>  
>    aarch64_def_or_undef (TARGET_CRYPTO, "__ARM_FEATURE_CRYPTO", pfile);
>    aarch64_def_or_undef (TARGET_SIMD_RDMA, "__ARM_FEATURE_QRDMX", pfile);
> +
> +  /* Not for ACLE, but required to keep "float.h" correct if we switch
> +     target between implementations that do or do not support ARMv8.2-A
> +     16-bit floating-point extensions.  */
> +  cpp_undef (pfile, "__FLT_EVAL_METHOD__");
> +  builtin_define_with_int_value ("__FLT_EVAL_METHOD__",
> +				 c_flt_eval_method (true));
> +  cpp_undef (pfile, "__FLT_EVAL_METHOD_C99__");
> +  builtin_define_with_int_value ("__FLT_EVAL_METHOD_C99__",
> +				 c_flt_eval_method (false));
>  }
>  
>  /* Implement TARGET_CPU_CPP_BUILTINS.  */
> diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
> index ec17af4..824b27c 100644
> --- a/gcc/config/aarch64/aarch64.c
> +++ b/gcc/config/aarch64/aarch64.c
> @@ -14143,12 +14143,20 @@ aarch64_vec_fpconst_pow_of_2 (rtx x)
>    return firstval;
>  }
>  
> -/* Implement TARGET_PROMOTED_TYPE to promote __fp16 to float.  */
> +/* Implement TARGET_PROMOTED_TYPE to promote 16-bit floating point types
> +   to float.
> +
> +   __fp16 always promotes through this hook.
> +   _Float16 may promote if TARGET_FLT_EVAL_METHOD is 16, but we do that
> +   through the generic excess precision logic rather than here.  */
> +
>  static tree
>  aarch64_promoted_type (const_tree t)
>  {
> -  if (SCALAR_FLOAT_TYPE_P (t) && TYPE_PRECISION (t) == 16)
> +
> +  if (TYPE_P (t) && TYPE_MAIN_VARIANT (t) == aarch64_fp16_type_node)
>      return float_type_node;
> +
>    return NULL_TREE;
>  }
>  
> @@ -14168,6 +14176,17 @@ aarch64_optab_supported_p (int op, machine_mode mode1, machine_mode,
>      }
>  }
>  
> +/* Implement TARGET_LIBGCC_FLOATING_POINT_MODE_SUPPORTED_P - return TRUE
> +   if MODE is HFmode, and punt to the generic implementation otherwise.  */
> +
> +static bool
> +aarch64_libgcc_floating_mode_supported_p (machine_mode mode)
> +{
> +  return (mode == HFmode
> +	  ? true
> +	  : default_libgcc_floating_mode_supported_p (mode));
> +}
> +
>  /* Implement TARGET_SCALAR_MODE_SUPPORTED_P - return TRUE
>     if MODE is HFmode, and punt to the generic implementation otherwise.  */
>  
> @@ -14179,6 +14198,47 @@ aarch64_scalar_mode_supported_p (machine_mode mode)
>  	  : default_scalar_mode_supported_p (mode));
>  }
>  
> +/* Set the value of FLT_EVAL_METHOD.
> +   ISO/IEC TS 18661-3 defines two values that we'd like to make use of:
> +
> +    0: evaluate all operations and constants, whose semantic type has at
> +       most the range and precision of type float, to the range and
> +       precision of float; evaluate all other operations and constants to
> +       the range and precision of the semantic type;
> +
> +    N, where _FloatN is a supported interchange floating type
> +       evaluate all operations and constants, whose semantic type has at
> +       most the range and precision of _FloatN type, to the range and
> +       precision of the _FloatN type; evaluate all other operations and
> +       constants to the range and precision of the semantic type;
> +
> +   If we have the ARMv8.2-A extensions then we support _Float16 in native
> +   precision, so we should set this to 16.  Otherwise, we support the type,
> +   but want to evaluate expressions in float precision, so set this to
> +   0.  */
> +
> +static enum flt_eval_method
> +aarch64_excess_precision (enum excess_precision_type type)
> +{
> +  switch (type)
> +    {
> +      case EXCESS_PRECISION_TYPE_FAST:
> +      case EXCESS_PRECISION_TYPE_STANDARD:
> +	/* We can calculate either in 16-bit range and precision or
> +	   32-bit range and precision.  Make that decision based on whether
> +	   we have native support for the ARMv8.2-A 16-bit floating-point
> +	   instructions or not.  */
> +	return (TARGET_FP_F16INST
> +		? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16
> +		: FLT_EVAL_METHOD_PROMOTE_TO_FLOAT);
> +      case EXCESS_PRECISION_TYPE_IMPLICIT:
> +	return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16;
> +      default:
> +	gcc_unreachable ();
> +    }
> +  return FLT_EVAL_METHOD_UNPREDICTABLE;
> +}
> +
>  #undef TARGET_ADDRESS_COST
>  #define TARGET_ADDRESS_COST aarch64_address_cost
>  
> @@ -14257,6 +14317,9 @@ aarch64_scalar_mode_supported_p (machine_mode mode)
>  #undef TARGET_BUILTIN_RECIPROCAL
>  #define TARGET_BUILTIN_RECIPROCAL aarch64_builtin_reciprocal
>  
> +#undef TARGET_C_EXCESS_PRECISION
> +#define TARGET_C_EXCESS_PRECISION aarch64_excess_precision
> +
>  #undef  TARGET_EXPAND_BUILTIN
>  #define TARGET_EXPAND_BUILTIN aarch64_expand_builtin
>  
> @@ -14313,6 +14376,10 @@ aarch64_scalar_mode_supported_p (machine_mode mode)
>  #undef TARGET_LIBGCC_CMP_RETURN_MODE
>  #define TARGET_LIBGCC_CMP_RETURN_MODE aarch64_libgcc_cmp_return_mode
>  
> +#undef TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P
> +#define TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P \
> +aarch64_libgcc_floating_mode_supported_p
> +
>  #undef TARGET_MANGLE_TYPE
>  #define TARGET_MANGLE_TYPE aarch64_mangle_type
>  
> diff --git a/gcc/testsuite/gcc.target/aarch64/_Float16_1.c b/gcc/testsuite/gcc.target/aarch64/_Float16_1.c
> new file mode 100644
> index 0000000..320f154
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/_Float16_1.c
> @@ -0,0 +1,47 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=armv8.2-a+nofp16" } */
> +
> +#pragma GCC target ("arch=armv8.2-a+nofp16")
> +
> +_Float16
> +foo_v8 (_Float16 x, _Float16 y, unsigned int *eval)
> +{
> +  *eval = __FLT_EVAL_METHOD__;
> +  return x * x + y;
> +}
> +
> +__fp16
> +bar_v8 (__fp16 x, __fp16 y, unsigned int *eval)
> +{
> +  *eval = __FLT_EVAL_METHOD__;
> +  return x * x + y;
> +}
> +
> +#pragma GCC target ("arch=armv8.2-a+fp16")
> +
> +_Float16
> +foo_v82 (_Float16 x, _Float16 y, unsigned int *eval)
> +{
> +  *eval = __FLT_EVAL_METHOD__;
> +  return x * x + y;
> +}
> +
> +__fp16
> +bar_v82 (__fp16 x, __fp16 y, unsigned int *eval)
> +{
> +  *eval = __FLT_EVAL_METHOD__;
> +  return x * x + y;
> +}
> +
> +/* Test that we merge to FMA operations.  This indicates that we are not
> +   making extraneous conversions between modes.  */
> +
> +/* Three FMA operations in 32-bit precision, from foo_v8, bar_v8, bar_v82.  */
> +/* { dg-final { scan-assembler-times "fmadd\ts\[0-9\]\+" 3 } } */
> +
> +/* One FMA operation in 16-bit precision, from foo_v82.  */
> +/* { dg-final { scan-assembler-times "fmadd\th\[0-9\]\+" 1 } } */
> +
> +/* Test that we are resetting the __FLT_EVAL_METHOD__.  */
> +/* { dg-final { scan-assembler-times "mov\tw\[0-9\]\+, 16" 2 } } */
> +/* { dg-final { scan-assembler-times "str\twzr" 2 } } */
> diff --git a/gcc/testsuite/gcc.target/aarch64/_Float16_2.c b/gcc/testsuite/gcc.target/aarch64/_Float16_2.c
> new file mode 100644
> index 0000000..8b2aa1e
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/_Float16_2.c
> @@ -0,0 +1,47 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=armv8.2-a+nofp16 -fpermitted-flt-eval-methods=c11" } */
> +
> +#pragma GCC target ("arch=armv8.2-a+nofp16")
> +
> +_Float16
> +foo_v8 (_Float16 x, _Float16 y, unsigned int *eval)
> +{
> +  *eval = __FLT_EVAL_METHOD__;
> +  return x * x + y;
> +}
> +
> +__fp16
> +bar_v8 (__fp16 x, __fp16 y, unsigned int *eval)
> +{
> +  *eval = __FLT_EVAL_METHOD__;
> +  return x * x + y;
> +}
> +
> +#pragma GCC target ("arch=armv8.2-a+fp16")
> +
> +_Float16
> +foo_v82 (_Float16 x, _Float16 y, unsigned int *eval)
> +{
> +  *eval = __FLT_EVAL_METHOD__;
> +  return x * x + y;
> +}
> +
> +__fp16
> +bar_v82 (__fp16 x, __fp16 y, unsigned int *eval)
> +{
> +  *eval = __FLT_EVAL_METHOD__;
> +  return x * x + y;
> +}
> +
> +/* Test that we merge to FMA operations.  This indicates that we are not
> +   making extraneous conversions between modes.  */
> +
> +/* Three FMA operations in 32-bit precision, from foo_v8, bar_v8, bar_v82.  */
> +/* { dg-final { scan-assembler-times "fmadd\ts\[0-9\]\+" 3 } } */
> +
> +/* One FMA operation in 16-bit precision, from foo_v82.  */
> +/* { dg-final { scan-assembler-times "fmadd\th\[0-9\]\+" 1 } } */
> +
> +/* Test that in -fpermitted-flt-eval-methods=c11 we don't set the
> +   __FLT_EVAL_METHOD__ to anything other than 0.  */
> +/* { dg-final { scan-assembler-times "str\twzr" 4 } } */
> diff --git a/gcc/testsuite/gcc.target/aarch64/_Float16_3.c b/gcc/testsuite/gcc.target/aarch64/_Float16_3.c
> new file mode 100644
> index 0000000..2d20250
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/_Float16_3.c
> @@ -0,0 +1,46 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -march=armv8.2-a+nofp16 -std=c11 -ffp-contract=fast" } */
> +
> +#pragma GCC target ("arch=armv8.2-a+nofp16")
> +
> +_Float16
> +foo_v8 (_Float16 x, _Float16 y, unsigned int *eval)
> +{
> +  *eval = __FLT_EVAL_METHOD__;
> +  return x * x + y;
> +}
> +
> +__fp16
> +bar_v8 (__fp16 x, __fp16 y, unsigned int *eval)
> +{
> +  *eval = __FLT_EVAL_METHOD__;
> +  return x * x + y;
> +}
> +
> +#pragma GCC target ("arch=armv8.2-a+fp16")
> +
> +_Float16
> +foo_v82 (_Float16 x, _Float16 y, unsigned int *eval)
> +{
> +  *eval = __FLT_EVAL_METHOD__;
> +  return x * x + y;
> +}
> +
> +__fp16
> +bar_v82 (__fp16 x, __fp16 y, unsigned int *eval)
> +{
> +  *eval = __FLT_EVAL_METHOD__;
> +  return x * x + y;
> +}
> +
> +/* Test that we merge to FMA operations.  This indicates that we are not
> +   making extraneous conversions between modes.  */
> +
> +/* Three FMA operations in 32-bit precision, from foo_v8, bar_v8, bar_v82.  */
> +/* { dg-final { scan-assembler-times "fmadd\ts\[0-9\]\+" 3 } } */
> +
> +/* One FMA operation in 16-bit precision, from foo_v82.  */
> +/* { dg-final { scan-assembler-times "fmadd\th\[0-9\]\+" 1 } } */
> +
> +/* Test that in C11 mode, we don't reset __FLT_EVAL_METHOD__.  */
> +/* { dg-final { scan-assembler-times "str\twzr" 4 } } */
> 

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

* Re: [Patch ARM 17/17] Enable _Float16 for ARM.
  2016-11-16 14:15       ` Kyrill Tkachov
@ 2016-11-25  8:55         ` Christophe Lyon
  0 siblings, 0 replies; 95+ messages in thread
From: Christophe Lyon @ 2016-11-25  8:55 UTC (permalink / raw)
  To: Kyrill Tkachov
  Cc: James Greenhalgh, gcc-patches, Richard Earnshaw,
	Ramana Radhakrishnan, Joseph S. Myers

Hi James,


On 16 November 2016 at 15:15, Kyrill Tkachov
<kyrylo.tkachov@foss.arm.com> wrote:
>
> On 11/11/16 15:42, James Greenhalgh wrote:
>>
>> Hi,
>>
>> Finally, having added support for single-step DFmode to HFmode
>> conversions,
>> this patch adds support for _Float16 to the ARM back-end.
>>
>> That means making sure that only __fp16 promotes and adding similar hooks
>> to
>> those used in the AArch64 port giving the excess precision rules, and
>> marking HFmode as supported in libgcc.
>>
>> Bootstrapped on an ARMv8-A machine, and crosstested with no issues.
>>
>> OK?
>
>
> This looks ok to me once the prerequisites are approved.
>
> Thanks,
> Kyrill
>
>
>> Thanks,
>> James
>>
>> ---
>> gcc/
>>
>> 2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>
>>
>>         PR target/63250
>>         * config/arm/arm-builtins.c (arm_simd_floatHF_type_node): Rename
>> to...
>>         (arm_fp16_type_node): ...This, make visibile.
>>         (arm_simd_builtin_std_type): Rename arm_simd_floatHF_type_node to
>>         arm_fp16_type_node.
>>         (arm_init_simd_builtin_types): Likewise.
>>         (arm_init_fp16_builtins): Likewise.
>>         * config/arm/arm.c (arm_excess_precision): New.
>>         (arm_floatn_mode): Likewise.
>>         (TARGET_C_EXCESS_PRECISION): Likewise.
>>         (TARGET_FLOATN_MODE): Likewise.
>>         (arm_promoted_type): Only promote arm_fp16_type_node.
>>         * config/arm/arm.h (arm_fp16_type_node): Declare.
>>
>> gcc/testsuite/
>>
>> 2016-11-09  James Greenhalgh  <james.greenhalgh@arm.com>
>>
>>         * lib/target-supports.exp (add_options_for_float16): Add
>>         -mfp16-format=ieee when testign arm*-*-*.
>>
>

I've noticed that after this patch (r242784),
gcc.dg/torture/float16-basic.c
fail on armeb*

Christophe

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

end of thread, other threads:[~2016-11-25  8:55 UTC | newest]

Thread overview: 95+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 7/11] Delete TARGET_FLT_EVAL_METHOD and poison it James Greenhalgh
2016-09-30 17:29   ` Jeff Law
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 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 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-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-11-11 15:38 ` [Patch v4 0/17] Add support for _Float16 to AArch64 and ARM 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 4/17] Implement TARGET_C_EXCESS_PRECISION for m68k 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 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 1/17] Add a new target hook for describing excess precision intentions James Greenhalgh
2016-11-11 15:38   ` [Patch 7/17] Delete TARGET_FLT_EVAL_METHOD and poison it James Greenhalgh
2016-11-11 15:39   ` [Patch 8/17] Make _Float16 available if HFmode is available 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 libgcc 9/17] Update soft-fp from glibc James Greenhalgh
2016-11-11 15:41   ` [Patch AArch64 11/17] Add floatdihf2 and floatunsdihf2 patterns James Greenhalgh
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-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-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 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 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
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

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).