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  <seg...@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(+)

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
-- 
1.8.3.1

Reply via email to