Commit 7faa1bbb by Kaveh R. Ghazi Committed by Kaveh Ghazi

re PR target/30652 (SSE expansion is missing for isinf() and other fpclassify functions)

	PR target/30652
	PR middle-end/20558

	* builtins.c (expand_builtin_interclass_mathfn): Provide a
	generic fallback for isinf.
	* c-cppbuiltin.c (builtin_define_float_constants): Move FP max
	calculation code ...
	* real.c (get_max_float): ... to here.
	* real.h (get_max_float): New.

testsuite:
	* gcc.dg/pr28796-1.c: Add more cases.
	* gcc.dg/pr28796-2.c: Likewise.

From-SVN: r126724
parent b5d32c25
2007-07-18 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
PR target/30652
PR middle-end/20558
* builtins.c (expand_builtin_interclass_mathfn): Provide a
generic fallback for isinf.
* c-cppbuiltin.c (builtin_define_float_constants): Move FP max
calculation code ...
* real.c (get_max_float): ... to here.
* real.h (get_max_float): New.
2007-07-18 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
PR middle-end/32668
* builtin-attrs.def (ATTR_TYPEGENERIC,
......
......@@ -2275,6 +2275,30 @@ expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget)
return target;
}
/* If there is no optab, try generic code. */
switch (DECL_FUNCTION_CODE (fndecl))
{
tree result;
CASE_FLT_FN (BUILT_IN_ISINF):
{
/* isinf(x) -> isgreater(fabs(x),DBL_MAX). */
tree const isgr_fn = built_in_decls[BUILT_IN_ISGREATER];
tree const type = TREE_TYPE (arg);
REAL_VALUE_TYPE r;
char buf[128];
get_max_float (REAL_MODE_FORMAT (mode), buf, sizeof (buf));
real_from_string (&r, buf);
result = build_call_expr (isgr_fn, 2,
fold_build1 (ABS_EXPR, type, arg),
build_real (type, r));
return expand_expr (result, target, VOIDmode, EXPAND_NORMAL);
}
default:
break;
}
target = expand_call (exp, target, target == const0_rtx);
return target;
......
......@@ -200,31 +200,8 @@ 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. */
/* The maximum representable finite floating-point number,
(1 - b**-p) * b**emax */
{
int i, n;
char *p;
strcpy (buf, "0x0.");
n = fmt->p;
for (i = 0, p = buf + 4; i + 3 < n; i += 4)
*p++ = 'f';
if (i < n)
*p++ = "08ce"[n - i];
sprintf (p, "p%d", fmt->emax);
if (fmt->pnan < fmt->p)
{
/* This is an IBM extended double format made up of two IEEE
doubles. The value of the long double is the sum of the
values of the two parts. The most significant part is
required to be the value of the long double rounded to the
nearest double. Rounding means we need a slightly smaller
value for LDBL_MAX. */
buf[4 + fmt->pnan / 4] = "7bde"[fmt->pnan % 4];
}
}
get_max_float (fmt, buf, sizeof (buf));
sprintf (name, "__%s_MAX__", name_prefix);
builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix, fp_cast);
......
......@@ -4835,3 +4835,35 @@ real_isinteger (const REAL_VALUE_TYPE *c, enum machine_mode mode)
real_trunc (&cint, mode, c);
return real_identical (c, &cint);
}
/* 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. */
void
get_max_float (const struct real_format *fmt, char *buf, size_t len)
{
int i, n;
char *p;
strcpy (buf, "0x0.");
n = fmt->p;
for (i = 0, p = buf + 4; i + 3 < n; i += 4)
*p++ = 'f';
if (i < n)
*p++ = "08ce"[n - i];
sprintf (p, "p%d", fmt->emax);
if (fmt->pnan < fmt->p)
{
/* This is an IBM extended double format made up of two IEEE
doubles. The value of the long double is the sum of the
values of the two parts. The most significant part is
required to be the value of the long double rounded to the
nearest double. Rounding means we need a slightly smaller
value for LDBL_MAX. */
buf[4 + fmt->pnan / 4] = "7bde"[fmt->pnan % 4];
}
gcc_assert (strlen (buf) < len);
}
......@@ -438,4 +438,8 @@ extern void mpfr_from_real (mpfr_ptr, const REAL_VALUE_TYPE *, mp_rnd_t);
/* Check whether the real constant value given is an integer. */
extern bool real_isinteger (const REAL_VALUE_TYPE *c, enum machine_mode mode);
/* 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);
#endif /* ! GCC_REAL_H */
2007-07-18 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* gcc.dg/pr28796-1.c: Add more cases.
* gcc.dg/pr28796-2.c: Likewise.
2007-07-17 Janus Weil <jaydub66@gmail.com>
PR fortran/32535
/* { dg-do link } */
/* { dg-options "-ffinite-math-only" } */
extern void link_error(void);
float f;
double d;
long double ld;
int main()
{
if (__builtin_isunordered (f, f) != 0)
link_error ();
if (__builtin_isunordered (d, d) != 0)
link_error ();
if (__builtin_isunordered (ld, ld) != 0)
link_error ();
if (__builtin_isnan (f) != 0)
link_error ();
if (__builtin_isnan (d) != 0)
link_error ();
if (__builtin_isnan (ld) != 0)
link_error ();
if (__builtin_isnanf (f) != 0)
link_error ();
if (__builtin_isnanl (ld) != 0)
link_error ();
if (__builtin_finite (f) != 1)
link_error ();
if (__builtin_finite (d) != 1)
link_error ();
if (__builtin_finite (ld) != 1)
link_error ();
if (__builtin_finitef (f) != 1)
link_error ();
if (__builtin_finitel (ld) != 1)
link_error ();
if (f != f)
link_error ();
if (d != d)
link_error ();
if (ld != ld)
link_error ();
return 0;
}
......@@ -4,19 +4,79 @@
extern void abort (void);
void foo(float f)
void __attribute__ ((__noinline__))
foo_1 (float f, double d, long double ld,
int res_unord, int res_isnan, int res_isinf, int res_isfin)
{
if (__builtin_isunordered (f, f) != 1)
if (__builtin_isunordered (f, 0) != res_unord)
abort ();
if (__builtin_isnan (f) != 1)
if (__builtin_isunordered (0, f) != res_unord)
abort ();
if (__builtin_finite (f) != 0)
if (__builtin_isunordered (d, 0) != res_unord)
abort ();
if (__builtin_isunordered (0, d) != res_unord)
abort ();
if (__builtin_isunordered (ld, 0) != res_unord)
abort ();
if (__builtin_isunordered (0, ld) != res_unord)
abort ();
if (__builtin_isnan (f) != res_isnan)
abort ();
if (__builtin_isnan (d) != res_isnan)
abort ();
if (__builtin_isnan (ld) != res_isnan)
abort ();
if (__builtin_isnanf (f) != res_isnan)
abort ();
if (__builtin_isnanl (ld) != res_isnan)
abort ();
if (__builtin_isinf (f) != res_isinf)
abort ();
if (__builtin_isinf (d) != res_isinf)
abort ();
if (__builtin_isinf (ld) != res_isinf)
abort ();
if (__builtin_isinff (f) != res_isinf)
abort ();
if (__builtin_isinfl (ld) != res_isinf)
abort ();
if (__builtin_finite (f) != res_isfin)
abort ();
if (__builtin_finite (d) != res_isfin)
abort ();
}
void __attribute__ ((__noinline__))
foo (float f, double d, long double ld,
int res_unord, int res_isnan, int res_isinf, int res_isfin)
{
foo_1 (f, d, ld, res_unord, res_isnan, res_isinf, res_isfin);
foo_1 (-f, -d, -ld, res_unord, res_isnan, res_isinf, res_isfin);
}
int main()
{
float f = __builtin_nanf("");
foo(f);
float f;
double d;
long double ld;
f = __builtin_nanf(""); d = __builtin_nan(""); ld = __builtin_nanl("");
foo(f, d, ld, /*unord=*/ 1, /*isnan=*/ 1, /*isinf=*/ 0, /*isfin=*/ 0);
f = __builtin_inff(); d = __builtin_inf(); ld = __builtin_infl();
foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 1, /*isfin=*/ 0);
f = 0; d = 0; ld = 0;
foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1);
f = __FLT_MIN__; d = __DBL_MIN__; ld = __LDBL_MIN__;
foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1);
f = __FLT_MAX__; d = __DBL_MAX__; ld = __LDBL_MAX__;
foo(f, d, ld, /*unord=*/ 0, /*isnan=*/ 0, /*isinf=*/ 0, /*isfin=*/ 1);
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment