This is the mail archive of the gcc-patches@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]
Other format: [Raw text]

gcse.c patch for IA-64 glibc math test failures


I tracked down some glibc math test failures with -0.0 to a problem with gcse.

The gcse function find_implicit_sets looks at compares, and and creates an
implicit set for the register being compared.  This does not work when an FP
value is compared against 0.0, since the compare will return true for both 0.0
and -0.0.  The call to gcse_constant_p does not help, because it is passed
(CONST_DOUBLE 0.0), which it accepts because it is CONSTANT_P.

Just disallowing FP modes here looks like the obvious solution.  We could
perhaps check for flag_unsafe_math_optimizations here.  I looked at combine.c
and simplify-rtx.c and they seemed a little inconsistent.  They check for
unsafe math for compares, but not for comparison operators, which is the case
here.

This was tested with an ia64-linux bootstrap, make check, and glibc build and
make check.  It fixed more glibc math failures than I expected, so I don't
have an exact count.  I think it is around 600-700.

I have a simplified testcase, but it is very sensitive to compiler options
and compiler versions.  It also requires a C99 library and IEEE math, which
poses portability problems.  Compile this with -O2 -std=gnu99 and it fails
with an abort without this patch.
	
I haven't checked in this patch yet in case someone wants to comment.  The
part I am most unsure about is how to safely add the testcase to our testsuite.
Maybe it is enough that glibc will test this for us?  glibc will do a much
better job of testing this than my testcase ever will.

2003-12-16  James E Wilson  <wilson@specifixinc.com>

	* gcse.c (find_implicit_sets): Don't accept cond with FP mode.

Index: gcse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gcse.c,v
retrieving revision 1.281
diff -p -r1.281 gcse.c
*** gcse.c	11 Dec 2003 00:20:39 -0000	1.281
--- gcse.c	16 Dec 2003 08:48:56 -0000
*************** find_implicit_sets (void)
*** 4584,4589 ****
--- 4584,4590 ----
  	    && (GET_CODE (cond) == EQ || GET_CODE (cond) == NE)
  	    && GET_CODE (XEXP (cond, 0)) == REG
  	    && REGNO (XEXP (cond, 0)) >= FIRST_PSEUDO_REGISTER
+ 	    && ! FLOAT_MODE_P (GET_MODE (XEXP (cond, 0)))
  	    && gcse_constant_p (XEXP (cond, 1)))
  	  {
  	    dest = GET_CODE (cond) == EQ ? BRANCH_EDGE (bb)->dest

Testcase:
#include <math.h>
#include <stdlib.h>

int
sub (double d, double e)
{
  if (d == 0.0 && e == 0.0
      && signbit (d) == 0 && signbit (e) == 0)
    return 1;
  else
    return 0;
}

int
main(void)
{
  double minus_zero = copysign (0.0, -1.0);
  if (sub (minus_zero, 0))
    abort ();
  return 0;
}

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


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