__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 <jakub@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.
(cherry picked from commit
f39e6b4f5cd4e5362cf4b1004a591df2c8b00304)
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));
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));
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);
/* 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
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;
--- /dev/null
+/* 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 ();
+}