From 00be2a5f394119085c72aee8d18adefd8ec3ec22 Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Wed, 13 Nov 2019 15:25:15 +0000 Subject: [PATCH] Add C2x *_NORM_MAX constants to . C2x adds constants FLT_NORM_MAX, DBL_NORM_MAX and LDBL_NORM_MAX. These are for the maximum "normalized" finite floating-point number, where the given definition of normalized is that all possible values with MANT_DIG significand digits (leading one not zero) can be represented with that exponent. The effect of that definition is that these macros are the same as the corresponding MAX macros for all formats except IBM long double, where the NORM_MAX value has exponent 1 smaller than the MAX one so that all 106 digits can be 1. This patch adds those macros to GCC. They are only defined for float, double and long double; C2x does not include such macros for DFP types, and while the integration of TS 18661-3 into C2x has not yet occurred, the draft proposed text does not add them for the _FloatN / _FloatNx types (where they would always be the same as the MAX macros). Bootstrapped with no regressions on x86_64-pc-linux-gnu. Also tested compilation of the new test for powerpc-linux-gnu to confirm the check of LDBL_NORM_MAX in the IBM long double case does get properly optimized out. gcc: * ginclude/float.c [__STDC_VERSION__ > 201710L] (FLT_NORM_MAX, DBL_NORM_MAX, LDBL_NORM_MAX): Define. * real.c (get_max_float): Add norm_max argument. * real.h (get_max_float): Update prototype. * builtins.c (fold_builtin_interclass_mathfn): Update calls to get_max_float. gcc/c-family: * c-cppbuiltin.c (builtin_define_float_constants): Also define NORM_MAX constants. Update call to get_max_float. (LAZY_HEX_FP_VALUES_CNT): Update value to include NORM_MAX constants. gcc/d: * d-target.cc (define_float_constants): Update call to get_max_float. gcc/testsuite: * gcc.dg/c11-float-3.c, gcc.dg/c2x-float-1.c: New tests. From-SVN: r278145 --- gcc/ChangeLog | 9 ++++++++ gcc/builtins.c | 6 ++--- gcc/c-family/ChangeLog | 7 ++++++ gcc/c-family/c-cppbuiltin.c | 11 ++++++--- gcc/d/ChangeLog | 5 ++++ gcc/d/d-target.cc | 2 +- gcc/ginclude/float.h | 12 ++++++++++ gcc/real.c | 15 ++++++++---- gcc/real.h | 2 +- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/gcc.dg/c11-float-3.c | 17 ++++++++++++++ gcc/testsuite/gcc.dg/c2x-float-1.c | 37 ++++++++++++++++++++++++++++++ 12 files changed, 115 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/c11-float-3.c create mode 100644 gcc/testsuite/gcc.dg/c2x-float-1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fdc7805d574..5a52fd6516f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2019-11-13 Joseph Myers + + * ginclude/float.c [__STDC_VERSION__ > 201710L] (FLT_NORM_MAX, + DBL_NORM_MAX, LDBL_NORM_MAX): Define. + * real.c (get_max_float): Add norm_max argument. + * real.h (get_max_float): Update prototype. + * builtins.c (fold_builtin_interclass_mathfn): Update calls to + get_max_float. + 2019-11-13 Martin Liska * dbgcnt.c (test_sorted_dbg_counters): New. diff --git a/gcc/builtins.c b/gcc/builtins.c index 450cc7ad4c2..f94151bd84d 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -9038,7 +9038,7 @@ fold_builtin_interclass_mathfn (location_t loc, tree fndecl, tree arg) mode = DFmode; arg = fold_build1_loc (loc, NOP_EXPR, type, arg); } - get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf)); + get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf), false); real_from_string (&r, buf); result = build_call_expr (isgr_fn, 2, fold_build1_loc (loc, ABS_EXPR, type, arg), @@ -9062,7 +9062,7 @@ fold_builtin_interclass_mathfn (location_t loc, tree fndecl, tree arg) mode = DFmode; arg = fold_build1_loc (loc, NOP_EXPR, type, arg); } - get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf)); + get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf), false); real_from_string (&r, buf); result = build_call_expr (isle_fn, 2, fold_build1_loc (loc, ABS_EXPR, type, arg), @@ -9101,7 +9101,7 @@ fold_builtin_interclass_mathfn (location_t loc, tree fndecl, tree arg) } arg = fold_build1_loc (loc, ABS_EXPR, type, arg); - get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf)); + get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf), false); real_from_string (&rmax, buf); sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (orig_mode)->emin - 1); real_from_string (&rmin, buf); diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index c7813a12d7d..e96ed631f52 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,10 @@ +2019-11-13 Joseph Myers + + * c-cppbuiltin.c (builtin_define_float_constants): Also define + NORM_MAX constants. Update call to get_max_float. + (LAZY_HEX_FP_VALUES_CNT): Update value to include NORM_MAX + constants. + 2019-11-13 Eric Botcazou * c-ada-spec.c (get_underlying_decl): Do not look through typedefs. diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c index cf3d437fc37..76d1e4a380e 100644 --- a/gcc/c-family/c-cppbuiltin.c +++ b/gcc/c-family/c-cppbuiltin.c @@ -259,11 +259,16 @@ builtin_define_float_constants (const char *name_prefix, /* Since, for the supported formats, B is always a power of 2, we construct the following numbers directly as a hexadecimal constants. */ - get_max_float (fmt, buf, sizeof (buf)); + get_max_float (fmt, buf, sizeof (buf), false); sprintf (name, "__%s_MAX__", name_prefix); builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix, fp_cast); + get_max_float (fmt, buf, sizeof (buf), true); + + sprintf (name, "__%s_NORM_MAX__", name_prefix); + builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix, fp_cast); + /* The minimum normalized positive floating-point number, b**(emin-1). */ sprintf (name, "__%s_MIN__", name_prefix); @@ -1607,10 +1612,10 @@ struct GTY(()) lazy_hex_fp_value_struct }; /* Number of the expensive to compute macros we should evaluate lazily. Each builtin_define_float_constants invocation calls - builtin_define_with_hex_fp_value 4 times and builtin_define_float_constants + builtin_define_with_hex_fp_value 5 times and builtin_define_float_constants is called for FLT, DBL, LDBL and up to NUM_FLOATN_NX_TYPES times for FLTNN*. */ -#define LAZY_HEX_FP_VALUES_CNT (4 * (3 + NUM_FLOATN_NX_TYPES)) +#define LAZY_HEX_FP_VALUES_CNT (5 * (3 + NUM_FLOATN_NX_TYPES)) static GTY(()) struct lazy_hex_fp_value_struct lazy_hex_fp_values[LAZY_HEX_FP_VALUES_CNT]; static GTY(()) unsigned lazy_hex_fp_value_count; diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog index 2591b4c727f..012d4958a44 100644 --- a/gcc/d/ChangeLog +++ b/gcc/d/ChangeLog @@ -1,3 +1,8 @@ +2019-11-13 Joseph Myers + + * d-target.cc (define_float_constants): Update call to + get_max_float. + 2019-11-04 Richard Sandiford * d-builtins.cc (build_frontend_type): Cope with variable diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc index dfaf9bf3792..37a07b14d9f 100644 --- a/gcc/d/d-target.cc +++ b/gcc/d/d-target.cc @@ -82,7 +82,7 @@ define_float_constants (tree type) const real_format *fmt = REAL_MODE_FORMAT (mode); /* The largest representable value that's not infinity. */ - get_max_float (fmt, buf, sizeof (buf)); + get_max_float (fmt, buf, sizeof (buf), false); real_from_string (&T::max.rv (), buf); /* The smallest representable normalized value that's not 0. */ diff --git a/gcc/ginclude/float.h b/gcc/ginclude/float.h index dc91c75603e..cafedc16c2f 100644 --- a/gcc/ginclude/float.h +++ b/gcc/ginclude/float.h @@ -238,6 +238,18 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #endif /* C11 */ +#if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L +/* Maximum finite positive value with MANT_DIG digits in the + significand taking their maximum value. */ +#undef FLT_NORM_MAX +#undef DBL_NORM_MAX +#undef LDBL_NORM_MAX +#define FLT_NORM_MAX __FLT_NORM_MAX__ +#define DBL_NORM_MAX __DBL_NORM_MAX__ +#define LDBL_NORM_MAX __LDBL_NORM_MAX__ + +#endif /* C2X */ + #ifdef __STDC_WANT_IEC_60559_BFP_EXT__ /* Number of decimal digits for which conversions between decimal character strings and binary formats, in both directions, are diff --git a/gcc/real.c b/gcc/real.c index 6e6a3949a45..90067f0087b 100644 --- a/gcc/real.c +++ b/gcc/real.c @@ -5242,13 +5242,19 @@ real_nextafter (REAL_VALUE_TYPE *r, format_helper fmt, /* Write into BUF the maximum representable finite floating-point number, (1 - b**-p) * b**emax for a given FP format FMT as a hex float string. LEN is the size of BUF, and the buffer must be large - enough to contain the resulting string. */ + enough to contain the resulting string. If NORM_MAX, instead write + the maximum representable finite normalized floating-point number, + defined to be such that all choices of digits for that exponent are + representable in the format (this only makes a difference for IBM + long double). */ void -get_max_float (const struct real_format *fmt, char *buf, size_t len) +get_max_float (const struct real_format *fmt, char *buf, size_t len, + bool norm_max) { int i, n; char *p; + bool is_ibm_extended = fmt->pnan < fmt->p; strcpy (buf, "0x0."); n = fmt->p; @@ -5256,8 +5262,9 @@ get_max_float (const struct real_format *fmt, char *buf, size_t len) *p++ = 'f'; if (i < n) *p++ = "08ce"[n - i]; - sprintf (p, "p%d", fmt->emax); - if (fmt->pnan < fmt->p) + sprintf (p, "p%d", + (is_ibm_extended && norm_max) ? fmt->emax - 1 : fmt->emax); + if (is_ibm_extended && !norm_max) { /* This is an IBM extended double format made up of two IEEE doubles. The value of the long double is the sum of the diff --git a/gcc/real.h b/gcc/real.h index 2f41834ecfd..0f660c9c671 100644 --- a/gcc/real.h +++ b/gcc/real.h @@ -524,7 +524,7 @@ extern bool real_nextafter (REAL_VALUE_TYPE *, format_helper, /* Write into BUF the maximum representable finite floating-point number, (1 - b**-p) * b**emax for a given FP format FMT as a hex float string. BUF must be large enough to contain the result. */ -extern void get_max_float (const struct real_format *, char *, size_t); +extern void get_max_float (const struct real_format *, char *, size_t, bool); #ifndef GENERATOR_FILE /* real related routines. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 23ad51b785c..9e062e799d3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-11-13 Joseph Myers + + * gcc.dg/c11-float-3.c, gcc.dg/c2x-float-1.c: New tests. + 2019-11-13 Martin Jambor PR ipa/92454 diff --git a/gcc/testsuite/gcc.dg/c11-float-3.c b/gcc/testsuite/gcc.dg/c11-float-3.c new file mode 100644 index 00000000000..95d2074ea2d --- /dev/null +++ b/gcc/testsuite/gcc.dg/c11-float-3.c @@ -0,0 +1,17 @@ +/* Test *_NORM_MAX not defined for C11. */ +/* { dg-do preprocess } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ + +#include + +#ifdef FLT_NORM_MAX +#error "FLT_NORM_MAX defined" +#endif + +#ifdef DBL_NORM_MAX +#error "DBL_NORM_MAX defined" +#endif + +#ifdef LDBL_NORM_MAX +#error "LDBL_NORM_MAX defined" +#endif diff --git a/gcc/testsuite/gcc.dg/c2x-float-1.c b/gcc/testsuite/gcc.dg/c2x-float-1.c new file mode 100644 index 00000000000..8df85f935fd --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-float-1.c @@ -0,0 +1,37 @@ +/* Test *_NORM_MAX macros. */ +/* { dg-do run } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +#include + +#ifndef FLT_NORM_MAX +#error "FLT_NORM_MAX undefined" +#endif + +#ifndef DBL_NORM_MAX +#error "DBL_NORM_MAX undefined" +#endif + +#ifndef LDBL_NORM_MAX +#error "LDBL_NORM_MAX undefined" +#endif + +extern void abort (void); +extern void exit (int); + +int +main (void) +{ + if (FLT_NORM_MAX != FLT_MAX) + abort (); + if (DBL_NORM_MAX != DBL_MAX) + abort (); +#if LDBL_MANT_DIG == 106 + if (LDBL_NORM_MAX != 0x0.ffffffffffffffffffffffffffcp1023L) + abort (); +#else + if (LDBL_NORM_MAX != LDBL_MAX) + abort (); +#endif + exit (0); +} -- 2.30.2