]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Replace exact_log2(x & -x) in favor of more direct computation.
authorRichard Henderson <rth@redhat.com>
Thu, 5 Aug 2010 19:41:31 +0000 (12:41 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Thu, 5 Aug 2010 19:41:31 +0000 (12:41 -0700)
* toplev.h (ctz_hwi, clz_hwi, ffs_hwi): New.
(floor_log2): Use clz_hwi.
(exact_log2): Use ctz_hwi.
* toplev.c (ctz_hwi, clz_hwi, ffs_hwi): New.
* builtins.c (fold_builtin_bitop): Use them.
* simplify-rtx.c (simplify_const_unary_operation): Likewise.
* combine.c (get_pos_from_mask): Use ctz_hwi.
* double-int.c (double_int_ctz): Likewise.
* explow.c (force_reg): Likewise.
* tree.h (SET_DECL_OFFSET_ALIGN): Use ffs_hwi.

From-SVN: r162920

gcc/ChangeLog
gcc/builtins.c
gcc/combine.c
gcc/double-int.c
gcc/explow.c
gcc/simplify-rtx.c
gcc/toplev.c
gcc/toplev.h
gcc/tree.h

index 0f5843141ed3800a416ff359894a9316772b556c..b7de0ed4ebbbe5a171a1dfb7041289071d639f8f 100644 (file)
@@ -1,3 +1,16 @@
+2010-08-05  Richard Henderson  <rth@redhat.com>
+
+       * toplev.h (ctz_hwi, clz_hwi, ffs_hwi): New.
+       (floor_log2): Use clz_hwi.
+       (exact_log2): Use ctz_hwi.
+       * toplev.c (ctz_hwi, clz_hwi, ffs_hwi): New.
+       * builtins.c (fold_builtin_bitop): Use them.
+       * simplify-rtx.c (simplify_const_unary_operation): Likewise.
+       * combine.c (get_pos_from_mask): Use ctz_hwi.
+       * double-int.c (double_int_ctz): Likewise.
+       * explow.c (force_reg): Likewise.
+       * tree.h (SET_DECL_OFFSET_ALIGN): Use ffs_hwi.
+
 2010-08-05  Richard Henderson  <rth@redhat.com>
 
        PR target/45189
index b20426cd784cb333632ca0b7bd2e01f9bc1173f3..096fec62ee39749e111f80e0749bc77e221da3f3 100644 (file)
@@ -7676,9 +7676,9 @@ fold_builtin_bitop (tree fndecl, tree arg)
        {
        CASE_INT_FN (BUILT_IN_FFS):
          if (lo != 0)
-           result = exact_log2 (lo & -lo) + 1;
+           result = ffs_hwi (lo);
          else if (hi != 0)
-           result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi) + 1;
+           result = HOST_BITS_PER_WIDE_INT + ffs_hwi (hi);
          else
            result = 0;
          break;
@@ -7694,9 +7694,9 @@ fold_builtin_bitop (tree fndecl, tree arg)
 
        CASE_INT_FN (BUILT_IN_CTZ):
          if (lo != 0)
-           result = exact_log2 (lo & -lo);
+           result = ctz_hwi (lo);
          else if (hi != 0)
-           result = HOST_BITS_PER_WIDE_INT + exact_log2 (hi & -hi);
+           result = HOST_BITS_PER_WIDE_INT + ctz_hwi (hi);
          else if (! CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (type), result))
            result = width;
          break;
@@ -7706,7 +7706,7 @@ fold_builtin_bitop (tree fndecl, tree arg)
          while (lo)
            result++, lo &= lo - 1;
          while (hi)
-           result++, hi &= hi - 1;
+           result++, hi &= (unsigned HOST_WIDE_INT) hi - 1;
          break;
 
        CASE_INT_FN (BUILT_IN_PARITY):
@@ -7714,7 +7714,7 @@ fold_builtin_bitop (tree fndecl, tree arg)
          while (lo)
            result++, lo &= lo - 1;
          while (hi)
-           result++, hi &= hi - 1;
+           result++, hi &= (unsigned HOST_WIDE_INT) hi - 1;
          result &= 1;
          break;
 
index 0725c862cf1edb751c6df43c82f2267304c483c3..41a0ec1dcb6fa7e015f1ee8861e86832d25204fc 100644 (file)
@@ -7436,7 +7436,7 @@ static int
 get_pos_from_mask (unsigned HOST_WIDE_INT m, unsigned HOST_WIDE_INT *plen)
 {
   /* Get the bit number of the first 1 bit from the right, -1 if none.  */
-  int pos = exact_log2 (m & -m);
+  int pos = m ? ctz_hwi (m) : -1;
   int len = 0;
 
   if (pos >= 0)
index 29e720b2919ad8e85be7980d5a94627d5c85e0cd..cb63f856df34348671f28c6de8c3e6da625b4030 100644 (file)
@@ -859,15 +859,7 @@ double_int_ctz (double_int a)
   unsigned bits = a.low ? 0 : HOST_BITS_PER_WIDE_INT;
   if (!w)
     return HOST_BITS_PER_DOUBLE_INT;
-#if (GCC_VERSION >= 3004)
-  bits += CTZ_HWI (w);
-#else
-  while (!(w & 1))
-    {
-      w >>= 1;
-      bits += 1;
-    }
-#endif
+  bits += ctz_hwi (w);
   return bits;
 }
 
index 09f786a253124aaa34cf46dde29df433f80a1b01..6f60b2e587bf7524050ca1dc14ff075d036e5c72 100644 (file)
@@ -707,9 +707,13 @@ force_reg (enum machine_mode mode, rtx x)
        if (SYMBOL_REF_DECL (s) && DECL_P (SYMBOL_REF_DECL (s)))
          sa = DECL_ALIGN (SYMBOL_REF_DECL (s));
 
-       ca = exact_log2 (INTVAL (c) & -INTVAL (c)) * BITS_PER_UNIT;
-
-       align = MIN (sa, ca);
+       if (INTVAL (c) == 0)
+         align = sa;
+       else
+         {
+           ca = ctz_hwi (INTVAL (c)) * BITS_PER_UNIT;
+           align = MIN (sa, ca);
+         }
       }
 
     if (align || (MEM_P (x) && MEM_POINTER (x)))
index 86de77e14061efb3a188c2627f275cebfae0e957..a7a91e5d50f8719701848ce6813ae3dd0da6b4fe 100644 (file)
@@ -1197,10 +1197,8 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode,
          break;
 
        case FFS:
-         /* Don't use ffs here.  Instead, get low order bit and then its
-            number.  If arg0 is zero, this will return 0, as desired.  */
          arg0 &= GET_MODE_MASK (mode);
-         val = exact_log2 (arg0 & (- arg0)) + 1;
+         val = ffs_hwi (arg0);
          break;
 
        case CLZ:
@@ -1221,7 +1219,7 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode,
                val = GET_MODE_BITSIZE (mode);
            }
          else
-           val = exact_log2 (arg0 & -arg0);
+           val = ctz_hwi (arg0);
          break;
 
        case POPCOUNT:
@@ -1351,15 +1349,12 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode,
 
        case FFS:
          hv = 0;
-         if (l1 == 0)
-           {
-             if (h1 == 0)
-               lv = 0;
-             else
-               lv = HOST_BITS_PER_WIDE_INT + exact_log2 (h1 & -h1) + 1;
-           }
+         if (l1 != 0)
+           lv = ffs_hwi (l1);
+         else if (h1 != 0)
+           lv = HOST_BITS_PER_WIDE_INT + ffs_hwi (h1);
          else
-           lv = exact_log2 (l1 & -l1) + 1;
+           lv = 0;
          break;
 
        case CLZ:
@@ -1376,9 +1371,9 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode,
        case CTZ:
          hv = 0;
          if (l1 != 0)
-           lv = exact_log2 (l1 & -l1);
+           lv = ctz_hwi (l1);
          else if (h1 != 0)
-           lv = HOST_BITS_PER_WIDE_INT + exact_log2 (h1 & -h1);
+           lv = HOST_BITS_PER_WIDE_INT + ctz_hwi (h1);
          else if (! CTZ_DEFINED_VALUE_AT_ZERO (mode, lv))
            lv = GET_MODE_BITSIZE (mode);
          break;
index 3836d0c50cf64ee115eeed66ae87c813e1ffc7cf..ff824662a226fd01c278d5d270ec227fd77402ca 100644 (file)
@@ -484,9 +484,9 @@ set_random_seed (const char *val)
 
 #if GCC_VERSION < 3004
 
-/* The functions floor_log2 and exact_log2 are defined as inline
-   functions in toplev.h if GCC_VERSION >= 3004.  The definitions here
-   are used for older versions of gcc.  */
+/* The functions clz_hwi, ctz_hwi, ffs_hwi, floor_log2 and exact_log2
+   are defined as inline functions in toplev.h if GCC_VERSION >= 3004.
+   The definitions here are used for older versions of gcc.  */
 
 /* Given X, an unsigned number, return the largest int Y such that 2**Y <= X.
    If X is 0, return -1.  */
@@ -530,6 +530,32 @@ exact_log2 (unsigned HOST_WIDE_INT x)
   return floor_log2 (x);
 }
 
+/* Given X, an unsigned number, return the number of least significant bits
+   that are zero.  When X == 0, the result is the word size.  */
+
+int
+ctz_hwi (unsigned HOST_WIDE_INT x)
+{
+  return x ? floor_log2 (x & -x) : HOST_BITS_PER_WIDE_INT;
+}
+
+/* Similarly for most significant bits.  */
+
+int
+clz_hwi (unsigned HOST_WIDE_INT x)
+{
+  return HOST_BITS_PER_WIDE_INT - 1 - floor_log2(x);
+}
+
+/* Similar to ctz_hwi, except that the least significant bit is numbered
+   starting from 1, and X == 0 yields 0.  */
+
+int
+ffs_hwi (unsigned HOST_WIDE_INT x)
+{
+  return 1 + floor_log2 (x & -x);
+}
+
 #endif /* GCC_VERSION < 3004 */
 
 /* Handler for fatal signals, such as SIGSEGV.  These are transformed
index 44920ed7a009d3c6e5f49bafc292421652c6b2fb..6de27a092bf89a152224a515c9187999e72b36dd 100644 (file)
@@ -111,6 +111,10 @@ extern bool fast_math_flags_struct_set_p (struct cl_optimization *);
 /* Inline versions of the above for speed.  */
 #if GCC_VERSION < 3004
 
+extern int clz_hwi (unsigned HOST_WIDE_INT x);
+extern int ctz_hwi (unsigned HOST_WIDE_INT x);
+extern int ffs_hwi (unsigned HOST_WIDE_INT x);
+
 /* Return log2, or -1 if not exact.  */
 extern int exact_log2                  (unsigned HOST_WIDE_INT);
 
@@ -119,27 +123,57 @@ extern int floor_log2                  (unsigned HOST_WIDE_INT);
 
 #else /* GCC_VERSION >= 3004 */
 
+/* For convenience, define 0 -> word_size.  */
+static inline int
+clz_hwi (unsigned HOST_WIDE_INT x)
+{
+  if (x == 0)
+    return HOST_BITS_PER_WIDE_INT;
+# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
+  return __builtin_clzl (x);
+# elif HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONGLONG
+  return __builtin_clzll (x);
+# else
+  return __builtin_clz (x);
+# endif
+}
+
+static inline int
+ctz_hwi (unsigned HOST_WIDE_INT x)
+{
+  if (x == 0)
+    return HOST_BITS_PER_WIDE_INT;
+# if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
+  return __builtin_ctzl (x);
+# elif HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONGLONG
+  return __builtin_ctzll (x);
+# else
+  return __builtin_ctz (x);
+# endif
+}
+
+static inline int
+ffs_hwi (unsigned HOST_WIDE_INT x)
+{
 # if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
-#  define CLZ_HWI __builtin_clzl
-#  define CTZ_HWI __builtin_ctzl
+  return __builtin_ffsl (x);
 # elif HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONGLONG
-#  define CLZ_HWI __builtin_clzll
-#  define CTZ_HWI __builtin_ctzll
+  return __builtin_ffsll (x);
 # else
-#  define CLZ_HWI __builtin_clz
-#  define CTZ_HWI __builtin_ctz
+  return __builtin_ffs (x);
 # endif
+}
 
 static inline int
 floor_log2 (unsigned HOST_WIDE_INT x)
 {
-  return x ? HOST_BITS_PER_WIDE_INT - 1 - (int) CLZ_HWI (x) : -1;
+  return HOST_BITS_PER_WIDE_INT - 1 - clz_hwi (x);
 }
 
 static inline int
 exact_log2 (unsigned HOST_WIDE_INT x)
 {
-  return x == (x & -x) && x ? (int) CTZ_HWI (x) : -1;
+  return x == (x & -x) && x ? ctz_hwi (x) : -1;
 }
 
 #endif /* GCC_VERSION >= 3004 */
index af8345a95becb6a51861e5c94f7b58c7b9bdb5d4..931155ca310dd16894b2b670b0d2d0650407a5b2 100644 (file)
@@ -2850,9 +2850,7 @@ struct GTY(()) tree_decl_with_rtl {
 
 /* Specify that DECL_ALIGN(NODE) is a multiple of X.  */
 #define SET_DECL_OFFSET_ALIGN(NODE, X) \
-  (FIELD_DECL_CHECK (NODE)->decl_common.off_align = exact_log2 ((X) & -(X)))
-/* 1 if the alignment for this type was requested by "aligned" attribute,
-   0 if it is the default for this type.  */
+  (FIELD_DECL_CHECK (NODE)->decl_common.off_align = ffs_hwi (X) - 1)
 
 /* For FIELD_DECLS, DECL_FCONTEXT is the *first* baseclass in
    which this FIELD_DECL is defined.  This information is needed when