aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaz Kojima <kkojima@gcc.gnu.org>2014-12-19 04:49:16 +0000
committerKaz Kojima <kkojima@gcc.gnu.org>2014-12-19 04:49:16 +0000
commitfc1fcfa0b666f04e7891b5665f418136f2731fad (patch)
tree770002d38ea52f933a8f6090b20a8e0ee731134f
parent106a52b7bff18807dedbfc54e48db07d375e7eac (diff)
downloadgcc-fc1fcfa0b666f04e7891b5665f418136f2731fad.zip
gcc-fc1fcfa0b666f04e7891b5665f418136f2731fad.tar.gz
gcc-fc1fcfa0b666f04e7891b5665f418136f2731fad.tar.bz2
* [SH] Miscellaneous changes for LRA.
From-SVN: r218889
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/config/sh/predicates.md42
-rw-r--r--gcc/config/sh/sh-protos.h2
-rw-r--r--gcc/config/sh/sh.c22
-rw-r--r--gcc/config/sh/sh.h4
-rw-r--r--gcc/config/sh/sh.md12
6 files changed, 93 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index fd92d52..2753fae 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,19 @@
2014-12-19 Kaz Kojima <kkojima@gcc.gnu.org>
+ * config/sh/predicates.md (general_movsrc_operand): Allow only
+ valid plus address expressions.
+ (general_movdst_operand): Likewise.
+ (t_reg_operand): Allow (zero_extend (reg t)).
+ * config/sh/sh-protos.h (sh_hard_regno_caller_save_mode): Declare.
+ * config/sh/sh.c (sh_hard_regno_caller_save_mode): New function.
+ (sh_secondary_reload): Return NO_REGS instead of FPUL_REGS in one
+ case.
+ * config/sh/sh.h (HARD_REGNO_CALLER_SAVE_MODE): Define.
+ * config/sh/sh.md (untyped_call): Clobber function value
+ registers before call.
+
+2014-12-19 Kaz Kojima <kkojima@gcc.gnu.org>
+
* config/sh/sh.c (sh_lra_p): New function.
(TARGET_LRA_P): Define.
(sh_legitimize_reload_address): Return false if sh_lra_p is true.
diff --git a/gcc/config/sh/predicates.md b/gcc/config/sh/predicates.md
index 52267f7..152056a 100644
--- a/gcc/config/sh/predicates.md
+++ b/gcc/config/sh/predicates.md
@@ -510,7 +510,25 @@
&& GET_CODE (x) == PLUS && REG_P (XEXP (x, 0)) && REG_P (XEXP (x, 1)))
return false;
- if ((mode == QImode || mode == HImode)
+ if (GET_CODE (x) == PLUS)
+ {
+ rtx y = XEXP (x, 0);
+
+ if (! REG_P (y)
+ && ! (GET_CODE (y) == SUBREG && REG_P (SUBREG_REG (y))))
+ return false;
+ y = XEXP (x, 1);
+ if (! REG_P (y)
+ && ! (GET_CODE (y) == SUBREG && REG_P (SUBREG_REG (y)))
+ && ! CONST_INT_P (y))
+ return false;
+ }
+
+ /* LRA will try to satisfy the constraints for the memory displacements
+ and thus we must not reject invalid displacements in the predicate,
+ or else LRA will bail out.
+ FIXME: maybe remove this check completely? */
+ if (!lra_in_progress && (mode == QImode || mode == HImode)
&& GET_CODE (x) == PLUS
&& REG_P (XEXP (x, 0))
&& CONST_INT_P (XEXP (x, 1)))
@@ -595,7 +613,25 @@
&& GET_CODE (x) == PLUS && REG_P (XEXP (x, 0)) && REG_P (XEXP (x, 1)))
return false;
- if ((mode == QImode || mode == HImode)
+ if (GET_CODE (x) == PLUS)
+ {
+ rtx y = XEXP (x, 0);
+
+ if (! REG_P (y)
+ && ! (GET_CODE (y) == SUBREG && REG_P (SUBREG_REG (y))))
+ return false;
+ y = XEXP (x, 1);
+ if (! REG_P (y)
+ && ! (GET_CODE (y) == SUBREG && REG_P (SUBREG_REG (y)))
+ && ! CONST_INT_P (y))
+ return false;
+ }
+
+ /* LRA will try to satisfy the constraints for the memory displacements
+ and thus we must not reject invalid displacements in the predicate,
+ or else LRA will bail out.
+ FIXME: maybe remove this check completely? */
+ if (!lra_in_progress && (mode == QImode || mode == HImode)
&& GET_CODE (x) == PLUS
&& REG_P (XEXP (x, 0))
&& CONST_INT_P (XEXP (x, 1)))
@@ -1117,6 +1153,8 @@
case ZERO_EXTEND:
case SIGN_EXTEND:
+ if (REG_P (XEXP (op, 0)) && REGNO (XEXP (op, 0)) == T_REG)
+ return true;
return GET_CODE (XEXP (op, 0)) == SUBREG
&& REG_P (SUBREG_REG (XEXP (op, 0)))
&& REGNO (SUBREG_REG (XEXP (op, 0))) == T_REG;
diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h
index 262c4fb..7697c4c 100644
--- a/gcc/config/sh/sh-protos.h
+++ b/gcc/config/sh/sh-protos.h
@@ -262,5 +262,7 @@ extern int sh2a_get_function_vector_number (rtx);
extern bool sh2a_is_function_vector_call (rtx);
extern void sh_fix_range (const char *);
extern bool sh_hard_regno_mode_ok (unsigned int, machine_mode);
+extern machine_mode sh_hard_regno_caller_save_mode (unsigned int, unsigned int,
+ machine_mode);
extern bool sh_can_use_simple_return_p (void);
#endif /* ! GCC_SH_PROTOS_H */
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index e586f48..b01efb0 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -12186,6 +12186,26 @@ sh_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
return true;
}
+/* Specify the modes required to caller save a given hard regno.
+ choose_hard_reg_mode chooses mode based on HARD_REGNO_MODE_OK
+ and returns ?Imode for float regs when sh_hard_regno_mode_ok
+ permits integer modes on them. That makes LRA's split process
+ unhappy. See PR55212.
+ */
+machine_mode
+sh_hard_regno_caller_save_mode (unsigned int regno, unsigned int nregs,
+ machine_mode mode)
+{
+ if (FP_REGISTER_P (regno)
+ && (mode == SFmode
+ || mode == SCmode
+ || ((mode == DFmode || mode == DCmode)
+ && ((regno - FIRST_FP_REG) & 1) == 0)))
+ return mode;
+
+ return choose_hard_reg_mode (regno, nregs, false);
+}
+
/* Return the class of registers for which a mode change from FROM to TO
is invalid. */
bool
@@ -13183,7 +13203,7 @@ sh_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
{
if (rclass == FPUL_REGS)
return GENERAL_REGS;
- return FPUL_REGS;
+ return NO_REGS; // LRA wants NO_REGS here, it used to be FPUL_REGS;
}
if ((rclass == TARGET_REGS
|| (TARGET_SHMEDIA && rclass == SIBCALL_REGS))
diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h
index 92835d7..ae1e39b 100644
--- a/gcc/config/sh/sh.h
+++ b/gcc/config/sh/sh.h
@@ -905,6 +905,10 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
&& (GET_MODE_SIZE (MODE2) <= 4)) \
: ((MODE1) != SFmode && (MODE2) != SFmode))))
+/* Specify the modes required to caller save a given hard regno. */
+#define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE) \
+ sh_hard_regno_caller_save_mode ((REGNO), (NREGS), (MODE))
+
/* A C expression that is nonzero if hard register NEW_REG can be
considered for use as a rename register for OLD_REG register */
#define HARD_REGNO_RENAME_OK(OLD_REG, NEW_REG) \
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index 5aa50a25..536a498 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -10055,6 +10055,18 @@ label:
(match_operand 2 "" "")])]
"(TARGET_SH2E || TARGET_SH2A) || TARGET_SHMEDIA"
{
+ if (! TARGET_SHMEDIA)
+ {
+ /* RA does not know that the call sets the function value registers.
+ We avoid problems by claiming that those registers are clobbered
+ at this point. */
+ for (int i = 0; i < XVECLEN (operands[2], 0); i++)
+ {
+ rtx set = XVECEXP (operands[2], 0, i);
+ emit_clobber (SET_SRC (set));
+ }
+ }
+
emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
for (int i = 0; i < XVECLEN (operands[2], 0); i++)