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