aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChung-Lin Tang <cltang@codesourcery.com>2011-03-21 07:27:03 +0000
committerChung-Lin Tang <cltang@gcc.gnu.org>2011-03-21 07:27:03 +0000
commit54833ec0a6bcc91163da4c3f7a017a2f73879cd1 (patch)
tree7be61378d32c6ae04d9c2b5ed89dfb6bc55d20fd
parent2757d5ecfc14883087e062b169e8355f8cc74b19 (diff)
downloadgcc-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/ChangeLog5
-rw-r--r--gcc/simplify-rtx.c40
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.target/arm/xor-and.c14
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" } } */