diff options
author | Chung-Lin Tang <cltang@codesourcery.com> | 2011-03-21 07:27:03 +0000 |
---|---|---|
committer | Chung-Lin Tang <cltang@gcc.gnu.org> | 2011-03-21 07:27:03 +0000 |
commit | 54833ec0a6bcc91163da4c3f7a017a2f73879cd1 (patch) | |
tree | 7be61378d32c6ae04d9c2b5ed89dfb6bc55d20fd | |
parent | 2757d5ecfc14883087e062b169e8355f8cc74b19 (diff) | |
download | gcc-54833ec0a6bcc91163da4c3f7a017a2f73879cd1.zip gcc-54833ec0a6bcc91163da4c3f7a017a2f73879cd1.tar.gz gcc-54833ec0a6bcc91163da4c3f7a017a2f73879cd1.tar.bz2 |
simplify-rtx.c (simplify_binary_operation_1): Handle (xor (and A B) C) case when B and C are both constants.
2011-03-21 Chung-Lin Tang <cltang@codesourcery.com>
* simplify-rtx.c (simplify_binary_operation_1): Handle
(xor (and A B) C) case when B and C are both constants.
testsuite/
* gcc.target/arm/xor-and.c: New.
From-SVN: r171208
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/simplify-rtx.c | 40 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/arm/xor-and.c | 14 |
4 files changed, 63 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8a1868b..7d38781 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2011-03-21 Chung-Lin Tang <cltang@codesourcery.com> + + * simplify-rtx.c (simplify_binary_operation_1): Handle + (xor (and A B) C) case when B and C are both constants. + 2011-03-21 Mingjie Xing <mingjie.xing@gmail.com> * tree-dfa.c (add_referenced_var): Fix typo in comment. diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index ce4eab4..4a8e3c6 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -2480,6 +2480,46 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode, XEXP (op0, 1), mode), op1); + /* Given (xor (and A B) C), using P^Q == (~P&Q) | (~Q&P), + we can transform like this: + (A&B)^C == ~(A&B)&C | ~C&(A&B) + == (~A|~B)&C | ~C&(A&B) * DeMorgan's Law + == ~A&C | ~B&C | A&(~C&B) * Distribute and re-order + Attempt a few simplifications when B and C are both constants. */ + if (GET_CODE (op0) == AND + && CONST_INT_P (op1) + && CONST_INT_P (XEXP (op0, 1))) + { + rtx a = XEXP (op0, 0); + rtx b = XEXP (op0, 1); + rtx c = op1; + HOST_WIDE_INT bval = INTVAL (b); + HOST_WIDE_INT cval = INTVAL (c); + + rtx na_c + = simplify_binary_operation (AND, mode, + simplify_gen_unary (NOT, mode, a, mode), + c); + if ((~cval & bval) == 0) + { + /* Try to simplify ~A&C | ~B&C. */ + if (na_c != NULL_RTX) + return simplify_gen_binary (IOR, mode, na_c, + GEN_INT (~bval & cval)); + } + else + { + /* If ~A&C is zero, simplify A&(~C&B) | ~B&C. */ + if (na_c == const0_rtx) + { + rtx a_nc_b = simplify_gen_binary (AND, mode, a, + GEN_INT (~cval & bval)); + return simplify_gen_binary (IOR, mode, a_nc_b, + GEN_INT (~bval & cval)); + } + } + } + /* (xor (comparison foo bar) (const_int 1)) can become the reversed comparison if STORE_FLAG_VALUE is 1. */ if (STORE_FLAG_VALUE == 1 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 259bcc0..dbf0e21 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2011-03-21 Chung-Lin Tang <cltang@codesourcery.com> + + * gcc.target/arm/xor-and.c: New. + 2010-03-21 Thomas Koenig <tkoenig@gcc.gnu.org> PR fortran/22572 diff --git a/gcc/testsuite/gcc.target/arm/xor-and.c b/gcc/testsuite/gcc.target/arm/xor-and.c new file mode 100644 index 0000000..4b0f790 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/xor-and.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O -march=armv6" } */ + +unsigned short foo (unsigned short x) +{ + x ^= 0x4002; + x >>= 1; + x |= 0x8000; + return x; +} + +/* { dg-final { scan-assembler "orr" } } */ +/* { dg-final { scan-assembler-not "mvn" } } */ +/* { dg-final { scan-assembler-not "uxth" } } */ |