bug-gnulib
[Top][All Lists]
Advanced

[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
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]