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]

[PATCH] Optimize (x - 1.0) > 0.0 into x > 1.0


The following patch optimizes comparisons of a floating point
constant against an addition or subtraction with a floating point
constant.  Almost identical code already exists in fold for
handling the integer case, but this patch adds support for the
equivalent transformation on floating point expressions when
-ffast-math is specified.

Whilst I was looking at the code, I also decided that we should
canonicalize both integer and floating point comparisons to put
any constant terms in arg1.  Unlike invert_tree_comparison, I
believe that swap_tree_comparison is safe in the presence of
NaNs, infinities, signed zeros, etc...  This canonicalization
is now applied before any other transformations.

The following patch has been tested on i686-pc-linux-gnu with
both "make bootstrap" and "make -k check", all languages except
Ada and treelang, with no new regressions.

Ok for mainline?


2002-06-05  Roger Sayle  <roger@eyesopen.com>

	* fold-const.c (fold) [EQ_EXPR]:  Place both integer and real
	constants last in comparisons.  Optimize (x+1.0)>0.0 into the
	equivalent x > -1.0 when -ffast-math.

	* gcc.dg/20020605-1.c: New test case.


Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.208
diff -c -3 -p -r1.208 fold-const.c
*** fold-const.c	4 Jun 2002 07:07:37 -0000	1.208
--- fold-const.c	5 Jun 2002 17:20:49 -0000
*************** fold (expr)
*** 5814,5819 ****
--- 5814,5833 ----
      case GT_EXPR:
      case LE_EXPR:
      case GE_EXPR:
+       /* If one arg is a real or integer constant, put it last.  */
+       if ((TREE_CODE (arg0) == INTEGER_CST
+ 	   && TREE_CODE (arg1) != INTEGER_CST)
+ 	  || (TREE_CODE (arg0) == REAL_CST
+ 	      && TREE_CODE (arg0) != REAL_CST))
+ 	{
+ 	  TREE_OPERAND (t, 0) = arg1;
+ 	  TREE_OPERAND (t, 1) = arg0;
+ 	  arg0 = TREE_OPERAND (t, 0);
+ 	  arg1 = TREE_OPERAND (t, 1);
+ 	  code = swap_tree_comparison (code);
+ 	  TREE_SET_CODE (t, code);
+ 	}
+
        if (FLOAT_TYPE_P (TREE_TYPE (arg0)))
  	{
  	  /* (-a) CMP (-b) -> b CMP a  */
*************** fold (expr)
*** 5835,5852 ****
  	      && REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (arg1)))
  	    return fold (build (code, type, arg0,
  				build_real (TREE_TYPE (arg1), dconst0)));
- 	}

!       /* If one arg is a constant integer, put it last.  */
!       if (TREE_CODE (arg0) == INTEGER_CST
! 	  && TREE_CODE (arg1) != INTEGER_CST)
! 	{
! 	  TREE_OPERAND (t, 0) = arg1;
! 	  TREE_OPERAND (t, 1) = arg0;
! 	  arg0 = TREE_OPERAND (t, 0);
! 	  arg1 = TREE_OPERAND (t, 1);
! 	  code = swap_tree_comparison (code);
! 	  TREE_SET_CODE (t, code);
  	}

        /* Convert foo++ == CONST into ++foo == CONST + INCR.
--- 5849,5869 ----
  	      && REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (arg1)))
  	    return fold (build (code, type, arg0,
  				build_real (TREE_TYPE (arg1), dconst0)));

! 	  /* If this is a comparison of a real constant with a PLUS_EXPR
! 	     or a MINUS_EXPR of a real constant, we can convert it into a
! 	     comparison with a revised real constant as long as no overflow
! 	     occurs when unsafe_math_optimizations are enabled.  */
! 	  if (flag_unsafe_math_optimizations
! 	      && TREE_CODE (arg1) == REAL_CST
! 	      && (TREE_CODE (arg0) == PLUS_EXPR
! 		  || TREE_CODE (arg0) == MINUS_EXPR)
! 	      && TREE_CODE (TREE_OPERAND (arg0, 1)) == REAL_CST
! 	      && 0 != (tem = const_binop (TREE_CODE (arg0) == PLUS_EXPR
! 					  ? MINUS_EXPR : PLUS_EXPR,
! 					  arg1, TREE_OPERAND (arg0, 1), 0))
! 	      && ! TREE_CONSTANT_OVERFLOW (tem))
! 	    return fold (build (code, type, TREE_OPERAND (arg0, 0), tem));
  	}

        /* Convert foo++ == CONST into ++foo == CONST + INCR.
*** /dev/null	Thu Aug 30 14:30:55 2001
--- gcc.dg/20020605-1.c	Wed Jun  5 17:30:57 2002
***************
*** 0 ****
--- 1,74 ----
+ /* Copyright (C) 2002 Free Software Foundation.
+
+    Test for correctness of floating point comparisons.
+
+    Written by Roger Sayle, 4th June 2002.  */
+
+ /* { dg-do execute } */
+ /* { dg-options "-O2 -ffast-math" } */
+
+ extern void abort (void);
+
+ int test1 (double x, int ok)
+ {
+   if ((x - 1.0) > 0.0)
+     {
+       if (!ok) abort ();
+     }
+   else
+     if (ok) abort ();
+ }
+
+ int test1f (float x, int ok)
+ {
+   if ((x - 1.0f) > 0.0f)
+     {
+       if (!ok) abort ();
+     }
+   else
+     if (ok) abort ();
+ }
+
+ int test2 (double x, int ok)
+ {
+   if ((x + 1.0) < 0.0)
+     {
+       if (!ok) abort ();
+     }
+   else
+     if (ok) abort ();
+ }
+
+ int test2f (float x, int ok)
+ {
+   if ((x + 1.0f) < 0.0f)
+     {
+       if (!ok) abort ();
+     }
+   else
+     if (ok) abort ();
+ }
+
+
+ int
+ main ()
+ {
+   test1 (-2.0, 0);
+   test1 ( 0.0, 0);
+   test1 ( 2.0, 1);
+
+   test1f (-2.0f, 0);
+   test1f ( 0.0f, 0);
+   test1f ( 2.0f, 1);
+
+   test2 (-2.0, 1);
+   test2 ( 0.0, 0);
+   test2 ( 2.0, 0);
+
+   test2f (-2.0f, 1);
+   test2f ( 0.0f, 0);
+   test2f ( 2.0f, 0);
+
+   return 0;
+ }
+

Roger
--
Roger Sayle,                         E-mail: roger@eyesopen.com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833


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