fold-const.c (fold_binary): Fold (X & Y) ^ Y as the equivalent ~X & Y, and the symmetry related transformations.
* fold-const.c (fold_binary) <BIT_XOR_EXPR>: Fold (X & Y) ^ Y as the equivalent ~X & Y, and the symmetry related transformations. (fold_binary) <BIT_AND_EXPR>: Similarly, fold (X ^ Y) & Y as ~X & Y, and symmetry related transforms. * gcc.dg/fold-andxor-1.c: New test case. * gcc.dg/fold-xorand-1.c: Likewise. From-SVN: r112459
This commit is contained in:
parent
3cc82eea2b
commit
dd2c62dcb6
@ -1,3 +1,10 @@
|
||||
2006-03-28 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
* fold-const.c (fold_binary) <BIT_XOR_EXPR>: Fold (X & Y) ^ Y as
|
||||
the equivalent ~X & Y, and the symmetry related transformations.
|
||||
(fold_binary) <BIT_AND_EXPR>: Similarly, fold (X ^ Y) & Y as
|
||||
~X & Y, and symmetry related transforms.
|
||||
|
||||
2006-03-28 Maxim Kuvyrkov <mkuvyrkov@ispras.ru>
|
||||
|
||||
Revert my 2006-03-27 patches.
|
||||
|
@ -8803,6 +8803,45 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
|
||||
return fold_build2 (EQ_EXPR, type, arg0,
|
||||
build_int_cst (TREE_TYPE (arg0), 0));
|
||||
|
||||
/* Fold (X & Y) ^ Y as ~X & Y. */
|
||||
if (TREE_CODE (arg0) == BIT_AND_EXPR
|
||||
&& operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
|
||||
{
|
||||
tem = fold_convert (type, TREE_OPERAND (arg0, 0));
|
||||
return fold_build2 (BIT_AND_EXPR, type,
|
||||
fold_build1 (BIT_NOT_EXPR, type, tem),
|
||||
fold_convert (type, arg1));
|
||||
}
|
||||
/* Fold (X & Y) ^ X as ~Y & X. */
|
||||
if (TREE_CODE (arg0) == BIT_AND_EXPR
|
||||
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
|
||||
&& reorder_operands_p (TREE_OPERAND (arg0, 1), arg1))
|
||||
{
|
||||
tem = fold_convert (type, TREE_OPERAND (arg0, 1));
|
||||
return fold_build2 (BIT_AND_EXPR, type,
|
||||
fold_build1 (BIT_NOT_EXPR, type, tem),
|
||||
fold_convert (type, arg1));
|
||||
}
|
||||
/* Fold X ^ (X & Y) as X & ~Y. */
|
||||
if (TREE_CODE (arg1) == BIT_AND_EXPR
|
||||
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
|
||||
{
|
||||
tem = fold_convert (type, TREE_OPERAND (arg1, 1));
|
||||
return fold_build2 (BIT_AND_EXPR, type,
|
||||
fold_convert (type, arg0),
|
||||
fold_build1 (BIT_NOT_EXPR, type, tem));
|
||||
}
|
||||
/* Fold X ^ (Y & X) as ~Y & X. */
|
||||
if (TREE_CODE (arg1) == BIT_AND_EXPR
|
||||
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 1), 0)
|
||||
&& reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
|
||||
{
|
||||
tem = fold_convert (type, TREE_OPERAND (arg1, 0));
|
||||
return fold_build2 (BIT_AND_EXPR, type,
|
||||
fold_build1 (BIT_NOT_EXPR, type, tem),
|
||||
fold_convert (type, arg0));
|
||||
}
|
||||
|
||||
/* See if this can be simplified into a rotate first. If that
|
||||
is unsuccessful continue in the association code. */
|
||||
goto bit_rotate;
|
||||
@ -8877,6 +8916,45 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
|
||||
build_int_cst (TREE_TYPE (tem), 0));
|
||||
}
|
||||
|
||||
/* Fold (X ^ Y) & Y as ~X & Y. */
|
||||
if (TREE_CODE (arg0) == BIT_XOR_EXPR
|
||||
&& operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
|
||||
{
|
||||
tem = fold_convert (type, TREE_OPERAND (arg0, 0));
|
||||
return fold_build2 (BIT_AND_EXPR, type,
|
||||
fold_build1 (BIT_NOT_EXPR, type, tem),
|
||||
fold_convert (type, arg1));
|
||||
}
|
||||
/* Fold (X ^ Y) & X as ~Y & X. */
|
||||
if (TREE_CODE (arg0) == BIT_XOR_EXPR
|
||||
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
|
||||
&& reorder_operands_p (TREE_OPERAND (arg0, 1), arg1))
|
||||
{
|
||||
tem = fold_convert (type, TREE_OPERAND (arg0, 1));
|
||||
return fold_build2 (BIT_AND_EXPR, type,
|
||||
fold_build1 (BIT_NOT_EXPR, type, tem),
|
||||
fold_convert (type, arg1));
|
||||
}
|
||||
/* Fold X & (X ^ Y) as X & ~Y. */
|
||||
if (TREE_CODE (arg1) == BIT_XOR_EXPR
|
||||
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
|
||||
{
|
||||
tem = fold_convert (type, TREE_OPERAND (arg1, 1));
|
||||
return fold_build2 (BIT_AND_EXPR, type,
|
||||
fold_convert (type, arg0),
|
||||
fold_build1 (BIT_NOT_EXPR, type, tem));
|
||||
}
|
||||
/* Fold X & (Y ^ X) as ~Y & X. */
|
||||
if (TREE_CODE (arg1) == BIT_XOR_EXPR
|
||||
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 1), 0)
|
||||
&& reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
|
||||
{
|
||||
tem = fold_convert (type, TREE_OPERAND (arg1, 0));
|
||||
return fold_build2 (BIT_AND_EXPR, type,
|
||||
fold_build1 (BIT_NOT_EXPR, type, tem),
|
||||
fold_convert (type, arg0));
|
||||
}
|
||||
|
||||
t1 = distribute_bit_expr (code, type, arg0, arg1);
|
||||
if (t1 != NULL_TREE)
|
||||
return t1;
|
||||
|
@ -1,3 +1,8 @@
|
||||
2006-03-28 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
* gcc.dg/fold-andxor-1.c: New test case.
|
||||
* gcc.dg/fold-xorand-1.c: Likewise.
|
||||
|
||||
2006-03-28 Roger Sayle <roger@eyesopen.com>
|
||||
|
||||
* gcc.dg/fold-convnotconv-1.c: New test case.
|
||||
|
29
gcc/testsuite/gcc.dg/fold-andxor-1.c
Normal file
29
gcc/testsuite/gcc.dg/fold-andxor-1.c
Normal file
@ -0,0 +1,29 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-original" } */
|
||||
|
||||
int test1(int a, int b)
|
||||
{
|
||||
return (a ^ b) & a;
|
||||
}
|
||||
|
||||
int test2(int c, int d)
|
||||
{
|
||||
return (c ^ d) & d;
|
||||
}
|
||||
|
||||
int test3(int e, int f)
|
||||
{
|
||||
return e & (e ^ f);
|
||||
}
|
||||
|
||||
int test4(int g, int h)
|
||||
{
|
||||
return g & (h ^ g);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "~b \& a" 1 "original" } } */
|
||||
/* { dg-final { scan-tree-dump-times "~c \& d" 1 "original" } } */
|
||||
/* { dg-final { scan-tree-dump-times "~f \& e" 1 "original" } } */
|
||||
/* { dg-final { scan-tree-dump-times "~h \& g" 1 "original" } } */
|
||||
/* { dg-final { cleanup-tree-dump "original" } } */
|
||||
|
29
gcc/testsuite/gcc.dg/fold-xorand-1.c
Normal file
29
gcc/testsuite/gcc.dg/fold-xorand-1.c
Normal file
@ -0,0 +1,29 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-original" } */
|
||||
|
||||
int test1(int a, int b)
|
||||
{
|
||||
return (a & b) ^ a;
|
||||
}
|
||||
|
||||
int test2(int c, int d)
|
||||
{
|
||||
return (c & d) ^ d;
|
||||
}
|
||||
|
||||
int test3(int e, int f)
|
||||
{
|
||||
return e ^ (e & f);
|
||||
}
|
||||
|
||||
int test4(int g, int h)
|
||||
{
|
||||
return g ^ (h & g);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "~b \& a" 1 "original" } } */
|
||||
/* { dg-final { scan-tree-dump-times "~c \& d" 1 "original" } } */
|
||||
/* { dg-final { scan-tree-dump-times "~f \& e" 1 "original" } } */
|
||||
/* { dg-final { scan-tree-dump-times "~h \& g" 1 "original" } } */
|
||||
/* { dg-final { cleanup-tree-dump "original" } } */
|
||||
|
Loading…
Reference in New Issue
Block a user