I'm not altogether happy with this approach, so I'm looking for
suggestions on how to address this issue.

The front end defines a bunch of unique constants in c_global_trees
that are not meant to be shared and are subject to pointer comparisons
throughout the front end.  Morevoer, some constants do not even have a
"valid" type.  For instance, void_zero_node has type void, which
build_int_cst_wide refuses to build.  So, we were ICEing when trying
to materialize these functions in the reader.

Other constants are fine, but they are pointer-compared against
c_global_trees[], so I need them to be materialized into the same
address.

Initially, I thought I would just make the streamer treat constants
the same as any other tree node, but this increases the size of the
on-disk representation.  Writing cache references for constants takes
more space.  It was also quite invasive, I was introducing regressions
in LTO and having a perfectly horrible time with it.

The approach I ended up taking is to allow the streamer to declare
that it has some INTEGER_CSTs that need to be unique.  Since those
unique constants are preloaded in the cache, we can simply stream
references to them if we find a match.

So, regular constants are streamed like always, but unique constants
are streamed as cache references.  This does not affect the gimple
streamer and allows the C++ FE to preload these constants in the cache
and continue to use pointer equality throughout the parser.

This was the least invasive and quick solution I could come up for
now.  Any other ideas?

Tested on x86_64.  Committed to pph.


Diego.

cp/ChangeLog.pph

        * pph-streamer.c (pph_stream_hooks_init): Set
        has_unique_integer_csts_p field to true.

ChangeLog.pph

        * lto-streamer-out.c (lto_output_tree): If the streamer
        has unique INTEGER_CST nodes and a match is found in the
        streamer cache, do not call lto_output_integer_cst.
        * lto-streamer.h (struct lto_streamer_hooks): Add field
        has_unique_integer_csts_p.

diff --git a/gcc/cp/pph-streamer.c b/gcc/cp/pph-streamer.c
index efac32e..18a5e25 100644
--- a/gcc/cp/pph-streamer.c
+++ b/gcc/cp/pph-streamer.c
@@ -101,6 +101,7 @@ pph_stream_hooks_init (void)
   h->unpack_value_fields = pph_stream_unpack_value_fields;
   h->alloc_tree = pph_stream_alloc_tree;
   h->output_tree_header = pph_stream_output_tree_header;
+  h->has_unique_integer_csts_p = true;
 }
 
 
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index b578419..a7f0965 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -1387,8 +1387,27 @@ lto_output_tree (struct output_block *ob, tree expr, 
bool ref_p)
      to be materialized by the reader (to implement TYPE_CACHED_VALUES).  */
   if (TREE_CODE (expr) == INTEGER_CST)
     {
-      lto_output_integer_cst (ob, expr, ref_p);
-      return;
+      bool is_special;
+
+     /* There are some constants that are special to the streamer
+       (e.g., void_zero_node, truthvalue_false_node).
+       These constants cannot be rematerialized with
+       build_int_cst_wide because they may actually lack a type (like
+       void_zero_node) and they need to be pointer-identical to trees
+       materialized by the compiler tables like global_trees or
+       c_global_trees.
+
+       If the streamer told us that it has special constants, they
+       will be preloaded in the streamer cache.  If we find a match,
+       then stream the constant as a reference so the reader can
+       re-materialize it from the cache.  */
+      is_special = streamer_hooks ()->has_unique_integer_csts_p
+                  && lto_streamer_cache_lookup (ob->writer_cache, expr, NULL);
+      if (!is_special)
+       {
+         lto_output_integer_cst (ob, expr, ref_p);
+         return;
+       }
     }
 
   existed_p = lto_streamer_cache_insert (ob->writer_cache, expr, &ix);
diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h
index 8be17da..9b64619 100644
--- a/gcc/lto-streamer.h
+++ b/gcc/lto-streamer.h
@@ -113,6 +113,12 @@ typedef struct lto_streamer_hooks {
      global symbol tables.  */
   unsigned register_decls_in_symtab_p : 1;
 
+  /* Non-zero if the streamer has special constants that cannot be
+     shared and are used in pointer-equality tests (e.g., void_zero_node,
+     truthvalue_false_node, etc).  These constants will be present in
+     the streamer cache and should be streamed as references.  */
+  unsigned has_unique_integer_csts_p : 1;
+
   /* Called by lto_materialize_tree for tree nodes that it does not
      know how to allocate memory for.  If defined, this hook should
      return a new tree node of the given code.  The data_in and

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

Reply via email to