https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65249

--- Comment #19 from Kazumoto Kojima <kkojima at gcc dot gnu.org> ---
Although this is essentially a problem with the old reload, I'm testing
another adhoc patch which is hinted by an Oleg's patch for gbr addressing.
The problematic insn is (set (DImode R0) (DImode reg for <return value>))
originally.  The subreg lowering pass splits it to two SImode move's:
  (set (SImode R0) (SImode reg for the first word of <return value>))
  (set (SImode R1) (SImode reg for the second word of <return value>))
The ICE happens on the latter insn because R0 is live there and the source
is replaced by memory with index addressing afterwards.  The patch below
pre-splits the original DImode move in the reversed order when generating.
It also produces a bit better code for the test case even when -mlra
is specified.  I intentionally limit this pre-splitting with pseudo reg
sources.  If not, I've got some wired ICEs with too complex subreg rtl
in building gcc.  I think that almost use of R0 destination is the above
pseudo reg for <retval> source and limiting it to that case would be
not a problem.

        * config/sh/sh.md (movdi): Split simple reg move to two movsi
        when the destination is R0.

--- ../../ORIG/trunk/gcc/config/sh/sh.md        2015-07-08 10:04:22.000000000
+0900
+++ config/sh/sh.md     2015-07-13 11:09:43.028613182 +0900
@@ -7892,6 +7892,24 @@ label:
   ""
 {
   prepare_move_operands (operands, DImode);
+  if (TARGET_SH1)
+    {
+      /* When the dest operand is (R0, R1) register pair, split it to
+        two movsi of which dest is R1 and R0 so as to lower R0-register
+        pressure on the first movsi.  Apply only for simple source not
+        to make complex rtl here.  */
+      if (REG_P (operands[0])
+         && REGNO (operands[0]) == R0_REG
+         && REG_P (operands[1])
+         && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER)
+       {
+         emit_insn (gen_movsi (gen_rtx_REG (SImode, R1_REG),
+                               gen_rtx_SUBREG (SImode, operands[1], 4)));
+         emit_insn (gen_movsi (gen_rtx_REG (SImode, R0_REG),
+                               gen_rtx_SUBREG (SImode, operands[1], 0)));
+         DONE;
+       }
+    }
 })

 (define_insn "movdf_media"

Reply via email to