https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119594
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |law at gcc dot gnu.org, | |rsandifo at gcc dot gnu.org --- Comment #8 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Ok, delete_trivially_dead_insns doesn't (thankfully) actually use REG_DEAD/REG_UNUSED notes. But it is clearly incorrect for these cases and has been latent for decades. The problem is IMHO in the count_reg_usage design: Don't count a usage of DEST, which is the SET_DEST of a SET which contains X in its SET_SRC. This is because such a SET does not modify the liveness of DEST. DEST is set to pc_rtx for a trapping insn, or for an insn with side effects. We must then count uses of a SET_DEST regardless, because the insn can't be deleted here. In (insn 7 2 8 2 (set (reg/v:DI 101 [ g ]) (const_int -1 [0xffffffffffffffff])) "pr119594.c":8:10 95 {*movdi_internal} (nil)) ... (insn 26 24 27 7 (set (reg:DI 104 [ g ]) (zero_extend:DI (subreg:SI (reg/v:DI 101 [ g ]) 0))) "pr119594.c":11:8 175 {*zero_extendsidi2} (expr_list:REG_EQUAL (const_int 4294967295 [0xffffffff]) (expr_list:REG_DEAD (reg/v:DI 101 [ g ]) (nil)))) (insn 27 26 28 7 (set (reg/v:DI 101 [ g ]) (zero_extend:DI (subreg:SI (reg/v:DI 101 [ g ]) 0))) "pr119594.c":11:8 175 {*zero_extendsidi2} (expr_list:REG_EQUAL (const_int 4294967295 [0xffffffff]) (expr_list:REG_UNUSED (reg/v:DI 101 [ g ]) (nil)))) we first process insn 7, that just sets pseudo 101 to constant, nothing is counted. In insn 26, the use of pseudo 101 is counted (so counts[101] = 1) because it doesn't match the destination. And finally in insn 27 nothing is counted again, because the destination is pseudo 101 and it is used somewhere in the insn. So, in the end we have counts[101] 1 and counts[104] 0. Then we process insns from the end, we see insn 27, counts[101] doesn't have zero count, so it is considered live. Next we process insn 26, counts[104] is 0, trivially dead insns, we decrease related counts (so counts[101] becomes 0) and delete the insn. Later on we process insn 7, counts[101] is 0, so trivially dead insn, let's delete it. But insn 27 wasn't deleted and so now uses result of removed insn. I think this is related to PR18992 r0-70024 and PR12142 r0-53304 and primarily r0-6313. Now, counting even the uses of REG SET_DEST in the SET_SRC pattern (e.g. with exception of noop insns) would result in insns like 27 not be trivially removable even if insn 26 wasn't there. So wonder if we just shouldn't count the x == dest REG cases in another part of the counts array and if we see that other part of the array have any non-zero cases where the corresponding counts is 0 (i.e. we might have optimized away some setters but left out other setters which used the register in its pattern), redo the IL walk and just remove the affected insns. Though, wonder about insns which set more than one pseudo register in a PARALLEL, we still might not be able to remove those and so maybe we just need to arrange in that case to use dest = pc_rtx. Ditto for other cases which are never insn_live_p regardless of counts. We already handle the !insn_nothrow_p cases and side_effects_p, but not when one of the SETs is not a REG, or is a hard reg.