[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Warnings in count-one-bits.h
From: |
Bruno Haible |
Subject: |
Re: Warnings in count-one-bits.h |
Date: |
Tue, 26 May 2020 22:35:37 +0200 |
User-agent: |
KMail/5.1.3 (Linux/4.4.0-177-generic; KDE/5.18.0; x86_64; ; ) |
Gisle Vanem wrote:
> The lines in count-one-bits.h:
> # pragma intrinsic __cpuid
> # pragma intrinsic __popcnt
> # pragma intrinsic __popcnt64
>
> triggers these warnings:
> count-one-bits.h(79): warning C4083: expected '('; found identifier
> '__cpuid'
> count-one-bits.h(80): warning C4083: expected '('; found identifier
> '__popcnt'
> count-one-bits.h(81): warning C4083: expected '('; found identifier
> '__popcnt64'
Indeed, the #pragma intrinsic syntax expects parentheses. This is not new;
here's a documentation from 2010 already that specifies it like this:
https://www.geoffchappell.com/studies/msvc/language/preprocessor/directives/pragma/intrinsic.htm
> Since on MSVC-2019/x86, I get:
> warning C4163: '__popcnt64': not available as an intrinsic function
>
> It seems '__popcnt64' is an intrinsic on x64 only:
>
> https://docs.microsoft.com/en-us/cpp/intrinsics/popcnt16-popcnt-popcnt64?view=vs-2019
Indeed.
The patch below should fix it.
> PS. Using clang-cl compiling the same file:
> ./count-one-bits.h(79,22): warning: '__cpuid' is not a recognized builtin;
> consider including <intrin.h> to access non-builtin intrinsics
> [-Wignored-pragma-intrinsic]
> # pragma intrinsic (__cpuid, __popcnt)
> ^
What is this clang-cl compiler? Is it disguising itself as _MSC_VER ?
2020-05-26 Bruno Haible <address@hidden>
count-one-bits: Fix MSVC specific code.
Reported by Gisle Vanem <address@hidden> 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.
diff --git a/lib/count-one-bits.h b/lib/count-one-bits.h
index eea56d8..6c5b757 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