diff mbox

[GOOGLE] Rewrite FUNCTION_DECL references after LIPO linking

Message ID CAAe5K+XL+icHS-u4kMg3NC2ey+HqcfdL__ZaD-j6kuLaMx+dPg@mail.gmail.com
State New
Headers show

Commit Message

Teresa Johnson July 15, 2014, 10:24 a.m. UTC
This patch will rewrite references to function decls in all statements
after LIPO linking so that the subsequent cgraph rebuild will set up
references correctly.

Passes regression and internal testing. Ok for google/4_9?

Thanks,
Teresa

2014-07-15  Teresa Johnson  <tejohnson@google.com>

        Google ref b/16190119
        * cgraphbuild.c (mark_address): Assert that node is resolved.
        (fixup_ref): New function.
        (fixup_address): Ditto.
        (fixup_load): Ditto.
        (lipo_fixup_load_addr_ops): Ditto.
        (lipo_link_and_fixup): Invoke lipo_fixup_load_addr_ops.

Comments

Xinliang David Li July 15, 2014, 3:48 p.m. UTC | #1
ok. This is now consistent with how cgraph targets are handled.
(Changes like this may shake up more bugs due to bad assumptions. More
extensive testing after this is expected).

David

On Tue, Jul 15, 2014 at 3:24 AM, Teresa Johnson <tejohnson@google.com> wrote:
> This patch will rewrite references to function decls in all statements
> after LIPO linking so that the subsequent cgraph rebuild will set up
> references correctly.
>
> Passes regression and internal testing. Ok for google/4_9?
>
> Thanks,
> Teresa
>
> 2014-07-15  Teresa Johnson  <tejohnson@google.com>
>
>         Google ref b/16190119
>         * cgraphbuild.c (mark_address): Assert that node is resolved.
>         (fixup_ref): New function.
>         (fixup_address): Ditto.
>         (fixup_load): Ditto.
>         (lipo_fixup_load_addr_ops): Ditto.
>         (lipo_link_and_fixup): Invoke lipo_fixup_load_addr_ops.
>
> Index: cgraphbuild.c
> ===================================================================
> --- cgraphbuild.c       (revision 212546)
> +++ cgraphbuild.c       (working copy)
> @@ -424,7 +424,14 @@ mark_address (gimple stmt, tree addr, tree, void *
>           */
>        if (L_IPO_COMP_MODE && cgraph_pre_profiling_inlining_done
>            && first_clone && !first_clone->global.inlined_to)
> -        node = cgraph_lipo_get_resolved_node (addr);
> +        {
> +          /* We now fix up address references to function decls after the LIPO
> +             link, so any existing node that isn't an inline clone should be
> +             the resolved node.  */
> +          struct cgraph_node *resolved = cgraph_lipo_get_resolved_node (addr);
> +          gcc_assert (resolved == first_clone);
> +          gcc_assert (resolved == node);
> +        }
>
>        cgraph_mark_address_taken_node (node);
>        ipa_record_reference ((symtab_node *)data,
> @@ -658,6 +665,56 @@ record_references_in_initializer (tree decl, bool
>    pointer_set_destroy (visited_nodes);
>  }
>
> +/* Update any function decl references in base ADDR of operand OP to refer to
> +   the resolved node.  */
> +
> +static bool
> +fixup_ref (gimple, tree addr, tree op)
> +{
> +  addr = get_base_address (addr);
> +  if (addr && TREE_CODE (addr) == FUNCTION_DECL)
> +    {
> +      gcc_assert (TREE_CODE (op) == ADDR_EXPR);
> +      gcc_assert (TREE_OPERAND (op,0) == addr);
> +      struct cgraph_node *real_callee;
> +      real_callee = cgraph_lipo_get_resolved_node (addr);
> +      if (addr == real_callee->decl)
> +        return false;
> +      TREE_OPERAND (op,0) = real_callee->decl;
> +    }
> +  return false;
> +}
> +
> +/* Update any function decl references in base ADDR of operand OP from address
> +   STMT operand OP to refer to the resolved node.  */
> +
> +static bool
> +fixup_address (gimple stmt, tree addr, tree op, void *)
> +{
> +  return fixup_ref (stmt, addr, op);
> +}
> +
> +/* Update any function decl references in base ADDR of operand OP from load
> +   STMT operand OP to refer to the resolved node.  See comments in mark_load
> +   on when a load may have a function decl reference.  */
> +
> +static bool
> +fixup_load (gimple stmt, tree addr, tree op, void *)
> +{
> +  return fixup_ref (stmt, addr, op);
> +}
> +
> +/* After the LIPO link, references to function decls should be updated
> +   to the resolved node, so that the correct references are added to the
> +   cgraph.  Update all references in STMT.  */
> +
> +void
> +lipo_fixup_load_addr_ops (gimple stmt)
> +{
> +  walk_stmt_load_store_addr_ops (stmt, NULL, fixup_load, NULL,
> +                                fixup_address);
> +}
> +
>  /* In LIPO mode, before tree_profiling, the call graph edge
>     needs to be built with the original target node to make
>     sure consistent early inline decisions between profile
> @@ -730,7 +787,10 @@ lipo_link_and_fixup ()
>                   gimple stmt = gsi_stmt (gsi);
>                   if (is_gimple_call (stmt))
>                     lipo_fixup_cgraph_edge_call_target (stmt);
> +                 lipo_fixup_load_addr_ops (stmt);
>                 }
> +             for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
> +               lipo_fixup_load_addr_ops (gsi_stmt (gsi));
>             }
>           update_ssa (TODO_update_ssa);
>         }
>
> --
> Teresa Johnson | Software Engineer | tejohnson@google.com | 408-460-2413
diff mbox

Patch

Index: cgraphbuild.c
===================================================================
--- cgraphbuild.c       (revision 212546)
+++ cgraphbuild.c       (working copy)
@@ -424,7 +424,14 @@  mark_address (gimple stmt, tree addr, tree, void *
          */
       if (L_IPO_COMP_MODE && cgraph_pre_profiling_inlining_done
           && first_clone && !first_clone->global.inlined_to)
-        node = cgraph_lipo_get_resolved_node (addr);
+        {
+          /* We now fix up address references to function decls after the LIPO
+             link, so any existing node that isn't an inline clone should be
+             the resolved node.  */
+          struct cgraph_node *resolved = cgraph_lipo_get_resolved_node (addr);
+          gcc_assert (resolved == first_clone);
+          gcc_assert (resolved == node);
+        }

       cgraph_mark_address_taken_node (node);
       ipa_record_reference ((symtab_node *)data,
@@ -658,6 +665,56 @@  record_references_in_initializer (tree decl, bool
   pointer_set_destroy (visited_nodes);
 }

+/* Update any function decl references in base ADDR of operand OP to refer to
+   the resolved node.  */
+
+static bool
+fixup_ref (gimple, tree addr, tree op)
+{
+  addr = get_base_address (addr);
+  if (addr && TREE_CODE (addr) == FUNCTION_DECL)
+    {
+      gcc_assert (TREE_CODE (op) == ADDR_EXPR);
+      gcc_assert (TREE_OPERAND (op,0) == addr);
+      struct cgraph_node *real_callee;
+      real_callee = cgraph_lipo_get_resolved_node (addr);
+      if (addr == real_callee->decl)
+        return false;
+      TREE_OPERAND (op,0) = real_callee->decl;
+    }
+  return false;
+}
+
+/* Update any function decl references in base ADDR of operand OP from address
+   STMT operand OP to refer to the resolved node.  */
+
+static bool
+fixup_address (gimple stmt, tree addr, tree op, void *)
+{
+  return fixup_ref (stmt, addr, op);
+}
+
+/* Update any function decl references in base ADDR of operand OP from load
+   STMT operand OP to refer to the resolved node.  See comments in mark_load
+   on when a load may have a function decl reference.  */
+
+static bool
+fixup_load (gimple stmt, tree addr, tree op, void *)
+{
+  return fixup_ref (stmt, addr, op);
+}
+
+/* After the LIPO link, references to function decls should be updated
+   to the resolved node, so that the correct references are added to the
+   cgraph.  Update all references in STMT.  */
+
+void
+lipo_fixup_load_addr_ops (gimple stmt)
+{
+  walk_stmt_load_store_addr_ops (stmt, NULL, fixup_load, NULL,
+                                fixup_address);
+}
+
 /* In LIPO mode, before tree_profiling, the call graph edge
    needs to be built with the original target node to make
    sure consistent early inline decisions between profile
@@ -730,7 +787,10 @@  lipo_link_and_fixup ()
                  gimple stmt = gsi_stmt (gsi);
                  if (is_gimple_call (stmt))
                    lipo_fixup_cgraph_edge_call_target (stmt);
+                 lipo_fixup_load_addr_ops (stmt);
                }
+             for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+               lipo_fixup_load_addr_ops (gsi_stmt (gsi));
            }
          update_ssa (TODO_update_ssa);
        }