This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[Committed] Fold (~X & 4) != 0 as (X & 4) == 0.
- From: Roger Sayle <roger at eyesopen dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sun, 26 Feb 2006 20:17:46 -0700 (MST)
- Subject: [Committed] Fold (~X & 4) != 0 as (X & 4) == 0.
Argghh! The following patch was intended to resolve PR middle-end/14752,
by allowing fold to absorb BIT_NOT_EXPR in bit tests such as the one
above. Unfortunately, although this patch improves the attached test
case, it doesn't affect Kazu's original example in the bugzilla PR!
The difference is that Kazu's example uses "unsigned int" which somehow
results in different trees to those I was expecting. The following
patch fixes the variant of Kazu's code that uses "int" instead of
"unsigned". Now to investigate what's going on with (_Bool)...
The following patch has been tested on x86_64-unknown-linux-gnu with
a full "make bootstrap", all default languages, and regression tested
with a top-level "make -k check" with no new failures.
Committed to mainline as revision 111471.
2006-02-26 Roger Sayle <roger@eyesopen.com>
* fold-const.c (fold_binary) <EQ_EXPR>: Fold (~X & C) eq/ne 0 as
(X & C) ne/eq 0, where C is a single bit, i.e. a power of two.
Fold both "((X & C) ^ C) eq/ne 0" and "((X ^ C) & C) eq/ne 0"
as (X & C) ne/eq 0.
* gcc.dg/fold-eqandnot-1.c: New test case.
Index: fold-const.c
===================================================================
*** fold-const.c (revision 111454)
--- fold-const.c (working copy)
*************** fold_binary (enum tree_code code, tree t
*** 9868,9873 ****
--- 9868,9917 ----
fold_build2 (BIT_XOR_EXPR, TREE_TYPE (arg1),
TREE_OPERAND (arg0, 1), arg1));
+ /* Fold (~X & C) == 0 into (X & C) != 0 and (~X & C) != 0 into
+ (X & C) == 0 when C is a single bit. */
+ if (TREE_CODE (arg0) == BIT_AND_EXPR
+ && TREE_CODE (TREE_OPERAND (arg0, 0)) == BIT_NOT_EXPR
+ && integer_zerop (arg1)
+ && integer_pow2p (TREE_OPERAND (arg0, 1)))
+ {
+ tem = fold_build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
+ TREE_OPERAND (TREE_OPERAND (arg0, 0), 0),
+ TREE_OPERAND (arg0, 1));
+ return fold_build2 (code == EQ_EXPR ? NE_EXPR : EQ_EXPR,
+ type, tem, arg1);
+ }
+
+ /* Fold ((X & C) ^ C) eq/ne 0 into (X & C) ne/eq 0, when the
+ constant C is a power of two, i.e. a single bit. */
+ if (TREE_CODE (arg0) == BIT_XOR_EXPR
+ && TREE_CODE (TREE_OPERAND (arg0, 0)) == BIT_AND_EXPR
+ && integer_zerop (arg1)
+ && integer_pow2p (TREE_OPERAND (arg0, 1))
+ && operand_equal_p (TREE_OPERAND (TREE_OPERAND (arg0, 0), 1),
+ TREE_OPERAND (arg0, 1), OEP_ONLY_CONST))
+ {
+ tree arg00 = TREE_OPERAND (arg0, 0);
+ return fold_build2 (code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
+ arg00, build_int_cst (TREE_TYPE (arg00), 0));
+ }
+
+ /* Likewise, fold ((X ^ C) & C) eq/ne 0 into (X & C) ne/eq 0,
+ when is C is a power of two, i.e. a single bit. */
+ if (TREE_CODE (arg0) == BIT_AND_EXPR
+ && TREE_CODE (TREE_OPERAND (arg0, 0)) == BIT_XOR_EXPR
+ && integer_zerop (arg1)
+ && integer_pow2p (TREE_OPERAND (arg0, 1))
+ && operand_equal_p (TREE_OPERAND (TREE_OPERAND (arg0, 0), 1),
+ TREE_OPERAND (arg0, 1), OEP_ONLY_CONST))
+ {
+ tree arg000 = TREE_OPERAND (TREE_OPERAND (arg0, 0), 0);
+ tem = fold_build2 (BIT_AND_EXPR, TREE_TYPE (arg000),
+ arg000, TREE_OPERAND (arg0, 1));
+ return fold_build2 (code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
+ tem, build_int_cst (TREE_TYPE (tem), 0));
+ }
+
if (integer_zerop (arg1)
&& tree_expr_nonzero_p (arg0))
{
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-original" } */
int test1(int a)
{
return !(a & 4);
}
int test2(int b)
{
return (b & 4) == 0;
}
int test3(int c)
{
return ((c & 4) ^ 4) != 0;
}
int test4(int d)
{
return ((d ^ 4) & 4) != 0;
}
int test5(int e)
{
return (~e & 4) != 0;
}
/* { dg-final { scan-tree-dump-times "\\(a \& 4\\) == 0" 1 "original" } } */
/* { dg-final { scan-tree-dump-times "\\(b \& 4\\) == 0" 1 "original" } } */
/* { dg-final { scan-tree-dump-times "\\(c \& 4\\) == 0" 1 "original" } } */
/* { dg-final { scan-tree-dump-times "\\(d \& 4\\) == 0" 1 "original" } } */
/* { dg-final { scan-tree-dump-times "\\(e \& 4\\) == 0" 1 "original" } } */
/* { dg-final { cleanup-tree-dump "original" } } */
Roger
--