summaryrefslogtreecommitdiff
path: root/gcc/fold-const-call.c
diff options
context:
space:
mode:
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2015-11-07 10:08:31 +0000
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2015-11-07 10:08:31 +0000
commitaa6703b259a406b201a1c6b05476b173ad11567f (patch)
treeec9ea09087c5f93cc1650b6838db331fe6529046 /gcc/fold-const-call.c
parentad3ca0b8f2d8e5fc2ad093e5d1715c698dae02f2 (diff)
downloadgcc-aa6703b259a406b201a1c6b05476b173ad11567f.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@229921 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fold-const-call.c')
-rw-r--r--gcc/fold-const-call.c76
1 files changed, 76 insertions, 0 deletions
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. */
@@ -768,6 +769,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)
where FORMAT is the format of ARG and of the real and imaginary parts
@@ -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));