diff options
author | Richard Sandiford <richard.sandiford@arm.com> | 2015-11-07 10:10:44 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2015-11-07 10:10:44 +0000 |
commit | df838ef0f1a11355a217ab11ed8546dd97873870 (patch) | |
tree | 0a6fba6186ee90f2710a360da3bcb509e1e7f047 /gcc/fold-const-call.c | |
parent | db9bd5d5752356a71b1ce6986f30c164c39cf51d (diff) |
Move const char * -> int/fp folds to fold-const-call.c
This patch moves folds that deal with constant string arguments and
return a constant integer or floating-point value. For example, it
handles strcmp ("foo", "bar") but not strstr ("foobar", "bar"),
which wouldn't currently be accepted by the gimple folders.
The builtins.c folding for strlen (via c_strlen) is a bit more general
than what the fold-const-call.c code does (and more general than we need
for the gimple folders). I've therefore left it as-is, even though it
partially duplicates the new code.
Tested on x86_64-linux-gnu, aarch64-linux-gnu and arm-linux-gnueabi.
gcc/
* builtins.c (fold_builtin_nan): Delete.
(fold_builtin_memcmp): Remove case where both arguments are constant.
(fold_builtin_strcmp, fold_builtin_strncmp): Likewise.
(fold_builtin_strspn, fold_builtin_strcspn): Likewise.
(fold_builtin_1): Remove BUILT_IN_NAN* handling.
* fold-const-call.c: Include fold-const.h.
(host_size_t_cst_p): New function.
(build_cmp_result, fold_const_builtin_nan): Likewise.
(fold_const_call_1): New function, split out from...
(fold_const_call): ...here (for all three interfaces). Handle
constant nan, nans, strlen, strcmp, strncmp, strspn and strcspn.
From-SVN: r229922
Diffstat (limited to 'gcc/fold-const-call.c')
-rw-r--r-- | gcc/fold-const-call.c | 155 |
1 files changed, 142 insertions, 13 deletions
diff --git a/gcc/fold-const-call.c b/gcc/fold-const-call.c index 48e05a967b3..49793a5ab6f 100644 --- a/gcc/fold-const-call.c +++ b/gcc/fold-const-call.c @@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "stor-layout.h" #include "options.h" +#include "fold-const.h" #include "fold-const-call.h" #include "tm.h" /* For C[LT]Z_DEFINED_AT_ZERO. */ @@ -48,6 +49,31 @@ complex_cst_p (tree t) return TREE_CODE (t) == COMPLEX_CST; } +/* Return true if ARG is a constant in the range of the host size_t. + Store it in *SIZE_OUT if so. */ + +static inline bool +host_size_t_cst_p (tree t, size_t *size_out) +{ + if (integer_cst_p (t) + && wi::min_precision (t, UNSIGNED) <= sizeof (size_t) * CHAR_BIT) + { + *size_out = tree_to_uhwi (t); + return true; + } + return false; +} + +/* RES is the result of a comparison in which < 0 means "less", 0 means + "equal" and > 0 means "more". Canonicalize it to -1, 0 or 1 and + return it in type TYPE. */ + +static inline tree +build_cmp_result (tree type, int res) +{ + return build_int_cst (type, res < 0 ? -1 : res > 0 ? 1 : 0); +} + /* M is the result of trying to constant-fold an expression (starting with clear MPFR flags) and INEXACT says whether the result in M is exact or inexact. Return true if M can be used as a constant-folded @@ -527,6 +553,20 @@ fold_const_builtin_load_exponent (real_value *result, const real_value *arg0, return real_equal (&initial_result, result); } +/* Fold a call to __builtin_nan or __builtin_nans with argument ARG and + return type TYPE. QUIET is true if a quiet rather than signalling + NaN is required. */ + +static tree +fold_const_builtin_nan (tree type, tree arg, bool quiet) +{ + REAL_VALUE_TYPE real; + const char *str = c_getstr (arg); + if (str && real_nan (&real, str, quiet, TYPE_MODE (type))) + return build_real (type, real); + return NULL_TREE; +} + /* Try to evaluate: *RESULT = FN (*ARG) @@ -971,11 +1011,11 @@ fold_const_call_cc (real_value *result_real, real_value *result_imag, } } -/* Try to fold FN (ARG) to a constant. Return the constant on success, - otherwise return null. TYPE is the type of the return value. */ +/* Subroutine of fold_const_call, with the same interface. Handle cases + where the arguments and result are numerical. */ -tree -fold_const_call (built_in_function fn, tree type, tree arg) +static tree +fold_const_call_1 (built_in_function fn, tree type, tree arg) { machine_mode mode = TYPE_MODE (type); machine_mode arg_mode = TYPE_MODE (TREE_TYPE (arg)); @@ -1066,6 +1106,33 @@ fold_const_call (built_in_function fn, tree type, tree arg) return NULL_TREE; } +/* Try to fold FN (ARG) to a constant. Return the constant on success, + otherwise return null. TYPE is the type of the return value. */ + +tree +fold_const_call (built_in_function fn, tree type, tree arg) +{ + switch (fn) + { + case BUILT_IN_STRLEN: + if (const char *str = c_getstr (arg)) + return build_int_cst (type, strlen (str)); + return NULL_TREE; + + CASE_FLT_FN (BUILT_IN_NAN): + case BUILT_IN_NAND32: + case BUILT_IN_NAND64: + case BUILT_IN_NAND128: + return fold_const_builtin_nan (type, arg, true); + + CASE_FLT_FN (BUILT_IN_NANS): + return fold_const_builtin_nan (type, arg, false); + + default: + return fold_const_call_1 (fn, type, arg); + } +} + /* Try to evaluate: *RESULT = FN (*ARG0, *ARG1) @@ -1194,11 +1261,11 @@ fold_const_call_ccc (real_value *result_real, real_value *result_imag, } } -/* Try to fold FN (ARG0, ARG1) to a constant. Return the constant on success, - otherwise return null. TYPE is the type of the return value. */ +/* Subroutine of fold_const_call, with the same interface. Handle cases + where the arguments and result are numerical. */ -tree -fold_const_call (built_in_function fn, tree type, tree arg0, tree arg1) +static tree +fold_const_call_1 (built_in_function fn, tree type, tree arg0, tree arg1) { machine_mode mode = TYPE_MODE (type); machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0)); @@ -1286,6 +1353,35 @@ fold_const_call (built_in_function fn, tree type, tree arg0, tree arg1) return NULL_TREE; } +/* Try to fold FN (ARG0, ARG1) to a constant. Return the constant on success, + otherwise return null. TYPE is the type of the return value. */ + +tree +fold_const_call (built_in_function fn, tree type, tree arg0, tree arg1) +{ + const char *p0, *p1; + switch (fn) + { + case BUILT_IN_STRSPN: + if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1))) + return build_int_cst (type, strspn (p0, p1)); + return NULL_TREE; + + case BUILT_IN_STRCSPN: + if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1))) + return build_int_cst (type, strcspn (p0, p1)); + return NULL_TREE; + + case BUILT_IN_STRCMP: + if ((p0 = c_getstr (arg0)) && (p1 = c_getstr (arg1))) + return build_cmp_result (type, strcmp (p0, p1)); + return NULL_TREE; + + default: + return fold_const_call_1 (fn, type, arg0, arg1); + } +} + /* Try to evaluate: *RESULT = FN (*ARG0, *ARG1, *ARG2) @@ -1307,12 +1403,12 @@ fold_const_call_ssss (real_value *result, built_in_function fn, } } -/* Try to fold FN (ARG0, ARG1, ARG2) to a constant. Return the constant on - success, otherwise return null. TYPE is the type of the return value. */ +/* Subroutine of fold_const_call, with the same interface. Handle cases + where the arguments and result are numerical. */ -tree -fold_const_call (built_in_function fn, tree type, tree arg0, tree arg1, - tree arg2) +static tree +fold_const_call_1 (built_in_function fn, tree type, tree arg0, tree arg1, + tree arg2) { machine_mode mode = TYPE_MODE (type); machine_mode arg0_mode = TYPE_MODE (TREE_TYPE (arg0)); @@ -1342,6 +1438,39 @@ fold_const_call (built_in_function fn, tree type, tree arg0, tree arg1, return NULL_TREE; } +/* Try to fold FN (ARG0, ARG1, ARG2) to a constant. Return the constant on + success, otherwise return null. TYPE is the type of the return value. */ + +tree +fold_const_call (built_in_function fn, tree type, tree arg0, tree arg1, + tree arg2) +{ + const char *p0, *p1; + size_t s2; + switch (fn) + { + case BUILT_IN_STRNCMP: + if ((p0 = c_getstr (arg0)) + && (p1 = c_getstr (arg1)) + && host_size_t_cst_p (arg2, &s2)) + return build_int_cst (type, strncmp (p0, p1, s2)); + return NULL_TREE; + + case BUILT_IN_BCMP: + case BUILT_IN_MEMCMP: + if ((p0 = c_getstr (arg0)) + && (p1 = c_getstr (arg1)) + && host_size_t_cst_p (arg2, &s2) + && s2 <= strlen (p0) + && s2 <= strlen (p1)) + return build_cmp_result (type, memcmp (p0, p1, s2)); + return NULL_TREE; + + default: + return fold_const_call_1 (fn, type, arg0, arg1, arg2); + } +} + /* Fold a fma operation with arguments ARG[012]. */ tree |