https://gcc.gnu.org/g:9726eff169f13850e68363d3f8b3fb420339a3b6
commit r16-7847-g9726eff169f13850e68363d3f8b3fb420339a3b6 Author: Alfie Richards <[email protected]> Date: Mon Feb 23 13:13:30 2026 +0000 aarch64: Fix FMV reachability and cgraph_node defintion value [PR 124167] Fix the reachability checks for FMV nodes which were put in the wrong place and fix the definition value for a dispatched symbol to match that of the default node. PR target/124167 gcc/ChangeLog * attribs.cc (make_dispatcher_decl): Change node->definition to inherit from the node its called on. * ipa.cc (remote_unreachable_nodes): Move FMV logic out of (!in_boundary_p) if block. gcc/testsuite/ChangeLog: * gcc.target/aarch64/pr124167.c: New test. Diff: --- gcc/attribs.cc | 6 +++++- gcc/ipa.cc | 19 +++++++++---------- gcc/testsuite/gcc.target/aarch64/pr124167.c | 7 +++++++ 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/gcc/attribs.cc b/gcc/attribs.cc index c63d13d7e550..99f2fd75531a 100644 --- a/gcc/attribs.cc +++ b/gcc/attribs.cc @@ -1230,7 +1230,11 @@ make_dispatcher_decl (const tree decl) /* Set flags on the cgraph_node for the new decl. */ cgraph_node *func_node = cgraph_node::get_create (func_decl); func_node->dispatcher_function = true; - func_node->definition = true; + /* For targets with TARGET_HAS_FMV_TARGET_ATTRIBUTE, the resolver is created + unconditionally if any versioned nodes are present. + For !TARGET_HAS_FMV_TARGET_ATTRIBUTE, the dispatcher is only defined when + the default node is defined. */ + func_node->definition = node->definition || TARGET_HAS_FMV_TARGET_ATTRIBUTE; cgraph_function_version_info *func_v = func_node->insert_new_function_version (); diff --git a/gcc/ipa.cc b/gcc/ipa.cc index ca939c9c1189..d1a0bb8ce1d0 100644 --- a/gcc/ipa.cc +++ b/gcc/ipa.cc @@ -441,16 +441,6 @@ symbol_table::remove_unreachable_nodes (FILE *file) } } - /* A reference to the default node implies use of all the other - versions (they get used in the function resolver made later - in multiple_target.cc) */ - cgraph_function_version_info *node_v = cnode->function_version (); - if (node_v && is_function_default_version (node->decl)) - for (cgraph_function_version_info *fvi = node_v->next; - fvi; - fvi = fvi->next) - enqueue_node (fvi->this_node, &first, &reachable); - for (e = cnode->callees; e; e = e->next_callee) { symtab_node *body = e->callee->function_symbol (); @@ -494,6 +484,15 @@ symbol_table::remove_unreachable_nodes (FILE *file) else if (cnode->thunk) enqueue_node (cnode->callees->callee, &first, &reachable); + /* A reference to the default node implies use of all the other + versions (they get used in the function resolver made later + in multiple_target.cc) */ + cgraph_function_version_info *node_v = cnode->function_version (); + if (node_v && is_function_default_version (node->decl)) + for (cgraph_function_version_info *fvi = node_v->next; fvi; + fvi = fvi->next) + enqueue_node (fvi->this_node, &first, &reachable); + /* If any reachable function has simd clones, mark them as reachable as well. */ if (cnode->simd_clones) diff --git a/gcc/testsuite/gcc.target/aarch64/pr124167.c b/gcc/testsuite/gcc.target/aarch64/pr124167.c new file mode 100644 index 000000000000..4ba94b0fe9ac --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/pr124167.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ + +/* Check there is no ICE. */ + +__attribute__ ((target_version ("default"))) int foo (); + +int bar () { return foo (); }
