From d8b42d069ef1e97ebba1c7d3730ff3673199d856 Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Sat, 9 Apr 2005 07:31:46 +0200 Subject: [PATCH] * builtins.def (BUILT_IN_LFLOOR, BUILT_IN_LFLOORF, BUILT_IN_LFLOORL) (BUILT_IN_LLFLOOR, BUILT_IN_LLFLOORF, BUILT_IN_LLFLOORL): New. * optabs.h (enum optab_index): Add new OTI_lfloor. (lfloor_optab): Define corresponding macro. * optabs.c (init_optabs): Initialize lfloor_optab. * genopinit.c (optabs): Implement lfloor_optab using lfloorsi2 and lfloordi2 patterns. * builtins.c (expand_builtin_int_roundingfn): New prototype. (expand_builtin_int_roundingfn): New function. (fold_builtin_int_roundingfn): New prototype. (fold_builtin_int_roundingfn): New function, renamed from fold_builtin_lround. Handle BUILT_IN_LROUND{,F,L}, BUILT_IN_LLROUND{,F,L} and BUILT_IN_LFLOOR{,F,L}, BUILT_IN_LLFLOOR{,F,L}. (fold_builtin_1): Fold BUILT_IN_LFLOOR{,F,L} and BUILT_IN_LLFLOOR{,F,L} using fold_builtin_int_roundingfn. (mathfn_built_in): Handle BUILT_IN LFLOOR and BUILT_IN_LLFLOOR. (expand_builtin): Expand BUILT_IN_LFLOOR{,F,L} and BUILT_IN_LLFLOOR{,F,L} using expand_builtin_int_roundingfn. * convert.c (convert_to_integer): Convert (long int)floor{,f,l}, into lfloor built-in function and (long long int)floor{,f,l} into llfloor built-in function. * fold-const.c (tree_expr_nonnegative_p): Add BUILT_IN_LFLOOR and BUILT_IN_LLFLOOR. testsuite: * gcc.dg/builtins-53.c: New test. From-SVN: r97886 --- gcc/ChangeLog | 29 +++++- gcc/builtins.c | 148 ++++++++++++++++++++++++++++- gcc/builtins.def | 6 ++ gcc/convert.c | 7 ++ gcc/fold-const.c | 2 + gcc/genopinit.c | 1 + gcc/optabs.c | 1 + gcc/optabs.h | 2 + gcc/testsuite/ChangeLog | 4 + gcc/testsuite/gcc.dg/builtins-53.c | 45 +++++++++ 10 files changed, 239 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/builtins-53.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b2324c6906e..adeed7feb9f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,30 @@ +2005-04-09 Uros Bizjak + + * builtins.def (BUILT_IN_LFLOOR, BUILT_IN_LFLOORF, BUILT_IN_LFLOORL) + (BUILT_IN_LLFLOOR, BUILT_IN_LLFLOORF, BUILT_IN_LLFLOORL): New. + * optabs.h (enum optab_index): Add new OTI_lfloor. + (lfloor_optab): Define corresponding macro. + * optabs.c (init_optabs): Initialize lfloor_optab. + * genopinit.c (optabs): Implement lfloor_optab using lfloorsi2 + and lfloordi2 patterns. + * builtins.c (expand_builtin_int_roundingfn): New prototype. + (expand_builtin_int_roundingfn): New function. + (fold_builtin_int_roundingfn): New prototype. + (fold_builtin_int_roundingfn): New function, renamed from + fold_builtin_lround. + Handle BUILT_IN_LROUND{,F,L}, BUILT_IN_LLROUND{,F,L} and + BUILT_IN_LFLOOR{,F,L}, BUILT_IN_LLFLOOR{,F,L}. + (fold_builtin_1): Fold BUILT_IN_LFLOOR{,F,L} and + BUILT_IN_LLFLOOR{,F,L} using fold_builtin_int_roundingfn. + (mathfn_built_in): Handle BUILT_IN LFLOOR and BUILT_IN_LLFLOOR. + (expand_builtin): Expand BUILT_IN_LFLOOR{,F,L} and + BUILT_IN_LLFLOOR{,F,L} using expand_builtin_int_roundingfn. + * convert.c (convert_to_integer): Convert (long int)floor{,f,l}, + into lfloor built-in function and (long long int)floor{,f,l} into + llfloor built-in function. + * fold-const.c (tree_expr_nonnegative_p): Add BUILT_IN_LFLOOR and + BUILT_IN_LLFLOOR. + 2005-04-08 Ian Lance Taylor * c-common.def: Move FOR_STMT, WHILE_STMT, DO_STMT, BREAK_STMT, @@ -987,7 +1014,7 @@ * tree-chrec.c (chrec_convert): Return chrec_dont_know for constants that don't fit in their type after conversion. -2005-04-05 Uros Bizjak +2005-04-05 Uros Bizjak PR target/20421 * config/i386/i386.md (frndintxf2_floor, frndintxf2_ceil) diff --git a/gcc/builtins.c b/gcc/builtins.c index 56bdc873df3..034934cd153 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -98,6 +98,7 @@ static void expand_errno_check (tree, rtx); static rtx expand_builtin_mathfn (tree, rtx, rtx); static rtx expand_builtin_mathfn_2 (tree, rtx, rtx); static rtx expand_builtin_mathfn_3 (tree, rtx, rtx); +static rtx expand_builtin_int_roundingfn (tree, rtx, rtx); static rtx expand_builtin_args_info (tree); static rtx expand_builtin_next_arg (void); static rtx expand_builtin_va_start (tree); @@ -161,6 +162,7 @@ static tree fold_builtin_trunc (tree, tree); static tree fold_builtin_floor (tree, tree); static tree fold_builtin_ceil (tree, tree); static tree fold_builtin_round (tree, tree); +static tree fold_builtin_int_roundingfn (tree, tree); static tree fold_builtin_bitop (tree, tree); static tree fold_builtin_memcpy (tree, tree); static tree fold_builtin_mempcpy (tree, tree, int); @@ -1548,7 +1550,9 @@ mathfn_built_in (tree type, enum built_in_function fn) CASE_MATHFN (BUILT_IN_J1) CASE_MATHFN (BUILT_IN_JN) CASE_MATHFN (BUILT_IN_LDEXP) + CASE_MATHFN (BUILT_IN_LFLOOR) CASE_MATHFN (BUILT_IN_LGAMMA) + CASE_MATHFN (BUILT_IN_LLFLOOR) CASE_MATHFN (BUILT_IN_LLRINT) CASE_MATHFN (BUILT_IN_LLROUND) CASE_MATHFN (BUILT_IN_LOG) @@ -2112,6 +2116,100 @@ expand_builtin_mathfn_3 (tree exp, rtx target, rtx subtarget) return target; } +/* Expand a call to one of the builtin rounding functions (lfloor). + If expanding via optab fails, lower expression to (int)(floor(x)). + EXP is the expression that is a call to the builtin function; + if convenient, the result should be placed in TARGET. SUBTARGET may + be used as the target for computing one of EXP's operands. */ + +static rtx +expand_builtin_int_roundingfn (tree exp, rtx target, rtx subtarget) +{ + optab builtin_optab; + rtx op0, insns, tmp; + tree fndecl = get_callee_fndecl (exp); + tree arglist = TREE_OPERAND (exp, 1); + enum built_in_function fallback_fn; + tree fallback_fndecl; + enum machine_mode mode; + tree arg, narg; + + if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE)) + gcc_unreachable (); + + arg = TREE_VALUE (arglist); + + switch (DECL_FUNCTION_CODE (fndecl)) + { + case BUILT_IN_LFLOOR: + case BUILT_IN_LFLOORF: + case BUILT_IN_LFLOORL: + case BUILT_IN_LLFLOOR: + case BUILT_IN_LLFLOORF: + case BUILT_IN_LLFLOORL: + builtin_optab = lfloor_optab; + fallback_fn = BUILT_IN_FLOOR; + break; + + default: + gcc_unreachable (); + } + + /* Make a suitable register to place result in. */ + mode = TYPE_MODE (TREE_TYPE (exp)); + + /* Before working hard, check whether the instruction is available. */ + if (builtin_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing) + { + target = gen_reg_rtx (mode); + + /* Wrap the computation of the argument in a SAVE_EXPR, as we may + need to expand the argument again. This way, we will not perform + side-effects more the once. */ + narg = builtin_save_expr (arg); + if (narg != arg) + { + arg = narg; + arglist = build_tree_list (NULL_TREE, arg); + exp = build_function_call_expr (fndecl, arglist); + } + + op0 = expand_expr (arg, subtarget, VOIDmode, 0); + + start_sequence (); + + /* Compute into TARGET. + Set TARGET to wherever the result comes back. */ + target = expand_unop (mode, builtin_optab, op0, target, 0); + + if (target != 0) + { + /* Output the entire sequence. */ + insns = get_insns (); + end_sequence (); + emit_insn (insns); + return target; + } + + /* If we were unable to expand via the builtin, stop the sequence + (without outputting the insns). */ + end_sequence (); + } + + /* Fall back to floating point rounding optab. */ + fallback_fndecl = mathfn_built_in (TREE_TYPE (arg), fallback_fn); + exp = build_function_call_expr (fallback_fndecl, arglist); + + tmp = expand_builtin_mathfn (exp, NULL_RTX, NULL_RTX); + + /* Truncate the result of floating point optab to integer + via expand_fix (). */ + target = gen_reg_rtx (mode); + expand_fix (target, tmp, 0); + + return target; +} + /* To evaluate powi(x,n), the floating point value x raised to the constant integer exponent n, we use a hybrid algorithm that combines the "window method" with look-up tables. For an @@ -5278,6 +5376,17 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, return target; break; + case BUILT_IN_LFLOOR: + case BUILT_IN_LFLOORF: + case BUILT_IN_LFLOORL: + case BUILT_IN_LLFLOOR: + case BUILT_IN_LLFLOORF: + case BUILT_IN_LLFLOORL: + target = expand_builtin_int_roundingfn (exp, target, subtarget); + if (target) + return target; + break; + case BUILT_IN_POW: case BUILT_IN_POWF: case BUILT_IN_POWL: @@ -6627,11 +6736,11 @@ fold_builtin_round (tree fndecl, tree arglist) } /* Fold function call to builtin lround, lroundf or lroundl (or the - corresponding long long versions). Return NULL_TREE if no - simplification can be made. */ + corresponding long long versions) and other rounding functions. + Return NULL_TREE if no simplification can be made. */ static tree -fold_builtin_lround (tree fndecl, tree arglist) +fold_builtin_int_roundingfn (tree fndecl, tree arglist) { tree arg; @@ -6651,7 +6760,30 @@ fold_builtin_lround (tree fndecl, tree arglist) HOST_WIDE_INT hi, lo; REAL_VALUE_TYPE r; - real_round (&r, TYPE_MODE (ftype), &x); + switch (DECL_FUNCTION_CODE (fndecl)) + { + case BUILT_IN_LFLOOR: + case BUILT_IN_LFLOORF: + case BUILT_IN_LFLOORL: + case BUILT_IN_LLFLOOR: + case BUILT_IN_LLFLOORF: + case BUILT_IN_LLFLOORL: + real_floor (&r, TYPE_MODE (ftype), &x); + break; + + case BUILT_IN_LROUND: + case BUILT_IN_LROUNDF: + case BUILT_IN_LROUNDL: + case BUILT_IN_LLROUND: + case BUILT_IN_LLROUNDF: + case BUILT_IN_LLROUNDL: + real_round (&r, TYPE_MODE (ftype), &x); + break; + + default: + gcc_unreachable (); + } + REAL_VALUE_TO_INT (&lo, &hi, r); result = build_int_cst_wide (NULL_TREE, lo, hi); if (int_fits_type_p (result, itype)) @@ -8196,13 +8328,19 @@ fold_builtin_1 (tree fndecl, tree arglist, bool ignore) case BUILT_IN_RINTL: return fold_trunc_transparent_mathfn (fndecl, arglist); + case BUILT_IN_LFLOOR: + case BUILT_IN_LFLOORF: + case BUILT_IN_LFLOORL: + case BUILT_IN_LLFLOOR: + case BUILT_IN_LLFLOORF: + case BUILT_IN_LLFLOORL: case BUILT_IN_LROUND: case BUILT_IN_LROUNDF: case BUILT_IN_LROUNDL: case BUILT_IN_LLROUND: case BUILT_IN_LLROUNDF: case BUILT_IN_LLROUNDL: - return fold_builtin_lround (fndecl, arglist); + return fold_builtin_int_roundingfn (fndecl, arglist); case BUILT_IN_LRINT: case BUILT_IN_LRINTF: diff --git a/gcc/builtins.def b/gcc/builtins.def index c7cfb083ec4..36a644c82d3 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -260,9 +260,15 @@ DEF_EXT_LIB_BUILTIN (BUILT_IN_JNL, "jnl", BT_FN_LONGDOUBLE_INT_LONGDOUBLE, AT DEF_LIB_BUILTIN (BUILT_IN_LDEXP, "ldexp", BT_FN_DOUBLE_DOUBLE_INT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_C90RES_BUILTIN (BUILT_IN_LDEXPF, "ldexpf", BT_FN_FLOAT_FLOAT_INT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_C90RES_BUILTIN (BUILT_IN_LDEXPL, "ldexpl", BT_FN_LONGDOUBLE_LONGDOUBLE_INT, ATTR_MATHFN_FPROUNDING_ERRNO) +DEF_GCC_BUILTIN (BUILT_IN_LFLOOR, "lfloor", BT_FN_LONG_DOUBLE, ATTR_MATHFN_FPROUNDING) +DEF_GCC_BUILTIN (BUILT_IN_LFLOORF, "lfloorf", BT_FN_LONG_FLOAT, ATTR_MATHFN_FPROUNDING) +DEF_GCC_BUILTIN (BUILT_IN_LFLOORL, "lfloorl", BT_FN_LONG_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) DEF_C99_BUILTIN (BUILT_IN_LGAMMA, "lgamma", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_LGAMMAF, "lgammaf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_LGAMMAL, "lgammal", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) +DEF_GCC_BUILTIN (BUILT_IN_LLFLOOR, "llfloor", BT_FN_LONGLONG_DOUBLE, ATTR_MATHFN_FPROUNDING) +DEF_GCC_BUILTIN (BUILT_IN_LLFLOORF, "llfloorf", BT_FN_LONGLONG_FLOAT, ATTR_MATHFN_FPROUNDING) +DEF_GCC_BUILTIN (BUILT_IN_LLFLOORL, "llfloorl", BT_FN_LONGLONG_LONGDOUBLE, ATTR_MATHFN_FPROUNDING) DEF_C99_BUILTIN (BUILT_IN_LLRINT, "llrint", BT_FN_LONGLONG_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_LLRINTF, "llrintf", BT_FN_LONGLONG_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_LLRINTL, "llrintl", BT_FN_LONGLONG_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) diff --git a/gcc/convert.c b/gcc/convert.c index f900ace21e4..79aef2140cf 100644 --- a/gcc/convert.c +++ b/gcc/convert.c @@ -349,6 +349,13 @@ convert_to_integer (tree type, tree expr) switch (fcode) { + case BUILT_IN_FLOOR: case BUILT_IN_FLOORF: case BUILT_IN_FLOORL: + if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (long_long_integer_type_node)) + fn = mathfn_built_in (s_intype, BUILT_IN_LLFLOOR); + else + fn = mathfn_built_in (s_intype, BUILT_IN_LFLOOR); + break; + case BUILT_IN_ROUND: case BUILT_IN_ROUNDF: case BUILT_IN_ROUNDL: if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (long_long_integer_type_node)) fn = mathfn_built_in (s_intype, BUILT_IN_LLROUND); diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 6a84630bb60..4d7ee93b40e 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -10619,6 +10619,8 @@ tree_expr_nonnegative_p (tree t) CASE_BUILTIN_F (BUILT_IN_FLOOR) CASE_BUILTIN_F (BUILT_IN_FMOD) CASE_BUILTIN_F (BUILT_IN_LDEXP) + CASE_BUILTIN_F (BUILT_IN_LFLOOR) + CASE_BUILTIN_F (BUILT_IN_LLFLOOR) CASE_BUILTIN_F (BUILT_IN_LLRINT) CASE_BUILTIN_F (BUILT_IN_LLROUND) CASE_BUILTIN_F (BUILT_IN_LRINT) diff --git a/gcc/genopinit.c b/gcc/genopinit.c index 92b1c207544..42a525f8ceb 100644 --- a/gcc/genopinit.c +++ b/gcc/genopinit.c @@ -119,6 +119,7 @@ static const char * const optabs[] = "copysign_optab->handlers[$A].insn_code = CODE_FOR_$(copysign$F$a3$)", "sqrt_optab->handlers[$A].insn_code = CODE_FOR_$(sqrt$a2$)", "floor_optab->handlers[$A].insn_code = CODE_FOR_$(floor$a2$)", + "lfloor_optab->handlers[$A].insn_code = CODE_FOR_$(lfloor$a2$)", "ceil_optab->handlers[$A].insn_code = CODE_FOR_$(ceil$a2$)", "round_optab->handlers[$A].insn_code = CODE_FOR_$(round$a2$)", "btrunc_optab->handlers[$A].insn_code = CODE_FOR_$(btrunc$a2$)", diff --git a/gcc/optabs.c b/gcc/optabs.c index ecaff987e04..d67274427ae 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -5033,6 +5033,7 @@ init_optabs (void) parity_optab = init_optab (PARITY); sqrt_optab = init_optab (SQRT); floor_optab = init_optab (UNKNOWN); + lfloor_optab = init_optab (UNKNOWN); ceil_optab = init_optab (UNKNOWN); round_optab = init_optab (UNKNOWN); btrunc_optab = init_optab (UNKNOWN); diff --git a/gcc/optabs.h b/gcc/optabs.h index 53958fcd7b6..a1c2d37c3ba 100644 --- a/gcc/optabs.h +++ b/gcc/optabs.h @@ -186,6 +186,7 @@ enum optab_index OTI_log1p, /* Rounding functions */ OTI_floor, + OTI_lfloor, OTI_ceil, OTI_btrunc, OTI_round, @@ -313,6 +314,7 @@ extern GTY(()) optab optab_table[OTI_MAX]; #define log2_optab (optab_table[OTI_log2]) #define log1p_optab (optab_table[OTI_log1p]) #define floor_optab (optab_table[OTI_floor]) +#define lfloor_optab (optab_table[OTI_lfloor]) #define ceil_optab (optab_table[OTI_ceil]) #define btrunc_optab (optab_table[OTI_btrunc]) #define round_optab (optab_table[OTI_round]) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f6f8cefcdaf..14258a19ec0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2005-04-09 Uros Bizjak + + * gcc.dg/builtins-53.c: New test. + 2005-04-08 Diego Novillo * g++.dg/tree-ssa/pr18178.C: New test. diff --git a/gcc/testsuite/gcc.dg/builtins-53.c b/gcc/testsuite/gcc.dg/builtins-53.c new file mode 100644 index 00000000000..6b1a6f8cb9d --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtins-53.c @@ -0,0 +1,45 @@ +/* Copyright (C) 2005 Free Software Foundation. + + Check that (long)floor, (long)floorf, (long)floorl, + (long long)floor, (long long)floorf and (long long)floorl + built-in functions compile. + + Written by Uros Bizjak, 5th April 2005. */ + +/* { dg-do compile } */ +/* { dg-options "-O2 -ffast-math" } */ + +extern double floor(double); +extern float floorf(float); +extern long double floorl(long double); + + +long int test1(double x) +{ + return floor(x); +} + +long long int test2(double x) +{ + return floor(x); +} + +long int test1f(float x) +{ + return floorf(x); +} + +long long int test2f(float x) +{ + return floorf(x); +} + +long int test1l(long double x) +{ + return floorl(x); +} + +long long int test2l(long double x) +{ + return floorl(x); +} -- 2.30.2