https://gcc.gnu.org/bugzilla/show_bug.cgi?id=62151
--- Comment #15 from bin.cheng <amker.cheng at gmail dot com> --- Hmm, words on tem_insn issue at the end of comment #12 isn't mature. It's more complicated than that. Turns out live range of register which is noted as DEAD in i1/i2 can be extended because we propagate its use into i3, like below example: ix: rx <- frags:CCZ!=0 i1: r1 <- r0 & 0xfffe REG_DEAD (r0) i2: r2 <- r1 | rx REG_DEAD (r1) REG_DEAD (rx) i3: r3 <- r2 & 0xfffd REG_DEAD (r2) Which can be combined into: ix: rx <- frags:CCZ!=0 i1: INSN_DELETED i2: r2 <- r0 & 0xfffc REG_DEAD (r0) i3: r3 <- r2 | rx REG_DEAD (rx) Apparently, live ranges of both r0 and rx are extended. The REG_DEAD(r0) in new i2 and REG_DEAD(rx) in new i3 are distributed from the original i1 and i2. In this case, if we set tem_insn to from_insn, gcc will delete the previous definition of r0/rx, resulting in wrong code. I think the case I given in #12 may still hold. Interesting thing is, the comment in distribute_notes is describing that case, rather than what it handles as in this comment: Quoted from source code: /* ... If the register is not used as an input in either I3 or I2 and it is not one of the registers we were supposed to eliminate, there are two possibilities. We might have a non-adjacent I2 or we might have somehow eliminated an additional register from a computation. For example, we might have had A & B where we discover that B will always be zero. In this case we will eliminate the reference to A. In both cases, we must search to see if we can find a previous use of A and put the death note there. */ I will rephrase the comments along with code changes.