diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/combine.c | 19 |
2 files changed, 21 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4cc3ac6..3f632ca 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2017-09-01 Segher Boessenkool <segher@kernel.crashing.org> + + PR rtl-optimization/82024 + * combine.c (try_combine): If the combination result is a PARALLEL, + and we only need to retain the SET in there that would be placed + at I2, check that we can place that at I3 instead, before doing so. + 2017-09-01 Jakub Jelinek <jakub@redhat.com> PR target/81766 diff --git a/gcc/combine.c b/gcc/combine.c index 8605538..c748c92 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -3488,7 +3488,10 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, i3, and one from i2. Combining then splitting the parallel results in the original i2 again plus an invalid insn (which we delete). The net effect is only to move instructions around, which makes - debug info less accurate. */ + debug info less accurate. + + If the remaining SET came from I2 its destination should not be used + between I2 and I3. See PR82024. */ if (!(added_sets_2 && i1 == 0) && is_parallel_of_n_reg_sets (newpat, 2) @@ -3517,11 +3520,17 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, && insn_nothrow_p (i3) && !side_effects_p (SET_SRC (set0))) { - newpat = set1; - insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes); + rtx dest = SET_DEST (set1); + if (GET_CODE (dest) == SUBREG) + dest = SUBREG_REG (dest); + if (!reg_used_between_p (dest, i2, i3)) + { + newpat = set1; + insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes); - if (insn_code_number >= 0) - changed_i3_dest = 1; + if (insn_code_number >= 0) + changed_i3_dest = 1; + } } if (insn_code_number < 0) |