re PR target/37633 (wrong register use on sh64)

PR target/37633
	* config/sh/sh.c (sh_hard_regno_mode_ok): New function.
	* config/sh/sh.h (HARD_REGNO_MODE_OK): Use it.
	* config/sh/sh-protos.h (sh_hard_regno_mode_ok): Declare.

From-SVN: r141282
This commit is contained in:
Kaz Kojima 2008-10-21 23:40:41 +00:00
parent e58d5f65d7
commit 347146a487
4 changed files with 113 additions and 46 deletions

View File

@ -1,3 +1,10 @@
2008-10-22 Kaz Kojima <kkojima@gcc.gnu.org>
PR target/37633
* config/sh/sh.c (sh_hard_regno_mode_ok): New function.
* config/sh/sh.h (HARD_REGNO_MODE_OK): Use it.
* config/sh/sh-protos.h (sh_hard_regno_mode_ok): Declare.
2008-10-22 Jakub Jelinek <jakub@redhat.com>
PR target/37880

View File

@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler for Renesas / SuperH SH.
Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2003,
2004, 2005, 2006, 2007
2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
Contributed by Steve Chamberlain (sac@cygnus.com).
Improved by Jim Wilson (wilson@cygnus.com).
@ -174,7 +174,7 @@ extern enum reg_class sh_secondary_reload (bool, rtx, enum reg_class,
extern int sh2a_get_function_vector_number (rtx);
extern int sh2a_is_function_vector_call (rtx);
extern void sh_fix_range (const char *);
extern bool sh_hard_regno_mode_ok (unsigned int, enum machine_mode);
#endif /* ! GCC_SH_PROTOS_H */
#ifdef SYMBIAN

View File

@ -10193,6 +10193,108 @@ sh_expand_binop_v2sf (enum rtx_code code, rtx op0, rtx op1, rtx op2)
emit_insn (gen_binary_sf_op1 (op0, op1, op2, op));
}
/* Return true if hard register REGNO can hold a value of machine-mode MODE.
We can allow any mode in any general register. The special registers
only allow SImode. Don't allow any mode in the PR.
We cannot hold DCmode values in the XD registers because alter_reg
handles subregs of them incorrectly. We could work around this by
spacing the XD registers like the DR registers, but this would require
additional memory in every compilation to hold larger register vectors.
We could hold SFmode / SCmode values in XD registers, but that
would require a tertiary reload when reloading from / to memory,
and a secondary reload to reload from / to general regs; that
seems to be a loosing proposition.
We want to allow TImode FP regs so that when V4SFmode is loaded as TImode,
it won't be ferried through GP registers first. */
bool
sh_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode)
{
if (SPECIAL_REGISTER_P (regno))
return mode == SImode;
if (regno == FPUL_REG)
return (mode == SImode || mode == SFmode);
if (FP_REGISTER_P (regno) && mode == SFmode)
return true;
if (mode == V2SFmode)
{
if (((FP_REGISTER_P (regno) && (regno - FIRST_FP_REG) % 2 == 0)
|| GENERAL_REGISTER_P (regno)))
return true;
else
return false;
}
if (mode == V4SFmode)
{
if ((FP_REGISTER_P (regno) && (regno - FIRST_FP_REG) % 4 == 0)
|| GENERAL_REGISTER_P (regno))
return true;
else
return false;
}
if (mode == V16SFmode)
{
if (TARGET_SHMEDIA)
{
if (FP_REGISTER_P (regno) && (regno - FIRST_FP_REG) % 16 == 0)
return true;
else
return false;
}
else
return regno == FIRST_XD_REG;
}
if (FP_REGISTER_P (regno))
{
if (mode == SFmode
|| mode == SImode
|| ((TARGET_SH2E || TARGET_SHMEDIA) && mode == SCmode)
|| ((((TARGET_SH4 || TARGET_SH2A_DOUBLE) && mode == DFmode)
|| mode == DCmode
|| (TARGET_SHMEDIA
&& (mode == DFmode || mode == DImode
|| mode == V2SFmode || mode == TImode)))
&& ((regno - FIRST_FP_REG) & 1) == 0)
|| ((TARGET_SH4 || TARGET_SHMEDIA) && mode == TImode
&& ((regno - FIRST_FP_REG) & 3) == 0))
return true;
else
return false;
}
if (XD_REGISTER_P (regno))
return mode == DFmode;
if (TARGET_REGISTER_P (regno))
return (mode == DImode || mode == SImode || mode == PDImode);
if (regno == PR_REG)
return mode == SImode;
if (regno == FPSCR_REG)
return mode == PSImode;
/* FIXME. This works around PR target/37633 for -O0. */
if (!optimize && TARGET_SHMEDIA32 && GET_MODE_SIZE (mode) > 4)
{
unsigned int n = GET_MODE_SIZE (mode) / 8;
if (regno >= FIRST_GENERAL_REG + 10 - n + 1
&& regno <= FIRST_GENERAL_REG + 14)
return false;
}
return true;
}
/* Return the class of registers for which a mode change from FROM to TO
is invalid. */
bool

View File

@ -1208,52 +1208,10 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
? ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD/2 - 1) / (UNITS_PER_WORD/2)) \
: ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
We can allow any mode in any general register. The special registers
only allow SImode. Don't allow any mode in the PR. */
/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */
/* We cannot hold DCmode values in the XD registers because alter_reg
handles subregs of them incorrectly. We could work around this by
spacing the XD registers like the DR registers, but this would require
additional memory in every compilation to hold larger register vectors.
We could hold SFmode / SCmode values in XD registers, but that
would require a tertiary reload when reloading from / to memory,
and a secondary reload to reload from / to general regs; that
seems to be a loosing proposition. */
/* We want to allow TImode FP regs so that when V4SFmode is loaded as TImode,
it won't be ferried through GP registers first. */
#define HARD_REGNO_MODE_OK(REGNO, MODE) \
(SPECIAL_REGISTER_P (REGNO) ? (MODE) == SImode \
: (REGNO) == FPUL_REG ? (MODE) == SImode || (MODE) == SFmode \
: FP_REGISTER_P (REGNO) && (MODE) == SFmode \
? 1 \
: (MODE) == V2SFmode \
? ((FP_REGISTER_P (REGNO) && ((REGNO) - FIRST_FP_REG) % 2 == 0) \
|| GENERAL_REGISTER_P (REGNO)) \
: (MODE) == V4SFmode \
? ((FP_REGISTER_P (REGNO) && ((REGNO) - FIRST_FP_REG) % 4 == 0) \
|| GENERAL_REGISTER_P (REGNO)) \
: (MODE) == V16SFmode \
? (TARGET_SHMEDIA \
? (FP_REGISTER_P (REGNO) && ((REGNO) - FIRST_FP_REG) % 16 == 0) \
: (REGNO) == FIRST_XD_REG) \
: FP_REGISTER_P (REGNO) \
? ((MODE) == SFmode || (MODE) == SImode \
|| ((TARGET_SH2E || TARGET_SHMEDIA) && (MODE) == SCmode) \
|| ((((TARGET_SH4 || TARGET_SH2A_DOUBLE) && (MODE) == DFmode) || (MODE) == DCmode \
|| (TARGET_SHMEDIA && ((MODE) == DFmode || (MODE) == DImode \
|| (MODE) == V2SFmode || (MODE) == TImode))) \
&& (((REGNO) - FIRST_FP_REG) & 1) == 0) \
|| ((TARGET_SH4 || TARGET_SHMEDIA) \
&& (MODE) == TImode \
&& (((REGNO) - FIRST_FP_REG) & 3) == 0)) \
: XD_REGISTER_P (REGNO) \
? (MODE) == DFmode \
: TARGET_REGISTER_P (REGNO) \
? ((MODE) == DImode || (MODE) == SImode || (MODE) == PDImode) \
: (REGNO) == PR_REG ? (MODE) == SImode \
: (REGNO) == FPSCR_REG ? (MODE) == PSImode \
: 1)
sh_hard_regno_mode_ok ((REGNO), (MODE))
/* Value is 1 if it is a good idea to tie two pseudo registers
when one has mode MODE1 and one has mode MODE2.