r248336 added these lines to free_growth_caches if (edge_removal_hook_holder) symtab->remove_edge_removal_hook (edge_removal_hook_holder);
which broke the JIT; attempts to compile more than one time within a single process segfault here: 305 symbol_table::remove_edge_removal_hook (cgraph_edge_hook_list *entry) 306 { 307 cgraph_edge_hook_list **ptr = &m_first_edge_removal_hook; 308 309 while (*ptr != entry) >>310 ptr = &(*ptr)->next; 311 *ptr = entry->next; 312 free (entry); 313 } (gdb) p ptr $3 = (cgraph_edge_hook_list **) 0x10 (gdb) bt #0 symbol_table::remove_edge_removal_hook (this=0x7fffeef83200, entry=0x664c90) at ../../src/gcc/cgraph.c:310 #1 0x00007ffff6a03e2c in free_growth_caches () at ../../src/gcc/ipa-inline-analysis.c:113 #2 0x00007ffff73e7bd9 in inline_small_functions () at ../../src/gcc/ipa-inline.c:2059 #3 ipa_inline () at ../../src/gcc/ipa-inline.c:2417 [...] The root cause is that initialize_growth_caches lazily adds edge_removal_hook_holder to the symtab: 99 if (!edge_removal_hook_holder) 100 edge_removal_hook_holder = 101 symtab->add_edge_removal_hook (&inline_edge_removal_hook, NULL); but free_growth_caches removes it without NULL-ing it: 112 if (edge_removal_hook_holder) 113 symtab->remove_edge_removal_hook (edge_removal_hook_holder); Hence on the second call to free_growth_caches, it attempts to remove the edge_removal_hook_holder from the 1st iteration's initialize_growth_caches, which isn't present in the 2nd iteration's symtab. Hence the edge_removal_hook_holder isn't present, and symtab::remove_edge_removal_hook, relying on it as a sentinel value, reads through ((cgraph_edge_hook_list *)NULL)->next. This patch fixes the segfault by resetting it to NULL when removing it. Successfully bootstrapped®rtested on x86_64-pc-linux-gnu. Restores jit.sum from: # of expected passes 2892 # of unexpected failures 61 # of unresolved testcases 1 to: # of expected passes 3202 Committed to trunk as r248841, under the "obvious" rule. gcc/ChangeLog: PR jit/80954 * ipa-inline-analysis.c (free_growth_caches): Set edge_removal_hook_holder to NULL after removing it. --- gcc/ipa-inline-analysis.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c index f562ca5..9f7b2a1 100644 --- a/gcc/ipa-inline-analysis.c +++ b/gcc/ipa-inline-analysis.c @@ -110,7 +110,10 @@ void free_growth_caches (void) { if (edge_removal_hook_holder) - symtab->remove_edge_removal_hook (edge_removal_hook_holder); + { + symtab->remove_edge_removal_hook (edge_removal_hook_holder); + edge_removal_hook_holder = NULL; + } edge_growth_cache.release (); } -- 1.8.5.3