aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSegher Boessenkool <segher@kernel.crashing.org>2016-11-10 01:32:43 +0100
committerSegher Boessenkool <segher@gcc.gnu.org>2016-11-10 01:32:43 +0100
commita62436c0a505155fc8becac07a8c0abe2c265bfe (patch)
treebb6f4efa2648eb51dc815e233e1459b00835762f
parenta84a4f0b87c7ff9836a5b7c030be43aec6126966 (diff)
downloadgcc-a62436c0a505155fc8becac07a8c0abe2c265bfe.zip
gcc-a62436c0a505155fc8becac07a8c0abe2c265bfe.tar.gz
gcc-a62436c0a505155fc8becac07a8c0abe2c265bfe.tar.bz2
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
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/simplify-rtx.c31
2 files changed, 38 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index edf734f..c9034e8d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index 5c3dea1..11a2e02 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