From a62436c0a505155fc8becac07a8c0abe2c265bfe Mon Sep 17 00:00:00 2001 From: Segher Boessenkool Date: Thu, 10 Nov 2016 01:32:43 +0100 Subject: [PATCH] simplify-rtx: Transform (xor (and (xor A B) C) B) with C const match.pd transforms (A&C)|(B&~C) to ((A^B)&C)^B, which is fewer operations if C is not const (and it is not on simple tests at least, this transform is done very early already). Various processors have "insert" instructions that can do this, but combine cannot build those from the xor-and-xor, especially it has no chance at all to do that if A or B or multiple instructions as well (on PowerPC, the rl[wd]imi instructions can do this with together with a rotate, or a simple shift with appropriate C; other ISAs have similar insns). This patch makes RTL simplify transform (xor (and (xor A B) C) B) back to (ior (and A C) (and B ~C)) for constant C (and similar with A instead of B for that last term). * 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. From-SVN: r242031 --- gcc/ChangeLog | 7 +++++++ gcc/simplify-rtx.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index edf734fa9a6..c9034e8dca4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2016-11-09 Segher Boessenkool + + * 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. + 2016-11-09 David Malcolm * print-rtl-function.c: Include varasm.h. 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); + } + /* (xor (comparison foo bar) (const_int 1)) can become the reversed comparison if STORE_FLAG_VALUE is 1. */ if (STORE_FLAG_VALUE == 1 -- 2.30.2