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
This commit is contained in:
Segher Boessenkool 2016-11-10 01:32:43 +01:00 committed by Segher Boessenkool
parent a84a4f0b87
commit a62436c0a5
2 changed files with 38 additions and 0 deletions

View File

@ -1,3 +1,10 @@
2016-11-09 Segher Boessenkool <segher@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.
2016-11-09 David Malcolm <dmalcolm@redhat.com>
* print-rtl-function.c: Include varasm.h.

View File

@ -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