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]

Re: [PATCH] Fix PR26898, 2nd try


On Fri, 31 Mar 2006, Joseph S. Myers wrote:

> On Fri, 31 Mar 2006, Richard Guenther wrote:
> 
> > On 3/31/06, Joseph S. Myers <joseph@codesourcery.com> wrote:
> > > I take it that at this point in folding it is guaranteed that the
> > > constants are non-negative, i.e. you don't have to deal with "X + -1" or
> > > "X - -1"?
> > 
> > Hmm I thought they were canonicalized - but now I verified they are not.
> > *sigh*  Are there any problems with treating X - -1 as X + 1?
> 
> No, though you can't fold X + INT_MIN or X - INT_MIN that way.  (But 
> the optimization is still valid as applied to X + INT_MIN CMP Y - INT_MAX 
> converted to X - 1 CMP Y.)

Like this one.

Richard.

2006-03-30  Richard Guenther  <rguenther@suse.de>

	PR middle-end/26898
	* fold-const.c (fold_comparison): Fold signed comparisons
	of the form X +- C1 CMP Y +- C2.

	* gcc.dg/torture/pr26898-1.c: New testcase.
	* gcc.dg/torture/pr26898-2.c: Likewise.

Index: fold-const.c
===================================================================
*** fold-const.c	(revision 112530)
--- fold-const.c	(working copy)
*************** fold_comparison (enum tree_code code, tr
*** 7356,7361 ****
--- 7356,7403 ----
  	return fold_build2 (code, type, variable, lhs);
      }
  
+   /* Transform comparisons of the form X +- C1 CMP Y +- C2 to
+      X CMP Y +- C2 +- C1 for signed X, Y.  This is valid if
+      the resulting offset is smaller in absolute value than the
+      original one.  */
+   if (!(flag_wrapv || flag_trapv)
+       && !TYPE_UNSIGNED (TREE_TYPE (arg0))
+       && (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
+       && (TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
+ 	  && !TREE_OVERFLOW (TREE_OPERAND (arg0, 1)))
+       && (TREE_CODE (arg1) == PLUS_EXPR || TREE_CODE (arg1) == MINUS_EXPR)
+       && (TREE_CODE (TREE_OPERAND (arg1, 1)) == INTEGER_CST
+ 	  && !TREE_OVERFLOW (TREE_OPERAND (arg1, 1))))
+     {
+       tree const1 = TREE_OPERAND (arg0, 1);
+       tree const2 = TREE_OPERAND (arg1, 1);
+       tree variable1 = TREE_OPERAND (arg0, 0);
+       tree variable2 = TREE_OPERAND (arg1, 0);
+       tree cst;
+ 
+       /* Put the constant on the side where it doesn't overflow and is
+ 	 of lower absolute value than before.  */
+       cst = int_const_binop (TREE_CODE (arg0) == TREE_CODE (arg1)
+ 			     ? MINUS_EXPR : PLUS_EXPR,
+ 			     const2, const1, 0);
+       if (!TREE_OVERFLOW (cst)
+ 	  && tree_int_cst_compare (const2, cst) == tree_int_cst_sgn (const2))
+ 	return fold_build2 (code, type,
+ 			    variable1,
+ 			    fold_build2 (TREE_CODE (arg1), TREE_TYPE (arg1),
+ 					 variable2, cst));
+ 
+       cst = int_const_binop (TREE_CODE (arg0) == TREE_CODE (arg1)
+ 			     ? MINUS_EXPR : PLUS_EXPR,
+ 			     const1, const2, 0);
+       if (!TREE_OVERFLOW (cst)
+ 	  && tree_int_cst_compare (const1, cst) == tree_int_cst_sgn (const1))
+ 	return fold_build2 (code, type,
+ 			    fold_build2 (TREE_CODE (arg0), TREE_TYPE (arg0),
+ 					 variable1, cst),
+ 			    variable2);
+     }
+ 
    if (FLOAT_TYPE_P (TREE_TYPE (arg0)))
      {
        tree targ0 = strip_float_extensions (arg0);
Index: testsuite/gcc.dg/torture/pr26898-2.c
===================================================================
*** testsuite/gcc.dg/torture/pr26898-2.c	(revision 0)
--- testsuite/gcc.dg/torture/pr26898-2.c	(revision 0)
***************
*** 0 ****
--- 1,12 ----
+ /* { dg-do run } */
+ 
+ #include <limits.h>
+ 
+ int a = 0, b = INT_MAX - 1;
+ extern void abort(void);
+ int main()
+ {
+   if (a - 1 > b + 1)
+     abort();
+   return 0;
+ }
Index: testsuite/gcc.dg/torture/pr26898-1.c
===================================================================
*** testsuite/gcc.dg/torture/pr26898-1.c	(revision 0)
--- testsuite/gcc.dg/torture/pr26898-1.c	(revision 0)
***************
*** 0 ****
--- 1,14 ----
+ /* { dg-do link } */
+ 
+ #include <limits.h>
+ 
+ extern void link_error(void);
+ int main()
+ {
+   int i0, i1;
+   if (!(i0 + 1 < i1 + 1 == i0 < i1))
+     link_error ();
+   if (!(i0 + INT_MIN < i1 - INT_MAX == i0 - 1 < i1))
+     link_error ();
+   return 0;
+ }


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