Compiler Problem

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

Pablo Vazquez
Posts: 154
Joined: Thu May 31, 2007 9:05 pm
Location: Madrid, Spain

Re: Compiler Problem

Post by Pablo Vazquez »

I looks like piece_bb[] and color_bb[] are never initialized. I don't know if global structs are required to be initialized to 0, maybe this could be the problem?
LoopList

Re: Compiler Problem

Post by LoopList »

Gian-Carlo Pascutto wrote:
LoopList wrote: Did you really have a close look at the above code?
Yes, I don't see anything wrong, except for the prototype that is incorrect, but that can't cause the problem because this is C++ code and the function will simply get overloaded.
There is nothing more to narrow, I suppose.
You don't seem to have understood what I said. You have 2 compiles of the code, one giving a correct result, one giving a wrong one. The wrong result doesn't pop out magically, it exists because one or multiple statement are giving a wrong result. You want to find this single statement, which makes it obvious what the bug is (code or compiler). If you want to, you can even look at the generated assembler at that point and identify what's wrong.

To find the place where the right and wrong version diverge, you want to look at the intermediate results in the computation. Normally you'd do this with a debugger, but given that the problem only occurs in release mode with heavy optimizations, the alternative is to plaster printfs over all the intermediate computations and then look where they give a different result.

If you're unlucky, the printfs make the problem go away :-P

Without doing this exercise, it's going to be hard to be absolutely sure whether the problem is compiler or code.
Thats the point. By implementing further printfs() the problem goes away. And thats the reason I don't understand whats going on?

Perhaps someone with more experience in Assembler can give me the reason for this annoying behaviour.

Fritz
Gian-Carlo Pascutto
Posts: 1243
Joined: Sat Dec 13, 2008 7:00 pm

Re: Compiler Problem

Post by Gian-Carlo Pascutto »

No, globals are guaranteed to be zero-ed.
LoopList

Re: Compiler Problem

Post by LoopList »

Pablo Vazquez wrote:I looks like piece_bb[] and color_bb[] are never initialized. I don't know if global structs are required to be initialized to 0, maybe this could be the problem?
I dont think that is the problem, see here:

Code: Select all

#include <stdio.h>

namespace &#123;
  const int IS_ENPASSANT = 1 << 15;

  struct move_info_c &#123; int move, value; &#125;;
  struct board_c &#123; int piece_on&#91;64&#93;; &#125; B;

  inline int move_to&#40;int move&#41; &#123; return move & 63; &#125;
  inline int move_from&#40;int move&#41; &#123; return &#40;move >> 6&#41; & 63; &#125;
  inline int move_is_enpassant&#40;int move&#41; &#123; return &#40;move & IS_ENPASSANT&#41; != 0; &#125;
  inline int make_enpassant&#40;int from, int to&#41; &#123; return to | &#40;from << 6&#41; | IS_ENPASSANT; &#125;
  inline int piece_on_square&#40;int square&#41; &#123; return B.piece_on&#91;square&#93;; &#125;
  inline int move_is_capture&#40;int move&#41; &#123; return &#40;piece_on_square&#40;move_to&#40;move&#41;) != 6&#41; || move_is_enpassant&#40;move&#41;; &#125;
  inline int move_piece&#40;int move&#41; &#123; return piece_on_square&#40;move_from&#40;move&#41;); &#125;
  inline int move_piece_captured&#40;int move&#41; &#123; return move_is_enpassant&#40;move&#41; ? 0 &#58; piece_on_square&#40;move_to&#40;move&#41;); &#125;

  inline int piece_value_midgame&#40;int piece&#41; &#123;
    int piece_value_mg&#91;7&#93; = &#123;100, 300, 400, 500, 900, 1000, 0&#125;;
    return piece_value_mg&#91;piece&#93;;
  &#125;

  void initialize&#40;) &#123;
    for &#40;int square = 0; square < 64; square++) B.piece_on&#91;square&#93; = 6;
    B.piece_on&#91;28&#93; = B.piece_on&#91;29&#93; = 0;
  &#125;

  class sort_c &#123;
  public&#58;
    sort_c&#40;);
    move_info_c * last_move, move_list&#91;256&#93;;
  &#125;;

  sort_c&#58;&#58;sort_c&#40;) &#123;
    move_list&#91;0&#93;.move = make_enpassant&#40;28, 21&#41;;
    move_info_c * current = move_list;
    int move = current->move, value = 0, temp = 0;

    if &#40;value < 0&#41; current->value = value;
    else if &#40;move_is_capture&#40;move&#41;) &#123;
      temp = 50000 + piece_value_midgame&#40;move_piece_captured&#40;move&#41;) - move_piece&#40;move&#41;;
      current->value = temp;
    &#125;
    else current->value = 0;

    printf_s&#40;"value...........%d\n", current->value&#41;;
    printf_s&#40;"temp............%d\n", temp&#41;;
  &#125;
&#125;

int main&#40;) &#123;
  initialize&#40;);
  sort_c s;
  return 0;
&#125;
This code produces the error, too. And I cannot see any problems in the code.

Fritz
Last edited by LoopList on Wed Jun 30, 2010 3:19 pm, edited 1 time in total.
svchbe

Re: Compiler Problem

Post by svchbe »

I couldn't really pinpoint the problem, but their seems to be something wrong with inlining in case of:

int value;
a(b((c(value)!=0)||d(value)));
//function calls indicat inlined functions

if you place some printf_s it does return the rightvalue, because the compiler doesn't inline the whole expression if you do something like this:

printf(b((c(value)!=0)||d(value)));
a(b((c(value)!=0)||d(value)));

the compiler does something like:

temp=b((c(value)!=0)||d(value));
printf(temp);
a(temp);

or something else with only a small part inlined in which case the bug doesn't trigger.
It's oversimplified, anyway their is something getting mixed up inlining these boolean expressions and the recursive inlining happening here.
wgarvin
Posts: 838
Joined: Thu Jul 05, 2007 5:03 pm
Location: British Columbia, Canada

Re: Compiler Problem

Post by wgarvin »

LoopList wrote:
Gian-Carlo Pascutto wrote: If you're unlucky, the printfs make the problem go away :-P

Without doing this exercise, it's going to be hard to be absolutely sure whether the problem is compiler or code.
Thats the point. By implementing further printfs() the problem goes away. And thats the reason I don't understand whats going on?

Perhaps someone with more experience in Assembler can give me the reason for this annoying behaviour.

Fritz
Could you post the complete disassembly of the buggy-compiled program ? Asm-with-source or something ? Maybe someone will be able to spot the cause that way.

[Edit: I mean a disassembly of the shortened program in your post at Jun 30 8:04 am, not the real engine.]
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Compiler Problem

Post by bob »

LoopList wrote:
Gian-Carlo Pascutto wrote:
LoopList wrote: Did you really have a close look at the above code?
Yes, I don't see anything wrong, except for the prototype that is incorrect, but that can't cause the problem because this is C++ code and the function will simply get overloaded.
There is nothing more to narrow, I suppose.
You don't seem to have understood what I said. You have 2 compiles of the code, one giving a correct result, one giving a wrong one. The wrong result doesn't pop out magically, it exists because one or multiple statement are giving a wrong result. You want to find this single statement, which makes it obvious what the bug is (code or compiler). If you want to, you can even look at the generated assembler at that point and identify what's wrong.

To find the place where the right and wrong version diverge, you want to look at the intermediate results in the computation. Normally you'd do this with a debugger, but given that the problem only occurs in release mode with heavy optimizations, the alternative is to plaster printfs over all the intermediate computations and then look where they give a different result.

If you're unlucky, the printfs make the problem go away :-P

Without doing this exercise, it's going to be hard to be absolutely sure whether the problem is compiler or code.
Thats the point. By implementing further printfs() the problem goes away. And thats the reason I don't understand whats going on?

Perhaps someone with more experience in Assembler can give me the reason for this annoying behaviour.

Fritz
That begins to sound like either a variable that is uninitialized, or a local array subscript that goes out of bounds. If a printf fixes the problem, the only change a printf has is that it will alter the stack since it is a library call. And altering the stack can change a value you might get on a bad array index.

Rather than outright printf's, you might just stuff the value you would print into a global (not local) array, and then dump the array after the computation is finished, that way you avoid changing the stack contents during execution.
LoopList

Re: Compiler Problem

Post by LoopList »

bob wrote:
LoopList wrote:
Gian-Carlo Pascutto wrote:
LoopList wrote: Did you really have a close look at the above code?
Yes, I don't see anything wrong, except for the prototype that is incorrect, but that can't cause the problem because this is C++ code and the function will simply get overloaded.
There is nothing more to narrow, I suppose.
You don't seem to have understood what I said. You have 2 compiles of the code, one giving a correct result, one giving a wrong one. The wrong result doesn't pop out magically, it exists because one or multiple statement are giving a wrong result. You want to find this single statement, which makes it obvious what the bug is (code or compiler). If you want to, you can even look at the generated assembler at that point and identify what's wrong.

To find the place where the right and wrong version diverge, you want to look at the intermediate results in the computation. Normally you'd do this with a debugger, but given that the problem only occurs in release mode with heavy optimizations, the alternative is to plaster printfs over all the intermediate computations and then look where they give a different result.

If you're unlucky, the printfs make the problem go away :-P

Without doing this exercise, it's going to be hard to be absolutely sure whether the problem is compiler or code.
Thats the point. By implementing further printfs() the problem goes away. And thats the reason I don't understand whats going on?

Perhaps someone with more experience in Assembler can give me the reason for this annoying behaviour.

Fritz
That begins to sound like either a variable that is uninitialized, or a local array subscript that goes out of bounds. If a printf fixes the problem, the only change a printf has is that it will alter the stack since it is a library call. And altering the stack can change a value you might get on a bad array index.

Rather than outright printf's, you might just stuff the value you would print into a global (not local) array, and then dump the array after the computation is finished, that way you avoid changing the stack contents during execution.
Hi Robert!

We cannot find uninitialized variables or array-access that goes out of bounds. Some people in a MS forum suppose a compiler bug.

In which line of the following code do you see the problem or bug? I simplified the code a bit.

Code: Select all

#include <stdio.h> 

const int IS_ENPASSANT = 1 << 15; 

struct move_info_c &#123; int move, value; &#125;; 
struct board_c &#123; int piece_on&#91;64&#93;; &#125; B; 

inline int move_to&#40;int move&#41; &#123; return move & 63; &#125; 
inline int move_from&#40;int move&#41; &#123; return &#40;move >> 6&#41; & 63; &#125; 
inline int move_is_enpassant&#40;int move&#41; &#123; return &#40;move & IS_ENPASSANT&#41; != 0; &#125; 
inline int make_enpassant&#40;int from, int to&#41; &#123; return to | &#40;from << 6&#41; | IS_ENPASSANT; &#125; 
inline int piece_on_square&#40;int square&#41; &#123; return B.piece_on&#91;square&#93;; &#125; 
inline int move_is_capture&#40;int move&#41; &#123; return &#40;piece_on_square&#40;move_to&#40;move&#41;) != 6&#41; || move_is_enpassant&#40;move&#41;; &#125; 
inline int move_piece&#40;int move&#41; &#123; return piece_on_square&#40;move_from&#40;move&#41;); &#125; 
inline int move_piece_captured&#40;int move&#41; &#123; return move_is_enpassant&#40;move&#41; ? 0 &#58; piece_on_square&#40;move_to&#40;move&#41;); &#125; 

inline int piece_value_midgame&#40;int piece&#41; &#123; 
    int piece_value_mg&#91;7&#93; = &#123;100, 300, 400, 500, 900, 1000, 0&#125;; 
    return piece_value_mg&#91;piece&#93;; 
&#125; 

void initialize&#40;) &#123; 
    for &#40;int square = 0; square < 64; square++) B.piece_on&#91;square&#93; = 6; 
    B.piece_on&#91;28&#93; = B.piece_on&#91;29&#93; = 0; 
&#125; 

class sort_c &#123; 
public&#58; 
    sort_c&#40;); 
    move_info_c * last_move, move_list&#91;256&#93;; 
&#125;; 

sort_c&#58;&#58;sort_c&#40;) &#123; 
    move_list&#91;0&#93;.move = make_enpassant&#40;28, 21&#41;; 
    move_info_c * current = move_list; 
    int move = current->move, value = 0, temp = 0; 

    if &#40;value < 0&#41; current->value = value; 
    else if &#40;move_is_capture&#40;move&#41;) &#123; 
      temp = 50000 + piece_value_midgame&#40;move_piece_captured&#40;move&#41;) - move_piece&#40;move&#41;; 
      current->value = temp; 
    &#125; 
    else current->value = 0; 

    printf_s&#40;"value...........%d\n", current->value&#41;; 
    printf_s&#40;"temp............%d\n", temp&#41;; 
&#125; 

int main&#40;) &#123; 
  initialize&#40;); 
  sort_c s; 
  return 0; 
&#125; 
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Compiler Problem

Post by bob »

LoopList wrote:
bob wrote:
LoopList wrote:
Gian-Carlo Pascutto wrote:
LoopList wrote: Did you really have a close look at the above code?
Yes, I don't see anything wrong, except for the prototype that is incorrect, but that can't cause the problem because this is C++ code and the function will simply get overloaded.
There is nothing more to narrow, I suppose.
You don't seem to have understood what I said. You have 2 compiles of the code, one giving a correct result, one giving a wrong one. The wrong result doesn't pop out magically, it exists because one or multiple statement are giving a wrong result. You want to find this single statement, which makes it obvious what the bug is (code or compiler). If you want to, you can even look at the generated assembler at that point and identify what's wrong.

To find the place where the right and wrong version diverge, you want to look at the intermediate results in the computation. Normally you'd do this with a debugger, but given that the problem only occurs in release mode with heavy optimizations, the alternative is to plaster printfs over all the intermediate computations and then look where they give a different result.

If you're unlucky, the printfs make the problem go away :-P

Without doing this exercise, it's going to be hard to be absolutely sure whether the problem is compiler or code.
Thats the point. By implementing further printfs() the problem goes away. And thats the reason I don't understand whats going on?

Perhaps someone with more experience in Assembler can give me the reason for this annoying behaviour.

Fritz
That begins to sound like either a variable that is uninitialized, or a local array subscript that goes out of bounds. If a printf fixes the problem, the only change a printf has is that it will alter the stack since it is a library call. And altering the stack can change a value you might get on a bad array index.

Rather than outright printf's, you might just stuff the value you would print into a global (not local) array, and then dump the array after the computation is finished, that way you avoid changing the stack contents during execution.
Hi Robert!

We cannot find uninitialized variables or array-access that goes out of bounds. Some people in a MS forum suppose a compiler bug.

In which line of the following code do you see the problem or bug? I simplified the code a bit.

Code: Select all

#include <stdio.h> 

const int IS_ENPASSANT = 1 << 15; 

struct move_info_c &#123; int move, value; &#125;; 
struct board_c &#123; int piece_on&#91;64&#93;; &#125; B; 

inline int move_to&#40;int move&#41; &#123; return move & 63; &#125; 
inline int move_from&#40;int move&#41; &#123; return &#40;move >> 6&#41; & 63; &#125; 
inline int move_is_enpassant&#40;int move&#41; &#123; return &#40;move & IS_ENPASSANT&#41; != 0; &#125; 
inline int make_enpassant&#40;int from, int to&#41; &#123; return to | &#40;from << 6&#41; | IS_ENPASSANT; &#125; 
inline int piece_on_square&#40;int square&#41; &#123; return B.piece_on&#91;square&#93;; &#125; 
inline int move_is_capture&#40;int move&#41; &#123; return &#40;piece_on_square&#40;move_to&#40;move&#41;) != 6&#41; || move_is_enpassant&#40;move&#41;; &#125; 
inline int move_piece&#40;int move&#41; &#123; return piece_on_square&#40;move_from&#40;move&#41;); &#125; 
inline int move_piece_captured&#40;int move&#41; &#123; return move_is_enpassant&#40;move&#41; ? 0 &#58; piece_on_square&#40;move_to&#40;move&#41;); &#125; 

inline int piece_value_midgame&#40;int piece&#41; &#123; 
    int piece_value_mg&#91;7&#93; = &#123;100, 300, 400, 500, 900, 1000, 0&#125;; 
    return piece_value_mg&#91;piece&#93;; 
&#125; 

void initialize&#40;) &#123; 
    for &#40;int square = 0; square < 64; square++) B.piece_on&#91;square&#93; = 6; 
    B.piece_on&#91;28&#93; = B.piece_on&#91;29&#93; = 0; 
&#125; 

class sort_c &#123; 
public&#58; 
    sort_c&#40;); 
    move_info_c * last_move, move_list&#91;256&#93;; 
&#125;; 

sort_c&#58;&#58;sort_c&#40;) &#123; 
    move_list&#91;0&#93;.move = make_enpassant&#40;28, 21&#41;; 
    move_info_c * current = move_list; 
    int move = current->move, value = 0, temp = 0; 

    if &#40;value < 0&#41; current->value = value; 
    else if &#40;move_is_capture&#40;move&#41;) &#123; 
      temp = 50000 + piece_value_midgame&#40;move_piece_captured&#40;move&#41;) - move_piece&#40;move&#41;; 
      current->value = temp; 
    &#125; 
    else current->value = 0; 

    printf_s&#40;"value...........%d\n", current->value&#41;; 
    printf_s&#40;"temp............%d\n", temp&#41;; 
&#125; 

int main&#40;) &#123; 
  initialize&#40;); 
  sort_c s; 
  return 0; 
&#125; 
Nothing obvious stands out. And it _could_ be a compiler bug that incorrectly addresses the stack. But any time you can "fix" a problem simply by inserting a printf(), or if inserting the printf() changes the behaviour even if it doesn't fix it, the most likely culprit is the stack, which contains all local data. Whether your code is accessing it incorrectly or the compiler is causing the issue is not clear since I can't make it fail here using either gcc or icc...
Mincho Georgiev
Posts: 454
Joined: Sat Apr 04, 2009 6:44 pm
Location: Bulgaria

Re: Compiler Problem

Post by Mincho Georgiev »

If the class sort_c s; was initialized globally, the issue would most likely be gone. I've seen the same behavior with exact same compiler version and /O2 flag. In my case was improper preserving of the registers inside a block. Here the case might be different, but just on first sight it looks the same. Probably it is a compiler bug after all.