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 ();

Reply via email to