+ aggvals = ipa_get_agg_replacements_for_node (node);
+ encoder = ob->decl_state->symtab_node_encoder;
+ node_ref = lto_symtab_encoder_encode (encoder, (symtab_node) node);
+ streamer_write_uhwi (ob, node_ref);
+
+ for (av = aggvals; av; av = av->next)
+ count++;
+ streamer_write_uhwi (ob, count);
+
+ for (av = aggvals; av; av = av->next)
+ {
+ streamer_write_uhwi (ob, av->offset);
+ streamer_write_uhwi (ob, av->index);
+ stream_write_tree (ob, av->value, true);
+ }
+}
+
+/* Stream in the aggregate value replacement chain for NODE from IB. */
+
+static void
+read_agg_replacement_chain (struct lto_input_block *ib,
+ struct cgraph_node *node,
+ struct data_in *data_in)
+{
+ struct ipa_agg_replacement_value *aggvals = NULL;
+ unsigned int count, i;
+
+ count = streamer_read_uhwi (ib);
+ for (i = 0; i <count; i++)
+ {
+ struct ipa_agg_replacement_value *av;
+
+ av = ggc_alloc_ipa_agg_replacement_value ();
+ av->offset = streamer_read_uhwi (ib);
+ av->index = streamer_read_uhwi (ib);
+ av->value = stream_read_tree (ib, data_in);
+ av->next = aggvals;
+ aggvals = av;
+ }
+ ipa_set_node_agg_value_chain (node, aggvals);
+}
+
+/* Write all aggregate replacement for nodes in set. */
+
+void
+ipa_prop_write_all_agg_replacement (void)
+{
+ struct cgraph_node *node;
+ struct output_block *ob;
+ unsigned int count = 0;
+ lto_symtab_encoder_iterator lsei;
+ lto_symtab_encoder_t encoder;
+
+ if (!ipa_node_agg_replacements)
+ return;
+
+ ob = create_output_block (LTO_section_ipcp_transform);
+ encoder = ob->decl_state->symtab_node_encoder;
+ ob->cgraph_node = NULL;
+ for (lsei = lsei_start_function_in_partition (encoder); !lsei_end_p (lsei);
+ lsei_next_function_in_partition (&lsei))
+ {
+ node = lsei_cgraph_node (lsei);
+ if (cgraph_function_with_gimple_body_p (node)
+ && ipa_get_agg_replacements_for_node (node) != NULL)
+ count++;
+ }
+
+ streamer_write_uhwi (ob, count);
+
+ for (lsei = lsei_start_function_in_partition (encoder); !lsei_end_p (lsei);
+ lsei_next_function_in_partition (&lsei))
+ {
+ node = lsei_cgraph_node (lsei);
+ if (cgraph_function_with_gimple_body_p (node)
+ && ipa_get_agg_replacements_for_node (node) != NULL)
+ write_agg_replacement_chain (ob, node);
+ }
+ streamer_write_char_stream (ob->main_stream, 0);
+ produce_asm (ob, NULL);
+ destroy_output_block (ob);
+}
+
+/* Read replacements section in file FILE_DATA of length LEN with data
+ DATA. */
+
+static void
+read_replacements_section (struct lto_file_decl_data *file_data,
+ const char *data,
+ size_t len)
+{
+ const struct lto_function_header *header =
+ (const struct lto_function_header *) data;
+ const int cfg_offset = sizeof (struct lto_function_header);
+ const int main_offset = cfg_offset + header->cfg_size;
+ const int string_offset = main_offset + header->main_size;
+ struct data_in *data_in;
+ struct lto_input_block ib_main;
+ unsigned int i;
+ unsigned int count;
+
+ LTO_INIT_INPUT_BLOCK (ib_main, (const char *) data + main_offset, 0,
+ header->main_size);
+
+ data_in = lto_data_in_create (file_data, (const char *) data + string_offset,
+ header->string_size, vNULL);
+ count = streamer_read_uhwi (&ib_main);
+
+ for (i = 0; i < count; i++)
+ {
+ unsigned int index;
+ struct cgraph_node *node;
+ lto_symtab_encoder_t encoder;
+
+ index = streamer_read_uhwi (&ib_main);
+ encoder = file_data->symtab_node_encoder;
+ node = cgraph (lto_symtab_encoder_deref (encoder, index));
+ gcc_assert (node->analyzed);
+ read_agg_replacement_chain (&ib_main, node, data_in);
+ }
+ lto_free_section_data (file_data, LTO_section_jump_functions, NULL, data,
+ len);
+ lto_data_in_delete (data_in);
+}
+
+/* Read IPA-CP aggregate replacements. */
+
+void
+ipa_prop_read_all_agg_replacement (void)
+{
+ struct lto_file_decl_data **file_data_vec = lto_get_file_decl_data ();
+ struct lto_file_decl_data *file_data;
+ unsigned int j = 0;
+
+ while ((file_data = file_data_vec[j++]))
+ {
+ size_t len;
+ const char *data = lto_get_section_data (file_data,
+ LTO_section_ipcp_transform,
+ NULL, &len);
+ if (data)
+ read_replacements_section (file_data, data, len);
+ }
+}
+
+/* Adjust the aggregate replacements in AGGVAL to reflect parameters skipped in
+ NODE. */
+
+static void
+adjust_agg_replacement_values (struct cgraph_node *node,
+ struct ipa_agg_replacement_value *aggval)
+{
+ struct ipa_agg_replacement_value *v;
+ int i, c = 0, d = 0, *adj;
+
+ if (!node->clone.combined_args_to_skip)
+ return;
+
+ for (v = aggval; v; v = v->next)
+ {
+ gcc_assert (v->index >= 0);
+ if (c < v->index)
+ c = v->index;
+ }
+ c++;
+
+ adj = XALLOCAVEC (int, c);
+ for (i = 0; i < c; i++)
+ if (bitmap_bit_p (node->clone.combined_args_to_skip, i))
+ {
+ adj[i] = -1;
+ d++;
+ }
+ else
+ adj[i] = i - d;
+
+ for (v = aggval; v; v = v->next)
+ v->index = adj[v->index];