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