From 66576e1bc7e407f69d09c2b85b69d65b70df4643 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Thu, 20 May 2010 01:55:38 +0200 Subject: ipareference2_0.c: New file. * gcc.dg/lto/ipareference2_0.c: New file. * gcc.dg/lto/ipareference2_1.c: New file. * lto.c (promote_var, promote_fn): New functions. (lto_promote_cross_file_statics): Compute correctly boundary including static initializers of readonly vars. From-SVN: r159604 --- gcc/lto/ChangeLog | 8 +++- gcc/lto/lto.c | 123 ++++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 109 insertions(+), 22 deletions(-) (limited to 'gcc/lto') diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index b26268a..492cd61 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,6 +1,12 @@ +2010-05-20 Jan Hubicka + + * lto.c (promote_var, promote_fn): New functions. + (lto_promote_cross_file_statics): Compute correctly boundary including + static initializers of readonly vars. + 2010-05-18 Jan Hubicka - * lto/lto.c (lto_1_to_1_map): Partition non-inline clones. + * lto.c (lto_1_to_1_map): Partition non-inline clones. (lto_promote_cross_file_statics): Deal with non-inline clones. 2010-05-18 Jan Hubicka diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c index adfeae9..92fa4dd 100644 --- a/gcc/lto/lto.c +++ b/gcc/lto/lto.c @@ -691,6 +691,42 @@ lto_add_all_inlinees (cgraph_node_set set) lto_bitmap_free (original_decls); } +/* Promote variable VNODE to be static. */ + +static bool +promote_var (struct varpool_node *vnode) +{ + if (TREE_PUBLIC (vnode->decl) || DECL_EXTERNAL (vnode->decl)) + return false; + gcc_assert (flag_wpa); + TREE_PUBLIC (vnode->decl) = 1; + DECL_VISIBILITY (vnode->decl) = VISIBILITY_HIDDEN; + return true; +} + +/* Promote function NODE to be static. */ + +static bool +promote_fn (struct cgraph_node *node) +{ + gcc_assert (flag_wpa); + if (TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl)) + return false; + TREE_PUBLIC (node->decl) = 1; + DECL_VISIBILITY (node->decl) = VISIBILITY_HIDDEN; + if (node->same_body) + { + struct cgraph_node *alias; + for (alias = node->same_body; + alias; alias = alias->next) + { + TREE_PUBLIC (alias->decl) = 1; + DECL_VISIBILITY (alias->decl) = VISIBILITY_HIDDEN; + } + } + return true; +} + /* Find out all static decls that need to be promoted to global because of cross file sharing. This function must be run in the WPA mode after all inlinees are added. */ @@ -704,6 +740,8 @@ lto_promote_cross_file_statics (void) varpool_node_set vset; cgraph_node_set_iterator csi; varpool_node_set_iterator vsi; + VEC(varpool_node_ptr, heap) *promoted_initializers = NULL; + struct pointer_set_t *inserted = pointer_set_create (); gcc_assert (flag_wpa); @@ -725,21 +763,7 @@ lto_promote_cross_file_statics (void) if (!DECL_EXTERNAL (node->decl) && (referenced_from_other_partition_p (&node->ref_list, set, vset) || reachable_from_other_partition_p (node, set))) - { - gcc_assert (flag_wpa); - TREE_PUBLIC (node->decl) = 1; - DECL_VISIBILITY (node->decl) = VISIBILITY_HIDDEN; - if (node->same_body) - { - struct cgraph_node *alias; - for (alias = node->same_body; - alias; alias = alias->next) - { - TREE_PUBLIC (alias->decl) = 1; - DECL_VISIBILITY (alias->decl) = VISIBILITY_HIDDEN; - } - } - } + promote_fn (node); } for (vsi = vsi_start (vset); !vsi_end_p (vsi); vsi_next (&vsi)) { @@ -748,16 +772,73 @@ lto_promote_cross_file_statics (void) be made global. It is sensible to keep those ltrans local to allow better optimization. */ if (!DECL_IN_CONSTANT_POOL (vnode->decl) - && !vnode->externally_visible && vnode->analyzed - && referenced_from_other_partition_p (&vnode->ref_list, set, vset)) + && !vnode->externally_visible && vnode->analyzed + && referenced_from_other_partition_p (&vnode->ref_list, + set, vset)) + promote_var (vnode); + } + + /* We export initializers of read-only var into each partition + referencing it. Folding might take declarations from the + initializers and use it; so everything referenced from the + initializers needs can be accessed from this partition after + folding. + + This means that we need to promote all variables and functions + referenced from all initializers from readonly vars referenced + from this partition that are not in this partition. + This needs to be done recursively. */ + for (vnode = varpool_nodes; vnode; vnode = vnode->next) + if ((TREE_READONLY (vnode->decl) || DECL_IN_CONSTANT_POOL (vnode->decl)) + && DECL_INITIAL (vnode->decl) + && !varpool_node_in_set_p (vnode, vset) + && referenced_from_this_partition_p (&vnode->ref_list, set, vset) + && !pointer_set_insert (inserted, vnode)) + VEC_safe_push (varpool_node_ptr, heap, promoted_initializers, vnode); + while (!VEC_empty (varpool_node_ptr, promoted_initializers)) + { + int i; + struct ipa_ref *ref; + + vnode = VEC_pop (varpool_node_ptr, promoted_initializers); + for (i = 0; ipa_ref_list_reference_iterate (&vnode->ref_list, i, ref); i++) { - gcc_assert (flag_wpa); - TREE_PUBLIC (vnode->decl) = 1; - DECL_VISIBILITY (vnode->decl) = VISIBILITY_HIDDEN; + if (ref->refered_type == IPA_REF_CGRAPH) + { + struct cgraph_node *n = ipa_ref_node (ref); + gcc_assert (!n->global.inlined_to); + if (!n->local.externally_visible + && !cgraph_node_in_set_p (n, set)) + promote_fn (n); + } + else + { + struct varpool_node *v = ipa_ref_varpool_node (ref); + if (varpool_node_in_set_p (v, vset)) + continue; + /* Constant pool references use internal labels and thus can not + be made global. It is sensible to keep those ltrans local to + allow better optimization. */ + if (DECL_IN_CONSTANT_POOL (v->decl)) + { + if (!pointer_set_insert (inserted, vnode)) + VEC_safe_push (varpool_node_ptr, heap, + promoted_initializers, v); + } + else if (!DECL_IN_CONSTANT_POOL (v->decl) + && !v->externally_visible && v->analyzed) + { + if (promote_var (v) + && DECL_INITIAL (v->decl) && TREE_READONLY (v->decl) + && !pointer_set_insert (inserted, vnode)) + VEC_safe_push (varpool_node_ptr, heap, + promoted_initializers, v); + } + } } } - } + pointer_set_destroy (inserted); } -- cgit v1.1