* [SH] Split QI/HImode load/store via r0 when LRA is enabled.
authorKaz Kojima <kkojima@gcc.gnu.org>
Fri, 19 Dec 2014 04:56:26 +0000 (04:56 +0000)
committerKaz Kojima <kkojima@gcc.gnu.org>
Fri, 19 Dec 2014 04:56:26 +0000 (04:56 +0000)
From-SVN: r218892

gcc/ChangeLog
gcc/config/sh/sh.c

index a9741366392184a677327010dd5e507380c361be..e67e97c9d24d8b369483c8b4ac1f7ce2f4fe5084 100644 (file)
@@ -1,3 +1,8 @@
+2014-12-19  Kaz Kojima  <kkojima@gcc.gnu.org>
+
+       * config/sh/sh.c (prepare_move_operands): Split HI/QImode load/store
+       to two move insns via r0.
+
 2014-12-19  Kaz Kojima  <kkojima@gcc.gnu.org>
 
        * config/sh/predicates.md (arith_or_int_operand): New predicate.
index 7851fe86863e7be0b05d97d5f06094a32c4d8755..8ad8afa5ac6ee671a03ffd54bda625e1ff496c36 100644 (file)
@@ -1778,6 +1778,38 @@ prepare_move_operands (rtx operands[], machine_mode mode)
               && GET_CODE (XEXP (operands[0], 0)) == PLUS
               && REG_P (XEXP (XEXP (operands[0], 0), 1)))
        operands[1] = copy_to_mode_reg (mode, operands[1]);
+
+      /* When the displacement addressing is used, RA will assign r0 to
+        the pseudo register operand for the QI/HImode load/store.
+        This tends to make a long live range for R0 and might cause
+        anomalous register spills in some case with LRA.  See PR
+        target/55212.
+        We split possible load/store to two move insns via r0 so as to
+        shorten R0 live range.  It will make some codes worse but will
+        win on avarage for LRA.  */
+      else if (sh_lra_p ()
+              && TARGET_SH1 && ! TARGET_SH2A
+              && (mode == QImode || mode == HImode)
+              && ((REG_P (operands[0]) && MEM_P (operands[1]))
+                  || (REG_P (operands[1]) && MEM_P (operands[0]))))
+       {
+         bool load_p = REG_P (operands[0]);
+         rtx reg = operands[load_p ? 0 : 1];
+         rtx adr = XEXP (operands[load_p ? 1 : 0], 0);
+
+         if (REGNO (reg) >= FIRST_PSEUDO_REGISTER
+             && GET_CODE (adr) == PLUS
+             && REG_P (XEXP (adr, 0))
+             && (REGNO (XEXP (adr, 0)) >= FIRST_PSEUDO_REGISTER)
+             && CONST_INT_P (XEXP (adr, 1))
+             && INTVAL (XEXP (adr, 1)) != 0
+             && sh_legitimate_index_p (mode, XEXP (adr, 1), false, true))
+           {
+             rtx r0_rtx = gen_rtx_REG (mode, R0_REG);
+             emit_move_insn (r0_rtx, operands[1]);
+             operands[1] = r0_rtx;
+           }
+       }
     }
 
   if (mode == Pmode || mode == ptr_mode)