Re: ==operator gives unexpected result using -O0

2005-07-28 Thread James E Wilson

Jakob Andreas Bærentzen wrote:
It seems to me that if a,b, and c are float or double values and if a has been 
assigned b*c then a == (b*c)
should return true since a should contain the same bitpattern as the temporary 
being assigned the value of b*c. Is it not so? 


This is the infamous x86 excess precision problem, which has been 
discussed in PR 323 and elsewhere.

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=323

The problem is that the x87 FP register stack has 80 bit registers. 
Doubles are 64-bits.  If you aren't careful (or if the compiler isn't), 
then you can end up comparing a full unrounded 80-bit value against a 
rounded 64-bit value, which will not be equal.  Thus the result that you 
are seeing.


There are various ways to work around this, but unfortunately, there is 
no good solution to the problem that makes everyone happy.  The hardware 
design and the linux ABI design makes it difficult for the compiler to 
both get the right answer and give good performance.  This problem has 
gone unsolved for well over a decade, and may never be solved.


This problem can be avoided by using SSE registers instead of the x87 FP 
register stack.  If you are running 64-bit linux on an AMD64/EM64T 
system, you won't have this problem, because they use the SSE registers 
by default.

--
Jim Wilson, GNU Tools Support, http://www.specifix.com


==operator gives unexpected result using -O0

2005-07-26 Thread Jakob Andreas Bærentzen
Hello,

I do apologize if my ignorance is the problem here, but I am having a strange 
problem with the version of gcc included in suse 9.3: gcc version 3.3.5 
20050117 (prerelease) (SUSE Linux). The same problem was observed with gcc 
3.3.1. I have not tried later versions, but I can't find the problem in 
bugzilla so I assume it is either so trivial that I should be ashamed or 
unknown. It is an intel XEON processor.

It seems to me that if a,b, and c are float or double values and if a has been 
assigned b*c

then

a == (b*c)

should return true since a should contain the same bitpattern as the temporary 
being assigned the value of b*c. Is it not so? 

Never the less, the following piece of code does not work as expected when 
compiling with -O0. It works FINE when compiling with -O1 or higher.

---
#include iostream

using namespace std;
int main()
{
double b = 9.5245435435564536; 
double c = 7.98786542345446565;
double a = b*c;

//Does not work.
cout  (a == (b*c))  endl;

// Works
double d = b*c;
cout  (a == d)  endl;
}
---

With O0 the output is 
0
1

With O1, O2 or O3 the output is
1
1

as one would expect.

I have made a similar program in C and I also changed double to float. It 
makes no difference. Nor does the actual float/double values. The 
optimization flag seems to decide what happens.

Any insight would be appreciated.

Andreas