https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88714
--- Comment #18 from Jakub Jelinek <jakub at gcc dot gnu.org> --- So, I've hacked up assembly version which contained 2 versions of this function (good and bad) plus a wrapper function: void * vn_reference_lookup_2b (ao_ref *op, tree vuse, unsigned int cnt, void *vr_); void * vn_reference_lookup_2c (ao_ref *op, tree vuse, unsigned int cnt, void *vr_); void * vn_reference_lookup_2a (ao_ref *op, tree vuse, unsigned int cnt, void *vr_) { vn_reference_t vr = (vn_reference_t)vr_; vn_reference_s a = *vr; void *r1 = vn_reference_lookup_2a (op, vuse, cnt, vr_); vn_reference_s b = *vr; *vr = a; void *r2 = vn_reference_lookup_2b (op, vuse, cnt, vr_); if (r1 != r2 || __builtin_memcmp (vr, &b, sizeof (b))) fancy_abort (__FILE__, __LINE__, __FUNCTION__); return r1; } adjusted in the assembly, so that it is actually that vn_reference_lookup_2 that calls the good and bad versions. This ICEs on the second call to vn_reference_lookup_2. vuse is .MEM_59, so is vr->vuse on entry and vr->hashcode is 0xd16d45ea. The if (vr->vuse) vr->hashcode = vr->hashcode - (vr->vuse)->base.u.version; is performed correctly in both, changing vr->hashcode to 0xd16d45af (i.e. subtracting 59), next vr->vuse is updated to .MEM_48. The problem is with the if (vr->vuse) vr->hashcode = vr->hashcode + (vr->vuse)->base.u.version; in the good version it does what the source tells it to do, adds 48, making vr->hashcode 0xd16d45df and calling find_slot_with_hash with that value. But in the bad version, we actually store 0xd16d45ea again.