gcc miscompilation in Stockfish 1.6

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

zamar
Posts: 613
Joined: Sun Jan 18, 2009 7:03 am

Re: gcc miscompilation in Stockfish 1.6

Post by zamar »

Note that here compiler is free to choose between signed and unsigned type:

Code: Select all

enum Score &#123; ENSURE_32_BIT_SIZE = 1 << 31 &#125;;
while here compiler is forced to use signed int:

Code: Select all

enum Score &#123; ENSURE_32_BIT_SIZE_MAX = 1 << 31,  ENSURE_32_BIT_SIZE_MIN = -&#40;1<<31&#41;&#125;;
Or perhaps more easily:

Code: Select all


enum Score &#123; ENSURE_32_BIT_SIZE_MAX = 1 << 31, ENSURE_NEGATIVE=-1 &#125;;
Joona Kiiski
mcostalba
Posts: 2684
Joined: Sat Jun 14, 2008 9:17 pm

Re: gcc miscompilation in Stockfish 1.6

Post by mcostalba »

Gian-Carlo Pascutto wrote: Note that if enum is (a signed) int, and the Scores can be negative (which I think they can for you), then the result of that >> 16 is entirely implementation defined.
Sorry, I don't understand this. Why should be an error a right shift of a negative number ? I would think the right shift of an int is sign extended.

Care to explain ? Thanks.

BTW according to your reasoning, if I have understood correctly, should be wrong also this one:

Code: Select all

inline Value mg_value&#40;Score s&#41; &#123; return Value&#40;&#40;int&#40;s&#41; + 32768&#41; >> 16&#41;; &#125;
Jan Brouwer
Posts: 201
Joined: Thu Mar 22, 2007 7:12 pm
Location: Netherlands

Re: gcc miscompilation in Stockfish 1.6

Post by Jan Brouwer »

How is Value exactly defined?
I didn't find in this thread (maybe I missed it).

Jan
mcostalba
Posts: 2684
Joined: Sat Jun 14, 2008 9:17 pm

Re: gcc miscompilation in Stockfish 1.6

Post by mcostalba »

Jan Brouwer wrote:How is Value exactly defined?
I didn't find in this thread (maybe I missed it).

Jan
It is defined just few lines above Score in value.h file

Code: Select all

enum Value &#123;
  VALUE_DRAW = 0,
  VALUE_KNOWN_WIN = 15000,
  VALUE_MATE = 30000,
  VALUE_INFINITE = 30001,
  VALUE_NONE = 30002
&#125;;
Gian-Carlo Pascutto
Posts: 1243
Joined: Sat Dec 13, 2008 7:00 pm

Re: gcc miscompilation in Stockfish 1.6

Post by Gian-Carlo Pascutto »

mcostalba wrote: Sorry, I don't understand this. Why should be an error a right shift of a negative number ?
It's not an error, it's implementation defined. Meaning, if you switch compilers or compiler versions, or even optimization settings, the result is allowed to change.

If you care for the exact outcome (which I would presume), then the code is wrong.
I would think the right shift of an int is sign extended.
There is nothing in the C standard that guarantees that. See section 6.5.7, point 5:

http://www.open-std.org/JTC1/SC22/WG14/ ... /n1256.pdf
mcostalba
Posts: 2684
Joined: Sat Jun 14, 2008 9:17 pm

Re: gcc miscompilation in Stockfish 1.6

Post by mcostalba »

Gian-Carlo Pascutto wrote:
mcostalba wrote: Sorry, I don't understand this. Why should be an error a right shift of a negative number ?
It's not an error, it's implementation defined. Meaning, if you switch compilers or compiler versions, or even optimization settings, the result is allowed to change.

If you care for the exact outcome (which I would presume), then the code is wrong.
I would think the right shift of an int is sign extended.
There is nothing in the C standard that guarantees that. See section 6.5.7, point 5:

http://www.open-std.org/JTC1/SC22/WG14/ ... /n1256.pdf
Thanks,

so I presume also this one should be changed

Code: Select all

inline Value mg_value&#40;Score s&#41; &#123; return Value&#40;&#40;int&#40;s&#41; + 32768&#41; >> 16&#41;; &#125; 

Have you a suggestion on how to extract the _signed_ 16 bits of the lower and upper part of a 32 bit field (integer) ?
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: gcc miscompilation in Stockfish 1.6

Post by Sven »

mcostalba wrote:
Gian-Carlo Pascutto wrote: Note that if enum is (a signed) int, and the Scores can be negative (which I think they can for you), then the result of that >> 16 is entirely implementation defined.
Sorry, I don't understand this. Why should be an error a right shift of a negative number ? I would think the right shift of an int is sign extended.

Care to explain ? Thanks.

BTW according to your reasoning, if I have understood correctly, should be wrong also this one:

Code: Select all

inline Value mg_value&#40;Score s&#41; &#123; return Value&#40;&#40;int&#40;s&#41; + 32768&#41; >> 16&#41;; &#125;
From C++ standard which essentially contains the same text as the C standard pointed to by Gian-Carlo regarding shift operators:
5.8 Shift operators
[...]
3 The value of E1 >>E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 divided by the quantity 2 raised to the power E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined.
Sven
mcostalba
Posts: 2684
Joined: Sat Jun 14, 2008 9:17 pm

Re: gcc miscompilation in Stockfish 1.6

Post by mcostalba »

Gian-Carlo Pascutto wrote: There is nothing in the C standard that guarantees that. See section 6.5.7, point 5:

http://www.open-std.org/JTC1/SC22/WG14/ ... /n1256.pdf
Ok, so what about this one ?

Code: Select all

inline Value eg_value&#40;Score s&#41; &#123; return Value&#40;&#40;int&#41;&#40;unsigned&#40;s&#41; & 0x7fffu&#41; - &#40;int&#41;&#40;unsigned&#40;s&#41; & 0x8000u&#41;); &#125;
I have verified it works with all the compilers and does not rely on shifts or cast to shorts. I have found it googling around and it seems safe to me.
Gerd Isenberg
Posts: 2250
Joined: Wed Mar 08, 2006 8:47 pm
Location: Hattingen, Germany

Re: gcc miscompilation in Stockfish 1.6

Post by Gerd Isenberg »

mcostalba wrote: so I presume also this one should be changed

Code: Select all

inline Value mg_value&#40;Score s&#41; &#123; return Value&#40;&#40;int&#40;s&#41; + 32768&#41; >> 16&#41;; &#125; 
Have you a suggestion on how to extract the _signed_ 16 bits of the lower and upper part of a 32 bit field (integer) ?
You may use div instead of shift right:

Code: Select all

inline Value mg_value&#40;Score s&#41; &#123;return Value&#40;int&#40;s & ~0xffff&#41; / 0x10000&#41;;&#125; 
inline Value eg_value&#40;Score s&#41; &#123;return Value&#40;int&#40;short&#40;s &  0xffff&#41;));&#125; 
Likely x86 compiler will emit the intended x86 sar instruction instead of div, as mentioned in the Software Optimization Guide for AMD Family 10h Processors (pdf) pg 122:

Code: Select all

Signed Division by 2^n
; In&#58; EAX = dividend
; Out&#58; EAX = quotient
cdq ; Sign extend into EDX.
and edx, &#40;2^n - 1&#41; ; Mask correction &#40;use divisor - 1&#41;
add eax, edx ; Apply correction if necessary.
sar eax, &#40;n&#41; ; Perform right shift by log2&#40;divisor&#41;.
User avatar
Zach Wegner
Posts: 1922
Joined: Thu Mar 09, 2006 12:51 am
Location: Earth

Re: gcc miscompilation in Stockfish 1.6

Post by Zach Wegner »

zamar wrote:Note that here compiler is free to choose between signed and unsigned type:

Code: Select all

enum Score &#123; ENSURE_32_BIT_SIZE = 1 << 31 &#125;;
while here compiler is forced to use signed int:

Code: Select all

enum Score &#123; ENSURE_32_BIT_SIZE_MAX = 1 << 31,  ENSURE_32_BIT_SIZE_MIN = -&#40;1<<31&#41;&#125;;
No, for the last one it would have to use something more than 32 bit. In 32 bits, (1<<31) and -(1<<31) are the same number. And in the first example, it would have to use unsigned ints, bit 31 is the sign bit so (1<<31) is negative in signed arithmetic. Your examples would work if you change the 31s to 30s, though.