Looks good.
On Wed, Sep 21, 2016 at 4:37 AM, Richard Biener <richard.guent...@gmail.com> wrote: > On Wed, Aug 26, 2015 at 1:34 PM, Richard Biener <rguent...@suse.de> wrote: >> >> The following fixes a GC issue I run into when doing >> prune_unused_types_prune early. The issue is that the DIE struct >> has a chain_circular marked field (die_sib) which cannot tolerate >> spurious extra entries from old removed entries into the circular >> chain. Otherwise we fail to properly mark parts of the chain. >> Those stray entries are kept live referenced from TYPE_SYMTAB_DIE. >> >> So the following patch that makes sure to clear ->die_sib for >> nodes we remove. (these DIEs remaining in TYPE_SYMTAB_DIE also >> means we may end up re-using them which is probably not what we >> want ... in the original LTO experiment I had a ->removed flag >> in the DIE struct and removed DIEs from the cache at cache lookup >> time if I hit a removed DIE) >> >> Bootstrapped and tested on x86_64-unknown-linux-gnu, gdb tested there >> as well. >> >> Ok for trunk? > > I am re-testing this now and will commit it as part of the piecewise early LTO > merge. > > Richard. > >> Thanks, >> Richard. >> >> 2015-08-26 Richard Biener <rguent...@suse.de> >> >> * dwarf2out.c (remove_child_with_prev): Clear child->die_sib. >> (replace_child): Likewise. >> (remove_child_TAG): Adjust. >> (move_marked_base_types): Likewise. >> (prune_unused_types_prune): Clear die_sib of removed children. >> >> Index: trunk/gcc/dwarf2out.c >> =================================================================== >> --- trunk.orig/gcc/dwarf2out.c 2015-08-26 09:30:54.679185817 +0200 >> +++ trunk/gcc/dwarf2out.c 2015-08-25 16:54:09.150506037 +0200 >> @@ -4827,6 +4827,7 @@ remove_child_with_prev (dw_die_ref child >> prev->die_sib = child->die_sib; >> if (child->die_parent->die_child == child) >> child->die_parent->die_child = prev; >> + child->die_sib = NULL; >> } >> >> /* Replace OLD_CHILD with NEW_CHILD. PREV must have the property that >> @@ -4853,6 +4854,7 @@ replace_child (dw_die_ref old_child, dw_ >> } >> if (old_child->die_parent->die_child == old_child) >> old_child->die_parent->die_child = new_child; >> + old_child->die_sib = NULL; >> } >> >> /* Move all children from OLD_PARENT to NEW_PARENT. */ >> @@ -4883,9 +4885,9 @@ remove_child_TAG (dw_die_ref die, enum d >> remove_child_with_prev (c, prev); >> c->die_parent = NULL; >> /* Might have removed every child. */ >> - if (c == c->die_sib) >> + if (die->die_child == NULL) >> return; >> - c = c->die_sib; >> + c = prev->die_sib; >> } >> } while (c != die->die_child); >> } >> @@ -24565,8 +24590,8 @@ prune_unused_types_prune (dw_die_ref die >> >> c = die->die_child; >> do { >> - dw_die_ref prev = c; >> - for (c = c->die_sib; ! c->die_mark; c = c->die_sib) >> + dw_die_ref prev = c, next; >> + for (c = c->die_sib; ! c->die_mark; c = next) >> if (c == die->die_child) >> { >> /* No marked children between 'prev' and the end of the list. */ >> @@ -24578,8 +24603,14 @@ prune_unused_types_prune (dw_die_ref die >> prev->die_sib = c->die_sib; >> die->die_child = prev; >> } >> + c->die_sib = NULL; >> return; >> } >> + else >> + { >> + next = c->die_sib; >> + c->die_sib = NULL; >> + } >> >> if (c != prev->die_sib) >> prev->die_sib = c; >> @@ -24824,8 +24855,8 @@ move_marked_base_types (void) >> remove_child_with_prev (c, prev); >> /* As base types got marked, there must be at least >> one node other than DW_TAG_base_type. */ >> - gcc_assert (c != c->die_sib); >> - c = c->die_sib; >> + gcc_assert (die->die_child != NULL); >> + c = prev->die_sib; >> } >> } >> while (c != die->die_child);