Add hardware POPCNT support for gcc
authorMarco Costalba <mcostalba@gmail.com>
Sat, 30 Jan 2010 18:18:27 +0000 (19:18 +0100)
committerMarco Costalba <mcostalba@gmail.com>
Sun, 31 Jan 2010 08:39:32 +0000 (09:39 +0100)
With new target 'make gcc-popcnt' it is now
possible to compile with enabled hardware POPCNT
support also with gcc. Until now was possible only
for Intel and MSVC compilers.

When this instruction is supported by CPU, for instance
on Intel i7 or i5 family, produced binary is a bit faster.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
src/Makefile
src/bitcount.h

index 1388f465fd49a0c00e1a52c3bec993aebfafe8b1..3963e5589d6fdfc85a87dd230ff0d3ef048830fc 100644 (file)
@@ -80,6 +80,7 @@ help:
        @echo "Makefile options:"
        @echo ""
        @echo "make                >  Default: Compiler = g++"
+       @echo "make gcc-popcnt     >  Compiler = g++ + popcnt-support"
        @echo "make icc            >  Compiler = icpc"
        @echo "make icc-profile    >  Compiler = icpc + automatic pgo-build"
        @echo "make icc-profile-popcnt >  Compiler = icpc + automatic pgo-build + popcnt-support"
@@ -108,6 +109,13 @@ gcc:
        CXXFLAGS="$(GCCFLAGS)" \
        all
 
+gcc-popcnt:
+       $(MAKE) \
+       CXX='g++' \
+       CXXFLAGS="$(GCCFLAGS) -DUSE_POPCNT" \
+       all
+
+
 icc:
        $(MAKE) \
        CXX='icpc' \
index aa27c049415bcc3ce98750d48a9194152f8d8486..b32314d8201ee88db1a6ee5a050d92d398803b86 100644 (file)
@@ -53,6 +53,30 @@ inline bool cpu_has_popcnt() {
 
 #define POPCNT_INTRINSIC(x) __popcnt64(x)
 
+#elif defined(__GNUC__) && defined(USE_POPCNT) // Gcc compiler
+
+inline void __cpuid(unsigned int op,
+                    unsigned int *eax, unsigned int *ebx,
+                    unsigned int *ecx, unsigned int *edx)
+{
+  *eax = op;
+  *ecx = 0;
+  __asm__("cpuid" : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
+                  : "0" (*eax), "2" (*ecx));
+}
+
+inline bool cpu_has_popcnt() {
+
+  unsigned int eax, ebx, ecx, edx;
+  __cpuid(1, &eax, &ebx, &ecx, &edx);
+  return (ecx >> 23) & 1;
+}
+
+#define POPCNT_INTRINSIC(x) ({ \
+   unsigned long __ret; \
+   __asm__("popcnt %1, %0" : "=r" (__ret) : "r" (x)); \
+   __ret; })
+
 #else // Safe fallback for unsupported compilers or when USE_POPCNT is disabled
 
 inline bool cpu_has_popcnt() { return false; }