This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]