sh.md: Add new unnamed split pattern to handle movt-movt sequences.
authorOleg Endo <olegendo@gcc.gnu.org>
Fri, 2 Oct 2015 12:30:05 +0000 (12:30 +0000)
committerOleg Endo <olegendo@gcc.gnu.org>
Fri, 2 Oct 2015 12:30:05 +0000 (12:30 +0000)
gcc/
* config/sh/sh.md: Add new unnamed split pattern to handle movt-movt
sequences.

From-SVN: r228386

gcc/ChangeLog
gcc/config/sh/sh.md

index c71a020..a84b8a9 100644 (file)
@@ -1,3 +1,8 @@
+2015-10-02  Oleg Endo  <olegendo@gcc.gnu.org>
+
+       * config/sh/sh.md: Add new unnamed split pattern to handle movt-movt
+       sequences.
+
 2015-10-02  Renlin Li  <renlin.li@arm.com>
 
        PR target/66776
index d758e3b..3b56afb 100644 (file)
@@ -14860,6 +14860,46 @@ label:
                          gen_rtx_REG (SImode, (REGNO (operands[1])))));
 })
 
+;; This is not a peephole, but it's here because it's actually supposed
+;; to be one.  It tries to convert a sequence such as
+;;     movt    r2      ->      movt    r2
+;;     movt    r13             mov     r2,r13
+;; This gives the schduler a bit more freedom to hoist a following
+;; comparison insn.  Moreover, it the reg-reg mov insn is MT group which has
+;; better chances for parallel execution.
+;; We can do this with a peephole2 pattern, but then the cprop_hardreg
+;; pass will revert the change.  See also PR 64331.
+;; Thus do it manually in one of the split passes after register allocation.
+;; Sometimes the cprop_hardreg pass might also eliminate the reg-reg copy.
+(define_split
+  [(set (match_operand:SI 0 "arith_reg_dest")
+       (match_operand:SI 1 "t_reg_operand"))]
+  "TARGET_SH1 && reload_completed"
+  [(set (match_dup 0) (match_dup 1))]
+{
+  rtx t_reg = get_t_reg_rtx ();
+
+  for (rtx_insn* i = prev_nonnote_insn_bb (curr_insn); i != NULL;
+       i = prev_nonnote_insn_bb (i))
+    {
+      if (!INSN_P (i) || DEBUG_INSN_P (i))
+       continue;
+
+      if (modified_in_p (t_reg, i) || BARRIER_P (i))
+       FAIL;
+
+      if (sh_is_movt_insn (i))
+       {
+         rtx r = sh_movt_set_dest (i);
+         if (!modified_between_p (r, i, curr_insn))
+           {
+             operands[1] = r;
+             break;
+          }
+       }
+    }
+})
+
 (define_peephole
   [(set (match_operand:SI 0 "register_operand" "=r")
        (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))