PR rtl-optimization/87761
	* config/mips/mips-protos.h (mips_split_move): Add new argument.
	(mips_emit_move_or_split): Pass NULL for INSN into mips_split_move.
	(mips_split_move): Accept new INSN argument.  Try to forward SRC
	into the next instruction.
	(mips_split_move_insn): Pass INSN through to mips_split_move.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@269880 138bc75d-0d04-0410-961f-82ee72b054a4
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c10c4c7..7e31779 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2019-02-26  Jeff Law  <law@redhat.com>
+
+	PR rtl-optimization/87761
+	* config/mips/mips-protos.h (mips_split_move): Add new argument.
+	(mips_emit_move_or_split): Pass NULL for INSN into mips_split_move.
+	(mips_split_move): Accept new INSN argument.  Try to forward SRC
+	into the next instruction.
+	(mips_split_move_insn): Pass INSN through to mips_split_move.
+
 2019-03-22  Vladimir Makarov  <vmakarov@redhat.com>
 
 	PR rtl-optimization/89676
diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h
index 64afb35..32070fd 100644
--- a/gcc/config/mips/mips-protos.h
+++ b/gcc/config/mips/mips-protos.h
@@ -214,7 +214,7 @@
 
 extern rtx mips_subword (rtx, bool);
 extern bool mips_split_move_p (rtx, rtx, enum mips_split_type);
-extern void mips_split_move (rtx, rtx, enum mips_split_type);
+extern void mips_split_move (rtx, rtx, enum mips_split_type, rtx);
 extern bool mips_split_move_insn_p (rtx, rtx, rtx);
 extern void mips_split_move_insn (rtx, rtx, rtx);
 extern void mips_split_128bit_move (rtx, rtx);
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 48f3244..1de33b2 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -3031,7 +3031,7 @@
 mips_emit_move_or_split (rtx dest, rtx src, enum mips_split_type split_type)
 {
   if (mips_split_move_p (dest, src, split_type))
-    mips_split_move (dest, src, split_type);
+    mips_split_move (dest, src, split_type, NULL);
   else
     mips_emit_move (dest, src);
 }
@@ -4780,10 +4780,11 @@
 }
 
 /* Split a move from SRC to DEST, given that mips_split_move_p holds.
-   SPLIT_TYPE describes the split condition.  */
+   SPLIT_TYPE describes the split condition.  INSN is the insn being
+   split, if we know it, NULL otherwise.  */
 
 void
-mips_split_move (rtx dest, rtx src, enum mips_split_type split_type)
+mips_split_move (rtx dest, rtx src, enum mips_split_type split_type, rtx insn_)
 {
   rtx low_dest;
 
@@ -4843,6 +4844,21 @@
 	  mips_emit_move (mips_subword (dest, true), mips_subword (src, true));
 	}
     }
+
+  /* This is a hack.  See if the next insn uses DEST and if so, see if we
+     can forward SRC for DEST.  This is most useful if the next insn is a
+     simple store.   */
+  rtx_insn *insn = (rtx_insn *)insn_;
+  if (insn)
+    {
+      rtx_insn *next = next_nonnote_nondebug_insn_bb (insn);
+      if (next)
+	{
+	  rtx set = single_set (next);
+	  if (set && SET_SRC (set) == dest)
+	    validate_change (next, &SET_SRC (set), src, false);
+	}
+    }
 }
 
 /* Return the split type for instruction INSN.  */
@@ -5070,7 +5086,7 @@
 void
 mips_split_move_insn (rtx dest, rtx src, rtx insn)
 {
-  mips_split_move (dest, src, mips_insn_split_type (insn));
+  mips_split_move (dest, src, mips_insn_split_type (insn), insn);
 }
 
 /* Return the appropriate instructions to move SRC into DEST.  Assume