This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[middle-end]: Handle rotate simplification on subregs.
- From: Alan Modra <amodra at bigpond dot net dot au>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 6 Sep 2005 11:05:20 +0930
- Subject: [middle-end]: Handle rotate simplification on subregs.
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=21017 is an enhancement
request to generate a rotate on 64-bit targets for something like:
unsigned int foo (unsigned int x)
{
return ((x >> 16) & 0xffff) | ((x & 0xffff) << 16);
}
On powerpc64-linux, the code in combine.c:simplify_logical that handles
simplification to a rotate is presented with
(ior:SI (lshiftrt:SI (subreg:SI (reg/v:DI 119 [ x ]) 4)
(const_int 16 [0x10]))
(subreg:SI (ashift:DI (reg/v:DI 119 [ x ])
(const_int 16 [0x10])) 4))
The second operand of ior has been "simplified" by simplify_shift_const
from (ashift:SI (subreg:SI (reg/v:DI 119 [ x ]) 4) (const_int 16 [0x10])),
which, if it was left that way, would allow a match. I think
simplify_shift_const is OK in what it's doing, ie. it is a useful
optimisation in other cases, so this patch allows the the subreg pattern
to match.
* combine.c (simplify_logical <IOR>): Simplify more patterns to
rotates.
Bootstrap and regression test in progress. Assuming that passes, is
this OK to queue for 4.2?
Index: gcc/combine.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/combine.c,v
retrieving revision 1.503
diff -u -p -r1.503 combine.c
--- gcc/combine.c 26 Aug 2005 21:52:23 -0000 1.503
+++ gcc/combine.c 6 Sep 2005 01:16:00 -0000
@@ -5553,7 +5553,7 @@ simplify_logical (rtx x)
enum machine_mode mode = GET_MODE (x);
rtx op0 = XEXP (x, 0);
rtx op1 = XEXP (x, 1);
- rtx reversed;
+ rtx tmp, reversed;
switch (GET_CODE (x))
{
@@ -5680,16 +5680,37 @@ simplify_logical (rtx x)
/* Convert (ior (ashift A CX) (lshiftrt A CY)) where CX+CY equals the
mode size to (rotate A CX). */
- if (((GET_CODE (op0) == ASHIFT && GET_CODE (op1) == LSHIFTRT)
- || (GET_CODE (op1) == ASHIFT && GET_CODE (op0) == LSHIFTRT))
+ if (GET_CODE (op1) == ASHIFT
+ || GET_CODE (op1) == SUBREG)
+ tmp = op1, op1 = op0, op0 = tmp;
+
+ if (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == LSHIFTRT
&& rtx_equal_p (XEXP (op0, 0), XEXP (op1, 0))
&& GET_CODE (XEXP (op0, 1)) == CONST_INT
&& GET_CODE (XEXP (op1, 1)) == CONST_INT
&& (INTVAL (XEXP (op0, 1)) + INTVAL (XEXP (op1, 1))
== GET_MODE_BITSIZE (mode)))
- return gen_rtx_ROTATE (mode, XEXP (op0, 0),
- (GET_CODE (op0) == ASHIFT
- ? XEXP (op0, 1) : XEXP (op1, 1)));
+ return gen_rtx_ROTATE (mode, XEXP (op1, 0), XEXP (op0, 1));
+
+ /* Same, but for ashift that has been "simplified" to a wider mode
+ by simplify_shift_const. */
+
+ if (GET_CODE (op0) == SUBREG
+ && GET_CODE (SUBREG_REG (op0)) == ASHIFT
+ && GET_CODE (op1) == LSHIFTRT
+ && GET_CODE (XEXP (op1, 0)) == SUBREG
+ && GET_MODE (op0) == GET_MODE (XEXP (op1, 0))
+ && SUBREG_BYTE (op0) == SUBREG_BYTE (XEXP (op1, 0))
+ && (GET_MODE_SIZE (GET_MODE (op0))
+ < GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0))))
+ && rtx_equal_p (XEXP (SUBREG_REG (op0), 0),
+ SUBREG_REG (XEXP (op1, 0)))
+ && GET_CODE (XEXP (SUBREG_REG (op0), 1)) == CONST_INT
+ && GET_CODE (XEXP (op1, 1)) == CONST_INT
+ && (INTVAL (XEXP (SUBREG_REG (op0), 1)) + INTVAL (XEXP (op1, 1))
+ == GET_MODE_BITSIZE (mode)))
+ return gen_rtx_ROTATE (mode, XEXP (op1, 0),
+ XEXP (SUBREG_REG (op0), 1));
/* If OP0 is (ashiftrt (plus ...) C), it might actually be
a (sign_extend (plus ...)). If so, OP1 is a CONST_INT, and the PLUS