This patch adds a new streamer hook to populate the streamer cache
with common nodes.

The nodes we populate for GIMPLE in lto_get_common_nodes is not
sufficient for C++, unsurprisingly.

The patch fixes these regressions in pph.exp:

FAIL: g++.dg/pph/p1stdlib.cc  -fpph-map=pph.map -I. (test for excess errors)
FAIL: g++.dg/pph/p1stdlib.cc , PPH assembly missing

There is a second part to this patch to handle INTEGER_CSTs as regular
trees (so they can be cached).  This would allow us to handle special
constants in the C++ FE like void_zero_node, but that's giving me some
trouble with LTO tests.

Tested on x86_64.  Committed to the branch.


Diego.

ChangeLog.pph

        * Makefile.in (cgraphunit.o): Add dependency on LTO_STREAMER_H.
        * cgraphunit.c: Include lto-streamer.h
        (cgraph_finalize_compilation_unit): Call gimple_streamer_hooks_init
        if LTO is enabled.
        * lto-streamer-out.c (lto_output): Move call to
        gimple_streamer_hooks_init to cgraph_finalize_compilation_unit.
        * lto-streamer.c (lto_get_common_nodes): Remove if0 hack.
        (lto_streamer_cache_create): Call streamer_hooks.get_common_nodes
        instead of lto_get_common_nodes.
        (gimple_streamer_hooks_init): Set h->get_common_nodes to
        lto_get_common_nodes.
        * lto-streamer.h (struct lto_streamer_hooks): Add field
        get_common_nodes.

cp/ChangeLog.pph

        * pph-streamer.c (pph_get_common_nodes): New.
        (pph_stream_hooks_init): Set it in h->get_common_nodes.

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 0af93ba..f96e059 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -3001,7 +3001,7 @@ cgraphunit.o : cgraphunit.c $(CONFIG_H) $(SYSTEM_H) 
coretypes.h $(TM_H) \
    $(TREE_FLOW_H) $(TREE_PASS_H) debug.h $(DIAGNOSTIC_H) \
    $(FIBHEAP_H) output.h $(PARAMS_H) $(RTL_H) $(TIMEVAR_H) $(IPA_PROP_H) \
    gt-cgraphunit.h tree-iterator.h $(COVERAGE_H) $(TREE_DUMP_H) \
-   tree-pretty-print.h gimple-pretty-print.h
+   tree-pretty-print.h gimple-pretty-print.h $(LTO_STREAMER_H)
 cgraphbuild.o : cgraphbuild.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
    $(TREE_H) langhooks.h $(CGRAPH_H) intl.h pointer-set.h $(GIMPLE_H) \
    $(TREE_FLOW_H) $(TREE_PASS_H) $(IPA_UTILS_H) $(EXCEPT_H) \
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 3dbfc2b..0d1ec89 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -138,6 +138,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "output.h"
 #include "coverage.h"
 #include "plugin.h"
+#include "lto-streamer.h"
 
 static void cgraph_expand_all_functions (void);
 static void cgraph_mark_functions_to_output (void);
@@ -1062,6 +1063,10 @@ cgraph_finalize_compilation_unit (void)
 {
   timevar_push (TV_CGRAPH);
 
+  /* If LTO is enabled, initialize the streamer hooks needed by GIMPLE.  */
+  if (flag_lto)
+    gimple_streamer_hooks_init ();
+
   /* If we're here there's no current function anymore.  Some frontends
      are lazy in clearing these.  */
   current_function_decl = NULL;
diff --git a/gcc/cp/pph-streamer.c b/gcc/cp/pph-streamer.c
index 5f2112e..c363c06 100644
--- a/gcc/cp/pph-streamer.c
+++ b/gcc/cp/pph-streamer.c
@@ -55,6 +55,36 @@ pph_indexable_with_decls_p (tree t)
 }
 
 
+/* Generate a vector of common nodes that should always be streamed as
+   indexes into the streamer cache.  These nodes are always built by
+   the front end, so there is no need to emit them.  */
+
+static VEC(tree,heap) *
+pph_get_common_nodes (void)
+{
+  unsigned i;
+  VEC(tree,heap) *common_nodes = NULL;
+
+  for (i = itk_char; i < itk_none; i++)
+    VEC_safe_push (tree, heap, common_nodes, integer_types[i]);
+
+  for (i = 0; i < TYPE_KIND_LAST; i++)
+    VEC_safe_push (tree, heap, common_nodes, sizetype_tab[i]);
+
+  /* global_trees[] can have NULL entries in it.  Skip them.  */
+  for (i = 0; i < TI_MAX; i++)
+    if (global_trees[i])
+      VEC_safe_push (tree, heap, common_nodes, global_trees[i]);
+
+  /* c_global_trees[] can have NULL entries in it.  Skip them.  */
+  for (i = 0; i < CTI_MAX; i++)
+    if (c_global_trees[i])
+      VEC_safe_push (tree, heap, common_nodes, c_global_trees[i]);
+
+  return common_nodes;
+}
+
+
 /* Initialize all the streamer hooks used for streaming ASTs.  */
 
 static void
@@ -62,6 +92,9 @@ pph_stream_hooks_init (void)
 {
   lto_streamer_hooks *h = streamer_hooks_init ();
   h->name = "C++ AST";
+  h->get_common_nodes = pph_get_common_nodes;
   h->is_streamable = pph_is_streamable;
   h->write_tree = pph_stream_write_tree;
   h->read_tree = pph_stream_read_tree;
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index c26de5d..b578419 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -2198,7 +2198,6 @@ lto_output (cgraph_node_set set, varpool_node_set vset)
   int i, n_nodes;
   lto_cgraph_encoder_t encoder = lto_get_out_decl_state 
()->cgraph_node_encoder;
 
-  gimple_streamer_hooks_init ();
   lto_writer_init ();
 
   n_nodes = lto_cgraph_encoder_size (encoder);
diff --git a/gcc/lto-streamer.c b/gcc/lto-streamer.c
index 04a9f7a..d6b78c8 100644
--- a/gcc/lto-streamer.c
+++ b/gcc/lto-streamer.c
@@ -550,10 +550,6 @@ lto_get_common_nodes (void)
   else
     main_identifier_node = get_identifier ("main");
 
-  /* FIXME pph.  These assertions are never met while in the front end.
-     There should be a way of checking this only when we are in LTO
-     mode.  */
-#if 0
   gcc_assert (ptrdiff_type_node == integer_type_node);
 
   /* FIXME lto.  In the C++ front-end, fileptr_type_node is defined as a
@@ -564,7 +560,6 @@ lto_get_common_nodes (void)
      These should be assured in pass_ipa_free_lang_data.  */
   gcc_assert (fileptr_type_node == ptr_type_node);
   gcc_assert (TYPE_MAIN_VARIANT (fileptr_type_node) == ptr_type_node);
-#endif
 
   seen_nodes = pointer_set_create ();
 
@@ -631,7 +626,7 @@ lto_streamer_cache_create (void)
   /* Load all the well-known tree nodes that are always created by
      the compiler on startup.  This prevents writing them out
      unnecessarily.  */
-  common_nodes = lto_get_common_nodes ();
+  common_nodes = streamer_hooks ()->get_common_nodes ();
 
   FOR_EACH_VEC_ELT (tree, common_nodes, i, node)
     preload_common_node (cache, node);
@@ -820,6 +815,7 @@ gimple_streamer_hooks_init (void)
   h->name = "gimple";
   h->reader_init = gimple_streamer_reader_init;
   h->writer_init = NULL;
+  h->get_common_nodes = lto_get_common_nodes;
   h->is_streamable = lto_is_streamable;
   h->write_tree = gimple_streamer_write_tree;
   h->read_tree = gimple_streamer_read_tree;
diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h
index b6f4b79..8be17da 100644
--- a/gcc/lto-streamer.h
+++ b/gcc/lto-streamer.h
@@ -55,6 +55,16 @@ typedef struct lto_streamer_hooks {
   /* A string identifying this streamer.  */
   const char *name;
 
+  /* Called by lto_streamer_cache_create to instantiate a cache of
+     well-known nodes.  These are tree nodes that are always
+     instantiated by the compiler on startup.  Additionally, these
+     nodes need to be shared.  This function produces a vector of
+     these well known trees that are then added to the streamer cache.
+     This way, the writer will only write out a reference to the tree
+     and the reader will instantiate the tree out of this
+     pre-populated cache.  */
+  VEC(tree,heap) *(*get_common_nodes) (void);
+
   /* Called by lto_reader_init after it does basic initialization.  */
   void (*reader_init) (void);
 

--
This patch is available for review at http://codereview.appspot.com/4478043

Reply via email to