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

Jim Wilson wilson@specifixinc.com
Wed Dec 17 03:44:00 GMT 2003


On Tue, 2003-12-16 at 05:54, Roger Sayle wrote:
> How about something like:
> static bool implicit_set_cond_p (rtx cond)

I tried this.  I think I found a few problems.

The treatment of NaNs does not appear to be correct.  We only create an
implicit set on the path where the compare operands are equal.  However,
if one of the operands is a NaN, we can not reach the equal side, as
NaNs always compare unordered even to themselves.  Thus I think we need
no handling of NaNs here.

There is also a problem with the treatment of signed zeros.  Your
suggested patch handles only scalar float modes.  We also need to handle
complex and vector.  If any subpart of a complex or vector has a zero
value, then we must disallow the optimization when HONOR_SIGNED_ZEROS.
Unfortunately, I don't know of any function that can do that check, so I
am just returning zero for them and documenting it as a future
optimization.

The inclusion of tree.h is a mild annoyance.  This is needed because
REAL_VALUES_EQUAL uses EQ_EXPR.  simplify-rtx.c has the same problem, so
at least there is precedent for this.

This gives me the attached patch.  This works OK on my original
testcase.  Does this seem reasonable?  If so, then I will start
testing.  I'd like to have agreement on a patch before I start testing,
as it will take an entire day.
-- 
Jim Wilson, GNU Tools Support, http://www.SpecifixInc.com
-------------- next part --------------
gcc/ChangeLog
2003-12-16  James E Wilson  <wilson@specifixinc.com>
	    Roger Sayle  <roger@eyesopen.com>
	
	* Makefile.in (gcse.o): Add $(TREE_H) to dependencies.
	* gcse.c: Include tree.h.
	(implicit_set_cond_p): New.
	(find_implicit_sets): Call it.

gcc/testsuite/ChangeLog
2003-12-16  James E Wilson  <wilson@specifixinc.com>
	    Roger Sayle  <roger@eyesopen.com>

	* gcc.c-torture/execute/ieee/mzero5.c: New.

Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.1207
diff -p -r1.1207 Makefile.in
*** Makefile.in	8 Dec 2003 02:32:10 -0000	1.1207
--- Makefile.in	17 Dec 2003 03:22:00 -0000
*************** web.o : web.c $(CONFIG_H) $(SYSTEM_H) co
*** 1652,1658 ****
     hard-reg-set.h flags.h $(BASIC_BLOCK_H) function.h output.h toplev.h df.h
  gcse.o : gcse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(REGS_H) \
     hard-reg-set.h flags.h real.h insn-config.h $(GGC_H) $(RECOG_H) $(EXPR_H) \
!    $(BASIC_BLOCK_H) function.h output.h toplev.h $(TM_P_H) $(PARAMS_H) except.h gt-gcse.h
  sibcall.o : sibcall.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(REGS_H) \
     function.h hard-reg-set.h flags.h insn-config.h $(RECOG_H) $(BASIC_BLOCK_H)
  resource.o : resource.c $(CONFIG_H) $(RTL_H) hard-reg-set.h $(SYSTEM_H) coretypes.h \
--- 1652,1659 ----
     hard-reg-set.h flags.h $(BASIC_BLOCK_H) function.h output.h toplev.h df.h
  gcse.o : gcse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(REGS_H) \
     hard-reg-set.h flags.h real.h insn-config.h $(GGC_H) $(RECOG_H) $(EXPR_H) \
!    $(BASIC_BLOCK_H) function.h output.h toplev.h $(TM_P_H) $(PARAMS_H) \
!    except.h gt-gcse.h $(TREE_H)
  sibcall.o : sibcall.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(REGS_H) \
     function.h hard-reg-set.h flags.h insn-config.h $(RECOG_H) $(BASIC_BLOCK_H)
  resource.o : resource.c $(CONFIG_H) $(RTL_H) hard-reg-set.h $(SYSTEM_H) coretypes.h \
Index: gcse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gcse.c,v
retrieving revision 1.280
diff -p -r1.280 gcse.c
*** gcse.c	3 Dec 2003 10:02:28 -0000	1.280
--- gcse.c	17 Dec 2003 03:22:08 -0000
*************** Software Foundation, 59 Temple Place - S
*** 150,155 ****
--- 150,156 ----
  #include "toplev.h"
  
  #include "rtl.h"
+ #include "tree.h"
  #include "tm_p.h"
  #include "regs.h"
  #include "hard-reg-set.h"
*************** fis_get_condition (rtx jump)
*** 4559,4564 ****
--- 4560,4597 ----
    return tmp;
  }
  
+ /* Check the comparison COND to see if we can safely form an implicit set from
+    it.  COND is either an EQ or NE comparison.  */
+ 
+ static bool
+ implicit_set_cond_p (rtx cond)
+ {
+   enum machine_mode mode = GET_MODE (XEXP (cond, 0));
+   rtx cst = XEXP (cond, 1);
+ 
+   /* We can't perform this optimization if either operand might be or might
+      contain a signed zero.  */
+   if (HONOR_SIGNED_ZEROS (mode))
+     {
+       /* It is sufficient to check if CST is or contains a zero.  We must
+ 	 handle float, complex, and vector.  If any subpart is a zero, then
+ 	 the optimization can't be performed.  */
+       /* ??? The complex and vector checks are not implemented yet.  We just
+ 	 always return zero for them.  */
+       if (GET_CODE (cst) == CONST_DOUBLE)
+ 	{
+ 	  REAL_VALUE_TYPE d;
+ 	  REAL_VALUE_FROM_CONST_DOUBLE (d, cst);
+ 	  if (REAL_VALUES_EQUAL (d, dconst0))
+ 	    return 0;
+ 	}
+       else
+ 	return 0;
+     }
+ 
+   return gcse_constant_p (cst);
+ }
+ 
  /* Find the implicit sets of a function.  An "implicit set" is a constraint
     on the value of a variable, implied by a conditional jump.  For example,
     following "if (x == 2)", the then branch may be optimized as though the
*************** find_implicit_sets (void)
*** 4584,4590 ****
  	    && (GET_CODE (cond) == EQ || GET_CODE (cond) == NE)
  	    && GET_CODE (XEXP (cond, 0)) == REG
  	    && REGNO (XEXP (cond, 0)) >= FIRST_PSEUDO_REGISTER
! 	    && gcse_constant_p (XEXP (cond, 1)))
  	  {
  	    dest = GET_CODE (cond) == EQ ? BRANCH_EDGE (bb)->dest
  					 : FALLTHRU_EDGE (bb)->dest;
--- 4617,4623 ----
  	    && (GET_CODE (cond) == EQ || GET_CODE (cond) == NE)
  	    && GET_CODE (XEXP (cond, 0)) == REG
  	    && REGNO (XEXP (cond, 0)) >= FIRST_PSEUDO_REGISTER
! 	    && implicit_set_cond_p (cond))
  	  {
  	    dest = GET_CODE (cond) == EQ ? BRANCH_EDGE (bb)->dest
  					 : FALLTHRU_EDGE (bb)->dest;
Index: testsuite/gcc.c-torture/execute/ieee/mzero5.c
===================================================================
RCS file: testsuite/gcc.c-torture/execute/ieee/mzero5.c
diff -N testsuite/gcc.c-torture/execute/ieee/mzero5.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/gcc.c-torture/execute/ieee/mzero5.c	17 Dec 2003 03:22:08 -0000
***************
*** 0 ****
--- 1,29 ----
+ /* Test gcse handling of IEEE 0/-0 rules.  */
+ static double zero = 0.0;
+ 
+ int
+ negzero_check (double d)
+ {
+   if (d == 0)
+     return !!memcmp ((void *)&zero, (void *)&d, sizeof (double));
+   return 0;
+ }
+ 
+ int
+ sub (double d, double e)
+ {
+   if (d == 0.0 && e == 0.0
+       && negzero_check (d) == 0 && negzero_check (e) == 0)
+     return 1;
+   else
+     return 0;
+ }
+ 
+ int
+ main (void)
+ {
+   double minus_zero = -0.0;
+   if (sub (minus_zero, 0))
+     abort ();
+   return 0;
+ }


More information about the Gcc-patches mailing list