This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[m68k 05/13] improve 64bit shift handling
- From: zippel at linux-m68k dot org
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 30 Jan 2007 12:26:20 +0100
- Subject: [m68k 05/13] improve 64bit shift handling
- References: <20070130112615.782382000@linux-m68k.org>
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"
{
--