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) \
......
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