aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaz Kojima <kkojima@gcc.gnu.org>2008-10-21 23:40:41 +0000
committerKaz Kojima <kkojima@gcc.gnu.org>2008-10-21 23:40:41 +0000
commitf79c15785b57d8fbdb8b65ce4371addebab2d8ad (patch)
tree8a734a168b86d6a35016d05123952c28510d6d50
parent7ca1bb15b4646f05ba79a54243c5dbd6d790d56f (diff)
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. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@141282 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/config/sh/sh-protos.h4
-rw-r--r--gcc/config/sh/sh.c102
-rw-r--r--gcc/config/sh/sh.h48
4 files changed, 114 insertions, 47 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 08743f849bd..f95f4e4afc9 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h
index a03c624d660..5b971960f2d 100644
--- a/gcc/config/sh/sh-protos.h
+++ b/gcc/config/sh/sh-protos.h
@@ -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
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index 7c0bdd4a72f..14892ce310a 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -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
diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h
index 8b9ec86ceef..6a4ccb0f0e6 100644
--- a/gcc/config/sh/sh.h
+++ b/gcc/config/sh/sh.h
@@ -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. */
-
-/* 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. */
+/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */
+
#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.