lto-cgraph.c (compute_ltrans_boundary): Add abstract origins into boundaries.
authorJan Hubicka <jh@suse.cz>
Sat, 3 Aug 2013 19:54:18 +0000 (21:54 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Sat, 3 Aug 2013 19:54:18 +0000 (19:54 +0000)
* lto-cgraph.c (compute_ltrans_boundary): Add abstract origins into
boundaries.
* lto-streamer-out.c (tree_is_indexable): Results decls and
parm decls are not indexable.
(DFS_write_tree_body): Do not follow args and results.
(hash_tree): Likewise.
(output_functions): Rearrange so struct function is needed
only when real body is output; be able to also ouptut abstract
functions; output DECL_ARGUMENTS and DECL_RESULT.
(lto_output): When not in WPA, ale store abstract functions.
(write_symbol): Do not care about RESULT_DECL.
(output_symbol_p): Handle correctly sbtract decls.
* lto-streamer-in.c (input_function): Rearrange so struct
function can be NULL at entry; allow streaming of
functions w/o body; store DECL_ARGUMENTS and DECL_RESULT.
* ipa.c (symtab_remove_unreachable_nodes): Silence confused
sanity check during LTO.
* tree-streamer-out.c (write_ts_decl_non_common_tree_pointers): Skip
RESULT_DECl and DECL_ARGUMENTS.
* tree-streamer-in.c (lto_input_ts_decl_non_common_tree_pointers):
Likewise.

* lto.c (lto_materialize_function): Do not push struct function.
* lto-partition.c (get_symbol_class): Handle abstracts correctly.
(may_need_named_section_p): Even abstract origins may need
named section.

From-SVN: r201468

gcc/ChangeLog
gcc/ipa.c
gcc/lto-cgraph.c
gcc/lto-streamer-in.c
gcc/lto-streamer-out.c
gcc/lto/ChangeLog
gcc/lto/lto-partition.c
gcc/lto/lto.c
gcc/tree-streamer-in.c
gcc/tree-streamer-out.c

index c172782..dbac140 100644 (file)
@@ -1,3 +1,27 @@
+2013-08-02  Jan Hubicka  <jh@suse.cz>
+
+       * lto-cgraph.c (compute_ltrans_boundary): Add abstract origins into
+       boundaries.
+       * lto-streamer-out.c (tree_is_indexable): Results decls and
+       parm decls are not indexable.
+       (DFS_write_tree_body): Do not follow args and results.
+       (hash_tree): Likewise.
+       (output_functions): Rearrange so struct function is needed
+       only when real body is output; be able to also ouptut abstract
+       functions; output DECL_ARGUMENTS and DECL_RESULT.
+       (lto_output): When not in WPA, ale store abstract functions.
+       (write_symbol): Do not care about RESULT_DECL.
+       (output_symbol_p): Handle correctly sbtract decls.
+       * lto-streamer-in.c (input_function): Rearrange so struct
+       function can be NULL at entry; allow streaming of
+       functions w/o body; store DECL_ARGUMENTS and DECL_RESULT.
+       * ipa.c (symtab_remove_unreachable_nodes): Silence confused
+       sanity check during LTO.
+       * tree-streamer-out.c (write_ts_decl_non_common_tree_pointers): Skip
+       RESULT_DECl and DECL_ARGUMENTS.
+       * tree-streamer-in.c (lto_input_ts_decl_non_common_tree_pointers):
+       Likewise.
+
 2013-08-03  Gabriel Dos Reis  <gdr@integrable-solutions.net>
 
        * pretty-print.h (pp_underscore): New.
index f42de4d..2f60a98 100644 (file)
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -371,7 +371,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
          if (!pointer_set_contains (body_needed_for_clonning, node->symbol.decl))
            cgraph_release_function_body (node);
          else if (!node->clone_of)
-           gcc_assert (DECL_RESULT (node->symbol.decl));
+           gcc_assert (in_lto_p || DECL_RESULT (node->symbol.decl));
          if (node->symbol.definition)
            {
              if (file)
@@ -382,7 +382,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
        }
       else
        gcc_assert (node->clone_of || !cgraph_function_with_gimple_body_p (node)
-                   || DECL_RESULT (node->symbol.decl));
+                   || in_lto_p || DECL_RESULT (node->symbol.decl));
     }
 
   /* Inline clones might be kept around so their materializing allows further
index 3f9c56d..c3c393f 100644 (file)
@@ -749,6 +749,13 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
       add_node_to (encoder, node, true);
       lto_set_symtab_encoder_in_partition (encoder, (symtab_node)node);
       add_references (encoder, &node->symbol.ref_list);
+      /* For proper debug info, we need to ship the origins, too.  */
+      if (DECL_ABSTRACT_ORIGIN (node->symbol.decl))
+       {
+         struct cgraph_node *origin_node
+         = cgraph_get_node (DECL_ABSTRACT_ORIGIN (node->symbol.decl));
+         add_node_to (encoder, origin_node, true);
+       }
     }
   for (lsei = lsei_start_variable_in_partition (in_encoder);
        !lsei_end_p (lsei); lsei_next_variable_in_partition (&lsei))
@@ -758,6 +765,13 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
       lto_set_symtab_encoder_in_partition (encoder, (symtab_node)vnode);
       lto_set_symtab_encoder_encode_initializer (encoder, vnode);
       add_references (encoder, &vnode->symbol.ref_list);
+      /* For proper debug info, we need to ship the origins, too.  */
+      if (DECL_ABSTRACT_ORIGIN (vnode->symbol.decl))
+       {
+         struct varpool_node *origin_node
+         = varpool_get_node (DECL_ABSTRACT_ORIGIN (node->symbol.decl));
+         lto_set_symtab_encoder_in_partition (encoder, (symtab_node)origin_node);
+       }
     }
   /* Pickle in also the initializer of all referenced readonly variables
      to help folding.  Constant pool variables are not shared, so we must
index fe7ab7c..70a87d1 100644 (file)
@@ -851,7 +851,7 @@ input_struct_function_base (struct function *fn, struct data_in *data_in,
 
 static void
 input_function (tree fn_decl, struct data_in *data_in,
-               struct lto_input_block *ib)
+               struct lto_input_block *ib, struct lto_input_block *ib_cfg)
 {
   struct function *fn;
   enum LTO_tags tag;
@@ -859,13 +859,30 @@ input_function (tree fn_decl, struct data_in *data_in,
   basic_block bb;
   struct cgraph_node *node;
 
-  fn = DECL_STRUCT_FUNCTION (fn_decl);
   tag = streamer_read_record_start (ib);
+  lto_tag_check (tag, LTO_function);
+
+  /* Read decls for parameters and args.  */
+  DECL_RESULT (fn_decl) = stream_read_tree (ib, data_in);
+  DECL_ARGUMENTS (fn_decl) = streamer_read_chain (ib, data_in);
+
+  /* Read the tree of lexical scopes for the function.  */
+  DECL_INITIAL (fn_decl) = stream_read_tree (ib, data_in);
+
+  if (!streamer_read_uhwi (ib))
+    return;
+
+  push_struct_function (fn_decl);
+  fn = DECL_STRUCT_FUNCTION (fn_decl);
+  init_tree_ssa (fn);
+  /* We input IL in SSA form.  */
+  cfun->gimple_df->in_ssa_p = true;
 
   gimple_register_cfg_hooks ();
-  lto_tag_check (tag, LTO_function);
 
+  node = cgraph_get_create_node (fn_decl);
   input_struct_function_base (fn, data_in, ib);
+  input_cfg (ib_cfg, fn, node->count_materialization_scale);
 
   /* Read all the SSA names.  */
   input_ssa_names (ib, data_in, fn);
@@ -873,11 +890,8 @@ input_function (tree fn_decl, struct data_in *data_in,
   /* Read the exception handling regions in the function.  */
   input_eh_regions (ib, data_in, fn);
 
-  /* Read the tree of lexical scopes for the function.  */
-  DECL_INITIAL (fn_decl) = stream_read_tree (ib, data_in);
   gcc_assert (DECL_INITIAL (fn_decl));
   DECL_SAVED_TREE (fn_decl) = NULL_TREE;
-  node = cgraph_get_create_node (fn_decl);
 
   /* Read all the basic blocks.  */
   tag = streamer_read_record_start (ib);
@@ -987,28 +1001,21 @@ lto_read_body (struct lto_file_decl_data *file_data, tree fn_decl,
 
   if (section_type == LTO_section_function_body)
     {
-      struct function *fn = DECL_STRUCT_FUNCTION (fn_decl);
       struct lto_in_decl_state *decl_state;
       struct cgraph_node *node = cgraph_get_node (fn_decl);
       unsigned from;
 
       gcc_checking_assert (node);
-      push_cfun (fn);
-      init_tree_ssa (fn);
-
-      /* We input IL in SSA form.  */
-      cfun->gimple_df->in_ssa_p = true;
 
       /* Use the function's decl state. */
       decl_state = lto_get_function_in_decl_state (file_data, fn_decl);
       gcc_assert (decl_state);
       file_data->current_decl_state = decl_state;
 
-      input_cfg (&ib_cfg, fn, node->count_materialization_scale);
 
       /* Set up the struct function.  */
       from = data_in->reader_cache->nodes.length ();
-      input_function (fn_decl, data_in, &ib_main);
+      input_function (fn_decl, data_in, &ib_main, &ib_cfg);
       /* And fixup types we streamed locally.  */
        {
          struct streamer_tree_cache_d *cache = data_in->reader_cache;
index a962e9c..ab7a899 100644 (file)
@@ -124,8 +124,8 @@ output_type_ref (struct output_block *ob, tree node)
 static bool
 tree_is_indexable (tree t)
 {
-  if (TREE_CODE (t) == PARM_DECL)
-    return true;
+  if (TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
+    return false;
   else if (TREE_CODE (t) == VAR_DECL && decl_function_context (t)
           && !TREE_STATIC (t))
     return false;
@@ -506,13 +506,7 @@ DFS_write_tree_body (struct output_block *ob,
 
   if (CODE_CONTAINS_STRUCT (code, TS_DECL_NON_COMMON))
     {
-      if (TREE_CODE (expr) == FUNCTION_DECL)
-       {
-         for (tree t = DECL_ARGUMENTS (expr); t; t = TREE_CHAIN (t))
-           DFS_follow_tree_edge (t);
-         DFS_follow_tree_edge (DECL_RESULT (expr));
-       }
-      else if (TREE_CODE (expr) == TYPE_DECL)
+      if (TREE_CODE (expr) == TYPE_DECL)
        DFS_follow_tree_edge (DECL_ORIGINAL_TYPE (expr));
       DFS_follow_tree_edge (DECL_VINDEX (expr));
     }
@@ -936,13 +930,7 @@ hash_tree (struct streamer_tree_cache_d *cache, tree t)
 
   if (CODE_CONTAINS_STRUCT (code, TS_DECL_NON_COMMON))
     {
-      if (code == FUNCTION_DECL)
-       {
-         for (tree a = DECL_ARGUMENTS (t); a; a = DECL_CHAIN (a))
-           visit (a);
-         visit (DECL_RESULT (t));
-       }
-      else if (code == TYPE_DECL)
+      if (code == TYPE_DECL)
        visit (DECL_ORIGINAL_TYPE (t));
       visit (DECL_VINDEX (t));
     }
@@ -1772,50 +1760,63 @@ output_function (struct cgraph_node *node)
 
   streamer_write_record_start (ob, LTO_function);
 
-  output_struct_function_base (ob, fn);
-
-  /* Output all the SSA names used in the function.  */
-  output_ssa_names (ob, fn);
-
-  /* Output any exception handling regions.  */
-  output_eh_regions (ob, fn);
+  /* Output decls for parameters and args.  */
+  stream_write_tree (ob, DECL_RESULT (function), true);
+  streamer_write_chain (ob, DECL_ARGUMENTS (function), true);
 
   /* Output DECL_INITIAL for the function, which contains the tree of
      lexical scopes.  */
   stream_write_tree (ob, DECL_INITIAL (function), true);
 
-  /* We will renumber the statements.  The code that does this uses
-     the same ordering that we use for serializing them so we can use
-     the same code on the other end and not have to write out the
-     statement numbers.  We do not assign UIDs to PHIs here because
-     virtual PHIs get re-computed on-the-fly which would make numbers
-     inconsistent.  */
-  set_gimple_stmt_max_uid (cfun, 0);
-  FOR_ALL_BB (bb)
-    {
-      gimple_stmt_iterator gsi;
-      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+  /* We also stream abstract functions where we stream only stuff needed for
+     debug info.  */
+  if (gimple_has_body_p (function))
+    {
+      streamer_write_uhwi (ob, 1);
+      output_struct_function_base (ob, fn);
+
+      /* Output all the SSA names used in the function.  */
+      output_ssa_names (ob, fn);
+
+      /* Output any exception handling regions.  */
+      output_eh_regions (ob, fn);
+
+
+      /* We will renumber the statements.  The code that does this uses
+        the same ordering that we use for serializing them so we can use
+        the same code on the other end and not have to write out the
+        statement numbers.  We do not assign UIDs to PHIs here because
+        virtual PHIs get re-computed on-the-fly which would make numbers
+        inconsistent.  */
+      set_gimple_stmt_max_uid (cfun, 0);
+      FOR_ALL_BB (bb)
        {
-         gimple stmt = gsi_stmt (gsi);
-         gimple_set_uid (stmt, inc_gimple_stmt_max_uid (cfun));
+         gimple_stmt_iterator gsi;
+         for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+           {
+             gimple stmt = gsi_stmt (gsi);
+             gimple_set_uid (stmt, inc_gimple_stmt_max_uid (cfun));
+           }
        }
-    }
 
-  /* Output the code for the function.  */
-  FOR_ALL_BB_FN (bb, fn)
-    output_bb (ob, bb, fn);
+      /* Output the code for the function.  */
+      FOR_ALL_BB_FN (bb, fn)
+       output_bb (ob, bb, fn);
 
-  /* The terminator for this function.  */
-  streamer_write_record_start (ob, LTO_null);
+      /* The terminator for this function.  */
+      streamer_write_record_start (ob, LTO_null);
 
-  output_cfg (ob, fn);
+      output_cfg (ob, fn);
+
+      pop_cfun ();
+   }
+  else
+    streamer_write_uhwi (ob, 0);
 
   /* Create a section to hold the pickled output of this function.   */
   produce_asm (ob, function);
 
   destroy_output_block (ob);
-
-  pop_cfun ();
 }
 
 
@@ -1966,7 +1967,7 @@ lto_output (void)
 #endif
          decl_state = lto_new_out_decl_state ();
          lto_push_out_decl_state (decl_state);
-         if (gimple_has_body_p (node->symbol.decl))
+         if (gimple_has_body_p (node->symbol.decl) || !flag_wpa)
            output_function (node);
          else
            copy_function (node);
@@ -2149,9 +2150,9 @@ write_symbol (struct streamer_tree_cache_d *cache,
   if (!TREE_PUBLIC (t)
       || is_builtin_fn (t)
       || DECL_ABSTRACT (t)
-      || TREE_CODE (t) == RESULT_DECL
       || (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t)))
     return;
+  gcc_assert (TREE_CODE (t) != RESULT_DECL);
 
   gcc_assert (TREE_CODE (t) == VAR_DECL
              || TREE_CODE (t) == FUNCTION_DECL);
@@ -2254,7 +2255,7 @@ output_symbol_p (symtab_node node)
      and devirtualization.  We do not want to see them in symbol table as
      references unless they are really used.  */
   cnode = dyn_cast <cgraph_node> (node);
-  if (cnode && DECL_EXTERNAL (cnode->symbol.decl)
+  if (cnode && (!node->symbol.definition || DECL_EXTERNAL (cnode->symbol.decl))
       && cnode->callers)
     return true;
 
@@ -2262,7 +2263,7 @@ output_symbol_p (symtab_node node)
     part of the compilation unit until they are used by folding.  Some symbols,
     like references to external construction vtables can not be referred to at all.
     We decide this at can_refer_decl_in_current_unit_p.  */
- if (DECL_EXTERNAL (node->symbol.decl))
+ if (!node->symbol.definition || DECL_EXTERNAL (node->symbol.decl))
     {
       int i;
       struct ipa_ref *ref;
index 37e8afd..33f3b32 100644 (file)
@@ -1,3 +1,10 @@
+2013-08-02  Jan Hubicka  <jh@suse.cz>
+
+       * lto.c (lto_materialize_function): Do not push struct function.
+       * lto-partition.c (get_symbol_class): Handle abstracts correctly.
+       (may_need_named_section_p): Even abstract origins may need
+       named section.
+
 2013-07-30  David Malcolm  <dmalcolm@redhat.com>
 
        * Make-lang.in (lto/lto.o:): Depend on CONTEXT_H and
index 63e6ab9..879218c 100644 (file)
@@ -56,6 +56,10 @@ get_symbol_class (symtab_node node)
   /* Inline clones are always duplicated.
      This include external delcarations.   */
   cgraph_node *cnode = dyn_cast <cgraph_node> (node);
+
+  if (DECL_ABSTRACT (node->symbol.decl))
+    return SYMBOL_EXTERNAL;
+
   if (cnode && cnode->global.inlined_to)
     return SYMBOL_DUPLICATE;
 
@@ -840,8 +844,6 @@ may_need_named_section_p (lto_symtab_encoder_t encoder, symtab_node node)
     return false;
   if (symtab_real_symbol_p (node))
     return false;
-  if (!cnode->global.inlined_to && !cnode->clones)
-    return false;
   return (!encoder
          || (lto_symtab_encoder_lookup (encoder, node) != LCC_NOT_FOUND
               && lto_symtab_encoder_encode_body_p (encoder,
index 32f8326..42d67f1 100644 (file)
@@ -225,7 +225,6 @@ lto_materialize_function (struct cgraph_node *node)
 
          gcc_assert (DECL_STRUCT_FUNCTION (decl) == NULL);
 
-         push_struct_function (decl);
          announce_function (decl);
          lto_input_function_body (file_data, decl, data);
          if (DECL_FUNCTION_PERSONALITY (decl) && !first_personality_decl)
@@ -233,7 +232,6 @@ lto_materialize_function (struct cgraph_node *node)
          lto_stats.num_function_bodies++;
          lto_free_section_data (file_data, LTO_section_function_body, name,
                                 data, len);
-         pop_cfun ();
          ggc_collect ();
        }
     }
index 00f78a1..9efd099 100644 (file)
@@ -678,12 +678,7 @@ static void
 lto_input_ts_decl_non_common_tree_pointers (struct lto_input_block *ib,
                                            struct data_in *data_in, tree expr)
 {
-  if (TREE_CODE (expr) == FUNCTION_DECL)
-    {
-      DECL_ARGUMENTS (expr) = streamer_read_chain (ib, data_in);
-      DECL_RESULT (expr) = stream_read_tree (ib, data_in);
-    }
-  else if (TREE_CODE (expr) == TYPE_DECL)
+  if (TREE_CODE (expr) == TYPE_DECL)
     DECL_ORIGINAL_TYPE (expr) = stream_read_tree (ib, data_in);
   DECL_VINDEX (expr) = stream_read_tree (ib, data_in);
 }
index fa50ef5..692a46a 100644 (file)
@@ -606,12 +606,7 @@ static void
 write_ts_decl_non_common_tree_pointers (struct output_block *ob, tree expr,
                                        bool ref_p)
 {
-  if (TREE_CODE (expr) == FUNCTION_DECL)
-    {
-      streamer_write_chain (ob, DECL_ARGUMENTS (expr), ref_p);
-      stream_write_tree (ob, DECL_RESULT (expr), ref_p);
-    }
-  else if (TREE_CODE (expr) == TYPE_DECL)
+  if (TREE_CODE (expr) == TYPE_DECL)
     stream_write_tree (ob, DECL_ORIGINAL_TYPE (expr), ref_p);
   stream_write_tree (ob, DECL_VINDEX (expr), ref_p);
 }