Yet another pop_1st_bit() optimization
authorMarco Costalba <mcostalba@gmail.com>
Sun, 12 Oct 2008 12:34:54 +0000 (14:34 +0200)
committerMarco Costalba <mcostalba@gmail.com>
Sun, 12 Oct 2008 12:34:54 +0000 (14:34 +0200)
Always for 32 bit but withot relying on MSVC intrinsics.

It is very similar to previous ones, but this does not
segfaults due to -fno-strict-aliasing compiler option.

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

index 2b89bc12e23b86a65a04f35440b33fc5583958da..b55ef7eab284e8f4ca19d05c1f4f36fb9fa77d6b 100644 (file)
@@ -78,7 +78,7 @@ CXXFLAGS += -Wall -g
 # General optimization flags.  Note that -O2 might be faster than -O3 on some
 # systems; this requires testing.
 
-CXXFLAGS += -O3 -fno-exceptions -fomit-frame-pointer -fno-rtti -fstrict-aliasing
+CXXFLAGS += -O3 -fno-exceptions -fomit-frame-pointer -fno-rtti -fno-strict-aliasing
 
 # Disable most annoying warnings for the Intel C++ compiler
 
index 8250e829713020bb7d13cf061eb41f39bc9082e6..89065c49fe81eb11d0328e08b121cb0018c23f77 100644 (file)
@@ -349,30 +349,39 @@ Square first_1(Bitboard b) {
 /// pop_1st_bit() finds and clears the least significant nonzero bit in a
 /// nonzero bitboard.
 
-#if defined(USE_32BIT_ATTACKS) && defined(_MSC_VER)
+#if defined(USE_32BIT_ATTACKS)
 
-// On 32bit system compiled with MSVC this verion seems
-// slightly faster then the standard one.
+// Use type-punning
+union b_union {
 
-Square pop_1st_bit(Bitboard *b) {
+    Bitboard b;
+    struct {
+        uint32_t l;
+        uint32_t h;
+    };
+};
 
-    unsigned long index;
-    uint32_t *l, *h;
+// WARNING: Needs -fno-strict-aliasing compiler option
+Square pop_1st_bit(Bitboard *bb) {
 
-    if (*(l = (uint32_t*)b) != 0)
-    {
-        _BitScanForward(&index, *l);
-        *l &= ~(1 << index);
-    }
-    else if (*(h = (uint32_t*)b + 1) != 0)
-    {
-        _BitScanForward(&index, *h);
-        *h &= ~(1 << index);
-        index += 32;
-    } else
-        return SQ_NONE;
-
-    return Square(index);
+  b_union u;
+  uint32_t b;
+
+  u.b = *bb;
+
+  if (u.l)
+  {
+      b = u.l;
+      *((uint32_t*)bb) = b & (b - 1);
+      b ^= (b - 1);
+  }
+  else
+  {
+      b = u.h;
+      *((uint32_t*)bb+1) = b & (b - 1); // Little endian only?
+      b = ~(b ^ (b - 1));
+  }
+  return Square(BitTable[(b * 0x783a9b23) >> 26]);
 }
 
 #else