This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
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;
+ }