Commit 8c2a3f3b by Oleg Endo

re PR target/50751 (SH Target: Displacement addressing does not work for QImode and HImode)

	PR target/50751
	* config/sh/sh-protos.h (sh_legitimate_index_p): Add new arguments
	consider_sh2a and allow_zero.
	* config/sh/sh.c (sh_legitimate_index_p): Likewise.
	(disp_addr_displacement): New function.
	(sh_address_cost): Use disp_addr_displacement function instead
	of DISP_ADDR_OFFSET.
	(sh_legitimate_address_p): Adapt to changed
	sh_legitimate_index_p declaration.
	(sh_find_mov_disp_adjust): Remove HImode check.
	(sh_secondary_reload): Add HImode case.  Use satisfies_constraint_Sdd,
	disp_addr_displacement and max_mov_insn_displacement.
	(max_mov_insn_displacement): Remove HImode check.
	* config/sh/sh.h (CONST_OK_FOR_K04, CONST_OK_FOR_K12, 
	DISP_ADDR_P, DISP_ADDR_OFFSET): Remove.
	* config/sh/constraints.md (K05, K13): New constraints.
	(K12): Correct comment.
	(Sdd): Do not use DISP_ADDR_P macro.
	(Snd, Sbw): Use satisfies_constraint_Sdd.
	* config/sh/sh.md (extendhisi2): Remove constraints from expander.
	(*extendhisi2_compact, movhi_i): Remove.
	(*extendhisi2_compact_reg, *extendhisi2_compact_mem_disp,
	*extendhisi2_compact_mem_disp, *extendhisi2_compact_snd,
	*movhi_reg_reg, *movhi_store_mem_disp05, *movhi_store_mem_disp13,
	*movhi_load_mem_disp, *movhi_load_mem_disp, *movhi): New insns.
	(*extendqisi2_compact_mem_disp, *extendqisi2_compact_mem_disp,
	*movqi_store_mem_disp04, *movqi_store_mem_disp12, *movqi_load_mem_disp,
	*movqi_load_mem_disp): Use sh_legitimate_index_p instead of
	CONST_OK_FOR_Kxx.
	Add new peepholes for HImode displacement addressing.

From-SVN: r186311
parent b16212bd
2012-04-11 Oleg Endo <olegendo@gcc.gnu.org> 2012-04-11 Oleg Endo <olegendo@gcc.gnu.org>
PR target/50751
* config/sh/sh-protos.h (sh_legitimate_index_p): Add new arguments
consider_sh2a and allow_zero.
* config/sh/sh.c (sh_legitimate_index_p): Likewise.
(disp_addr_displacement): New function.
(sh_address_cost): Use disp_addr_displacement function instead
of DISP_ADDR_OFFSET.
(sh_legitimate_address_p): Adapt to changed
sh_legitimate_index_p declaration.
(sh_find_mov_disp_adjust): Remove HImode check.
(sh_secondary_reload): Add HImode case. Use satisfies_constraint_Sdd,
disp_addr_displacement and max_mov_insn_displacement.
(max_mov_insn_displacement): Remove HImode check.
* config/sh/sh.h (CONST_OK_FOR_K04, CONST_OK_FOR_K12,
DISP_ADDR_P, DISP_ADDR_OFFSET): Remove.
* config/sh/constraints.md (K05, K13): New constraints.
(K12): Correct comment.
(Sdd): Do not use DISP_ADDR_P macro.
(Snd, Sbw): Use satisfies_constraint_Sdd.
* config/sh/sh.md (extendhisi2): Remove constraints from expander.
(*extendhisi2_compact, movhi_i): Remove.
(*extendhisi2_compact_reg, *extendhisi2_compact_mem_disp,
*extendhisi2_compact_mem_disp, *extendhisi2_compact_snd,
*movhi_reg_reg, *movhi_store_mem_disp05, *movhi_store_mem_disp13,
*movhi_load_mem_disp, *movhi_load_mem_disp, *movhi): New insns.
(*extendqisi2_compact_mem_disp, *extendqisi2_compact_mem_disp,
*movqi_store_mem_disp04, *movqi_store_mem_disp12, *movqi_load_mem_disp,
*movqi_load_mem_disp): Use sh_legitimate_index_p instead of
CONST_OK_FOR_Kxx.
Add new peepholes for HImode displacement addressing.
2012-04-11 Oleg Endo <olegendo@gcc.gnu.org>
* config/sh/sh.h (SIDI_OFF): Remove. * config/sh/sh.h (SIDI_OFF): Remove.
* config/sh/sh.md: Use gen_highpart and gen_lowpart to access * config/sh/sh.md: Use gen_highpart and gen_lowpart to access
DImode subregs instead of gen_rtx_REG or simplifly_gen_subreg DImode subregs instead of gen_rtx_REG or simplifly_gen_subreg
......
...@@ -145,16 +145,28 @@ ...@@ -145,16 +145,28 @@
(and (match_code "const_int") (and (match_code "const_int")
(match_test "ival >= 0 && ival <= 15"))) (match_test "ival >= 0 && ival <= 15")))
(define_constraint "K05"
"An unsigned 5-bit constant, as used in mov.w displacement addressing."
(and (match_code "const_int")
(match_test "ival >= 0 && ival <= 31")))
(define_constraint "K08" (define_constraint "K08"
"An unsigned 8-bit constant, as used in and, or, etc." "An unsigned 8-bit constant, as used in and, or, etc."
(and (match_code "const_int") (and (match_code "const_int")
(match_test "ival >= 0 && ival <= 255"))) (match_test "ival >= 0 && ival <= 255")))
(define_constraint "K12" (define_constraint "K12"
"An unsigned 12-bit constant, as used in SH2A 12-bit displacement addressing." "An unsigned 12-bit constant, as used in SH2A 12-bit mov.b displacement
addressing."
(and (match_code "const_int") (and (match_code "const_int")
(match_test "ival >= 0 && ival <= 4095"))) (match_test "ival >= 0 && ival <= 4095")))
(define_constraint "K13"
"An unsigned 13-bit constant, as used in SH2A 12-bit mov.w displacement
addressing."
(and (match_code "const_int")
(match_test "ival >= 0 && ival <= 8191")))
(define_constraint "K16" (define_constraint "K16"
"An unsigned 16-bit constant, as used in SHmedia shori." "An unsigned 16-bit constant, as used in SHmedia shori."
(and (match_code "const_int") (and (match_code "const_int")
...@@ -262,6 +274,16 @@ ...@@ -262,6 +274,16 @@
(and (match_test "memory_operand (op, GET_MODE (op))") (and (match_test "memory_operand (op, GET_MODE (op))")
(match_test "GET_CODE (XEXP (op, 0)) != PLUS"))) (match_test "GET_CODE (XEXP (op, 0)) != PLUS")))
(define_memory_constraint "Sdd"
"A memory reference that uses displacement addressing."
(and (match_test "MEM_P (op) && GET_CODE (XEXP (op, 0)) == PLUS")
(match_test "REG_P (XEXP (XEXP (op, 0), 0))")
(match_test "CONST_INT_P (XEXP (XEXP (op, 0), 1))")))
(define_memory_constraint "Snd"
"A memory reference that excludes displacement addressing."
(match_test "! satisfies_constraint_Sdd (op)"))
(define_memory_constraint "Sbv" (define_memory_constraint "Sbv"
"A memory reference, as used in SH2A bclr.b, bset.b, etc." "A memory reference, as used in SH2A bclr.b, bset.b, etc."
(and (match_test "MEM_P (op) && GET_MODE (op) == QImode") (and (match_test "MEM_P (op) && GET_MODE (op) == QImode")
...@@ -269,15 +291,7 @@ ...@@ -269,15 +291,7 @@
(define_memory_constraint "Sbw" (define_memory_constraint "Sbw"
"A memory reference, as used in SH2A bclr.b, bset.b, etc." "A memory reference, as used in SH2A bclr.b, bset.b, etc."
(and (match_test "MEM_P (op) && GET_MODE (op) == QImode") (and (match_test "satisfies_constraint_Sdd (op)")
(match_test "GET_CODE (XEXP (op, 0)) == PLUS") (match_test "GET_MODE (op) == QImode")
(match_test "REG_P (XEXP (XEXP (op, 0), 0))")
(match_test "satisfies_constraint_K12 (XEXP (XEXP (op, 0), 1))"))) (match_test "satisfies_constraint_K12 (XEXP (XEXP (op, 0), 1))")))
(define_memory_constraint "Snd"
"A memory reference that excludes displacement addressing."
(match_test "! DISP_ADDR_P (op)"))
(define_memory_constraint "Sdd"
"A memory reference that uses displacement addressing."
(match_test "DISP_ADDR_P (op)"))
...@@ -404,7 +404,7 @@ ...@@ -404,7 +404,7 @@
if (GET_CODE (x) == PLUS if (GET_CODE (x) == PLUS
&& REG_P (XEXP (x, 0)) && REG_P (XEXP (x, 0))
&& CONST_INT_P (XEXP (x, 1))) && CONST_INT_P (XEXP (x, 1)))
return sh_legitimate_index_p (mode, XEXP (x, 1)); return sh_legitimate_index_p (mode, XEXP (x, 1), TARGET_SH2A, false);
} }
if (TARGET_SHMEDIA if (TARGET_SHMEDIA
...@@ -466,7 +466,7 @@ ...@@ -466,7 +466,7 @@
if (GET_CODE (x) == PLUS if (GET_CODE (x) == PLUS
&& REG_P (XEXP (x, 0)) && REG_P (XEXP (x, 0))
&& CONST_INT_P (XEXP (x, 1))) && CONST_INT_P (XEXP (x, 1)))
return sh_legitimate_index_p (mode, XEXP (x, 1)); return sh_legitimate_index_p (mode, XEXP (x, 1), TARGET_SH2A, false);
} }
return general_operand (op, mode); return general_operand (op, mode);
......
...@@ -56,7 +56,7 @@ extern int sh_loop_align (rtx); ...@@ -56,7 +56,7 @@ extern int sh_loop_align (rtx);
extern bool fp_zero_operand (rtx); extern bool fp_zero_operand (rtx);
extern bool fp_one_operand (rtx); extern bool fp_one_operand (rtx);
extern rtx get_fpscr_rtx (void); extern rtx get_fpscr_rtx (void);
extern bool sh_legitimate_index_p (enum machine_mode, rtx); extern bool sh_legitimate_index_p (enum machine_mode, rtx, bool, bool);
extern bool sh_legitimize_reload_address (rtx *, enum machine_mode, int, int); extern bool sh_legitimize_reload_address (rtx *, enum machine_mode, int, int);
extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx); extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
extern bool nonpic_symbol_mentioned_p (rtx); extern bool nonpic_symbol_mentioned_p (rtx);
......
...@@ -304,6 +304,7 @@ static bool sh_legitimate_constant_p (enum machine_mode, rtx); ...@@ -304,6 +304,7 @@ static bool sh_legitimate_constant_p (enum machine_mode, rtx);
static int mov_insn_size (enum machine_mode, bool); static int mov_insn_size (enum machine_mode, bool);
static int max_mov_insn_displacement (enum machine_mode, bool); static int max_mov_insn_displacement (enum machine_mode, bool);
static int mov_insn_alignment_mask (enum machine_mode, bool); static int mov_insn_alignment_mask (enum machine_mode, bool);
static HOST_WIDE_INT disp_addr_displacement (rtx);
static void sh_init_sync_libfuncs (void) ATTRIBUTE_UNUSED; static void sh_init_sync_libfuncs (void) ATTRIBUTE_UNUSED;
...@@ -3160,11 +3161,6 @@ max_mov_insn_displacement (enum machine_mode mode, bool consider_sh2a) ...@@ -3160,11 +3161,6 @@ max_mov_insn_displacement (enum machine_mode mode, bool consider_sh2a)
scale the max. displacement value accordingly. */ scale the max. displacement value accordingly. */
const int disp_scale = consider_sh2a ? (4095 / 15) : 1; const int disp_scale = consider_sh2a ? (4095 / 15) : 1;
/* FIXME: HImode with displacement addressing is not supported yet.
Make it purposefully fail for now. */
if (mode == HImode)
return 0;
/* SH2A supports FPU move insns with 12 bit displacements. /* SH2A supports FPU move insns with 12 bit displacements.
Other variants to do not support any kind of displacements for Other variants to do not support any kind of displacements for
FPU move insns. */ FPU move insns. */
...@@ -3194,15 +3190,24 @@ mov_insn_alignment_mask (enum machine_mode mode, bool consider_sh2a) ...@@ -3194,15 +3190,24 @@ mov_insn_alignment_mask (enum machine_mode mode, bool consider_sh2a)
return mov_insn_sz > 0 ? (mov_insn_sz - 1) : 0; return mov_insn_sz > 0 ? (mov_insn_sz - 1) : 0;
} }
/* Return the displacement value of a displacement address. */
static inline HOST_WIDE_INT
disp_addr_displacement (rtx x)
{
gcc_assert (satisfies_constraint_Sdd (x));
return INTVAL (XEXP (XEXP (x, 0), 1));
}
/* Compute the cost of an address. */ /* Compute the cost of an address. */
static int static int
sh_address_cost (rtx x, bool speed ATTRIBUTE_UNUSED) sh_address_cost (rtx x, bool speed ATTRIBUTE_UNUSED)
{ {
/* 'reg + disp' addressing. */ /* 'reg + disp' addressing. */
if (DISP_ADDR_P (x)) if (satisfies_constraint_Sdd (x))
{ {
const HOST_WIDE_INT offset = DISP_ADDR_OFFSET (x); const HOST_WIDE_INT offset = disp_addr_displacement (x);
const enum machine_mode mode = GET_MODE (x); const enum machine_mode mode = GET_MODE (x);
/* The displacement would fit into a 2 byte move insn. */ /* The displacement would fit into a 2 byte move insn. */
...@@ -9665,7 +9670,8 @@ sh_insn_length_adjustment (rtx insn) ...@@ -9665,7 +9670,8 @@ sh_insn_length_adjustment (rtx insn)
with MODE. */ with MODE. */
bool bool
sh_legitimate_index_p (enum machine_mode mode, rtx op) sh_legitimate_index_p (enum machine_mode mode, rtx op, bool consider_sh2a,
bool allow_zero)
{ {
if (! CONST_INT_P (op)) if (! CONST_INT_P (op))
return false; return false;
...@@ -9686,15 +9692,15 @@ sh_legitimate_index_p (enum machine_mode mode, rtx op) ...@@ -9686,15 +9692,15 @@ sh_legitimate_index_p (enum machine_mode mode, rtx op)
else else
{ {
const HOST_WIDE_INT offset = INTVAL (op); const HOST_WIDE_INT offset = INTVAL (op);
const int max_disp = max_mov_insn_displacement (mode, TARGET_SH2A); const int max_disp = max_mov_insn_displacement (mode, consider_sh2a);
const int align_mask = mov_insn_alignment_mask (mode, TARGET_SH2A); const int align_mask = mov_insn_alignment_mask (mode, consider_sh2a);
/* If the mode does not support any displacement always return false. /* If the mode does not support any displacement always return false.
Even though an index of '0' is actually always valid, it will cause Even though an index of '0' is actually always valid, it will cause
troubles when e.g. a DFmode move is split into two SFmode moves, troubles when e.g. a DFmode move is split into two SFmode moves,
where one SFmode move will have index '0' and the other move will where one SFmode move will have index '0' and the other move will
have index '4'. */ have index '4'. */
if (max_disp < 1) if (!allow_zero && max_disp < 1)
return false; return false;
return offset >= 0 && offset <= max_disp && (offset & align_mask) == 0; return offset >= 0 && offset <= max_disp && (offset & align_mask) == 0;
...@@ -9728,7 +9734,7 @@ sh_legitimate_address_p (enum machine_mode mode, rtx x, bool strict) ...@@ -9728,7 +9734,7 @@ sh_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
if (GET_MODE_SIZE (mode) <= 8 if (GET_MODE_SIZE (mode) <= 8
&& MAYBE_BASE_REGISTER_RTX_P (xop0, strict) && MAYBE_BASE_REGISTER_RTX_P (xop0, strict)
&& sh_legitimate_index_p (mode, xop1)) && sh_legitimate_index_p (mode, xop1, TARGET_SH2A, false))
return true; return true;
if ((ALLOW_INDEXED_ADDRESS || GET_MODE (x) == DImode if ((ALLOW_INDEXED_ADDRESS || GET_MODE (x) == DImode
...@@ -9875,11 +9881,6 @@ sh_find_mov_disp_adjust (enum machine_mode mode, HOST_WIDE_INT offset) ...@@ -9875,11 +9881,6 @@ sh_find_mov_disp_adjust (enum machine_mode mode, HOST_WIDE_INT offset)
if (mode_sz < 1 || mode_sz > 8 || max_disp < 1) if (mode_sz < 1 || mode_sz > 8 || max_disp < 1)
return res; return res;
/* FIXME: HImode with displacement addressing is not supported yet.
Make it purposefully fail for now. */
if (mov_insn_sz == 2)
return res;
/* Keeps the previous behavior for QImode displacement addressing. /* Keeps the previous behavior for QImode displacement addressing.
This just decides how the offset is re-based. Removing this special This just decides how the offset is re-based. Removing this special
case will result in slightly bigger code on average, but it's not that case will result in slightly bigger code on average, but it's not that
...@@ -12566,12 +12567,14 @@ sh_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i, ...@@ -12566,12 +12567,14 @@ sh_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
if (rclass == FPUL_REGS && true_regnum (x) == -1) if (rclass == FPUL_REGS && true_regnum (x) == -1)
return GENERAL_REGS; return GENERAL_REGS;
/* Force mov.b displacement addressing insn to use R0 as the other operand. /* Force mov.b / mov.w displacement addressing insn to use R0 as
the other operand.
On SH2A could also just leave it alone here, which would result in a On SH2A could also just leave it alone here, which would result in a
4 byte move insn being generated instead. However, for this to work 4 byte move insn being generated instead. However, for this to work
the insns must have the appropriate alternatives. */ the insns must have the appropriate alternatives. */
if (mode == QImode && rclass != R0_REGS if ((mode == QImode || mode == HImode) && rclass != R0_REGS
&& DISP_ADDR_P (x) && DISP_ADDR_OFFSET (x) < 16) && satisfies_constraint_Sdd (x)
&& disp_addr_displacement (x) <= max_mov_insn_displacement (mode, false))
return R0_REGS; return R0_REGS;
/* When reload is trying to address a QImode or HImode subreg on the stack, /* When reload is trying to address a QImode or HImode subreg on the stack,
......
...@@ -1210,24 +1210,12 @@ extern enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER]; ...@@ -1210,24 +1210,12 @@ extern enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER];
((HOST_BITS_PER_WIDE_INT >= 64 && (VALUE) == (HOST_WIDE_INT) 0xffffffff) \ ((HOST_BITS_PER_WIDE_INT >= 64 && (VALUE) == (HOST_WIDE_INT) 0xffffffff) \
|| (HOST_BITS_PER_WIDE_INT >= 64 && (VALUE) == (HOST_WIDE_INT) -1 << 32)) || (HOST_BITS_PER_WIDE_INT >= 64 && (VALUE) == (HOST_WIDE_INT) -1 << 32))
#define CONST_OK_FOR_K04(VALUE) (((HOST_WIDE_INT)(VALUE))>= 0 \
&& ((HOST_WIDE_INT)(VALUE)) <= 15)
#define CONST_OK_FOR_K08(VALUE) (((HOST_WIDE_INT)(VALUE))>= 0 \ #define CONST_OK_FOR_K08(VALUE) (((HOST_WIDE_INT)(VALUE))>= 0 \
&& ((HOST_WIDE_INT)(VALUE)) <= 255) && ((HOST_WIDE_INT)(VALUE)) <= 255)
#define CONST_OK_FOR_K12(VALUE) (((HOST_WIDE_INT)(VALUE))>= 0 \
&& ((HOST_WIDE_INT)(VALUE)) <= 4095)
#define ZERO_EXTRACT_ANDMASK(EXTRACT_SZ_RTX, EXTRACT_POS_RTX)\ #define ZERO_EXTRACT_ANDMASK(EXTRACT_SZ_RTX, EXTRACT_POS_RTX)\
(((1 << INTVAL (EXTRACT_SZ_RTX)) - 1) << INTVAL (EXTRACT_POS_RTX)) (((1 << INTVAL (EXTRACT_SZ_RTX)) - 1) << INTVAL (EXTRACT_POS_RTX))
#define DISP_ADDR_P(X) (MEM_P (X) && GET_CODE (XEXP (X, 0)) == PLUS \
&& REG_P (XEXP (XEXP (X, 0), 0)) \
&& CONST_INT_P (XEXP (XEXP (X, 0), 1)))
#define DISP_ADDR_OFFSET(X) (INTVAL (XEXP (XEXP (X, 0), 1)))
#if 0 #if 0
#define SECONDARY_INOUT_RELOAD_CLASS(CLASS,MODE,X,ELSE) \ #define SECONDARY_INOUT_RELOAD_CLASS(CLASS,MODE,X,ELSE) \
((((REGCLASS_HAS_FP_REG (CLASS) \ ((((REGCLASS_HAS_FP_REG (CLASS) \
......
...@@ -4743,20 +4743,18 @@ label: ...@@ -4743,20 +4743,18 @@ label:
operands[1] = XEXP (operands[1], 0); operands[1] = XEXP (operands[1], 0);
}) })
;; FIXME: Maybe fold HImode and QImode stuff with mode iterator?
(define_expand "extendhisi2" (define_expand "extendhisi2"
[(set (match_operand:SI 0 "arith_reg_dest" "=r,r") [(set (match_operand:SI 0 "arith_reg_dest" "")
(sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))] (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "")))]
"" ""
"") "")
(define_insn "*extendhisi2_compact" (define_expand "extendqisi2"
[(set (match_operand:SI 0 "arith_reg_dest" "=r,r") [(set (match_operand:SI 0 "arith_reg_dest" "")
(sign_extend:SI (match_operand:HI 1 "general_movsrc_operand" "r,m")))] (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "")))]
"TARGET_SH1" ""
"@ "")
exts.w %1,%0
mov.w %1,%0"
[(set_attr "type" "arith,load")])
(define_insn "*extendhisi2_media" (define_insn "*extendhisi2_media"
[(set (match_operand:SI 0 "register_operand" "=r,r") [(set (match_operand:SI 0 "register_operand" "=r,r")
...@@ -4786,12 +4784,6 @@ label: ...@@ -4786,12 +4784,6 @@ label:
subreg_lowpart_offset (SImode, GET_MODE (op1))); subreg_lowpart_offset (SImode, GET_MODE (op1)));
}) })
(define_expand "extendqisi2"
[(set (match_operand:SI 0 "arith_reg_dest" "")
(sign_extend:SI (match_operand:QI 1 "general_extend_operand" "")))]
""
"")
(define_insn "*extendqisi2_compact_reg" (define_insn "*extendqisi2_compact_reg"
[(set (match_operand:SI 0 "arith_reg_dest" "=r,r") [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
(sign_extend:SI (match_operand:QI 1 "register_operand" "r,t")))] (sign_extend:SI (match_operand:QI 1 "register_operand" "r,t")))]
...@@ -4801,6 +4793,15 @@ label: ...@@ -4801,6 +4793,15 @@ label:
movt %0" movt %0"
[(set_attr "type" "arith,arith")]) [(set_attr "type" "arith,arith")])
(define_insn "*extendhisi2_compact_reg"
[(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
(sign_extend:SI (match_operand:HI 1 "register_operand" "r,t")))]
"TARGET_SH1"
"@
exts.w %1,%0
movt %0"
[(set_attr "type" "arith,arith")])
;; FIXME: Fold non-SH2A and SH2A alternatives with "enabled" attribute. ;; FIXME: Fold non-SH2A and SH2A alternatives with "enabled" attribute.
;; See movqi insns. ;; See movqi insns.
(define_insn "*extendqisi2_compact_mem_disp" (define_insn "*extendqisi2_compact_mem_disp"
...@@ -4808,20 +4809,31 @@ label: ...@@ -4808,20 +4809,31 @@ label:
(sign_extend:SI (sign_extend:SI
(mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r") (mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r")
(match_operand:SI 2 "const_int_operand" "K04,N")))))] (match_operand:SI 2 "const_int_operand" "K04,N")))))]
"TARGET_SH1 && ! TARGET_SH2A && CONST_OK_FOR_K04 (INTVAL (operands[2]))" "TARGET_SH1 && ! TARGET_SH2A
&& sh_legitimate_index_p (QImode, operands[2], false, true)"
"@ "@
mov.b @(%O2,%1),%0 mov.b @(%O2,%1),%0
mov.b @%1,%0" mov.b @%1,%0"
[(set_attr "type" "load")]) [(set_attr "type" "load")])
(define_insn "*extendhisi2_compact_mem_disp"
[(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
(sign_extend:SI
(mem:HI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r")
(match_operand:SI 2 "const_int_operand" "K05,N")))))]
"TARGET_SH1 && ! TARGET_SH2A
&& sh_legitimate_index_p (HImode, operands[2], false, true)"
"@
mov.w @(%O2,%1),%0
mov.w @%1,%0"
[(set_attr "type" "load")])
(define_insn "*extendqisi2_compact_mem_disp" (define_insn "*extendqisi2_compact_mem_disp"
[(set (match_operand:SI 0 "arith_reg_dest" "=z,r,r") [(set (match_operand:SI 0 "arith_reg_dest" "=z,r,r")
(sign_extend:SI (sign_extend:SI
(mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r,r") (mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r,r")
(match_operand:SI 2 "const_int_operand" "K04,N,K12")))))] (match_operand:SI 2 "const_int_operand" "K04,N,K12")))))]
"TARGET_SH2A "TARGET_SH2A && sh_legitimate_index_p (QImode, operands[2], true, true)"
&& (CONST_OK_FOR_K04 (INTVAL (operands[2]))
|| (CONST_OK_FOR_K12 (INTVAL (operands[2]))))"
"@ "@
mov.b @(%O2,%1),%0 mov.b @(%O2,%1),%0
mov.b @%1,%0 mov.b @%1,%0
...@@ -4829,8 +4841,23 @@ label: ...@@ -4829,8 +4841,23 @@ label:
[(set_attr "type" "load") [(set_attr "type" "load")
(set_attr "length" "2,2,4")]) (set_attr "length" "2,2,4")])
;; This will take care of other QImode addressing modes than displacement (define_insn "*extendhisi2_compact_mem_disp"
;; addressing. [(set (match_operand:SI 0 "arith_reg_dest" "=z,r,r")
(sign_extend:SI
(mem:HI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r,r")
(match_operand:SI 2 "const_int_operand" "K05,N,K13")))))]
"TARGET_SH2A && sh_legitimate_index_p (HImode, operands[2], true, true)"
"@
mov.w @(%O2,%1),%0
mov.w @%1,%0
mov.w @(%O2,%1),%0"
[(set_attr "type" "load")
(set_attr "length" "2,2,4")])
;; The *_snd patterns will take care of other QImode/HImode addressing
;; modes than displacement addressing. They must be defined _after_ the
;; displacement addressing patterns. Otherwise the displacement addressing
;; patterns will not be picked.
(define_insn "*extendqisi2_compact_snd" (define_insn "*extendqisi2_compact_snd"
[(set (match_operand:SI 0 "arith_reg_dest" "=r") [(set (match_operand:SI 0 "arith_reg_dest" "=r")
(sign_extend:SI (match_operand:QI 1 "movsrc_no_disp_mem_operand" "Snd")))] (sign_extend:SI (match_operand:QI 1 "movsrc_no_disp_mem_operand" "Snd")))]
...@@ -4838,6 +4865,13 @@ label: ...@@ -4838,6 +4865,13 @@ label:
"mov.b %1,%0" "mov.b %1,%0"
[(set_attr "type" "load")]) [(set_attr "type" "load")])
(define_insn "*extendhisi2_compact_snd"
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
(sign_extend:SI (match_operand:HI 1 "movsrc_no_disp_mem_operand" "Snd")))]
"TARGET_SH1"
"mov.w %1,%0"
[(set_attr "type" "load")])
(define_insn "*extendqisi2_media" (define_insn "*extendqisi2_media"
[(set (match_operand:SI 0 "register_operand" "=r,r") [(set (match_operand:SI 0 "register_operand" "=r,r")
(sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))] (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))]
...@@ -5416,6 +5450,14 @@ label: ...@@ -5416,6 +5450,14 @@ label:
[(set_attr "type" "sfunc") [(set_attr "type" "sfunc")
(set_attr "needs_delay_slot" "yes")]) (set_attr "needs_delay_slot" "yes")])
(define_expand "movhi"
[(set (match_operand:HI 0 "general_movdst_operand" "")
(match_operand:HI 1 "general_movsrc_operand" ""))]
""
{
prepare_move_operands (operands, HImode);
})
(define_expand "movqi" (define_expand "movqi"
[(set (match_operand:QI 0 "general_operand" "") [(set (match_operand:QI 0 "general_operand" "")
(match_operand:QI 1 "general_operand" ""))] (match_operand:QI 1 "general_operand" ""))]
...@@ -5431,6 +5473,7 @@ label: ...@@ -5431,6 +5473,7 @@ label:
;; With the movqi_reg_reg being specified before movqi it will be intially ;; With the movqi_reg_reg being specified before movqi it will be intially
;; picked to load/store regs. If the regs regs are on the stack reload will ;; picked to load/store regs. If the regs regs are on the stack reload will
;; try other insns and not stick to movqi_reg_reg. ;; try other insns and not stick to movqi_reg_reg.
;; The same applies to the movhi variants.
(define_insn "*movqi_reg_reg" (define_insn "*movqi_reg_reg"
[(set (match_operand:QI 0 "arith_reg_dest" "=r,r") [(set (match_operand:QI 0 "arith_reg_dest" "=r,r")
(match_operand:QI 1 "register_operand" "r,t"))] (match_operand:QI 1 "register_operand" "r,t"))]
...@@ -5440,44 +5483,82 @@ label: ...@@ -5440,44 +5483,82 @@ label:
movt %0" movt %0"
[(set_attr "type" "move,arith")]) [(set_attr "type" "move,arith")])
(define_insn "*movhi_reg_reg"
[(set (match_operand:HI 0 "arith_reg_dest" "=r,r")
(match_operand:HI 1 "register_operand" "r,t"))]
"TARGET_SH1"
"@
mov %1,%0
movt %0"
[(set_attr "type" "move,arith")])
;; FIXME: The non-SH2A and SH2A variants should be combined by adding ;; FIXME: The non-SH2A and SH2A variants should be combined by adding
;; "enabled" attribute as it is done in other targets. ;; "enabled" attribute as it is done in other targets.
(define_insn "*movqi_store_mem_disp04" (define_insn "*movqi_store_mem_disp04"
[(set (mem:QI (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r,r") [(set (mem:QI (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r,r")
(match_operand:SI 1 "const_int_operand" "K04,N"))) (match_operand:SI 1 "const_int_operand" "K04,N")))
(match_operand:QI 2 "arith_reg_operand" "z,r"))] (match_operand:QI 2 "arith_reg_operand" "z,r"))]
"TARGET_SH1 && CONST_OK_FOR_K04 (INTVAL (operands[1]))" "TARGET_SH1 && sh_legitimate_index_p (QImode, operands[1], false, true)"
"@ "@
mov.b %2,@(%O1,%0) mov.b %2,@(%O1,%0)
mov.b %2,@%0" mov.b %2,@%0"
[(set_attr "type" "store")]) [(set_attr "type" "store")])
(define_insn "*movhi_store_mem_disp05"
[(set (mem:HI (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r,r")
(match_operand:SI 1 "const_int_operand" "K05,N")))
(match_operand:HI 2 "arith_reg_operand" "z,r"))]
"TARGET_SH1 && sh_legitimate_index_p (HImode, operands[1], false, true)"
"@
mov.w %2,@(%O1,%0)
mov.w %2,@%0"
[(set_attr "type" "store")])
(define_insn "*movqi_store_mem_disp12" (define_insn "*movqi_store_mem_disp12"
[(set (mem:QI (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r") [(set (mem:QI (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r")
(match_operand:SI 1 "const_int_operand" "K12"))) (match_operand:SI 1 "const_int_operand" "K12")))
(match_operand:QI 2 "arith_reg_operand" "r"))] (match_operand:QI 2 "arith_reg_operand" "r"))]
"TARGET_SH2A && CONST_OK_FOR_K12 (INTVAL (operands[1]))" "TARGET_SH2A && sh_legitimate_index_p (QImode, operands[1], true, true)"
"mov.b %2,@(%O1,%0)" "mov.b %2,@(%O1,%0)"
[(set_attr "type" "store") [(set_attr "type" "store")
(set_attr "length" "4")]) (set_attr "length" "4")])
(define_insn "*movhi_store_mem_disp13"
[(set (mem:HI (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r")
(match_operand:SI 1 "const_int_operand" "K13")))
(match_operand:HI 2 "arith_reg_operand" "r"))]
"TARGET_SH2A && sh_legitimate_index_p (HImode, operands[1], true, true)"
"mov.w %2,@(%O1,%0)"
[(set_attr "type" "store")
(set_attr "length" "4")])
(define_insn "*movqi_load_mem_disp" (define_insn "*movqi_load_mem_disp"
[(set (match_operand:QI 0 "arith_reg_dest" "=z,r") [(set (match_operand:QI 0 "arith_reg_dest" "=z,r")
(mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r") (mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r")
(match_operand:SI 2 "const_int_operand" "K04,N"))))] (match_operand:SI 2 "const_int_operand" "K04,N"))))]
"TARGET_SH1 && ! TARGET_SH2A && CONST_OK_FOR_K04 (INTVAL (operands[2]))" "TARGET_SH1 && ! TARGET_SH2A
&& sh_legitimate_index_p (QImode, operands[2], false, true)"
"@ "@
mov.b @(%O2,%1),%0 mov.b @(%O2,%1),%0
mov.b @%1,%0" mov.b @%1,%0"
[(set_attr "type" "load")]) [(set_attr "type" "load")])
(define_insn "*movhi_load_mem_disp"
[(set (match_operand:HI 0 "arith_reg_dest" "=z,r")
(mem:HI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r")
(match_operand:SI 2 "const_int_operand" "K05,N"))))]
"TARGET_SH1 && ! TARGET_SH2A
&& sh_legitimate_index_p (HImode, operands[2], false, true)"
"@
mov.w @(%O2,%1),%0
mov.w @%1,%0"
[(set_attr "type" "load")])
(define_insn "*movqi_load_mem_disp" (define_insn "*movqi_load_mem_disp"
[(set (match_operand:QI 0 "arith_reg_dest" "=z,r,r") [(set (match_operand:QI 0 "arith_reg_dest" "=z,r,r")
(mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r,r") (mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r,r")
(match_operand:SI 2 "const_int_operand" "K04,N,K12"))))] (match_operand:SI 2 "const_int_operand" "K04,N,K12"))))]
"TARGET_SH2A "TARGET_SH2A && sh_legitimate_index_p (QImode, operands[2], true, true)"
&& (CONST_OK_FOR_K04 (INTVAL (operands[2]))
|| CONST_OK_FOR_K12 (INTVAL (operands[2])))"
"@ "@
mov.b @(%O2,%1),%0 mov.b @(%O2,%1),%0
mov.b @%1,%0 mov.b @%1,%0
...@@ -5485,6 +5566,18 @@ label: ...@@ -5485,6 +5566,18 @@ label:
[(set_attr "type" "load") [(set_attr "type" "load")
(set_attr "length" "2,2,4")]) (set_attr "length" "2,2,4")])
(define_insn "*movhi_load_mem_disp"
[(set (match_operand:HI 0 "arith_reg_dest" "=z,r,r")
(mem:HI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r,r")
(match_operand:SI 2 "const_int_operand" "K05,N,K13"))))]
"TARGET_SH2A && sh_legitimate_index_p (HImode, operands[2], true, true)"
"@
mov.w @(%O2,%1),%0
mov.w @%1,%0
mov.w @(%O2,%1),%0"
[(set_attr "type" "load")
(set_attr "length" "2,2,4")])
;; The m constraints basically allow any kind of addresses to be used with any ;; The m constraints basically allow any kind of addresses to be used with any
;; source/target register as the other operand. This is not true for ;; source/target register as the other operand. This is not true for
;; displacement addressing modes on anything but SH2A. That's why the ;; displacement addressing modes on anything but SH2A. That's why the
...@@ -5503,6 +5596,21 @@ label: ...@@ -5503,6 +5596,21 @@ label:
lds %1,%0" lds %1,%0"
[(set_attr "type" "movi8,load,store,prget,prset")]) [(set_attr "type" "movi8,load,store,prget,prset")])
(define_insn "*movhi"
[(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,m,r,l")
(match_operand:HI 1 "general_movsrc_operand" "Q,i,m,r,l,r"))]
"TARGET_SH1
&& (arith_reg_operand (operands[0], HImode)
|| arith_reg_operand (operands[1], HImode))"
"@
mov.w %1,%0
mov %1,%0
mov.w %1,%0
mov.w %1,%0
sts %1,%0
lds %1,%0"
[(set_attr "type" "pcload,movi8,load,store,prget,prset")])
(define_insn "*movqi_media" (define_insn "*movqi_media"
[(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m") [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m")
(match_operand:QI 1 "general_movsrc_operand" "r,I16Css,m,rZ"))] (match_operand:QI 1 "general_movsrc_operand" "r,I16Css,m,rZ"))]
...@@ -5535,28 +5643,6 @@ label: ...@@ -5535,28 +5643,6 @@ label:
operands[3] = gen_rtx_REG (DImode, REGNO (operands[2])); operands[3] = gen_rtx_REG (DImode, REGNO (operands[2]));
}) })
;; When storing r0, we have to avoid reg+reg addressing.
(define_insn "movhi_i"
[(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,r,m,r,l,r")
(match_operand:HI 1 "general_movsrc_operand" "Q,rI08,m,t,r,l,r,i"))]
"TARGET_SH1
&& (arith_reg_operand (operands[0], HImode)
|| arith_reg_operand (operands[1], HImode))
&& (!MEM_P (operands[0])
|| GET_CODE (XEXP (operands[0], 0)) != PLUS
|| !REG_P (XEXP (XEXP (operands[0], 0), 1))
|| ! refers_to_regno_p (R0_REG, R0_REG + 1, operands[1], (rtx *)0))"
"@
mov.w %1,%0
mov %1,%0
mov.w %1,%0
movt %0
mov.w %1,%0
sts %1,%0
lds %1,%0
fake %1,%0"
[(set_attr "type" "pcload,move,load,move,store,move,move,pcload")])
(define_insn "*movhi_media" (define_insn "*movhi_media"
[(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,r,m") [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,r,m")
(match_operand:HI 1 "general_movsrc_operand" "r,I16Css,n,m,rZ"))] (match_operand:HI 1 "general_movsrc_operand" "r,I16Css,n,m,rZ"))]
...@@ -5582,14 +5668,6 @@ label: ...@@ -5582,14 +5668,6 @@ label:
&& ! satisfies_constraint_I16 (operands[1])" && ! satisfies_constraint_I16 (operands[1])"
[(set (subreg:DI (match_dup 0) 0) (match_dup 1))]) [(set (subreg:DI (match_dup 0) 0) (match_dup 1))])
(define_expand "movhi"
[(set (match_operand:HI 0 "general_movdst_operand" "")
(match_operand:HI 1 "general_movsrc_operand" ""))]
""
{
prepare_move_operands (operands, HImode);
})
(define_expand "reload_inhi" (define_expand "reload_inhi"
[(set (match_operand:SI 2 "" "=&r") [(set (match_operand:SI 2 "" "=&r")
(match_operand:HI 1 "inqhi_operand" "")) (match_operand:HI 1 "inqhi_operand" ""))
...@@ -11538,10 +11616,10 @@ label: ...@@ -11538,10 +11616,10 @@ label:
;; Fold sequence: ;; Fold sequence:
;; mov #54,r0 ;; mov #54,r0
;; mov.b @(r0,r15),r0 ;; mov.{b,w} @(r0,r15),r0
;; mov r0,r3 ;; mov r0,r3
;; into: ;; into:
;; mov.b @(54,r15),r3 ;; mov.{b,w} @(54,r15),r3
;; ;;
(define_peephole2 (define_peephole2
[(set (match_operand:SI 0 "arith_reg_dest" "") [(set (match_operand:SI 0 "arith_reg_dest" "")
...@@ -11553,17 +11631,33 @@ label: ...@@ -11553,17 +11631,33 @@ label:
(set (match_operand:QI 4 "arith_reg_dest" "") (set (match_operand:QI 4 "arith_reg_dest" "")
(match_operand:QI 5 "arith_reg_operand" ""))] (match_operand:QI 5 "arith_reg_operand" ""))]
"TARGET_SH2A "TARGET_SH2A
&& CONST_OK_FOR_K12 (INTVAL (operands[1])) && sh_legitimate_index_p (QImode, operands[1], true, true)
&& REGNO (operands[2]) == REGNO (operands[5]) && REGNO (operands[2]) == REGNO (operands[5])
&& peep2_reg_dead_p (3, operands[5])" && peep2_reg_dead_p (3, operands[5])"
[(set (match_dup 4) (mem:QI (plus:SI (match_dup 3) (match_dup 1))))] [(set (match_dup 4) (mem:QI (plus:SI (match_dup 3) (match_dup 1))))]
"") "")
(define_peephole2
[(set (match_operand:SI 0 "arith_reg_dest" "")
(match_operand:SI 1 "const_int_operand" ""))
(set (match_operand:SI 2 "arith_reg_dest" "")
(sign_extend:SI
(mem:HI (plus:SI (match_dup 0)
(match_operand:SI 3 "arith_reg_operand" "")))))
(set (match_operand:HI 4 "arith_reg_dest" "")
(match_operand:HI 5 "arith_reg_operand" ""))]
"TARGET_SH2A
&& sh_legitimate_index_p (HImode, operands[1], true, true)
&& REGNO (operands[2]) == REGNO (operands[5])
&& peep2_reg_dead_p (3, operands[5])"
[(set (match_dup 4) (mem:HI (plus:SI (match_dup 3) (match_dup 1))))]
"")
;; Fold sequence: ;; Fold sequence:
;; mov #54,r0 ;; mov #54,r0
;; mov.b @(r0,r15),r1 ;; mov.{b,w} @(r0,r15),r1
;; into: ;; into:
;; mov.b @(54,r15),r1 ;; mov.{b,w} @(54,r15),r1
;; ;;
(define_peephole2 (define_peephole2
[(set (match_operand:SI 0 "arith_reg_dest" "") [(set (match_operand:SI 0 "arith_reg_dest" "")
...@@ -11573,19 +11667,37 @@ label: ...@@ -11573,19 +11667,37 @@ label:
(mem:QI (plus:SI (match_dup 0) (mem:QI (plus:SI (match_dup 0)
(match_operand:SI 3 "arith_reg_operand" "")))))] (match_operand:SI 3 "arith_reg_operand" "")))))]
"TARGET_SH2A "TARGET_SH2A
&& CONST_OK_FOR_K12 (INTVAL (operands[1])) && sh_legitimate_index_p (QImode, operands[1], true, true)
&& (peep2_reg_dead_p (2, operands[0]) && (peep2_reg_dead_p (2, operands[0])
|| REGNO (operands[0]) == REGNO (operands[2]))" || REGNO (operands[0]) == REGNO (operands[2]))"
[(set (match_dup 2) [(set (match_dup 2)
(sign_extend:SI (mem:QI (plus:SI (match_dup 3) (match_dup 1)))))] (sign_extend:SI (mem:QI (plus:SI (match_dup 3) (match_dup 1)))))]
"") "")
(define_peephole2
[(set (match_operand:SI 0 "arith_reg_dest" "")
(match_operand:SI 1 "const_int_operand" ""))
(set (match_operand:SI 2 "arith_reg_dest" "")
(sign_extend:SI
(mem:HI (plus:SI (match_dup 0)
(match_operand:SI 3 "arith_reg_operand" "")))))]
"TARGET_SH2A
&& sh_legitimate_index_p (HImode, operands[1], true, true)
&& (peep2_reg_dead_p (2, operands[0])
|| REGNO (operands[0]) == REGNO (operands[2]))"
[(set (match_dup 2)
(sign_extend:SI (mem:HI (plus:SI (match_dup 3) (match_dup 1)))))]
"")
;; Fold sequence: ;; Fold sequence:
;; mov.b @(r0,r15),r0 ;; mov.{b,w} @(r0,r15),r0
;; mov r0,r3 ;; mov r0,r3
;; into: ;; into:
;; mov.b @(r0,r15),r3 ;; mov.{b,w} @(r0,r15),r3
;; ;;
;; This can happen when initially a displacement address is picked, where
;; the destination reg is fixed to r0, and then the address is transformed
;; into 'r0 + reg'.
(define_peephole2 (define_peephole2
[(set (match_operand:SI 0 "arith_reg_dest" "") [(set (match_operand:SI 0 "arith_reg_dest" "")
(sign_extend:SI (sign_extend:SI
...@@ -11600,6 +11712,20 @@ label: ...@@ -11600,6 +11712,20 @@ label:
(mem:QI (plus:SI (match_dup 1) (match_dup 2))))] (mem:QI (plus:SI (match_dup 1) (match_dup 2))))]
"") "")
(define_peephole2
[(set (match_operand:SI 0 "arith_reg_dest" "")
(sign_extend:SI
(mem:HI (plus:SI (match_operand:SI 1 "arith_reg_operand" "")
(match_operand:SI 2 "arith_reg_operand" "")))))
(set (match_operand:HI 3 "arith_reg_dest" "")
(match_operand:HI 4 "arith_reg_operand" ""))]
"TARGET_SH1
&& REGNO (operands[0]) == REGNO (operands[4])
&& peep2_reg_dead_p (2, operands[0])"
[(set (match_dup 3)
(mem:HI (plus:SI (match_dup 1) (match_dup 2))))]
"")
;; These convert sequences such as `mov #k,r0; add r15,r0; mov.l @r0,rn' ;; These convert sequences such as `mov #k,r0; add r15,r0; mov.l @r0,rn'
;; to `mov #k,r0; mov.l @(r0,r15),rn'. These sequences are generated by ;; to `mov #k,r0; mov.l @(r0,r15),rn'. These sequences are generated by
;; reload when the constant is too large for a reg+offset address. ;; reload when the constant is too large for a reg+offset address.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment