This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR26898, 2nd try
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 31 Mar 2006 10:02:06 +0200 (CEST)
- Subject: [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;
}