aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--bignum.c30
-rw-r--r--internal.h6
-rw-r--r--pack.c7
4 files changed, 32 insertions, 19 deletions
diff --git a/ChangeLog b/ChangeLog
index 66b5029b92..e78debfce3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+Fri Apr 12 20:59:24 2013 Tanaka Akira <akr@fsij.org>
+
+ * bignum.c (ones): Use __builtin_popcountl if available.
+
+ * internal.h (GCC_VERSION_SINCE): Macro moved from pack.c.
+
+ * pack.c: Include internal.h for GCC_VERSION_SINCE.
+
Fri Apr 12 18:29:42 2013 Tanaka Akira <akr@fsij.org>
* common.mk: version.o depends on $(srcdir)/include/ruby/version.h
diff --git a/bignum.c b/bignum.c
index 6236ff32f7..306231c0df 100644
--- a/bignum.c
+++ b/bignum.c
@@ -887,27 +887,31 @@ static void bigdivmod(VALUE x, VALUE y, volatile VALUE *divp, volatile VALUE *mo
static inline int
ones(register unsigned long x)
{
-#if SIZEOF_LONG == 8
-# define MASK_55 0x5555555555555555UL
-# define MASK_33 0x3333333333333333UL
-# define MASK_0f 0x0f0f0f0f0f0f0f0fUL
+#if GCC_VERSION_SINCE(3, 4, 0)
+ return __builtin_popcountl(x);
#else
-# define MASK_55 0x55555555UL
-# define MASK_33 0x33333333UL
-# define MASK_0f 0x0f0f0f0fUL
-#endif
+# if SIZEOF_LONG == 8
+# define MASK_55 0x5555555555555555UL
+# define MASK_33 0x3333333333333333UL
+# define MASK_0f 0x0f0f0f0f0f0f0f0fUL
+# else
+# define MASK_55 0x55555555UL
+# define MASK_33 0x33333333UL
+# define MASK_0f 0x0f0f0f0fUL
+# endif
x -= (x >> 1) & MASK_55;
x = ((x >> 2) & MASK_33) + (x & MASK_33);
x = ((x >> 4) + x) & MASK_0f;
x += (x >> 8);
x += (x >> 16);
-#if SIZEOF_LONG == 8
+# if SIZEOF_LONG == 8
x += (x >> 32);
-#endif
+# endif
return (int)(x & 0x7f);
-#undef MASK_0f
-#undef MASK_33
-#undef MASK_55
+# undef MASK_0f
+# undef MASK_33
+# undef MASK_55
+#endif
}
static inline unsigned long
diff --git a/internal.h b/internal.h
index 964f8a3467..90388533dc 100644
--- a/internal.h
+++ b/internal.h
@@ -19,6 +19,12 @@ extern "C" {
#endif
#endif
+#define GCC_VERSION_SINCE(major, minor, patchlevel) \
+ (defined(__GNUC__) && !defined(__INTEL_COMPILER) && \
+ ((__GNUC__ > (major)) || \
+ (__GNUC__ == (major) && __GNUC_MINOR__ > (minor)) || \
+ (__GNUC__ == (major) && __GNUC_MINOR__ == (minor) && __GNUC_PATCHLEVEL__ >= (patchlevel))))
+
#if SIGNEDNESS_OF_TIME_T < 0 /* signed */
# define TIMET_MAX (time_t)((~(unsigned_time_t)0) >> 1)
# define TIMET_MIN (time_t)(((unsigned_time_t)1) << (sizeof(time_t) * CHAR_BIT - 1))
diff --git a/pack.c b/pack.c
index 7a12cfcf24..fb6472c809 100644
--- a/pack.c
+++ b/pack.c
@@ -11,16 +11,11 @@
#include "ruby/ruby.h"
#include "ruby/encoding.h"
+#include "internal.h"
#include <sys/types.h>
#include <ctype.h>
#include <errno.h>
-#define GCC_VERSION_SINCE(major, minor, patchlevel) \
- (defined(__GNUC__) && !defined(__INTEL_COMPILER) && \
- ((__GNUC__ > (major)) || \
- (__GNUC__ == (major) && __GNUC_MINOR__ > (minor)) || \
- (__GNUC__ == (major) && __GNUC_MINOR__ == (minor) && __GNUC_PATCHLEVEL__ >= (patchlevel))))
-
/*
* It is intentional that the condition for natstr is HAVE_TRUE_LONG_LONG
* instead of HAVE_LONG_LONG or LONG_LONG.