diff options
Diffstat (limited to 'gcc/convert.c')
-rw-r--r-- | gcc/convert.c | 88 |
1 files changed, 33 insertions, 55 deletions
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)) |