Index: convert.c =================================================================== --- convert.c (revision 121335) +++ convert.c (working copy) @@ -451,6 +451,37 @@ } } + /* Convert (int)logb(d) -> ilogb(d). */ + if (optimize + && flag_unsafe_math_optimizations + && 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 arglist = TREE_OPERAND (s_expr, 1); + tree newexpr = build_function_call_expr (fn, arglist); + return convert_to_integer (type, newexpr); + } + } + switch (TREE_CODE (intype)) { case POINTER_TYPE: Index: testsuite/gcc.dg/builtins-63.c =================================================================== --- testsuite/gcc.dg/builtins-63.c (revision 0) +++ testsuite/gcc.dg/builtins-63.c (revision 0) @@ -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; +} +