simplify-rtx.c (simplify_binary_operation_1): Handle (xor (and A B) C) case when...
authorChung-Lin Tang <cltang@codesourcery.com>
Mon, 21 Mar 2011 07:27:03 +0000 (07:27 +0000)
committerChung-Lin Tang <cltang@gcc.gnu.org>
Mon, 21 Mar 2011 07:27:03 +0000 (07:27 +0000)
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

gcc/ChangeLog
gcc/simplify-rtx.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/arm/xor-and.c [new file with mode: 0644]

index 8a1868b5324e7fde2b43de5145d89ce715b268db..7d3878107effc36680fcd5e8ff4aa82ca94c4055 100644 (file)
@@ -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.
index ce4eab45b922808bf4601a3f4a172e864c451053..4a8e3c6166726b76d0b33adde566b73d47a1fe00 100644 (file)
@@ -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
index 259bcc0bab291f42c292c0718439900553fb6da3..dbf0e213e39d82839ca3dca4e1835a1f10bde903 100644 (file)
@@ -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 (file)
index 0000000..4b0f790
--- /dev/null
@@ -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" } } */