diff mbox series

[4/6] Support -fexcess-precision=16 which will enable FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16 when backend supports _Float16.

Message ID 20210802063116.999830-5-hongtao.liu@intel.com
State New
Headers show
Series Initial support for AVX512FP16 | expand

Commit Message

liuhongt Aug. 2, 2021, 6:31 a.m. UTC
gcc/ada/ChangeLog:

	* gcc-interface/misc.c (gnat_post_options): Issue an error for
	-fexcess-precision=16.

gcc/c-family/ChangeLog:

	* c-common.c (excess_precision_mode_join): Update below comments.
	(c_ts18661_flt_eval_method): Set excess_precision_type to
	EXCESS_PRECISION_TYPE_FLOAT16 when -fexcess-precision=16.
	* c-cppbuiltin.c (cpp_atomic_builtins): Update below comments.
	(c_cpp_flt_eval_method_iec_559): Set excess_precision_type to
	EXCESS_PRECISION_TYPE_FLOAT16 when -fexcess-precision=16.

gcc/ChangeLog:

	* common.opt: Support -fexcess-precision=16.
	* config/aarch64/aarch64.c (aarch64_excess_precision): Return
	FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16 when
	EXCESS_PRECISION_TYPE_FLOAT16.
	* config/arm/arm.c (arm_excess_precision): Ditto.
	* config/i386/i386.c (ix86_get_excess_precision): Ditto.
	* config/m68k/m68k.c (m68k_excess_precision): Issue an error
	when EXCESS_PRECISION_TYPE_FLOAT16.
	* config/s390/s390.c (s390_excess_precision): Ditto.
	* coretypes.h (enum excess_precision_type): Add
	EXCESS_PRECISION_TYPE_FLOAT16.
	* doc/tm.texi (TARGET_C_EXCESS_PRECISION): Update documents.
	* doc/tm.texi.in (TARGET_C_EXCESS_PRECISION): Ditto.
	* doc/extend.texi (Half-Precision): Document
	-fexcess-precision=16.
	* flag-types.h (enum excess_precision): Add
	EXCESS_PRECISION_FLOAT16.
	* target.def (excess_precision): Update document.
	* tree.c (excess_precision_type): Set excess_precision_type to
	EXCESS_PRECISION_FLOAT16 when -fexcess-precision=16.

gcc/fortran/ChangeLog:

	* options.c (gfc_post_options): Issue an error for
	-fexcess-precision=16.

gcc/testsuite/ChangeLog:

	* gcc.target/i386/float16-6.c: New test.
---
 gcc/ada/gcc-interface/misc.c              |  3 +++
 gcc/c-family/c-common.c                   |  6 ++++--
 gcc/c-family/c-cppbuiltin.c               |  6 ++++--
 gcc/common.opt                            |  5 ++++-
 gcc/config/aarch64/aarch64.c              |  1 +
 gcc/config/arm/arm.c                      |  1 +
 gcc/config/i386/i386.c                    |  2 ++
 gcc/config/m68k/m68k.c                    |  2 ++
 gcc/config/s390/s390.c                    |  2 ++
 gcc/coretypes.h                           |  3 ++-
 gcc/doc/extend.texi                       |  3 ++-
 gcc/doc/tm.texi                           | 14 ++++++++++----
 gcc/doc/tm.texi.in                        |  3 +++
 gcc/flag-types.h                          |  3 ++-
 gcc/fortran/options.c                     |  3 +++
 gcc/target.def                            | 11 +++++++----
 gcc/testsuite/gcc.target/i386/float16-6.c |  8 ++++++++
 gcc/tree.c                                |  3 ++-
 18 files changed, 62 insertions(+), 17 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/float16-6.c

Comments

Joseph Myers Aug. 2, 2021, 7:34 p.m. UTC | #1
On Mon, 2 Aug 2021, liuhongt via Gcc-patches wrote:

> diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> index 7979e240426..dc673c89bc8 100644
> --- a/gcc/config/i386/i386.c
> +++ b/gcc/config/i386/i386.c
> @@ -23352,6 +23352,8 @@ ix86_get_excess_precision (enum excess_precision_type type)
>  	return (type == EXCESS_PRECISION_TYPE_STANDARD
>  		? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT
>  		: FLT_EVAL_METHOD_UNPREDICTABLE);
> +      case EXCESS_PRECISION_TYPE_FLOAT16:
> +	return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16;
>        default:
>  	gcc_unreachable ();
>      }

I'd expect an error for -fexcess-precision=16 with -mfpmath=387 (since x87 
doesn't do float or double arithmetic, but -fexcess-precision=16 implies 
that all of _Float16, float and double are represented to the range and 
precision of their type withou any excess precision).
Hongtao Liu Aug. 3, 2021, 2:44 a.m. UTC | #2
On Tue, Aug 3, 2021 at 3:34 AM Joseph Myers <joseph@codesourcery.com> wrote:
>
> On Mon, 2 Aug 2021, liuhongt via Gcc-patches wrote:
>
> > diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> > index 7979e240426..dc673c89bc8 100644
> > --- a/gcc/config/i386/i386.c
> > +++ b/gcc/config/i386/i386.c
> > @@ -23352,6 +23352,8 @@ ix86_get_excess_precision (enum excess_precision_type type)
> >       return (type == EXCESS_PRECISION_TYPE_STANDARD
> >               ? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT
> >               : FLT_EVAL_METHOD_UNPREDICTABLE);
> > +      case EXCESS_PRECISION_TYPE_FLOAT16:
> > +     return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16;
> >        default:
> >       gcc_unreachable ();
> >      }
>
> I'd expect an error for -fexcess-precision=16 with -mfpmath=387 (since x87
> doesn't do float or double arithmetic, but -fexcess-precision=16 implies
> that all of _Float16, float and double are represented to the range and
> precision of their type withou any excess precision).
>
Yes, additional changes like this.

modified   gcc/config/i386/i386.c
@@ -23443,6 +23443,9 @@ ix86_get_excess_precision (enum
excess_precision_type type)
  ? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT
  : FLT_EVAL_METHOD_UNPREDICTABLE);
       case EXCESS_PRECISION_TYPE_FLOAT16:
+ if (TARGET_80387
+     && !(TARGET_SSE_MATH && TARGET_SSE))
+   error ("%<-fexcess-precision=16%> is not compatible with %<-mfpmath=387%>");
  return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16;
       default:
  gcc_unreachable ();
new file   gcc/testsuite/gcc.target/i386/float16-7.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mfpmath=387 -fexcess-precision=16" } */
+/* { dg-excess-errors "'-fexcess-precision=16' is not compatible with
'-mfpmath=387'" } */
+_Float16
+foo (_Float16 a, _Float16 b)
+{
+  return a + b;/* { dg-error "'-fexcess-precision=16' is not
compatible with '-mfpmath=387'" } */
+}
+

> --
> Joseph S. Myers
> joseph@codesourcery.com
Hongtao Liu Aug. 6, 2021, 6:06 a.m. UTC | #3
On Tue, Aug 3, 2021 at 10:44 AM Hongtao Liu <crazylht@gmail.com> wrote:
>
> On Tue, Aug 3, 2021 at 3:34 AM Joseph Myers <joseph@codesourcery.com> wrote:
> >
> > On Mon, 2 Aug 2021, liuhongt via Gcc-patches wrote:
> >
> > > diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> > > index 7979e240426..dc673c89bc8 100644
> > > --- a/gcc/config/i386/i386.c
> > > +++ b/gcc/config/i386/i386.c
> > > @@ -23352,6 +23352,8 @@ ix86_get_excess_precision (enum excess_precision_type type)
> > >       return (type == EXCESS_PRECISION_TYPE_STANDARD
> > >               ? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT
> > >               : FLT_EVAL_METHOD_UNPREDICTABLE);
> > > +      case EXCESS_PRECISION_TYPE_FLOAT16:
> > > +     return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16;
> > >        default:
> > >       gcc_unreachable ();
> > >      }
> >
> > I'd expect an error for -fexcess-precision=16 with -mfpmath=387 (since x87
> > doesn't do float or double arithmetic, but -fexcess-precision=16 implies
> > that all of _Float16, float and double are represented to the range and
> > precision of their type withou any excess precision).
> >
> Yes, additional changes like this.
>
> modified   gcc/config/i386/i386.c
> @@ -23443,6 +23443,9 @@ ix86_get_excess_precision (enum
> excess_precision_type type)
>   ? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT
>   : FLT_EVAL_METHOD_UNPREDICTABLE);
>        case EXCESS_PRECISION_TYPE_FLOAT16:
> + if (TARGET_80387
> +     && !(TARGET_SSE_MATH && TARGET_SSE))
> +   error ("%<-fexcess-precision=16%> is not compatible with %<-mfpmath=387%>");
>   return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16;
>        default:
>   gcc_unreachable ();
> new file   gcc/testsuite/gcc.target/i386/float16-7.c
> @@ -0,0 +1,9 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -mfpmath=387 -fexcess-precision=16" } */
> +/* { dg-excess-errors "'-fexcess-precision=16' is not compatible with
> '-mfpmath=387'" } */
> +_Float16
> +foo (_Float16 a, _Float16 b)
> +{
> +  return a + b;/* { dg-error "'-fexcess-precision=16' is not
> compatible with '-mfpmath=387'" } */
> +}
> +
>
> > --
> > Joseph S. Myers
> > joseph@codesourcery.com
>
>
>
> --
> BR,
> Hongtao


Updated patch and ping for it.

Also for backend changes.
1. For backend m68k/s390 which totally don't support _Float16, backend
will issue an error for -fexcess-precision=16, I think it should be
fine.
2. For backend like arm/aarch64 which supports _Float16 , backend will
set FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16 for -fexcess-precision=16 even
hardware instruction for fp16 is not supported. Would that be ok for
arm?
Hongtao Liu Aug. 17, 2021, 1:53 a.m. UTC | #4
On Fri, Aug 6, 2021 at 2:06 PM Hongtao Liu <crazylht@gmail.com> wrote:
>
> On Tue, Aug 3, 2021 at 10:44 AM Hongtao Liu <crazylht@gmail.com> wrote:
> >
> > On Tue, Aug 3, 2021 at 3:34 AM Joseph Myers <joseph@codesourcery.com> wrote:
> > >
> > > On Mon, 2 Aug 2021, liuhongt via Gcc-patches wrote:
> > >
> > > > diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> > > > index 7979e240426..dc673c89bc8 100644
> > > > --- a/gcc/config/i386/i386.c
> > > > +++ b/gcc/config/i386/i386.c
> > > > @@ -23352,6 +23352,8 @@ ix86_get_excess_precision (enum excess_precision_type type)
> > > >       return (type == EXCESS_PRECISION_TYPE_STANDARD
> > > >               ? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT
> > > >               : FLT_EVAL_METHOD_UNPREDICTABLE);
> > > > +      case EXCESS_PRECISION_TYPE_FLOAT16:
> > > > +     return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16;
> > > >        default:
> > > >       gcc_unreachable ();
> > > >      }
> > >
> > > I'd expect an error for -fexcess-precision=16 with -mfpmath=387 (since x87
> > > doesn't do float or double arithmetic, but -fexcess-precision=16 implies
> > > that all of _Float16, float and double are represented to the range and
> > > precision of their type withou any excess precision).
> > >
> > Yes, additional changes like this.
> >
> > modified   gcc/config/i386/i386.c
> > @@ -23443,6 +23443,9 @@ ix86_get_excess_precision (enum
> > excess_precision_type type)
> >   ? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT
> >   : FLT_EVAL_METHOD_UNPREDICTABLE);
> >        case EXCESS_PRECISION_TYPE_FLOAT16:
> > + if (TARGET_80387
> > +     && !(TARGET_SSE_MATH && TARGET_SSE))
> > +   error ("%<-fexcess-precision=16%> is not compatible with %<-mfpmath=387%>");
> >   return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16;
> >        default:
> >   gcc_unreachable ();
> > new file   gcc/testsuite/gcc.target/i386/float16-7.c
> > @@ -0,0 +1,9 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O2 -mfpmath=387 -fexcess-precision=16" } */
> > +/* { dg-excess-errors "'-fexcess-precision=16' is not compatible with
> > '-mfpmath=387'" } */
> > +_Float16
> > +foo (_Float16 a, _Float16 b)
> > +{
> > +  return a + b;/* { dg-error "'-fexcess-precision=16' is not
> > compatible with '-mfpmath=387'" } */
> > +}
> > +
> >
> > > --
> > > Joseph S. Myers
> > > joseph@codesourcery.com
> >
> >
> >
> > --
> > BR,
> > Hongtao
>
>
> Updated patch and ping for it.
>
> Also for backend changes.
> 1. For backend m68k/s390 which totally don't support _Float16, backend
> will issue an error for -fexcess-precision=16, I think it should be
> fine.
> 2. For backend like arm/aarch64 which supports _Float16 , backend will
> set FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16 for -fexcess-precision=16 even
> hardware instruction for fp16 is not supported. Would that be ok for
> arm?

Ping for this patch.

> --
> BR,
> Hongtao
Hongtao Liu Aug. 24, 2021, 9:39 a.m. UTC | #5
On Tue, Aug 17, 2021 at 9:53 AM Hongtao Liu <crazylht@gmail.com> wrote:
>
> On Fri, Aug 6, 2021 at 2:06 PM Hongtao Liu <crazylht@gmail.com> wrote:
> >
> > On Tue, Aug 3, 2021 at 10:44 AM Hongtao Liu <crazylht@gmail.com> wrote:
> > >
> > > On Tue, Aug 3, 2021 at 3:34 AM Joseph Myers <joseph@codesourcery.com> wrote:
> > > >
> > > > On Mon, 2 Aug 2021, liuhongt via Gcc-patches wrote:
> > > >
> > > > > diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> > > > > index 7979e240426..dc673c89bc8 100644
> > > > > --- a/gcc/config/i386/i386.c
> > > > > +++ b/gcc/config/i386/i386.c
> > > > > @@ -23352,6 +23352,8 @@ ix86_get_excess_precision (enum excess_precision_type type)
> > > > >       return (type == EXCESS_PRECISION_TYPE_STANDARD
> > > > >               ? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT
> > > > >               : FLT_EVAL_METHOD_UNPREDICTABLE);
> > > > > +      case EXCESS_PRECISION_TYPE_FLOAT16:
> > > > > +     return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16;
> > > > >        default:
> > > > >       gcc_unreachable ();
> > > > >      }
> > > >
> > > > I'd expect an error for -fexcess-precision=16 with -mfpmath=387 (since x87
> > > > doesn't do float or double arithmetic, but -fexcess-precision=16 implies
> > > > that all of _Float16, float and double are represented to the range and
> > > > precision of their type withou any excess precision).
> > > >
> > > Yes, additional changes like this.
> > >
> > > modified   gcc/config/i386/i386.c
> > > @@ -23443,6 +23443,9 @@ ix86_get_excess_precision (enum
> > > excess_precision_type type)
> > >   ? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT
> > >   : FLT_EVAL_METHOD_UNPREDICTABLE);
> > >        case EXCESS_PRECISION_TYPE_FLOAT16:
> > > + if (TARGET_80387
> > > +     && !(TARGET_SSE_MATH && TARGET_SSE))
> > > +   error ("%<-fexcess-precision=16%> is not compatible with %<-mfpmath=387%>");
> > >   return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16;
> > >        default:
> > >   gcc_unreachable ();
> > > new file   gcc/testsuite/gcc.target/i386/float16-7.c
> > > @@ -0,0 +1,9 @@
> > > +/* { dg-do compile } */
> > > +/* { dg-options "-O2 -mfpmath=387 -fexcess-precision=16" } */
> > > +/* { dg-excess-errors "'-fexcess-precision=16' is not compatible with
> > > '-mfpmath=387'" } */
> > > +_Float16
> > > +foo (_Float16 a, _Float16 b)
> > > +{
> > > +  return a + b;/* { dg-error "'-fexcess-precision=16' is not
> > > compatible with '-mfpmath=387'" } */
> > > +}
> > > +
> > >
> > > > --
> > > > Joseph S. Myers
> > > > joseph@codesourcery.com
> > >
> > >
> > >
> > > --
> > > BR,
> > > Hongtao
> >
> >
> > Updated patch and ping for it.
> >
> > Also for backend changes.
> > 1. For backend m68k/s390 which totally don't support _Float16, backend
> > will issue an error for -fexcess-precision=16, I think it should be
> > fine.
> > 2. For backend like arm/aarch64 which supports _Float16 , backend will
> > set FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16 for -fexcess-precision=16 even
> > hardware instruction for fp16 is not supported. Would that be ok for
> > arm?
>
> Ping for this patch.
>
> > --
> > BR,
> > Hongtao
>
>
>
> --
> BR,
> Hongtao

Rebased and ping^3, there are plenty of avx512fp16 patches blocked by
this patch, i'd like someone to help review this patch.
Hongtao Liu Sept. 2, 2021, 6:06 a.m. UTC | #6
On Tue, Aug 24, 2021 at 5:39 PM Hongtao Liu <crazylht@gmail.com> wrote:
>
> On Tue, Aug 17, 2021 at 9:53 AM Hongtao Liu <crazylht@gmail.com> wrote:
> >
> > On Fri, Aug 6, 2021 at 2:06 PM Hongtao Liu <crazylht@gmail.com> wrote:
> > >
> > > On Tue, Aug 3, 2021 at 10:44 AM Hongtao Liu <crazylht@gmail.com> wrote:
> > > >
> > > > On Tue, Aug 3, 2021 at 3:34 AM Joseph Myers <joseph@codesourcery.com> wrote:
> > > > >
> > > > > On Mon, 2 Aug 2021, liuhongt via Gcc-patches wrote:
> > > > >
> > > > > > diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> > > > > > index 7979e240426..dc673c89bc8 100644
> > > > > > --- a/gcc/config/i386/i386.c
> > > > > > +++ b/gcc/config/i386/i386.c
> > > > > > @@ -23352,6 +23352,8 @@ ix86_get_excess_precision (enum excess_precision_type type)
> > > > > >       return (type == EXCESS_PRECISION_TYPE_STANDARD
> > > > > >               ? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT
> > > > > >               : FLT_EVAL_METHOD_UNPREDICTABLE);
> > > > > > +      case EXCESS_PRECISION_TYPE_FLOAT16:
> > > > > > +     return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16;
> > > > > >        default:
> > > > > >       gcc_unreachable ();
> > > > > >      }
> > > > >
> > > > > I'd expect an error for -fexcess-precision=16 with -mfpmath=387 (since x87
> > > > > doesn't do float or double arithmetic, but -fexcess-precision=16 implies
> > > > > that all of _Float16, float and double are represented to the range and
> > > > > precision of their type withou any excess precision).
> > > > >
> > > > Yes, additional changes like this.
> > > >
> > > > modified   gcc/config/i386/i386.c
> > > > @@ -23443,6 +23443,9 @@ ix86_get_excess_precision (enum
> > > > excess_precision_type type)
> > > >   ? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT
> > > >   : FLT_EVAL_METHOD_UNPREDICTABLE);
> > > >        case EXCESS_PRECISION_TYPE_FLOAT16:
> > > > + if (TARGET_80387
> > > > +     && !(TARGET_SSE_MATH && TARGET_SSE))
> > > > +   error ("%<-fexcess-precision=16%> is not compatible with %<-mfpmath=387%>");
> > > >   return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16;
> > > >        default:
> > > >   gcc_unreachable ();
> > > > new file   gcc/testsuite/gcc.target/i386/float16-7.c
> > > > @@ -0,0 +1,9 @@
> > > > +/* { dg-do compile } */
> > > > +/* { dg-options "-O2 -mfpmath=387 -fexcess-precision=16" } */
> > > > +/* { dg-excess-errors "'-fexcess-precision=16' is not compatible with
> > > > '-mfpmath=387'" } */
> > > > +_Float16
> > > > +foo (_Float16 a, _Float16 b)
> > > > +{
> > > > +  return a + b;/* { dg-error "'-fexcess-precision=16' is not
> > > > compatible with '-mfpmath=387'" } */
> > > > +}
> > > > +
> > > >
> > > > > --
> > > > > Joseph S. Myers
> > > > > joseph@codesourcery.com
> > > >
> > > >
> > > >
> > > > --
> > > > BR,
> > > > Hongtao
> > >
> > >
> > > Updated patch and ping for it.
> > >
> > > Also for backend changes.
> > > 1. For backend m68k/s390 which totally don't support _Float16, backend
> > > will issue an error for -fexcess-precision=16, I think it should be
> > > fine.
> > > 2. For backend like arm/aarch64 which supports _Float16 , backend will
> > > set FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16 for -fexcess-precision=16 even
> > > hardware instruction for fp16 is not supported. Would that be ok for
> > > arm?
> >
> > Ping for this patch.
> >
> > > --
> > > BR,
> > > Hongtao
> >
> >
> >
> > --
> > BR,
> > Hongtao
>
> Rebased and ping^3, there are plenty of avx512fp16 patches blocked by
> this patch, i'd like someone to help review this patch.
I'm going to check in this patch if there's no objections in the next 48 hours.

> --
> BR,
> Hongtao
diff mbox series

Patch

diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c
index 186367ac6d1..96199bd4b63 100644
--- a/gcc/ada/gcc-interface/misc.c
+++ b/gcc/ada/gcc-interface/misc.c
@@ -256,6 +256,9 @@  gnat_post_options (const char **pfilename ATTRIBUTE_UNUSED)
   /* Excess precision other than "fast" requires front-end support.  */
   if (flag_excess_precision == EXCESS_PRECISION_STANDARD)
     sorry ("%<-fexcess-precision=standard%> for Ada");
+  else if (flag_excess_precision == EXCESS_PRECISION_FLOAT16)
+    sorry ("%<-fexcess-precision=16%> for Ada");
+
   flag_excess_precision = EXCESS_PRECISION_FAST;
 
   /* No psABI change warnings for Ada.  */
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index aacdfb46a02..7e72062c77c 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -8772,7 +8772,7 @@  excess_precision_mode_join (enum flt_eval_method x,
 
    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
+   -fexcess-precision={standard,fast,16} and the implicit excess precision
    the target uses.  */
 
 static enum flt_eval_method
@@ -8784,7 +8784,9 @@  c_ts18661_flt_eval_method (void)
   enum excess_precision_type flag_type
     = (flag_excess_precision == EXCESS_PRECISION_STANDARD
        ? EXCESS_PRECISION_TYPE_STANDARD
-       : EXCESS_PRECISION_TYPE_FAST);
+       : (flag_excess_precision == EXCESS_PRECISION_FLOAT16
+	  ? EXCESS_PRECISION_TYPE_FLOAT16
+	  : EXCESS_PRECISION_TYPE_FAST));
 
   enum flt_eval_method requested
     = targetm.c.excess_precision (flag_type);
diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
index f79f939bd10..5f30354a33c 100644
--- a/gcc/c-family/c-cppbuiltin.c
+++ b/gcc/c-family/c-cppbuiltin.c
@@ -753,7 +753,7 @@  cpp_atomic_builtins (cpp_reader *pfile)
 /* 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].
+   -fexcess-precision=[standard|fast|16].
 
    More intuitively, return TRUE if the excess precision proposed by the
    front-end is the excess precision that will actually be used.  */
@@ -764,7 +764,9 @@  c_cpp_flt_eval_method_iec_559 (void)
   enum excess_precision_type front_end_ept
     = (flag_excess_precision == EXCESS_PRECISION_STANDARD
        ? EXCESS_PRECISION_TYPE_STANDARD
-       : EXCESS_PRECISION_TYPE_FAST);
+       : (flag_excess_precision == EXCESS_PRECISION_FLOAT16
+	  ? EXCESS_PRECISION_TYPE_FLOAT16
+	  : EXCESS_PRECISION_TYPE_FAST));
 
   enum flt_eval_method back_end
     = targetm.c.excess_precision (EXCESS_PRECISION_TYPE_IMPLICIT);
diff --git a/gcc/common.opt b/gcc/common.opt
index d9da1131eda..3dd74766400 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1518,7 +1518,7 @@  Perform a number of minor, expensive optimizations.
 
 fexcess-precision=
 Common Joined RejectNegative Enum(excess_precision) Var(flag_excess_precision) Init(EXCESS_PRECISION_DEFAULT) Optimization SetByCombined
--fexcess-precision=[fast|standard]	Specify handling of excess floating-point precision.
+-fexcess-precision=[fast|standard|16]	Specify handling of excess floating-point precision.
 
 Enum
 Name(excess_precision) Type(enum excess_precision) UnknownError(unknown excess precision style %qs)
@@ -1529,6 +1529,9 @@  Enum(excess_precision) String(fast) Value(EXCESS_PRECISION_FAST)
 EnumValue
 Enum(excess_precision) String(standard) Value(EXCESS_PRECISION_STANDARD)
 
+EnumValue
+Enum(excess_precision) String(16) Value(EXCESS_PRECISION_FLOAT16)
+
 ; 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=
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 3bdf19d71b5..c986a93a243 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -24797,6 +24797,7 @@  aarch64_excess_precision (enum excess_precision_type type)
 		? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16
 		: FLT_EVAL_METHOD_PROMOTE_TO_FLOAT);
       case EXCESS_PRECISION_TYPE_IMPLICIT:
+      case EXCESS_PRECISION_TYPE_FLOAT16:
 	return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16;
       default:
 	gcc_unreachable ();
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 6d781e23ee9..e2a18615860 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -25599,6 +25599,7 @@  arm_excess_precision (enum excess_precision_type type)
 		? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16
 		: FLT_EVAL_METHOD_PROMOTE_TO_FLOAT);
       case EXCESS_PRECISION_TYPE_IMPLICIT:
+      case EXCESS_PRECISION_TYPE_FLOAT16:
 	return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16;
       default:
 	gcc_unreachable ();
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 7979e240426..dc673c89bc8 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -23352,6 +23352,8 @@  ix86_get_excess_precision (enum excess_precision_type type)
 	return (type == EXCESS_PRECISION_TYPE_STANDARD
 		? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT
 		: FLT_EVAL_METHOD_UNPREDICTABLE);
+      case EXCESS_PRECISION_TYPE_FLOAT16:
+	return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16;
       default:
 	gcc_unreachable ();
     }
diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
index 3f63c60fa92..2fef457c09e 100644
--- a/gcc/config/m68k/m68k.c
+++ b/gcc/config/m68k/m68k.c
@@ -7115,6 +7115,8 @@  m68k_excess_precision (enum excess_precision_type type)
 	  return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT;
 
 	return FLT_EVAL_METHOD_PROMOTE_TO_LONG_DOUBLE;
+      case EXCESS_PRECISION_TYPE_FLOAT16:
+	error ("%<-fexcess-precision=16%> is not supported on this target");
       default:
 	gcc_unreachable ();
     }
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index b1d3b99784d..234ee4ac9c4 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -16515,6 +16515,8 @@  s390_excess_precision (enum excess_precision_type type)
 	   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;
+      case EXCESS_PRECISION_TYPE_FLOAT16:
+	error ("%<-fexcess-precision=16%> is not supported on this target");
       default:
 	gcc_unreachable ();
     }
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index 406572e947d..07b9aa656c5 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -424,7 +424,8 @@  enum excess_precision_type
 {
   EXCESS_PRECISION_TYPE_IMPLICIT,
   EXCESS_PRECISION_TYPE_STANDARD,
-  EXCESS_PRECISION_TYPE_FAST
+  EXCESS_PRECISION_TYPE_FAST,
+  EXCESS_PRECISION_TYPE_FLOAT16
 };
 
 /* Level of size optimization.  */
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index f42fd633725..3a1978efc97 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -1161,7 +1161,8 @@  operations will be emulated by software emulation and the @code{float}
 instructions. The default behavior for @code{FLT_EVAL_METHOD} is to keep
 the intermediate result of the operation as 32-bit precision. This may lead
 to inconsistent behavior between software emulation and AVX512-FP16
-instructions.
+instructions. Using @option{-fexcess-precision=16} and  will force round
+back after each operation.
 
 @node Decimal Float
 @section Decimal Floating Types
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index c8f4abe3e41..9fac173a217 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -982,20 +982,26 @@  Do not define this macro if it would never modify @var{m}.
 Return a value, with the same meaning as the C99 macro
 @code{FLT_EVAL_METHOD} 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_FAST},
+@code{EXCESS_PRECISION_TYPE_STANDARD}, or
+@code{EXCESS_PRECISION_TYPE_FLOAT16}.  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_STANDARD}, 
+@code{EXCESS_PRECISION_TYPE_FLOAT16}, 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{]}}.
 Note that unpredictable explicit excess precision does not make sense,
 so a target should never return @code{FLT_EVAL_METHOD_UNPREDICTABLE}
-when @var{type} is @code{EXCESS_PRECISION_TYPE_STANDARD} or
+when @var{type} is @code{EXCESS_PRECISION_TYPE_STANDARD},
+@code{EXCESS_PRECISION_TYPE_FLOAT16} or
 @code{EXCESS_PRECISION_TYPE_FAST}.
 @end deftypefn
+Return a value, with the same meaning as the C99 macro
+@code{FLT_EVAL_METHOD} that describes which excess precision should be
+applied.
 
 @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
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 9c4b5016053..90a8d790758 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -929,6 +929,9 @@  Do not define this macro if it would never modify @var{m}.
 @end defmac
 
 @hook TARGET_C_EXCESS_PRECISION
+Return a value, with the same meaning as the C99 macro
+@code{FLT_EVAL_METHOD} that describes which excess precision should be
+applied.
 
 @hook TARGET_PROMOTE_FUNCTION_MODE
 
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index e43d1de490d..5eeb5046222 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -198,7 +198,8 @@  enum excess_precision
 {
   EXCESS_PRECISION_DEFAULT,
   EXCESS_PRECISION_FAST,
-  EXCESS_PRECISION_STANDARD
+  EXCESS_PRECISION_STANDARD,
+  EXCESS_PRECISION_FLOAT16
 };
 
 /* The options for which values of FLT_EVAL_METHOD are permissible.  */
diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c
index 1723f689a57..847e20e8829 100644
--- a/gcc/fortran/options.c
+++ b/gcc/fortran/options.c
@@ -267,6 +267,9 @@  gfc_post_options (const char **pfilename)
      support.  */
   if (flag_excess_precision == EXCESS_PRECISION_STANDARD)
     sorry ("%<-fexcess-precision=standard%> for Fortran");
+  else if (flag_excess_precision == EXCESS_PRECISION_FLOAT16)
+    sorry ("%<-fexcess-precision=16%> for Fortran");
+
   flag_excess_precision = EXCESS_PRECISION_FAST;
 
   /* Fortran allows associative math - but we cannot reassociate if
diff --git a/gcc/target.def b/gcc/target.def
index 2e40448e6c5..b0bd79a0671 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -6192,18 +6192,21 @@  DEFHOOK
  "Return a value, with the same meaning as the C99 macro\n\
 @code{FLT_EVAL_METHOD} that describes which excess precision should be\n\
 applied.  @var{type} is either @code{EXCESS_PRECISION_TYPE_IMPLICIT},\n\
-@code{EXCESS_PRECISION_TYPE_FAST}, or\n\
-@code{EXCESS_PRECISION_TYPE_STANDARD}.  For\n\
+@code{EXCESS_PRECISION_TYPE_FAST},\n\
+@code{EXCESS_PRECISION_TYPE_STANDARD}, or\n\
+@code{EXCESS_PRECISION_TYPE_FLOAT16}.  For\n\
 @code{EXCESS_PRECISION_TYPE_IMPLICIT}, the target should return which\n\
 precision and range operations will be implictly evaluated in regardless\n\
 of the excess precision explicitly added.  For\n\
-@code{EXCESS_PRECISION_TYPE_STANDARD} and\n\
+@code{EXCESS_PRECISION_TYPE_STANDARD}, \n\
+@code{EXCESS_PRECISION_TYPE_FLOAT16}, and\n\
 @code{EXCESS_PRECISION_TYPE_FAST}, the target should return the\n\
 explicit excess precision that should be added depending on the\n\
 value set for @option{-fexcess-precision=@r{[}standard@r{|}fast@r{]}}.\n\
 Note that unpredictable explicit excess precision does not make sense,\n\
 so a target should never return @code{FLT_EVAL_METHOD_UNPREDICTABLE}\n\
-when @var{type} is @code{EXCESS_PRECISION_TYPE_STANDARD} or\n\
+when @var{type} is @code{EXCESS_PRECISION_TYPE_STANDARD},\n\
+@code{EXCESS_PRECISION_TYPE_FLOAT16} or\n\
 @code{EXCESS_PRECISION_TYPE_FAST}.",
  enum flt_eval_method, (enum excess_precision_type type),
  default_excess_precision)
diff --git a/gcc/testsuite/gcc.target/i386/float16-6.c b/gcc/testsuite/gcc.target/i386/float16-6.c
new file mode 100644
index 00000000000..599f4495086
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/float16-6.c
@@ -0,0 +1,8 @@ 
+/* { dg-do compile } */
+/* { dg-options "-msse2 -O2 -fdump-tree-gimple -fexcess-precision=16" } */
+/* { dg-final { scan-tree-dump-not "\\(float\\)" "gimple" } } */
+_Float16
+foo (_Float16 a, _Float16 b, _Float16 c)
+{
+  return a + b + c;
+}
diff --git a/gcc/tree.c b/gcc/tree.c
index bead1ac134c..20dfbe00b88 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -7633,7 +7633,8 @@  excess_precision_type (tree type)
   enum excess_precision_type requested_type
     = (flag_excess_precision == EXCESS_PRECISION_FAST
        ? EXCESS_PRECISION_TYPE_FAST
-       : EXCESS_PRECISION_TYPE_STANDARD);
+       : (flag_excess_precision == EXCESS_PRECISION_FLOAT16
+	  ? EXCESS_PRECISION_TYPE_FLOAT16 :EXCESS_PRECISION_TYPE_STANDARD));
 
   enum flt_eval_method target_flt_eval_method
     = targetm.c.excess_precision (requested_type);