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, 2nd try


This again introduces the possibility to fold X +- CST CMP Y +- CST to 
fold, whilst handling correctly the overflow conditions as noted by jsm.

Boostrapped and tested on x86_64-unknown-linux-gnu, ok for mainline?

Thanks,
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/pr26898.c: New testcase.

Index: fold-const.c
===================================================================
*** fold-const.c	(revision 112530)
--- fold-const.c	(working copy)
*************** fold_comparison (enum tree_code code, tr
*** 7356,7361 ****
--- 7356,7398 ----
  	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 constant offsets have the same sign and the resulting
+      offset is smaller 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 (arg0) == TREE_CODE (arg1))
+       && (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);
+ 
+       /* Decide on which side to put the now smaller or zero constant.  */
+       if (tree_int_cst_lt (const2, const1))
+ 	{
+ 	  const1 = int_const_binop (MINUS_EXPR, const1, const2, 0);
+ 	  return fold_build2 (code, type,
+ 			      fold_build2 (TREE_CODE (arg0), TREE_TYPE (arg0),
+ 					   variable1, const1),
+ 			      variable2);
+ 	}
+       else
+ 	{
+ 	  const2 = int_const_binop (MINUS_EXPR, const2, const1, 0);
+ 	  return fold_build2 (code, type,
+ 			      variable1,
+ 			      fold_build2 (TREE_CODE (arg0), TREE_TYPE (arg0),
+ 					   variable2, const2));
+ 	}
+     }
+ 
    if (FLOAT_TYPE_P (TREE_TYPE (arg0)))
      {
        tree targ0 = strip_float_extensions (arg0);

/* { dg-do link } */
/* { dg-options "-O2" } */

extern void link_error(void);
int main()
{
  int i0, i1;
  if (!(i0 + 1 < i1 + 1 == i0 < 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]