sh-protos.h (sh_legitimate_index_p): Declare.

* config/sh/sh-protos.h (sh_legitimate_index_p): Declare.
	(sh_legitimate_address_p): Likewise.
	* config/sh/sh.c (sh_legitimate_index_p): New.
	(sh_legitimate_address_p): Likewise.
	* config/sh/sh.h (REG_OK_FOR_BASE_P): Add STRICT parameter.
	(REG_OK_FOR_INDEX_P, SUBREG_OK_FOR_INDEX_P): Likewise.
	(MODE_DISP_OK_4, MODE_DISP_OK_8): Remove.
	(MAYBE_BASE_REGISTER_RTX_P): New macro.
	(MAYBE_INDEX_REGISTER_RTX_P): Likewise.
	(BASE_REGISTER_RTX_P): Use MAYBE_BASE_REGISTER_RTX_P.
	(INDEX_REGISTER_RTX_P): Use MAYBE_INDEX_REGISTER_RTX_P.
	(GO_IF_LEGITIMATE_INDEX): Use sh_legitimate_index_p.
	(GO_IF_LEGITIMATE_ADDRESS): Use sh_legitimate_address_p.

From-SVN: r147450
This commit is contained in:
Kaz Kojima 2009-05-12 22:41:54 +00:00
parent 1195342643
commit cdeed45ae6
4 changed files with 188 additions and 161 deletions

View File

@ -1,3 +1,19 @@
2009-05-12 Kaz Kojima <kkojima@gcc.gnu.org>
* config/sh/sh-protos.h (sh_legitimate_index_p): Declare.
(sh_legitimate_address_p): Likewise.
* config/sh/sh.c (sh_legitimate_index_p): New.
(sh_legitimate_address_p): Likewise.
* config/sh/sh.h (REG_OK_FOR_BASE_P): Add STRICT parameter.
(REG_OK_FOR_INDEX_P, SUBREG_OK_FOR_INDEX_P): Likewise.
(MODE_DISP_OK_4, MODE_DISP_OK_8): Remove.
(MAYBE_BASE_REGISTER_RTX_P): New macro.
(MAYBE_INDEX_REGISTER_RTX_P): Likewise.
(BASE_REGISTER_RTX_P): Use MAYBE_BASE_REGISTER_RTX_P.
(INDEX_REGISTER_RTX_P): Use MAYBE_INDEX_REGISTER_RTX_P.
(GO_IF_LEGITIMATE_INDEX): Use sh_legitimate_index_p.
(GO_IF_LEGITIMATE_ADDRESS): Use sh_legitimate_address_p.
2009-05-12 Jan Hubicka <jh@suse.cz>
* tree-inline.c (estimate_operator_cost): Add operands;

View File

@ -58,6 +58,8 @@ extern int fp_zero_operand (rtx);
extern int fp_one_operand (rtx);
extern int fp_int_operand (rtx);
extern rtx get_fpscr_rtx (void);
extern bool sh_legitimate_index_p (enum machine_mode, rtx);
extern bool sh_legitimate_address_p (enum machine_mode, rtx, bool);
extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
extern int nonpic_symbol_mentioned_p (rtx);
extern void emit_sf_insn (rtx);

View File

@ -8950,6 +8950,124 @@ sh_insn_length_adjustment (rtx insn)
return 0;
}
/* Return TRUE for a valid displacement for the REG+disp addressing
with MODE. */
/* ??? The SH2e does not have the REG+disp addressing mode when loading values
into the FRx registers. We implement this by setting the maximum offset
to zero when the value is SFmode. This also restricts loading of SFmode
values into the integer registers, but that can't be helped. */
/* The SH allows a displacement in a QI or HI amode, but only when the
other operand is R0. GCC doesn't handle this very well, so we forgot
all of that.
A legitimate index for a QI or HI is 0, SI can be any number 0..63,
DI can be any number 0..60. */
bool
sh_legitimate_index_p (enum machine_mode mode, rtx op)
{
if (GET_CODE (op) == CONST_INT)
{
if (TARGET_SHMEDIA)
{
int size;
/* Check if this the address of an unaligned load / store. */
if (mode == VOIDmode)
return CONST_OK_FOR_I06 (INTVAL (op));
size = GET_MODE_SIZE (mode);
return (!(INTVAL (op) & (size - 1))
&& INTVAL (op) >= -512 * size
&& INTVAL (op) < 512 * size);
}
if (TARGET_SH2A)
{
if (GET_MODE_SIZE (mode) == 1
&& (unsigned) INTVAL (op) < 4096)
return true;
}
if ((GET_MODE_SIZE (mode) == 4
&& (unsigned) INTVAL (op) < 64
&& !(INTVAL (op) & 3)
&& !(TARGET_SH2E && mode == SFmode))
|| (GET_MODE_SIZE (mode) == 4
&& (unsigned) INTVAL (op) < 16383
&& !(INTVAL (op) & 3) && TARGET_SH2A))
return true;
if ((GET_MODE_SIZE (mode) == 8
&& (unsigned) INTVAL (op) < 60
&& !(INTVAL (op) & 3)
&& !((TARGET_SH4 || TARGET_SH2A) && mode == DFmode))
|| ((GET_MODE_SIZE (mode)==8)
&& (unsigned) INTVAL (op) < 8192
&& !(INTVAL (op) & (TARGET_SH2A_DOUBLE ? 7 : 3))
&& (TARGET_SH2A && mode == DFmode)))
return true;
}
return false;
}
/* Recognize an RTL expression that is a valid memory address for
an instruction.
The MODE argument is the machine mode for the MEM expression
that wants to use this address.
Allow REG
REG+disp
REG+r0
REG++
--REG */
bool
sh_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
{
if (MAYBE_BASE_REGISTER_RTX_P (x, strict))
return true;
else if ((GET_CODE (x) == POST_INC || GET_CODE (x) == PRE_DEC)
&& ! TARGET_SHMEDIA
&& MAYBE_BASE_REGISTER_RTX_P (XEXP (x, 0), strict))
return true;
else if (GET_CODE (x) == PLUS
&& (mode != PSImode || reload_completed))
{
rtx xop0 = XEXP (x, 0);
rtx xop1 = XEXP (x, 1);
if (GET_MODE_SIZE (mode) <= 8
&& MAYBE_BASE_REGISTER_RTX_P (xop0, strict)
&& sh_legitimate_index_p (mode, xop1))
return true;
if ((ALLOW_INDEXED_ADDRESS || GET_MODE (x) == DImode
|| ((xop0 == stack_pointer_rtx
|| xop0 == hard_frame_pointer_rtx)
&& REG_P (xop1) && REGNO (xop1) == R0_REG)
|| ((xop1 == stack_pointer_rtx
|| xop1 == hard_frame_pointer_rtx)
&& REG_P (xop0) && REGNO (xop0) == R0_REG))
&& ((!TARGET_SHMEDIA && GET_MODE_SIZE (mode) <= 4)
|| (TARGET_SHMEDIA && GET_MODE_SIZE (mode) <= 8)
|| ((TARGET_SH4 || TARGET_SH2A_DOUBLE)
&& TARGET_FMOVD && mode == DFmode)))
{
if (MAYBE_BASE_REGISTER_RTX_P (xop1, strict)
&& MAYBE_INDEX_REGISTER_RTX_P (xop0, strict))
return true;
if (MAYBE_INDEX_REGISTER_RTX_P (xop1, strict)
&& MAYBE_BASE_REGISTER_RTX_P (xop0, strict))
return true;
}
}
return false;
}
/* Return TRUE if X references a SYMBOL_REF or LABEL_REF whose symbol
isn't protected by a PIC unspec. */
int

View File

@ -2191,45 +2191,25 @@ struct sh_args {
/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
and check its validity for a certain class.
We have two alternate definitions for each of them.
The usual definition accepts all pseudo regs; the other rejects
them unless they have been allocated suitable hard regs.
The symbol REG_OK_STRICT causes the latter definition to be used. */
The suitable hard regs are always accepted and all pseudo regs
are also accepted if STRICT is not set. */
#ifndef REG_OK_STRICT
/* Nonzero if X is a reg that can be used as a base reg. */
#define REG_OK_FOR_BASE_P(X, STRICT) \
(GENERAL_OR_AP_REGISTER_P (REGNO (X)) \
|| (!STRICT && REGNO (X) >= FIRST_PSEUDO_REGISTER))
/* Nonzero if X is a hard reg that can be used as a base reg
or if it is a pseudo reg. */
#define REG_OK_FOR_BASE_P(X) \
(GENERAL_OR_AP_REGISTER_P (REGNO (X)) || REGNO (X) >= FIRST_PSEUDO_REGISTER)
/* Nonzero if X is a reg that can be used as an index. */
#define REG_OK_FOR_INDEX_P(X, STRICT) \
((TARGET_SHMEDIA ? GENERAL_REGISTER_P (REGNO (X)) \
: REGNO (X) == R0_REG) \
|| (!STRICT && REGNO (X) >= FIRST_PSEUDO_REGISTER))
/* Nonzero if X is a hard reg that can be used as an index
or if it is a pseudo reg. */
#define REG_OK_FOR_INDEX_P(X) \
((TARGET_SHMEDIA ? GENERAL_REGISTER_P (REGNO (X)) \
: REGNO (X) == R0_REG) || REGNO (X) >= FIRST_PSEUDO_REGISTER)
/* Nonzero if X/OFFSET is a hard reg that can be used as an index
or if X is a pseudo reg. */
#define SUBREG_OK_FOR_INDEX_P(X, OFFSET) \
((TARGET_SHMEDIA ? GENERAL_REGISTER_P (REGNO (X)) \
: REGNO (X) == R0_REG && OFFSET == 0) || REGNO (X) >= FIRST_PSEUDO_REGISTER)
#else
/* Nonzero if X is a hard reg that can be used as a base reg. */
#define REG_OK_FOR_BASE_P(X) \
REGNO_OK_FOR_BASE_P (REGNO (X))
/* Nonzero if X is a hard reg that can be used as an index. */
#define REG_OK_FOR_INDEX_P(X) \
REGNO_OK_FOR_INDEX_P (REGNO (X))
/* Nonzero if X/OFFSET is a hard reg that can be used as an index. */
#define SUBREG_OK_FOR_INDEX_P(X, OFFSET) \
(REGNO_OK_FOR_INDEX_P (REGNO (X)) && (OFFSET) == 0)
#endif
/* Nonzero if X/OFFSET is a reg that can be used as an index. */
#define SUBREG_OK_FOR_INDEX_P(X, OFFSET, STRICT) \
((TARGET_SHMEDIA ? GENERAL_REGISTER_P (REGNO (X)) \
: REGNO (X) == R0_REG && OFFSET == 0) \
|| (!STRICT && REGNO (X) >= FIRST_PSEUDO_REGISTER))
/* Macros for extra constraints. */
@ -2305,144 +2285,55 @@ struct sh_args {
|| PCREL_SYMOFF_P (OP)) \
: NON_PIC_REFERENCE_P (OP))
/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
that is a valid memory address for an instruction.
The MODE argument is the machine mode for the MEM expression
that wants to use this address. */
#define MODE_DISP_OK_4(X,MODE) \
(GET_MODE_SIZE (MODE) == 4 && (unsigned) INTVAL (X) < 64 \
&& ! (INTVAL (X) & 3) && ! (TARGET_SH2E && (MODE) == SFmode))
#define MODE_DISP_OK_8(X,MODE) \
((GET_MODE_SIZE(MODE)==8) && ((unsigned)INTVAL(X)<60) \
&& ! (INTVAL(X) & 3) && ! (TARGET_SH4 && (MODE) == DFmode))
#undef MODE_DISP_OK_4
#define MODE_DISP_OK_4(X,MODE) \
((GET_MODE_SIZE (MODE) == 4 && (unsigned) INTVAL (X) < 64 \
&& ! (INTVAL (X) & 3) && ! (TARGET_SH2E && (MODE) == SFmode)) \
|| ((GET_MODE_SIZE(MODE)==4) && ((unsigned)INTVAL(X)<16383) \
&& ! (INTVAL(X) & 3) && TARGET_SH2A))
#undef MODE_DISP_OK_8
#define MODE_DISP_OK_8(X,MODE) \
(((GET_MODE_SIZE(MODE)==8) && ((unsigned)INTVAL(X)<60) \
&& ! (INTVAL(X) & 3) && ! ((TARGET_SH4 || TARGET_SH2A) && (MODE) == DFmode)) \
|| ((GET_MODE_SIZE(MODE)==8) && ((unsigned)INTVAL(X)<8192) \
&& ! (INTVAL(X) & (TARGET_SH2A_DOUBLE ? 7 : 3)) && (TARGET_SH2A && (MODE) == DFmode)))
#define BASE_REGISTER_RTX_P(X) \
((GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \
|| (GET_CODE (X) == SUBREG \
&& TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (GET_MODE ((X))), \
#define MAYBE_BASE_REGISTER_RTX_P(X, STRICT) \
((GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X, STRICT)) \
|| (GET_CODE (X) == SUBREG \
&& TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (GET_MODE ((X))), \
GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (X)))) \
&& GET_CODE (SUBREG_REG (X)) == REG \
&& REG_OK_FOR_BASE_P (SUBREG_REG (X))))
&& GET_CODE (SUBREG_REG (X)) == REG \
&& REG_OK_FOR_BASE_P (SUBREG_REG (X), STRICT)))
/* Since this must be r0, which is a single register class, we must check
SUBREGs more carefully, to be sure that we don't accept one that extends
outside the class. */
#define INDEX_REGISTER_RTX_P(X) \
((GET_CODE (X) == REG && REG_OK_FOR_INDEX_P (X)) \
|| (GET_CODE (X) == SUBREG \
#define MAYBE_INDEX_REGISTER_RTX_P(X, STRICT) \
((GET_CODE (X) == REG && REG_OK_FOR_INDEX_P (X, STRICT)) \
|| (GET_CODE (X) == SUBREG \
&& TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (GET_MODE ((X))), \
GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (X)))) \
&& GET_CODE (SUBREG_REG (X)) == REG \
&& SUBREG_OK_FOR_INDEX_P (SUBREG_REG (X), SUBREG_BYTE (X))))
&& SUBREG_OK_FOR_INDEX_P (SUBREG_REG (X), SUBREG_BYTE (X), STRICT)))
/* Jump to LABEL if X is a valid address RTX. This must also take
REG_OK_STRICT into account when deciding about valid registers, but it uses
the above macros so we are in luck.
Allow REG
REG+disp
REG+r0
REG++
--REG */
/* ??? The SH2e does not have the REG+disp addressing mode when loading values
into the FRx registers. We implement this by setting the maximum offset
to zero when the value is SFmode. This also restricts loading of SFmode
values into the integer registers, but that can't be helped. */
/* The SH allows a displacement in a QI or HI amode, but only when the
other operand is R0. GCC doesn't handle this very well, so we forgo
all of that.
A legitimate index for a QI or HI is 0, SI can be any number 0..63,
DI can be any number 0..60. */
#define GO_IF_LEGITIMATE_INDEX(MODE, OP, LABEL) \
do { \
if (GET_CODE (OP) == CONST_INT) \
{ \
if (TARGET_SHMEDIA) \
{ \
int MODE_SIZE; \
/* Check if this the address of an unaligned load / store. */\
if ((MODE) == VOIDmode) \
{ \
if (CONST_OK_FOR_I06 (INTVAL (OP))) \
goto LABEL; \
break; \
} \
MODE_SIZE = GET_MODE_SIZE (MODE); \
if (! (INTVAL (OP) & (MODE_SIZE - 1)) \
&& INTVAL (OP) >= -512 * MODE_SIZE \
&& INTVAL (OP) < 512 * MODE_SIZE) \
goto LABEL; \
else \
break; \
} \
if (TARGET_SH2A) \
{ \
if (GET_MODE_SIZE (MODE) == 1 \
&& (unsigned) INTVAL (OP) < 4096) \
goto LABEL; \
} \
if (MODE_DISP_OK_4 ((OP), (MODE))) goto LABEL; \
if (MODE_DISP_OK_8 ((OP), (MODE))) goto LABEL; \
} \
} while(0)
#ifdef REG_OK_STRICT
#define BASE_REGISTER_RTX_P(X) MAYBE_BASE_REGISTER_RTX_P(X, true)
#define INDEX_REGISTER_RTX_P(X) MAYBE_INDEX_REGISTER_RTX_P(X, true)
#else
#define BASE_REGISTER_RTX_P(X) MAYBE_BASE_REGISTER_RTX_P(X, false)
#define INDEX_REGISTER_RTX_P(X) MAYBE_INDEX_REGISTER_RTX_P(X, false)
#endif
#define ALLOW_INDEXED_ADDRESS \
((!TARGET_SHMEDIA32 && !TARGET_SHCOMPACT) || TARGET_ALLOW_INDEXED_ADDRESS)
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL) \
{ \
if (BASE_REGISTER_RTX_P (X)) \
goto LABEL; \
else if ((GET_CODE (X) == POST_INC || GET_CODE (X) == PRE_DEC) \
&& ! TARGET_SHMEDIA \
&& BASE_REGISTER_RTX_P (XEXP ((X), 0))) \
goto LABEL; \
else if (GET_CODE (X) == PLUS \
&& ((MODE) != PSImode || reload_completed)) \
{ \
rtx xop0 = XEXP ((X), 0); \
rtx xop1 = XEXP ((X), 1); \
if (GET_MODE_SIZE (MODE) <= 8 && BASE_REGISTER_RTX_P (xop0)) \
GO_IF_LEGITIMATE_INDEX ((MODE), xop1, LABEL); \
if ((ALLOW_INDEXED_ADDRESS || GET_MODE (X) == DImode \
|| ((xop0 == stack_pointer_rtx \
|| xop0 == hard_frame_pointer_rtx) \
&& REG_P (xop1) && REGNO (xop1) == R0_REG) \
|| ((xop1 == stack_pointer_rtx \
|| xop1 == hard_frame_pointer_rtx) \
&& REG_P (xop0) && REGNO (xop0) == R0_REG)) \
&& ((!TARGET_SHMEDIA && GET_MODE_SIZE (MODE) <= 4) \
|| (TARGET_SHMEDIA && GET_MODE_SIZE (MODE) <= 8) \
|| ((TARGET_SH4 || TARGET_SH2A_DOUBLE) \
&& TARGET_FMOVD && MODE == DFmode))) \
{ \
if (BASE_REGISTER_RTX_P (xop1) && INDEX_REGISTER_RTX_P (xop0))\
goto LABEL; \
if (INDEX_REGISTER_RTX_P (xop1) && BASE_REGISTER_RTX_P (xop0))\
goto LABEL; \
} \
} \
}
#define GO_IF_LEGITIMATE_INDEX(MODE, OP, WIN) \
do { \
if (sh_legitimate_index_p ((MODE), (OP))) \
goto WIN; \
} while (0)
#ifdef REG_OK_STRICT
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL) \
do { \
if (sh_legitimate_address_p ((MODE), (X), true)) \
goto LABEL; \
} while (0)
#else
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL) \
do { \
if (sh_legitimate_address_p ((MODE), (X), false)) \
goto LABEL; \
} while (0)
#endif
/* A C compound statement that attempts to replace X, which is an address
that needs reloading, with a valid memory address for an operand of