diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ca88155904f..01d2a0d8b54 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,7 @@ +2009-06-18 Uros Bizjak + + * convert.c (convert_to_integer): Convert (int)logb() into ilogb(). + 2009-06-17 Olivier Hainque * collect2.c (main): Use CONST_CAST2 to perform char ** to diff --git a/gcc/convert.c b/gcc/convert.c index b6a9d3dc531..8245e1647fb 100644 --- a/gcc/convert.c +++ b/gcc/convert.c @@ -482,6 +482,37 @@ convert_to_integer (tree type, tree expr) } } + /* Convert (int)logb(d) -> ilogb(d). */ + if (optimize + && flag_unsafe_math_optimizations + && !flag_trapping_math && !flag_errno_math && flag_finite_math_only + && integer_type_node + && (outprec > TYPE_PRECISION (integer_type_node) + || (outprec == TYPE_PRECISION (integer_type_node) + && !TYPE_UNSIGNED (type)))) + { + tree s_expr = strip_float_extensions (expr); + tree s_intype = TREE_TYPE (s_expr); + const enum built_in_function fcode = builtin_mathfn_code (s_expr); + tree fn = 0; + + switch (fcode) + { + CASE_FLT_FN (BUILT_IN_LOGB): + fn = mathfn_built_in (s_intype, BUILT_IN_ILOGB); + break; + + default: + break; + } + + if (fn) + { + tree newexpr = build_call_expr (fn, 1, CALL_EXPR_ARG (s_expr, 0)); + return convert_to_integer (type, newexpr); + } + } + switch (TREE_CODE (intype)) { case POINTER_TYPE: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c16ecd04795..e0d1f6f421c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2009-06-18 Uros Bizjak + + * gcc.dg/builtins-65.c: New test. + 2009-06-18 Janus Weil PR fortran/40451 diff --git a/gcc/testsuite/gcc.dg/builtins-65.c b/gcc/testsuite/gcc.dg/builtins-65.c new file mode 100644 index 00000000000..7c6aa20bd84 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtins-65.c @@ -0,0 +1,39 @@ +/* { dg-do link } */ +/* { dg-options "-O2 -ffast-math" } */ + +extern int ilogbf (float); +extern float logbf (float); +extern int ilogb (double); +extern double logb (double); +extern int ilogbl (long double); +extern long double logbl (long double); + +extern void link_error(void); + +void testf(float x) +{ + if ((int) logbf (x) != ilogbf (x)) + link_error (); +} + +void test(double x) +{ + if ((int) logb (x) != ilogb (x)) + link_error (); +} + +void testl(long double x) +{ + if ((int) logbl (x) != ilogbl (x)) + link_error (); +} + +int main() +{ + testf (2.0f); + test (2.0); + testl (2.0l); + + return 0; +} +