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)