https://gcc.gnu.org/g:1e314be3ccc50dc7dcf0ad6c3aebe63cf025f4bf
commit r16-6458-g1e314be3ccc50dc7dcf0ad6c3aebe63cf025f4bf Author: Kugan Vivekanandarajah <[email protected]> Date: Fri Jan 2 07:58:28 2026 +1100 [PATCH] [AutoFDO/devirt] Fix ICE with duplicate speculative ID This happens due to autoprofile pass makes edge make_speculative. Then ipa-devirt does the same with the same speculative_id which reults in duplicate speculative_id and ICE. during IPA pass: cp test.i:31:1: internal compiler error: verify_cgraph_node failed 0x39bfa6b internal_error(char const*, ...) ../../gcc/gcc/diagnostic-global-context.cc:787 0x13914eb cgraph_node::verify_node() ../../gcc/gcc/cgraph.cc:4454 0x13738ab symtab_node::verify() ../../gcc/gcc/symtab.cc:1377 0x1373d1b symtab_node::verify_symtab_nodes() ../../gcc/gcc/symtab.cc:1499 0x13a3653 symtab_node::checking_verify_symtab_nodes() ../../gcc/gcc/cgraph.h:718 0x182d267 symbol_table::remove_unreachable_nodes(_IO_FILE*) ../../gcc/gcc/ipa.cc:688 0x19f8c33 execute_todo ../../gcc/gcc/passes.cc:2163 We may also have to check if the speculative edge is present before making speculative. gcc/ChangeLog: 2025-12-22 Kugan Vivekanandarajah <[email protected]> * cgraph.cc (cgraph_edge::get_next_speculative_id): New. * cgraph.h (cgraph_edge::get_next_speculative_id): New. * ipa-devirt.cc (ipa_devirt): Use get_next_speculative_id in make_speculative. Signed-off-by: Kugan Vivekanandarajah <[email protected]> Diff: --- gcc/cgraph.cc | 26 ++++++++++++++++++++++++++ gcc/cgraph.h | 5 +++++ gcc/ipa-devirt.cc | 5 +++-- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/gcc/cgraph.cc b/gcc/cgraph.cc index 9e273642dab9..0c1995dcfbdb 100644 --- a/gcc/cgraph.cc +++ b/gcc/cgraph.cc @@ -1265,6 +1265,32 @@ cgraph_edge::remove (cgraph_edge *edge) symtab->free_edge (edge); } +/* Returns the next speculative_id based on currently in use + for the given statement for the edge. + Returns 0 if no speculative edges exist for this statement. */ + +int +cgraph_edge::get_next_speculative_id () +{ + int max_id = -1; + cgraph_edge *e; + + /* Iterate through all edges leaving this caller */ + for (e = caller->callees; e; e = e->next_callee) + { + /* Match the specific GIMPLE statement and check the + speculative flag */ + if (e->call_stmt == call_stmt && e->speculative) + { + if (e->speculative_id > max_id) + max_id = e->speculative_id; + } + } + + return max_id + 1; +} + + /* Turn edge into speculative call calling N2. Update the profile so the direct call is taken COUNT times with FREQUENCY. diff --git a/gcc/cgraph.h b/gcc/cgraph.h index dbbab4087a9a..d471ce85c1ed 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -1894,6 +1894,11 @@ public: call. */ static cgraph_edge *make_direct (cgraph_edge *edge, cgraph_node *callee); + /* Returns the next speculative_id based on currently in use + for the given statement for the edge. + Returns 0 if no speculative edges exist for this statement. */ + int get_next_speculative_id (); + /* Turn edge into speculative call calling N2. Update the profile so the direct call is taken COUNT times with FREQUENCY. speculative_id is used to link direct calls with their diff --git a/gcc/ipa-devirt.cc b/gcc/ipa-devirt.cc index bb0f5c767102..0b7e8bb6fae6 100644 --- a/gcc/ipa-devirt.cc +++ b/gcc/ipa-devirt.cc @@ -3865,7 +3865,7 @@ ipa_devirt (void) continue; } bool first = true; - unsigned speculative_id = 0; + unsigned speculative_id = e->get_next_speculative_id (); for (cgraph_node * likely_target: likely_targets) { if (!devirt_target_ok_p (likely_target, &stats)) @@ -3940,7 +3940,8 @@ ipa_devirt (void) update = true; e->make_speculative (likely_tgt_node, - e->count.apply_scale (8, 10)); + e->count.apply_scale (8, 10), + e->get_next_speculative_id ()); } } if (update)
