diff options
author | Roger Sayle <roger@eyesopen.com> | 2006-03-28 17:55:26 +0000 |
---|---|---|
committer | Roger Sayle <sayle@gcc.gnu.org> | 2006-03-28 17:55:26 +0000 |
commit | dd2c62dcb685f9de4d53cd8c6e656e358754589a (patch) | |
tree | 1b476f274da069b822455449eb6034e17e14926c /gcc | |
parent | 3cc82eea2bfea5681e8374a85794102b68bdd4be (diff) | |
download | gcc-dd2c62dcb685f9de4d53cd8c6e656e358754589a.zip gcc-dd2c62dcb685f9de4d53cd8c6e656e358754589a.tar.gz gcc-dd2c62dcb685f9de4d53cd8c6e656e358754589a.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/fold-const.c | 78 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/fold-andxor-1.c | 29 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/fold-xorand-1.c | 29 |
5 files changed, 148 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 12d43d4..17f1e2e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 695dc5d..aa710b1 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8443fda..91e2220 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,10 @@ 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. 2006-03-28 Paul Thomas <pault@gcc.gnu.org> diff --git a/gcc/testsuite/gcc.dg/fold-andxor-1.c b/gcc/testsuite/gcc.dg/fold-andxor-1.c new file mode 100644 index 0000000..cc46577 --- /dev/null +++ b/gcc/testsuite/gcc.dg/fold-andxor-1.c @@ -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" } } */ + diff --git a/gcc/testsuite/gcc.dg/fold-xorand-1.c b/gcc/testsuite/gcc.dg/fold-xorand-1.c new file mode 100644 index 0000000..8d42654 --- /dev/null +++ b/gcc/testsuite/gcc.dg/fold-xorand-1.c @@ -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" } } */ + |