https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85960
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Keywords| |wrong-code CC| |hubicka at gcc dot gnu.org Version|unknown |8.1.1 --- Comment #5 from Richard Biener <rguenth at gcc dot gnu.org> --- The issue seems to be that the multiver stuff is multiver_test/35 (multiver_test) @0x7ff2d74c62e0 Type: function definition analyzed alias Visibility: externally_visible public References: resolve_multiver/34 (alias) Referring: Availability: overwritable First run: 0 Function flags: Called by: main/37 (955630223 (estimated locally),8.09 per call) Calls: resolve_multiver/34 (resolve_multiver) @0x7ff2d74c6170 Type: function definition analyzed Visibility: prevailing_def_ironly References: multiver_default/33 (addr) Referring: multiver_test/35 (alias) Availability: available First run: 0 Function flags: count: 1073741826 (estimated locally) body nonfreeing_fn Called by: Calls: multiver_default/33 (multiver_default) @0x7ff2d74c6000 Type: function definition analyzed Visibility: prevailing_def_ironly Address is taken. References: Referring: resolve_multiver/34 (addr) Availability: available First run: 0 Function flags: count: 1073741826 (estimated locally) body nonfreeing_fn hot Called by: Calls: so multiver_test is an alias of resolve_multiver which means we get constraints for resolve_multiver instead of the union of resolve_multiver and multiver_default. In IPA PTA we do /* Build the constraints. */ FOR_EACH_DEFINED_FUNCTION (node) { ... node->call_for_symbol_thunks_and_aliases (associate_varinfo_to_alias, vi, true); where we "merge" aliases into the DEFINED copy. How we represent ifuncs wrecks with this it seems. We use the resolve_multiver data for calls to multiver_test. We probably can add a ifunc attribute lookup but IMHO the cgraph representation is just bogus. It looks like the multiver_test cgraph node has ifunc_resolver set to 1(!?) but resolve_multiver doesn't. /* Set when symbol is an IFUNC resolver. */ unsigned ifunc_resolver : 1; I expected resolve_multiver to be the IFUNC resolver. So without actually understanding this mess the following "fixes" the issue: Index: gcc/tree-ssa-structalias.c =================================================================== --- gcc/tree-ssa-structalias.c (revision 260950) +++ gcc/tree-ssa-structalias.c (working copy) @@ -7713,7 +7713,8 @@ associate_varinfo_to_alias (struct cgrap if ((node->alias || (node->thunk.thunk_p && ! node->global.inlined_to)) - && node->analyzed) + && node->analyzed + && !node->ifunc_resolver) insert_vi_for_tree (node->decl, (varinfo_t)data); return false; } My point is that multiver_test doesn't call resolve_multiver but it calls one of the functions returned by the resolver. So - a different fix from the above would handle this at the point we generate constraints for the call to multiver_test and emit constraints for fn = resolve_multiver (); (*fn) (args...). That looks needed because if you make multiver_test static the constraints still look wrong. We still need to avoid associating one decl with the other like above. And we need to get the clobbers on the ifunc call correct... Half-way patch where the points-to sets look good but the clobbers/uses are still broken: Index: gcc/tree-ssa-structalias.c =================================================================== --- gcc/tree-ssa-structalias.c (revision 260950) +++ gcc/tree-ssa-structalias.c (working copy) @@ -3903,7 +3903,7 @@ get_function_part_constraint (varinfo_t c.offset = 0; c.type = SCALAR; } - else if (TREE_CODE (fi->decl) == FUNCTION_DECL) + else if (fi->decl && TREE_CODE (fi->decl) == FUNCTION_DECL) { varinfo_t ai = first_vi_for_offset (fi, part); if (ai) @@ -4732,6 +4732,30 @@ find_func_aliases_for_call (struct funct return; fi = get_fi_for_callee (t); + /* First process an ifunc resolver if we run into one. */ + if (fndecl) + { + cgraph_node *node = cgraph_node::get (fndecl); + if (node->ifunc_resolver) + { + fi = get_vi_for_tree (node->get_alias_target ()->decl); + if (fi->is_fn_info) + { + constraint_expr rhs + = get_function_part_constraint (fi, fi_result); + fi = new_var_info (NULL_TREE, "ifuncres", true); + fi->is_reg_var = true; + constraint_expr lhs; + lhs.type = SCALAR; + lhs.var = fi->id; + lhs.offset = 0; + process_constraint (new_constraint (lhs, rhs)); + } + else + fi = get_varinfo (anything_id); + fndecl = NULL_TREE; + } if (!in_ipa_mode || (fndecl && !fi->is_fn_info)) { @@ -7713,7 +7737,8 @@ associate_varinfo_to_alias (struct cgrap if ((node->alias || (node->thunk.thunk_p && ! node->global.inlined_to)) - && node->analyzed) + && node->analyzed + && !node->ifunc_resolver) insert_vi_for_tree (node->decl, (varinfo_t)data); return false; }