This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Avoid creating TREE_OVERFLOW constants in convert_to_integer (PR middle-end/26729)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 19 Apr 2006 18:30:08 -0400
- Subject: [PATCH] Avoid creating TREE_OVERFLOW constants in convert_to_integer (PR middle-end/26729)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
convert_to_integer seems to optimize truncation (shouldn't that be solely
fold's job?), but during that can create integer overflowed constants that
mess optimizers later on. The following patch fixes that by doing the same
that e.g. the C frontend does after calling convert - dropping the overflow
bit if it was introduced during the optimization.
Bootstrapped/regtested on x86_64-linux, ok for trunk/4.1?
I know Roger's patch might make this eventually unnecessary on the trunk,
still 4.1 branch is probably not going to have those changes.
2006-04-19 Jakub Jelinek <jakub@redhat.com>
PR middle-end/26729
* convert.c (convert_to_integer): Ignore integer overflows when
truncating.
* gcc.c-torture/execute/20060419-1.c: New test.
--- gcc/convert.c.jj 2006-04-19 16:23:13.000000000 +0200
+++ gcc/convert.c 2006-04-19 17:11:43.000000000 +0200
@@ -616,6 +616,7 @@ convert_to_integer (tree type, tree expr
(Otherwise would recurse infinitely in convert. */
if (TYPE_PRECISION (typex) != inprec)
{
+ tree carg0, carg1;
/* Don't do unsigned arithmetic where signed was wanted,
or vice versa.
Exception: if both of the original operands were
@@ -648,10 +649,29 @@ convert_to_integer (tree type, tree expr
typex = lang_hooks.types.unsigned_type (typex);
else
typex = lang_hooks.types.signed_type (typex);
- return convert (type,
- fold_build2 (ex_form, typex,
- convert (typex, arg0),
- convert (typex, arg1)));
+ carg0 = convert (typex, arg0);
+ carg1 = convert (typex, arg1);
+ /* Ignore integer overflows caused by the downcasts. */
+ if (TREE_CODE (carg0) == INTEGER_CST
+ && (TREE_OVERFLOW (carg0)
+ || TREE_CONSTANT_OVERFLOW (carg0))
+ && (!CONSTANT_CLASS_P (arg0)
+ || (!TREE_OVERFLOW (arg0)
+ && !TREE_CONSTANT_OVERFLOW (arg0))))
+ carg0 = build_int_cst_wide (typex,
+ TREE_INT_CST_LOW (carg0),
+ TREE_INT_CST_HIGH (carg0));
+ if (TREE_CODE (carg1) == INTEGER_CST
+ && (TREE_OVERFLOW (carg1)
+ || TREE_CONSTANT_OVERFLOW (carg1))
+ && (!CONSTANT_CLASS_P (arg1)
+ || (!TREE_OVERFLOW (arg1)
+ && !TREE_CONSTANT_OVERFLOW (arg1))))
+ carg1 = build_int_cst_wide (typex,
+ TREE_INT_CST_LOW (carg1),
+ TREE_INT_CST_HIGH (carg1));
+ return convert (type, fold_build2 (ex_form, typex,
+ carg0, carg1));
}
}
}
--- gcc/testsuite/gcc.c-torture/execute/20060419-1.c.jj 2006-04-19 17:15:12.000000000 +0200
+++ gcc/testsuite/gcc.c-torture/execute/20060419-1.c 2006-04-19 17:16:13.000000000 +0200
@@ -0,0 +1,17 @@
+/* PR middle-end/26729 */
+
+void abort (void);
+
+int
+foo (unsigned short x)
+{
+ return (x & 0x1) && (((unsigned short) (x & 0x8000)) == 0x8000);
+}
+
+int
+main (void)
+{
+ if (! foo (0x8001))
+ abort ();
+ return 0;
+}
Jakub