X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Flto-cgraph.c;h=cb87143e4ac62b2f4b610a19f96a8029d619a2b1;hp=88741f5a12adb34d813e2b13b43ce08056b48628;hb=5686a04eaa36667071c9c392ef01737fffa65e3d;hpb=f8b7e3ec43723c9f6bd4213794a33d6c57046103 diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c index 88741f5a12a..cb87143e4ac 100644 --- a/gcc/lto-cgraph.c +++ b/gcc/lto-cgraph.c @@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. If not see #include "flags.h" #include "params.h" #include "input.h" +#include "varray.h" #include "hashtab.h" #include "langhooks.h" #include "basic-block.h" @@ -46,23 +47,6 @@ along with GCC; see the file COPYING3. If not see #include "lto-streamer.h" #include "gcov-io.h" -static void output_varpool (cgraph_node_set, varpool_node_set); - -/* Cgraph streaming is organized as set of record whose type - is indicated by a tag. */ -enum LTO_cgraph_tags -{ - /* Must leave 0 for the stopper. */ - - /* Cgraph node without body available. */ - LTO_cgraph_unavail_node = 1, - /* Cgraph node with function body. */ - LTO_cgraph_analyzed_node, - /* Cgraph edges. */ - LTO_cgraph_edge, - LTO_cgraph_indirect_edge -}; - /* Create a new cgraph encoder. */ lto_cgraph_encoder_t @@ -111,7 +95,6 @@ lto_cgraph_encoder_encode (lto_cgraph_encoder_t encoder, return ref; } -#define LCC_NOT_FOUND (-1) /* Look up NODE in encoder. Return NODE's reference if it has been encoded or LCC_NOT_FOUND if it is not there. */ @@ -145,105 +128,6 @@ lto_cgraph_encoder_size (lto_cgraph_encoder_t encoder) return VEC_length (cgraph_node_ptr, encoder->nodes); } -/* Create a new varpool encoder. */ - -lto_varpool_encoder_t -lto_varpool_encoder_new (void) -{ - lto_varpool_encoder_t encoder = XCNEW (struct lto_varpool_encoder_d); - encoder->map = pointer_map_create (); - encoder->initializer = pointer_set_create (); - encoder->nodes = NULL; - return encoder; -} - - -/* Delete ENCODER and its components. */ - -void -lto_varpool_encoder_delete (lto_varpool_encoder_t encoder) -{ - VEC_free (varpool_node_ptr, heap, encoder->nodes); - pointer_map_destroy (encoder->map); - pointer_set_destroy (encoder->initializer); - free (encoder); -} - - -/* Return the existing reference number of NODE in the varpool encoder in - output block OB. Assign a new reference if this is the first time - NODE is encoded. */ - -int -lto_varpool_encoder_encode (lto_varpool_encoder_t encoder, - struct varpool_node *node) -{ - int ref; - void **slot; - - slot = pointer_map_contains (encoder->map, node); - if (!slot) - { - ref = VEC_length (varpool_node_ptr, encoder->nodes); - slot = pointer_map_insert (encoder->map, node); - *slot = (void *) (intptr_t) ref; - VEC_safe_push (varpool_node_ptr, heap, encoder->nodes, node); - } - else - ref = (int) (intptr_t) *slot; - - return ref; -} - -/* Look up NODE in encoder. Return NODE's reference if it has been encoded - or LCC_NOT_FOUND if it is not there. */ - -int -lto_varpool_encoder_lookup (lto_varpool_encoder_t encoder, - struct varpool_node *node) -{ - void **slot = pointer_map_contains (encoder->map, node); - return (slot ? (int) (intptr_t) *slot : LCC_NOT_FOUND); -} - - -/* Return the varpool node corresponding to REF using ENCODER. */ - -struct varpool_node * -lto_varpool_encoder_deref (lto_varpool_encoder_t encoder, int ref) -{ - if (ref == LCC_NOT_FOUND) - return NULL; - - return VEC_index (varpool_node_ptr, encoder->nodes, ref); -} - - -/* Return number of encoded nodes in ENCODER. */ - -static int -lto_varpool_encoder_size (lto_varpool_encoder_t encoder) -{ - return VEC_length (varpool_node_ptr, encoder->nodes); -} - -/* Return TRUE if we should encode initializer of NODE (if any). */ - -bool -lto_varpool_encoder_encode_initializer_p (lto_varpool_encoder_t encoder, - struct varpool_node *node) -{ - return pointer_set_contains (encoder->initializer, node); -} - -/* Return TRUE if we should encode initializer of NODE (if any). */ - -static void -lto_set_varpool_encoder_encode_initializer (lto_varpool_encoder_t encoder, - struct varpool_node *node) -{ - pointer_set_insert (encoder->initializer, node); -} /* Output the cgraph EDGE to OB using ENCODER. */ @@ -255,21 +139,15 @@ lto_output_edge (struct lto_simple_output_block *ob, struct cgraph_edge *edge, intptr_t ref; struct bitpack_d *bp; - if (edge->indirect_unknown_callee) - lto_output_uleb128_stream (ob->main_stream, LTO_cgraph_indirect_edge); - else - lto_output_uleb128_stream (ob->main_stream, LTO_cgraph_edge); + lto_output_uleb128_stream (ob->main_stream, LTO_cgraph_edge); ref = lto_cgraph_encoder_lookup (encoder, edge->caller); gcc_assert (ref != LCC_NOT_FOUND); lto_output_sleb128_stream (ob->main_stream, ref); - if (!edge->indirect_unknown_callee) - { - ref = lto_cgraph_encoder_lookup (encoder, edge->callee); - gcc_assert (ref != LCC_NOT_FOUND); - lto_output_sleb128_stream (ob->main_stream, ref); - } + ref = lto_cgraph_encoder_lookup (encoder, edge->callee); + gcc_assert (ref != LCC_NOT_FOUND); + lto_output_sleb128_stream (ob->main_stream, ref); lto_output_sleb128_stream (ob->main_stream, edge->count); @@ -279,58 +157,21 @@ lto_output_edge (struct lto_simple_output_block *ob, struct cgraph_edge *edge, bp_pack_value (bp, edge->inline_failed, HOST_BITS_PER_INT); bp_pack_value (bp, edge->frequency, HOST_BITS_PER_INT); bp_pack_value (bp, edge->loop_nest, 30); - bp_pack_value (bp, edge->indirect_inlining_edge, 1); + bp_pack_value (bp, edge->indirect_call, 1); bp_pack_value (bp, edge->call_stmt_cannot_inline_p, 1); bp_pack_value (bp, edge->can_throw_external, 1); - if (edge->indirect_unknown_callee) - { - int flags = edge->indirect_info->ecf_flags; - bp_pack_value (bp, (flags & ECF_CONST) != 0, 1); - bp_pack_value (bp, (flags & ECF_PURE) != 0, 1); - bp_pack_value (bp, (flags & ECF_NORETURN) != 0, 1); - bp_pack_value (bp, (flags & ECF_MALLOC) != 0, 1); - bp_pack_value (bp, (flags & ECF_NOTHROW) != 0, 1); - bp_pack_value (bp, (flags & ECF_RETURNS_TWICE) != 0, 1); - /* Flags that should not appear on indirect calls. */ - gcc_assert (!(flags & (ECF_LOOPING_CONST_OR_PURE - | ECF_MAY_BE_ALLOCA - | ECF_SIBCALL - | ECF_NOVOPS))); - } lto_output_bitpack (ob->main_stream, bp); bitpack_delete (bp); } -/* Return if LIST contain references from other partitions. */ -bool -referenced_from_other_partition_p (struct ipa_ref_list *list, cgraph_node_set set, - varpool_node_set vset) -{ - int i; - struct ipa_ref *ref; - for (i = 0; ipa_ref_list_refering_iterate (list, i, ref); i++) - { - if (ref->refering_type == IPA_REF_CGRAPH) - { - if (!cgraph_node_in_set_p (ipa_ref_refering_node (ref), set)) - return true; - } - else - { - if (!varpool_node_in_set_p (ipa_ref_refering_varpool_node (ref), - vset)) - return true; - } - } - return false; -} - /* Return true when node is reachable from other partition. */ -bool +static bool reachable_from_other_partition_p (struct cgraph_node *node, cgraph_node_set set) { struct cgraph_edge *e; + if (node->needed) + return true; if (!node->analyzed) return false; if (node->global.inlined_to) @@ -352,11 +193,11 @@ reachable_from_other_partition_p (struct cgraph_node *node, cgraph_node_set set) static void lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, lto_cgraph_encoder_t encoder, cgraph_node_set set, - varpool_node_set vset, bitmap written_decls) { unsigned int tag; struct bitpack_d *bp; + unsigned local, externally_visible, inlinable, analyzed; bool boundary_p, wrote_decl_p; intptr_t ref; bool in_other_partition = false; @@ -364,13 +205,35 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, boundary_p = !cgraph_node_in_set_p (node, set); wrote_decl_p = bitmap_bit_p (written_decls, DECL_UID (node->decl)); - if (node->analyzed && !boundary_p) - tag = LTO_cgraph_analyzed_node; - else + switch (cgraph_function_body_availability (node)) + { + case AVAIL_NOT_AVAILABLE: + tag = LTO_cgraph_unavail_node; + break; + + case AVAIL_AVAILABLE: + case AVAIL_LOCAL: + tag = LTO_cgraph_avail_node; + break; + + case AVAIL_OVERWRITABLE: + tag = LTO_cgraph_overwritable_node; + break; + + default: + gcc_unreachable (); + } + + if (boundary_p) tag = LTO_cgraph_unavail_node; lto_output_uleb128_stream (ob->main_stream, tag); + local = node->local.local; + externally_visible = node->local.externally_visible; + inlinable = node->local.inlinable; + analyzed = node->analyzed; + /* In WPA mode, we only output part of the call-graph. Also, we fake cgraph node attributes. There are two cases that we care. @@ -381,7 +244,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, Cherry-picked nodes: These are nodes we pulled from other translation units into SET during IPA-inlining. We make them as local static nodes to prevent clashes with other local statics. */ - if (boundary_p && node->analyzed) + if (boundary_p) { /* Inline clones can not be part of boundary. gcc_assert (!node->global.inlined_to); @@ -392,6 +255,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, needs a bit extra work and will be promplty done by cgraph_remove_node after reading back. */ in_other_partition = 1; + analyzed = 0; } lto_output_uleb128_stream (ob->main_stream, wrote_decl_p); @@ -403,29 +267,29 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, lto_output_sleb128_stream (ob->main_stream, node->count); bp = bitpack_create (); - bp_pack_value (bp, node->local.local, 1); - bp_pack_value (bp, node->local.externally_visible, 1); + bp_pack_value (bp, local, 1); + bp_pack_value (bp, externally_visible, 1); bp_pack_value (bp, node->local.finalized, 1); - bp_pack_value (bp, node->local.inlinable, 1); + bp_pack_value (bp, inlinable, 1); bp_pack_value (bp, node->local.disregard_inline_limits, 1); bp_pack_value (bp, node->local.redefined_extern_inline, 1); + bp_pack_value (bp, node->local.for_functions_valid, 1); bp_pack_value (bp, node->local.vtable_method, 1); bp_pack_value (bp, node->needed, 1); bp_pack_value (bp, node->address_taken, 1); bp_pack_value (bp, node->abstract_and_needed, 1); - bp_pack_value (bp, tag == LTO_cgraph_analyzed_node - && !DECL_EXTERNAL (node->decl) - && (reachable_from_other_partition_p (node, set) - || referenced_from_other_partition_p (&node->ref_list, set, vset)), 1); + bp_pack_value (bp, node->reachable, 1); + bp_pack_value (bp, analyzed && reachable_from_other_partition_p (node, set), 1); bp_pack_value (bp, node->lowered, 1); + bp_pack_value (bp, analyzed, 1); bp_pack_value (bp, in_other_partition, 1); + bp_pack_value (bp, node->process, 1); bp_pack_value (bp, node->alias, 1); bp_pack_value (bp, node->finalized_by_frontend, 1); - bp_pack_value (bp, node->frequency, 2); lto_output_bitpack (ob->main_stream, bp); bitpack_delete (bp); - if (tag == LTO_cgraph_analyzed_node) + if (tag != LTO_cgraph_unavail_node) { lto_output_sleb128_stream (ob->main_stream, node->local.inline_summary.estimated_self_stack_size); @@ -437,17 +301,29 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, node->local.inline_summary.self_time); lto_output_sleb128_stream (ob->main_stream, node->local.inline_summary.time_inlining_benefit); - if (node->global.inlined_to) - { - ref = lto_cgraph_encoder_lookup (encoder, node->global.inlined_to); - gcc_assert (ref != LCC_NOT_FOUND); - } - else - ref = LCC_NOT_FOUND; + } - lto_output_sleb128_stream (ob->main_stream, ref); + /* FIXME lto: Outputting global info is not neccesary until after + inliner was run. Global structure holds results of propagation + done by inliner. */ + lto_output_sleb128_stream (ob->main_stream, + node->global.estimated_stack_size); + lto_output_sleb128_stream (ob->main_stream, + node->global.stack_frame_offset); + if (node->global.inlined_to && !boundary_p) + { + ref = lto_cgraph_encoder_lookup (encoder, node->global.inlined_to); + gcc_assert (ref != LCC_NOT_FOUND); } + else + ref = LCC_NOT_FOUND; + lto_output_sleb128_stream (ob->main_stream, ref); + lto_output_sleb128_stream (ob->main_stream, node->global.time); + lto_output_sleb128_stream (ob->main_stream, node->global.size); + lto_output_sleb128_stream (ob->main_stream, + node->global.estimated_growth); + lto_output_uleb128_stream (ob->main_stream, node->global.inlined); if (node->same_comdat_group && !boundary_p) { ref = lto_cgraph_encoder_lookup (encoder, node->same_comdat_group); @@ -495,85 +371,6 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, lto_output_uleb128_stream (ob->main_stream, 0); } -/* Output the varpool NODE to OB. - If NODE is not in SET, then NODE is a boundary. */ - -static void -lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node *node, - cgraph_node_set set, varpool_node_set vset) -{ - bool boundary_p = !varpool_node_in_set_p (node, vset) && node->analyzed; - struct bitpack_d *bp; - struct varpool_node *alias; - int count = 0; - - lto_output_var_decl_index (ob->decl_state, ob->main_stream, node->decl); - bp = bitpack_create (); - bp_pack_value (bp, node->externally_visible, 1); - bp_pack_value (bp, node->force_output, 1); - bp_pack_value (bp, node->finalized, 1); - bp_pack_value (bp, node->alias, 1); - gcc_assert (!node->alias || !node->extra_name); - gcc_assert (node->finalized || !node->analyzed); - gcc_assert (node->needed); - /* Constant pool initializers can be de-unified into individual ltrans units. - FIXME: Alternatively at -Os we may want to avoid generating for them the local - labels and share them across LTRANS partitions. */ - if (DECL_IN_CONSTANT_POOL (node->decl)) - { - bp_pack_value (bp, 0, 1); /* used_from_other_parition. */ - bp_pack_value (bp, 0, 1); /* in_other_partition. */ - } - else - { - bp_pack_value (bp, node->analyzed - && referenced_from_other_partition_p (&node->ref_list, - set, vset), 1); - bp_pack_value (bp, boundary_p, 1); /* in_other_partition. */ - } - /* Also emit any extra name aliases. */ - for (alias = node->extra_name; alias; alias = alias->next) - count++; - bp_pack_value (bp, count != 0, 1); - lto_output_bitpack (ob->main_stream, bp); - bitpack_delete (bp); - - if (count) - { - lto_output_uleb128_stream (ob->main_stream, count); - for (alias = node->extra_name; alias; alias = alias->next) - lto_output_var_decl_index (ob->decl_state, ob->main_stream, alias->decl); - } -} - -/* Output the varpool NODE to OB. - If NODE is not in SET, then NODE is a boundary. */ - -static void -lto_output_ref (struct lto_simple_output_block *ob, struct ipa_ref *ref, - lto_cgraph_encoder_t encoder, - lto_varpool_encoder_t varpool_encoder) -{ - struct bitpack_d *bp = bitpack_create (); - bp_pack_value (bp, ref->refered_type, 1); - bp_pack_value (bp, ref->use, 2); - lto_output_bitpack (ob->main_stream, bp); - bitpack_delete (bp); - if (ref->refered_type == IPA_REF_CGRAPH) - { - int nref = lto_cgraph_encoder_lookup (encoder, ipa_ref_node (ref)); - gcc_assert (nref != LCC_NOT_FOUND); - lto_output_sleb128_stream (ob->main_stream, nref); - } - else - { - int nref = lto_varpool_encoder_lookup (varpool_encoder, - ipa_ref_varpool_node (ref)); - gcc_assert (nref != LCC_NOT_FOUND); - lto_output_sleb128_stream (ob->main_stream, nref); - } -} - /* Stream out profile_summary to OB. */ static void @@ -602,113 +399,18 @@ add_node_to (lto_cgraph_encoder_t encoder, struct cgraph_node *node) lto_cgraph_encoder_encode (encoder, node); } -/* Add all references in LIST to encoders. */ - -static void -add_references (lto_cgraph_encoder_t encoder, - lto_varpool_encoder_t varpool_encoder, - struct ipa_ref_list *list) -{ - int i; - struct ipa_ref *ref; - for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++) - if (ref->refered_type == IPA_REF_CGRAPH) - add_node_to (encoder, ipa_ref_node (ref)); - else - { - struct varpool_node *vnode = ipa_ref_varpool_node (ref); - lto_varpool_encoder_encode (varpool_encoder, vnode); - } -} - -/* Output all callees or indirect outgoing edges. EDGE must be the first such - edge. */ - -static void -output_outgoing_cgraph_edges (struct cgraph_edge *edge, - struct lto_simple_output_block *ob, - lto_cgraph_encoder_t encoder) -{ - if (!edge) - return; - - /* Output edges in backward direction, so the reconstructed callgraph match - and it is easy to associate call sites in the IPA pass summaries. */ - while (edge->next_callee) - edge = edge->next_callee; - for (; edge; edge = edge->prev_callee) - lto_output_edge (ob, edge, encoder); -} - -/* Output the part of the cgraph in SET. */ - -static void -output_refs (cgraph_node_set set, varpool_node_set vset, - lto_cgraph_encoder_t encoder, - lto_varpool_encoder_t varpool_encoder) -{ - cgraph_node_set_iterator csi; - varpool_node_set_iterator vsi; - struct lto_simple_output_block *ob; - int count; - struct ipa_ref *ref; - int i; - - ob = lto_create_simple_output_block (LTO_section_refs); - - for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi)) - { - struct cgraph_node *node = csi_node (csi); - - count = ipa_ref_list_nreferences (&node->ref_list); - if (count) - { - lto_output_uleb128_stream (ob->main_stream, count); - lto_output_uleb128_stream (ob->main_stream, - lto_cgraph_encoder_lookup (encoder, node)); - for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++) - lto_output_ref (ob, ref, encoder, varpool_encoder); - } - } - - lto_output_uleb128_stream (ob->main_stream, 0); - - for (vsi = vsi_start (vset); !vsi_end_p (vsi); vsi_next (&vsi)) - { - struct varpool_node *node = vsi_node (vsi); - - count = ipa_ref_list_nreferences (&node->ref_list); - if (count) - { - lto_output_uleb128_stream (ob->main_stream, count); - lto_output_uleb128_stream (ob->main_stream, - lto_varpool_encoder_lookup (varpool_encoder, - node)); - for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++) - lto_output_ref (ob, ref, encoder, varpool_encoder); - } - } - - lto_output_uleb128_stream (ob->main_stream, 0); - - lto_destroy_simple_output_block (ob); -} - - /* Output the part of the cgraph in SET. */ void -output_cgraph (cgraph_node_set set, varpool_node_set vset) +output_cgraph (cgraph_node_set set) { struct cgraph_node *node; struct lto_simple_output_block *ob; cgraph_node_set_iterator csi; - varpool_node_set_iterator vsi; struct cgraph_edge *edge; int i, n_nodes; bitmap written_decls; lto_cgraph_encoder_t encoder; - lto_varpool_encoder_t varpool_encoder; struct cgraph_asm_node *can; ob = lto_create_simple_output_block (LTO_section_cgraph); @@ -718,9 +420,7 @@ output_cgraph (cgraph_node_set set, varpool_node_set vset) /* An encoder for cgraph nodes should have been created by ipa_write_summaries_1. */ gcc_assert (ob->decl_state->cgraph_node_encoder); - gcc_assert (ob->decl_state->varpool_node_encoder); encoder = ob->decl_state->cgraph_node_encoder; - varpool_encoder = ob->decl_state->varpool_node_encoder; /* The FUNCTION_DECLs for which we have written a node. The first node found is written as the "original" node, the remaining nodes @@ -732,31 +432,6 @@ output_cgraph (cgraph_node_set set, varpool_node_set vset) { node = csi_node (csi); add_node_to (encoder, node); - add_references (encoder, varpool_encoder, &node->ref_list); - } - for (vsi = vsi_start (vset); !vsi_end_p (vsi); vsi_next (&vsi)) - { - struct varpool_node *vnode = vsi_node (vsi); - gcc_assert (!vnode->alias); - lto_varpool_encoder_encode (varpool_encoder, vnode); - lto_set_varpool_encoder_encode_initializer (varpool_encoder, vnode); - add_references (encoder, varpool_encoder, &vnode->ref_list); - } - /* Pickle in also the initializer of all referenced readonly variables - to help folding. Constant pool variables are not shared, so we must - pickle those too. */ - for (i = 0; i < lto_varpool_encoder_size (varpool_encoder); i++) - { - struct varpool_node *vnode = lto_varpool_encoder_deref (varpool_encoder, i); - if (DECL_INITIAL (vnode->decl) - && !lto_varpool_encoder_encode_initializer_p (varpool_encoder, - vnode) - && (DECL_IN_CONSTANT_POOL (vnode->decl) - || TREE_READONLY (vnode->decl))) - { - lto_set_varpool_encoder_encode_initializer (varpool_encoder, vnode); - add_references (encoder, varpool_encoder, &vnode->ref_list); - } } /* Go over all the nodes again to include callees that are not in @@ -783,7 +458,7 @@ output_cgraph (cgraph_node_set set, varpool_node_set vset) for (i = 0; i < n_nodes; i++) { node = lto_cgraph_encoder_deref (encoder, i); - lto_output_node (ob, node, encoder, set, vset, written_decls); + lto_output_node (ob, node, encoder, set, written_decls); } lto_bitmap_free (written_decls); @@ -792,8 +467,16 @@ output_cgraph (cgraph_node_set set, varpool_node_set vset) for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi)) { node = csi_node (csi); - output_outgoing_cgraph_edges (node->callees, ob, encoder); - output_outgoing_cgraph_edges (node->indirect_calls, ob, encoder); + if (node->callees) + { + /* Output edges in backward direction, so the reconstructed callgraph + match and it is easy to associate call sites in the IPA pass summaries. */ + edge = node->callees; + while (edge->next_callee) + edge = edge->next_callee; + for (; edge; edge = edge->prev_callee) + lto_output_edge (ob, edge, encoder); + } } lto_output_uleb128_stream (ob->main_stream, 0); @@ -811,10 +494,9 @@ output_cgraph (cgraph_node_set set, varpool_node_set vset) lto_output_uleb128_stream (ob->main_stream, 0); lto_destroy_simple_output_block (ob); - output_varpool (set, vset); - output_refs (set, vset, encoder, varpool_encoder); } + /* Overwrite the information in NODE based on FILE_DATA, TAG, FLAGS, STACK_SIZE, SELF_TIME and SELF_SIZE. This is called either to initialize NODE or to replace the values in it, for instance because the first @@ -841,8 +523,6 @@ input_overwrite_node (struct lto_file_decl_data *file_data, node->local.inline_summary.size_inlining_benefit = size_inlining_benefit; node->global.time = self_time; node->global.size = self_size; - node->global.estimated_stack_size = stack_size; - node->global.estimated_growth = INT_MIN; node->local.lto_file_data = file_data; node->local.local = bp_unpack_value (bp, 1); @@ -851,41 +531,21 @@ input_overwrite_node (struct lto_file_decl_data *file_data, node->local.inlinable = bp_unpack_value (bp, 1); node->local.disregard_inline_limits = bp_unpack_value (bp, 1); node->local.redefined_extern_inline = bp_unpack_value (bp, 1); + node->local.for_functions_valid = bp_unpack_value (bp, 1); node->local.vtable_method = bp_unpack_value (bp, 1); node->needed = bp_unpack_value (bp, 1); node->address_taken = bp_unpack_value (bp, 1); node->abstract_and_needed = bp_unpack_value (bp, 1); + node->reachable = bp_unpack_value (bp, 1); node->reachable_from_other_partition = bp_unpack_value (bp, 1); node->lowered = bp_unpack_value (bp, 1); - node->analyzed = tag == LTO_cgraph_analyzed_node; + node->analyzed = bp_unpack_value (bp, 1); node->in_other_partition = bp_unpack_value (bp, 1); + node->process = bp_unpack_value (bp, 1); node->alias = bp_unpack_value (bp, 1); node->finalized_by_frontend = bp_unpack_value (bp, 1); - node->frequency = (enum node_frequency)bp_unpack_value (bp, 2); } -/* Output the part of the cgraph in SET. */ - -static void -output_varpool (cgraph_node_set set, varpool_node_set vset) -{ - struct lto_simple_output_block *ob = lto_create_simple_output_block (LTO_section_varpool); - lto_varpool_encoder_t varpool_encoder = ob->decl_state->varpool_node_encoder; - int len = lto_varpool_encoder_size (varpool_encoder), i; - - lto_output_uleb128_stream (ob->main_stream, len); - - /* Write out the nodes. We must first output a node and then its clones, - otherwise at a time reading back the node there would be nothing to clone - from. */ - for (i = 0; i < len; i++) - { - lto_output_varpool_node (ob, lto_varpool_encoder_deref (varpool_encoder, i), - set, vset); - } - - lto_destroy_simple_output_block (ob); -} /* Read a node from input_block IB. TAG is the node's tag just read. Return the node read or overwriten. */ @@ -901,12 +561,18 @@ input_node (struct lto_file_decl_data *file_data, int stack_size = 0; unsigned decl_index; bool clone_p; + int estimated_stack_size = 0; + int stack_frame_offset = 0; int ref = LCC_NOT_FOUND, ref2 = LCC_NOT_FOUND; + int estimated_growth = 0; + int time = 0; + int size = 0; int self_time = 0; int self_size = 0; int time_inlining_benefit = 0; int size_inlining_benefit = 0; unsigned long same_body_count = 0; + bool inlined = false; clone_p = (lto_input_uleb128 (ib) != 0); @@ -923,17 +589,22 @@ input_node (struct lto_file_decl_data *file_data, node->count = lto_input_sleb128 (ib); bp = lto_input_bitpack (ib); - if (tag == LTO_cgraph_analyzed_node) + if (tag != LTO_cgraph_unavail_node) { stack_size = lto_input_sleb128 (ib); self_size = lto_input_sleb128 (ib); size_inlining_benefit = lto_input_sleb128 (ib); self_time = lto_input_sleb128 (ib); time_inlining_benefit = lto_input_sleb128 (ib); - - ref = lto_input_sleb128 (ib); } + estimated_stack_size = lto_input_sleb128 (ib); + stack_frame_offset = lto_input_sleb128 (ib); + ref = lto_input_sleb128 (ib); + time = lto_input_sleb128 (ib); + size = lto_input_sleb128 (ib); + estimated_growth = lto_input_sleb128 (ib); + inlined = lto_input_uleb128 (ib); ref2 = lto_input_sleb128 (ib); same_body_count = lto_input_uleb128 (ib); @@ -950,9 +621,17 @@ input_node (struct lto_file_decl_data *file_data, size_inlining_benefit); bitpack_delete (bp); + node->global.estimated_stack_size = estimated_stack_size; + node->global.stack_frame_offset = stack_frame_offset; + node->global.time = time; + node->global.size = size; + /* Store a reference for now, and fix up later to be a pointer. */ node->global.inlined_to = (cgraph_node_ptr) (intptr_t) ref; + node->global.estimated_growth = estimated_growth; + node->global.inlined = inlined; + /* Store a reference for now, and fix up later to be a pointer. */ node->same_comdat_group = (cgraph_node_ptr) (intptr_t) ref2; @@ -986,85 +665,12 @@ input_node (struct lto_file_decl_data *file_data, return node; } -/* Read a node from input_block IB. TAG is the node's tag just read. - Return the node read or overwriten. */ - -static struct varpool_node * -input_varpool_node (struct lto_file_decl_data *file_data, - struct lto_input_block *ib) -{ - int decl_index; - tree var_decl; - struct varpool_node *node; - struct bitpack_d *bp; - bool aliases_p; - int count; - - decl_index = lto_input_uleb128 (ib); - var_decl = lto_file_decl_data_get_var_decl (file_data, decl_index); - node = varpool_node (var_decl); - - bp = lto_input_bitpack (ib); - node->externally_visible = bp_unpack_value (bp, 1); - node->force_output = bp_unpack_value (bp, 1); - node->finalized = bp_unpack_value (bp, 1); - node->alias = bp_unpack_value (bp, 1); - node->analyzed = node->finalized; - node->used_from_other_partition = bp_unpack_value (bp, 1); - node->in_other_partition = bp_unpack_value (bp, 1); - aliases_p = bp_unpack_value (bp, 1); - if (node->finalized) - varpool_mark_needed_node (node); - bitpack_delete (bp); - if (aliases_p) - { - count = lto_input_uleb128 (ib); - for (; count > 0; count --) - { - tree decl = lto_file_decl_data_get_var_decl (file_data, - lto_input_uleb128 (ib)); - varpool_extra_name_alias (decl, var_decl); - } - } - return node; -} - -/* Read a node from input_block IB. TAG is the node's tag just read. - Return the node read or overwriten. */ -static void -input_ref (struct lto_input_block *ib, - struct cgraph_node *refering_node, - struct varpool_node *refering_varpool_node, - VEC(cgraph_node_ptr, heap) *nodes, - VEC(varpool_node_ptr, heap) *varpool_nodes) -{ - struct cgraph_node *node = NULL; - struct varpool_node *varpool_node = NULL; - struct bitpack_d *bp; - enum ipa_ref_type type; - enum ipa_ref_use use; - - bp = lto_input_bitpack (ib); - type = (enum ipa_ref_type) bp_unpack_value (bp, 1); - use = (enum ipa_ref_use) bp_unpack_value (bp, 2); - bitpack_delete (bp); - if (type == IPA_REF_CGRAPH) - node = VEC_index (cgraph_node_ptr, nodes, lto_input_sleb128 (ib)); - else - varpool_node = VEC_index (varpool_node_ptr, varpool_nodes, lto_input_sleb128 (ib)); - ipa_record_reference (refering_node, refering_varpool_node, - node, varpool_node, use, NULL); -} - -/* Read an edge from IB. NODES points to a vector of previously read nodes for - decoding caller and callee of the edge to be read. If INDIRECT is true, the - edge being read is indirect (in the sense that it has - indirect_unknown_callee set). */ +/* Read an edge from IB. NODES points to a vector of previously read + nodes for decoding caller and callee of the edge to be read. */ static void -input_edge (struct lto_input_block *ib, VEC(cgraph_node_ptr, heap) *nodes, - bool indirect) +input_edge (struct lto_input_block *ib, VEC(cgraph_node_ptr, heap) *nodes) { struct cgraph_node *caller, *callee; struct cgraph_edge *edge; @@ -1075,20 +681,14 @@ input_edge (struct lto_input_block *ib, VEC(cgraph_node_ptr, heap) *nodes, cgraph_inline_failed_t inline_failed; struct bitpack_d *bp; enum ld_plugin_symbol_resolution caller_resolution; - int ecf_flags = 0; caller = VEC_index (cgraph_node_ptr, nodes, lto_input_sleb128 (ib)); if (caller == NULL || caller->decl == NULL_TREE) internal_error ("bytecode stream: no caller found while reading edge"); - if (!indirect) - { - callee = VEC_index (cgraph_node_ptr, nodes, lto_input_sleb128 (ib)); - if (callee == NULL || callee->decl == NULL_TREE) - internal_error ("bytecode stream: no callee found while reading edge"); - } - else - callee = NULL; + callee = VEC_index (cgraph_node_ptr, nodes, lto_input_sleb128 (ib)); + if (callee == NULL || callee->decl == NULL_TREE) + internal_error ("bytecode stream: no callee found while reading edge"); count = (gcov_type) lto_input_sleb128 (ib); @@ -1106,39 +706,19 @@ input_edge (struct lto_input_block *ib, VEC(cgraph_node_ptr, heap) *nodes, || caller_resolution == LDPR_PREEMPTED_IR) return; - if (indirect) - edge = cgraph_create_indirect_edge (caller, NULL, 0, count, freq, nest); - else - edge = cgraph_create_edge (caller, callee, NULL, count, freq, nest); - - edge->indirect_inlining_edge = bp_unpack_value (bp, 1); + edge = cgraph_create_edge (caller, callee, NULL, count, freq, nest); edge->lto_stmt_uid = stmt_id; edge->inline_failed = inline_failed; + edge->indirect_call = bp_unpack_value (bp, 1); edge->call_stmt_cannot_inline_p = bp_unpack_value (bp, 1); edge->can_throw_external = bp_unpack_value (bp, 1); - if (indirect) - { - if (bp_unpack_value (bp, 1)) - ecf_flags |= ECF_CONST; - if (bp_unpack_value (bp, 1)) - ecf_flags |= ECF_PURE; - if (bp_unpack_value (bp, 1)) - ecf_flags |= ECF_NORETURN; - if (bp_unpack_value (bp, 1)) - ecf_flags |= ECF_MALLOC; - if (bp_unpack_value (bp, 1)) - ecf_flags |= ECF_NOTHROW; - if (bp_unpack_value (bp, 1)) - ecf_flags |= ECF_RETURNS_TWICE; - edge->indirect_info->ecf_flags = ecf_flags; - } bitpack_delete (bp); } /* Read a cgraph from IB using the info in FILE_DATA. */ -static VEC(cgraph_node_ptr, heap) * +static void input_cgraph_1 (struct lto_file_decl_data *file_data, struct lto_input_block *ib) { @@ -1152,9 +732,7 @@ input_cgraph_1 (struct lto_file_decl_data *file_data, while (tag) { if (tag == LTO_cgraph_edge) - input_edge (ib, nodes, false); - else if (tag == LTO_cgraph_indirect_edge) - input_edge (ib, nodes, true); + input_edge (ib, nodes); else { node = input_node (file_data, ib, tag); @@ -1198,66 +776,9 @@ input_cgraph_1 (struct lto_file_decl_data *file_data, else node->same_comdat_group = NULL; } - return nodes; -} - -/* Read a varpool from IB using the info in FILE_DATA. */ - -static VEC(varpool_node_ptr, heap) * -input_varpool_1 (struct lto_file_decl_data *file_data, - struct lto_input_block *ib) -{ - unsigned HOST_WIDE_INT len; - VEC(varpool_node_ptr, heap) *varpool = NULL; - - len = lto_input_uleb128 (ib); - while (len) - { - VEC_safe_push (varpool_node_ptr, heap, varpool, - input_varpool_node (file_data, ib)); - len--; - } - return varpool; -} - -/* Input ipa_refs. */ -static void -input_refs (struct lto_input_block *ib, - VEC(cgraph_node_ptr, heap) *nodes, - VEC(varpool_node_ptr, heap) *varpool) -{ - int count; - int idx; - while (true) - { - struct cgraph_node *node; - count = lto_input_uleb128 (ib); - if (!count) - break; - idx = lto_input_uleb128 (ib); - node = VEC_index (cgraph_node_ptr, nodes, idx); - while (count) - { - input_ref (ib, node, NULL, nodes, varpool); - count--; - } - } - while (true) - { - struct varpool_node *node; - count = lto_input_uleb128 (ib); - if (!count) - break; - node = VEC_index (varpool_node_ptr, varpool, lto_input_uleb128 (ib)); - while (count) - { - input_ref (ib, NULL, node, nodes, varpool); - count--; - } - } + VEC_free (cgraph_node_ptr, heap, nodes); } - static struct gcov_ctr_summary lto_gcov_summary; @@ -1305,30 +826,18 @@ input_cgraph (void) const char *data; size_t len; struct lto_input_block *ib; - VEC(cgraph_node_ptr, heap) *nodes; - VEC(varpool_node_ptr, heap) *varpool; ib = lto_create_simple_input_block (file_data, LTO_section_cgraph, &data, &len); input_profile_summary (ib); file_data->cgraph_node_encoder = lto_cgraph_encoder_new (); - nodes = input_cgraph_1 (file_data, ib); + input_cgraph_1 (file_data, ib); lto_destroy_simple_input_block (file_data, LTO_section_cgraph, ib, data, len); - ib = lto_create_simple_input_block (file_data, LTO_section_varpool, - &data, &len); - varpool = input_varpool_1 (file_data, ib); - lto_destroy_simple_input_block (file_data, LTO_section_varpool, - ib, data, len); - - ib = lto_create_simple_input_block (file_data, LTO_section_refs, - &data, &len); - input_refs (ib, nodes, varpool); - lto_destroy_simple_input_block (file_data, LTO_section_refs, - ib, data, len); - VEC_free (cgraph_node_ptr, heap, nodes); - VEC_free (varpool_node_ptr, heap, varpool); + /* Assume that every file read needs to be processed by LTRANS. */ + if (flag_wpa) + lto_mark_file_for_ltrans (file_data); } /* Clear out the aux field that was used to store enough state to