diff options
author | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-10-21 13:21:06 +0000 |
---|---|---|
committer | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-10-21 13:21:06 +0000 |
commit | 91ceb6b76458690abf3303e716d1acd5506efec8 (patch) | |
tree | 4cf583b76df07ca2a2dedcc508f861ce8f54ba4f | |
parent | b503e57cf616f493a465962d11478d55f9736086 (diff) | |
download | gcc-91ceb6b76458690abf3303e716d1acd5506efec8.tar.gz |
2006-10-21 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@117931 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/fold-const.c | 42 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr26898-1.c | 14 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr26898-2.c | 12 |
5 files changed, 80 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0bb59aab9b1..fdaa244cfe5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,11 @@ 2006-10-21 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. + +2006-10-21 Richard Guenther <rguenther@suse.de> + PR target/19116 * config/i386/i386.c (override_options): Do not set MASK_IEEE_FP if flag_unsafe_math_optimizations is specified. We have diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 30efccd7ea7..b04022e1086 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -7835,6 +7835,48 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1) } } + /* 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); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8634b8e41ec..55d336cc162 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2006-10-21 Richard Guenther <rguenther@suse.de> + + PR middle-end/26898 + * gcc.dg/torture/pr26898-1.c: New testcase. + * gcc.dg/torture/pr26898-2.c: Likewise. + 2006-10-20 Lee Millward <lee.millward@codesourcery.com> PR c++/28053 diff --git a/gcc/testsuite/gcc.dg/torture/pr26898-1.c b/gcc/testsuite/gcc.dg/torture/pr26898-1.c new file mode 100644 index 00000000000..12ca1f38a91 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr26898-1.c @@ -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 < i1 - -1)) + link_error (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr26898-2.c b/gcc/testsuite/gcc.dg/torture/pr26898-2.c new file mode 100644 index 00000000000..508fde4ce7d --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr26898-2.c @@ -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; +} |