next bug

Ulrich Drepper drepper@cygnus.com
Sun Apr 26 21:33:00 GMT 1998


Here's the next bug which can be found by simply compiling glibc.  I
got several bugs in the math function test suite and maybe there is
more than one bug.  I chose the simplest function first and will see
whether this is the same problem as in the other tests.

The appended source is the nextafter function for double).  With the
2.91.24 compiler (from earlier this week) compiled the code to (this is only the beginning):

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00000000 <__nextafter>:
   0:   83 ec 24        subl   $0x24,%esp
   3:   55              pushl  %ebp
   4:   57              pushl  %edi
   5:   56              pushl  %esi
   6:   dd 44 24 34     fldl   0x34(%esp,1)
   a:   dd 44 24 3c     fldl   0x3c(%esp,1)
   e:   d9 c9           fxch   %st(1)
  10:   dd 54 24 0c     fstl   0xc(%esp,1)
  14:   d9 c9           fxch   %st(1)
  16:   8b 6c 24 10     movl   0x10(%esp,1),%ebp
  1a:   8b 4c 24 0c     movl   0xc(%esp,1),%ecx
  1e:   dd 54 24 0c     fstl   0xc(%esp,1)
  22:   8b 44 24 10     movl   0x10(%esp,1),%eax
  26:   89 44 24 2c     movl   %eax,0x2c(%esp,1)
  2a:   8b 44 24 0c     movl   0xc(%esp,1),%eax
  2e:   89 44 24 24     movl   %eax,0x24(%esp,1)
  32:   89 ea           movl   %ebp,%edx
  34:   81 e2 ff ff ff  andl   $0x7fffffff,%edx
  39:   7f 
  3a:   8b 44 24 2c     movl   0x2c(%esp,1),%eax
  3e:   25 ff ff ff 7f  andl   $0x7fffffff,%eax
  43:   89 44 24 28     movl   %eax,0x28(%esp,1)
  47:   81 fa ff ff ef  cmpl   $0x7fefffff,%edx
  4c:   7f 
  4d:   7e 0d           jle    5c <__nextafter+0x5c>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The current compiler (2.91.25, cvs update ran at about 14:00PDT, Sunday):

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00000000 <__nextafter>:
   0:   83 ec 24        subl   $0x24,%esp
   3:   55              pushl  %ebp
   4:   57              pushl  %edi
   5:   56              pushl  %esi
   6:   dd 44 24 34     fldl   0x34(%esp,1)
   a:   dd 44 24 3c     fldl   0x3c(%esp,1)
   e:   d9 c9           fxch   %st(1)
  10:   dd 54 24 0c     fstl   0xc(%esp,1)
  14:   d9 c9           fxch   %st(1)
  16:   8b 6c 24 10     movl   0x10(%esp,1),%ebp
  1a:   8b 4c 24 0c     movl   0xc(%esp,1),%ecx
  1e:   dd 54 24 0c     fstl   0xc(%esp,1)
  22:   89 e8           movl   %ebp,%eax
  24:   89 44 24 2c     movl   %eax,0x2c(%esp,1)
  28:   89 c8           movl   %ecx,%eax
  2a:   89 44 24 24     movl   %eax,0x24(%esp,1)
  2e:   89 ea           movl   %ebp,%edx
  30:   81 e2 ff ff ff  andl   $0x7fffffff,%edx
  35:   7f 
  36:   8b 44 24 2c     movl   0x2c(%esp,1),%eax
  3a:   25 ff ff ff 7f  andl   $0x7fffffff,%eax
  3f:   89 44 24 28     movl   %eax,0x28(%esp,1)
  43:   81 fa ff ff ef  cmpl   $0x7fefffff,%edx
  48:   7f 
  49:   7e 0d           jle    58 <__nextafter+0x58>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The problem in this piece of code is at address 22 in both cases.  In
the old version the instruction

	movl   0x10(%esp,1),%eax

gets the MSW from the floating point value it just stored (see the
instruction before).  The new egcs is somehow very confused since it
thinks the value is already in a register (%ebp) and therefore does
not load it anymore.

But this is of course very wrong since the value in %ebp is from the
other floating point value.  I.e., egcs thinks it has both values in
the integer registers but in fact it only has two copies of the first
floating point value in the registers.

-- Uli
---------------.      drepper at gnu.org  ,-.   1325 Chesapeake Terrace
Ulrich Drepper  \    ,-------------------'   \  Sunnyvale, CA 94089 USA
Cygnus Solutions `--' drepper at cygnus.com   `------------------------

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
typedef unsigned int u_int32_t;
typedef int int32_t;

typedef union
{
  double value;
  struct
  {
    u_int32_t lsw;
    u_int32_t msw;
  } parts;
} ieee_double_shape_type;


double
__nextafter(double x, double y)
{
  int32_t hx,hy,ix,iy;
  u_int32_t lx,ly;

  do
    {
      ieee_double_shape_type ew_u;
      ew_u.value = x;
      hx = ew_u.parts.msw;
      lx = ew_u.parts.lsw;
    }
  while (0);
  do
    {
      ieee_double_shape_type ew_u;
      ew_u.value = y;
      hy = ew_u.parts.msw;
      ly = ew_u.parts.lsw;
    }
  while (0);

  ix = hx&0x7fffffff;
  iy = hy&0x7fffffff;

  if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) ||
     ((iy>=0x7ff00000)&&((iy-0x7ff00000)|ly)!=0))
    return x+y;
  if(x==y) return y;
  if((ix|lx)==0)
    {
      do
	{
	  ieee_double_shape_type iw_u;
	  iw_u.parts.msw = hy&0x80000000;
	  iw_u.parts.lsw = 1;
	  x = iw_u.value;
	}
      while (0) ;
      y = x*x;
      if(y==x) return y; else return x;
    }
  if(hx>=0)
    {
      if(hx>hy||((hx==hy)&&(lx>ly)))
	{
	  if(lx==0) hx -= 1;
	  lx -= 1;
	}
      else
	{
	  lx += 1;
	  if(lx==0) hx += 1;
	}
    }
  else
    {
      if(hy>=0||hx>hy||((hx==hy)&&(lx>ly)))
	{
	  if(lx==0) hx -= 1;
	  lx -= 1;
	}
      else
	{
	  lx += 1;
	  if(lx==0) hx += 1;
	}
    }
  hy = hx&0x7ff00000;
  if(hy>=0x7ff00000) return x+x;
  if(hy<0x00100000)
    {
      y = x*x;
      if(y!=x)
	{
	  do
	    {
	      ieee_double_shape_type iw_u;
	      iw_u.parts.msw = hx;
	      iw_u.parts.lsw = lx;
	      y = iw_u.value;
	    }
	  while (0);
	  return y;
	}
    }
  do
    {
      ieee_double_shape_type iw_u;
      iw_u.parts.msw = hx;
      iw_u.parts.lsw = lx;
      x = iw_u.value;
    }
  while (0);
  return x;
}



More information about the Gcc-bugs mailing list