This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

assignment problem with doubles: getting -NaN unexpectedly


Hi,

I have a problem with an assigment of one double variable to another,
like dub1 = dub2;
I'm getting -NaN in dub1, even if there is a valid value in dub2.

This is on RedHat Linux 6.0, kernel 2.2.5, glibc-2.1.1-6
C compiler is egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)
(not the newest, I know).
Also tried compiling the relevant file with egcs-1.1.2-24,
which did not help.

HW is 2 x Pentium II, FPU.

this is the compiler call:
cc -g -ansi -fwritable-strings -DLINUX -D_BSD_SOURCE -Wall
-Wno-parentheses -Wno-unused -Wno-return-type -Wno-implicit-int
rvaldata.c


Here is a gdb session that shows the difference between a working
and a non working case:
Breakpoint 2, todouble (val=0x1085e094) at rvaldata.c:1445
1445                dub = val->v_double;
(gdb) info registers
     eax:  0x80e3c70   135150704
     ecx: 0x10850003   277151747
     edx:  0x86a0003   141164547
     ebx: 0x1085e094   277209236
     esp: 0x1085d5d8   277206488
     ebp: 0x1085d61c   277206556
     esi: 0x108a8a88   277514888
     edi: 0x10803060   276836448
     eip:  0x80e3c70   135150704
  eflags:      0x297 IOPL: 0; flags: CF PF AF SF IF
orig_eax: 0xffffffff          -1
      cs:       0x23          35
      ss:       0x2b          43
      ds:       0x2b          43
      es:       0x2b          43
      fs:        0x0           0
      gs:        0x0           0
(gdb) info float
     st0: 0x40008000000000000000  Valid Normal 2
     st1: 0x4000c000000000000000  Valid Normal 3
     st2: 0x40008000000000000000  Valid Normal 2
     st3: 0x4000c000000000000000  Valid Normal 3
     st4: 0x40008000000000000000  Valid Normal 2
     st5: 0x4000c000000000000000  Valid Normal 3
     st6: 0x40008000000000000000  Valid Normal 2
     st7: 0x3fff8000000000000000  Empty Normal 1
   fctrl:     0x037f 64 bit; NEAR; mask INVAL DENOR DIVZ OVERF UNDER
LOS;
   fstat:     0x0863 flags 0000; top 1; excep INVAL DENOR LOS STACK
    ftag:     0x0003
     fip: 0x400154ae
     fcs: 0x05400023
  fopoff: 0x108a87a8
  fopsel:     0x002b
(gdb) disass 0x80e3c70 0x80e3c7b
Dump of assembler code from 0x80e3c70 to 0x80e3c7b:
0x80e3c70 <todouble+712>:       fldl   0xc(%ebx)
0x80e3c73 <todouble+715>:       fstpl  0xfffffff8(%ebp)
0x80e3c76 <todouble+718>:       jmp    0x80e3d13 <todouble+875>
End of assembler dump.
(gdb) p val->v_double
$1 = 2
(gdb) p &val->v_double
$2 = (double *) 0x1085e0a0
(gdb) x/2 &val->v_double
0x1085e0a0:     0x00000000      0x40000000
(gdb) stepi
0x80e3c73       1445                dub = val->v_double;
(gdb) info float
     st0: 0x40008000000000000000  Valid Normal 2
     st1: 0x40008000000000000000  Valid Normal 2
     st2: 0x4000c000000000000000  Valid Normal 3
     st3: 0x40008000000000000000  Valid Normal 2
     st4: 0x4000c000000000000000  Valid Normal 3
     st5: 0x40008000000000000000  Valid Normal 2
     st6: 0x4000c000000000000000  Valid Normal 3
     st7: 0x40008000000000000000  Valid Normal 2
   fctrl:     0x037f 64 bit; NEAR; mask INVAL DENOR DIVZ OVERF UNDER
LOS;
   fstat:     0x0063 flags 0000; top 0; excep INVAL DENOR LOS STACK
    ftag:     0x0000
     fip: 0x080e3c70
     fcs: 0x05430023
  fopoff: 0x1085e0a0
  fopsel:     0x002b
(gdb) stepi
1446                break;
(gdb) info float
     st0: 0x40008000000000000000  Valid Normal 2
     st1: 0x4000c000000000000000  Valid Normal 3
     st2: 0x40008000000000000000  Valid Normal 2
     st3: 0x4000c000000000000000  Valid Normal 3
     st4: 0x40008000000000000000  Valid Normal 2
     st5: 0x4000c000000000000000  Valid Normal 3
     st6: 0x40008000000000000000  Valid Normal 2
     st7: 0x40008000000000000000  Empty Normal 2
   fctrl:     0x037f 64 bit; NEAR; mask INVAL DENOR DIVZ OVERF UNDER
LOS;
   fstat:     0x0863 flags 0000; top 1; excep INVAL DENOR LOS STACK
    ftag:     0x0003
     fip: 0x080e3c73
     fcs: 0x055d0023
  fopoff: 0x1085d614
  fopsel:     0x002b
(gdb) print dub
$3 = 2
(gdb) p &dub
$4 = (double *) 0x1085d614
(gdb) x/2 &dub
0x1085d614:     0x00000000      0x40000000

The correct value was assigned.


Now the bad case:

(gdb) c
Continuing.

Breakpoint 2, todouble (val=0x1085e094) at rvaldata.c:1445
1445                dub = val->v_double;
(gdb) info registers
     eax:  0x80e3c70   135150704
     ecx: 0x10850003   277151747
     edx:  0x86a0003   141164547
     ebx: 0x1085e094   277209236
     esp: 0x1085d5d8   277206488
     ebp: 0x1085d61c   277206556
     esi: 0x108a8a88   277514888
     edi: 0x10803060   276836448
     eip:  0x80e3c70   135150704
  eflags:      0x297 IOPL: 0; flags: CF PF AF SF IF
orig_eax: 0xffffffff          -1
      cs:       0x23          35
      ss:       0x2b          43
      ds:       0x2b          43
      es:       0x2b          43
      fs:        0x0           0
      gs:        0x0           0
(gdb) info float
     st0: 0x4000c000000000000000  Valid Normal 3
     st1: 0x40008000000000000000  Valid Normal 2
     st2: 0x4000c000000000000000  Valid Normal 3
     st3: 0x40008000000000000000  Valid Normal 2
     st4: 0x4000c000000000000000  Valid Normal 3
     st5: 0x40008000000000000000  Valid Normal 2
     st6: 0x4000c000000000000000  Valid Normal 3
     st7: 0x40008000000000000000  Valid Normal 2
   fctrl:     0x037f 64 bit; NEAR; mask INVAL DENOR DIVZ OVERF UNDER
LOS;
   fstat:     0x0063 flags 0000; top 0; excep INVAL DENOR LOS STACK
    ftag:     0x0000
     fip: 0x400154ae
     fcs: 0x05400023
  fopoff: 0x108a87a8
  fopsel:     0x002b
(gdb) disass 0x80e3c70 0x80e3c7b
Dump of assembler code from 0x80e3c70 to 0x80e3c7b:
0x80e3c70 <todouble+712>:       fldl   0xc(%ebx)
0x80e3c73 <todouble+715>:       fstpl  0xfffffff8(%ebp)
0x80e3c76 <todouble+718>:       jmp    0x80e3d13 <todouble+875>
End of assembler dump.
(gdb) p val->v_val.vdub
$5 = 3
(gdb) p &val->v_val.vdub
$6 = (double *) 0x1085e0a0
(gdb) x/2 &val->v_val.vdub
0x1085e0a0:     0x00000000      0x40080000
(gdb) stepi
0x80e3c73       1445                dub = val->v_double;

The fldl machine instruction does not place the expected value into st0.

Is this because of some FPU flags?
This may be a compiler bug, but I don't know.
Now, I'm getting the unexpected value in st0:

(gdb) info float
     st0: 0xffffc000000000000000  Spec  QNaN   -NaN(0xc000000000000000)
     st1: 0x4000c000000000000000  Valid Normal 3
     st2: 0x40008000000000000000  Valid Normal 2
     st3: 0x4000c000000000000000  Valid Normal 3
     st4: 0x40008000000000000000  Valid Normal 2
     st5: 0x4000c000000000000000  Valid Normal 3
     st6: 0x40008000000000000000  Valid Normal 2
     st7: 0x4000c000000000000000  Valid Normal 3
   fctrl:     0x037f 64 bit; NEAR; mask INVAL DENOR DIVZ OVERF UNDER
LOS;
   fstat:     0x3a63 flags 0010; top 7; excep INVAL DENOR LOS STACK
    ftag:     0x8000
     fip: 0x080e3c70
     fcs: 0x05430023
  fopoff: 0x1085e0a0
  fopsel:     0x002b
(gdb) stepi
1446                break;
(gdb) info float
     st0: 0x4000c000000000000000  Valid Normal 3
     st1: 0x40008000000000000000  Valid Normal 2
     st2: 0x4000c000000000000000  Valid Normal 3
     st3: 0x40008000000000000000  Valid Normal 2
     st4: 0x4000c000000000000000  Valid Normal 3
     st5: 0x40008000000000000000  Valid Normal 2
     st6: 0x4000c000000000000000  Valid Normal 3
     st7: 0xffffc000000000000000  Empty QNaN   -NaN(0xc000000000000000)
   fctrl:     0x037f 64 bit; NEAR; mask INVAL DENOR DIVZ OVERF UNDER
LOS;
   fstat:     0x0063 flags 0000; top 0; excep INVAL DENOR LOS STACK
    ftag:     0xc000
     fip: 0x080e3c73
     fcs: 0x055d0023
  fopoff: 0x1085d614
  fopsel:     0x002b
(gdb) print dub
$7 = -NaN(0x8000000000000)
(gdb) p &dub
$8 = (double *) 0x1085d614
(gdb) x/2 &dub
0x1085d614:     0x00000000      0xfff80000


Are there any known compiler bugs causing this?

There are two scenarios which are reproducing this problem.
I did some code changes which did not help:
1. add -O or -O0, did not work
2. add register to the definition of the local variable:
   this solves the first scenario (!) but the second fails
3. add -mno-fp-ret-in-387 compiler switch, and compile the
   relevant file only.
   this solves the second scenario, but the first fails
4. add -mno-fp-ret-in-387 compiler switch, and compile all
   files of my lib this files belongs to:
   both scenarios fail !
5. substitute assignment by a memcpy()
   This helps directly for this function, but the problem
   occurs in the next assignment of a double value.
6. add -ffloat-store compiler switch, does not help


Pls reply to: kostner@informix.com.

Thanks in advance for your help,

  Karl Ostner




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]