From: Kaz Kojima Date: Fri, 19 Dec 2014 04:49:16 +0000 (+0000) Subject: * [SH] Miscellaneous changes for LRA. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=fc1fcfa0b666f04e7891b5665f418136f2731fad;p=gcc.git * [SH] Miscellaneous changes for LRA. From-SVN: r218889 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fd92d522057..2753fae33b2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2014-12-19 Kaz Kojima + + * 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 * config/sh/sh.c (sh_lra_p): New function. diff --git a/gcc/config/sh/predicates.md b/gcc/config/sh/predicates.md index 52267f71d23..152056ae360 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 262c4fb556a..7697c4cbe0b 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 e586f48c5ea..b01efb09d3f 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 92835d7d8e0..ae1e39b5135 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 5aa50a25af9..536a4989665 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++)