This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix folding of (X | C1) & C2 (PR c/37261)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 29 Aug 2008 08:30:00 -0400
- Subject: [PATCH] Fix folding of (X | C1) & C2 (PR c/37261)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
This bug got introduced by PR33691 fix, which fixed the folding to use
the same type, but unfortunately not the right one as the following
testcase shows. TREE_TYPE (arg0) is int and TREE_TYPE (arg1) is unsigned
int and it has the uppermost bit set, so overflow is set when it is
fold_converted. The right fix is to do all the BIT_AND_EXPRs and
BIT_IOR_EXPRs in the resulting type, which in case of mixing signed with
unsigned arguments will be unsigned.
Starting bootstrap on x86_64-linux, ok for trunk/4.3 if it succeeds?
2008-08-29 Jakub Jelinek <jakub@redhat.com>
PR c/37261
* fold-const.c (fold_binary): In (X | C1) & C2 canonicalization
compute new & and | in type rather than TREE_TYPE (arg0).
* gcc.dg/pr37261.c: New test.
--- gcc/fold-const.c.jj 2008-08-22 19:49:36.000000000 +0200
+++ gcc/fold-const.c 2008-08-29 13:54:30.000000000 +0200
@@ -10726,14 +10726,13 @@ fold_binary (enum tree_code code, tree t
&& TREE_CODE (arg1) == INTEGER_CST
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
{
- tree tmp1 = fold_convert (TREE_TYPE (arg0), arg1);
- tree tmp2 = fold_build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
- TREE_OPERAND (arg0, 0), tmp1);
- tree tmp3 = fold_build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
- TREE_OPERAND (arg0, 1), tmp1);
+ tree tmp1 = fold_convert (type, arg1);
+ tree tmp2 = fold_convert (type, TREE_OPERAND (arg0, 0));
+ tree tmp3 = fold_convert (type, TREE_OPERAND (arg0, 1));
+ tmp2 = fold_build2 (BIT_AND_EXPR, type, tmp2, tmp1);
+ tmp3 = fold_build2 (BIT_AND_EXPR, type, tmp3, tmp1);
return fold_convert (type,
- fold_build2 (BIT_IOR_EXPR, TREE_TYPE (arg0),
- tmp2, tmp3));
+ fold_build2 (BIT_IOR_EXPR, type, tmp2, tmp3));
}
/* (X | Y) & Y is (X, Y). */
--- gcc/testsuite/gcc.dg/pr37261.c.jj 2008-08-29 14:07:17.000000000 +0200
+++ gcc/testsuite/gcc.dg/pr37261.c 2008-08-29 14:06:56.000000000 +0200
@@ -0,0 +1,15 @@
+/* PR c/37261 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+unsigned
+foo (int x)
+{
+ unsigned a = ((x & 1) | 2) & 0x80000000; /* { dg-bogus "integer overflow in expression" } */
+ unsigned b = ((x & 2) | 2) & 0x80000000; /* { dg-bogus "integer overflow in expression" } */
+ unsigned c = ((x & 4) | 2) & 0x80000000; /* { dg-bogus "integer overflow in expression" } */
+ return a + b + c;
+}
+
+/* { dg-final { scan-tree-dump "return 0" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
Jakub