On 2011/3/18 12:18 AM, Richard Henderson wrote:
> On 03/16/2011 06:55 PM, Chung-Lin Tang wrote:
>> You have to use DeMorgan's Law to distribute the ~ operator:
> 
> Duh.  Not sure where my head was yesterday.
> 
> Let's enhance the comment for someone else having an off day.  Perhaps
> 
>       /* Given (xor (and A B) C), using P^Q == ~P&Q | ~Q&P and DeMorgan's
>          we can transform
>               A&B ^ C == ~(A&B)&C | ~C&(A&B)
>                       == (~A|~B)&C | A&B&~C
>                       == ~A&C | ~B&C | A&B&~C
>          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)))
> 
> Should have a newline before the second && here.
> 
> Ok with those changes.

Thanks, committed patch attached below. Hope the comments are now
descriptive enough.

C.L.
Index: simplify-rtx.c
===================================================================
--- simplify-rtx.c      (revision 171207)
+++ simplify-rtx.c      (revision 171208)
@@ -2480,6 +2480,46 @@
                                                        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

Reply via email to