https://gcc.gnu.org/g:f39e6b4f5cd4e5362cf4b1004a591df2c8b00304

commit r15-5671-gf39e6b4f5cd4e5362cf4b1004a591df2c8b00304
Author: Jakub Jelinek <ja...@redhat.com>
Date:   Tue Nov 26 09:45:21 2024 +0100

    builtins: Fix up DFP ICEs on __builtin_is{inf,finite,normal} [PR43374]
    
    __builtin_is{inf,finite,normal} builtins ICE on _Decimal{32,64,128,64x}
    operands unless those operands are constant.
    
    The problem is that we fold the builtins to comparisons with the largest
    finite number, but
    a) get_max_float was only handling binary floats
    b) real_from_string again assumes binary float
    and so we were ICEing in the build_real called after the two calls.
    
    This patch adds decimal handling into get_max_float (well, moves it
    from c-cppbuiltin.cc which was printing those for __DEC{32,64,128}_MAX__
    macros) and uses real_from_string3 (perhaps it is time to rename it
    to just real_from_string now that we can use function overloading)
    so that it handles both binary and decimal floats.
    
    2024-11-26  Jakub Jelinek  <ja...@redhat.com>
    
            PR middle-end/43374
    gcc/
            * real.cc (get_max_float): Handle decimal float.
            * builtins.cc (fold_builtin_interclass_mathfn): Use
            real_from_string3 rather than real_from_string.  Use
            "1E%d" format string rather than "0x1p%d" for decimal
            float minimum.
    gcc/c-family/
            * c-cppbuiltin.cc (builtin_define_decimal_float_constants): Use
            get_max_float.
    gcc/testsuite/
            * gcc.dg/dfp/pr43374.c: New test.

Diff:
---
 gcc/builtins.cc                    | 13 +++++----
 gcc/c-family/c-cppbuiltin.cc       | 13 ++-------
 gcc/real.cc                        | 16 +++++++++++
 gcc/testsuite/gcc.dg/dfp/pr43374.c | 56 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 82 insertions(+), 16 deletions(-)

diff --git a/gcc/builtins.cc b/gcc/builtins.cc
index 029c561d4665..055b31d264ca 100644
--- a/gcc/builtins.cc
+++ b/gcc/builtins.cc
@@ -9580,7 +9580,7 @@ fold_builtin_interclass_mathfn (location_t loc, tree 
fndecl, tree arg)
            arg = fold_build1_loc (loc, NOP_EXPR, type, arg);
          }
        get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf), false);
-       real_from_string (&r, buf);
+       real_from_string3 (&r, buf, mode);
        result = build_call_expr (isgr_fn, 2,
                                  fold_build1_loc (loc, ABS_EXPR, type, arg),
                                  build_real (type, r));
@@ -9604,7 +9604,7 @@ fold_builtin_interclass_mathfn (location_t loc, tree 
fndecl, tree arg)
            arg = fold_build1_loc (loc, NOP_EXPR, type, arg);
          }
        get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf), false);
-       real_from_string (&r, buf);
+       real_from_string3 (&r, buf, mode);
        result = build_call_expr (isle_fn, 2,
                                  fold_build1_loc (loc, ABS_EXPR, type, arg),
                                  build_real (type, r));
@@ -9643,9 +9643,12 @@ 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), false);
-       real_from_string (&rmax, buf);
-       sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (orig_mode)->emin - 1);
-       real_from_string (&rmin, buf);
+       real_from_string3 (&rmax, buf, mode);
+       if (DECIMAL_FLOAT_MODE_P (mode))
+         sprintf (buf, "1E%d", REAL_MODE_FORMAT (orig_mode)->emin - 1);
+       else
+         sprintf (buf, "0x1p%d", REAL_MODE_FORMAT (orig_mode)->emin - 1);
+       real_from_string3 (&rmin, buf, orig_mode);
        max_exp = build_real (type, rmax);
        min_exp = build_real (type, rmin);
 
diff --git a/gcc/c-family/c-cppbuiltin.cc b/gcc/c-family/c-cppbuiltin.cc
index 349918c325cd..8fbfef561e8a 100644
--- a/gcc/c-family/c-cppbuiltin.cc
+++ b/gcc/c-family/c-cppbuiltin.cc
@@ -357,17 +357,8 @@ builtin_define_decimal_float_constants (const char 
*name_prefix,
 
   /* Compute the maximum representable value.  */
   sprintf (name, "__%s_MAX__", name_prefix);
-  p = buf;
-  for (digits = fmt->p; digits; digits--)
-    {
-      *p++ = '9';
-      if (digits == fmt->p)
-       *p++ = '.';
-    }
-  *p = 0;
-  /* fmt->p plus 1, to account for the decimal point and fmt->emax
-     minus 1 because the digits are nines, not 1.0.  */
-  sprintf (&buf[fmt->p + 1], "E%d%s", fmt->emax - 1, suffix);
+  get_max_float (fmt, buf, sizeof (buf) - strlen (suffix), false);
+  strcat (buf, suffix);
   builtin_define_with_value (name, buf, 0);
 
   /* Compute epsilon (the difference between 1 and least value greater
diff --git a/gcc/real.cc b/gcc/real.cc
index 1392595a72f1..b89ff8334091 100644
--- a/gcc/real.cc
+++ b/gcc/real.cc
@@ -5438,6 +5438,22 @@ void
 get_max_float (const struct real_format *fmt, char *buf, size_t len,
               bool norm_max)
 {
+  if (fmt->b == 10)
+    {
+      char *p = buf;
+      for (int i = fmt->p; i; i--)
+       {
+         *p++ = '9';
+         if (i == fmt->p)
+           *p++ = '.';
+       }
+      /* fmt->p plus 1, to account for the decimal point and fmt->emax
+        minus 1 because the digits are nines, not 1.0.  */
+      sprintf (buf + fmt->p + 1, "E%d", fmt->emax - 1);
+      gcc_assert (strlen (buf) < len);
+      return;
+    }
+
   int i, n;
   char *p;
   bool is_ibm_extended = fmt->pnan < fmt->p;
diff --git a/gcc/testsuite/gcc.dg/dfp/pr43374.c 
b/gcc/testsuite/gcc.dg/dfp/pr43374.c
new file mode 100644
index 000000000000..83f3dca1c1f2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/dfp/pr43374.c
@@ -0,0 +1,56 @@
+/* PR middle-end/43374 */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+__attribute__((noipa)) int
+foo (_Decimal32 x)
+{
+  return __builtin_isinf (x);
+}
+
+__attribute__((noipa)) int
+bar (_Decimal64 x)
+{
+  return __builtin_isfinite (x);
+}
+
+__attribute__((noipa)) int
+baz (_Decimal128 x)
+{
+  return __builtin_isnormal (x);
+}
+
+int
+main ()
+{
+  if (!foo (__builtin_infd32 ())
+      || !foo (-__builtin_infd32 ())
+      || foo (__builtin_nand32 (""))
+      || foo (9.999999E96DF)
+      || foo (-1E-95DF)
+      || foo (0.999999E-95DF)
+      || foo (-0.000001E-95DF)
+      || foo (0.000DF)
+      || foo (-0.00000DF))
+    __builtin_abort ();
+  if (bar (__builtin_infd64 ())
+      || bar (-__builtin_infd64 ())
+      || bar (__builtin_nand64 (""))
+      || !bar (9.999999999999999E384DD)
+      || !bar (-1E-383DD)
+      || !bar (0.999999999999999E-383DD)
+      || !bar (-0.000000000000001E-383DD)
+      || !bar (0.000DD)
+      || !bar (-0.0000000000DD))
+    __builtin_abort ();
+  if (baz (__builtin_infd128 ())
+      || baz (-__builtin_infd128 ())
+      || baz (__builtin_nand128 (""))
+      || !baz (9.999999999999999999999999999999999E6144DL)
+      || !baz (-1E-6143DL)
+      || baz (0.999999999999999999999999999999999E-6143DL)
+      || baz (-0.000000000000000000000000000000001E-6143DL)
+      || baz (0.000DL)
+      || baz (-0.0000000000000000000000DL))
+    __builtin_abort ();
+}

Reply via email to