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>
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.md: Use gen_highpart and gen_lowpart to access
DImode subregs instead of gen_rtx_REG or simplifly_gen_subreg
......
......@@ -145,16 +145,28 @@
(and (match_code "const_int")
(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"
"An unsigned 8-bit constant, as used in and, or, etc."
(and (match_code "const_int")
(match_test "ival >= 0 && ival <= 255")))
(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")
(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"
"An unsigned 16-bit constant, as used in SHmedia shori."
(and (match_code "const_int")
......@@ -262,6 +274,16 @@
(and (match_test "memory_operand (op, GET_MODE (op))")
(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"
"A memory reference, as used in SH2A bclr.b, bset.b, etc."
(and (match_test "MEM_P (op) && GET_MODE (op) == QImode")
......@@ -269,15 +291,7 @@
(define_memory_constraint "Sbw"
"A memory reference, as used in SH2A bclr.b, bset.b, etc."
(and (match_test "MEM_P (op) && GET_MODE (op) == QImode")
(match_test "GET_CODE (XEXP (op, 0)) == PLUS")
(match_test "REG_P (XEXP (XEXP (op, 0), 0))")
(and (match_test "satisfies_constraint_Sdd (op)")
(match_test "GET_MODE (op) == QImode")
(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 @@
if (GET_CODE (x) == PLUS
&& REG_P (XEXP (x, 0))
&& 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
......@@ -466,7 +466,7 @@
if (GET_CODE (x) == PLUS
&& REG_P (XEXP (x, 0))
&& 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);
......
......@@ -56,7 +56,7 @@ extern int sh_loop_align (rtx);
extern bool fp_zero_operand (rtx);
extern bool fp_one_operand (rtx);
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 rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
extern bool nonpic_symbol_mentioned_p (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 max_mov_insn_displacement (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;
......@@ -3160,11 +3161,6 @@ max_mov_insn_displacement (enum machine_mode mode, bool consider_sh2a)
scale the max. displacement value accordingly. */
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.
Other variants to do not support any kind of displacements for
FPU move insns. */
......@@ -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 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. */
static int
sh_address_cost (rtx x, bool speed ATTRIBUTE_UNUSED)
{
/* '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);
/* The displacement would fit into a 2 byte move insn. */
......@@ -9665,7 +9670,8 @@ sh_insn_length_adjustment (rtx insn)
with MODE. */
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))
return false;
......@@ -9686,15 +9692,15 @@ sh_legitimate_index_p (enum machine_mode mode, rtx op)
else
{
const HOST_WIDE_INT offset = INTVAL (op);
const int max_disp = max_mov_insn_displacement (mode, TARGET_SH2A);
const int align_mask = mov_insn_alignment_mask (mode, TARGET_SH2A);
const int max_disp = max_mov_insn_displacement (mode, consider_sh2a);
const int align_mask = mov_insn_alignment_mask (mode, consider_sh2a);
/* If the mode does not support any displacement always return false.
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,
where one SFmode move will have index '0' and the other move will
have index '4'. */
if (max_disp < 1)
if (!allow_zero && max_disp < 1)
return false;
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)
if (GET_MODE_SIZE (mode) <= 8
&& MAYBE_BASE_REGISTER_RTX_P (xop0, strict)
&& sh_legitimate_index_p (mode, xop1))
&& sh_legitimate_index_p (mode, xop1, TARGET_SH2A, false))
return true;
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)
if (mode_sz < 1 || mode_sz > 8 || max_disp < 1)
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.
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
......@@ -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)
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
4 byte move insn being generated instead. However, for this to work
the insns must have the appropriate alternatives. */
if (mode == QImode && rclass != R0_REGS
&& DISP_ADDR_P (x) && DISP_ADDR_OFFSET (x) < 16)
if ((mode == QImode || mode == HImode) && rclass != R0_REGS
&& satisfies_constraint_Sdd (x)
&& disp_addr_displacement (x) <= max_mov_insn_displacement (mode, false))
return R0_REGS;
/* 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];
((HOST_BITS_PER_WIDE_INT >= 64 && (VALUE) == (HOST_WIDE_INT) 0xffffffff) \
|| (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 \
&& ((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)\
(((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
#define SECONDARY_INOUT_RELOAD_CLASS(CLASS,MODE,X,ELSE) \
((((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