diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 18376aeeec13..6a3a05b8ac03 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2018-07-30 Segher Boessenkool + + PR rtl-optimization/85160 + * combine.c (is_just_move): New function. + (try_combine): Allow combining two instructions into two if neither of + the original instructions was a move. + 2018-07-30 Alexander Monakov PR target/86673 diff --git a/gcc/combine.c b/gcc/combine.c index 8f6db4ff95be..3a5883a4c756 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -2604,6 +2604,17 @@ can_split_parallel_of_n_reg_sets (rtx_insn *insn, int n) return true; } +/* Return whether X is just a single set, with the source + a general_operand. */ +static bool +is_just_move (rtx x) +{ + if (INSN_P (x)) + x = PATTERN (x); + + return (GET_CODE (x) == SET && general_operand (SET_SRC (x), VOIDmode)); +} + /* Try to combine the insns I0, I1 and I2 into I3. Here I0, I1 and I2 appear earlier than I3. I0 and I1 can be zero; then we combine just I2 into I3, or I1 and I2 into @@ -2668,6 +2679,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, int swap_i2i3 = 0; int split_i2i3 = 0; int changed_i3_dest = 0; + bool i2_was_move = false, i3_was_move = false; int maxreg; rtx_insn *temp_insn; @@ -3059,6 +3071,10 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, return 0; } + /* Record whether i2 and i3 are trivial moves. */ + i2_was_move = is_just_move (i2); + i3_was_move = is_just_move (i3); + /* Record whether I2DEST is used in I2SRC and similarly for the other cases. Knowing this will help in register status updating below. */ i2dest_in_i2src = reg_overlap_mentioned_p (i2dest, i2src); @@ -4014,8 +4030,10 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, && XVECLEN (newpat, 0) == 2 && GET_CODE (XVECEXP (newpat, 0, 0)) == SET && GET_CODE (XVECEXP (newpat, 0, 1)) == SET - && (i1 || set_noop_p (XVECEXP (newpat, 0, 0)) - || set_noop_p (XVECEXP (newpat, 0, 1))) + && (i1 + || set_noop_p (XVECEXP (newpat, 0, 0)) + || set_noop_p (XVECEXP (newpat, 0, 1)) + || (!i2_was_move && !i3_was_move)) && GET_CODE (SET_DEST (XVECEXP (newpat, 0, 0))) != ZERO_EXTRACT && GET_CODE (SET_DEST (XVECEXP (newpat, 0, 0))) != STRICT_LOW_PART && GET_CODE (SET_DEST (XVECEXP (newpat, 0, 1))) != ZERO_EXTRACT