diff mbox series

Simplify tree streaming

Message ID 20200526084105.GA48736@kam.mff.cuni.cz
State New
Headers show
Series Simplify tree streaming | expand

Commit Message

Jan Hubicka May 26, 2020, 8:41 a.m. UTC
Hi,
this patch cleans up tree streaming.  The code is prepared to stream nested
trees, but we only handle flat trees. As a result we have quite heavy function
to stream in/out tree reference which is used many times and shows up in
profile.

This patch adds stream_write_tree_ref/stream_read_tree_ref which is used to
stream references to trees that are required to exist in the cache or be
indexable.

The actual implementation is just a first cut.  I would like to make it more
compact. We used to stream 2 byte tag (as UHWI) + UHWI representing the index.
Now we stream one UHWI that represent type of reference + index for references
to cache, but still two integers for references to global stream.  This is
becaue the abstraction is not very helpful here and I want to clean this up
incrementally.

I would also like to get rid of the ref_p parameters which seems unnecessary for
flat streams.

This reduces around 7% of global stream, 3% when compressed.
More reduction will happen once the format is sanitized a bit.

from
[WPA] read 4597161 unshared trees
[WPA] read 2937414 mergeable SCCs of average size 1.364280
[WPA] 8604617 tree bodies read in total
[WPA] tree SCC table: size 524287, 247507 elements, collision ratio: 0.377468
[WPA] tree SCC max chain length 2 (size 1)
[WPA] Compared 2689907 SCCs, 184 collisions (0.000068)
[WPA] Merged 2689890 SCCs
[WPA] Merged 3722677 tree bodies
[WPA] Merged 632040 types
...
[WPA] Compression: 88124141 input bytes, 234906430 uncompressed bytes (ratio: 2.665631)
[WPA] Size of mmap'd section decls: 88124141 bytes
...
[WPA] Compression: 113758813 input bytes, 316149514 uncompressed bytes (ratio: 2.779121)
[WPA] Size of mmap'd section decls: 88124141 bytes
[WPA] Size of mmap'd section function_body: 14485721 bytes

to

[WPA] read 4597174 unshared trees
[WPA] read 2937413 mergeable SCCs of average size 1.364280
[WPA] 8604629 tree bodies read in total
[WPA] tree SCC table: size 524287, 247509 elements, collision ratio: 0.377458
[WPA] tree SCC max chain length 2 (size 1)
[WPA] Compared 2689904 SCCs, 183 collisions (0.000068)
[WPA] Merged 2689888 SCCs
[WPA] Merged 3722675 tree bodies
[WPA] Merged 632041 types
....
[WPA] Size of mmap'd section decls: 86177293 bytes
[WPA] Compression: 86177293 input bytes, 217625095 uncompressed bytes (ratio: 2.525318)
....
[WPA] Compression: 111682269 input bytes, 297228756 uncompressed bytes (ratio: 2.661378)
[WPA] Size of mmap'd section decls: 86177293 bytes
[WPA] Size of mmap'd section function_body: 14349032 bytes

Bootstrapped/regtested x86_64-linux, OK?

gcc/ChangeLog:

2020-05-26  Jan Hubicka  <hubicka@ucw.cz>

	* lto-streamer-in.c (streamer_read_chain): Move here from
	tree-streamer-in.c.
	(stream_read_tree_ref): New.
	(lto_input_tree_1): Simplify.
	* lto-streamer-out.c (stream_write_tree_ref): New.
	(lto_write_tree_1): Simplify.
	(lto_output_tree_1): Simplify.
	(DFS::DFS_write_tree): Simplify.
	(streamer_write_chain): Move here from tree-stremaer-out.c.
	* lto-streamer.h (lto_output_tree_ref): Update prototype.
	(stream_read_tree_ref): Declare
	(stream_write_tree_ref): Declare
	* tree-streamer-in.c (streamer_read_chain): Update to use
	stream_read_tree_ref.
	(lto_input_ts_common_tree_pointers): Likewise.
	(lto_input_ts_vector_tree_pointers): Likewise.
	(lto_input_ts_poly_tree_pointers): Likewise.
	(lto_input_ts_complex_tree_pointers): Likewise.
	(lto_input_ts_decl_minimal_tree_pointers): Likewise.
	(lto_input_ts_decl_common_tree_pointers): Likewise.
	(lto_input_ts_decl_with_vis_tree_pointers): Likewise.
	(lto_input_ts_field_decl_tree_pointers): Likewise.
	(lto_input_ts_function_decl_tree_pointers): Likewise.
	(lto_input_ts_type_common_tree_pointers): Likewise.
	(lto_input_ts_type_non_common_tree_pointers): Likewise.
	(lto_input_ts_list_tree_pointers): Likewise.
	(lto_input_ts_vec_tree_pointers): Likewise.
	(lto_input_ts_exp_tree_pointers): Likewise.
	(lto_input_ts_block_tree_pointers): Likewise.
	(lto_input_ts_binfo_tree_pointers): Likewise.
	(lto_input_ts_constructor_tree_pointers): Likewise.
	(lto_input_ts_omp_clause_tree_pointers): Likewise.
	* tree-streamer-out.c (streamer_write_chain): Update to use
	stream_write_tree_ref.
	(write_ts_common_tree_pointers): Likewise.
	(write_ts_vector_tree_pointers): Likewise.
	(write_ts_poly_tree_pointers): Likewise.
	(write_ts_complex_tree_pointers): Likewise.
	(write_ts_decl_minimal_tree_pointers): Likewise.
	(write_ts_decl_common_tree_pointers): Likewise.
	(write_ts_decl_non_common_tree_pointers): Likewise.
	(write_ts_decl_with_vis_tree_pointers): Likewise.
	(write_ts_field_decl_tree_pointers): Likewise.
	(write_ts_function_decl_tree_pointers): Likewise.
	(write_ts_type_common_tree_pointers): Likewise.
	(write_ts_type_non_common_tree_pointers): Likewise.
	(write_ts_list_tree_pointers): Likewise.
	(write_ts_vec_tree_pointers): Likewise.
	(write_ts_exp_tree_pointers): Likewise.
	(write_ts_block_tree_pointers): Likewise.
	(write_ts_binfo_tree_pointers): Likewise.
	(write_ts_constructor_tree_pointers): Likewise.
	(write_ts_omp_clause_tree_pointers): Likewise.
	(streamer_write_tree_body): Likewise.
	(streamer_write_integer_cst): Likewise.
	* tree-streamer.h (streamer_read_chain):Declare.
	(streamer_write_chain):Declare.
	(streamer_write_tree_body): Update prototype.
	(streamer_write_integer_cst): Update prototype.

Comments

Richard Biener May 29, 2020, 10:51 a.m. UTC | #1
On Tue, May 26, 2020 at 10:44 AM Jan Hubicka <hubicka@ucw.cz> wrote:
>
> Hi,
> this patch cleans up tree streaming.  The code is prepared to stream nested
> trees, but we only handle flat trees. As a result we have quite heavy function
> to stream in/out tree reference which is used many times and shows up in
> profile.
>
> This patch adds stream_write_tree_ref/stream_read_tree_ref which is used to
> stream references to trees that are required to exist in the cache or be
> indexable.
>
> The actual implementation is just a first cut.  I would like to make it more
> compact. We used to stream 2 byte tag (as UHWI) + UHWI representing the index.
> Now we stream one UHWI that represent type of reference + index for references
> to cache, but still two integers for references to global stream.  This is
> becaue the abstraction is not very helpful here and I want to clean this up
> incrementally.
>
> I would also like to get rid of the ref_p parameters which seems unnecessary for
> flat streams.
>
> This reduces around 7% of global stream, 3% when compressed.
> More reduction will happen once the format is sanitized a bit.
>
> from
> [WPA] read 4597161 unshared trees
> [WPA] read 2937414 mergeable SCCs of average size 1.364280
> [WPA] 8604617 tree bodies read in total
> [WPA] tree SCC table: size 524287, 247507 elements, collision ratio: 0.377468
> [WPA] tree SCC max chain length 2 (size 1)
> [WPA] Compared 2689907 SCCs, 184 collisions (0.000068)
> [WPA] Merged 2689890 SCCs
> [WPA] Merged 3722677 tree bodies
> [WPA] Merged 632040 types
> ...
> [WPA] Compression: 88124141 input bytes, 234906430 uncompressed bytes (ratio: 2.665631)
> [WPA] Size of mmap'd section decls: 88124141 bytes
> ...
> [WPA] Compression: 113758813 input bytes, 316149514 uncompressed bytes (ratio: 2.779121)
> [WPA] Size of mmap'd section decls: 88124141 bytes
> [WPA] Size of mmap'd section function_body: 14485721 bytes
>
> to
>
> [WPA] read 4597174 unshared trees
> [WPA] read 2937413 mergeable SCCs of average size 1.364280
> [WPA] 8604629 tree bodies read in total
> [WPA] tree SCC table: size 524287, 247509 elements, collision ratio: 0.377458
> [WPA] tree SCC max chain length 2 (size 1)
> [WPA] Compared 2689904 SCCs, 183 collisions (0.000068)
> [WPA] Merged 2689888 SCCs
> [WPA] Merged 3722675 tree bodies
> [WPA] Merged 632041 types
> ....
> [WPA] Size of mmap'd section decls: 86177293 bytes
> [WPA] Compression: 86177293 input bytes, 217625095 uncompressed bytes (ratio: 2.525318)
> ....
> [WPA] Compression: 111682269 input bytes, 297228756 uncompressed bytes (ratio: 2.661378)
> [WPA] Size of mmap'd section decls: 86177293 bytes
> [WPA] Size of mmap'd section function_body: 14349032 bytes
>
> Bootstrapped/regtested x86_64-linux, OK?
>
> gcc/ChangeLog:
>
> 2020-05-26  Jan Hubicka  <hubicka@ucw.cz>
>
>         * lto-streamer-in.c (streamer_read_chain): Move here from
>         tree-streamer-in.c.
>         (stream_read_tree_ref): New.
>         (lto_input_tree_1): Simplify.
>         * lto-streamer-out.c (stream_write_tree_ref): New.
>         (lto_write_tree_1): Simplify.
>         (lto_output_tree_1): Simplify.
>         (DFS::DFS_write_tree): Simplify.
>         (streamer_write_chain): Move here from tree-stremaer-out.c.
>         * lto-streamer.h (lto_output_tree_ref): Update prototype.
>         (stream_read_tree_ref): Declare
>         (stream_write_tree_ref): Declare
>         * tree-streamer-in.c (streamer_read_chain): Update to use
>         stream_read_tree_ref.
>         (lto_input_ts_common_tree_pointers): Likewise.
>         (lto_input_ts_vector_tree_pointers): Likewise.
>         (lto_input_ts_poly_tree_pointers): Likewise.
>         (lto_input_ts_complex_tree_pointers): Likewise.
>         (lto_input_ts_decl_minimal_tree_pointers): Likewise.
>         (lto_input_ts_decl_common_tree_pointers): Likewise.
>         (lto_input_ts_decl_with_vis_tree_pointers): Likewise.
>         (lto_input_ts_field_decl_tree_pointers): Likewise.
>         (lto_input_ts_function_decl_tree_pointers): Likewise.
>         (lto_input_ts_type_common_tree_pointers): Likewise.
>         (lto_input_ts_type_non_common_tree_pointers): Likewise.
>         (lto_input_ts_list_tree_pointers): Likewise.
>         (lto_input_ts_vec_tree_pointers): Likewise.
>         (lto_input_ts_exp_tree_pointers): Likewise.
>         (lto_input_ts_block_tree_pointers): Likewise.
>         (lto_input_ts_binfo_tree_pointers): Likewise.
>         (lto_input_ts_constructor_tree_pointers): Likewise.
>         (lto_input_ts_omp_clause_tree_pointers): Likewise.
>         * tree-streamer-out.c (streamer_write_chain): Update to use
>         stream_write_tree_ref.
>         (write_ts_common_tree_pointers): Likewise.
>         (write_ts_vector_tree_pointers): Likewise.
>         (write_ts_poly_tree_pointers): Likewise.
>         (write_ts_complex_tree_pointers): Likewise.
>         (write_ts_decl_minimal_tree_pointers): Likewise.
>         (write_ts_decl_common_tree_pointers): Likewise.
>         (write_ts_decl_non_common_tree_pointers): Likewise.
>         (write_ts_decl_with_vis_tree_pointers): Likewise.
>         (write_ts_field_decl_tree_pointers): Likewise.
>         (write_ts_function_decl_tree_pointers): Likewise.
>         (write_ts_type_common_tree_pointers): Likewise.
>         (write_ts_type_non_common_tree_pointers): Likewise.
>         (write_ts_list_tree_pointers): Likewise.
>         (write_ts_vec_tree_pointers): Likewise.
>         (write_ts_exp_tree_pointers): Likewise.
>         (write_ts_block_tree_pointers): Likewise.
>         (write_ts_binfo_tree_pointers): Likewise.
>         (write_ts_constructor_tree_pointers): Likewise.
>         (write_ts_omp_clause_tree_pointers): Likewise.
>         (streamer_write_tree_body): Likewise.
>         (streamer_write_integer_cst): Likewise.
>         * tree-streamer.h (streamer_read_chain):Declare.
>         (streamer_write_chain):Declare.
>         (streamer_write_tree_body): Update prototype.
>         (streamer_write_integer_cst): Update prototype.
>
> diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c
> index d0532c5ac51..c80574be207 100644
> --- a/gcc/lto-streamer-in.c
> +++ b/gcc/lto-streamer-in.c
> @@ -1021,6 +1021,30 @@ input_struct_function_base (struct function *fn, class data_in *data_in,
>      }
>  }
>
> +/* Read a chain of tree nodes from input block IB.  DATA_IN contains
> +   tables and descriptors for the file being read.  */
> +
> +static tree
> +streamer_read_chain (class lto_input_block *ib, class data_in *data_in)
> +{
> +  tree first, prev, curr;
> +
> +  /* The chain is written as NULL terminated list of trees.  */
> +  first = prev = NULL_TREE;
> +  do
> +    {
> +      curr = stream_read_tree (ib, data_in);
> +      if (prev)
> +       TREE_CHAIN (prev) = curr;
> +      else
> +       first = curr;
> +
> +      prev = curr;
> +    }
> +  while (curr);
> +
> +  return first;
> +}
>
>  /* Read the body of function FN_DECL from DATA_IN using input block IB.  */
>
> @@ -1481,6 +1505,25 @@ lto_input_scc (class lto_input_block *ib, class data_in *data_in,
>    return scc_hash;
>  }
>
> +tree
> +stream_read_tree_ref (lto_input_block *ib, data_in *data_in)

Function comment missing.

> +{
> +  unsigned ix = streamer_read_uhwi (ib);
> +  tree ret;
> +  if (!ix)
> +    return NULL_TREE;
> +  else if (ix < LTO_NUM_TAGS)
> +    ret = lto_input_tree_ref (ib, data_in, cfun, (LTO_tags)ix);
> +  else
> +    ret = streamer_tree_cache_get_tree (data_in->reader_cache,
> +                                       ix - LTO_NUM_TAGS);
> +  if (ret && streamer_debugging)
> +    {
> +      enum tree_code c = (enum tree_code)streamer_read_uhwi (ib);
> +      gcc_assert (c == TREE_CODE (ret));
> +    }
> +  return ret;
> +}
>
>  /* Read a tree from input block IB using the per-file context in
>     DATA_IN.  This context is used, for example, to resolve references
> @@ -1513,7 +1556,7 @@ lto_input_tree_1 (class lto_input_block *ib, class data_in *data_in,
>      {
>        /* For shared integer constants in singletons we can use the
>           existing tree integer constant merging code.  */
> -      tree type = stream_read_tree (ib, data_in);
> +      tree type = stream_read_tree_ref (ib, data_in);
>        unsigned HOST_WIDE_INT len = streamer_read_uhwi (ib);
>        unsigned HOST_WIDE_INT i;
>        HOST_WIDE_INT a[WIDE_INT_MAX_ELTS];
> diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
> index 288e3c0f4c6..522986278a7 100644
> --- a/gcc/lto-streamer-out.c
> +++ b/gcc/lto-streamer-out.c
> @@ -228,7 +228,7 @@ lto_output_location (struct output_block *ob, struct bitpack_d *bp,
>     output block OB.  Otherwise, output the physical representation of
>     EXPR to OB.  */
>
> -static void
> +void
>  lto_output_tree_ref (struct output_block *ob, tree expr)
>  {
>    enum tree_code code;
> @@ -409,6 +409,29 @@ get_symbol_initial_value (lto_symtab_encoder_t encoder, tree expr)
>  }
>
>
> +/* Output reference to tree T to the stream.
> +   Assume that T is already in encoder cache.  */
> +
> +void
> +stream_write_tree_ref (struct output_block *ob, tree t)
> +{
> +  if (!t)
> +    streamer_write_zero (ob);
> +  else
> +    {
> +      unsigned int ix;
> +      bool existed_p = streamer_tree_cache_lookup (ob->writer_cache, t, &ix);
> +      if (existed_p)
> +       streamer_write_uhwi (ob, ix + LTO_NUM_TAGS);
> +      else
> +       lto_output_tree_ref (ob, t);

The comment of the function says we assume it is already in cache
but here we actually handle the case it is not?  So I guess an assert
that the tree is indexable is in order here.

Otherwise looks OK.

Thanks,
Richard.

> +      if (streamer_debugging)
> +      streamer_write_uhwi (ob, TREE_CODE (t));
> +    }
> +}
> +
> +
> +
>  /* Write a physical representation of tree node EXPR to output block
>     OB.  If REF_P is true, the leaves of EXPR are emitted as references
>     via lto_output_tree_ref.  IX is the index into the streamer cache
> @@ -430,7 +453,7 @@ lto_write_tree_1 (struct output_block *ob, tree expr, bool ref_p)
>    streamer_write_tree_bitfields (ob, expr);
>
>    /* Write all the pointer fields in EXPR.  */
> -  streamer_write_tree_body (ob, expr, ref_p);
> +  streamer_write_tree_body (ob, expr);
>
>    /* Write any LTO-specific data to OB.  */
>    if (DECL_P (expr)
> @@ -505,7 +528,7 @@ lto_output_tree_1 (struct output_block *ob, tree expr, hashval_t hash,
>        /* Shared INTEGER_CST nodes are special because they need their
>          original type to be materialized by the reader (to implement
>          TYPE_CACHED_VALUES).  */
> -      streamer_write_integer_cst (ob, expr, ref_p);
> +      streamer_write_integer_cst (ob, expr);
>      }
>    else
>      {
> @@ -1685,7 +1708,7 @@ DFS::DFS_write_tree (struct output_block *ob, sccs *from_state,
>    /* Check if we already streamed EXPR.  */
>    if (streamer_tree_cache_lookup (ob->writer_cache, expr, NULL))
>      {
> -      /* Refernece to a local tree makes entry also local.  We always process
> +      /* Reference to a local tree makes entry also local.  We always process
>          top of stack entry, so set max to number of entries in stack - 1.  */
>        if (ob->local_trees
>           && ob->local_trees->contains (expr))
> @@ -2271,6 +2294,29 @@ lto_prepare_function_for_streaming (struct cgraph_node *node)
>
>  }
>
> +/* Emit the chain of tree nodes starting at T.  OB is the output block
> +   to write to.  REF_P is true if chain elements should be emitted
> +   as references.  */
> +
> +static void
> +streamer_write_chain (struct output_block *ob, tree t, bool ref_p)
> +{
> +  while (t)
> +    {
> +      /* We avoid outputting external vars or functions by reference
> +        to the global decls section as we do not want to have them
> +        enter decl merging.  We should not need to do this anymore because
> +        free_lang_data removes them from block scopes.  */
> +      gcc_assert (!VAR_OR_FUNCTION_DECL_P (t) || !DECL_EXTERNAL (t));
> +      stream_write_tree (ob, t, ref_p);
> +
> +      t = TREE_CHAIN (t);
> +    }
> +
> +  /* Write a sentinel to terminate the chain.  */
> +  stream_write_tree (ob, NULL_TREE, ref_p);
> +}
> +
>  /* Output the body of function NODE->DECL.  */
>
>  static void
> diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h
> index 93da3c66fd8..3470aa4cc95 100644
> --- a/gcc/lto-streamer.h
> +++ b/gcc/lto-streamer.h
> @@ -882,6 +882,7 @@ extern void lto_streamer_init (void);
>  extern bool gate_lto_out (void);
>  extern void lto_check_version (int, int, const char *);
>  extern void lto_streamer_hooks_init (void);
> +extern void lto_output_tree_ref (struct output_block *, tree);
>
>  /* In lto-streamer-in.c */
>  extern void lto_input_cgraph (struct lto_file_decl_data *, const char *);
> @@ -914,6 +915,7 @@ hashval_t lto_input_scc (class lto_input_block *, class data_in *,
>  tree lto_input_tree_1 (class lto_input_block *, class data_in *,
>                        enum LTO_tags, hashval_t hash);
>  tree lto_input_tree (class lto_input_block *, class data_in *);
> +tree stream_read_tree_ref (class lto_input_block *, class data_in *);
>
>
>  /* In lto-streamer-out.c  */
> @@ -921,6 +923,7 @@ extern void lto_register_decl_definition (tree, struct lto_file_decl_data *);
>  extern struct output_block *create_output_block (enum lto_section_type);
>  extern void destroy_output_block (struct output_block *);
>  extern void lto_output_tree (struct output_block *, tree, bool, bool);
> +extern void stream_write_tree_ref (struct output_block *, tree);
>  extern void lto_output_toplevel_asms (void);
>  extern void produce_asm (struct output_block *ob, tree fn);
>  extern void lto_output ();
> diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c
> index d2e45e33554..447a3110e82 100644
> --- a/gcc/tree-streamer-in.c
> +++ b/gcc/tree-streamer-in.c
> @@ -69,10 +69,10 @@ input_identifier (class data_in *data_in, class lto_input_block *ib)
>  }
>
>
> -/* Read a chain of tree nodes from input block IB. DATA_IN contains
> +/* Read a chain of tree nodes from input block IB.  DATA_IN contains
>     tables and descriptors for the file being read.  */
>
> -tree
> +static tree
>  streamer_read_chain (class lto_input_block *ib, class data_in *data_in)
>  {
>    tree first, prev, curr;
> @@ -81,7 +81,7 @@ streamer_read_chain (class lto_input_block *ib, class data_in *data_in)
>    first = prev = NULL_TREE;
>    do
>      {
> -      curr = stream_read_tree (ib, data_in);
> +      curr = stream_read_tree_ref (ib, data_in);
>        if (prev)
>         TREE_CHAIN (prev) = curr;
>        else
> @@ -651,7 +651,7 @@ lto_input_ts_common_tree_pointers (class lto_input_block *ib,
>                                    class data_in *data_in, tree expr)
>  {
>    if (TREE_CODE (expr) != IDENTIFIER_NODE)
> -    TREE_TYPE (expr) = stream_read_tree (ib, data_in);
> +    TREE_TYPE (expr) = stream_read_tree_ref (ib, data_in);
>  }
>
>
> @@ -665,7 +665,7 @@ lto_input_ts_vector_tree_pointers (class lto_input_block *ib,
>  {
>    unsigned int count = vector_cst_encoded_nelts (expr);
>    for (unsigned int i = 0; i < count; ++i)
> -    VECTOR_CST_ENCODED_ELT (expr, i) = stream_read_tree (ib, data_in);
> +    VECTOR_CST_ENCODED_ELT (expr, i) = stream_read_tree_ref (ib, data_in);
>  }
>
>
> @@ -678,7 +678,7 @@ lto_input_ts_poly_tree_pointers (class lto_input_block *ib,
>                                  class data_in *data_in, tree expr)
>  {
>    for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
> -    POLY_INT_CST_COEFF (expr, i) = stream_read_tree (ib, data_in);
> +    POLY_INT_CST_COEFF (expr, i) = stream_read_tree_ref (ib, data_in);
>  }
>
>
> @@ -690,8 +690,8 @@ static void
>  lto_input_ts_complex_tree_pointers (class lto_input_block *ib,
>                                     class data_in *data_in, tree expr)
>  {
> -  TREE_REALPART (expr) = stream_read_tree (ib, data_in);
> -  TREE_IMAGPART (expr) = stream_read_tree (ib, data_in);
> +  TREE_REALPART (expr) = stream_read_tree_ref (ib, data_in);
> +  TREE_IMAGPART (expr) = stream_read_tree_ref (ib, data_in);
>  }
>
>
> @@ -703,8 +703,8 @@ static void
>  lto_input_ts_decl_minimal_tree_pointers (class lto_input_block *ib,
>                                          class data_in *data_in, tree expr)
>  {
> -  DECL_NAME (expr) = stream_read_tree (ib, data_in);
> -  DECL_CONTEXT (expr) = stream_read_tree (ib, data_in);
> +  DECL_NAME (expr) = stream_read_tree_ref (ib, data_in);
> +  DECL_CONTEXT (expr) = stream_read_tree_ref (ib, data_in);
>  }
>
>
> @@ -716,19 +716,19 @@ static void
>  lto_input_ts_decl_common_tree_pointers (class lto_input_block *ib,
>                                         class data_in *data_in, tree expr)
>  {
> -  DECL_SIZE (expr) = stream_read_tree (ib, data_in);
> -  DECL_SIZE_UNIT (expr) = stream_read_tree (ib, data_in);
> -  DECL_ATTRIBUTES (expr) = stream_read_tree (ib, data_in);
> -  DECL_ABSTRACT_ORIGIN (expr) = stream_read_tree (ib, data_in);
> +  DECL_SIZE (expr) = stream_read_tree_ref (ib, data_in);
> +  DECL_SIZE_UNIT (expr) = stream_read_tree_ref (ib, data_in);
> +  DECL_ATTRIBUTES (expr) = stream_read_tree_ref (ib, data_in);
> +  DECL_ABSTRACT_ORIGIN (expr) = stream_read_tree_ref (ib, data_in);
>
>    if ((VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
>        && DECL_HAS_VALUE_EXPR_P (expr))
> -    SET_DECL_VALUE_EXPR (expr, stream_read_tree (ib, data_in));
> +    SET_DECL_VALUE_EXPR (expr, stream_read_tree_ref (ib, data_in));
>
>    if (VAR_P (expr)
>        && DECL_HAS_DEBUG_EXPR_P (expr))
>      {
> -      tree dexpr = stream_read_tree (ib, data_in);
> +      tree dexpr = stream_read_tree_ref (ib, data_in);
>        if (dexpr)
>         SET_DECL_DEBUG_EXPR (expr, dexpr);
>      }
> @@ -756,7 +756,7 @@ lto_input_ts_decl_with_vis_tree_pointers (class lto_input_block *ib,
>  {
>    tree id;
>
> -  id = stream_read_tree (ib, data_in);
> +  id = stream_read_tree_ref (ib, data_in);
>    if (id)
>      {
>        gcc_assert (TREE_CODE (id) == IDENTIFIER_NODE);
> @@ -773,10 +773,10 @@ static void
>  lto_input_ts_field_decl_tree_pointers (class lto_input_block *ib,
>                                        class data_in *data_in, tree expr)
>  {
> -  DECL_FIELD_OFFSET (expr) = stream_read_tree (ib, data_in);
> -  DECL_BIT_FIELD_TYPE (expr) = stream_read_tree (ib, data_in);
> -  DECL_BIT_FIELD_REPRESENTATIVE (expr) = stream_read_tree (ib, data_in);
> -  DECL_FIELD_BIT_OFFSET (expr) = stream_read_tree (ib, data_in);
> +  DECL_FIELD_OFFSET (expr) = stream_read_tree_ref (ib, data_in);
> +  DECL_BIT_FIELD_TYPE (expr) = stream_read_tree_ref (ib, data_in);
> +  DECL_BIT_FIELD_REPRESENTATIVE (expr) = stream_read_tree_ref (ib, data_in);
> +  DECL_FIELD_BIT_OFFSET (expr) = stream_read_tree_ref (ib, data_in);
>  }
>
>
> @@ -789,11 +789,12 @@ lto_input_ts_function_decl_tree_pointers (class lto_input_block *ib,
>                                           class data_in *data_in, tree expr)
>  {
>    /* DECL_STRUCT_FUNCTION is loaded on demand by cgraph_get_body.  */
> -  DECL_FUNCTION_PERSONALITY (expr) = stream_read_tree (ib, data_in);
> +  DECL_FUNCTION_PERSONALITY (expr) = stream_read_tree_ref (ib, data_in);
>  #ifndef ACCEL_COMPILER
> -  DECL_FUNCTION_SPECIFIC_TARGET (expr) = stream_read_tree (ib, data_in);
> +  DECL_FUNCTION_SPECIFIC_TARGET (expr) = stream_read_tree_ref (ib, data_in);
>  #endif
> -  DECL_FUNCTION_SPECIFIC_OPTIMIZATION (expr) = stream_read_tree (ib, data_in);
> +  DECL_FUNCTION_SPECIFIC_OPTIMIZATION (expr)
> +    = stream_read_tree_ref (ib, data_in);
>  #ifdef ACCEL_COMPILER
>    {
>      tree opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (expr);
> @@ -819,16 +820,16 @@ static void
>  lto_input_ts_type_common_tree_pointers (class lto_input_block *ib,
>                                         class data_in *data_in, tree expr)
>  {
> -  TYPE_SIZE (expr) = stream_read_tree (ib, data_in);
> -  TYPE_SIZE_UNIT (expr) = stream_read_tree (ib, data_in);
> -  TYPE_ATTRIBUTES (expr) = stream_read_tree (ib, data_in);
> -  TYPE_NAME (expr) = stream_read_tree (ib, data_in);
> +  TYPE_SIZE (expr) = stream_read_tree_ref (ib, data_in);
> +  TYPE_SIZE_UNIT (expr) = stream_read_tree_ref (ib, data_in);
> +  TYPE_ATTRIBUTES (expr) = stream_read_tree_ref (ib, data_in);
> +  TYPE_NAME (expr) = stream_read_tree_ref (ib, data_in);
>    /* Do not stream TYPE_POINTER_TO or TYPE_REFERENCE_TO.  They will be
>       reconstructed during fixup.  */
>    /* Do not stream TYPE_NEXT_VARIANT, we reconstruct the variant lists
>       during fixup.  */
> -  TYPE_MAIN_VARIANT (expr) = stream_read_tree (ib, data_in);
> -  TYPE_CONTEXT (expr) = stream_read_tree (ib, data_in);
> +  TYPE_MAIN_VARIANT (expr) = stream_read_tree_ref (ib, data_in);
> +  TYPE_CONTEXT (expr) = stream_read_tree_ref (ib, data_in);
>    /* TYPE_CANONICAL gets re-computed during type merging.  */
>    TYPE_CANONICAL (expr) = NULL_TREE;
>  }
> @@ -843,18 +844,18 @@ lto_input_ts_type_non_common_tree_pointers (class lto_input_block *ib,
>                                             tree expr)
>  {
>    if (TREE_CODE (expr) == ENUMERAL_TYPE)
> -    TYPE_VALUES (expr) = stream_read_tree (ib, data_in);
> +    TYPE_VALUES (expr) = stream_read_tree_ref (ib, data_in);
>    else if (TREE_CODE (expr) == ARRAY_TYPE)
> -    TYPE_DOMAIN (expr) = stream_read_tree (ib, data_in);
> +    TYPE_DOMAIN (expr) = stream_read_tree_ref (ib, data_in);
>    else if (RECORD_OR_UNION_TYPE_P (expr))
>      TYPE_FIELDS (expr) = streamer_read_chain (ib, data_in);
>    else if (TREE_CODE (expr) == FUNCTION_TYPE
>            || TREE_CODE (expr) == METHOD_TYPE)
> -    TYPE_ARG_TYPES (expr) = stream_read_tree (ib, data_in);
> +    TYPE_ARG_TYPES (expr) = stream_read_tree_ref (ib, data_in);
>
>    if (!POINTER_TYPE_P (expr))
> -    TYPE_MIN_VALUE_RAW (expr) = stream_read_tree (ib, data_in);
> -  TYPE_MAX_VALUE_RAW (expr) = stream_read_tree (ib, data_in);
> +    TYPE_MIN_VALUE_RAW (expr) = stream_read_tree_ref (ib, data_in);
> +  TYPE_MAX_VALUE_RAW (expr) = stream_read_tree_ref (ib, data_in);
>  }
>
>
> @@ -866,9 +867,9 @@ static void
>  lto_input_ts_list_tree_pointers (class lto_input_block *ib,
>                                  class data_in *data_in, tree expr)
>  {
> -  TREE_PURPOSE (expr) = stream_read_tree (ib, data_in);
> -  TREE_VALUE (expr) = stream_read_tree (ib, data_in);
> -  TREE_CHAIN (expr) = stream_read_tree (ib, data_in);
> +  TREE_PURPOSE (expr) = stream_read_tree_ref (ib, data_in);
> +  TREE_VALUE (expr) = stream_read_tree_ref (ib, data_in);
> +  TREE_CHAIN (expr) = stream_read_tree_ref (ib, data_in);
>  }
>
>
> @@ -885,7 +886,7 @@ lto_input_ts_vec_tree_pointers (class lto_input_block *ib,
>    /* Note that TREE_VEC_LENGTH was read by streamer_alloc_tree to
>       instantiate EXPR.  */
>    for (i = 0; i < TREE_VEC_LENGTH (expr); i++)
> -    TREE_VEC_ELT (expr, i) = stream_read_tree (ib, data_in);
> +    TREE_VEC_ELT (expr, i) = stream_read_tree_ref (ib, data_in);
>  }
>
>
> @@ -902,9 +903,9 @@ lto_input_ts_exp_tree_pointers (class lto_input_block *ib,
>    tree block;
>
>    for (i = 0; i < TREE_OPERAND_LENGTH (expr); i++)
> -    TREE_OPERAND (expr, i) = stream_read_tree (ib, data_in);
> +    TREE_OPERAND (expr, i) = stream_read_tree_ref (ib, data_in);
>
> -  block = stream_read_tree (ib, data_in);
> +  block = stream_read_tree_ref (ib, data_in);
>
>    /* TODO: Block is stored in the locus information.  It may make more sense to
>       to make it go via the location cache.  */
> @@ -926,8 +927,8 @@ lto_input_ts_block_tree_pointers (class lto_input_block *ib,
>  {
>    BLOCK_VARS (expr) = streamer_read_chain (ib, data_in);
>
> -  BLOCK_SUPERCONTEXT (expr) = stream_read_tree (ib, data_in);
> -  BLOCK_ABSTRACT_ORIGIN (expr) = stream_read_tree (ib, data_in);
> +  BLOCK_SUPERCONTEXT (expr) = stream_read_tree_ref (ib, data_in);
> +  BLOCK_ABSTRACT_ORIGIN (expr) = stream_read_tree_ref (ib, data_in);
>    /* We may end up prevailing a decl with DECL_ORIGIN (t) != t here
>       which breaks the invariant that BLOCK_ABSTRACT_ORIGIN is the
>       ultimate origin.  Fixup here.
> @@ -979,14 +980,14 @@ lto_input_ts_binfo_tree_pointers (class lto_input_block *ib,
>       list on the writer side.  */
>    do
>      {
> -      t = stream_read_tree (ib, data_in);
> +      t = stream_read_tree_ref (ib, data_in);
>        if (t)
>         BINFO_BASE_BINFOS (expr)->quick_push (t);
>      }
>    while (t);
>
> -  BINFO_OFFSET (expr) = stream_read_tree (ib, data_in);
> -  BINFO_VTABLE (expr) = stream_read_tree (ib, data_in);
> +  BINFO_OFFSET (expr) = stream_read_tree_ref (ib, data_in);
> +  BINFO_VTABLE (expr) = stream_read_tree_ref (ib, data_in);
>
>    /* Do not walk BINFO_INHERITANCE_CHAIN, BINFO_SUBVTT_INDEX,
>       BINFO_BASE_ACCESSES and BINFO_VPTR_INDEX; these are used by C++ FE
> @@ -1007,8 +1008,8 @@ lto_input_ts_constructor_tree_pointers (class lto_input_block *ib,
>    for (i = 0; i < CONSTRUCTOR_NELTS (expr); i++)
>      {
>        constructor_elt e;
> -      e.index = stream_read_tree (ib, data_in);
> -      e.value = stream_read_tree (ib, data_in);
> +      e.index = stream_read_tree_ref (ib, data_in);
> +      e.value = stream_read_tree_ref (ib, data_in);
>        (*CONSTRUCTOR_ELTS (expr))[i] = e;
>      }
>  }
> @@ -1025,8 +1026,8 @@ lto_input_ts_omp_clause_tree_pointers (class lto_input_block *ib,
>    int i;
>
>    for (i = 0; i < omp_clause_num_ops[OMP_CLAUSE_CODE (expr)]; i++)
> -    OMP_CLAUSE_OPERAND (expr, i) = stream_read_tree (ib, data_in);
> -  OMP_CLAUSE_CHAIN (expr) = stream_read_tree (ib, data_in);
> +    OMP_CLAUSE_OPERAND (expr, i) = stream_read_tree_ref (ib, data_in);
> +  OMP_CLAUSE_CHAIN (expr) = stream_read_tree_ref (ib, data_in);
>  }
>
>
> diff --git a/gcc/tree-streamer-out.c b/gcc/tree-streamer-out.c
> index 94635c4a8ae..98631789cc3 100644
> --- a/gcc/tree-streamer-out.c
> +++ b/gcc/tree-streamer-out.c
> @@ -510,8 +510,8 @@ streamer_write_tree_bitfields (struct output_block *ob, tree expr)
>     to write to.  REF_P is true if chain elements should be emitted
>     as references.  */
>
> -void
> -streamer_write_chain (struct output_block *ob, tree t, bool ref_p)
> +static void
> +streamer_write_chain (struct output_block *ob, tree t)
>  {
>    while (t)
>      {
> @@ -520,13 +520,13 @@ streamer_write_chain (struct output_block *ob, tree t, bool ref_p)
>          enter decl merging.  We should not need to do this anymore because
>          free_lang_data removes them from block scopes.  */
>        gcc_assert (!VAR_OR_FUNCTION_DECL_P (t) || !DECL_EXTERNAL (t));
> -      stream_write_tree (ob, t, ref_p);
> +      stream_write_tree_ref (ob, t);
>
>        t = TREE_CHAIN (t);
>      }
>
>    /* Write a sentinel to terminate the chain.  */
> -  stream_write_tree (ob, NULL_TREE, ref_p);
> +  stream_write_tree_ref (ob, NULL_TREE);
>  }
>
>
> @@ -535,10 +535,10 @@ streamer_write_chain (struct output_block *ob, tree t, bool ref_p)
>     fields.  */
>
>  static void
> -write_ts_common_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
> +write_ts_common_tree_pointers (struct output_block *ob, tree expr)
>  {
>    if (TREE_CODE (expr) != IDENTIFIER_NODE)
> -    stream_write_tree (ob, TREE_TYPE (expr), ref_p);
> +    stream_write_tree_ref (ob, TREE_TYPE (expr));
>  }
>
>
> @@ -547,13 +547,13 @@ write_ts_common_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
>     fields.  */
>
>  static void
> -write_ts_vector_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
> +write_ts_vector_tree_pointers (struct output_block *ob, tree expr)
>  {
>    /* Note that the number of elements for EXPR has already been emitted
>       in EXPR's header (see streamer_write_tree_header).  */
>    unsigned int count = vector_cst_encoded_nelts (expr);
>    for (unsigned int i = 0; i < count; ++i)
> -    stream_write_tree (ob, VECTOR_CST_ENCODED_ELT (expr, i), ref_p);
> +    stream_write_tree_ref (ob, VECTOR_CST_ENCODED_ELT (expr, i));
>  }
>
>
> @@ -562,10 +562,10 @@ write_ts_vector_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
>     fields.  */
>
>  static void
> -write_ts_poly_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
> +write_ts_poly_tree_pointers (struct output_block *ob, tree expr)
>  {
>    for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
> -    stream_write_tree (ob, POLY_INT_CST_COEFF (expr, i), ref_p);
> +    stream_write_tree_ref (ob, POLY_INT_CST_COEFF (expr, i));
>  }
>
>
> @@ -574,10 +574,10 @@ write_ts_poly_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
>     fields.  */
>
>  static void
> -write_ts_complex_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
> +write_ts_complex_tree_pointers (struct output_block *ob, tree expr)
>  {
> -  stream_write_tree (ob, TREE_REALPART (expr), ref_p);
> -  stream_write_tree (ob, TREE_IMAGPART (expr), ref_p);
> +  stream_write_tree_ref (ob, TREE_REALPART (expr));
> +  stream_write_tree_ref (ob, TREE_IMAGPART (expr));
>  }
>
>
> @@ -586,21 +586,20 @@ write_ts_complex_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
>     pointer fields.  */
>
>  static void
> -write_ts_decl_minimal_tree_pointers (struct output_block *ob, tree expr,
> -                                    bool ref_p)
> +write_ts_decl_minimal_tree_pointers (struct output_block *ob, tree expr)
>  {
>    /* Drop names that were created for anonymous entities.  */
>    if (DECL_NAME (expr)
>        && TREE_CODE (DECL_NAME (expr)) == IDENTIFIER_NODE
>        && IDENTIFIER_ANON_P (DECL_NAME (expr)))
> -    stream_write_tree (ob, NULL_TREE, ref_p);
> +    stream_write_tree_ref (ob, NULL_TREE);
>    else
> -    stream_write_tree (ob, DECL_NAME (expr), ref_p);
> +    stream_write_tree_ref (ob, DECL_NAME (expr));
>    if (TREE_CODE (expr) != TRANSLATION_UNIT_DECL
>        && ! DECL_CONTEXT (expr))
> -    stream_write_tree (ob, (*all_translation_units)[0], ref_p);
> +    stream_write_tree_ref (ob, (*all_translation_units)[0]);
>    else
> -    stream_write_tree (ob, DECL_CONTEXT (expr), ref_p);
> +    stream_write_tree_ref (ob, DECL_CONTEXT (expr));
>  }
>
>
> @@ -609,16 +608,15 @@ write_ts_decl_minimal_tree_pointers (struct output_block *ob, tree expr,
>     pointer fields.  */
>
>  static void
> -write_ts_decl_common_tree_pointers (struct output_block *ob, tree expr,
> -                                   bool ref_p)
> +write_ts_decl_common_tree_pointers (struct output_block *ob, tree expr)
>  {
> -  stream_write_tree (ob, DECL_SIZE (expr), ref_p);
> -  stream_write_tree (ob, DECL_SIZE_UNIT (expr), ref_p);
> +  stream_write_tree_ref (ob, DECL_SIZE (expr));
> +  stream_write_tree_ref (ob, DECL_SIZE_UNIT (expr));
>
>    /* Note, DECL_INITIAL is not handled here.  Since DECL_INITIAL needs
>       special handling in LTO, it must be handled by streamer hooks.  */
>
> -  stream_write_tree (ob, DECL_ATTRIBUTES (expr), ref_p);
> +  stream_write_tree_ref (ob, DECL_ATTRIBUTES (expr));
>
>    /* On non-early-LTO enabled targets we claim we compiled with -g0
>       but dwarf2out still did its set_decl_origin_self game fooling
> @@ -628,15 +626,15 @@ write_ts_decl_common_tree_pointers (struct output_block *ob, tree expr,
>    if (debug_info_level == DINFO_LEVEL_NONE
>        && ao == expr)
>      ao = NULL_TREE;
> -  stream_write_tree (ob, ao, ref_p);
> +  stream_write_tree_ref (ob, ao);
>
>    if ((VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
>        && DECL_HAS_VALUE_EXPR_P (expr))
> -    stream_write_tree (ob, DECL_VALUE_EXPR (expr), ref_p);
> +    stream_write_tree_ref (ob, DECL_VALUE_EXPR (expr));
>
>    if (VAR_P (expr)
>        && DECL_HAS_DEBUG_EXPR_P (expr))
> -    stream_write_tree (ob, DECL_DEBUG_EXPR (expr), ref_p);
> +    stream_write_tree_ref (ob, DECL_DEBUG_EXPR (expr));
>  }
>
>
> @@ -645,7 +643,7 @@ write_ts_decl_common_tree_pointers (struct output_block *ob, tree expr,
>     pointer fields.  */
>
>  static void
> -write_ts_decl_non_common_tree_pointers (struct output_block *, tree, bool)
> +write_ts_decl_non_common_tree_pointers (struct output_block *, tree)
>  {
>  }
>
> @@ -655,14 +653,13 @@ write_ts_decl_non_common_tree_pointers (struct output_block *, tree, bool)
>     pointer fields.  */
>
>  static void
> -write_ts_decl_with_vis_tree_pointers (struct output_block *ob, tree expr,
> -                                     bool ref_p)
> +write_ts_decl_with_vis_tree_pointers (struct output_block *ob, tree expr)
>  {
>    /* Make sure we don't inadvertently set the assembler name.  */
>    if (DECL_ASSEMBLER_NAME_SET_P (expr))
> -    stream_write_tree (ob, DECL_ASSEMBLER_NAME (expr), ref_p);
> +    stream_write_tree_ref (ob, DECL_ASSEMBLER_NAME (expr));
>    else
> -    stream_write_tree (ob, NULL_TREE, false);
> +    stream_write_tree_ref (ob, NULL_TREE);
>  }
>
>
> @@ -671,13 +668,12 @@ write_ts_decl_with_vis_tree_pointers (struct output_block *ob, tree expr,
>     pointer fields.  */
>
>  static void
> -write_ts_field_decl_tree_pointers (struct output_block *ob, tree expr,
> -                                  bool ref_p)
> +write_ts_field_decl_tree_pointers (struct output_block *ob, tree expr)
>  {
> -  stream_write_tree (ob, DECL_FIELD_OFFSET (expr), ref_p);
> -  stream_write_tree (ob, DECL_BIT_FIELD_TYPE (expr), ref_p);
> -  stream_write_tree (ob, DECL_BIT_FIELD_REPRESENTATIVE (expr), ref_p);
> -  stream_write_tree (ob, DECL_FIELD_BIT_OFFSET (expr), ref_p);
> +  stream_write_tree_ref (ob, DECL_FIELD_OFFSET (expr));
> +  stream_write_tree_ref (ob, DECL_BIT_FIELD_TYPE (expr));
> +  stream_write_tree_ref (ob, DECL_BIT_FIELD_REPRESENTATIVE (expr));
> +  stream_write_tree_ref (ob, DECL_FIELD_BIT_OFFSET (expr));
>  }
>
>
> @@ -686,15 +682,14 @@ write_ts_field_decl_tree_pointers (struct output_block *ob, tree expr,
>     pointer fields.  */
>
>  static void
> -write_ts_function_decl_tree_pointers (struct output_block *ob, tree expr,
> -                                     bool ref_p)
> +write_ts_function_decl_tree_pointers (struct output_block *ob, tree expr)
>  {
>    /* DECL_STRUCT_FUNCTION is handled by lto_output_function.  */
> -  stream_write_tree (ob, DECL_FUNCTION_PERSONALITY (expr), ref_p);
> +  stream_write_tree_ref (ob, DECL_FUNCTION_PERSONALITY (expr));
>    /* Don't stream these when passing things to a different target.  */
>    if (!lto_stream_offload_p)
> -    stream_write_tree (ob, DECL_FUNCTION_SPECIFIC_TARGET (expr), ref_p);
> -  stream_write_tree (ob, DECL_FUNCTION_SPECIFIC_OPTIMIZATION (expr), ref_p);
> +    stream_write_tree_ref (ob, DECL_FUNCTION_SPECIFIC_TARGET (expr));
> +  stream_write_tree_ref (ob, DECL_FUNCTION_SPECIFIC_OPTIMIZATION (expr));
>  }
>
>
> @@ -703,19 +698,18 @@ write_ts_function_decl_tree_pointers (struct output_block *ob, tree expr,
>     pointer fields.  */
>
>  static void
> -write_ts_type_common_tree_pointers (struct output_block *ob, tree expr,
> -                                   bool ref_p)
> +write_ts_type_common_tree_pointers (struct output_block *ob, tree expr)
>  {
> -  stream_write_tree (ob, TYPE_SIZE (expr), ref_p);
> -  stream_write_tree (ob, TYPE_SIZE_UNIT (expr), ref_p);
> -  stream_write_tree (ob, TYPE_ATTRIBUTES (expr), ref_p);
> -  stream_write_tree (ob, TYPE_NAME (expr), ref_p);
> +  stream_write_tree_ref (ob, TYPE_SIZE (expr));
> +  stream_write_tree_ref (ob, TYPE_SIZE_UNIT (expr));
> +  stream_write_tree_ref (ob, TYPE_ATTRIBUTES (expr));
> +  stream_write_tree_ref (ob, TYPE_NAME (expr));
>    /* Do not stream TYPE_POINTER_TO or TYPE_REFERENCE_TO.  They will be
>       reconstructed during fixup.  */
>    /* Do not stream TYPE_NEXT_VARIANT, we reconstruct the variant lists
>       during fixup.  */
> -  stream_write_tree (ob, TYPE_MAIN_VARIANT (expr), ref_p);
> -  stream_write_tree (ob, TYPE_CONTEXT (expr), ref_p);
> +  stream_write_tree_ref (ob, TYPE_MAIN_VARIANT (expr));
> +  stream_write_tree_ref (ob, TYPE_CONTEXT (expr));
>    /* TYPE_CANONICAL is re-computed during type merging, so no need
>       to stream it here.  */
>    /* Do not stream TYPE_STUB_DECL; it is not needed by LTO but currently
> @@ -728,22 +722,21 @@ write_ts_type_common_tree_pointers (struct output_block *ob, tree expr,
>     pointer fields.  */
>
>  static void
> -write_ts_type_non_common_tree_pointers (struct output_block *ob, tree expr,
> -                                       bool ref_p)
> +write_ts_type_non_common_tree_pointers (struct output_block *ob, tree expr)
>  {
>    if (TREE_CODE (expr) == ENUMERAL_TYPE)
> -    stream_write_tree (ob, TYPE_VALUES (expr), ref_p);
> +    stream_write_tree_ref (ob, TYPE_VALUES (expr));
>    else if (TREE_CODE (expr) == ARRAY_TYPE)
> -    stream_write_tree (ob, TYPE_DOMAIN (expr), ref_p);
> +    stream_write_tree_ref (ob, TYPE_DOMAIN (expr));
>    else if (RECORD_OR_UNION_TYPE_P (expr))
> -    streamer_write_chain (ob, TYPE_FIELDS (expr), ref_p);
> +    streamer_write_chain (ob, TYPE_FIELDS (expr));
>    else if (TREE_CODE (expr) == FUNCTION_TYPE
>            || TREE_CODE (expr) == METHOD_TYPE)
> -    stream_write_tree (ob, TYPE_ARG_TYPES (expr), ref_p);
> +    stream_write_tree_ref (ob, TYPE_ARG_TYPES (expr));
>
>    if (!POINTER_TYPE_P (expr))
> -    stream_write_tree (ob, TYPE_MIN_VALUE_RAW (expr), ref_p);
> -  stream_write_tree (ob, TYPE_MAX_VALUE_RAW (expr), ref_p);
> +    stream_write_tree_ref (ob, TYPE_MIN_VALUE_RAW (expr));
> +  stream_write_tree_ref (ob, TYPE_MAX_VALUE_RAW (expr));
>  }
>
>
> @@ -752,11 +745,11 @@ write_ts_type_non_common_tree_pointers (struct output_block *ob, tree expr,
>     fields.  */
>
>  static void
> -write_ts_list_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
> +write_ts_list_tree_pointers (struct output_block *ob, tree expr)
>  {
> -  stream_write_tree (ob, TREE_PURPOSE (expr), ref_p);
> -  stream_write_tree (ob, TREE_VALUE (expr), ref_p);
> -  stream_write_tree (ob, TREE_CHAIN (expr), ref_p);
> +  stream_write_tree_ref (ob, TREE_PURPOSE (expr));
> +  stream_write_tree_ref (ob, TREE_VALUE (expr));
> +  stream_write_tree_ref (ob, TREE_CHAIN (expr));
>  }
>
>
> @@ -765,14 +758,14 @@ write_ts_list_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
>     fields.  */
>
>  static void
> -write_ts_vec_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
> +write_ts_vec_tree_pointers (struct output_block *ob, tree expr)
>  {
>    int i;
>
>    /* Note that the number of slots for EXPR has already been emitted
>       in EXPR's header (see streamer_write_tree_header).  */
>    for (i = 0; i < TREE_VEC_LENGTH (expr); i++)
> -    stream_write_tree (ob, TREE_VEC_ELT (expr, i), ref_p);
> +    stream_write_tree_ref (ob, TREE_VEC_ELT (expr, i));
>  }
>
>
> @@ -781,13 +774,13 @@ write_ts_vec_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
>     fields.  */
>
>  static void
> -write_ts_exp_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
> +write_ts_exp_tree_pointers (struct output_block *ob, tree expr)
>  {
>    int i;
>
>    for (i = 0; i < TREE_OPERAND_LENGTH (expr); i++)
> -    stream_write_tree (ob, TREE_OPERAND (expr, i), ref_p);
> -  stream_write_tree (ob, TREE_BLOCK (expr), ref_p);
> +    stream_write_tree_ref (ob, TREE_OPERAND (expr, i));
> +  stream_write_tree_ref (ob, TREE_BLOCK (expr));
>  }
>
>
> @@ -796,12 +789,12 @@ write_ts_exp_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
>     fields.  */
>
>  static void
> -write_ts_block_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
> +write_ts_block_tree_pointers (struct output_block *ob, tree expr)
>  {
> -  streamer_write_chain (ob, BLOCK_VARS (expr), ref_p);
> +  streamer_write_chain (ob, BLOCK_VARS (expr));
>
> -  stream_write_tree (ob, BLOCK_SUPERCONTEXT (expr), ref_p);
> -  stream_write_tree (ob, BLOCK_ABSTRACT_ORIGIN (expr), ref_p);
> +  stream_write_tree_ref (ob, BLOCK_SUPERCONTEXT (expr));
> +  stream_write_tree_ref (ob, BLOCK_ABSTRACT_ORIGIN (expr));
>
>    /* Do not stream BLOCK_NONLOCALIZED_VARS.  We cannot handle debug information
>       for early inlined BLOCKs so drop it on the floor instead of ICEing in
> @@ -820,7 +813,7 @@ write_ts_block_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
>     fields.  */
>
>  static void
> -write_ts_binfo_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
> +write_ts_binfo_tree_pointers (struct output_block *ob, tree expr)
>  {
>    unsigned i;
>    tree t;
> @@ -829,11 +822,11 @@ write_ts_binfo_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
>       EXPR's header (see streamer_write_tree_header) because this length
>       is needed to build the empty BINFO node on the reader side.  */
>    FOR_EACH_VEC_ELT (*BINFO_BASE_BINFOS (expr), i, t)
> -    stream_write_tree (ob, t, ref_p);
> -  stream_write_tree (ob, NULL_TREE, false);
> +    stream_write_tree_ref (ob, t);
> +  stream_write_tree_ref (ob, NULL_TREE);
>
> -  stream_write_tree (ob, BINFO_OFFSET (expr), ref_p);
> -  stream_write_tree (ob, BINFO_VTABLE (expr), ref_p);
> +  stream_write_tree_ref (ob, BINFO_OFFSET (expr));
> +  stream_write_tree_ref (ob, BINFO_VTABLE (expr));
>
>    /* Do not walk BINFO_INHERITANCE_CHAIN, BINFO_SUBVTT_INDEX,
>       BINFO_BASE_ACCESSES and BINFO_VPTR_INDEX; these are used by C++ FE only.  */
> @@ -845,16 +838,15 @@ write_ts_binfo_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
>     pointer fields.  */
>
>  static void
> -write_ts_constructor_tree_pointers (struct output_block *ob, tree expr,
> -                                   bool ref_p)
> +write_ts_constructor_tree_pointers (struct output_block *ob, tree expr)
>  {
>    unsigned i;
>    tree index, value;
>
>    FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (expr), i, index, value)
>      {
> -      stream_write_tree (ob, index, ref_p);
> -      stream_write_tree (ob, value, ref_p);
> +      stream_write_tree_ref (ob, index);
> +      stream_write_tree_ref (ob, value);
>      }
>  }
>
> @@ -864,12 +856,11 @@ write_ts_constructor_tree_pointers (struct output_block *ob, tree expr,
>     pointer fields.  */
>
>  static void
> -write_ts_omp_clause_tree_pointers (struct output_block *ob, tree expr,
> -                                  bool ref_p)
> +write_ts_omp_clause_tree_pointers (struct output_block *ob, tree expr)
>  {
>    int i;
>    for (i = 0; i < omp_clause_num_ops[OMP_CLAUSE_CODE (expr)]; i++)
> -    stream_write_tree (ob, OMP_CLAUSE_OPERAND (expr, i), ref_p);
> +    stream_write_tree_ref (ob, OMP_CLAUSE_OPERAND (expr, i));
>    switch (OMP_CLAUSE_CODE (expr))
>      {
>      case OMP_CLAUSE_REDUCTION:
> @@ -883,7 +874,7 @@ write_ts_omp_clause_tree_pointers (struct output_block *ob, tree expr,
>      default:
>        break;
>      }
> -  stream_write_tree (ob, OMP_CLAUSE_CHAIN (expr), ref_p);
> +  stream_write_tree_ref (ob, OMP_CLAUSE_CHAIN (expr));
>  }
>
>
> @@ -891,7 +882,7 @@ write_ts_omp_clause_tree_pointers (struct output_block *ob, tree expr,
>     the leaves of EXPR are emitted as references.  */
>
>  void
> -streamer_write_tree_body (struct output_block *ob, tree expr, bool ref_p)
> +streamer_write_tree_body (struct output_block *ob, tree expr)
>  {
>    enum tree_code code;
>
> @@ -900,61 +891,61 @@ streamer_write_tree_body (struct output_block *ob, tree expr, bool ref_p)
>    code = TREE_CODE (expr);
>
>    if (CODE_CONTAINS_STRUCT (code, TS_TYPED))
> -    write_ts_common_tree_pointers (ob, expr, ref_p);
> +    write_ts_common_tree_pointers (ob, expr);
>
>    if (CODE_CONTAINS_STRUCT (code, TS_VECTOR))
> -    write_ts_vector_tree_pointers (ob, expr, ref_p);
> +    write_ts_vector_tree_pointers (ob, expr);
>
>    if (CODE_CONTAINS_STRUCT (code, TS_POLY_INT_CST))
> -    write_ts_poly_tree_pointers (ob, expr, ref_p);
> +    write_ts_poly_tree_pointers (ob, expr);
>
>    if (CODE_CONTAINS_STRUCT (code, TS_COMPLEX))
> -    write_ts_complex_tree_pointers (ob, expr, ref_p);
> +    write_ts_complex_tree_pointers (ob, expr);
>
>    if (CODE_CONTAINS_STRUCT (code, TS_DECL_MINIMAL))
> -    write_ts_decl_minimal_tree_pointers (ob, expr, ref_p);
> +    write_ts_decl_minimal_tree_pointers (ob, expr);
>
>    if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
> -    write_ts_decl_common_tree_pointers (ob, expr, ref_p);
> +    write_ts_decl_common_tree_pointers (ob, expr);
>
>    if (CODE_CONTAINS_STRUCT (code, TS_DECL_NON_COMMON))
> -    write_ts_decl_non_common_tree_pointers (ob, expr, ref_p);
> +    write_ts_decl_non_common_tree_pointers (ob, expr);
>
>    if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
> -    write_ts_decl_with_vis_tree_pointers (ob, expr, ref_p);
> +    write_ts_decl_with_vis_tree_pointers (ob, expr);
>
>    if (CODE_CONTAINS_STRUCT (code, TS_FIELD_DECL))
> -    write_ts_field_decl_tree_pointers (ob, expr, ref_p);
> +    write_ts_field_decl_tree_pointers (ob, expr);
>
>    if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL))
> -    write_ts_function_decl_tree_pointers (ob, expr, ref_p);
> +    write_ts_function_decl_tree_pointers (ob, expr);
>
>    if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON))
> -    write_ts_type_common_tree_pointers (ob, expr, ref_p);
> +    write_ts_type_common_tree_pointers (ob, expr);
>
>    if (CODE_CONTAINS_STRUCT (code, TS_TYPE_NON_COMMON))
> -    write_ts_type_non_common_tree_pointers (ob, expr, ref_p);
> +    write_ts_type_non_common_tree_pointers (ob, expr);
>
>    if (CODE_CONTAINS_STRUCT (code, TS_LIST))
> -    write_ts_list_tree_pointers (ob, expr, ref_p);
> +    write_ts_list_tree_pointers (ob, expr);
>
>    if (CODE_CONTAINS_STRUCT (code, TS_VEC))
> -    write_ts_vec_tree_pointers (ob, expr, ref_p);
> +    write_ts_vec_tree_pointers (ob, expr);
>
>    if (CODE_CONTAINS_STRUCT (code, TS_EXP))
> -    write_ts_exp_tree_pointers (ob, expr, ref_p);
> +    write_ts_exp_tree_pointers (ob, expr);
>
>    if (CODE_CONTAINS_STRUCT (code, TS_BLOCK))
> -    write_ts_block_tree_pointers (ob, expr, ref_p);
> +    write_ts_block_tree_pointers (ob, expr);
>
>    if (CODE_CONTAINS_STRUCT (code, TS_BINFO))
> -    write_ts_binfo_tree_pointers (ob, expr, ref_p);
> +    write_ts_binfo_tree_pointers (ob, expr);
>
>    if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR))
> -    write_ts_constructor_tree_pointers (ob, expr, ref_p);
> +    write_ts_constructor_tree_pointers (ob, expr);
>
>    if (code == OMP_CLAUSE)
> -    write_ts_omp_clause_tree_pointers (ob, expr, ref_p);
> +    write_ts_omp_clause_tree_pointers (ob, expr);
>  }
>
>
> @@ -1021,7 +1012,7 @@ streamer_write_tree_header (struct output_block *ob, tree expr)
>     CST's type will be emitted as a reference.  */
>
>  void
> -streamer_write_integer_cst (struct output_block *ob, tree cst, bool ref_p)
> +streamer_write_integer_cst (struct output_block *ob, tree cst)
>  {
>    int i;
>    int len = TREE_INT_CST_NUNITS (cst);
> @@ -1033,7 +1024,7 @@ streamer_write_integer_cst (struct output_block *ob, tree cst, bool ref_p)
>        fprintf (streamer_dump_file, "\n");
>      }
>    streamer_write_record_start (ob, LTO_integer_cst);
> -  stream_write_tree (ob, TREE_TYPE (cst), ref_p);
> +  stream_write_tree_ref (ob, TREE_TYPE (cst));
>    /* We're effectively streaming a non-sign-extended wide_int here,
>       so there's no need to stream TREE_INT_CST_EXT_NUNITS or any
>       array members beyond LEN.  We'll recreate the tree from the
> diff --git a/gcc/tree-streamer.h b/gcc/tree-streamer.h
> index 7e239e03d60..d40724237a1 100644
> --- a/gcc/tree-streamer.h
> +++ b/gcc/tree-streamer.h
> @@ -59,7 +59,6 @@ struct streamer_tree_cache_d
>
>  /* In tree-streamer-in.c.  */
>  tree streamer_read_string_cst (class data_in *, class lto_input_block *);
> -tree streamer_read_chain (class lto_input_block *, class data_in *);
>  tree streamer_alloc_tree (class lto_input_block *, class data_in *,
>                           enum LTO_tags);
>  void streamer_read_tree_body (class lto_input_block *, class data_in *, tree);
> @@ -70,11 +69,10 @@ void streamer_read_tree_bitfields (class lto_input_block *,
>  /* In tree-streamer-out.c.  */
>  void streamer_write_string_cst (struct output_block *,
>                                 struct lto_output_stream *, tree);
> -void streamer_write_chain (struct output_block *, tree, bool);
>  void streamer_write_tree_header (struct output_block *, tree);
>  void streamer_write_tree_bitfields (struct output_block *, tree);
> -void streamer_write_tree_body (struct output_block *, tree, bool);
> -void streamer_write_integer_cst (struct output_block *, tree, bool);
> +void streamer_write_tree_body (struct output_block *, tree);
> +void streamer_write_integer_cst (struct output_block *, tree);
>
>  /* In tree-streamer.c.  */
>  extern unsigned char streamer_mode_table[1 << 8];
diff mbox series

Patch

diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c
index d0532c5ac51..c80574be207 100644
--- a/gcc/lto-streamer-in.c
+++ b/gcc/lto-streamer-in.c
@@ -1021,6 +1021,30 @@  input_struct_function_base (struct function *fn, class data_in *data_in,
     }
 }
 
+/* Read a chain of tree nodes from input block IB.  DATA_IN contains
+   tables and descriptors for the file being read.  */
+
+static tree
+streamer_read_chain (class lto_input_block *ib, class data_in *data_in)
+{
+  tree first, prev, curr;
+
+  /* The chain is written as NULL terminated list of trees.  */
+  first = prev = NULL_TREE;
+  do
+    {
+      curr = stream_read_tree (ib, data_in);
+      if (prev)
+	TREE_CHAIN (prev) = curr;
+      else
+	first = curr;
+
+      prev = curr;
+    }
+  while (curr);
+
+  return first;
+}
 
 /* Read the body of function FN_DECL from DATA_IN using input block IB.  */
 
@@ -1481,6 +1505,25 @@  lto_input_scc (class lto_input_block *ib, class data_in *data_in,
   return scc_hash;
 }
 
+tree
+stream_read_tree_ref (lto_input_block *ib, data_in *data_in)
+{
+  unsigned ix = streamer_read_uhwi (ib);
+  tree ret;
+  if (!ix)
+    return NULL_TREE;
+  else if (ix < LTO_NUM_TAGS)
+    ret = lto_input_tree_ref (ib, data_in, cfun, (LTO_tags)ix);
+  else
+    ret = streamer_tree_cache_get_tree (data_in->reader_cache,
+					ix - LTO_NUM_TAGS);
+  if (ret && streamer_debugging)
+    {
+      enum tree_code c = (enum tree_code)streamer_read_uhwi (ib);
+      gcc_assert (c == TREE_CODE (ret));
+    }
+  return ret;
+}
 
 /* Read a tree from input block IB using the per-file context in
    DATA_IN.  This context is used, for example, to resolve references
@@ -1513,7 +1556,7 @@  lto_input_tree_1 (class lto_input_block *ib, class data_in *data_in,
     {
       /* For shared integer constants in singletons we can use the
          existing tree integer constant merging code.  */
-      tree type = stream_read_tree (ib, data_in);
+      tree type = stream_read_tree_ref (ib, data_in);
       unsigned HOST_WIDE_INT len = streamer_read_uhwi (ib);
       unsigned HOST_WIDE_INT i;
       HOST_WIDE_INT a[WIDE_INT_MAX_ELTS];
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index 288e3c0f4c6..522986278a7 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -228,7 +228,7 @@  lto_output_location (struct output_block *ob, struct bitpack_d *bp,
    output block OB.  Otherwise, output the physical representation of
    EXPR to OB.  */
 
-static void
+void
 lto_output_tree_ref (struct output_block *ob, tree expr)
 {
   enum tree_code code;
@@ -409,6 +409,29 @@  get_symbol_initial_value (lto_symtab_encoder_t encoder, tree expr)
 }
 
 
+/* Output reference to tree T to the stream.
+   Assume that T is already in encoder cache.  */
+
+void
+stream_write_tree_ref (struct output_block *ob, tree t)
+{
+  if (!t)
+    streamer_write_zero (ob);
+  else
+    {
+      unsigned int ix;
+      bool existed_p = streamer_tree_cache_lookup (ob->writer_cache, t, &ix);
+      if (existed_p)
+	streamer_write_uhwi (ob, ix + LTO_NUM_TAGS);
+      else
+	lto_output_tree_ref (ob, t);
+      if (streamer_debugging)
+      streamer_write_uhwi (ob, TREE_CODE (t));
+    }
+}
+
+
+
 /* Write a physical representation of tree node EXPR to output block
    OB.  If REF_P is true, the leaves of EXPR are emitted as references
    via lto_output_tree_ref.  IX is the index into the streamer cache
@@ -430,7 +453,7 @@  lto_write_tree_1 (struct output_block *ob, tree expr, bool ref_p)
   streamer_write_tree_bitfields (ob, expr);
 
   /* Write all the pointer fields in EXPR.  */
-  streamer_write_tree_body (ob, expr, ref_p);
+  streamer_write_tree_body (ob, expr);
 
   /* Write any LTO-specific data to OB.  */
   if (DECL_P (expr)
@@ -505,7 +528,7 @@  lto_output_tree_1 (struct output_block *ob, tree expr, hashval_t hash,
       /* Shared INTEGER_CST nodes are special because they need their
 	 original type to be materialized by the reader (to implement
 	 TYPE_CACHED_VALUES).  */
-      streamer_write_integer_cst (ob, expr, ref_p);
+      streamer_write_integer_cst (ob, expr);
     }
   else
     {
@@ -1685,7 +1708,7 @@  DFS::DFS_write_tree (struct output_block *ob, sccs *from_state,
   /* Check if we already streamed EXPR.  */
   if (streamer_tree_cache_lookup (ob->writer_cache, expr, NULL))
     {
-      /* Refernece to a local tree makes entry also local.  We always process
+      /* Reference to a local tree makes entry also local.  We always process
 	 top of stack entry, so set max to number of entries in stack - 1.  */
       if (ob->local_trees
 	  && ob->local_trees->contains (expr))
@@ -2271,6 +2294,29 @@  lto_prepare_function_for_streaming (struct cgraph_node *node)
 
 }
 
+/* Emit the chain of tree nodes starting at T.  OB is the output block
+   to write to.  REF_P is true if chain elements should be emitted
+   as references.  */
+
+static void
+streamer_write_chain (struct output_block *ob, tree t, bool ref_p)
+{
+  while (t)
+    {
+      /* We avoid outputting external vars or functions by reference
+	 to the global decls section as we do not want to have them
+	 enter decl merging.  We should not need to do this anymore because
+	 free_lang_data removes them from block scopes.  */
+      gcc_assert (!VAR_OR_FUNCTION_DECL_P (t) || !DECL_EXTERNAL (t));
+      stream_write_tree (ob, t, ref_p);
+
+      t = TREE_CHAIN (t);
+    }
+
+  /* Write a sentinel to terminate the chain.  */
+  stream_write_tree (ob, NULL_TREE, ref_p);
+}
+
 /* Output the body of function NODE->DECL.  */
 
 static void
diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h
index 93da3c66fd8..3470aa4cc95 100644
--- a/gcc/lto-streamer.h
+++ b/gcc/lto-streamer.h
@@ -882,6 +882,7 @@  extern void lto_streamer_init (void);
 extern bool gate_lto_out (void);
 extern void lto_check_version (int, int, const char *);
 extern void lto_streamer_hooks_init (void);
+extern void lto_output_tree_ref (struct output_block *, tree);
 
 /* In lto-streamer-in.c */
 extern void lto_input_cgraph (struct lto_file_decl_data *, const char *);
@@ -914,6 +915,7 @@  hashval_t lto_input_scc (class lto_input_block *, class data_in *,
 tree lto_input_tree_1 (class lto_input_block *, class data_in *,
 		       enum LTO_tags, hashval_t hash);
 tree lto_input_tree (class lto_input_block *, class data_in *);
+tree stream_read_tree_ref (class lto_input_block *, class data_in *);
 
 
 /* In lto-streamer-out.c  */
@@ -921,6 +923,7 @@  extern void lto_register_decl_definition (tree, struct lto_file_decl_data *);
 extern struct output_block *create_output_block (enum lto_section_type);
 extern void destroy_output_block (struct output_block *);
 extern void lto_output_tree (struct output_block *, tree, bool, bool);
+extern void stream_write_tree_ref (struct output_block *, tree);
 extern void lto_output_toplevel_asms (void);
 extern void produce_asm (struct output_block *ob, tree fn);
 extern void lto_output ();
diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c
index d2e45e33554..447a3110e82 100644
--- a/gcc/tree-streamer-in.c
+++ b/gcc/tree-streamer-in.c
@@ -69,10 +69,10 @@  input_identifier (class data_in *data_in, class lto_input_block *ib)
 }
 
 
-/* Read a chain of tree nodes from input block IB. DATA_IN contains
+/* Read a chain of tree nodes from input block IB.  DATA_IN contains
    tables and descriptors for the file being read.  */
 
-tree
+static tree
 streamer_read_chain (class lto_input_block *ib, class data_in *data_in)
 {
   tree first, prev, curr;
@@ -81,7 +81,7 @@  streamer_read_chain (class lto_input_block *ib, class data_in *data_in)
   first = prev = NULL_TREE;
   do
     {
-      curr = stream_read_tree (ib, data_in);
+      curr = stream_read_tree_ref (ib, data_in);
       if (prev)
 	TREE_CHAIN (prev) = curr;
       else
@@ -651,7 +651,7 @@  lto_input_ts_common_tree_pointers (class lto_input_block *ib,
 				   class data_in *data_in, tree expr)
 {
   if (TREE_CODE (expr) != IDENTIFIER_NODE)
-    TREE_TYPE (expr) = stream_read_tree (ib, data_in);
+    TREE_TYPE (expr) = stream_read_tree_ref (ib, data_in);
 }
 
 
@@ -665,7 +665,7 @@  lto_input_ts_vector_tree_pointers (class lto_input_block *ib,
 {
   unsigned int count = vector_cst_encoded_nelts (expr);
   for (unsigned int i = 0; i < count; ++i)
-    VECTOR_CST_ENCODED_ELT (expr, i) = stream_read_tree (ib, data_in);
+    VECTOR_CST_ENCODED_ELT (expr, i) = stream_read_tree_ref (ib, data_in);
 }
 
 
@@ -678,7 +678,7 @@  lto_input_ts_poly_tree_pointers (class lto_input_block *ib,
 				 class data_in *data_in, tree expr)
 {
   for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
-    POLY_INT_CST_COEFF (expr, i) = stream_read_tree (ib, data_in);
+    POLY_INT_CST_COEFF (expr, i) = stream_read_tree_ref (ib, data_in);
 }
 
 
@@ -690,8 +690,8 @@  static void
 lto_input_ts_complex_tree_pointers (class lto_input_block *ib,
 				    class data_in *data_in, tree expr)
 {
-  TREE_REALPART (expr) = stream_read_tree (ib, data_in);
-  TREE_IMAGPART (expr) = stream_read_tree (ib, data_in);
+  TREE_REALPART (expr) = stream_read_tree_ref (ib, data_in);
+  TREE_IMAGPART (expr) = stream_read_tree_ref (ib, data_in);
 }
 
 
@@ -703,8 +703,8 @@  static void
 lto_input_ts_decl_minimal_tree_pointers (class lto_input_block *ib,
 					 class data_in *data_in, tree expr)
 {
-  DECL_NAME (expr) = stream_read_tree (ib, data_in);
-  DECL_CONTEXT (expr) = stream_read_tree (ib, data_in);
+  DECL_NAME (expr) = stream_read_tree_ref (ib, data_in);
+  DECL_CONTEXT (expr) = stream_read_tree_ref (ib, data_in);
 }
 
 
@@ -716,19 +716,19 @@  static void
 lto_input_ts_decl_common_tree_pointers (class lto_input_block *ib,
 					class data_in *data_in, tree expr)
 {
-  DECL_SIZE (expr) = stream_read_tree (ib, data_in);
-  DECL_SIZE_UNIT (expr) = stream_read_tree (ib, data_in);
-  DECL_ATTRIBUTES (expr) = stream_read_tree (ib, data_in);
-  DECL_ABSTRACT_ORIGIN (expr) = stream_read_tree (ib, data_in);
+  DECL_SIZE (expr) = stream_read_tree_ref (ib, data_in);
+  DECL_SIZE_UNIT (expr) = stream_read_tree_ref (ib, data_in);
+  DECL_ATTRIBUTES (expr) = stream_read_tree_ref (ib, data_in);
+  DECL_ABSTRACT_ORIGIN (expr) = stream_read_tree_ref (ib, data_in);
 
   if ((VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
       && DECL_HAS_VALUE_EXPR_P (expr))
-    SET_DECL_VALUE_EXPR (expr, stream_read_tree (ib, data_in));
+    SET_DECL_VALUE_EXPR (expr, stream_read_tree_ref (ib, data_in));
 
   if (VAR_P (expr)
       && DECL_HAS_DEBUG_EXPR_P (expr))
     {
-      tree dexpr = stream_read_tree (ib, data_in);
+      tree dexpr = stream_read_tree_ref (ib, data_in);
       if (dexpr)
 	SET_DECL_DEBUG_EXPR (expr, dexpr);
     }
@@ -756,7 +756,7 @@  lto_input_ts_decl_with_vis_tree_pointers (class lto_input_block *ib,
 {
   tree id;
 
-  id = stream_read_tree (ib, data_in);
+  id = stream_read_tree_ref (ib, data_in);
   if (id)
     {
       gcc_assert (TREE_CODE (id) == IDENTIFIER_NODE);
@@ -773,10 +773,10 @@  static void
 lto_input_ts_field_decl_tree_pointers (class lto_input_block *ib,
 				       class data_in *data_in, tree expr)
 {
-  DECL_FIELD_OFFSET (expr) = stream_read_tree (ib, data_in);
-  DECL_BIT_FIELD_TYPE (expr) = stream_read_tree (ib, data_in);
-  DECL_BIT_FIELD_REPRESENTATIVE (expr) = stream_read_tree (ib, data_in);
-  DECL_FIELD_BIT_OFFSET (expr) = stream_read_tree (ib, data_in);
+  DECL_FIELD_OFFSET (expr) = stream_read_tree_ref (ib, data_in);
+  DECL_BIT_FIELD_TYPE (expr) = stream_read_tree_ref (ib, data_in);
+  DECL_BIT_FIELD_REPRESENTATIVE (expr) = stream_read_tree_ref (ib, data_in);
+  DECL_FIELD_BIT_OFFSET (expr) = stream_read_tree_ref (ib, data_in);
 }
 
 
@@ -789,11 +789,12 @@  lto_input_ts_function_decl_tree_pointers (class lto_input_block *ib,
 					  class data_in *data_in, tree expr)
 {
   /* DECL_STRUCT_FUNCTION is loaded on demand by cgraph_get_body.  */
-  DECL_FUNCTION_PERSONALITY (expr) = stream_read_tree (ib, data_in);
+  DECL_FUNCTION_PERSONALITY (expr) = stream_read_tree_ref (ib, data_in);
 #ifndef ACCEL_COMPILER
-  DECL_FUNCTION_SPECIFIC_TARGET (expr) = stream_read_tree (ib, data_in);
+  DECL_FUNCTION_SPECIFIC_TARGET (expr) = stream_read_tree_ref (ib, data_in);
 #endif
-  DECL_FUNCTION_SPECIFIC_OPTIMIZATION (expr) = stream_read_tree (ib, data_in);
+  DECL_FUNCTION_SPECIFIC_OPTIMIZATION (expr)
+    = stream_read_tree_ref (ib, data_in);
 #ifdef ACCEL_COMPILER
   {
     tree opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (expr);
@@ -819,16 +820,16 @@  static void
 lto_input_ts_type_common_tree_pointers (class lto_input_block *ib,
 					class data_in *data_in, tree expr)
 {
-  TYPE_SIZE (expr) = stream_read_tree (ib, data_in);
-  TYPE_SIZE_UNIT (expr) = stream_read_tree (ib, data_in);
-  TYPE_ATTRIBUTES (expr) = stream_read_tree (ib, data_in);
-  TYPE_NAME (expr) = stream_read_tree (ib, data_in);
+  TYPE_SIZE (expr) = stream_read_tree_ref (ib, data_in);
+  TYPE_SIZE_UNIT (expr) = stream_read_tree_ref (ib, data_in);
+  TYPE_ATTRIBUTES (expr) = stream_read_tree_ref (ib, data_in);
+  TYPE_NAME (expr) = stream_read_tree_ref (ib, data_in);
   /* Do not stream TYPE_POINTER_TO or TYPE_REFERENCE_TO.  They will be
      reconstructed during fixup.  */
   /* Do not stream TYPE_NEXT_VARIANT, we reconstruct the variant lists
      during fixup.  */
-  TYPE_MAIN_VARIANT (expr) = stream_read_tree (ib, data_in);
-  TYPE_CONTEXT (expr) = stream_read_tree (ib, data_in);
+  TYPE_MAIN_VARIANT (expr) = stream_read_tree_ref (ib, data_in);
+  TYPE_CONTEXT (expr) = stream_read_tree_ref (ib, data_in);
   /* TYPE_CANONICAL gets re-computed during type merging.  */
   TYPE_CANONICAL (expr) = NULL_TREE;
 }
@@ -843,18 +844,18 @@  lto_input_ts_type_non_common_tree_pointers (class lto_input_block *ib,
 					    tree expr)
 {
   if (TREE_CODE (expr) == ENUMERAL_TYPE)
-    TYPE_VALUES (expr) = stream_read_tree (ib, data_in);
+    TYPE_VALUES (expr) = stream_read_tree_ref (ib, data_in);
   else if (TREE_CODE (expr) == ARRAY_TYPE)
-    TYPE_DOMAIN (expr) = stream_read_tree (ib, data_in);
+    TYPE_DOMAIN (expr) = stream_read_tree_ref (ib, data_in);
   else if (RECORD_OR_UNION_TYPE_P (expr))
     TYPE_FIELDS (expr) = streamer_read_chain (ib, data_in);
   else if (TREE_CODE (expr) == FUNCTION_TYPE
 	   || TREE_CODE (expr) == METHOD_TYPE)
-    TYPE_ARG_TYPES (expr) = stream_read_tree (ib, data_in);
+    TYPE_ARG_TYPES (expr) = stream_read_tree_ref (ib, data_in);
 
   if (!POINTER_TYPE_P (expr))
-    TYPE_MIN_VALUE_RAW (expr) = stream_read_tree (ib, data_in);
-  TYPE_MAX_VALUE_RAW (expr) = stream_read_tree (ib, data_in);
+    TYPE_MIN_VALUE_RAW (expr) = stream_read_tree_ref (ib, data_in);
+  TYPE_MAX_VALUE_RAW (expr) = stream_read_tree_ref (ib, data_in);
 }
 
 
@@ -866,9 +867,9 @@  static void
 lto_input_ts_list_tree_pointers (class lto_input_block *ib,
 				 class data_in *data_in, tree expr)
 {
-  TREE_PURPOSE (expr) = stream_read_tree (ib, data_in);
-  TREE_VALUE (expr) = stream_read_tree (ib, data_in);
-  TREE_CHAIN (expr) = stream_read_tree (ib, data_in);
+  TREE_PURPOSE (expr) = stream_read_tree_ref (ib, data_in);
+  TREE_VALUE (expr) = stream_read_tree_ref (ib, data_in);
+  TREE_CHAIN (expr) = stream_read_tree_ref (ib, data_in);
 }
 
 
@@ -885,7 +886,7 @@  lto_input_ts_vec_tree_pointers (class lto_input_block *ib,
   /* Note that TREE_VEC_LENGTH was read by streamer_alloc_tree to
      instantiate EXPR.  */
   for (i = 0; i < TREE_VEC_LENGTH (expr); i++)
-    TREE_VEC_ELT (expr, i) = stream_read_tree (ib, data_in);
+    TREE_VEC_ELT (expr, i) = stream_read_tree_ref (ib, data_in);
 }
 
 
@@ -902,9 +903,9 @@  lto_input_ts_exp_tree_pointers (class lto_input_block *ib,
   tree block;
 
   for (i = 0; i < TREE_OPERAND_LENGTH (expr); i++)
-    TREE_OPERAND (expr, i) = stream_read_tree (ib, data_in);
+    TREE_OPERAND (expr, i) = stream_read_tree_ref (ib, data_in);
 
-  block = stream_read_tree (ib, data_in);
+  block = stream_read_tree_ref (ib, data_in);
 
   /* TODO: Block is stored in the locus information.  It may make more sense to
      to make it go via the location cache.  */
@@ -926,8 +927,8 @@  lto_input_ts_block_tree_pointers (class lto_input_block *ib,
 {
   BLOCK_VARS (expr) = streamer_read_chain (ib, data_in);
 
-  BLOCK_SUPERCONTEXT (expr) = stream_read_tree (ib, data_in);
-  BLOCK_ABSTRACT_ORIGIN (expr) = stream_read_tree (ib, data_in);
+  BLOCK_SUPERCONTEXT (expr) = stream_read_tree_ref (ib, data_in);
+  BLOCK_ABSTRACT_ORIGIN (expr) = stream_read_tree_ref (ib, data_in);
   /* We may end up prevailing a decl with DECL_ORIGIN (t) != t here
      which breaks the invariant that BLOCK_ABSTRACT_ORIGIN is the
      ultimate origin.  Fixup here.
@@ -979,14 +980,14 @@  lto_input_ts_binfo_tree_pointers (class lto_input_block *ib,
      list on the writer side.  */
   do
     {
-      t = stream_read_tree (ib, data_in);
+      t = stream_read_tree_ref (ib, data_in);
       if (t)
 	BINFO_BASE_BINFOS (expr)->quick_push (t);
     }
   while (t);
 
-  BINFO_OFFSET (expr) = stream_read_tree (ib, data_in);
-  BINFO_VTABLE (expr) = stream_read_tree (ib, data_in);
+  BINFO_OFFSET (expr) = stream_read_tree_ref (ib, data_in);
+  BINFO_VTABLE (expr) = stream_read_tree_ref (ib, data_in);
 
   /* Do not walk BINFO_INHERITANCE_CHAIN, BINFO_SUBVTT_INDEX,
      BINFO_BASE_ACCESSES and BINFO_VPTR_INDEX; these are used by C++ FE
@@ -1007,8 +1008,8 @@  lto_input_ts_constructor_tree_pointers (class lto_input_block *ib,
   for (i = 0; i < CONSTRUCTOR_NELTS (expr); i++)
     {
       constructor_elt e;
-      e.index = stream_read_tree (ib, data_in);
-      e.value = stream_read_tree (ib, data_in);
+      e.index = stream_read_tree_ref (ib, data_in);
+      e.value = stream_read_tree_ref (ib, data_in);
       (*CONSTRUCTOR_ELTS (expr))[i] = e;
     }
 }
@@ -1025,8 +1026,8 @@  lto_input_ts_omp_clause_tree_pointers (class lto_input_block *ib,
   int i;
 
   for (i = 0; i < omp_clause_num_ops[OMP_CLAUSE_CODE (expr)]; i++)
-    OMP_CLAUSE_OPERAND (expr, i) = stream_read_tree (ib, data_in);
-  OMP_CLAUSE_CHAIN (expr) = stream_read_tree (ib, data_in);
+    OMP_CLAUSE_OPERAND (expr, i) = stream_read_tree_ref (ib, data_in);
+  OMP_CLAUSE_CHAIN (expr) = stream_read_tree_ref (ib, data_in);
 }
 
 
diff --git a/gcc/tree-streamer-out.c b/gcc/tree-streamer-out.c
index 94635c4a8ae..98631789cc3 100644
--- a/gcc/tree-streamer-out.c
+++ b/gcc/tree-streamer-out.c
@@ -510,8 +510,8 @@  streamer_write_tree_bitfields (struct output_block *ob, tree expr)
    to write to.  REF_P is true if chain elements should be emitted
    as references.  */
 
-void
-streamer_write_chain (struct output_block *ob, tree t, bool ref_p)
+static void
+streamer_write_chain (struct output_block *ob, tree t)
 {
   while (t)
     {
@@ -520,13 +520,13 @@  streamer_write_chain (struct output_block *ob, tree t, bool ref_p)
 	 enter decl merging.  We should not need to do this anymore because
 	 free_lang_data removes them from block scopes.  */
       gcc_assert (!VAR_OR_FUNCTION_DECL_P (t) || !DECL_EXTERNAL (t));
-      stream_write_tree (ob, t, ref_p);
+      stream_write_tree_ref (ob, t);
 
       t = TREE_CHAIN (t);
     }
 
   /* Write a sentinel to terminate the chain.  */
-  stream_write_tree (ob, NULL_TREE, ref_p);
+  stream_write_tree_ref (ob, NULL_TREE);
 }
 
 
@@ -535,10 +535,10 @@  streamer_write_chain (struct output_block *ob, tree t, bool ref_p)
    fields.  */
 
 static void
-write_ts_common_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
+write_ts_common_tree_pointers (struct output_block *ob, tree expr)
 {
   if (TREE_CODE (expr) != IDENTIFIER_NODE)
-    stream_write_tree (ob, TREE_TYPE (expr), ref_p);
+    stream_write_tree_ref (ob, TREE_TYPE (expr));
 }
 
 
@@ -547,13 +547,13 @@  write_ts_common_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
    fields.  */
 
 static void
-write_ts_vector_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
+write_ts_vector_tree_pointers (struct output_block *ob, tree expr)
 {
   /* Note that the number of elements for EXPR has already been emitted
      in EXPR's header (see streamer_write_tree_header).  */
   unsigned int count = vector_cst_encoded_nelts (expr);
   for (unsigned int i = 0; i < count; ++i)
-    stream_write_tree (ob, VECTOR_CST_ENCODED_ELT (expr, i), ref_p);
+    stream_write_tree_ref (ob, VECTOR_CST_ENCODED_ELT (expr, i));
 }
 
 
@@ -562,10 +562,10 @@  write_ts_vector_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
    fields.  */
 
 static void
-write_ts_poly_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
+write_ts_poly_tree_pointers (struct output_block *ob, tree expr)
 {
   for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
-    stream_write_tree (ob, POLY_INT_CST_COEFF (expr, i), ref_p);
+    stream_write_tree_ref (ob, POLY_INT_CST_COEFF (expr, i));
 }
 
 
@@ -574,10 +574,10 @@  write_ts_poly_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
    fields.  */
 
 static void
-write_ts_complex_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
+write_ts_complex_tree_pointers (struct output_block *ob, tree expr)
 {
-  stream_write_tree (ob, TREE_REALPART (expr), ref_p);
-  stream_write_tree (ob, TREE_IMAGPART (expr), ref_p);
+  stream_write_tree_ref (ob, TREE_REALPART (expr));
+  stream_write_tree_ref (ob, TREE_IMAGPART (expr));
 }
 
 
@@ -586,21 +586,20 @@  write_ts_complex_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
    pointer fields.  */
 
 static void
-write_ts_decl_minimal_tree_pointers (struct output_block *ob, tree expr,
-				     bool ref_p)
+write_ts_decl_minimal_tree_pointers (struct output_block *ob, tree expr)
 {
   /* Drop names that were created for anonymous entities.  */
   if (DECL_NAME (expr)
       && TREE_CODE (DECL_NAME (expr)) == IDENTIFIER_NODE
       && IDENTIFIER_ANON_P (DECL_NAME (expr)))
-    stream_write_tree (ob, NULL_TREE, ref_p);
+    stream_write_tree_ref (ob, NULL_TREE);
   else
-    stream_write_tree (ob, DECL_NAME (expr), ref_p);
+    stream_write_tree_ref (ob, DECL_NAME (expr));
   if (TREE_CODE (expr) != TRANSLATION_UNIT_DECL
       && ! DECL_CONTEXT (expr))
-    stream_write_tree (ob, (*all_translation_units)[0], ref_p);
+    stream_write_tree_ref (ob, (*all_translation_units)[0]);
   else
-    stream_write_tree (ob, DECL_CONTEXT (expr), ref_p);
+    stream_write_tree_ref (ob, DECL_CONTEXT (expr));
 }
 
 
@@ -609,16 +608,15 @@  write_ts_decl_minimal_tree_pointers (struct output_block *ob, tree expr,
    pointer fields.  */
 
 static void
-write_ts_decl_common_tree_pointers (struct output_block *ob, tree expr,
-				    bool ref_p)
+write_ts_decl_common_tree_pointers (struct output_block *ob, tree expr)
 {
-  stream_write_tree (ob, DECL_SIZE (expr), ref_p);
-  stream_write_tree (ob, DECL_SIZE_UNIT (expr), ref_p);
+  stream_write_tree_ref (ob, DECL_SIZE (expr));
+  stream_write_tree_ref (ob, DECL_SIZE_UNIT (expr));
 
   /* Note, DECL_INITIAL is not handled here.  Since DECL_INITIAL needs
      special handling in LTO, it must be handled by streamer hooks.  */
 
-  stream_write_tree (ob, DECL_ATTRIBUTES (expr), ref_p);
+  stream_write_tree_ref (ob, DECL_ATTRIBUTES (expr));
 
   /* On non-early-LTO enabled targets we claim we compiled with -g0
      but dwarf2out still did its set_decl_origin_self game fooling
@@ -628,15 +626,15 @@  write_ts_decl_common_tree_pointers (struct output_block *ob, tree expr,
   if (debug_info_level == DINFO_LEVEL_NONE
       && ao == expr)
     ao = NULL_TREE;
-  stream_write_tree (ob, ao, ref_p);
+  stream_write_tree_ref (ob, ao);
 
   if ((VAR_P (expr) || TREE_CODE (expr) == PARM_DECL)
       && DECL_HAS_VALUE_EXPR_P (expr))
-    stream_write_tree (ob, DECL_VALUE_EXPR (expr), ref_p);
+    stream_write_tree_ref (ob, DECL_VALUE_EXPR (expr));
 
   if (VAR_P (expr)
       && DECL_HAS_DEBUG_EXPR_P (expr))
-    stream_write_tree (ob, DECL_DEBUG_EXPR (expr), ref_p);
+    stream_write_tree_ref (ob, DECL_DEBUG_EXPR (expr));
 }
 
 
@@ -645,7 +643,7 @@  write_ts_decl_common_tree_pointers (struct output_block *ob, tree expr,
    pointer fields.  */
 
 static void
-write_ts_decl_non_common_tree_pointers (struct output_block *, tree, bool)
+write_ts_decl_non_common_tree_pointers (struct output_block *, tree)
 {
 }
 
@@ -655,14 +653,13 @@  write_ts_decl_non_common_tree_pointers (struct output_block *, tree, bool)
    pointer fields.  */
 
 static void
-write_ts_decl_with_vis_tree_pointers (struct output_block *ob, tree expr,
-			              bool ref_p)
+write_ts_decl_with_vis_tree_pointers (struct output_block *ob, tree expr)
 {
   /* Make sure we don't inadvertently set the assembler name.  */
   if (DECL_ASSEMBLER_NAME_SET_P (expr))
-    stream_write_tree (ob, DECL_ASSEMBLER_NAME (expr), ref_p);
+    stream_write_tree_ref (ob, DECL_ASSEMBLER_NAME (expr));
   else
-    stream_write_tree (ob, NULL_TREE, false);
+    stream_write_tree_ref (ob, NULL_TREE);
 }
 
 
@@ -671,13 +668,12 @@  write_ts_decl_with_vis_tree_pointers (struct output_block *ob, tree expr,
    pointer fields.  */
 
 static void
-write_ts_field_decl_tree_pointers (struct output_block *ob, tree expr,
-				   bool ref_p)
+write_ts_field_decl_tree_pointers (struct output_block *ob, tree expr)
 {
-  stream_write_tree (ob, DECL_FIELD_OFFSET (expr), ref_p);
-  stream_write_tree (ob, DECL_BIT_FIELD_TYPE (expr), ref_p);
-  stream_write_tree (ob, DECL_BIT_FIELD_REPRESENTATIVE (expr), ref_p);
-  stream_write_tree (ob, DECL_FIELD_BIT_OFFSET (expr), ref_p);
+  stream_write_tree_ref (ob, DECL_FIELD_OFFSET (expr));
+  stream_write_tree_ref (ob, DECL_BIT_FIELD_TYPE (expr));
+  stream_write_tree_ref (ob, DECL_BIT_FIELD_REPRESENTATIVE (expr));
+  stream_write_tree_ref (ob, DECL_FIELD_BIT_OFFSET (expr));
 }
 
 
@@ -686,15 +682,14 @@  write_ts_field_decl_tree_pointers (struct output_block *ob, tree expr,
    pointer fields.  */
 
 static void
-write_ts_function_decl_tree_pointers (struct output_block *ob, tree expr,
-				      bool ref_p)
+write_ts_function_decl_tree_pointers (struct output_block *ob, tree expr)
 {
   /* DECL_STRUCT_FUNCTION is handled by lto_output_function.  */
-  stream_write_tree (ob, DECL_FUNCTION_PERSONALITY (expr), ref_p);
+  stream_write_tree_ref (ob, DECL_FUNCTION_PERSONALITY (expr));
   /* Don't stream these when passing things to a different target.  */
   if (!lto_stream_offload_p)
-    stream_write_tree (ob, DECL_FUNCTION_SPECIFIC_TARGET (expr), ref_p);
-  stream_write_tree (ob, DECL_FUNCTION_SPECIFIC_OPTIMIZATION (expr), ref_p);
+    stream_write_tree_ref (ob, DECL_FUNCTION_SPECIFIC_TARGET (expr));
+  stream_write_tree_ref (ob, DECL_FUNCTION_SPECIFIC_OPTIMIZATION (expr));
 }
 
 
@@ -703,19 +698,18 @@  write_ts_function_decl_tree_pointers (struct output_block *ob, tree expr,
    pointer fields.  */
 
 static void
-write_ts_type_common_tree_pointers (struct output_block *ob, tree expr,
-				    bool ref_p)
+write_ts_type_common_tree_pointers (struct output_block *ob, tree expr)
 {
-  stream_write_tree (ob, TYPE_SIZE (expr), ref_p);
-  stream_write_tree (ob, TYPE_SIZE_UNIT (expr), ref_p);
-  stream_write_tree (ob, TYPE_ATTRIBUTES (expr), ref_p);
-  stream_write_tree (ob, TYPE_NAME (expr), ref_p);
+  stream_write_tree_ref (ob, TYPE_SIZE (expr));
+  stream_write_tree_ref (ob, TYPE_SIZE_UNIT (expr));
+  stream_write_tree_ref (ob, TYPE_ATTRIBUTES (expr));
+  stream_write_tree_ref (ob, TYPE_NAME (expr));
   /* Do not stream TYPE_POINTER_TO or TYPE_REFERENCE_TO.  They will be
      reconstructed during fixup.  */
   /* Do not stream TYPE_NEXT_VARIANT, we reconstruct the variant lists
      during fixup.  */
-  stream_write_tree (ob, TYPE_MAIN_VARIANT (expr), ref_p);
-  stream_write_tree (ob, TYPE_CONTEXT (expr), ref_p);
+  stream_write_tree_ref (ob, TYPE_MAIN_VARIANT (expr));
+  stream_write_tree_ref (ob, TYPE_CONTEXT (expr));
   /* TYPE_CANONICAL is re-computed during type merging, so no need
      to stream it here.  */
   /* Do not stream TYPE_STUB_DECL; it is not needed by LTO but currently
@@ -728,22 +722,21 @@  write_ts_type_common_tree_pointers (struct output_block *ob, tree expr,
    pointer fields.  */
 
 static void
-write_ts_type_non_common_tree_pointers (struct output_block *ob, tree expr,
-					bool ref_p)
+write_ts_type_non_common_tree_pointers (struct output_block *ob, tree expr)
 {
   if (TREE_CODE (expr) == ENUMERAL_TYPE)
-    stream_write_tree (ob, TYPE_VALUES (expr), ref_p);
+    stream_write_tree_ref (ob, TYPE_VALUES (expr));
   else if (TREE_CODE (expr) == ARRAY_TYPE)
-    stream_write_tree (ob, TYPE_DOMAIN (expr), ref_p);
+    stream_write_tree_ref (ob, TYPE_DOMAIN (expr));
   else if (RECORD_OR_UNION_TYPE_P (expr))
-    streamer_write_chain (ob, TYPE_FIELDS (expr), ref_p);
+    streamer_write_chain (ob, TYPE_FIELDS (expr));
   else if (TREE_CODE (expr) == FUNCTION_TYPE
 	   || TREE_CODE (expr) == METHOD_TYPE)
-    stream_write_tree (ob, TYPE_ARG_TYPES (expr), ref_p);
+    stream_write_tree_ref (ob, TYPE_ARG_TYPES (expr));
 
   if (!POINTER_TYPE_P (expr))
-    stream_write_tree (ob, TYPE_MIN_VALUE_RAW (expr), ref_p);
-  stream_write_tree (ob, TYPE_MAX_VALUE_RAW (expr), ref_p);
+    stream_write_tree_ref (ob, TYPE_MIN_VALUE_RAW (expr));
+  stream_write_tree_ref (ob, TYPE_MAX_VALUE_RAW (expr));
 }
 
 
@@ -752,11 +745,11 @@  write_ts_type_non_common_tree_pointers (struct output_block *ob, tree expr,
    fields.  */
 
 static void
-write_ts_list_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
+write_ts_list_tree_pointers (struct output_block *ob, tree expr)
 {
-  stream_write_tree (ob, TREE_PURPOSE (expr), ref_p);
-  stream_write_tree (ob, TREE_VALUE (expr), ref_p);
-  stream_write_tree (ob, TREE_CHAIN (expr), ref_p);
+  stream_write_tree_ref (ob, TREE_PURPOSE (expr));
+  stream_write_tree_ref (ob, TREE_VALUE (expr));
+  stream_write_tree_ref (ob, TREE_CHAIN (expr));
 }
 
 
@@ -765,14 +758,14 @@  write_ts_list_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
    fields.  */
 
 static void
-write_ts_vec_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
+write_ts_vec_tree_pointers (struct output_block *ob, tree expr)
 {
   int i;
 
   /* Note that the number of slots for EXPR has already been emitted
      in EXPR's header (see streamer_write_tree_header).  */
   for (i = 0; i < TREE_VEC_LENGTH (expr); i++)
-    stream_write_tree (ob, TREE_VEC_ELT (expr, i), ref_p);
+    stream_write_tree_ref (ob, TREE_VEC_ELT (expr, i));
 }
 
 
@@ -781,13 +774,13 @@  write_ts_vec_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
    fields.  */
 
 static void
-write_ts_exp_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
+write_ts_exp_tree_pointers (struct output_block *ob, tree expr)
 {
   int i;
 
   for (i = 0; i < TREE_OPERAND_LENGTH (expr); i++)
-    stream_write_tree (ob, TREE_OPERAND (expr, i), ref_p);
-  stream_write_tree (ob, TREE_BLOCK (expr), ref_p);
+    stream_write_tree_ref (ob, TREE_OPERAND (expr, i));
+  stream_write_tree_ref (ob, TREE_BLOCK (expr));
 }
 
 
@@ -796,12 +789,12 @@  write_ts_exp_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
    fields.  */
 
 static void
-write_ts_block_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
+write_ts_block_tree_pointers (struct output_block *ob, tree expr)
 {
-  streamer_write_chain (ob, BLOCK_VARS (expr), ref_p);
+  streamer_write_chain (ob, BLOCK_VARS (expr));
 
-  stream_write_tree (ob, BLOCK_SUPERCONTEXT (expr), ref_p);
-  stream_write_tree (ob, BLOCK_ABSTRACT_ORIGIN (expr), ref_p);
+  stream_write_tree_ref (ob, BLOCK_SUPERCONTEXT (expr));
+  stream_write_tree_ref (ob, BLOCK_ABSTRACT_ORIGIN (expr));
 
   /* Do not stream BLOCK_NONLOCALIZED_VARS.  We cannot handle debug information
      for early inlined BLOCKs so drop it on the floor instead of ICEing in
@@ -820,7 +813,7 @@  write_ts_block_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
    fields.  */
 
 static void
-write_ts_binfo_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
+write_ts_binfo_tree_pointers (struct output_block *ob, tree expr)
 {
   unsigned i;
   tree t;
@@ -829,11 +822,11 @@  write_ts_binfo_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
      EXPR's header (see streamer_write_tree_header) because this length
      is needed to build the empty BINFO node on the reader side.  */
   FOR_EACH_VEC_ELT (*BINFO_BASE_BINFOS (expr), i, t)
-    stream_write_tree (ob, t, ref_p);
-  stream_write_tree (ob, NULL_TREE, false);
+    stream_write_tree_ref (ob, t);
+  stream_write_tree_ref (ob, NULL_TREE);
 
-  stream_write_tree (ob, BINFO_OFFSET (expr), ref_p);
-  stream_write_tree (ob, BINFO_VTABLE (expr), ref_p);
+  stream_write_tree_ref (ob, BINFO_OFFSET (expr));
+  stream_write_tree_ref (ob, BINFO_VTABLE (expr));
 
   /* Do not walk BINFO_INHERITANCE_CHAIN, BINFO_SUBVTT_INDEX,
      BINFO_BASE_ACCESSES and BINFO_VPTR_INDEX; these are used by C++ FE only.  */
@@ -845,16 +838,15 @@  write_ts_binfo_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
    pointer fields.  */
 
 static void
-write_ts_constructor_tree_pointers (struct output_block *ob, tree expr,
-				    bool ref_p)
+write_ts_constructor_tree_pointers (struct output_block *ob, tree expr)
 {
   unsigned i;
   tree index, value;
 
   FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (expr), i, index, value)
     {
-      stream_write_tree (ob, index, ref_p);
-      stream_write_tree (ob, value, ref_p);
+      stream_write_tree_ref (ob, index);
+      stream_write_tree_ref (ob, value);
     }
 }
 
@@ -864,12 +856,11 @@  write_ts_constructor_tree_pointers (struct output_block *ob, tree expr,
    pointer fields.  */
 
 static void
-write_ts_omp_clause_tree_pointers (struct output_block *ob, tree expr,
-				   bool ref_p)
+write_ts_omp_clause_tree_pointers (struct output_block *ob, tree expr)
 {
   int i;
   for (i = 0; i < omp_clause_num_ops[OMP_CLAUSE_CODE (expr)]; i++)
-    stream_write_tree (ob, OMP_CLAUSE_OPERAND (expr, i), ref_p);
+    stream_write_tree_ref (ob, OMP_CLAUSE_OPERAND (expr, i));
   switch (OMP_CLAUSE_CODE (expr))
     {
     case OMP_CLAUSE_REDUCTION:
@@ -883,7 +874,7 @@  write_ts_omp_clause_tree_pointers (struct output_block *ob, tree expr,
     default:
       break;
     }
-  stream_write_tree (ob, OMP_CLAUSE_CHAIN (expr), ref_p);
+  stream_write_tree_ref (ob, OMP_CLAUSE_CHAIN (expr));
 }
 
 
@@ -891,7 +882,7 @@  write_ts_omp_clause_tree_pointers (struct output_block *ob, tree expr,
    the leaves of EXPR are emitted as references.  */
 
 void
-streamer_write_tree_body (struct output_block *ob, tree expr, bool ref_p)
+streamer_write_tree_body (struct output_block *ob, tree expr)
 {
   enum tree_code code;
 
@@ -900,61 +891,61 @@  streamer_write_tree_body (struct output_block *ob, tree expr, bool ref_p)
   code = TREE_CODE (expr);
 
   if (CODE_CONTAINS_STRUCT (code, TS_TYPED))
-    write_ts_common_tree_pointers (ob, expr, ref_p);
+    write_ts_common_tree_pointers (ob, expr);
 
   if (CODE_CONTAINS_STRUCT (code, TS_VECTOR))
-    write_ts_vector_tree_pointers (ob, expr, ref_p);
+    write_ts_vector_tree_pointers (ob, expr);
 
   if (CODE_CONTAINS_STRUCT (code, TS_POLY_INT_CST))
-    write_ts_poly_tree_pointers (ob, expr, ref_p);
+    write_ts_poly_tree_pointers (ob, expr);
 
   if (CODE_CONTAINS_STRUCT (code, TS_COMPLEX))
-    write_ts_complex_tree_pointers (ob, expr, ref_p);
+    write_ts_complex_tree_pointers (ob, expr);
 
   if (CODE_CONTAINS_STRUCT (code, TS_DECL_MINIMAL))
-    write_ts_decl_minimal_tree_pointers (ob, expr, ref_p);
+    write_ts_decl_minimal_tree_pointers (ob, expr);
 
   if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
-    write_ts_decl_common_tree_pointers (ob, expr, ref_p);
+    write_ts_decl_common_tree_pointers (ob, expr);
 
   if (CODE_CONTAINS_STRUCT (code, TS_DECL_NON_COMMON))
-    write_ts_decl_non_common_tree_pointers (ob, expr, ref_p);
+    write_ts_decl_non_common_tree_pointers (ob, expr);
 
   if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
-    write_ts_decl_with_vis_tree_pointers (ob, expr, ref_p);
+    write_ts_decl_with_vis_tree_pointers (ob, expr);
 
   if (CODE_CONTAINS_STRUCT (code, TS_FIELD_DECL))
-    write_ts_field_decl_tree_pointers (ob, expr, ref_p);
+    write_ts_field_decl_tree_pointers (ob, expr);
 
   if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL))
-    write_ts_function_decl_tree_pointers (ob, expr, ref_p);
+    write_ts_function_decl_tree_pointers (ob, expr);
 
   if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON))
-    write_ts_type_common_tree_pointers (ob, expr, ref_p);
+    write_ts_type_common_tree_pointers (ob, expr);
 
   if (CODE_CONTAINS_STRUCT (code, TS_TYPE_NON_COMMON))
-    write_ts_type_non_common_tree_pointers (ob, expr, ref_p);
+    write_ts_type_non_common_tree_pointers (ob, expr);
 
   if (CODE_CONTAINS_STRUCT (code, TS_LIST))
-    write_ts_list_tree_pointers (ob, expr, ref_p);
+    write_ts_list_tree_pointers (ob, expr);
 
   if (CODE_CONTAINS_STRUCT (code, TS_VEC))
-    write_ts_vec_tree_pointers (ob, expr, ref_p);
+    write_ts_vec_tree_pointers (ob, expr);
 
   if (CODE_CONTAINS_STRUCT (code, TS_EXP))
-    write_ts_exp_tree_pointers (ob, expr, ref_p);
+    write_ts_exp_tree_pointers (ob, expr);
 
   if (CODE_CONTAINS_STRUCT (code, TS_BLOCK))
-    write_ts_block_tree_pointers (ob, expr, ref_p);
+    write_ts_block_tree_pointers (ob, expr);
 
   if (CODE_CONTAINS_STRUCT (code, TS_BINFO))
-    write_ts_binfo_tree_pointers (ob, expr, ref_p);
+    write_ts_binfo_tree_pointers (ob, expr);
 
   if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR))
-    write_ts_constructor_tree_pointers (ob, expr, ref_p);
+    write_ts_constructor_tree_pointers (ob, expr);
 
   if (code == OMP_CLAUSE)
-    write_ts_omp_clause_tree_pointers (ob, expr, ref_p);
+    write_ts_omp_clause_tree_pointers (ob, expr);
 }
 
 
@@ -1021,7 +1012,7 @@  streamer_write_tree_header (struct output_block *ob, tree expr)
    CST's type will be emitted as a reference.  */
 
 void
-streamer_write_integer_cst (struct output_block *ob, tree cst, bool ref_p)
+streamer_write_integer_cst (struct output_block *ob, tree cst)
 {
   int i;
   int len = TREE_INT_CST_NUNITS (cst);
@@ -1033,7 +1024,7 @@  streamer_write_integer_cst (struct output_block *ob, tree cst, bool ref_p)
       fprintf (streamer_dump_file, "\n");
     }
   streamer_write_record_start (ob, LTO_integer_cst);
-  stream_write_tree (ob, TREE_TYPE (cst), ref_p);
+  stream_write_tree_ref (ob, TREE_TYPE (cst));
   /* We're effectively streaming a non-sign-extended wide_int here,
      so there's no need to stream TREE_INT_CST_EXT_NUNITS or any
      array members beyond LEN.  We'll recreate the tree from the
diff --git a/gcc/tree-streamer.h b/gcc/tree-streamer.h
index 7e239e03d60..d40724237a1 100644
--- a/gcc/tree-streamer.h
+++ b/gcc/tree-streamer.h
@@ -59,7 +59,6 @@  struct streamer_tree_cache_d
 
 /* In tree-streamer-in.c.  */
 tree streamer_read_string_cst (class data_in *, class lto_input_block *);
-tree streamer_read_chain (class lto_input_block *, class data_in *);
 tree streamer_alloc_tree (class lto_input_block *, class data_in *,
 		          enum LTO_tags);
 void streamer_read_tree_body (class lto_input_block *, class data_in *, tree);
@@ -70,11 +69,10 @@  void streamer_read_tree_bitfields (class lto_input_block *,
 /* In tree-streamer-out.c.  */
 void streamer_write_string_cst (struct output_block *,
 				struct lto_output_stream *, tree);
-void streamer_write_chain (struct output_block *, tree, bool);
 void streamer_write_tree_header (struct output_block *, tree);
 void streamer_write_tree_bitfields (struct output_block *, tree);
-void streamer_write_tree_body (struct output_block *, tree, bool);
-void streamer_write_integer_cst (struct output_block *, tree, bool);
+void streamer_write_tree_body (struct output_block *, tree);
+void streamer_write_integer_cst (struct output_block *, tree);
 
 /* In tree-streamer.c.  */
 extern unsigned char streamer_mode_table[1 << 8];