diff options
author | Roger Sayle <roger@eyesopen.com> | 2006-07-25 23:21:56 +0000 |
---|---|---|
committer | Roger Sayle <sayle@gcc.gnu.org> | 2006-07-25 23:21:56 +0000 |
commit | 738764ef1e4321a6e385b30cf52f8ae1d9eb43b1 (patch) | |
tree | fe2cca2c97ebff50cdce92939507476d43dba1e2 | |
parent | cdc30c457970d9876af28cdfe7e3a90d590e55ae (diff) | |
download | gcc-738764ef1e4321a6e385b30cf52f8ae1d9eb43b1.tar.gz |
re PR middle-end/28473 (with -O, casting result of round(x) to uint64_t produces wrong values for x > INT_MAX)
PR middle-end/28473
* convert.c (convert_to_integer): When transforming (T)foo(x) into
bar(x) check that bar's result type can represent all the values of T.
* gcc.dg/fold-convround-1.c: New test case.
From-SVN: r115742
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/convert.c | 38 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/fold-convround-1.c | 30 |
4 files changed, 66 insertions, 13 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 80caad9edde..0ec948f9b2a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2006-07-25 Roger Sayle <roger@eyesopen.com> + + PR middle-end/28473 + * convert.c (convert_to_integer): When transforming (T)foo(x) into + bar(x) check that bar's result type can represent all the values of T. + 2006-07-25 Zdenek Dvorak <dvorakz@suse.cz> * tree-chrec.c (chrec_convert_aggressive): Return NULL on failure. diff --git a/gcc/convert.c b/gcc/convert.c index ab780d8ebd3..27571956a1e 100644 --- a/gcc/convert.c +++ b/gcc/convert.c @@ -388,27 +388,36 @@ convert_to_integer (tree type, tree expr) /* Only convert in ISO C99 mode. */ if (!TARGET_C99_FUNCTIONS) break; - if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (long_long_integer_type_node)) - fn = mathfn_built_in (s_intype, BUILT_IN_LLCEIL); - else + if (outprec < TYPE_PRECISION (long_integer_type_node) + || (outprec == TYPE_PRECISION (long_integer_type_node) + && !TYPE_UNSIGNED (type))) fn = mathfn_built_in (s_intype, BUILT_IN_LCEIL); + else if (outprec == TYPE_PRECISION (long_long_integer_type_node) + && !TYPE_UNSIGNED (type)) + fn = mathfn_built_in (s_intype, BUILT_IN_LLCEIL); break; CASE_FLT_FN (BUILT_IN_FLOOR): /* Only convert in ISO C99 mode. */ if (!TARGET_C99_FUNCTIONS) break; - if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (long_long_integer_type_node)) - fn = mathfn_built_in (s_intype, BUILT_IN_LLFLOOR); - else + if (outprec < TYPE_PRECISION (long_integer_type_node) + || (outprec == TYPE_PRECISION (long_integer_type_node) + && !TYPE_UNSIGNED (type))) fn = mathfn_built_in (s_intype, BUILT_IN_LFLOOR); + else if (outprec == TYPE_PRECISION (long_long_integer_type_node) + && !TYPE_UNSIGNED (type)) + fn = mathfn_built_in (s_intype, BUILT_IN_LLFLOOR); break; CASE_FLT_FN (BUILT_IN_ROUND): - if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (long_long_integer_type_node)) - fn = mathfn_built_in (s_intype, BUILT_IN_LLROUND); - else + if (outprec < TYPE_PRECISION (long_integer_type_node) + || (outprec == TYPE_PRECISION (long_integer_type_node) + && !TYPE_UNSIGNED (type))) fn = mathfn_built_in (s_intype, BUILT_IN_LROUND); + else if (outprec == TYPE_PRECISION (long_long_integer_type_node) + && !TYPE_UNSIGNED (type)) + fn = mathfn_built_in (s_intype, BUILT_IN_LLROUND); break; CASE_FLT_FN (BUILT_IN_RINT): @@ -417,10 +426,13 @@ convert_to_integer (tree type, tree expr) break; /* ... Fall through ... */ CASE_FLT_FN (BUILT_IN_NEARBYINT): - if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (long_long_integer_type_node)) - fn = mathfn_built_in (s_intype, BUILT_IN_LLRINT); - else - fn = mathfn_built_in (s_intype, BUILT_IN_LRINT); + if (outprec < TYPE_PRECISION (long_integer_type_node) + || (outprec == TYPE_PRECISION (long_integer_type_node) + && !TYPE_UNSIGNED (type))) + fn = mathfn_built_in (s_intype, BUILT_IN_LRINT); + else if (outprec == TYPE_PRECISION (long_long_integer_type_node) + && !TYPE_UNSIGNED (type)) + fn = mathfn_built_in (s_intype, BUILT_IN_LLRINT); break; CASE_FLT_FN (BUILT_IN_TRUNC): diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 00fd5b8e53b..63aadaf8e28 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2006-07-25 Roger Sayle <roger@eyesopen.com> + + PR middle-end/28473 + * gcc.dg/fold-convround-1.c: New test case. + 2006-07-24 Steven G. Kargl <kargls@comcast.net> * gfortran.dg/arithmetic_if.f90: Fix comments. diff --git a/gcc/testsuite/gcc.dg/fold-convround-1.c b/gcc/testsuite/gcc.dg/fold-convround-1.c new file mode 100644 index 00000000000..86612aa81b3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/fold-convround-1.c @@ -0,0 +1,30 @@ +/* PR middle-end/28473. */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-original" } */ + +extern double round(double); +extern double floor(double); +extern double ceil(double); + +unsigned long long test1(double x) +{ + return (unsigned long long) round(x); +} + +unsigned long long test2(double x) +{ + return (unsigned long long) floor(x); +} +unsigned long long test3(double x) +{ + return (unsigned long long) ceil(x); +} + +/* { dg-final { scan-tree-dump-times "__builtin_lround" 0 "original" } } */ +/* { dg-final { scan-tree-dump-times "__builtin_llround" 0 "original" } } */ +/* { dg-final { scan-tree-dump-times "__builtin_lfloor" 0 "original" } } */ +/* { dg-final { scan-tree-dump-times "__builtin_llfloor" 0 "original" } } */ +/* { dg-final { scan-tree-dump-times "__builtin_lceil" 0 "original" } } */ +/* { dg-final { scan-tree-dump-times "__builtin_llceil" 0 "original" } } */ +/* { dg-final { cleanup-tree-dump "original" } } */ + |