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] Fix PR26898, folding of X +- C1 CMP Y +- C2


This is the final version of the above folding, which is safe for
signed types and resulting constant that is smaller in absolute
value than the original one.

Bootstrapped and tested on x86_64-unknown-linux-gnu.

Ok for mainline?

Thanks,
Richard.

:ADDPATCH middle-end:

2006-04-05  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]