diff options
author | Kaz Kojima <kkojima@gcc.gnu.org> | 2014-12-19 04:49:16 +0000 |
---|---|---|
committer | Kaz Kojima <kkojima@gcc.gnu.org> | 2014-12-19 04:49:16 +0000 |
commit | fc1fcfa0b666f04e7891b5665f418136f2731fad (patch) | |
tree | 770002d38ea52f933a8f6090b20a8e0ee731134f | |
parent | 106a52b7bff18807dedbfc54e48db07d375e7eac (diff) | |
download | gcc-fc1fcfa0b666f04e7891b5665f418136f2731fad.zip gcc-fc1fcfa0b666f04e7891b5665f418136f2731fad.tar.gz gcc-fc1fcfa0b666f04e7891b5665f418136f2731fad.tar.bz2 |
* [SH] Miscellaneous changes for LRA.
From-SVN: r218889
-rw-r--r-- | gcc/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/config/sh/predicates.md | 42 | ||||
-rw-r--r-- | gcc/config/sh/sh-protos.h | 2 | ||||
-rw-r--r-- | gcc/config/sh/sh.c | 22 | ||||
-rw-r--r-- | gcc/config/sh/sh.h | 4 | ||||
-rw-r--r-- | gcc/config/sh/sh.md | 12 |
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++) |