From: Segher Boessenkool Date: Fri, 8 Dec 2017 11:26:35 +0000 (+0100) Subject: combine: Fix PR83304 X-Git-Tag: upstream/12.2.0~34976 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b1cf82933e894cbdb21d63653c20258dc8c87997;p=platform%2Fupstream%2Fgcc.git combine: Fix PR83304 In PR83304 two insns are combined, where the I2 uses a register that has a REG_DEAD note on an insn after I2 but before I3. In such a case move_deaths should move that death note. But move_deaths only looks at the reg_stat[regno].last_death insn, and that field can be zeroed out (previously, use_crosses_set_p would prevent the combination in this case). If the last_death field is zero it means "unknown", not "no death", so we have to find if there is a REG_DEAD note. PR rtl-optimization/83304 * combine.c (move_deaths): If we do not know where a register died, search for it. From-SVN: r255506 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e8aa3a1..dcd1fb6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2017-12-08 Segher Boessenkool + + PR rtl-optimization/83304 + * combine.c (move_deaths): If we do not know where a register died, + search for it. + 2017-12-08 Richard Biener * gimple-loop-interchange.cc (tree_loop_interchange::interchange): diff --git a/gcc/combine.c b/gcc/combine.c index 34c89a1..786a840 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -13876,6 +13876,26 @@ move_deaths (rtx x, rtx maybe_kill_insn, int from_luid, rtx_insn *to_insn, unsigned int regno = REGNO (x); rtx_insn *where_dead = reg_stat[regno].last_death; + /* If we do not know where the register died, it may still die between + FROM_LUID and TO_INSN. If so, find it. This is PR83304. */ + if (!where_dead) + { + rtx_insn *insn = prev_real_insn (to_insn); + while (insn + && BLOCK_FOR_INSN (insn) == BLOCK_FOR_INSN (to_insn) + && DF_INSN_LUID (insn) >= from_luid) + { + if (dead_or_set_regno_p (insn, regno)) + { + if (find_regno_note (insn, REG_DEAD, regno)) + where_dead = insn; + break; + } + + insn = prev_real_insn (insn); + } + } + /* Don't move the register if it gets killed in between from and to. */ if (maybe_kill_insn && reg_set_p (x, maybe_kill_insn) && ! reg_referenced_p (x, maybe_kill_insn))