summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2020-05-26 22:27:51 +0200
committerBruno Haible <bruno@clisp.org>2020-05-26 22:27:51 +0200
commitcd3078f00c6dc5e74080b95dc4bee07953256eb9 (patch)
treee3f1be2892e363db04392cfb44d48f173bf62eb9
parent2dd2dab4bccfaca6b6b92a3b9ff5a6dce606af0d (diff)
downloadgnulib-cd3078f00c6dc5e74080b95dc4bee07953256eb9.tar.gz
gnulib-cd3078f00c6dc5e74080b95dc4bee07953256eb9.tar.bz2
count-one-bits: Fix MSVC specific code.
Reported by Gisle Vanem <gisle.vanem@gmail.com> in <https://lists.gnu.org/archive/html/bug-gnulib/2020-05/msg00309.html>. * lib/count-one-bits.h (COUNT_ONE_BITS_GENERIC): Don't define if we're using GCC. [_MSC_VER]: Use correct syntax for #pragma intrinsic. (__popcnt64): In 32-bit mode, define as an inline function. (COUNT_ONE_BITS): Rename first argument to GCC_BUILTIN.
-rw-r--r--ChangeLog11
-rw-r--r--lib/count-one-bits.h85
2 files changed, 64 insertions, 32 deletions
diff --git a/ChangeLog b/ChangeLog
index 2ce774639e..523de74b20 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
2020-05-26 Bruno Haible <bruno@clisp.org>
+ count-one-bits: Fix MSVC specific code.
+ Reported by Gisle Vanem <gisle.vanem@gmail.com> in
+ <https://lists.gnu.org/archive/html/bug-gnulib/2020-05/msg00309.html>.
+ * lib/count-one-bits.h (COUNT_ONE_BITS_GENERIC): Don't define if we're
+ using GCC.
+ [_MSC_VER]: Use correct syntax for #pragma intrinsic.
+ (__popcnt64): In 32-bit mode, define as an inline function.
+ (COUNT_ONE_BITS): Rename first argument to GCC_BUILTIN.
+
+2020-05-26 Bruno Haible <bruno@clisp.org>
+
argz: Avoid name clashes through argz.h.
Reported by Gisle Vanem <gisle.vanem@gmail.com> in
<https://lists.gnu.org/archive/html/bug-gnulib/2020-05/msg00308.html>.
diff --git a/lib/count-one-bits.h b/lib/count-one-bits.h
index eea56d8591..6c5b75708c 100644
--- a/lib/count-one-bits.h
+++ b/lib/count-one-bits.h
@@ -34,29 +34,13 @@ _GL_INLINE_HEADER_BEGIN
extern "C" {
#endif
-/* Expand to code that computes the number of 1-bits of the local
- variable 'x' of type TYPE (an unsigned integer type) and return it
- from the current function. */
-#define COUNT_ONE_BITS_GENERIC(TYPE) \
- do \
- { \
- int count = 0; \
- int bits; \
- for (bits = 0; bits < sizeof (TYPE) * CHAR_BIT; bits += 32) \
- { \
- count += count_one_bits_32 (x); \
- x = x >> 31 >> 1; \
- } \
- return count; \
- } \
- while (0)
-
-/* Assuming the GCC builtin is BUILTIN and the MSC builtin is MSC_BUILTIN,
+/* Assuming the GCC builtin is GCC_BUILTIN and the MSC builtin is MSC_BUILTIN,
expand to code that computes the number of 1-bits of the local
variable 'x' of type TYPE (an unsigned integer type) and return it
from the current function. */
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
-# define COUNT_ONE_BITS(BUILTIN, MSC_BUILTIN, TYPE) return BUILTIN (x)
+# define COUNT_ONE_BITS(GCC_BUILTIN, MSC_BUILTIN, TYPE) \
+ return GCC_BUILTIN (x)
#else
/* Compute and return the number of 1-bits set in the least
@@ -71,14 +55,46 @@ count_one_bits_32 (unsigned int x)
return (x >> 8) + (x & 0x00ff);
}
+/* Expand to code that computes the number of 1-bits of the local
+ variable 'x' of type TYPE (an unsigned integer type) and return it
+ from the current function. */
+# define COUNT_ONE_BITS_GENERIC(TYPE) \
+ do \
+ { \
+ int count = 0; \
+ int bits; \
+ for (bits = 0; bits < sizeof (TYPE) * CHAR_BIT; bits += 32) \
+ { \
+ count += count_one_bits_32 (x); \
+ x = x >> 31 >> 1; \
+ } \
+ return count; \
+ } \
+ while (0)
+
# if 1500 <= _MSC_VER && (defined _M_IX86 || defined _M_X64)
/* While gcc falls back to its own generic code if the machine
on which it's running doesn't support popcount, with Microsoft's
compiler we need to detect and fallback ourselves. */
-# pragma intrinsic __cpuid
-# pragma intrinsic __popcnt
-# pragma intrinsic __popcnt64
+
+# if 0
+# include <intrin.h>
+# else
+ /* Don't pollute the namespace with too many MSVC intrinsics. */
+# pragma intrinsic (__cpuid)
+# pragma intrinsic (__popcnt)
+# if defined _M_X64
+# pragma intrinsic (__popcnt64)
+# endif
+# endif
+
+# if !defined _M_X64
+static inline __popcnt64 (unsigned long long x)
+{
+ return __popcnt ((unsigned int) (x >> 32)) + __popcnt ((unsigned int) x);
+}
+# endif
/* Return nonzero if popcount is supported. */
@@ -90,25 +106,30 @@ popcount_supported (void)
{
if (popcount_support < 0)
{
+ /* Do as described in
+ <https://docs.microsoft.com/en-us/cpp/intrinsics/popcnt16-popcnt-popcnt64> */
int cpu_info[4];
__cpuid (cpu_info, 1);
- popcount_support = (cpu_info[2] >> 23) & 1; /* See MSDN. */
+ popcount_support = (cpu_info[2] >> 23) & 1;
}
return popcount_support;
}
-# define COUNT_ONE_BITS(BUILTIN, MSC_BUILTIN, TYPE) \
- do \
- { \
- if (popcount_supported ()) \
- return MSC_BUILTIN (x); \
- else \
- COUNT_ONE_BITS_GENERIC (TYPE); \
- } \
+# define COUNT_ONE_BITS(GCC_BUILTIN, MSC_BUILTIN, TYPE) \
+ do \
+ { \
+ if (popcount_supported ()) \
+ return MSC_BUILTIN (x); \
+ else \
+ COUNT_ONE_BITS_GENERIC (TYPE); \
+ } \
while (0)
+
# else
-# define COUNT_ONE_BITS(BUILTIN, MSC_BUILTIN, TYPE) \
+
+# define COUNT_ONE_BITS(GCC_BUILTIN, MSC_BUILTIN, TYPE) \
COUNT_ONE_BITS_GENERIC (TYPE)
+
# endif
#endif

Return to:

Send suggestions and report system problems to the System administrator.