aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/fold-const.c5
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr56250.c13
4 files changed, 29 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 55e90b4..4c6bfba 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2013-02-08 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/56250
+ * fold-const.c (extract_muldiv_1) <case NEGATE_EXPR>: Don't optimize
+ if type is unsigned and code isn't MULT_EXPR.
+
2013-02-08 Georg-Johann Lay <avr@gjlay.de>
PR tree-optimization/56064
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 93f38cb..5acb4ad 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -5695,6 +5695,11 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
break;
/* FALLTHROUGH */
case NEGATE_EXPR:
+ /* For division and modulus, type can't be unsigned, as e.g.
+ (-(x / 2U)) / 2U isn't equal to -((x / 2U) / 2U) for x >= 2.
+ For signed types, even with wrapping overflow, this is fine. */
+ if (code != MULT_EXPR && TYPE_UNSIGNED (type))
+ break;
if ((t1 = extract_muldiv (op0, c, code, wide_type, strict_overflow_p))
!= 0)
return fold_build1 (tcode, ctype, fold_convert (ctype, t1));
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 31f0bf2..ae21e6b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2013-02-08 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/56250
+ * gcc.c-torture/execute/pr56250.c: New test.
+
2013-02-08 Georg-Johann Lay <avr@gjlay.de>
PR tree-optimization/56064
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr56250.c b/gcc/testsuite/gcc.c-torture/execute/pr56250.c
new file mode 100644
index 0000000..8da36f8
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr56250.c
@@ -0,0 +1,13 @@
+/* PR tree-optimization/56250 */
+
+extern void abort (void);
+
+int
+main ()
+{
+ unsigned int x = 2;
+ unsigned int y = (0U - x / 2) / 2;
+ if (-1U / x != y)
+ abort ();
+ return 0;
+}