+
+/* True when we need optimization summary for NODE. */
+
+static int
+output_cgraph_opt_summary_p (struct cgraph_node *node,
+ cgraph_node_set set ATTRIBUTE_UNUSED)
+{
+ return (node->clone_of
+ && (node->clone.tree_map
+ || node->clone.args_to_skip
+ || node->clone.combined_args_to_skip));
+}
+
+/* Output optimization summary for EDGE to OB. */
+static void
+output_edge_opt_summary (struct output_block *ob ATTRIBUTE_UNUSED,
+ struct cgraph_edge *edge ATTRIBUTE_UNUSED)
+{
+}
+
+/* Output optimization summary for NODE to OB. */
+
+static void
+output_node_opt_summary (struct output_block *ob,
+ struct cgraph_node *node,
+ cgraph_node_set set)
+{
+ unsigned int index;
+ bitmap_iterator bi;
+ struct ipa_replace_map *map;
+ struct bitpack_d bp;
+ int i;
+ struct cgraph_edge *e;
+
+ if (node->clone.args_to_skip)
+ {
+ streamer_write_uhwi (ob, bitmap_count_bits (node->clone.args_to_skip));
+ EXECUTE_IF_SET_IN_BITMAP (node->clone.args_to_skip, 0, index, bi)
+ streamer_write_uhwi (ob, index);
+ }
+ else
+ streamer_write_uhwi (ob, 0);
+ if (node->clone.combined_args_to_skip)
+ {
+ streamer_write_uhwi (ob, bitmap_count_bits (node->clone.combined_args_to_skip));
+ EXECUTE_IF_SET_IN_BITMAP (node->clone.combined_args_to_skip, 0, index, bi)
+ streamer_write_uhwi (ob, index);
+ }
+ else
+ streamer_write_uhwi (ob, 0);
+ streamer_write_uhwi (ob, VEC_length (ipa_replace_map_p,
+ node->clone.tree_map));
+ FOR_EACH_VEC_ELT (ipa_replace_map_p, node->clone.tree_map, i, map)
+ {
+ int parm_num;
+ tree parm;
+
+ for (parm_num = 0, parm = DECL_ARGUMENTS (node->decl); parm;
+ parm = DECL_CHAIN (parm), parm_num++)
+ if (map->old_tree == parm)
+ break;
+ /* At the moment we assume all old trees to be PARM_DECLs, because we have no
+ mechanism to store function local declarations into summaries. */
+ gcc_assert (parm);
+ streamer_write_uhwi (ob, parm_num);
+ stream_write_tree (ob, map->new_tree, true);
+ bp = bitpack_create (ob->main_stream);
+ bp_pack_value (&bp, map->replace_p, 1);
+ bp_pack_value (&bp, map->ref_p, 1);
+ streamer_write_bitpack (&bp);
+ }
+
+ if (cgraph_node_in_set_p (node, set))
+ {
+ for (e = node->callees; e; e = e->next_callee)
+ output_edge_opt_summary (ob, e);
+ for (e = node->indirect_calls; e; e = e->next_callee)
+ output_edge_opt_summary (ob, e);
+ }
+}
+
+/* Output optimization summaries stored in callgraph.
+ At the moment it is the clone info structure. */
+
+static void
+output_cgraph_opt_summary (cgraph_node_set set)
+{
+ struct cgraph_node *node;
+ int i, n_nodes;
+ lto_cgraph_encoder_t encoder;
+ struct output_block *ob = create_output_block (LTO_section_cgraph_opt_sum);
+ unsigned count = 0;
+
+ ob->cgraph_node = NULL;
+ encoder = ob->decl_state->cgraph_node_encoder;
+ n_nodes = lto_cgraph_encoder_size (encoder);
+ for (i = 0; i < n_nodes; i++)
+ if (output_cgraph_opt_summary_p (lto_cgraph_encoder_deref (encoder, i),
+ set))
+ count++;
+ streamer_write_uhwi (ob, count);
+ for (i = 0; i < n_nodes; i++)
+ {
+ node = lto_cgraph_encoder_deref (encoder, i);
+ if (output_cgraph_opt_summary_p (node, set))
+ {
+ streamer_write_uhwi (ob, i);
+ output_node_opt_summary (ob, node, set);
+ }
+ }
+ produce_asm (ob, NULL);
+ destroy_output_block (ob);
+}
+
+/* Input optimisation summary of EDGE. */
+
+static void
+input_edge_opt_summary (struct cgraph_edge *edge ATTRIBUTE_UNUSED,
+ struct lto_input_block *ib_main ATTRIBUTE_UNUSED)
+{
+}
+
+/* Input optimisation summary of NODE. */
+
+static void
+input_node_opt_summary (struct cgraph_node *node,
+ struct lto_input_block *ib_main,
+ struct data_in *data_in)
+{
+ int i;
+ int count;
+ int bit;
+ struct bitpack_d bp;
+ struct cgraph_edge *e;
+
+ count = streamer_read_uhwi (ib_main);
+ if (count)
+ node->clone.args_to_skip = BITMAP_GGC_ALLOC ();
+ for (i = 0; i < count; i++)
+ {
+ bit = streamer_read_uhwi (ib_main);
+ bitmap_set_bit (node->clone.args_to_skip, bit);
+ }
+ count = streamer_read_uhwi (ib_main);
+ if (count)
+ node->clone.combined_args_to_skip = BITMAP_GGC_ALLOC ();
+ for (i = 0; i < count; i++)
+ {
+ bit = streamer_read_uhwi (ib_main);
+ bitmap_set_bit (node->clone.combined_args_to_skip, bit);
+ }
+ count = streamer_read_uhwi (ib_main);
+ for (i = 0; i < count; i++)
+ {
+ int parm_num;
+ tree parm;
+ struct ipa_replace_map *map = ggc_alloc_ipa_replace_map ();
+
+ VEC_safe_push (ipa_replace_map_p, gc, node->clone.tree_map, map);
+ for (parm_num = 0, parm = DECL_ARGUMENTS (node->decl); parm_num;
+ parm = DECL_CHAIN (parm))
+ parm_num --;
+ map->parm_num = streamer_read_uhwi (ib_main);
+ map->old_tree = NULL;
+ map->new_tree = stream_read_tree (ib_main, data_in);
+ bp = streamer_read_bitpack (ib_main);
+ map->replace_p = bp_unpack_value (&bp, 1);
+ map->ref_p = bp_unpack_value (&bp, 1);
+ }
+ for (e = node->callees; e; e = e->next_callee)
+ input_edge_opt_summary (e, ib_main);
+ for (e = node->indirect_calls; e; e = e->next_callee)
+ input_edge_opt_summary (e, ib_main);
+}
+
+/* Read section in file FILE_DATA of length LEN with data DATA. */
+
+static void
+input_cgraph_opt_section (struct lto_file_decl_data *file_data,
+ const char *data, size_t len, VEC (cgraph_node_ptr,
+ heap) * nodes)
+{
+ const struct lto_function_header *header =
+ (const struct lto_function_header *) data;
+ const int32_t cfg_offset = sizeof (struct lto_function_header);
+ const int32_t main_offset = cfg_offset + header->cfg_size;
+ const int32_t 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, NULL);
+ count = streamer_read_uhwi (&ib_main);
+
+ for (i = 0; i < count; i++)
+ {
+ int ref = streamer_read_uhwi (&ib_main);
+ input_node_opt_summary (VEC_index (cgraph_node_ptr, nodes, ref),
+ &ib_main, data_in);
+ }
+ lto_free_section_data (file_data, LTO_section_cgraph_opt_sum, NULL, data,
+ len);
+ lto_data_in_delete (data_in);
+}
+
+/* Input optimization summary of cgraph. */
+
+static void
+input_cgraph_opt_summary (VEC (cgraph_node_ptr, heap) * nodes)
+{
+ 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_cgraph_opt_sum, NULL,
+ &len);
+
+ if (data)
+ input_cgraph_opt_section (file_data, data, len, nodes);
+ }
+}