Bug 34992 - compiler produces wrong code when optimizing
Summary: compiler produces wrong code when optimizing
Status: RESOLVED DUPLICATE of bug 323
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.2.3
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
Depends on:
Reported: 2008-01-27 22:48 UTC by axel
Modified: 2008-01-28 10:00 UTC (History)
55 users (show)

See Also:
Host: i686-pc-linux-gnu
Target: i686-pc-linux-gnu
Build: i686-pc-linux-gnu
Known to work:
Known to fail:
Last reconfirmed:

source file for reproducing the problem. (122.53 KB, text/plain)
2008-01-27 22:55 UTC, axel
script to compile the source and reproduce the problem (242 bytes, text/plain)
2008-01-27 22:57 UTC, axel

Note You need to log in before you can comment on or make changes to this bug.
Description axel 2008-01-27 22:48:22 UTC

for some time now I had problems with one of my projects with compilers gcc 4.2.1 and above. For obscure reasons my testsuite did not run correctly when I did compile with optimization enabled. I now tracked the problem down
to a very strange bug that I can reproduce with a test case that I will 
attach. The problem I encounter is the fact that inserting duplicated values into a std::set will end up with a set holding these values more than once.
This happens only with optimization enabled.

I was able to prevent the problem in the test case by means of just
moving the function that would create the error further away from
the position where the function is called. In the test case the offset is created by means of another function that is not used, and that can be removed from the object file by means of compiler macros. 

If the unused function is part of the object file, then the std::set manipulation runs fine, if the function is disabled and removed from the object file the manipulation of the std::set fails. The function is inserted into the object file by means of defining the precompiler macro MAKEOFFSET.

Kind regards,
Comment 1 axel 2008-01-27 22:55:33 UTC
Created attachment 15034 [details]
source file for reproducing the problem.
Comment 2 axel 2008-01-27 22:57:02 UTC
Created attachment 15035 [details]
script to compile the source and reproduce the problem
Comment 3 Andrew Pinski 2008-01-27 22:58:21 UTC
Since you are doing some <= for fp, does -ffloat-store help?
Comment 4 axel 2008-01-27 23:05:05 UTC
yes indeed, that fixes the problem.
now, does that mean holding double values in a set 
is not possible?
Comment 5 Andrew Pinski 2008-01-27 23:17:32 UTC
Even though  -mfpmath=sse is used, x87 is used in some cases still and what you are seeing is an effect of PR 323.  Closing as a duplicate.  You should be more careful with your comparison loop of FP values.

*** This bug has been marked as a duplicate of 323 ***
Comment 6 axel 2008-01-28 00:14:29 UTC

while -ffloat-store fixes the problem, this solution is obviously not acceptable. Moreover, here the problem is not that I compare floats 
using <= the problem is that std::set<double>::insert(double) compares
set elements using std::less<double> which in this case just does not work. 

Now using std::less<double> for a set does not seem not carefull
to me, be cause this is the default. So the default is nonsense ?

I fixed the problem by means of using  std::set<double,dless>
with dless being

struct dless{
  typedef double first_argument_type;
  typedef double second_argument_type;
  typedef bool result_type;
  volatile double d1;
  volatile double d2;
  bool operator()(double in1, double in2) {
    d1 = in1;
    d2 = in2;
    return d1 < d2;

which proves that the problem is in the std::less operator
and not in my code. In fact this even means that 
std::less<double> and std::greater<double> and all 
their company is useless because you can never be sure what they 
are comparing. So many of the functions of the std::library
may fail!! Am I wrong, here ? 

Comment 7 Andrew Pinski 2008-01-28 01:18:28 UTC
(In reply to comment #6)
> Am I wrong, here ? 

Semi, what is happening is the values for std::less<double> is being stored in the fpr register and that is really a 80bit register and not a 64bit fp register.  -mpc64 is another "fix" for the issue, but that only exists on the trunk.
Comment 8 axel 2008-01-28 10:00:02 UTC
For completeness :
I now use this function that was proposed in 
PR 323. It seems to solve my issue. Thanks for the pointer!

  void set_math_double_precision() {
    fpu_control_t fpu_control ;
    fpu_control = (fpu_control & ~_FPU_EXTENDED) | _FPU_DOUBLE;