From: Roger Sayle Date: Tue, 28 Mar 2006 17:55:26 +0000 (+0000) Subject: fold-const.c (fold_binary): Fold (X & Y) ^ Y as the equivalent ~X & Y, and the symmet... X-Git-Tag: releases/gcc-4.2.0~3529 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=dd2c62dcb685f9de4d53cd8c6e656e358754589a;p=thirdparty%2Fgcc.git fold-const.c (fold_binary): Fold (X & Y) ^ Y as the equivalent ~X & Y, and the symmetry related transformations. * fold-const.c (fold_binary) : Fold (X & Y) ^ Y as the equivalent ~X & Y, and the symmetry related transformations. (fold_binary) : 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 12d43d44e025..17f1e2e4fc26 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2006-03-28 Roger Sayle + + * fold-const.c (fold_binary) : Fold (X & Y) ^ Y as + the equivalent ~X & Y, and the symmetry related transformations. + (fold_binary) : Similarly, fold (X ^ Y) & Y as + ~X & Y, and symmetry related transforms. + 2006-03-28 Maxim Kuvyrkov Revert my 2006-03-27 patches. diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 695dc5d35122..aa710b126c8a 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 8443fdaded5c..91e22200af4a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2006-03-28 Roger Sayle + + * gcc.dg/fold-andxor-1.c: New test case. + * gcc.dg/fold-xorand-1.c: Likewise. + 2006-03-28 Roger Sayle * gcc.dg/fold-convnotconv-1.c: New test case. 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 000000000000..cc46577148af --- /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 000000000000..8d4265417c9e --- /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" } } */ +