This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Optimize (x - 1.0) > 0.0 into x > 1.0
- From: Roger Sayle <roger at eyesopen dot com>
- To: <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 5 Jun 2002 17:36:22 -0600 (MDT)
- Subject: [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