aboutsummaryrefslogtreecommitdiff
path: root/gcc/toplev.h
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2010-08-05 12:41:31 -0700
committerRichard Henderson <rth@gcc.gnu.org>2010-08-05 12:41:31 -0700
commitbd95721f862876dac7d1560806b18015bb5bbeb6 (patch)
treeebb0bcbba694540435097fb9c41ec0f70c57ab41 /gcc/toplev.h
parent55b324a67cf91568372f4e93c7dae01a572de9f4 (diff)
downloadgcc-bd95721f862876dac7d1560806b18015bb5bbeb6.zip
gcc-bd95721f862876dac7d1560806b18015bb5bbeb6.tar.gz
gcc-bd95721f862876dac7d1560806b18015bb5bbeb6.tar.bz2
Replace exact_log2(x & -x) in favor of more direct computation.
* 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
Diffstat (limited to 'gcc/toplev.h')
-rw-r--r--gcc/toplev.h50
1 files changed, 42 insertions, 8 deletions
diff --git a/gcc/toplev.h b/gcc/toplev.h
index 44920ed..6de27a0 100644
--- a/gcc/toplev.h
+++ b/gcc/toplev.h
@@ -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 */