combine: Don't set the same thing twice in one parallel
diff mbox series

Message ID 3837b7a2706c832a5f406ee2be064b6e67fcec78.1573945436.git.segher@kernel.crashing.org
State New
Headers show
Series
  • combine: Don't set the same thing twice in one parallel
Related show

Commit Message

Segher Boessenkool Nov. 16, 2019, 11:09 p.m. UTC
Instead, make the second arm copy from the dest of the first set.  Most
of the time this copy will be optimized away later.

I am still testing this across many archs; will commit later if that
works out well.


Segher


2019-11-16  Segher Boessenkool  <segher@kernel.crashing.org>

	* combine.c (try_combine): If we get a parallel setting the same value
	to two locations, only set it once and copy that.

---
 gcc/combine.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

Patch
diff mbox series

diff --git a/gcc/combine.c b/gcc/combine.c
index fdfa587..dec3c01 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -4122,6 +4122,22 @@  try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
       rtx set0 = XVECEXP (newpat, 0, 0);
       rtx set1 = XVECEXP (newpat, 0, 1);
 
+      /* If both set the same value, do it once and copy it; the copy
+	 can usually be optimised away later.  */
+      if (rtx_equal_p (SET_SRC (set0), SET_SRC (set1))
+	  && !modified_between_p (SET_SRC (set0), i2, i3)
+	  && !(REG_P (SET_DEST (set0))
+	       && find_reg_note (i2, REG_DEAD, SET_DEST (set0)))
+	  && !(GET_CODE (SET_DEST (set0)) == SUBREG
+	       && find_reg_note (i2, REG_DEAD, SUBREG_REG (SET_DEST (set0))))
+	  && !modified_between_p (SET_DEST (set0), i2, i3)
+	  && (!HAVE_cc0 || !reg_referenced_p (cc0_rtx, set1)))
+        {
+	  newi2pat = set0;
+	  newpat = set1;
+	  SUBST (SET_SRC (newpat), SET_DEST (newi2pat));
+	}
+      else
       /* Normally, it doesn't matter which of the two is done first,
 	 but the one that references cc0 can't be the second, and
 	 one which uses any regs/memory set in between i2 and i3 can't