https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90323
--- Comment #11 from luoxhu at gcc dot gnu.org --- I noticed that you added the below optimization with commit a62436c0a505155fc8becac07a8c0abe2c265bfe. But it doesn't even handle this case, cse1 pass will call simplify_binary_operation_1, both op0 and op1 are REGs instead of AND operators, do you have a test case to cover that piece of code? __attribute__ ((noinline)) long without_sel3( long l, long r) { long tmp = {0x0ff00fff}; l = ( (l ^ r) & tmp) ^ l; return l; } without_sel3: xor 4,3,4 rlwinm 4,4,0,20,11 rldicl 4,4,0,36 xor 3,4,3 blr .long 0 .byte 0,0,0,0,0,0,0,0 +2016-11-09 Segher Boessenkool <seg...@kernel.crashing.org> + + * simplify-rtx.c (simplify_binary_operation_1): Simplify + (xor (and (xor A B) C) B) to (ior (and A C) (and B ~C)) and + (xor (and (xor A B) C) A) to (ior (and A ~C) (and B C)) if C + is a const_int. diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 5c3dea1a349..11a2e0267c7 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -2886,6 +2886,37 @@ simplify_binary_operation_1 (enum rtx_code code, machine_mode mode, } } + /* If we have (xor (and (xor A B) C) A) with C a constant we can instead + do (ior (and A ~C) (and B C)) which is a machine instruction on some + machines, and also has shorter instruction path length. */ + if (GET_CODE (op0) == AND + && GET_CODE (XEXP (op0, 0)) == XOR + && CONST_INT_P (XEXP (op0, 1)) + && rtx_equal_p (XEXP (XEXP (op0, 0), 0), trueop1)) + { + rtx a = trueop1; + rtx b = XEXP (XEXP (op0, 0), 1); + rtx c = XEXP (op0, 1); + rtx nc = simplify_gen_unary (NOT, mode, c, mode); + rtx a_nc = simplify_gen_binary (AND, mode, a, nc); + rtx bc = simplify_gen_binary (AND, mode, b, c); + return simplify_gen_binary (IOR, mode, a_nc, bc); + } + /* Similarly, (xor (and (xor A B) C) B) as (ior (and A C) (and B ~C)) */ + else if (GET_CODE (op0) == AND + && GET_CODE (XEXP (op0, 0)) == XOR + && CONST_INT_P (XEXP (op0, 1)) + && rtx_equal_p (XEXP (XEXP (op0, 0), 1), trueop1)) + { + rtx a = XEXP (XEXP (op0, 0), 0); + rtx b = trueop1; + rtx c = XEXP (op0, 1); + rtx nc = simplify_gen_unary (NOT, mode, c, mode); + rtx b_nc = simplify_gen_binary (AND, mode, b, nc); + rtx ac = simplify_gen_binary (AND, mode, a, c); + return simplify_gen_binary (IOR, mode, ac, b_nc); + }