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]

[m68k 05/13] improve 64bit shift handling


Hi,

Originially this patch did fix one of the reload problems, but in the
meantime a slightly different patch went in, so this patch mainly cleans
up the 64bit shift handling.
It fixes many predicates to avoid unnecessary reloads, also the
expander definitions only accept register arguments and leaves
generating memory arguments (plus possible scratch register) to combine.
It also splits many constant shift operations into separate rtl
instructions where possible.


2007-01-30  Roman Zippel <zippel@linux-m68k.org>

	* config/m68k/m68k.c (split_di): New.
	* config/m68k/m68k-protos.h: Declare split_di.
	* config/m68k/m68k.md (ashldi3*,ashrdi3*,lshrdi3*):
	  Improve predicate handling and split constant shifts.

---
 gcc/config/m68k/m68k-protos.h |    3 
 gcc/config/m68k/m68k.c        |   26 +
 gcc/config/m68k/m68k.md       |  611 ++++++++++++++++++++++++++++++------------
 3 files changed, 476 insertions(+), 164 deletions(-)

Index: gcc/gcc/config/m68k/m68k-protos.h
===================================================================
--- gcc.orig/gcc/config/m68k/m68k-protos.h	2006-12-18 01:04:13.000000000 +0100
+++ gcc/gcc/config/m68k/m68k-protos.h	2006-12-26 01:57:15.000000000 +0100
@@ -22,5 +22,8 @@ Boston, MA 02110-1301, USA.  */
 
 #ifdef RTX_CODE
 extern HOST_WIDE_INT m68k_initial_elimination_offset (int from, int to);
+
+extern void split_di (rtx[], int, rtx[], rtx[]);
+
 extern bool valid_mov3q_const (HOST_WIDE_INT);
 extern const char *output_move_simode_const (rtx *);
Index: gcc/gcc/config/m68k/m68k.c
===================================================================
--- gcc.orig/gcc/config/m68k/m68k.c	2006-12-25 17:18:21.000000000 +0100
+++ gcc/gcc/config/m68k/m68k.c	2006-12-26 18:31:12.000000000 +0100
@@ -2454,6 +2454,32 @@ emit_move_sequence (rtx *operands, enum 
   return 0;
 }
 
+void
+split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
+{
+  while (num--)
+    {
+      rtx op = operands[num];
+
+      /* simplify_subreg refuse to split volatile memory addresses,
+	 but we still have to handle it.  */
+      if (GET_CODE (op) == MEM)
+	{
+	  lo_half[num] = adjust_address (op, SImode, 4);
+	  hi_half[num] = adjust_address (op, SImode, 0);
+	}
+      else
+	{
+	  lo_half[num] = simplify_gen_subreg (SImode, op,
+					      GET_MODE (op) == VOIDmode
+					      ? DImode : GET_MODE (op), 4);
+	  hi_half[num] = simplify_gen_subreg (SImode, op,
+					      GET_MODE (op) == VOIDmode
+					      ? DImode : GET_MODE (op), 0);
+	}
+    }
+}
+
 /* Return a REG that occurs in ADDR with coefficient 1.
    ADDR can be effectively incremented by incrementing REG.  */
 
Index: gcc/gcc/config/m68k/m68k.md
===================================================================
--- gcc.orig/gcc/config/m68k/m68k.md	2006-12-26 01:43:42.000000000 +0100
+++ gcc/gcc/config/m68k/m68k.md	2006-12-26 18:31:13.000000000 +0100
@@ -1496,17 +1496,31 @@
 })
 
 (define_insn "extendsidi2"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=d")
-	(sign_extend:DI
-	 (match_operand:SI 1 "general_operand" "rm")))]
+  [(set (match_operand:DI 0 "register_operand" "=d")
+	(sign_extend:DI (match_operand:SI 1 "nonimmediate_src_operand" "rm")))]
   ""
 {
   CC_STATUS_INIT;
-  operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
   if (TARGET_68020 || TARGET_COLDFIRE)
-    return "move%.l %1,%2\;smi %0\;extb%.l %0";
+    return "move%.l %1,%R0\;smi %0\;extb%.l %0";
   else
-    return "move%.l %1,%2\;smi %0\;ext%.w %0\;ext%.l %0";
+    return "move%.l %1,%R0\;smi %0\;ext%.w %0\;ext%.l %0";
+})
+
+(define_insn "*extendsidi2_mem"
+  [(set (match_operand:DI 0 "memory_operand" "=o,<")
+	(sign_extend:DI (match_operand:SI 1 "nonimmediate_src_operand" "rm,rm")))
+   (clobber (match_scratch:SI 2 "=d,d"))]
+   ""
+{
+  CC_STATUS_INIT;
+  operands[3] = adjust_address (operands[0], SImode,
+				which_alternative == 0 ? 4 : 0);
+  operands[0] = adjust_address (operands[0], SImode, 0);
+  if (TARGET_68020 || TARGET_COLDFIRE)
+    return "move%.l %1,%3\;smi %2\;extb%.l %2\;move%.l %2,%0";
+  else
+    return "move%.l %1,%3\;smi %2\;ext%.w %2\;ext%.l %2\;move%.l %2,%0";
 })
 
 ;; Special case when one can avoid register clobbering, copy and test
@@ -4095,69 +4109,168 @@
     return "move%.w %1,%0\;sub%.l %R0,%R0";
 })
 
-(define_insn "ashldi_const32"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
-	(ashift:DI (match_operand:DI 1 "general_operand" "ro")
-		     (const_int 32)))]
-  ""
+(define_insn "*ashldi3_const1"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+	(ashift:DI (match_operand:DI 1 "register_operand" "0")
+		   (const_int 1)))]
+  "!TARGET_COLDFIRE"
+  "add%.l %R0,%R0\;addx%.l %0,%0")
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+	(ashift:DI (match_operand:DI 1 "register_operand" "")
+		   (const_int 2)))]
+  "reload_completed && !TARGET_COLDFIRE"
+  [(set (match_dup 0)
+	(ashift:DI (match_dup 1) (const_int 1)))
+   (set (match_dup 0)
+	(ashift:DI (match_dup 0) (const_int 1)))]
+  "")
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+	(ashift:DI (match_operand:DI 1 "register_operand" "")
+		   (const_int 3)))]
+  "reload_completed && !TARGET_COLDFIRE"
+  [(set (match_dup 0)
+	(ashift:DI (match_dup 1) (const_int 2)))
+   (set (match_dup 0)
+	(ashift:DI (match_dup 0) (const_int 1)))]
+  "")
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+	(ashift:DI (match_operand:DI 1 "register_operand" "")
+		   (const_int 8)))]
+  "reload_completed && !TARGET_COLDFIRE"
+  [(set (match_dup 2)
+	(rotate:SI (match_dup 2) (const_int 8)))
+   (set (match_dup 3)
+	(rotate:SI (match_dup 3) (const_int 8)))
+   (set (strict_low_part (subreg:QI (match_dup 0) 3))
+	(subreg:QI (match_dup 0) 7))
+   (set (strict_low_part (subreg:QI (match_dup 0) 7))
+	(const_int 0))]
 {
-  CC_STATUS_INIT;
-  if (GET_CODE (operands[1]) == REG)
-    operands[3] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
-  else
-    operands[3] = adjust_address (operands[1], SImode, 4);
-  if (GET_CODE (operands[0]) == REG)
-    operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
-  else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
-    return "clr%.l %0\;move%.l %3,%0";
-  else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
-    return "move%.l %3,%0\;clr%.l %0";
-  else
-    operands[2] = adjust_address (operands[0], SImode, 4);
-  if (ADDRESS_REG_P (operands[2]))
-    return "move%.l %3,%0\;sub%.l %2,%2";
-  else
-    return "move%.l %3,%0\;clr%.l %2";
+  operands[2] = gen_highpart (SImode, operands[0]);
+  operands[3] = gen_lowpart (SImode, operands[0]);
 })
 
-;; The predicate below must be general_operand, because ashldi3 allows that
-(define_insn "ashldi_const"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=d")
-	(ashift:DI (match_operand:DI 1 "general_operand" "0")
-		     (match_operand 2 "const_int_operand" "n")))]
-  "(!TARGET_COLDFIRE
-    && ((INTVAL (operands[2]) >= 1 && INTVAL (operands[2]) <= 3)
-	|| INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16
-	|| (INTVAL (operands[2]) > 32 && INTVAL (operands[2]) <= 63)))"
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+	(ashift:DI (match_operand:DI 1 "register_operand" "")
+		   (const_int 16)))]
+  "reload_completed && !TARGET_COLDFIRE"
+  [(set (match_dup 2)
+	(rotate:SI (match_dup 2) (const_int 16)))
+   (set (match_dup 3)
+	(rotate:SI (match_dup 3) (const_int 16)))
+   (set (strict_low_part (subreg:HI (match_dup 0) 2))
+	(subreg:HI (match_dup 0) 6))
+   (set (strict_low_part (subreg:HI (match_dup 0) 6))
+	(const_int 0))]
 {
-  operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
-  if (INTVAL (operands[2]) == 1)
-    return "add%.l %1,%1\;addx%.l %0,%0";
-  else if (INTVAL (operands[2]) == 8)
-    return "rol%.l #8,%1\;rol%.l #8,%0\;move%.b %1,%0\;clr%.b %1";
-  else if (INTVAL (operands[2]) == 16)
-    return "swap %1\;swap %0\;move%.w %1,%0\;clr%.w %1";
-  else if (INTVAL (operands[2]) == 48)
-    return "mov%.l %1,%0\;swap %0\;clr%.l %1\;clr%.w %0";
-  else if (INTVAL (operands[2]) == 2)
-    return "add%.l %1,%1\;addx%.l %0,%0\;add%.l %1,%1\;addx%.l %0,%0";
-  else if (INTVAL (operands[2]) == 3)
-    return "add%.l %1,%1\;addx%.l %0,%0\;add%.l %1,%1\;addx%.l %0,%0\;add%.l %1,%1\;addx%.l %0,%0";
-  else /* 32 < INTVAL (operands[2]) <= 63 */
-    {
-      operands[2] = GEN_INT (INTVAL (operands[2]) - 32);
-      output_asm_insn (INTVAL (operands[2]) <= 8 ? "asl%.l %2,%1" :
-			"moveq %2,%0\;asl%.l %0,%1", operands);
-      return "mov%.l %1,%0\;moveq #0,%1";
-    }
+  operands[2] = gen_highpart (SImode, operands[0]);
+  operands[3] = gen_lowpart (SImode, operands[0]);
+})
+
+(define_split
+  [(set (match_operand:DI 0 "pre_dec_operand" "")
+	(ashift:DI (match_operand:DI 1 "nonimmediate_operand" "")
+		   (const_int 32)))]
+  "reload_completed"
+  [(set (match_dup 0) (const_int 0))
+   (set (match_dup 0) (match_dup 1))]
+{
+  operands[0] = adjust_address(operands[0], SImode, 0);
+  operands[1] = gen_lowpart(SImode, operands[1]);
+})
+
+(define_split
+  [(set (match_operand:DI 0 "post_inc_operand" "")
+	(ashift:DI (match_operand:DI 1 "nonimmediate_operand" "")
+		   (const_int 32)))]
+  "reload_completed"
+  [(set (match_dup 0) (match_dup 1))
+   (set (match_dup 0) (const_int 0))]
+{
+  operands[0] = adjust_address(operands[0], SImode, 0);
+  operands[1] = gen_lowpart(SImode, operands[1]);
+})
+
+(define_insn_and_split "*ashldi3_const32"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=ro<>")
+	(ashift:DI (match_operand:DI 1 "nonimmediate_operand" "ro")
+		   (const_int 32)))]
+  ""
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 4) (match_dup 3))
+   (set (match_dup 2) (const_int 0))]
+  "split_di(operands, 2, operands + 2, operands + 4);")
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+	(ashift:DI (match_operand:DI 1 "register_operand" "")
+		   (match_operand 2 "const_int_operand" "")))]
+  "reload_completed && !TARGET_COLDFIRE
+   && INTVAL (operands[2]) > 32 && INTVAL (operands[2]) <= 40"
+  [(set (match_dup 4) (ashift:SI (match_dup 4) (match_dup 2)))
+   (set (match_dup 3) (match_dup 4))
+   (set (match_dup 4) (const_int 0))]
+{
+  operands[2] = GEN_INT (INTVAL (operands[2]) - 32);
+  operands[3] = gen_highpart (SImode, operands[0]);
+  operands[4] = gen_lowpart (SImode, operands[0]);
+})
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+	(ashift:DI (match_operand:DI 1 "register_operand" "")
+		   (const_int 48)))]
+  "reload_completed && !TARGET_COLDFIRE"
+  [(set (match_dup 2) (match_dup 3))
+   (set (match_dup 2)
+	(rotate:SI (match_dup 2) (const_int 16)))
+   (set (match_dup 3) (const_int 0))
+   (set (strict_low_part (subreg:HI (match_dup 0) 2))
+	(const_int 0))]
+{
+  operands[2] = gen_highpart (SImode, operands[0]);
+  operands[3] = gen_lowpart (SImode, operands[0]);
+})
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+	(ashift:DI (match_operand:DI 1 "register_operand" "")
+		   (match_operand 2 "const_int_operand" "")))]
+  "reload_completed && !TARGET_COLDFIRE
+   && INTVAL (operands[2]) > 40 && INTVAL (operands[2]) <= 63"
+  [(set (match_dup 3) (match_dup 2))
+   (set (match_dup 4) (ashift:SI (match_dup 4) (match_dup 3)))
+   (set (match_dup 3) (match_dup 4))
+   (set (match_dup 4) (const_int 0))]
+{
+  operands[2] = GEN_INT (INTVAL (operands[2]) - 32);
+  operands[3] = gen_highpart (SImode, operands[0]);
+  operands[4] = gen_lowpart (SImode, operands[0]);
 })
 
+(define_insn "*ashldi3"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+	(ashift:DI (match_operand:DI 1 "register_operand" "0")
+		   (match_operand 2 "const_int_operand" "n")))]
+  "!TARGET_COLDFIRE
+    && ((INTVAL (operands[2]) >= 1 && INTVAL (operands[2]) <= 3)
+	|| INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16
+	|| (INTVAL (operands[2]) > 32 && INTVAL (operands[2]) <= 63))"
+  "#")
+
 (define_expand "ashldi3"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "")
-	(ashift:DI (match_operand:DI 1 "general_operand" "")
-		     (match_operand 2 "const_int_operand" "")))]
+  [(set (match_operand:DI 0 "register_operand" "")
+	(ashift:DI (match_operand:DI 1 "register_operand" "")
+		   (match_operand 2 "const_int_operand" "")))]
   "!TARGET_COLDFIRE"
-  "
 {
   /* ???  This is a named pattern like this is not allowed to FAIL based
      on its operands.  */
@@ -4166,7 +4279,7 @@
 	  && INTVAL (operands[2]) != 8 && INTVAL (operands[2]) != 16
 	  && (INTVAL (operands[2]) < 32 || INTVAL (operands[2]) > 63)))
     FAIL;
-} ")
+})
 
 ;; On most 68k models, this makes faster code in a special case.
 
@@ -4282,66 +4395,131 @@
   return "move%.l %1,%0";
 })
 
-(define_insn "ashrdi_const32"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=d,o,<")
-	(ashiftrt:DI (match_operand:DI 1 "general_operand" "ro,ro,ro")
+(define_insn "*ashrdi3_const1"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+	(ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
+		     (const_int 1)))]
+  "!TARGET_COLDFIRE"
+{
+  operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+  return "asr%.l #1,%0\;roxr%.l #1,%1";
+})
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+	(ashiftrt:DI (match_operand:DI 1 "register_operand" "")
+		     (const_int 2)))]
+  "reload_completed && !TARGET_COLDFIRE"
+  [(set (match_dup 0)
+	(ashiftrt:DI (match_dup 1) (const_int 1)))
+   (set (match_dup 0)
+	(ashiftrt:DI (match_dup 0) (const_int 1)))]
+  "")
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+	(ashiftrt:DI (match_operand:DI 1 "register_operand" "")
+		     (const_int 3)))]
+  "reload_completed && !TARGET_COLDFIRE"
+  [(set (match_dup 0)
+	(ashiftrt:DI (match_dup 1) (const_int 2)))
+   (set (match_dup 0)
+	(ashiftrt:DI (match_dup 0) (const_int 1)))]
+  "")
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+	(ashiftrt:DI (match_operand:DI 1 "register_operand" "")
+		     (const_int 8)))]
+  "reload_completed && !TARGET_COLDFIRE"
+  [(set (strict_low_part (subreg:QI (match_dup 0) 7))
+	(subreg:QI (match_dup 0) 3))
+   (set (match_dup 2)
+	(ashiftrt:SI (match_dup 2) (const_int 8)))
+   (set (match_dup 3)
+	(rotatert:SI (match_dup 3) (const_int 8)))]
+{
+  operands[2] = gen_highpart (SImode, operands[0]);
+  operands[3] = gen_lowpart (SImode, operands[0]);
+})
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+	(ashiftrt:DI (match_operand:DI 1 "register_operand" "")
+		     (const_int 16)))]
+  "reload_completed && !TARGET_COLDFIRE"
+  [(set (strict_low_part (subreg:HI (match_dup 0) 6))
+	(subreg:HI (match_dup 0) 2))
+   (set (match_dup 2)
+	(rotate:SI (match_dup 2) (const_int 16)))
+   (set (match_dup 3)
+	(rotate:SI (match_dup 3) (const_int 16)))
+   (set (match_dup 2)
+	(sign_extend:SI (subreg:HI (match_dup 2) 2)))]
+{
+  operands[2] = gen_highpart (SImode, operands[0]);
+  operands[3] = gen_lowpart (SImode, operands[0]);
+})
+
+(define_insn "*ashrdi_const32"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+	(ashiftrt:DI (match_operand:DI 1 "nonimmediate_src_operand" "ro")
+		     (const_int 32)))]
+  ""
+{
+  CC_STATUS_INIT;
+  if (TARGET_68020)
+    return "move%.l %1,%R0\;smi %0\;extb%.l %0";
+  else
+    return "move%.l %1,%R0\;smi %0\;ext%.w %0\;ext%.l %0";
+})
+
+(define_insn "*ashrdi_const32_mem"
+  [(set (match_operand:DI 0 "memory_operand" "=o,<")
+	(ashiftrt:DI (match_operand:DI 1 "nonimmediate_src_operand" "ro,ro")
 		     (const_int 32)))
-   (clobber (match_scratch:SI 2 "=X,d,d"))]
+   (clobber (match_scratch:SI 2 "=d,d"))]
   ""
 {
   CC_STATUS_INIT;
-  if (which_alternative == 0)
-    {
-      operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
-      if (TARGET_68020)
-	return "move%.l %1,%2\;smi %0\;extb%.l %0";
-      else
-	return "move%.l %1,%2\;smi %0\;ext%.w %0\;ext%.l %0";
-    }
+  operands[3] = adjust_address (operands[0], SImode,
+				which_alternative == 0 ? 4 : 0);
+  operands[0] = adjust_address (operands[0], SImode, 0);
+  if (TARGET_68020 || TARGET_COLDFIRE)
+    return "move%.l %1,%3\;smi %2\;extb%.l %2\;move%.l %2,%0";
   else
-    {
-      if (which_alternative == 2)
-	operands[3] = operands[0];
-      else if (which_alternative == 1)
-	operands[3] = adjust_address (operands[0], SImode, 4);
-      if (TARGET_68020)
-	return "move%.l %1,%3\;smi %2\;extb%.l %2\;move%.l %2,%0";
-      else
-	return "move%.l %1,%3\;smi %2\;ext%.w %2\;ext%.l %2\;move%.l %2,%0";
-    }
+    return "move%.l %1,%3\;smi %2\;ext%.w %2\;ext%.l %2\;move%.l %2,%0";
 })
 
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+	(ashiftrt:DI (match_operand:DI 1 "register_operand" "")
+		     (const_int 63)))]
+  "reload_completed && !TARGET_COLDFIRE"
+  [(set (match_dup 3)
+	(ashiftrt:SI (match_dup 3) (const_int 31)))
+   (set (match_dup 2)
+	(match_dup 3))]
+  "split_di(operands, 1, operands + 2, operands + 3);")
+
 ;; The predicate below must be general_operand, because ashrdi3 allows that
 (define_insn "ashrdi_const"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=d")
-	(ashiftrt:DI (match_operand:DI 1 "general_operand" "0")
-		     (match_operand 2 "const_int_operand" "n")))
-   (clobber (match_scratch:SI 3 "=X"))]
-  "(!TARGET_COLDFIRE 
+  [(set (match_operand:DI 0 "register_operand" "=d")
+	(ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
+		     (match_operand 2 "const_int_operand" "n")))]
+  "!TARGET_COLDFIRE
     && ((INTVAL (operands[2]) >= 1 && INTVAL (operands[2]) <= 3)
 	|| INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16
 	|| INTVAL (operands[2]) == 31
-	|| (INTVAL (operands[2]) > 32 && INTVAL (operands[2]) <= 63)))"
+	|| (INTVAL (operands[2]) > 32 && INTVAL (operands[2]) <= 63))"
 {
   operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
-  if (INTVAL (operands[2]) == 63)
-    return "add%.l %0,%0\;subx%.l %0,%0\;move%.l %0,%1";
   CC_STATUS_INIT;
-  if (INTVAL (operands[2]) == 1)
-    return "asr%.l #1,%0\;roxr%.l #1,%1";
-  else if (INTVAL (operands[2]) == 8)
-    return "move%.b %0,%1\;asr%.l #8,%0\;ror%.l #8,%1";
-  else if (INTVAL (operands[2]) == 16)
-    return "move%.w %0,%1\;swap %0\;ext%.l %0\;swap %1";
-  else if (INTVAL (operands[2]) == 48)
+  if (INTVAL (operands[2]) == 48)
     return "swap %0\;ext%.l %0\;move%.l %0,%1\;smi %0\;ext%.w %0";
-  else if (INTVAL (operands[2]) == 31)
+  if (INTVAL (operands[2]) == 31)
     return "add%.l %1,%1\;addx%.l %0,%0\;move%.l %0,%1\;subx%.l %0,%0";
-  else if (INTVAL (operands[2]) == 2)
-    return "asr%.l #1,%0\;roxr%.l #1,%1\;asr%.l #1,%0\;roxr%.l #1,%1";
-  else if (INTVAL (operands[2]) == 3)
-    return "asr%.l #1,%0\;roxr%.l #1,%1\;asr%.l #1,%0\;roxr%.l #1,%1\;asr%.l #1,%0\;roxr%.l #1,%1";
-  else /* 32 < INTVAL (operands[2]) <= 63 */
+  if (INTVAL (operands[2]) > 32 && INTVAL (operands[2]) <= 63)
     {
       operands[2] = GEN_INT (INTVAL (operands[2]) - 32);
       output_asm_insn (INTVAL (operands[2]) <= 8 ? "asr%.l %2,%0" :
@@ -4350,15 +4528,14 @@
       return INTVAL (operands[2]) >= 15 ? "ext%.w %d0" :
 	     TARGET_68020 ? "extb%.l %0" : "ext%.w %0\;ext%.l %0";
     }
+  return "#";
 })
 
 (define_expand "ashrdi3"
-  [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
-		   (ashiftrt:DI (match_operand:DI 1 "general_operand" "")
-				(match_operand 2 "const_int_operand" "")))
-	      (clobber (match_scratch:SI 3 ""))])]
+  [(set (match_operand:DI 0 "register_operand" "")
+	(ashiftrt:DI (match_operand:DI 1 "register_operand" "")
+		     (match_operand 2 "const_int_operand" "")))]
   "!TARGET_COLDFIRE"
-  "
 {
   /* ???  This is a named pattern like this is not allowed to FAIL based
      on its operands.  */
@@ -4367,8 +4544,7 @@
 	  && INTVAL (operands[2]) != 8 && INTVAL (operands[2]) != 16
 	  && (INTVAL (operands[2]) < 31 || INTVAL (operands[2]) > 63)))
     FAIL;
-  operands[3] = gen_rtx_SCRATCH (SImode);
-} ")
+})
 
 ;; On all 68k models, this makes faster code in a special case.
 
@@ -4456,69 +4632,176 @@
   return "move%.l %1,%0";
 })
 
-(define_insn "lshrdi_const32"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=ro,<,>")
-	(lshiftrt:DI (match_operand:DI 1 "general_operand" "ro,ro,ro")
+(define_insn "*lshrdi3_const1"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+	(lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
+		     (const_int 1)))]
+  "!TARGET_COLDFIRE"
+  "lsr%.l #1,%0\;roxr%.l #1,%R0")
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+	(lshiftrt:DI (match_operand:DI 1 "register_operand" "")
+		     (const_int 2)))]
+  "reload_completed && !TARGET_COLDFIRE"
+  [(set (match_dup 0)
+	(lshiftrt:DI (match_dup 1) (const_int 1)))
+   (set (match_dup 0)
+	(lshiftrt:DI (match_dup 0) (const_int 1)))]
+  "")
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+	(lshiftrt:DI (match_operand:DI 1 "register_operand" "")
+		     (const_int 3)))]
+  "reload_completed && !TARGET_COLDFIRE"
+  [(set (match_dup 0)
+	(lshiftrt:DI (match_dup 1) (const_int 2)))
+   (set (match_dup 0)
+	(lshiftrt:DI (match_dup 0) (const_int 1)))]
+  "")
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+	(lshiftrt:DI (match_operand:DI 1 "register_operand" "")
+		     (const_int 8)))]
+  "reload_completed && !TARGET_COLDFIRE"
+  [(set (strict_low_part (subreg:QI (match_dup 0) 7))
+	(subreg:QI (match_dup 0) 3))
+   (set (match_dup 2)
+	(lshiftrt:SI (match_dup 2) (const_int 8)))
+   (set (match_dup 3)
+	(rotatert:SI (match_dup 3) (const_int 8)))]
+{
+  operands[2] = gen_highpart (SImode, operands[0]);
+  operands[3] = gen_lowpart (SImode, operands[0]);
+})
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+	(lshiftrt:DI (match_operand:DI 1 "register_operand" "")
+		     (const_int 16)))]
+  "reload_completed && !TARGET_COLDFIRE"
+  [(set (strict_low_part (subreg:HI (match_dup 0) 6))
+	(subreg:HI (match_dup 0) 2))
+   (set (strict_low_part (subreg:HI (match_dup 0) 2))
+	(const_int 0))
+   (set (match_dup 3)
+	(rotate:SI (match_dup 3) (const_int 16)))
+   (set (match_dup 2)
+	(rotate:SI (match_dup 2) (const_int 16)))]
+{
+  operands[2] = gen_highpart (SImode, operands[0]);
+  operands[3] = gen_lowpart (SImode, operands[0]);
+})
+
+(define_split
+  [(set (match_operand:DI 0 "pre_dec_operand" "")
+	(lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "")
+		     (const_int 32)))]
+  "reload_completed"
+  [(set (match_dup 0) (match_dup 1))
+   (set (match_dup 0) (const_int 0))]
+{
+  operands[0] = adjust_address(operands[0], SImode, 0);
+  operands[1] = gen_highpart(SImode, operands[1]);
+})
+
+(define_split
+  [(set (match_operand:DI 0 "post_inc_operand" "")
+	(lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "")
+		     (const_int 32)))]
+  "reload_completed"
+  [(set (match_dup 0) (const_int 0))
+   (set (match_dup 0) (match_dup 1))]
+{
+  operands[0] = adjust_address(operands[0], SImode, 0);
+  operands[1] = gen_highpart(SImode, operands[1]);
+})
+
+(define_split
+  [(set (match_operand:DI 0 "nonimmediate_operand" "")
+	(lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "")
+		     (const_int 32)))]
+  "reload_completed"
+  [(set (match_dup 2) (match_dup 5))
+   (set (match_dup 4) (const_int 0))]
+  "split_di(operands, 2, operands + 2, operands + 4);")
+
+(define_insn "*lshrdi_const32"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=ro<>")
+	(lshiftrt:DI (match_operand:DI 1 "general_operand" "ro")
 		     (const_int 32)))]
   ""
+  "#")
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+	(lshiftrt:DI (match_operand:DI 1 "register_operand" "")
+		     (match_operand 2 "const_int_operand" "")))]
+  "reload_completed && !TARGET_COLDFIRE
+   && INTVAL (operands[2]) > 32 && INTVAL (operands[2]) <= 40"
+  [(set (match_dup 3) (lshiftrt:SI (match_dup 3) (match_dup 2)))
+   (set (match_dup 4) (match_dup 3))
+   (set (match_dup 3) (const_int 0))]
+{
+  operands[2] = GEN_INT (INTVAL (operands[2]) - 32);
+  operands[3] = gen_highpart (SImode, operands[0]);
+  operands[4] = gen_lowpart (SImode, operands[0]);
+})
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+	(lshiftrt:DI (match_operand:DI 1 "register_operand" "")
+		     (const_int 48)))]
+  "reload_completed"
+  [(set (match_dup 3) (match_dup 2))
+   (set (strict_low_part (subreg:HI (match_dup 0) 6))
+	(const_int 0))
+   (set (match_dup 2) (const_int 0))
+   (set (match_dup 3)
+	(rotate:SI (match_dup 3) (const_int 16)))]
 {
-  CC_STATUS_INIT;
-  if (which_alternative == 1)
-    return "move%.l %1,%0\;clr%.l %0";
-  if (which_alternative == 2)
-    return "clr%.l %0\;move%.l %1,%0";
-  if (GET_CODE (operands[0]) == REG)
-    operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
-  else
-    operands[2] = adjust_address (operands[0], SImode, 4);
-  if (GET_CODE (operands[1]) == REG)
-    operands[3] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
-  else
-    operands[3] = adjust_address (operands[1], SImode, 4);
-  if (ADDRESS_REG_P (operands[0]))
-    return "move%.l %1,%2\;sub%.l %0,%0";
-  else
-    return "move%.l %1,%2\;clr%.l %0";
+  operands[2] = gen_highpart (SImode, operands[0]);
+  operands[3] = gen_lowpart (SImode, operands[0]);
 })
 
-;; The predicate below must be general_operand, because lshrdi3 allows that
-(define_insn "lshrdi_const"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=d")
-	(lshiftrt:DI (match_operand:DI 1 "general_operand" "0")
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+	(lshiftrt:DI (match_operand:DI 1 "register_operand" "")
+		     (match_operand 2 "const_int_operand" "")))]
+  "reload_completed && !TARGET_COLDFIRE
+   && INTVAL (operands[2]) > 40 && INTVAL (operands[2]) <= 62"
+  [(set (match_dup 4) (match_dup 2))
+   (set (match_dup 3) (lshiftrt:SI (match_dup 3) (match_dup 4)))
+   (set (match_dup 4) (match_dup 3))
+   (set (match_dup 3) (const_int 0))]
+{
+  operands[2] = GEN_INT (INTVAL (operands[2]) - 32);
+  operands[3] = gen_highpart (SImode, operands[0]);
+  operands[4] = gen_lowpart (SImode, operands[0]);
+})
+
+(define_insn "*lshrdi_const63"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+	(lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
+		     (const_int 63)))]
+  ""
+  "add%.l %0,%0\;clr%.l %0\;clr%.l %R1\;addx%.l %R1,%R1")
+
+(define_insn "*lshrdi3_const"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+	(lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
 		     (match_operand 2 "const_int_operand" "n")))]
   "(!TARGET_COLDFIRE
-    && ((INTVAL (operands[2]) >= 1 && INTVAL (operands[2]) <= 3)
+    && ((INTVAL (operands[2]) >= 2 && INTVAL (operands[2]) <= 3)
 	 || INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16
 	 || (INTVAL (operands[2]) > 32 && INTVAL (operands[2]) <= 63)))"
-{
-  operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
-  if (INTVAL (operands[2]) == 63)
-    return "add%.l %0,%0\;clr%.l %0\;clr%.l %1\;addx%.l %1,%1";
-  CC_STATUS_INIT;
-  if (INTVAL (operands[2]) == 1)
-    return "lsr%.l #1,%0\;roxr%.l #1,%1";
-  else if (INTVAL (operands[2]) == 8)
-    return "move%.b %0,%1\;lsr%.l #8,%0\;ror%.l #8,%1";
-  else if (INTVAL (operands[2]) == 16)
-    return "move%.w %0,%1\;clr%.w %0\;swap %1\;swap %0";
-  else if (INTVAL (operands[2]) == 48)
-    return "move%.l %0,%1\;clr%.w %1\;clr%.l %0\;swap %1";
-  else if (INTVAL (operands[2]) == 2)
-    return "lsr%.l #1,%0\;roxr%.l #1,%1\;lsr%.l #1,%0\;roxr%.l #1,%1";
-  else if (INTVAL (operands[2]) == 3)
-    return "lsr%.l #1,%0\;roxr%.l #1,%1\;lsr%.l #1,%0\;roxr%.l #1,%1\;lsr%.l #1,%0\;roxr%.l #1,%1";
-  else /* 32 < INTVAL (operands[2]) <= 63 */
-    {
-      operands[2] = GEN_INT (INTVAL (operands[2]) - 32);
-      output_asm_insn (INTVAL (operands[2]) <= 8 ? "lsr%.l %2,%0" :
-			"moveq %2,%1\;lsr%.l %1,%0", operands);
-      return "mov%.l %0,%1\;moveq #0,%0";
-    }
-})
+  "#")
 
 (define_expand "lshrdi3"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "")
-	(lshiftrt:DI (match_operand:DI 1 "general_operand" "")
+  [(set (match_operand:DI 0 "register_operand" "")
+	(lshiftrt:DI (match_operand:DI 1 "register_operand" "")
 		     (match_operand 2 "const_int_operand" "")))]
   "!TARGET_COLDFIRE"
 {

--


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