Looking for intrinsic "least significant bit" on Visual Studio

Discussion of chess software programming and technical issues.

Moderator: Ras

Gerd Isenberg
Posts: 2251
Joined: Wed Mar 08, 2006 8:47 pm
Location: Hattingen, Germany

Re: Looking for intrinsic "least significant bit" on Visual Studio

Post by Gerd Isenberg »

OliverBr wrote: Sun Sep 06, 2020 2:28 pm
chrisw wrote: Sun Sep 06, 2020 1:09 pm
OliverBr wrote: Sun Sep 06, 2020 12:44 pm
MOBMAT wrote: Fri Sep 04, 2020 4:15 pm This shows all the options...

https://en.wikipedia.org/wiki/Find_first_set
This one is most interesting:

Code: Select all

ctz(x) = popcount((x & −x) − 1)
Most useful would be ctz_0, or bsf_0, which returns the bitno and clears it in one instruction, eg

bsf_0 r1, r2 // return bitno in r1, clears the corresponding bit in r2
This eliminates all except the lowest bit:

Code: Select all

x &= -x
This clears the lowest bit in x:

Code: Select all

x &= x - 1
I am not sure if there are such nice tricks with the most significant bit.
Related CPW pages: BitScan, least significant one bit, and most significant one bit. Due to the carry or borrow propagation, most significant one bit isolation requires some more computation. In some cases one may apply reverse arithmetic, see HQ.
OliverBr
Posts: 846
Joined: Tue Dec 18, 2007 9:38 pm
Location: Munich, Germany
Full name: Dr. Oliver Brausch

Re: Looking for intrinsic "least significant bit" on Visual Studio

Post by OliverBr »

chrisw wrote: Sun Sep 06, 2020 4:02 pm Msbit is way more problematical. Rule for chess engines is work with lsbit and move upwards.
I didn’t find a reason yet to work the other way round.
Actually I found a good reason and tried to implement it once:

When scanning the 64-bit boards for move generation it would make sense for white to do it with msbit, because more forward pieces would be processed first. This may improve move ordering.

I didn't notice any strength gain, but on the other hand I haven't got the 32-core server yet and couldn't tell anything for sure.
OliThink GitHub: https://github.com/olithink
Nice arcticle about OlIThink: https://www.chessengeria.eu/post/olithink-oldie-goldie
Chess Engine OliThink Homepage: http://brausch.org/home/chess
chrisw
Posts: 4638
Joined: Tue Apr 03, 2012 4:28 pm
Location: Midi-Pyrénées
Full name: Christopher Whittington

Re: Looking for intrinsic "least significant bit" on Visual Studio

Post by chrisw »

OliverBr wrote: Sun Sep 06, 2020 6:31 pm
chrisw wrote: Sun Sep 06, 2020 4:02 pm Msbit is way more problematical. Rule for chess engines is work with lsbit and move upwards.
I didn’t find a reason yet to work the other way round.
Actually I found a good reason and tried to implement it once:

When scanning the 64-bit boards for move generation it would make sense for white to do it with msbit, because more forward pieces would be processed first. This may improve move ordering.
True. Although you could achieve the same (in that movegen scenario) by using bsf and processing the movelist backwards for black.

I didn't notice any strength gain, but on the other hand I haven't got the 32-core server yet and couldn't tell anything for sure.
Gerd Isenberg
Posts: 2251
Joined: Wed Mar 08, 2006 8:47 pm
Location: Hattingen, Germany

Re: Looking for intrinsic "least significant bit" on Visual Studio

Post by Gerd Isenberg »

OliverBr wrote: Sun Sep 06, 2020 6:31 pm
chrisw wrote: Sun Sep 06, 2020 4:02 pm Msbit is way more problematical. Rule for chess engines is work with lsbit and move upwards.
I didn’t find a reason yet to work the other way round.
Actually I found a good reason and tried to implement it once:

When scanning the 64-bit boards for move generation it would make sense for white to do it with msbit, because more forward pieces would be processed first. This may improve move ordering.

I didn't notice any strength gain, but on the other hand I haven't got the 32-core server yet and couldn't tell anything for sure.
A suggestion for color agnostic bitboard traversal is conditional byteswap.

Code: Select all

if ( x ) {
   U64 m = (U64)color - 1; // e.g. -1 if white, 0 for black
   int o = (int)m & 56;
   x = x ^ ((x ^ flipVertical(x)) & m); // conditional flip
   do {
      int idx = bitScanForward(x) ^ o; // square index from 0..63
      *list++ = foo(idx , ...);
   } while (x &= x-1); // reset LS1B
}
One may color-flip the board in make move to even generate white moves always ;-)
OliverBr
Posts: 846
Joined: Tue Dec 18, 2007 9:38 pm
Location: Munich, Germany
Full name: Dr. Oliver Brausch

Re: Looking for intrinsic "least significant bit" on Visual Studio

Post by OliverBr »

Hello,
For Windows exes I want to give mingw a chance, but it won't compile because of the "_tzcnt_u64" method. The error messagt does not much sense to me:

Code: Select all

x86_64-w64-mingw32-gcc -Ofast olithink.c -o OliThink.exe
In file included from /usr/lib/gcc/x86_64-w64-mingw32/8.3-win32/include/immintrin.h:93,
                 from /usr/lib/gcc/x86_64-w64-mingw32/8.3-win32/include/x86intrin.h:48,
                 from /usr/share/mingw-w64/include/winnt.h:1554,
                 from /usr/share/mingw-w64/include/minwindef.h:163,
                 from /usr/share/mingw-w64/include/windef.h:8,
                 from /usr/share/mingw-w64/include/windows.h:69,
                 from olithink.c:6:
olithink.c: In function 'pullLsb':
/usr/lib/gcc/x86_64-w64-mingw32/8.3-win32/include/bmiintrin.h:172:1: error: inlining failed in call to always_inline '_tzcnt_u64': target specific option mismatch
 _tzcnt_u64 (unsigned long long __X)
 ^~~~~~~~~~
olithink.c:12:19: note: called from here
 #define getLsb(x) _tzcnt_u64(x)
                   ^~~~~~~~~~~~~
olithink.c:12:19: note: in definition of macro 'getLsb'
 #define getLsb(x) _tzcnt_u64(x)
                   ^~~~~~~~~~
Do you have a tip, how I can solve this? Here is the relevant code snippet from line 5 to 13:, __popcnt64(x) doesn't make problems. Using _tzcnt_u64(x) directly without #define brings the same error.

Code: Select all

#if defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#include <conio.h>
#include <sys/timeb.h>
#include <intrin.h>
struct _timeb tv;
#define _bitcnt(x) __popcnt64(x)
#define getLsb(x) _tzcnt_u64(x)
#else
OliThink GitHub: https://github.com/olithink
Nice arcticle about OlIThink: https://www.chessengeria.eu/post/olithink-oldie-goldie
Chess Engine OliThink Homepage: http://brausch.org/home/chess
mar
Posts: 2665
Joined: Fri Nov 26, 2010 2:00 pm
Location: Czech Republic
Full name: Martin Sedlak

Re: Looking for intrinsic "least significant bit" on Visual Studio

Post by mar »

a late reply, you've probably solved this since.

you should be able to use gcc builtins with mingw:
__builtin_clzll and __builtin_ctzll

they compile to lzcnt/tzcnt but you have to specify target arch. -march=native should work just fine on your CPU

(these builtins should work with clang as well)
OliverBr
Posts: 846
Joined: Tue Dec 18, 2007 9:38 pm
Location: Munich, Germany
Full name: Dr. Oliver Brausch

Re: Looking for intrinsic "least significant bit" on Visual Studio

Post by OliverBr »

mar wrote: Fri Sep 25, 2020 12:23 pm a late reply, you've probably solved this since.

you should be able to use gcc builtins with mingw:
__builtin_clzll and __builtin_ctzll

they compile to lzcnt/tzcnt but you have to specify target arch. -march=native should work just fine on your CPU

(these builtins should work with clang as well)
Thank you. I haven't found it out, because I stashed it. Your tip works well.
Unfortunately the mingw executable is 5% slower than the VisualC executable. This hasn't change since many years ago.
OliThink GitHub: https://github.com/olithink
Nice arcticle about OlIThink: https://www.chessengeria.eu/post/olithink-oldie-goldie
Chess Engine OliThink Homepage: http://brausch.org/home/chess