aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2006-10-21 13:21:06 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2006-10-21 13:21:06 +0000
commit8a1eca08037f5a936526485f1056385708dc5c7c (patch)
tree4cf583b76df07ca2a2dedcc508f861ce8f54ba4f
parent5a4171a01d9f9041175a6b7c473ed43a623bea0b (diff)
downloadgcc-8a1eca08037f5a936526485f1056385708dc5c7c.zip
gcc-8a1eca08037f5a936526485f1056385708dc5c7c.tar.gz
gcc-8a1eca08037f5a936526485f1056385708dc5c7c.tar.bz2
re PR middle-end/26898 (Fold does not fold signed + CST1 CMP signed + CST2)
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. From-SVN: r117931
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/fold-const.c42
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr26898-1.c14
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr26898-2.c12
5 files changed, 80 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0bb59aa..fdaa244 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 30efccd..b04022e 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 8634b8e..55d336c 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 0000000..12ca1f3
--- /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 0000000..508fde4
--- /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;
+}