https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109491
--- Comment #8 from Richard Biener <rguenth at gcc dot gnu.org> --- So we have a NULL op, in this case (gdb) p *vro1 $4 = {opcode = TARGET_MEM_REF, clique = 0, base = 0, reverse = 0, align = 0, off = {coeffs = {-1}}, type = <real_type 0x7ffff7309930 float>, op0 = <tree 0x0>, op1 = <tree 0x0>, op2 = <integer_cst 0x7ffff12cd138>} (gdb) p *vro2 $5 = {opcode = TARGET_MEM_REF, clique = 0, base = 0, reverse = 0, align = 0, off = {coeffs = {-1}}, type = <real_type 0x7ffff7309930 float>, op0 = <ssa_name 0x7ffff656f120 8261>, op1 = <tree 0x0>, op2 = <integer_cst 0x7ffff6119528>} I think we're lucky to not hit this more often (good hash!) and unlucky here (bad hash!). We used to have /* If only one of them is null, they cannot be equal. */ if (!e1 || !e2) return false; but r11-4982-g4d6b8d4213376e removed that. r11-5047-gaaccdb9cec423e fixed one case where that was previously needed. Now, for TARGET_MEM_REF a NULL operand is different from an operand with no effect (a zero) since the addressing mode is different. So canonicalization in copy_reference_ops_from_ref is unwanted (we'd use that representation for PRE insertion for example). The safest option is to restore the above check.