diff options
author | Kaveh R. Ghazi <ghazi@caip.rutgers.edu> | 2007-07-18 17:30:38 +0000 |
---|---|---|
committer | Kaveh Ghazi <ghazi@gcc.gnu.org> | 2007-07-18 17:30:38 +0000 |
commit | 7faa1bbb5d0206cc83f20c1145f612f7754fdcf3 (patch) | |
tree | eb2db58c64bbaba8f0181d8d24ef99a386911de5 | |
parent | b5d32c25372d1e0604bbd8471d735e46215dbe03 (diff) | |
download | gcc-7faa1bbb5d0206cc83f20c1145f612f7754fdcf3.tar.gz |
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
-rw-r--r-- | gcc/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/builtins.c | 24 | ||||
-rw-r--r-- | gcc/c-cppbuiltin.c | 27 | ||||
-rw-r--r-- | gcc/real.c | 32 | ||||
-rw-r--r-- | gcc/real.h | 4 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr28796-1.c | 31 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr28796-2.c | 72 |
8 files changed, 176 insertions, 31 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 94074ff9a72..87ae99a53e5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,17 @@ 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, diff --git a/gcc/builtins.c b/gcc/builtins.c index 44cfc0d48b2..e92e56fbff7 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -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; diff --git a/gcc/c-cppbuiltin.c b/gcc/c-cppbuiltin.c index 19bb47c1410..653c5e48442 100644 --- a/gcc/c-cppbuiltin.c +++ b/gcc/c-cppbuiltin.c @@ -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); diff --git a/gcc/real.c b/gcc/real.c index b4d617f94d6..258ecf6635b 100644 --- a/gcc/real.c +++ b/gcc/real.c @@ -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); +} diff --git a/gcc/real.h b/gcc/real.h index 09b1e52fb2c..68ad362849d 100644 --- a/gcc/real.h +++ b/gcc/real.h @@ -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 */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e1a8f1ff828..1c48519a212 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +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 diff --git a/gcc/testsuite/gcc.dg/pr28796-1.c b/gcc/testsuite/gcc.dg/pr28796-1.c index a762becdafb..d200b1a682c 100644 --- a/gcc/testsuite/gcc.dg/pr28796-1.c +++ b/gcc/testsuite/gcc.dg/pr28796-1.c @@ -1,17 +1,48 @@ /* { 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; } diff --git a/gcc/testsuite/gcc.dg/pr28796-2.c b/gcc/testsuite/gcc.dg/pr28796-2.c index f76bfed35fa..25454849646 100644 --- a/gcc/testsuite/gcc.dg/pr28796-2.c +++ b/gcc/testsuite/gcc.dg/pr28796-2.c @@ -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; } |