* 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).