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
This commit is contained in:
Richard Sandiford 2015-11-07 10:08:31 +00:00 committed by Richard Sandiford
parent 2556a032cc
commit db9bd5d575
3 changed files with 84 additions and 107 deletions

View File

@ -1,3 +1,11 @@
2015-11-07 Richard Sandiford <richard.sandiford@arm.com>
* 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 <richard.sandiford@arm.com>
* builtins.c (fold_builtin_classify): Move constant cases to...

View File

@ -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);

View File

@ -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));