public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* g++-4.0.3: program output is different when compiled with -O3 (did  not happen with gcc-3.4.5)
@ 2006-05-14 13:21 Erik
  2006-05-15 11:21 ` John Love-Jensen
  2006-05-16 14:49 ` Peter Doerfler
  0 siblings, 2 replies; 9+ messages in thread
From: Erik @ 2006-05-14 13:21 UTC (permalink / raw)
  To: gcc-help

I just installed g++-4.0.3 on a Pentium Mobile. I have a program that 
behaves as expected when compiled with -O0 but gives different output 
when compiled with -O3. I do not know what to do about it. The program 
is called prov. Here is the result of compiling and running it:
$ g++-4.0.3 -O0 -Wall -o prov prov.cc -I/usr/include/SDL && ./prov; echo $?
1
$ g++-4.0.3 -O3 -Wall -o prov prov.cc -I/usr/include/SDL && ./prov; echo $?
0

The program looks like this:
______________________________________________________
#include <SDL_types.h>
struct Coords {
    bool operator<(const Coords other) const {
        return
            *reinterpret_cast<const Uint32 * const>(this)
            <
            *reinterpret_cast<const Uint32 * const>(&other);
    }
   
    int x : 16, y : 16;
};
int main() {
    Coords a = {0, 1}, b = {1, 0};
    return b < a and a < b;
}
______________________________________________________


The operator< is for use with standard containers, so it has to work. It 
should of course never happen that b is less than a and a is less than 
b, so the program should always return 0. I can see that the assembly 
output is very different, but I admitt that I do not understand much of 
it. With g++-3.4.5 the program produces identical output for the 
different optimization levels.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: g++-4.0.3: program output is different when compiled with -O3  (did  not happen with gcc-3.4.5)
  2006-05-14 13:21 g++-4.0.3: program output is different when compiled with -O3 (did not happen with gcc-3.4.5) Erik
@ 2006-05-15 11:21 ` John Love-Jensen
  2006-05-16 14:49 ` Peter Doerfler
  1 sibling, 0 replies; 9+ messages in thread
From: John Love-Jensen @ 2006-05-15 11:21 UTC (permalink / raw)
  To: Erik, MSX to GCC

Hi Erik,

I think you just need to rework your operator< a little bit, and you'll be
fine.

struct Coords {
  bool operator<(const Coords other) const {
    Uint32 lhs = (Uint32(x) << 16) | Uint32(y);
    Uint32 rhs = (Uint32(other.x) << 16) | Uint32(other.y);
    return lhs < rhs;
  }
   
  int x : 16, y : 16;
};

HTH.
--Eljay

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: g++-4.0.3: program output is different when compiled with -O3  (did  not happen with gcc-3.4.5)
  2006-05-14 13:21 g++-4.0.3: program output is different when compiled with -O3 (did not happen with gcc-3.4.5) Erik
  2006-05-15 11:21 ` John Love-Jensen
@ 2006-05-16 14:49 ` Peter Doerfler
  2006-05-16 17:33   ` Erik
  1 sibling, 1 reply; 9+ messages in thread
From: Peter Doerfler @ 2006-05-16 14:49 UTC (permalink / raw)
  To: Erik; +Cc: gcc-help

Erik wrote:
> I just installed g++-4.0.3 on a Pentium Mobile. I have a program that 
> behaves as expected when compiled with -O0 but gives different output 
> when compiled with -O3. I do not know what to do about it. The program 
> is called prov. Here is the result of compiling and running it:
> $ g++-4.0.3 -O0 -Wall -o prov prov.cc -I/usr/include/SDL && ./prov; echo $?
> 1
> $ g++-4.0.3 -O3 -Wall -o prov prov.cc -I/usr/include/SDL && ./prov; echo $?
> 0
> 
> The program looks like this:
> ______________________________________________________
> #include <SDL_types.h>
> struct Coords {
>    bool operator<(const Coords other) const {
>        return
>            *reinterpret_cast<const Uint32 * const>(this)
>            <
>            *reinterpret_cast<const Uint32 * const>(&other);
>    }
>      int x : 16, y : 16;
> };
> int main() {
>    Coords a = {0, 1}, b = {1, 0};
>    return b < a and a < b;
> }
> ______________________________________________________
> 
> 
> The operator< is for use with standard containers, so it has to work. It 
> should of course never happen that b is less than a and a is less than 
> b, so the program should always return 0. I can see that the assembly 
> output is very different, but I admitt that I do not understand much of 
> it. With g++-3.4.5 the program produces identical output for the 
> different optimization levels.

Why don't you use an anonymous union, like so?

struct Coords {

   bool operator<(const Coords other) const;

   union {
     struct {
       int x : 16, y : 16;
     };

     unsigned int z;
   };
};

bool Coords::operator<(const Coords other) const {
   return z < other.z;
}


HTH, Peter

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: g++-4.0.3: program output is different when compiled with -O3  (did  not happen with gcc-3.4.5)
  2006-05-16 14:49 ` Peter Doerfler
@ 2006-05-16 17:33   ` Erik
  2006-05-17 12:38     ` Peter Doerfler
  0 siblings, 1 reply; 9+ messages in thread
From: Erik @ 2006-05-16 17:33 UTC (permalink / raw)
  To: Peter Doerfler; +Cc: gcc-help

Peter Doerfler wrote:

> Erik wrote:
>
>> I just installed g++-4.0.3 on a Pentium Mobile. I have a program that 
>> behaves as expected when compiled with -O0 but gives different output 
>> when compiled with -O3. I do not know what to do about it. The 
>> program is called prov. Here is the result of compiling and running it:
>> $ g++-4.0.3 -O0 -Wall -o prov prov.cc -I/usr/include/SDL && ./prov; 
>> echo $?
>> 1
>> $ g++-4.0.3 -O3 -Wall -o prov prov.cc -I/usr/include/SDL && ./prov; 
>> echo $?
>> 0
>>
>> The program looks like this:
>> ______________________________________________________
>> #include <SDL_types.h>
>> struct Coords {
>>    bool operator<(const Coords other) const {
>>        return
>>            *reinterpret_cast<const Uint32 * const>(this)
>>            <
>>            *reinterpret_cast<const Uint32 * const>(&other);
>>    }
>>      int x : 16, y : 16;
>> };
>> int main() {
>>    Coords a = {0, 1}, b = {1, 0};
>>    return b < a and a < b;
>> }
>> ______________________________________________________
>>
>>
>> The operator< is for use with standard containers, so it has to work. 
>> It should of course never happen that b is less than a and a is less 
>> than b, so the program should always return 0. I can see that the 
>> assembly output is very different, but I admitt that I do not 
>> understand much of it. With g++-3.4.5 the program produces identical 
>> output for the different optimization levels.
>
>
> Why don't you use an anonymous union, like so?

This is exactly what I was looking for. It seems to work great. Many 
thanks! Why did I not use it? I was just not smart enough.  I tried to 
use a union like

union T {
   Coords c;
   Uint32 i;
};

in the ordering functor, but I had to ditch that idea because it was not 
allowed to have a type with constructor in a union. (And Coords has a 
constructor, although it was omitted in the sample code here.)

> struct Coords {
>
>   bool operator<(const Coords other) const;
>
>   union {
>     struct {
>       int x : 16, y : 16;
>     };
>
>     unsigned int z;
>   };
> };
>
> bool Coords::operator<(const Coords other) const {
>   return z < other.z;
> }

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: g++-4.0.3: program output is different when compiled with -O3   (did  not happen with gcc-3.4.5)
  2006-05-16 17:33   ` Erik
@ 2006-05-17 12:38     ` Peter Doerfler
  2006-05-17 14:06       ` Peter Doerfler
  0 siblings, 1 reply; 9+ messages in thread
From: Peter Doerfler @ 2006-05-17 12:38 UTC (permalink / raw)
  To: Erik; +Cc: gcc-help

Erik wrote:
> Peter Doerfler wrote:
>> Why don't you use an anonymous union, like so?
> 
> This is exactly what I was looking for. It seems to work great. Many 
> thanks! Why did I not use it? I was just not smart enough.  I tried to 
> use a union like
> 
> union T {
>   Coords c;
>   Uint32 i;
> };
> 
> in the ordering functor, but I had to ditch that idea because it was not 
> allowed to have a type with constructor in a union. (And Coords has a 
> constructor, although it was omitted in the sample code here.)
> 
>> struct Coords {
>>
>>   bool operator<(const Coords other) const;
>>
>>   union {
>>     struct {
>>       int x : 16, y : 16;
>>     };
>>
>>     unsigned int z;
>>   };
>> };
>>
>> bool Coords::operator<(const Coords other) const {
>>   return z < other.z;
>> }

I just double checked with -Wall -Wextra -pedantic and it says
error: ISO C++ prohibits anonymous structs

which seemingly doesn't mean that it doesn't work. Something similar is 
in our production code. But the Standard is always right, so...

Here is a new version which has the advantage of hiding some 
implementation details. You lose the bitfield initialization though.
I'm not sure whether the compiler is required to keep struct bar members 
in a 32bit block now, I guess you need something like 
__attribute__(packed), but I have no idea about those. On the other hand 
the union should force this.
Maybe somebody can clarify although we're getting a bit off topic here.
Anyway this compiles without warnings under -Wall -Wextra -pedantic 
-ansi and Comeau++ is also happy.


class foo {
public:
   typedef unsigned short int16;

private:
   struct bar {
     int16 x;
     int16 y;
   };

   union {

     bar b;

     unsigned int z;
   };

public:
   foo() : x(b.x), y(b.y) {}
   foo(int16 xx, int16 yy) : x(b.x), y(b.y) {x=xx; y=yy;}

   bool operator<(const foo& other) {return z<other.z;}

   int16& x;
   int16& y;

};

int main () {

   foo f;
   f.x = 1; f.y=0;
   foo g(0,1);

   return f<g;
}


Best, Peter

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: g++-4.0.3: program output is different when compiled with -O3    (did  not happen with gcc-3.4.5)
  2006-05-17 12:38     ` Peter Doerfler
@ 2006-05-17 14:06       ` Peter Doerfler
  2006-05-17 16:10         ` Erik
  0 siblings, 1 reply; 9+ messages in thread
From: Peter Doerfler @ 2006-05-17 14:06 UTC (permalink / raw)
  To: Erik; +Cc: gcc-help

Peter Doerfler wrote:
> Erik wrote:
>> Peter Doerfler wrote:
>>> Why don't you use an anonymous union, like so?
>>
>> This is exactly what I was looking for. It seems to work great. Many 
>> thanks! Why did I not use it? I was just not smart enough.  I tried to 
>> use a union like
>>
>> union T {
>>   Coords c;
>>   Uint32 i;
>> };
>>
>> in the ordering functor, but I had to ditch that idea because it was 
>> not allowed to have a type with constructor in a union. (And Coords 
>> has a constructor, although it was omitted in the sample code here.)
>>
>>> struct Coords {
>>>
>>>   bool operator<(const Coords other) const;
>>>
>>>   union {
>>>     struct {
>>>       int x : 16, y : 16;
>>>     };
>>>
>>>     unsigned int z;
>>>   };
>>> };
>>>
>>> bool Coords::operator<(const Coords other) const {
>>>   return z < other.z;
>>> }
> 
> I just double checked with -Wall -Wextra -pedantic and it says
> error: ISO C++ prohibits anonymous structs
> 
> which seemingly doesn't mean that it doesn't work. Something similar is 
> in our production code. But the Standard is always right, so...
> 
> Here is a new version which has the advantage of hiding some 
> implementation details. You lose the bitfield initialization though.
> I'm not sure whether the compiler is required to keep struct bar members 
> in a 32bit block now, I guess you need something like 
> __attribute__(packed), but I have no idea about those. On the other hand 
> the union should force this.
> Maybe somebody can clarify although we're getting a bit off topic here.
> Anyway this compiles without warnings under -Wall -Wextra -pedantic 
> -ansi and Comeau++ is also happy.
> 
> 
> class foo {
> public:
>   typedef unsigned short int16;
> 
> private:
>   struct bar {
>     int16 x;
>     int16 y;
>   };
> 
>   union {
> 
>     bar b;
> 
>     unsigned int z;
>   };
> 
> public:
>   foo() : x(b.x), y(b.y) {}
>   foo(int16 xx, int16 yy) : x(b.x), y(b.y) {x=xx; y=yy;}
> 
>   bool operator<(const foo& other) {return z<other.z;}
> 
>   int16& x;
>   int16& y;
> 
> };
> 
> int main () {
> 
>   foo f;
>   f.x = 1; f.y=0;
>   foo g(0,1);
> 
>   return f<g;
> }
> 
> 
> Best, Peter

Never mind this approach. Now sizeof(foo) is 12 instead of 4 as it was 
before, which is probably not acceptable for most applications. I guess 
it's either compile without strict compliance or use the __extension__ 
workaround and make sure all the compilers you want to use on your code 
know what to do. Such a thing as an anonymous struct simply doesn't seem 
to exist in the Standard.

I guess further help should rather be sought at comp.lang.c++ etc.

Best, Peter

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: g++-4.0.3: program output is different when compiled with -O3     (did  not happen with gcc-3.4.5)
  2006-05-17 14:06       ` Peter Doerfler
@ 2006-05-17 16:10         ` Erik
  0 siblings, 0 replies; 9+ messages in thread
From: Erik @ 2006-05-17 16:10 UTC (permalink / raw)
  To: Peter Doerfler; +Cc: Erik, gcc-help

Peter Doerfler wrote:

> Never mind this approach. Now sizeof(foo) is 12 instead of 4 as it was 
> before, which is probably not acceptable for most applications. I 
> guess it's either compile without strict compliance or use the 
> __extension__ workaround and make sure all the compilers you want to 
> use on your code know what to do. Such a thing as an anonymous struct 
> simply doesn't seem to exist in the Standard.

The following seems to work with -Wextra -pedantic, although it uses 
accessors, which require a lot of changes to the code that uses Coords:
typedef signed short Sint16;
typedef unsigned int Uint32;
struct Coords {
    Coords(const int X, const int Y) {parts.x = X, parts.y = Y;}
    bool operator<(const Coords other) const {return all < other.all;}
    signed short int get_x() const {return parts.x;}
    signed short int get_y() const {return parts.y;}
    void set_x(const Sint16 X) {parts.x = X;}
    void set_y(const Sint16 Y) {parts.y = Y;}
    union {
        struct {Sint16 x, y;} parts;
        Uint32 all;
    };
};

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: g++-4.0.3: program output is different when compiled with -O3  (did  not happen with gcc-3.4.5)
  2006-05-16 12:02 ` Erik
@ 2006-05-16 12:20   ` John Love-Jensen
  0 siblings, 0 replies; 9+ messages in thread
From: John Love-Jensen @ 2006-05-16 12:20 UTC (permalink / raw)
  To: Erik, MSX to GCC

Hi Erik,

> The fast code works, but not with gcc-4.0, -O3 and strict aliasing.

The fast code is not compliant to the C or C++ standards.

Sincerely,
--Eljay

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: g++-4.0.3: program output is different when compiled with -O3  (did  not happen with gcc-3.4.5)
       [not found] <C08F1D26.10592%eljay@adobe.com>
@ 2006-05-16 12:02 ` Erik
  2006-05-16 12:20   ` John Love-Jensen
  0 siblings, 1 reply; 9+ messages in thread
From: Erik @ 2006-05-16 12:02 UTC (permalink / raw)
  To: John Love-Jensen, MSX to GCC

John Love-Jensen wrote:

>Well, I suppose it is a tradeoff between correct code that works-but-is-slow
>and incorrect code that is fast-and-doesn't-work.
>  
>
The fast code works, but not with gcc-4.0, -O3 and strict aliasing. 
Since there is a fast way to do it, and it works, it is a pity that it 
can not be easily used. Especially since it is such an easy problem; to 
create an ordering functor for a 32-bit type consisting of 2 16-bit types.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2006-05-17 16:10 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-05-14 13:21 g++-4.0.3: program output is different when compiled with -O3 (did not happen with gcc-3.4.5) Erik
2006-05-15 11:21 ` John Love-Jensen
2006-05-16 14:49 ` Peter Doerfler
2006-05-16 17:33   ` Erik
2006-05-17 12:38     ` Peter Doerfler
2006-05-17 14:06       ` Peter Doerfler
2006-05-17 16:10         ` Erik
     [not found] <C08F1D26.10592%eljay@adobe.com>
2006-05-16 12:02 ` Erik
2006-05-16 12:20   ` John Love-Jensen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).