[Bug ipa/85960] -fipa-pta and ifunc are incompatible

rguenth at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Wed May 30 13:43:00 GMT 2018


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;
 }


More information about the Gcc-bugs mailing list