compiler dependent scores!

Discussion of chess software programming and technical issues.

Moderator: Ras

gladius
Posts: 568
Joined: Tue Dec 12, 2006 10:10 am
Full name: Gary Linscott

Re: getting VERY weird

Post by gladius »

Looks like an optimizer bug. I wonder if it's trying to lift the if (c-(t*8) < 0) condition out of the loop and failing. Could you post the generated asm for the busted version?

Just for curiousity, I wonder what happens if you set "Bitmap b=1ULL;".
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: A complete and broken program

Post by bob »

jswaff wrote:A complete program demonstrating this problem is below. This problem occurs with Intel's compiler at -O2 (strangely this is working at -O1 where -O1 it didn't in Prophet). This is on a 32 bit machine (the original problem in Prophet was on a 64 bit machine).

With the printf commented out:

Code: Select all

00000000
00000000
00000000
00001000
00000000
00000000
00000000
00000000
With it in:

Code: Select all

considering: 1
considering: 2
considering: 3
considering: 4
considering: 5
00001000
00001000
00001000
00001000
00000000
00000000
00000000
00000000

Code: Select all

#include <stdio.h>

enum SQUARES { A8,B8,C8,D8,E8,F8,G8,H8,
               A7,B7,C7,D7,E7,F7,G7,H7,
               A6,B6,C6,D6,E6,F6,G6,H6,
               A5,B5,C5,D5,E5,F5,G5,H5,
               A4,B4,C4,D4,E4,F4,G4,H4,
               A3,B3,C3,D3,E3,F3,G3,H3,
               A2,B2,C2,D2,E2,F2,G2,H2,
               A1,B1,C1,D1,E1,F1,G1,H1,
               NO_SQUARE };

typedef unsigned long long Bitmap;
Bitmap bm_mask[64];
Bitmap to_boundary[64];


void DrawBitmap(Bitmap bmap) {
        for (int c=0;c<64;c++) {
                if (bmap&bm_mask[c]) printf("1"); else printf("0");
                if ((c%8)==7) printf("\n");
        }
        printf("\n");
}

void Initialize() {

        Bitmap b=1;
        for (int c=0;c<64;c++)
                bm_mask[c]=(b<<c);


        for (int c=0;c<64;c++) {
                to_boundary[c]=0;
                for (int t=1;t<8;t++) {
//                      if (c==E4) printf("considering: %d\n",t);
                        if (c-(t*8)<0) break;
                        to_boundary[c]|=bm_mask[c-(t*8)];
                }
        }

        DrawBitmap(to_boundary[E4]);

}

int main(int argc,char *argv[]) {
        Initialize();
        return 0;
}
I ran this on a 32 bit machine using latest intel C++ compiler. I get this:
crafty% ./bug
00001000
00001000
00001000
00001000
00000000
00000000
00000000
00000000

crafty% ./bug
considering: 1
considering: 2
considering: 3
considering: 4
considering: 5
00001000
00001000
00001000
00001000
00000000
00000000
00000000
00000000



I will note that intel C does not like the for (int i=0; ...) type declaration, so I just declared c and t as int at the top of the procedure(s) where they are used. Seems to work as expected here with that one change... whether I use -O, -O2 or -O3 has no effect on the output...

you are not doing any overclocking or anything like that I assume???
jswaff

Re: A complete and broken program

Post by jswaff »

I actually compiled it as a C++ program, so the for (int c=0 ... is legal there.
But I just compiled it as a C program and it's the same problem.

And no, I'm not overclocking. Remember I've reproduced this on two machines, both using icc 10.0.026 on Gentoo Linux. (one 32 bit and the other 64 bit)

I'm going to dig into the assembly, but I don't have time to do it tonight.

--
James
jswaff

Re: getting VERY weird

Post by jswaff »

Michael Sherwin wrote:Have you verified that bm_mask[] is correct at the different levels of optimization?

Code: Select all

DrawBitmap(bm_mask[E5]);
DrawBitmap(bm_mask[E6]);
DrawBitmap(bm_mask[E7]);
DrawBitmap(bm_mask[E8]);
produces...

Code: Select all

00000000
00000000
00000000
00001000
00000000
00000000
00000000
00000000

00000000
00000000
00001000
00000000
00000000
00000000
00000000
00000000

00000000
00001000
00000000
00000000
00000000
00000000
00000000
00000000

00001000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
Using -O2.
jswaff

Re: getting VERY weird

Post by jswaff »

gladius wrote:Looks like an optimizer bug. I wonder if it's trying to lift the if (c-(t*8) < 0) condition out of the loop and failing. Could you post the generated asm for the busted version?

Just for curiousity, I wonder what happens if you set "Bitmap b=1ULL;".
I tried 1ULL, and it had no effect. I'll definitely look at the assembly, probably tomorrow. I'll post again after I've had a look at it. It's hard to see how this is not a compiler bug though.

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

Re: A complete and broken program

Post by Gerd Isenberg »

jswaff wrote:

Code: Select all

        for (int c=0;c<64;c++) {
                to_boundary[c]=0;
                for (int t=1;t<8;t++) {
//                      if (c==E4) printf("considering: %d\n",t);
                        if (c-(t*8)<0) break;
                        to_boundary[c]|=bm_mask[c-(t*8)];
                }
        }
Just another try to avoid redundant repeat/break condition of the inner loop as a source of possible compiler confusion...

Code: Select all

   
   for (int c=0; c<64; c++) {
      to_boundary[c]=0;
      for (int t=8; t <= c; t += 8) {
         // if (c==E4) printf("considering: %d\n",t>>3);
         to_boundary[c] |= bm_mask[c-t];
      }
   }
I regocnized your big-endian rank mapping, thus the initialization code I posted before has to be adapted, since it relies on a1 == 0.
Harald Johnsen

Re: A complete and broken program

Post by Harald Johnsen »

Code: Select all

...
void Initialize() {

        Bitmap b=1;
        for (int c=0;c<64;c++)
                bm_mask[c]=(b<<c);


        for (int c=0;c<64;c++) {
                to_boundary[c]=0;
                for (int t=1;t<8;t++) {
                        if (!(c-(t*8)<0))
                                to_boundary[c]|=bm_mask[c-(t*8)];
                }
        }

        DrawBitmap(to_boundary[E4]);

}
Don't do a break in the loop, the compiler does not execute the loop in the order you think (ie 1 to 8).

HJ.
Tony

Re: A complete and broken program

Post by Tony »

Harald Johnsen wrote:

Code: Select all

...
void Initialize() {

        Bitmap b=1;
        for (int c=0;c<64;c++)
                bm_mask[c]=(b<<c);


        for (int c=0;c<64;c++) {
                to_boundary[c]=0;
                for (int t=1;t<8;t++) {
                        if (!(c-(t*8)<0))
                                to_boundary[c]|=bm_mask[c-(t*8)];
                }
        }

        DrawBitmap(to_boundary[E4]);

}
Don't do a break in the loop, the compiler does not execute the loop in the order you think (ie 1 to 8).

HJ.
Yes, iirc it's the combination of declaring the same loop variable twice wich will cause the compiler to combine them and a break in one of them, wich the compiler doesn't notice and still combines.


I had it in my initialisation code a bunch of

Code: Select all

for (int sq=0;(sq & 0x88)==0;sq++)
{
   ...
}

It went ok after removing the locals and declaring int sq global.

Tony
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: A complete and broken program

Post by bob »

jswaff wrote:I actually compiled it as a C++ program, so the for (int c=0 ... is legal there.
But I just compiled it as a C program and it's the same problem.

And no, I'm not overclocking. Remember I've reproduced this on two machines, both using icc 10.0.026 on Gentoo Linux. (one 32 bit and the other 64 bit)

I'm going to dig into the assembly, but I don't have time to do it tonight.

--
James
I am using 10.1.008 here
jswaff

Re: A complete and broken program

Post by jswaff »

Harald Johnsen wrote: Don't do a break in the loop, the compiler does not execute the loop in the order you think (ie 1 to 8).

HJ.
Shouldn't it though? The for-loop SHOULD be a sequential construct. If the compiler is optimizing in a way that isn't sequentially consistent with the unoptimized version, then that's a bug.

--
James