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.

Reply via email to