From 978ace6fbbc828adc20f21591d138f41d8508ebc Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 16 Feb 2018 16:06:17 -0800 Subject: [PATCH] Improve _hb_popcount() Support 128bit type. --- configure.ac | 3 +- src/hb-ot-layout-gpos-table.hh | 2 +- src/hb-ot-map.cc | 2 +- src/hb-private.hh | 61 ++++++++++++++++++++++------------ 4 files changed, 44 insertions(+), 24 deletions(-) diff --git a/configure.ac b/configure.ac index 7dbd553d1..02a4a8973 100644 --- a/configure.ac +++ b/configure.ac @@ -76,7 +76,8 @@ GTK_DOC_CHECK([1.15],[--flavour no-tmpl]) AM_CONDITIONAL([ENABLE_GTK_DOC], false) ]) -# Functions and headers +# Types, functions, and headers +AC_CHECK_TYPES(unsigned __int128) AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty newlocale strtod_l setlinebuf) AC_CHECK_HEADERS(unistd.h sys/mman.h xlocale.h) diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh index 14ee37131..5b1bc6abd 100644 --- a/src/hb-ot-layout-gpos-table.hh +++ b/src/hb-ot-layout-gpos-table.hh @@ -99,7 +99,7 @@ struct ValueFormat : HBUINT16 #endif inline unsigned int get_len (void) const - { return _hb_popcount32 ((unsigned int) *this); } + { return _hb_popcount ((unsigned int) *this); } inline unsigned int get_size (void) const { return get_len () * Value::static_size; } diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc index 6f07a7e22..54b0ce377 100644 --- a/src/hb-ot-map.cc +++ b/src/hb-ot-map.cc @@ -139,7 +139,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m, { static_assert ((!(HB_GLYPH_FLAG_DEFINED & (HB_GLYPH_FLAG_DEFINED + 1))), ""); unsigned int global_bit_mask = HB_GLYPH_FLAG_DEFINED + 1; - unsigned int global_bit_shift = _hb_popcount32 (HB_GLYPH_FLAG_DEFINED); + unsigned int global_bit_shift = _hb_popcount (HB_GLYPH_FLAG_DEFINED); m.global_mask = global_bit_mask; diff --git a/src/hb-private.hh b/src/hb-private.hh index aeed58ae2..f4a31a69b 100644 --- a/src/hb-private.hh +++ b/src/hb-private.hh @@ -323,31 +323,50 @@ typedef const struct _hb_void_t *hb_void_t; #define HB_VOID ((const _hb_void_t *) nullptr) /* Return the number of 1 bits in mask. */ +template static inline HB_CONST_FUNC unsigned int -_hb_popcount32 (uint32_t mask) +_hb_popcount (T mask) { -#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) - return __builtin_popcount (mask); -#else - /* "HACKMEM 169" */ - uint32_t y; - y = (mask >> 1) &033333333333; - y = mask - y - ((y >>1) & 033333333333); - return (((y + (y >> 3)) & 030707070707) % 077); +#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) && defined(__OPTIMIZE__) + if (sizeof (unsigned int) >= sizeof (mask)) + return __builtin_popcount (mask); + + if (sizeof (unsigned long) >= sizeof (mask)) + return __builtin_popcountl (mask); + + if (sizeof (unsigned long long) >= sizeof (mask)) + return __builtin_popcountll (mask); #endif + + if (sizeof (T) <= 4) + { + /* "HACKMEM 169" */ + uint32_t y; + y = (mask >> 1) &033333333333; + y = mask - y - ((y >>1) & 033333333333); + return (((y + (y >> 3)) & 030707070707) % 077); + } + + if (sizeof (T) == 8) + { + unsigned int shift = 32; + return _hb_popcount ((uint32_t) mask) + _hb_popcount ((uint32_t) (mask >> shift)); + } + + if (sizeof (T) == 16) + { + unsigned int shift = 64; + return _hb_popcount ((uint64_t) mask) + _hb_popcount ((uint64_t) (mask >> shift)); + } + + unsigned int count = 0; + while (mask) + { + count += _hb_popcount ((uint64_t) mask); + unsigned int shift = 64; + mask = (T) (mask >> shift); + } } -static inline HB_CONST_FUNC unsigned int -_hb_popcount64 (uint64_t mask) -{ -#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) - if (sizeof (long) >= sizeof (mask)) - return __builtin_popcountl (mask); -#endif - return _hb_popcount32 (mask & 0xFFFFFFFF) + _hb_popcount32 (mask >> 32); -} -template static inline unsigned int _hb_popcount (T mask); -template <> inline unsigned int _hb_popcount (uint32_t mask) { return _hb_popcount32 (mask); } -template <> inline unsigned int _hb_popcount (uint64_t mask) { return _hb_popcount64 (mask); } /* Returns the number of bits needed to store number */ static inline HB_CONST_FUNC unsigned int