simplify-rtx: Transform (xor (and (xor A B) C) B) with C const
authorSegher Boessenkool <segher@kernel.crashing.org>
Thu, 10 Nov 2016 00:32:43 +0000 (01:32 +0100)
committerSegher Boessenkool <segher@gcc.gnu.org>
Thu, 10 Nov 2016 00:32:43 +0000 (01:32 +0100)
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
gcc/simplify-rtx.c

index edf734fa9a6422c6e14e915e701cf114f6e80a00..c9034e8dca4efe3fd7b6469125623080bf856594 100644 (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.
index 5c3dea1a349f6546260864b7580bfb1170c1904b..11a2e0267c7d182f2d92ebc86befe6b70c606384 100644 (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