aboutsummaryrefslogtreecommitdiff
path: root/gcc/function.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2012-07-19 20:48:25 +0000
committerJakub Jelinek <jakub@redhat.com>2012-07-19 20:48:25 +0000
commit430d754dd6b14a4baa640c80acb402916ea79c27 (patch)
tree0b64e6d9e88dfbc57439877cbb5bccdfdbdd43ed /gcc/function.c
parentca8834825c05076b509b649a3ad0f066bc0e739b (diff)
PR rtl-optimization/53942
* function.c (assign_parm_setup_reg): Avoid zero/sign extension directly from likely spilled non-fixed hard registers, move them to pseudo first. * gcc.dg/pr53942.c: New test. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@189681 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/function.c')
-rw-r--r--gcc/function.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/gcc/function.c b/gcc/function.c
index c56758870bc..f1e0b2d3eba 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -2987,11 +2987,26 @@ assign_parm_setup_reg (struct assign_parm_data_all *all, tree parm,
&& insn_operand_matches (icode, 1, op1))
{
enum rtx_code code = unsignedp ? ZERO_EXTEND : SIGN_EXTEND;
- rtx insn, insns;
+ rtx insn, insns, t = op1;
HARD_REG_SET hardregs;
start_sequence ();
- insn = gen_extend_insn (op0, op1, promoted_nominal_mode,
+ /* If op1 is a hard register that is likely spilled, first
+ force it into a pseudo, otherwise combiner might extend
+ its lifetime too much. */
+ if (GET_CODE (t) == SUBREG)
+ t = SUBREG_REG (t);
+ if (REG_P (t)
+ && HARD_REGISTER_P (t)
+ && ! TEST_HARD_REG_BIT (fixed_reg_set, REGNO (t))
+ && targetm.class_likely_spilled_p (REGNO_REG_CLASS (REGNO (t))))
+ {
+ t = gen_reg_rtx (GET_MODE (op1));
+ emit_move_insn (t, op1);
+ }
+ else
+ t = op1;
+ insn = gen_extend_insn (op0, t, promoted_nominal_mode,
data->passed_mode, unsignedp);
emit_insn (insn);
insns = get_insns ();