https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90275
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |ebotcazou at gcc dot gnu.org, | |law at gcc dot gnu.org --- Comment #5 from Jakub Jelinek <jakub at gcc dot gnu.org> --- So, what I see that happens is that when processing that insn 97, insert_regs calls make_regs_eqv (135, 131) and as pseudo 131 is live at the end of the bb while pseudo 135 is not, 131 is selected as the canonical register for the equivalence. 5968 elt = insert (dest, sets[i].src_elt, 5969 sets[i].dest_hash, GET_MODE (dest)); afterwards stores the table entry, but under the pseudo 135, such as lookup_for_remove (reg_135, HASH (reg_135), E_VOIDmode) is non-NULL and contains in ->exp reg_135 and in ->first_same_value->exp reg_131, while lookup_for_remove (reg_131, HASH (reg_131), E_VOIDmode) is NULL. Later on we process the 131 = 135 assignment, canonicalize_insn canonicalizes that into 131 = 131 assignment (i.e. noop). Later we invalidate_reg (reg_131) as the destination, which undoes the reg equivalency, but as lookup_for_remove (reg_131, HASH (reg_131), E_VOIDmode) used to be NULL, nothing is removed from the table. And then insert_regs is called again, and ICEs, because 1128 gcc_assert (REGNO_QTY_VALID_P (c_regno)); I'd think that invalidate_reg really should remove the traces of that pseudo from the tables, wonder e.g. if the remove_pseudo_from_table call in invalidate_reg couldn't be done before delete_reg_equiv and lookup_for_remove use exp_equiv_p. It does use it already for the !REG_P case, but I believe it is never called with non-REG.