http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53942
--- Comment #4 from Jakub Jelinek <jakub at gcc dot gnu.org> 2012-07-16
11:54:23 UTC ---
The following patch fixes this issue during expansion, don't have time right
now to test what effects it might have on generated code though:
--- gcc/function.c.jj 2012-06-25 08:38:26.000000000 +0200
+++ gcc/function.c 2012-07-16 13:41:52.847928315 +0200
@@ -2988,11 +2988,26 @@ assign_parm_setup_reg (struct assign_par
&& 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 ();