On Tue, 26 Nov 2024, Jakub Jelinek wrote:

> Hi!
> 
> __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.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK.

Thanks,
Richard.

> 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.
> 
> --- gcc/real.cc.jj    2024-10-25 10:00:29.511767242 +0200
> +++ gcc/real.cc       2024-11-25 14:00:49.502682021 +0100
> @@ -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;
> --- gcc/builtins.cc.jj        2024-11-21 09:33:29.192600776 +0100
> +++ gcc/builtins.cc   2024-11-25 14:15:55.923876729 +0100
> @@ -9580,7 +9580,7 @@ fold_builtin_interclass_mathfn (location
>           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
>           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
>       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);
>  
> --- gcc/c-family/c-cppbuiltin.cc.jj   2024-11-15 08:43:34.598097013 +0100
> +++ gcc/c-family/c-cppbuiltin.cc      2024-11-25 14:05:51.558414628 +0100
> @@ -357,17 +357,8 @@ builtin_define_decimal_float_constants (
>  
>    /* 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
> --- gcc/testsuite/gcc.dg/dfp/pr43374.c.jj     2024-11-25 15:01:42.406115003 
> +0100
> +++ gcc/testsuite/gcc.dg/dfp/pr43374.c        2024-11-25 15:00:21.781252431 
> +0100
> @@ -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 ();
> +}
> 
>       Jakub
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)

Reply via email to