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