From: Richard Sandiford Date: Sat, 7 Nov 2015 10:08:31 +0000 (+0000) Subject: Move constant bitop and bswap folds to fold-const-call.c X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=db9bd5d5752356a71b1ce6986f30c164c39cf51d;p=gcc.git Move constant bitop and bswap folds to fold-const-call.c The only folds left in builtins.c were for constants, so we can remove the builtins.c handling entirely. Tested on x86_64-linux-gnu, aarch64-linux-gnu and arm-linux-gnueabi. gcc/ * builtins.c (fold_builtin_bitop, fold_builtin_bswap): Delete. (fold_builtin_1): Don't call them. * fold-const-call.c: Include tm.h. (fold_const_call_ss): New variant for integer-to-integer folds. (fold_const_call): Call it. From-SVN: r229921 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 518c2163fbe..7b9f63ce6fe 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2015-11-07 Richard Sandiford + + * builtins.c (fold_builtin_bitop, fold_builtin_bswap): Delete. + (fold_builtin_1): Don't call them. + * fold-const-call.c: Include tm.h. + (fold_const_call_ss): New variant for integer-to-integer folds. + (fold_const_call): Call it. + 2015-11-07 Richard Sandiford * builtins.c (fold_builtin_classify): Move constant cases to... diff --git a/gcc/builtins.c b/gcc/builtins.c index 6eefd5409ca..3f7fe3b9bbc 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -148,7 +148,6 @@ static tree rewrite_call_expr (location_t, tree, int, tree, int, ...); static bool validate_arg (const_tree, enum tree_code code); static rtx expand_builtin_fabs (tree, rtx, rtx); static rtx expand_builtin_signbit (tree, rtx); -static tree fold_builtin_bitop (tree, tree); static tree fold_builtin_strchr (location_t, tree, tree, tree); static tree fold_builtin_memchr (location_t, tree, tree, tree, tree); static tree fold_builtin_memcmp (location_t, tree, tree, tree); @@ -7332,99 +7331,6 @@ fold_builtin_sincos (location_t loc, fold_build1_loc (loc, REALPART_EXPR, type, call))); } -/* Fold function call to builtin ffs, clz, ctz, popcount and parity - and their long and long long variants (i.e. ffsl and ffsll). ARG is - the argument to the call. Return NULL_TREE if no simplification can - be made. */ - -static tree -fold_builtin_bitop (tree fndecl, tree arg) -{ - if (!validate_arg (arg, INTEGER_TYPE)) - return NULL_TREE; - - /* Optimize for constant argument. */ - if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg)) - { - tree type = TREE_TYPE (arg); - int result; - - switch (DECL_FUNCTION_CODE (fndecl)) - { - CASE_INT_FN (BUILT_IN_FFS): - result = wi::ffs (arg); - break; - - CASE_INT_FN (BUILT_IN_CLZ): - if (wi::ne_p (arg, 0)) - result = wi::clz (arg); - else if (! CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result)) - result = TYPE_PRECISION (type); - break; - - CASE_INT_FN (BUILT_IN_CTZ): - if (wi::ne_p (arg, 0)) - result = wi::ctz (arg); - else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result)) - result = TYPE_PRECISION (type); - break; - - CASE_INT_FN (BUILT_IN_CLRSB): - result = wi::clrsb (arg); - break; - - CASE_INT_FN (BUILT_IN_POPCOUNT): - result = wi::popcount (arg); - break; - - CASE_INT_FN (BUILT_IN_PARITY): - result = wi::parity (arg); - break; - - default: - gcc_unreachable (); - } - - return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), result); - } - - return NULL_TREE; -} - -/* Fold function call to builtin_bswap and the short, long and long long - variants. Return NULL_TREE if no simplification can be made. */ -static tree -fold_builtin_bswap (tree fndecl, tree arg) -{ - if (! validate_arg (arg, INTEGER_TYPE)) - return NULL_TREE; - - /* Optimize constant value. */ - if (TREE_CODE (arg) == INTEGER_CST && !TREE_OVERFLOW (arg)) - { - tree type = TREE_TYPE (TREE_TYPE (fndecl)); - - switch (DECL_FUNCTION_CODE (fndecl)) - { - case BUILT_IN_BSWAP16: - case BUILT_IN_BSWAP32: - case BUILT_IN_BSWAP64: - { - signop sgn = TYPE_SIGN (type); - tree result = - wide_int_to_tree (type, - wide_int::from (arg, TYPE_PRECISION (type), - sgn).bswap ()); - return result; - } - default: - gcc_unreachable (); - } - } - - return NULL_TREE; -} - /* Fold function call to builtin memchr. ARG1, ARG2 and LEN are the arguments to the call, and TYPE is its return type. Return NULL_TREE if no simplification can be made. */ @@ -8364,19 +8270,6 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0) CASE_FLT_FN (BUILT_IN_NANS): return fold_builtin_nan (arg0, type, false); - case BUILT_IN_BSWAP16: - case BUILT_IN_BSWAP32: - case BUILT_IN_BSWAP64: - return fold_builtin_bswap (fndecl, arg0); - - CASE_INT_FN (BUILT_IN_FFS): - CASE_INT_FN (BUILT_IN_CLZ): - CASE_INT_FN (BUILT_IN_CTZ): - CASE_INT_FN (BUILT_IN_CLRSB): - CASE_INT_FN (BUILT_IN_POPCOUNT): - CASE_INT_FN (BUILT_IN_PARITY): - return fold_builtin_bitop (fndecl, arg0); - case BUILT_IN_ISASCII: return fold_builtin_isascii (loc, arg0); diff --git a/gcc/fold-const-call.c b/gcc/fold-const-call.c index c277d2b98fc..48e05a967b3 100644 --- a/gcc/fold-const-call.c +++ b/gcc/fold-const-call.c @@ -25,6 +25,7 @@ along with GCC; see the file COPYING3. If not see #include "stor-layout.h" #include "options.h" #include "fold-const-call.h" +#include "tm.h" /* For C[LT]Z_DEFINED_AT_ZERO. */ /* Functions that test for certain constant types, abstracting away the decision about whether to check for overflow. */ @@ -766,6 +767,69 @@ fold_const_call_ss (wide_int *result, built_in_function fn, } } +/* Try to evaluate: + + *RESULT = FN (ARG) + + where ARG_TYPE is the type of ARG and PRECISION is the number of bits + in the result. Return true on success. */ + +static bool +fold_const_call_ss (wide_int *result, built_in_function fn, + const wide_int_ref &arg, unsigned int precision, + tree arg_type) +{ + switch (fn) + { + CASE_INT_FN (BUILT_IN_FFS): + *result = wi::shwi (wi::ffs (arg), precision); + return true; + + CASE_INT_FN (BUILT_IN_CLZ): + { + int tmp; + if (wi::ne_p (arg, 0)) + tmp = wi::clz (arg); + else if (! CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (arg_type), tmp)) + tmp = TYPE_PRECISION (arg_type); + *result = wi::shwi (tmp, precision); + return true; + } + + CASE_INT_FN (BUILT_IN_CTZ): + { + int tmp; + if (wi::ne_p (arg, 0)) + tmp = wi::ctz (arg); + else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (arg_type), tmp)) + tmp = TYPE_PRECISION (arg_type); + *result = wi::shwi (tmp, precision); + return true; + } + + CASE_INT_FN (BUILT_IN_CLRSB): + *result = wi::shwi (wi::clrsb (arg), precision); + return true; + + CASE_INT_FN (BUILT_IN_POPCOUNT): + *result = wi::shwi (wi::popcount (arg), precision); + return true; + + CASE_INT_FN (BUILT_IN_PARITY): + *result = wi::shwi (wi::parity (arg), precision); + return true; + + case BUILT_IN_BSWAP16: + case BUILT_IN_BSWAP32: + case BUILT_IN_BSWAP64: + *result = wide_int::from (arg, precision, TYPE_SIGN (arg_type)).bswap (); + return true; + + default: + return false; + } +} + /* Try to evaluate: RESULT = FN (*ARG) @@ -916,6 +980,18 @@ fold_const_call (built_in_function fn, tree type, tree arg) machine_mode mode = TYPE_MODE (type); machine_mode arg_mode = TYPE_MODE (TREE_TYPE (arg)); + if (integer_cst_p (arg)) + { + if (SCALAR_INT_MODE_P (mode)) + { + wide_int result; + if (fold_const_call_ss (&result, fn, arg, TYPE_PRECISION (type), + TREE_TYPE (arg))) + return wide_int_to_tree (type, result); + } + return NULL_TREE; + } + if (real_cst_p (arg)) { gcc_checking_assert (SCALAR_FLOAT_MODE_P (arg_mode));