diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 04c39d42cb0..118b147fc76 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +Sat Jan 25 12:05:17 CET 2003 Jan Hubicka + + * builtins.c (fold_trunc_transparent_mathfn): New function. + (fold_builtin): Use it. + * convert.c (convert_to_real): Re-enable code to convert + math functions; add support for floor familly functions. + 2003-01-25 Zdenek Dvorak * Makefile.in (cfgloop.o, cfgloopanal.o, cfgloopmanip.o): Add diff --git a/gcc/builtins.c b/gcc/builtins.c index 851fc274437..d544410cf0c 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -157,6 +157,7 @@ static tree fold_builtin_classify_type PARAMS ((tree)); static tree fold_builtin_inf PARAMS ((tree, int)); static tree fold_builtin_nan PARAMS ((tree, tree, int)); static int validate_arglist PARAMS ((tree, ...)); +static tree fold_trunc_transparent_mathfn PARAMS ((tree)); /* Return the alignment in bits of EXP, a pointer valued expression. But don't return more than MAX_ALIGN no matter what. @@ -4423,6 +4424,36 @@ fold_builtin_nan (arglist, type, quiet) return build_real (type, real); } +/* EXP is assumed to me builtin call where truncation can be propagated + across (for instance floor((double)f) == (double)floorf (f). + Do the transformation. */ +static tree +fold_trunc_transparent_mathfn (exp) + tree exp; +{ + tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); + tree arglist = TREE_OPERAND (exp, 1); + enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); + + if (optimize && validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) + { + tree arg0 = strip_float_extensions (TREE_VALUE (arglist)); + tree ftype = TREE_TYPE (exp); + tree newtype = TREE_TYPE (arg0); + tree decl; + + if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype) + && (decl = mathfn_built_in (newtype, fcode))) + { + arglist = + build_tree_list (NULL_TREE, fold (convert (newtype, arg0))); + return convert (ftype, + build_function_call_expr (decl, arglist)); + } + } + return 0; +} + /* Used by constant folding to eliminate some builtin calls early. EXP is the CALL_EXPR of a call to a builtin function. */ @@ -4574,6 +4605,23 @@ fold_builtin (exp) case BUILT_IN_NANSL: return fold_builtin_nan (arglist, TREE_TYPE (TREE_TYPE (fndecl)), false); + case BUILT_IN_FLOOR: + case BUILT_IN_FLOORF: + case BUILT_IN_FLOORL: + case BUILT_IN_CEIL: + case BUILT_IN_CEILF: + case BUILT_IN_CEILL: + case BUILT_IN_TRUNC: + case BUILT_IN_TRUNCF: + case BUILT_IN_TRUNCL: + case BUILT_IN_ROUND: + case BUILT_IN_ROUNDF: + case BUILT_IN_ROUNDL: + case BUILT_IN_NEARBYINT: + case BUILT_IN_NEARBYINTF: + case BUILT_IN_NEARBYINTL: + return fold_trunc_transparent_mathfn (exp); + default: break; } diff --git a/gcc/convert.c b/gcc/convert.c index ae7b2c37bf4..73db933b97e 100644 --- a/gcc/convert.c +++ b/gcc/convert.c @@ -127,13 +127,11 @@ tree convert_to_real (type, expr) tree type, expr; { + enum built_in_function fcode = builtin_mathfn_code (expr); tree itype = TREE_TYPE (expr); /* Disable until we figure out how to decide whether the functions are present in runtime. */ -#if 0 - enum built_in_function fcode = builtin_mathfn_code (expr); - /* Convert (float)sqrt((double)x) where x is float into sqrtf(x) */ if ((fcode == BUILT_IN_SQRT || fcode == BUILT_IN_SQRTL @@ -155,72 +153,52 @@ convert_to_real (type, expr) if (TYPE_PRECISION (TREE_TYPE (arg0)) > TYPE_PRECISION (type)) newtype = TREE_TYPE (arg0); - /* Be careful about integer to fp conversions. + /* Be curefull about integer to fp conversions. These may overflow still. */ if (FLOAT_TYPE_P (TREE_TYPE (arg0)) - && TYPE_PRECISION (newtype) <= TYPE_PRECISION (itype) + && TYPE_PRECISION (newtype) < TYPE_PRECISION (itype) && (TYPE_MODE (newtype) == TYPE_MODE (double_type_node) || TYPE_MODE (newtype) == TYPE_MODE (float_type_node))) { tree arglist; - if (TYPE_MODE (type) == TYPE_MODE (float_type_node)) - switch (fcode) - { - case BUILT_IN_SQRT: - case BUILT_IN_SQRTL: - fcode = BUILT_IN_SQRTF; - break; - case BUILT_IN_SIN: - case BUILT_IN_SINL: - fcode = BUILT_IN_SINF; - break; - case BUILT_IN_COS: - case BUILT_IN_COSL: - fcode = BUILT_IN_COSF; - break; - case BUILT_IN_EXP: - case BUILT_IN_EXPL: - fcode = BUILT_IN_EXPF; - break; - default: - abort (); - } - else - switch (fcode) - { - case BUILT_IN_SQRT: - case BUILT_IN_SQRTL: - fcode = BUILT_IN_SQRT; - break; - case BUILT_IN_SIN: - case BUILT_IN_SINL: - fcode = BUILT_IN_SIN; - break; - case BUILT_IN_COS: - case BUILT_IN_COSL: - fcode = BUILT_IN_COS; - break; - case BUILT_IN_EXP: - case BUILT_IN_EXPL: - fcode = BUILT_IN_EXP; - break; - default: - abort (); - } + tree fn = mathfn_built_in (newtype, fcode); - /* ??? Fortran frontend does not initialize built_in_decls. - For some reason creating the decl using builtin_function does not - work as it should. */ - if (built_in_decls [fcode]) + if (fn) { arglist = build_tree_list (NULL_TREE, fold (convert_to_real (newtype, arg0))); - expr = build_function_call_expr (built_in_decls [fcode], arglist); + expr = build_function_call_expr (fn, arglist); if (newtype == type) return expr; } } } -#endif + if (optimize + && (((fcode == BUILT_IN_FLOORL + || fcode == BUILT_IN_CEILL + || fcode == BUILT_IN_ROUND + || fcode == BUILT_IN_TRUNC + || fcode == BUILT_IN_NEARBYINT) + && (TYPE_MODE (type) == TYPE_MODE (double_type_node) + || TYPE_MODE (type) == TYPE_MODE (float_type_node))) + || ((fcode == BUILT_IN_FLOOR + || fcode == BUILT_IN_CEIL + || fcode == BUILT_IN_ROUND + || fcode == BUILT_IN_TRUNC + || fcode == BUILT_IN_NEARBYINT) + && (TYPE_MODE (type) == TYPE_MODE (float_type_node))))) + { + tree fn = mathfn_built_in (type, fcode); + + if (fn) + { + tree arg0 = strip_float_extensions (TREE_VALUE (TREE_OPERAND (expr, + 1))); + tree arglist = build_tree_list (NULL_TREE, + fold (convert_to_real (type, arg0))); + + return build_function_call_expr (fn, arglist); + } + } /* Propagate the cast into the operation. */ if (itype != type && FLOAT_TYPE_P (type))