Move constant bitop and bswap folds to fold-const-call.c
authorRichard Sandiford <richard.sandiford@arm.com>
Sat, 7 Nov 2015 10:08:31 +0000 (10:08 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Sat, 7 Nov 2015 10:08:31 +0000 (10:08 +0000)
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

gcc/ChangeLog
gcc/builtins.c
gcc/fold-const-call.c

index 518c2163fbe3e454bdba60992b5edbbda3af2acb..7b9f63ce6fe9e38adcdc95861288cac767bc5e3e 100644 (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...
index 6eefd5409caa62a3c9c98e4a56f5bc8dd54bd67a..3f7fe3b9bbc9da0da29a93d0a7dc4918d577642a 100644 (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);
 
index c277d2b98fc2dc9a1b2fa316bbb6907f467d2f1e..48e05a967b34af809051b866f12cfce6165f9233 100644 (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));