Add C2x *_NORM_MAX constants to <float.h>.
authorJoseph Myers <joseph@codesourcery.com>
Wed, 13 Nov 2019 15:25:15 +0000 (15:25 +0000)
committerJoseph Myers <jsm28@gcc.gnu.org>
Wed, 13 Nov 2019 15:25:15 +0000 (15:25 +0000)
C2x adds <float.h> 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

12 files changed:
gcc/ChangeLog
gcc/builtins.c
gcc/c-family/ChangeLog
gcc/c-family/c-cppbuiltin.c
gcc/d/ChangeLog
gcc/d/d-target.cc
gcc/ginclude/float.h
gcc/real.c
gcc/real.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/c11-float-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c2x-float-1.c [new file with mode: 0644]

index fdc7805d5740e751256245bd0f3fc58dd7e70bc5..5a52fd6516f4c03ef5e0e1cc9ec65e0723c9543c 100644 (file)
@@ -1,3 +1,12 @@
+2019-11-13  Joseph Myers  <joseph@codesourcery.com>
+
+       * 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  <mliska@suse.cz>
 
        * dbgcnt.c (test_sorted_dbg_counters): New.
index 450cc7ad4c23b3f67d3931612574fec98a83b198..f94151bd84d8f762de63277b78d3d76597a92b09 100644 (file)
@@ -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);
index c7813a12d7db623279e7c0a6aea8f56ccdddad4d..e96ed631f52e61af0249206c3cf9199cc1de2985 100644 (file)
@@ -1,3 +1,10 @@
+2019-11-13  Joseph Myers  <joseph@codesourcery.com>
+
+       * 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  <ebotcazou@adacore.com>
 
        * c-ada-spec.c (get_underlying_decl): Do not look through typedefs.
index cf3d437fc37065704448984a0b284c916ba73509..76d1e4a380e03495d2036bcead9e13e117c40c04 100644 (file)
@@ -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;
index 2591b4c727f8833fa1b8b28b7800ae5717a96a16..012d4958a4466ea44051e12bb7da521272c5a502 100644 (file)
@@ -1,3 +1,8 @@
+2019-11-13  Joseph Myers  <joseph@codesourcery.com>
+
+       * d-target.cc (define_float_constants): Update call to
+       get_max_float.
+
 2019-11-04  Richard Sandiford  <richard.sandiford@arm.com>
 
        * d-builtins.cc (build_frontend_type): Cope with variable
index dfaf9bf3792c80322f4a2f048a019af8970c5e65..37a07b14d9fe75838f042312b21632f07712ae2a 100644 (file)
@@ -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.  */
index dc91c75603e0471b1f16a49ea1233bc7d937372d..cafedc16c2f98ab1a711b2623180e3653a077bbf 100644 (file)
@@ -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
index 6e6a3949a457590756a130fc062825df5ddc1168..90067f0087b9dab6ab23775bc68957708e28985a 100644 (file)
@@ -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
index 2f41834ecfd22f9e2f8ec5b3de23a245fdabd958..0f660c9c671c26fe21e3d85fbec219e234a24e7c 100644 (file)
@@ -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.  */
index 23ad51b785c277e4abc2036eb795c5dabc0734a3..9e062e799d31ad70fbdefdc33a93de2b67301228 100644 (file)
@@ -1,3 +1,7 @@
+2019-11-13  Joseph Myers  <joseph@codesourcery.com>
+
+       * gcc.dg/c11-float-3.c, gcc.dg/c2x-float-1.c: New tests.
+
 2019-11-13  Martin Jambor  <mjambor@suse.cz>
 
        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 (file)
index 0000000..95d2074
--- /dev/null
@@ -0,0 +1,17 @@
+/* Test *_NORM_MAX not defined for C11.  */
+/* { dg-do preprocess } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <float.h>
+
+#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 (file)
index 0000000..8df85f9
--- /dev/null
@@ -0,0 +1,37 @@
+/* Test *_NORM_MAX macros.  */
+/* { dg-do run } */
+/* { dg-options "-std=c2x -pedantic-errors" } */
+
+#include <float.h>
+
+#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);
+}