summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/fold-const.c11
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr33779-1.c14
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr33779-2.c12
5 files changed, 46 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2808ae787c3..9e46938b0d0 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2007-10-31 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/33779
+ * fold-const.c (extract_muldiv_1): Make sure to not introduce
+ new undefined integer overflow.
+ (fold_binary): Avoid useless conversion.
+
2007-10-31 Richard Sandiford <rsandifo@nildram.co.uk>
PR target/33948
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 2598ec1e18f..a7d2756116b 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -6060,7 +6060,12 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
then we cannot pass through this conversion. */
|| (code != MULT_EXPR
&& (TYPE_UNSIGNED (ctype)
- != TYPE_UNSIGNED (TREE_TYPE (op0))))))
+ != TYPE_UNSIGNED (TREE_TYPE (op0))))
+ /* ... or has undefined overflow while the converted to
+ type has not, we cannot do the operation in the inner type
+ as that would introduce undefined overflow. */
+ || (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (op0))
+ && !TYPE_OVERFLOW_UNDEFINED (type))))
break;
/* Pass the constant down and see if we can make a simplification. If
@@ -10266,9 +10271,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
strict_overflow_p = false;
if (TREE_CODE (arg1) == INTEGER_CST
- && 0 != (tem = extract_muldiv (op0,
- fold_convert (type, arg1),
- code, NULL_TREE,
+ && 0 != (tem = extract_muldiv (op0, arg1, code, NULL_TREE,
&strict_overflow_p)))
{
if (strict_overflow_p)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 59ae5ef3d10..385b384e4c6 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2007-10-31 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/33779
+ * gcc.c-torture/execute/pr33779-1.c: New testcase.
+ * gcc.c-torture/execute/pr33779-2.c: Likewise.
+
2007-10-31 Paul Thomas <pault@gcc.gnu.org>
PR fortran/33897
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr33779-1.c b/gcc/testsuite/gcc.c-torture/execute/pr33779-1.c
new file mode 100644
index 00000000000..da08e013a05
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr33779-1.c
@@ -0,0 +1,14 @@
+int foo(int i)
+{
+ if (((unsigned)(i + 1)) * 4 == 0)
+ return 1;
+ return 0;
+}
+
+extern void abort(void);
+int main()
+{
+ if (foo(0x3fffffff) == 0)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr33779-2.c b/gcc/testsuite/gcc.c-torture/execute/pr33779-2.c
new file mode 100644
index 00000000000..16c34b63c71
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr33779-2.c
@@ -0,0 +1,12 @@
+int foo(int i)
+{
+ return ((int)((unsigned)(i + 1) * 4)) / 4;
+}
+
+extern void abort(void);
+int main()
+{
+ if (foo(0x3fffffff) != 0)
+ abort ();
+ return 0;
+}