http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51725
--- Comment #11 from Jakub Jelinek <jakub at gcc dot gnu.org> 2012-01-03 16:24:00 UTC --- Managed to reproduce this even using x86_64-linux -> ia64-linux cross. Indeed, what happens is that when add_mem_for_addr is called, mem_elt is still its own canonical_cselib_val, the MEM is added to its locs. Later on #0 new_elt_loc_list (val=0x1f71e20, loc=0x226eea0) at ../../gcc/cselib.c:290 #1 0x00000000005ccabf in new_elt_loc_list (val=0x1f71eb0, loc=0x226ee58) at ../../gcc/cselib.c:258 #2 0x00000000005d1193 in cselib_add_permanent_equiv (elt=0x1f71e20, x=0x7fffe77dbaf8, insn=0x7fffe7217240) at ../../gcc/cselib.c:2339 is called and it moves all the locs to the new canonical cselib_val /* Bring all locs from LOC to VAL. */ and /* Chain LOC back to VAL. */ but nothing updated the first_containing_mem chain nor addr_list at this point. So, either we update those two here, or adjust cselib_invalidate_mem. I guess the easiest would be to update both spots. In the new_elt_loc_list code to move locs from a no longer canonical value to the canonical, if next_containing_mem of the no longer canonical value is non-NULL, but canonical value's next_containing_mem is NULL, add the canonical value to the first_containing_mem list (I guess unchaining of the old value would be too expensive). And in cselib_invalidate_mem ignore non-canonical values from the first_containing_mem chain (well, just unlink them; but I guess the code as is does that already) and call canonical_cselib_val in the tight loop as addr_list elements aren't necessary canonicalized.