* [PATCH][LTO] Fix multiple symbol definition problem in WHOPR.
@ 2008-11-12 21:50 Doug Kwan (關振德)
2008-11-13 16:35 ` Diego Novillo
0 siblings, 1 reply; 2+ messages in thread
From: Doug Kwan (關振德) @ 2008-11-12 21:50 UTC (permalink / raw)
To: gcc-patches, Diego Novillo, Rafael Espindola
[-- Attachment #1: Type: text/plain, Size: 4285 bytes --]
Hi,
This patch fixes a problem where a symbol is defined in more than
one LTRANS output. We track the state of globals output to each
LTRANS input and write additional flags in the intializers so that a
global is only defined int the LTRANS output corresponding the the
first written LTRANS input by WPA. Additionally, we now only write
out the reachable globals to each LTRANS input, except for the last
one, where any orphaned globals are stored. We also keep track of
file-scope static variables shared by multiple LTRANS inputs and
promote them to globals. I also moved some stuff around and remove
some duplicated code involving bitmap allocation. Finally, the
found_body_in_file_p information seemed to be not needed and weas
removed.
This patch is tested on i686-unknown-linux-gnu.
-Doug
2008-11-12 Doug Kwan <dougkwan@google.com>
* cgraph.h (struct cgraph_node_set_element_def): Add AUX field.
* lto-function-out.c (lto-utils.h): Include.
(output_local_vars): New bitmap functions in lto-utils.c.
(output_var_int, output_inits_in_decl_state,
output_used_constructors_and_inits,
output_remaining_constructors_and_inits,
output_all_constructors_and_inits): New functions.
(output_constructors_and_inits): Handle WPA mode specially.
(lto_output): Do not output constructs and intis here.
(output_var_decl): Promote file-scope static to global if necessary.
* lto-function-in.c (lto-utils.h): Include.
(input_constructors_or_inits): Read LTO var flags.
* lto-header.h (lto_get_section_name): Remove prototype.
* lto-section-in.c (lto-utils.h): Include.
(bitmap.h): Remove include.
(lto_section_out_obstack, function_body_in_file_p): Remove.
(lto_mark_function_body_in_file, lto_function_body_in_file_p): Remove.
* lto-section-in.h (lto_mark_function_body_in_file,
lto_function_body_in_file_p): Remove prototype.
* lto-wpa-fixup.c (lto-utils): Include.
(wpa_fixup_obstack, wpa_fixup_obstack_initialized): Remove vars.
(bitmap_alloc): Remove function.
(lto_mark_nothrow_fndecl, output_wpa_fixup): Use bitmap functions
in lto-utils.c instead.
* lto-tree-out.h (output_constructor_and_inits): New prototype.
* varasm.c (assemble_variable): Suppress output of variable in
LTRANS mode if LTO_VAR_FLAG_SUPPRESS_OUTPUT is set for the var.
* Makefile.in (OBJS-common): Add lto-utils.o
(lto-function-in.o, lto-function-out.o, lto-section-in.o,
lto-section-out.o, lto-wpa-fixup.o, varasm.o): Add lto-utils.h
to dependencies.
* lto-utils.c (File): New.
* lto-utils.h (File): Same.
* lto-section-out.c (lto-utils.h): Include.
(function_decl_state): Renamed var to LTO_FUCNTION_DECL_STATES and
make it global.
(lto_section_out_obstack): Remove var.
(lto_new_static_inline_states, lto_delete_static_inline_states,
produce_symtab):
Use bitmap functions in lto-utils.c.
(lto_get_section_name): Move to lto-utils.c.
(record_function_out_decl_state, write_sysmbols_of_kind): Adjust for
renaming of function_decl_states.
(produce_asm_for_decls): Remove ATTRIBUTE_UNUSED annotation for SET.
Call output_constructors_and_inits. Adjust for renaming of
function_decl_states.
* lto-section-out.h (lto_function_decl_states): New extern variable.
declaration.
lto/ChangeLog
* lto.c (lto_bitmap_obstack): Remove var.
(lto_materialize_function): Do nothing instead of marking function
body in file if flag_wpa is true.
(lto_add_all_inlinees): Use bitmap functions in lto-utils.c.
(lto_scan_statics_in_cgraph_node): New function.
(lto_promote_cross_file_statics): Same.
(lto_wpa_write_files): Call lto_promote_cross_file_statics.
Use bitmap functions in lto-utils.c. Remove unsued label OUT.
* Make-lang.in (lto/lto.o): Add lto-utils.h to dependency list.
testsuite/ChangeLog
* gcc.dg/lto/20081111_0.c: New.
* gcc.dg/lto/20081111_0.c: New.
* gcc.dg/lto/20081112_1.c: New.
* gcc.dg/lto/20081112_1.c: New.
[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 42002 bytes --]
Index: gcc/gcc/cgraph.h
===================================================================
--- gcc/gcc/cgraph.h (revision 141779)
+++ gcc/gcc/cgraph.h (working copy)
@@ -340,6 +340,7 @@ struct cgraph_node_set_def GTY(())
{
htab_t GTY((param_is (struct cgraph_node_set_element_def))) hashtab;
VEC(cgraph_node_ptr, gc) *nodes;
+ PTR GTY ((skip)) aux;
};
typedef struct cgraph_node_set_def *cgraph_node_set;
Index: gcc/gcc/lto-function-out.c
===================================================================
--- gcc/gcc/lto-function-out.c (revision 141779)
+++ gcc/gcc/lto-function-out.c (working copy)
@@ -50,6 +50,7 @@ Boston, MA 02110-1301, USA. */
#include "lto-section-in.h"
#include "lto-section-out.h"
#include "lto-tree-out.h"
+#include "lto-utils.h"
sbitmap lto_flags_needed_for;
sbitmap lto_types_needed_for;
@@ -1608,7 +1609,7 @@ output_local_vars (struct output_block *
tree t;
int i = 0;
struct lto_output_stream *tmp_stream = ob->main_stream;
- bitmap local_statics = BITMAP_ALLOC (NULL);
+ bitmap local_statics = lto_bitmap_alloc ();
ob->main_stream = ob->local_decl_stream;
@@ -1655,7 +1656,7 @@ output_local_vars (struct output_block *
/* End of statics. */
output_zero (ob);
- BITMAP_FREE (local_statics);
+ lto_bitmap_free (local_statics);
/* The easiest way to get all of this stuff generated is to play
pointer games with the streams and reuse the code for putting out
@@ -2258,14 +2259,136 @@ output_function (struct cgraph_node* nod
pop_cfun ();
}
+/* Output initializer of VAR in output block OB. */
-/* Output constructor for static or external vars. */
+static void
+output_var_init (struct output_block *ob, tree var)
+{
+ lto_var_flags_t flags;
+
+ output_expr_operand (ob, var);
+ LTO_DEBUG_TOKEN ("init");
+ if (DECL_INITIAL (var))
+ output_expr_operand (ob, DECL_INITIAL (var));
+ else
+ output_zero (ob);
+
+ LTO_DEBUG_TOKEN ("flags");
+ if (flag_wpa)
+ {
+ flags = lto_get_var_flags (var);
+
+ /* Make sure we only output a global from one LTRANS file. */
+ if (TREE_PUBLIC (var)
+ || (flags & LTO_VAR_FLAG_FORCE_GLOBAL))
+ {
+ if (flags & LTO_VAR_FLAG_DEFINED)
+ flags |= LTO_VAR_FLAG_SUPPRESS_OUTPUT;
+ else
+ flags |= LTO_VAR_FLAG_DEFINED;
+ lto_set_var_flags (var, flags);
+ }
+
+ output_uleb128 (ob, flags);
+ }
+ else
+ output_zero (ob);
+}
+
+/* Output all global vars reachable from STATE to output block OB.
+ SEEN is a bitmap indexed by DECL_UID of vars to avoid multiple
+ outputs in the same file. */
+
+static void
+output_inits_in_decl_state (struct output_block *ob,
+ struct lto_out_decl_state *state,
+ bitmap seen)
+{
+ struct lto_tree_ref_encoder *encoder =
+ &state->streams[LTO_DECL_STREAM_VAR_DECL];
+ unsigned num_vars, i;
+
+ num_vars = lto_tree_ref_encoder_size (encoder);
+ for (i = 0; i < num_vars; i++)
+ {
+ tree var = lto_tree_ref_encoder_get_tree (encoder, i);
+ tree context = DECL_CONTEXT (var);
+ if (TREE_STATIC (var)
+ && (!context || TREE_CODE (context) != FUNCTION_DECL)
+ && !bitmap_bit_p (seen, DECL_UID (var)))
+ {
+ bitmap_set_bit (seen, DECL_UID (var));
+ output_var_init (ob, var);
+ }
+ }
+}
+
+/* Output used constructors for static or external vars to OB. */
+
+static void
+output_used_constructors_and_inits (struct output_block *ob)
+{
+ bitmap seen;
+ struct lto_out_decl_state *out_state = lto_get_out_decl_state ();
+ struct lto_out_decl_state *fn_out_state;
+ unsigned i, num_fns;
+
+ /* Go through all out-state to find out variable used. */
+ seen = lto_bitmap_alloc ();
+ num_fns = VEC_length (lto_out_decl_state_ptr, lto_function_decl_states);
+ output_inits_in_decl_state (ob, out_state, seen);
+ for (i = 0; i < num_fns; i++)
+ {
+ fn_out_state =
+ VEC_index (lto_out_decl_state_ptr, lto_function_decl_states, i);
+ output_inits_in_decl_state (ob, fn_out_state, seen);
+ }
+ lto_bitmap_free (seen);
+}
+
+/* Output constructors and inits of all vars in varpool that have not been
+ output so far. This is done typically in the last LTRANS input. */
+
+static void
+output_remaining_constructors_and_inits (struct output_block *ob)
+{
+ struct varpool_node *vnode;
+
+ FOR_EACH_STATIC_VARIABLE (vnode)
+ {
+ tree var = vnode->decl;
+ tree context = DECL_CONTEXT (var);
+ if (TREE_STATIC (var)
+ && (!context || TREE_CODE (context) != FUNCTION_DECL)
+ && !(lto_get_var_flags (var) & LTO_VAR_FLAG_DEFINED))
+ output_var_init (ob, var);
+ }
+}
+
+/* Output constructors and inits of all vars in varpool to output block OB. */
static void
-output_constructors_and_inits (void)
+output_all_constructors_and_inits (struct output_block *ob)
{
- struct output_block *ob = create_output_block (LTO_section_static_initializer);
struct varpool_node *vnode;
+
+ FOR_EACH_STATIC_VARIABLE (vnode)
+ {
+ tree var = vnode->decl;
+ tree context = DECL_CONTEXT (var);
+ if (!context || TREE_CODE (context) != FUNCTION_DECL)
+ output_var_init (ob, var);
+ }
+}
+
+/* Output constructors and inits of all vars. SET is the current
+ cgraph node set being output. */
+
+void
+output_constructors_and_inits (cgraph_node_set set)
+{
+ struct output_block *ob =
+ create_output_block (LTO_section_static_initializer);
unsigned i;
alias_pair *p;
@@ -2277,23 +2400,18 @@ output_constructors_and_inits (void)
/* Make string 0 be a NULL string. */
lto_output_1_stream (ob->string_stream, 0);
- /* Process the global static vars that have initializers or
- constructors. */
- FOR_EACH_STATIC_VARIABLE (vnode)
+ /* In WPA mode. Output inits and constructors of used variables. */
+ if (flag_wpa)
{
- tree var = vnode->decl;
- tree context = DECL_CONTEXT (var);
- if (!context || TREE_CODE (context) != FUNCTION_DECL)
- {
- output_expr_operand (ob, var);
-
- LTO_DEBUG_TOKEN ("init");
- if (DECL_INITIAL (var))
- output_expr_operand (ob, DECL_INITIAL (var));
- else
- output_zero (ob);
- }
+ output_used_constructors_and_inits (ob);
+
+ /* Output all remaining vars into last LTRANS file. */
+ if (set->aux)
+ output_remaining_constructors_and_inits (ob);
}
+ else
+ output_all_constructors_and_inits (ob);
+
/* The terminator for the constructor. */
output_zero (ob);
@@ -2378,7 +2496,6 @@ lto_output (cgraph_node_set set)
struct lto_out_decl_state *decl_state;
cgraph_node_set_iterator csi;
- bitmap_obstack_initialize (NULL);
lto_static_init_local ();
/* Process only the functions with bodies and only process the master
@@ -2399,9 +2516,6 @@ lto_output (cgraph_node_set set)
lto_record_function_out_decl_state (node->decl, decl_state);
}
}
-
- output_constructors_and_inits ();
- bitmap_obstack_release (NULL);
}
struct ipa_opt_pass pass_ipa_lto_gimple_out =
@@ -2694,10 +2808,26 @@ output_function_decl (struct output_bloc
static void
output_var_decl (struct output_block *ob, tree decl)
{
+ bool saved_public;
+
/* tag and flags */
/* Assume static or external variable. */
output_global_record_start (ob, NULL, NULL, LTO_var_decl1);
- output_tree_flags (ob, 0, decl, true);
+ if (flag_wpa
+ && (lto_get_var_flags (decl) & LTO_VAR_FLAG_FORCE_GLOBAL))
+ {
+ /* This variable is a file-scope static that is now shared by
+ multiple translation units owing to IPA-inlining. We promote
+ it to a global. */
+
+ gcc_assert (TREE_STATIC (decl) && !TREE_PUBLIC (decl));
+ saved_public = TREE_PUBLIC (decl);
+ TREE_PUBLIC (decl) = true;
+ output_tree_flags (ob, 0, decl, true);
+ TREE_PUBLIC (decl) = saved_public;
+ }
+ else
+ output_tree_flags (ob, 0, decl, true);
global_vector_debug (ob);
Index: gcc/gcc/lto-function-in.c
===================================================================
--- gcc/gcc/lto-function-in.c (revision 141779)
+++ gcc/gcc/lto-function-in.c (working copy)
@@ -51,6 +51,7 @@ Boston, MA 02110-1301, USA. */
#include "lto-tags.h"
#include "lto-section-in.h"
#include "lto-tree-in.h"
+#include "lto-utils.h"
#include "cpplib.h"
tree input_tree (struct lto_input_block *, struct data_in *);
@@ -2303,6 +2304,7 @@ input_constructors_or_inits (struct data
struct lto_input_block *ib)
{
enum LTO_tags tag;
+ lto_var_flags_t flags;
clear_line_info (data_in);
tag = input_record_start (ib);
@@ -2314,6 +2316,10 @@ input_constructors_or_inits (struct data
tag = input_record_start (ib);
if (tag)
DECL_INITIAL (var) = input_expr_operand (ib, data_in, NULL, tag);
+ LTO_DEBUG_TOKEN ("flags");
+ flags = lto_input_uleb128 (ib);
+ if (flags)
+ lto_set_var_flags (var, lto_get_var_flags (var) | flags);
tag = input_record_start (ib);
}
Index: gcc/gcc/testsuite/gcc.dg/lto/20081112_1.c
===================================================================
--- gcc/gcc/testsuite/gcc.dg/lto/20081112_1.c (revision 0)
+++ gcc/gcc/testsuite/gcc.dg/lto/20081112_1.c (revision 0)
@@ -0,0 +1,13 @@
+static int mumble;
+
+void
+f (void)
+{
+ mumble = 41;
+}
+
+int __attribute__((noinline))
+g (void)
+{
+ return ++mumble;
+}
Index: gcc/gcc/testsuite/gcc.dg/lto/20081111_0.c
===================================================================
--- gcc/gcc/testsuite/gcc.dg/lto/20081111_0.c (revision 0)
+++ gcc/gcc/testsuite/gcc.dg/lto/20081111_0.c (revision 0)
@@ -0,0 +1,12 @@
+/* { dg-options "-fwhopr" } */
+extern int mumble;
+extern void abort (void);
+extern void exit (int);
+
+int
+main ()
+{
+ if (++mumble != 42)
+ abort ();
+ exit (0);
+}
Index: gcc/gcc/testsuite/gcc.dg/lto/20081111_1.c
===================================================================
--- gcc/gcc/testsuite/gcc.dg/lto/20081111_1.c (revision 0)
+++ gcc/gcc/testsuite/gcc.dg/lto/20081111_1.c (revision 0)
@@ -0,0 +1,7 @@
+int mumble = 41;
+
+int
+bar (void)
+{
+ return mumble;
+}
Index: gcc/gcc/testsuite/gcc.dg/lto/20081112_0.c
===================================================================
--- gcc/gcc/testsuite/gcc.dg/lto/20081112_0.c (revision 0)
+++ gcc/gcc/testsuite/gcc.dg/lto/20081112_0.c (revision 0)
@@ -0,0 +1,15 @@
+/* { dg-options "-fwhopr -O3" } */
+extern void exit (int);
+extern void abort (void);
+
+extern void f ();
+extern int g ();
+
+int
+main ()
+{
+ f ();
+ if (g () != 42)
+ abort ();
+ exit (0);
+}
Index: gcc/gcc/lto-header.h
===================================================================
--- gcc/gcc/lto-header.h (revision 141779)
+++ gcc/gcc/lto-header.h (working copy)
@@ -76,9 +76,6 @@ typedef enum {
LTO_N_DECL_STREAMS
} lto_decl_stream_e_t;
-/* In lto-section-out.c. */
-char *lto_get_section_name (enum lto_section_type, const char *);
-
/* In lto-wpa-fixup.c */
void lto_mark_nothrow_fndecl (tree);
void lto_fixup_nothrow_decls (void);
Index: gcc/gcc/lto-section-in.c
===================================================================
--- gcc/gcc/lto-section-in.c (revision 141779)
+++ gcc/gcc/lto-section-in.c (working copy)
@@ -48,11 +48,8 @@ Boston, MA 02110-1301, USA. */
#include "output.h"
#include "lto-section.h"
#include "lto-section-in.h"
+#include "lto-utils.h"
#include "cpplib.h"
-#include "bitmap.h"
-
-static bitmap_obstack lto_section_out_obstack;
-static bitmap function_body_in_file_p;
/* Return 0 or 1 based on the last bit of FLAGS and right shift FLAGS
by 1. */
@@ -508,27 +505,6 @@ lto_get_function_in_decl_state (struct l
return slot? ((struct lto_in_decl_state*) *slot) : NULL;
}
-/* Mark FN_DECL as a function whose body is in an LTO IR file. */
-
-void lto_mark_function_body_in_file (tree fn_decl)
-{
- if (!function_body_in_file_p)
- {
- bitmap_obstack_initialize (<o_section_out_obstack);
- function_body_in_file_p = BITMAP_ALLOC (<o_section_out_obstack);
- }
- bitmap_set_bit (function_body_in_file_p, DECL_UID (fn_decl));
-}
-
-/* Return true if FN_DECL has been marked as a function whose body is
- in an LTO IR file. */
-bool lto_function_body_in_file_p (tree fn_decl)
-{
- if (function_body_in_file_p)
- return bitmap_bit_p (function_body_in_file_p, DECL_UID (fn_decl));
- else
- return false;
-}
/*****************************************************************************/
/* Stream debugging support code. */
/*****************************************************************************/
Index: gcc/gcc/lto-section-in.h
===================================================================
--- gcc/gcc/lto-section-in.h (revision 141779)
+++ gcc/gcc/lto-section-in.h (working copy)
@@ -216,7 +216,4 @@ extern struct lto_in_decl_state *
extern void lto_debug_in_fun (struct lto_debug_context *, char);
#endif
-extern void lto_mark_function_body_in_file (tree);
-extern bool lto_function_body_in_file_p (tree);
-
#endif /* GCC_LTO_SECTION_IN_H */
Index: gcc/gcc/lto-wpa-fixup.c
===================================================================
--- gcc/gcc/lto-wpa-fixup.c (revision 141779)
+++ gcc/gcc/lto-wpa-fixup.c (working copy)
@@ -37,6 +37,7 @@ Boston, MA 02110-1301, USA. */
#include "timevar.h"
#include "lto-section-in.h"
#include "lto-section-out.h"
+#include "lto-utils.h"
#include "tree-flow.h"
/* LTO fix-up.
@@ -47,28 +48,11 @@ Boston, MA 02110-1301, USA. */
LTRANS to fix up the function bodies accordingly.
*/
-static bitmap_obstack wpa_fixup_obstack;
-static bool wpa_fixup_obstack_initialized;
-
/* The vectors records function DECLs having multiple copies with different
exception throwing attributes. We do not mark a DECL if all copies of it
have the same exception throwing attribute. */
static bitmap lto_nothrow_fndecls;
-/* Helper to allocate a bitmap from heap. Initializes the local obstack
- if necessary. */
-
-static bitmap
-bitmap_alloc (void)
-{
- if (!wpa_fixup_obstack_initialized)
- {
- bitmap_obstack_initialize (&wpa_fixup_obstack);
- wpa_fixup_obstack_initialized = true;
- }
- return BITMAP_ALLOC (&wpa_fixup_obstack);
-}
-
/* We need to fix up GIMPLE bodies due to changes in exception setting.
Consider this example:
@@ -142,7 +126,7 @@ lto_mark_nothrow_fndecl (tree fndecl)
{
gcc_assert (TREE_CODE (fndecl) == FUNCTION_DECL);
if (!lto_nothrow_fndecls)
- lto_nothrow_fndecls = bitmap_alloc ();
+ lto_nothrow_fndecls = lto_bitmap_alloc ();
bitmap_set_bit (lto_nothrow_fndecls, DECL_UID (fndecl));
}
@@ -167,7 +151,7 @@ output_wpa_fixup (cgraph_node_set set)
duplicates, we need to use a bitmap and a vector to save the
DECLs we want. Note that we need to check if lto_nothrow_fndecls
is NULL. This happens when no DECL has been marked. */
- seen_decls = bitmap_alloc ();
+ seen_decls = lto_bitmap_alloc ();
if (lto_nothrow_fndecls)
for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
{
@@ -192,7 +176,7 @@ output_wpa_fixup (cgraph_node_set set)
/* Release resources. */
lto_destroy_simple_output_block (ob);
VEC_free(tree, heap, decls);
- BITMAP_FREE (seen_decls);
+ lto_bitmap_free (seen_decls);
}
/* Read in WPA fix-up information from one file. FILE_DATA points to
Index: gcc/gcc/lto-tree-out.h
===================================================================
--- gcc/gcc/lto-tree-out.h (revision 141779)
+++ gcc/gcc/lto-tree-out.h (working copy)
@@ -110,6 +110,7 @@ struct output_block
struct output_block *create_output_block (enum lto_section_type);
void destroy_output_block (struct output_block *);
+extern void output_constructors_and_inits (struct cgraph_node_set_def *);
extern void output_tree (struct output_block *, tree);
#endif /* GCC_LTO_TREE_OUT_H */
Index: gcc/gcc/lto/lto.c
===================================================================
--- gcc/gcc/lto/lto.c (revision 141779)
+++ gcc/gcc/lto/lto.c (working copy)
@@ -40,6 +40,7 @@ Boston, MA 02110-1301, USA. */
#include "lto-section-out.h"
#include "lto-tree-in.h"
#include "lto-tags.h"
+#include "lto-utils.h"
#include "vec.h"
#include "bitmap.h"
#include "pointer-set.h"
@@ -51,8 +52,6 @@ Boston, MA 02110-1301, USA. */
will not be declared. */
#include <sys/mman.h>
-static bitmap_obstack lto_bitmap_obstack;
-
DEF_VEC_P(bitmap);
DEF_VEC_ALLOC_P(bitmap,heap);
@@ -97,9 +96,7 @@ lto_materialize_function (struct cgraph_
allocate_struct_function (decl, false);
- if (flag_wpa)
- lto_mark_function_body_in_file (decl);
- else
+ if (!flag_wpa)
lto_input_function_body (file_data, decl, data);
fn = DECL_STRUCT_FUNCTION (decl);
@@ -581,8 +578,8 @@ lto_add_all_inlinees (cgraph_node_set se
{
cgraph_node_set_iterator csi;
struct cgraph_node *node;
- bitmap original_nodes = BITMAP_ALLOC (<o_bitmap_obstack);
- bitmap inlined_decls = BITMAP_ALLOC (<o_bitmap_obstack);
+ bitmap original_nodes = lto_bitmap_alloc ();
+ bitmap inlined_decls = lto_bitmap_alloc();
/* We are going to iterate SET will adding to it, mark all original
nodes so that we only add node inlined to original nodes. */
@@ -596,10 +593,118 @@ lto_add_all_inlinees (cgraph_node_set se
lto_add_inline_clones (set, node, original_nodes, inlined_decls);
}
- BITMAP_FREE (original_nodes);
+ lto_bitmap_free (original_nodes);
return inlined_decls;
}
+/* Owing to inlining, we may need to promote a file-scope variable
+ to a global variable. Consider this case:
+
+ a.c:
+ static int var;
+
+ void
+ foo (void)
+ {
+ var++;
+ }
+
+ b.c:
+
+ extern void foo (void);
+
+ void
+ bar (void)
+ {
+ foo ();
+ }
+
+ If WPA inlines FOO inside BAR, then the static variable VAR needs to
+ be promoted to global because BAR and VAR may be in different LTRANS
+ files. */
+
+/* Promote file-scope variable reachable from NODE if necessary to global.
+ GLOBAL_VARS is a bitmap of file-scope variables output so far in all
+ LTRANS files. SEEN_FUNCS is a bitmap of seen functions in the current
+ LTRANS file, and SEEN_VARS is a bitmap of seen file-scope variable
+ in the current LTRANS file. All bitmaps are indexed by DECL_UID. */
+
+static void
+lto_scan_statics_in_cgraph_node (struct cgraph_node *node,
+ bitmap global_vars,
+ bitmap seen_funcs,
+ bitmap seen_vars)
+{
+ struct lto_in_decl_state *state;
+ tree var;
+ struct lto_tree_ref_table *var_table;
+ unsigned i;
+ lto_var_flags_t flags;
+
+ /* Return if node has no function body. */
+ if (!node->analyzed)
+ return;
+
+ /* We use a bitmap to avoid repeated scanning. */
+ if (bitmap_bit_p (seen_funcs, DECL_UID (node->decl)))
+ return;
+ bitmap_set_bit (seen_funcs, DECL_UID (node->decl));
+
+ state = lto_get_function_in_decl_state (node->local.lto_file_data,
+ node->decl);
+ var_table = &state->streams[LTO_DECL_STREAM_VAR_DECL];
+ for (i = 0; i < var_table->size; i++)
+ {
+ var = var_table->trees[i];
+ if (TREE_STATIC (var)
+ && !TREE_PUBLIC (var)
+ && !bitmap_bit_p (seen_vars, DECL_UID (var)))
+ {
+ bitmap_set_bit (seen_vars, DECL_UID (var));
+ if (bitmap_bit_p (global_vars, DECL_UID (var)))
+ {
+ /* This static var is seen in another file, we need to
+ promote it to be a global. */
+ flags = lto_get_var_flags (var);
+ lto_set_var_flags (var, flags | LTO_VAR_FLAG_FORCE_GLOBAL);
+ }
+ else
+ {
+ /* This is the first time we see this static var. */
+ bitmap_set_bit (global_vars, DECL_UID (var));
+ }
+ }
+ }
+}
+
+/* Find out all static variables 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. */
+
+static void
+lto_promote_cross_file_statics (void)
+{
+ unsigned i;
+ cgraph_node_set set;
+ cgraph_node_set_iterator csi;
+ bitmap global_vars, seen_vars, seen_funcs;
+
+ global_vars = lto_bitmap_alloc ();
+ for (i = 0; VEC_iterate (cgraph_node_set, lto_cgraph_node_sets, i, set); i++)
+ {
+ /* We use SEEN_VARS and SEEN_FUNCS to avoid redundant computation
+ within the same file. */
+ seen_vars = lto_bitmap_alloc ();
+ seen_funcs = lto_bitmap_alloc ();
+ for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
+ lto_scan_statics_in_cgraph_node (csi_node (csi), global_vars,
+ seen_funcs, seen_vars);
+ lto_bitmap_free (seen_vars);
+ lto_bitmap_free (seen_funcs);
+ }
+ lto_bitmap_free (global_vars);
+}
+
static lto_file *current_lto_file;
/* Write all output files in WPA mode. Returns a NULL-terminated array of
@@ -609,7 +714,7 @@ static char **
lto_wpa_write_files (void)
{
char **output_files;
- unsigned i;
+ unsigned i, n_sets;
lto_file *file;
cgraph_node_set set;
bitmap decls;
@@ -622,10 +727,15 @@ lto_wpa_write_files (void)
VEC_safe_push (bitmap, heap, inlined_decls, decls);
}
+ /* After adding all inlinees, find out statics that need to be promoted
+ to globals because of cross-file inlining. */
+ lto_promote_cross_file_statics ();
+
output_files = XNEWVEC (char *, VEC_length (cgraph_node_set,
lto_cgraph_node_sets) + 1);
- for (i = 0; VEC_iterate (cgraph_node_set, lto_cgraph_node_sets, i, set); i++)
+ n_sets = VEC_length (cgraph_node_set, lto_cgraph_node_sets);
+ for (i = 0; i < n_sets; i++)
{
char *temp_filename = make_cwd_temp_file (".lto.o");
@@ -641,6 +751,9 @@ lto_wpa_write_files (void)
decls = VEC_index (bitmap, inlined_decls, i);
lto_force_functions_static_inline (decls);
+ /* Set AUX to 1 in the last LTRANS file. */
+ set = VEC_index (cgraph_node_set, lto_cgraph_node_sets, i);
+ set->aux = (void*) (i == (n_sets - 1));
ipa_write_summaries_of_cgraph_node_set (set);
lto_delete_static_inline_states ();
@@ -652,7 +765,7 @@ lto_wpa_write_files (void)
output_files[i] = NULL;
for (i = 0; VEC_iterate (bitmap, inlined_decls, i, decls); i++)
- BITMAP_FREE (decls);
+ lto_bitmap_free (decls);
VEC_free (bitmap, heap, inlined_decls);
return output_files;
@@ -1011,8 +1124,6 @@ lto_main (int debug_p ATTRIBUTE_UNUSED)
lto_set_in_hooks (all_file_decl_data, get_section_data,
free_section_data);
- bitmap_obstack_initialize (<o_bitmap_obstack);
-
/* Read the resolution file. */
if (resolution_file_name)
{
@@ -1057,7 +1168,7 @@ lto_main (int debug_p ATTRIBUTE_UNUSED)
/* Skip over the rest if any errors were found. FIXME lto, this
should be reorganized to use the pass manager. */
if (errorcount)
- goto out;
+ return;
/* FIXME lto. This loop needs to be changed to use the pass manager to
call the ipa passes directly. */
@@ -1149,9 +1260,6 @@ lto_main (int debug_p ATTRIBUTE_UNUSED)
}
XDELETEVEC (output_files);
}
-
-out:
- bitmap_obstack_release (<o_bitmap_obstack);
}
#include "gt-lto-lto.h"
Index: gcc/gcc/lto/Make-lang.in
===================================================================
--- gcc/gcc/lto/Make-lang.in (revision 141779)
+++ gcc/gcc/lto/Make-lang.in (working copy)
@@ -97,7 +97,7 @@ lto/lto.o: lto/lto.c $(CONFIG_H) $(CGRAP
$(LTO_TREE_H) dwarf2out.h tree-ssa-operands.h gt-lto-lto.h \
lto-section.h $(LTO_SECTION_IN_H) tree-pass.h $(LTO_SECTION_OUT_H) \
pointer-set.h vec.h $(BITMAP_H) $(IPA_PROP_H) lto/common.h \
- diagnostic.h
+ diagnostic.h lto-utils.h
lto/lto-elf.o: lto/lto-elf.c $(CONFIG_H) coretypes.h $(SYSTEM_H) \
toplev.h $(LTO_H) $(TM_H)
lto/common.o: lto/common.h
Index: gcc/gcc/varasm.c
===================================================================
--- gcc/gcc/varasm.c (revision 141779)
+++ gcc/gcc/varasm.c (working copy)
@@ -54,6 +54,7 @@ along with GCC; see the file COPYING3.
#include "cfglayout.h"
#include "basic-block.h"
#include "tree-iterator.h"
+#include "lto-utils.h"
#ifdef XCOFF_DEBUGGING_INFO
#include "xcoffout.h" /* Needed for external data
@@ -2097,6 +2098,15 @@ assemble_variable (tree decl, int top_le
return;
}
+ /* Do nothing if we are running in LTRANS mode and we are told to
+ suppress output. */
+ if (flag_ltrans
+ && (lto_get_var_flags (decl) & LTO_VAR_FLAG_SUPPRESS_OUTPUT))
+ {
+ TREE_ASM_WRITTEN (decl) = 1;
+ return;
+ }
+
/* If type was incomplete when the variable was declared,
see if it is complete now. */
Index: gcc/gcc/Makefile.in
===================================================================
--- gcc/gcc/Makefile.in (revision 141779)
+++ gcc/gcc/Makefile.in (working copy)
@@ -1171,6 +1171,7 @@ OBJS-common = \
lto-section-out.o \
lto-stream-debug.o \
lto-symtab.o \
+ lto-utils.o \
lto-wpa-fixup.o \
mcf.o \
mode-switching.o \
@@ -2094,32 +2095,35 @@ lto-function-in.o: lto-function-in.c $(C
tree-flow.h $(CGRAPH_H) $(FUNCTION_H) $(GGC_H) $(DIAGNOSTIC_H) except.h \
debug.h $(TIMEVAR_H) $(LTO_TAGS_H) lto-tree-flags.def $(LTO_TREE_IN_H) \
lto-tree-tags.def $(LTO_SECTION_IN_H) output.h dwarf2asm.h dwarf2out.h \
- libfuncs.h
+ libfuncs.h lto-utils.h
lto-function-out.o : lto-function-out.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(TOPLEV_H) $(TREE_H) $(EXPR_H) $(FLAGS_H) $(PARAMS_H) input.h \
$(VARRAY_H) $(HASHTAB_H) langhooks.h $(BASIC_BLOCK_H) tree-iterator.h \
tree-pass.h tree-flow.h $(CGRAPH_H) $(FUNCTION_H) $(GGC_H) $(DIAGNOSTIC_H) \
except.h debug.h $(TIMEVAR_H) $(LTO_TAGS_H) lto-tree-flags.def \
lto-tree-tags.def lto-tags.h lto-header.h $(LTO_SECTION_OUT_H) output.h \
- dwarf2asm.h dwarf2out.h $(LTO_SECTION_IN_H)
+ dwarf2asm.h dwarf2out.h $(LTO_SECTION_IN_H) lto-utils.h
lto-section-in.o: lto-section-in.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TOPLEV_H) $(EXPR_H) $(FLAGS_H) $(PARAMS_H) input.h $(VARRAY_H) \
$(HASHTAB_H) langhooks.h $(BASIC_BLOCK_H) tree-iterator.h tree-pass.h \
tree-flow.h $(CGRAPH_H) $(FUNCTION_H) $(GGC_H) $(DIAGNOSTIC_H) except.h \
- debug.h $(TIMEVAR_H) $(LTO_SECTION_IN_H) output.h dwarf2asm.h dwarf2out.h
+ debug.h $(TIMEVAR_H) $(LTO_SECTION_IN_H) output.h dwarf2asm.h dwarf2out.h \
+ lto-utils.h
lto-section-out.o : lto-section-out.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(TOPLEV_H) $(TREE_H) $(EXPR_H) $(FLAGS_H) $(PARAMS_H) input.h \
$(VARRAY_H) $(HASHTAB_H) langhooks.h $(BASIC_BLOCK_H) tree-iterator.h \
tree-pass.h tree-flow.h $(CGRAPH_H) $(FUNCTION_H) $(GGC_H) $(DIAGNOSTIC_H) \
except.h debug.h $(TIMEVAR_H) lto-header.h $(LTO_SECTION_OUT_H) output.h \
- dwarf2asm.h dwarf2out.h $(BITMAP_H)
+ dwarf2asm.h dwarf2out.h $(BITMAP_H) lto-utils.h
lto-symtab.o: lto-symtab.c $(LTO_TREE_IN_H) $(CONFIG_H) coretypes.h \
$(SYSTEM_H) toplev.h $(LTO_TREE_H) $(GGC_H) $(LAMBDA_H) \
$(GIMPLE_H) $(HASHTAB_H) $(LTO_TREE_IN_H) gt-lto-symtab.h
+lto-utils.o: lto-utils.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(TM_H)
lto-wpa-fixup.o: lto-wpa-fixup.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(TOPLEV_H) $(TREE_H) $(EXPR_H) $(FLAGS_H) tree-pass.h \
$(CGRAPH_H) $(FUNCTION_H) $(DIAGNOSTIC_H) vec.h $(BITMAP_H) $(TIMEVAR_H) \
- $(LTO_SECTION_IN_H) $(LTO_SECTION_OUT_H)
+ $(LTO_SECTION_IN_H) $(LTO_SECTION_OUT_H) lto-utils.h
langhooks.o : langhooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) $(TOPLEV_H) $(TREE_INLINE_H) $(RTL_H) insn-config.h $(INTEGRATE_H) \
langhooks.h $(TARGET_H) $(LANGHOOKS_DEF_H) $(FLAGS_H) $(GGC_H) $(DIAGNOSTIC_H) \
@@ -2559,7 +2563,8 @@ varasm.o : varasm.c $(CONFIG_H) $(SYSTEM
$(RTL_H) $(FLAGS_H) $(FUNCTION_H) $(EXPR_H) hard-reg-set.h $(REGS_H) \
output.h $(C_PRAGMA_H) $(TOPLEV_H) xcoffout.h debug.h $(GGC_H) $(TM_P_H) \
$(HASHTAB_H) $(TARGET_H) langhooks.h gt-varasm.h $(BASIC_BLOCK_H) \
- $(CFGLAYOUT_H) $(CGRAPH_H) targhooks.h tree-mudflap.h $(REAL_H) tree-iterator.h
+ $(CFGLAYOUT_H) $(CGRAPH_H) targhooks.h tree-mudflap.h $(REAL_H) \
+ tree-iterator.h lto-utils.h
function.o : function.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
$(TREE_H) $(CFGLAYOUT_H) $(GIMPLE_H) $(FLAGS_H) $(FUNCTION_H) $(EXPR_H) \
$(OPTABS_H) libfuncs.h $(REGS_H) hard-reg-set.h insn-config.h $(RECOG_H) \
Index: gcc/gcc/lto-utils.c
===================================================================
--- gcc/gcc/lto-utils.c (revision 0)
+++ gcc/gcc/lto-utils.c (revision 0)
@@ -0,0 +1,128 @@
+/* Miscellaneous utilities. Things that are used in both input and output
+ or do not belong clearly to either are put here.
+
+ Copyright 2008 Free Software Foundation, Inc.
+ Contributed by Doug Kwan <dougkwan@google.com>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "bitmap.h"
+#include "vec.h"
+#include "lto-header.h"
+#include "lto-utils.h"
+
+/* LTO uses bitmaps with different life-times. So use a seperate
+ obstack for all LTO bitmaps. */
+
+static bitmap_obstack lto_obstack;
+static bool lto_obstack_initialized;
+
+/* We use this vector to keep extra DECL flags used by various parts of LTO.
+ Vector is indexed by DECL_UID. */
+
+DEF_VEC_I(lto_var_flags_t);
+DEF_VEC_ALLOC_I(lto_var_flags_t,heap);
+static VEC(lto_var_flags_t,heap) *lto_var_flags;
+
+/* Allocate a bitmap from heap. Initializes the LTO obstack if necessary. */
+
+bitmap
+lto_bitmap_alloc (void)
+{
+ if (!lto_obstack_initialized)
+ {
+ bitmap_obstack_initialize (<o_obstack);
+ lto_obstack_initialized = true;
+ }
+ return BITMAP_ALLOC (<o_obstack);
+}
+
+/* Free bitmap B. */
+
+void
+lto_bitmap_free (bitmap b)
+{
+ BITMAP_FREE (b);
+}
+
+/* Get the var-flags of VAR. */
+
+lto_var_flags_t
+lto_get_var_flags (tree var)
+{
+ unsigned idx = DECL_UID (var);
+ if (!lto_var_flags || VEC_length (lto_var_flags_t, lto_var_flags) <= idx)
+ return 0;
+ return VEC_index (lto_var_flags_t, lto_var_flags, idx);
+}
+
+/* Set the var-flags of VAR to FLAGS. */
+
+void
+lto_set_var_flags (tree var, lto_var_flags_t flags)
+{
+ unsigned idx = DECL_UID (var);
+ if (!lto_var_flags || VEC_length (lto_var_flags_t, lto_var_flags) <= idx)
+ VEC_safe_grow_cleared (lto_var_flags_t, heap, lto_var_flags, idx + 1);
+ VEC_replace (lto_var_flags_t, lto_var_flags, idx, flags);
+}
+
+/* Get a section name for a particular type or name. The NAME field
+ is only used if SECTION_TYPE is LTO_section_function_body or
+ lto_static_initializer. For all others it is ignored. The callee
+ of this function is responcible to free the returned name. */
+
+char *
+lto_get_section_name (int section_type, const char *name)
+{
+ switch (section_type)
+ {
+ case LTO_section_function_body:
+ return concat (LTO_SECTION_NAME_PREFIX, name, NULL);
+
+ case LTO_section_static_initializer:
+ return concat (LTO_SECTION_NAME_PREFIX, ".statics", NULL);
+
+ case LTO_section_symtab:
+ return concat (LTO_SECTION_NAME_PREFIX, ".symtab", NULL);
+
+ case LTO_section_decls:
+ return concat (LTO_SECTION_NAME_PREFIX, ".decls", NULL);
+
+ case LTO_section_cgraph:
+ return concat (LTO_SECTION_NAME_PREFIX, ".cgraph", NULL);
+
+ case LTO_section_ipa_pure_const:
+ return concat (LTO_SECTION_NAME_PREFIX, ".pureconst", NULL);
+
+ case LTO_section_ipa_reference:
+ return concat (LTO_SECTION_NAME_PREFIX, ".reference", NULL);
+
+ case LTO_section_wpa_fixup:
+ return concat (LTO_SECTION_NAME_PREFIX, ".wpa_fixup", NULL);
+
+ default:
+ gcc_unreachable ();
+ }
+}
+
Index: gcc/gcc/lto-utils.h
===================================================================
--- gcc/gcc/lto-utils.h (revision 0)
+++ gcc/gcc/lto-utils.h (revision 0)
@@ -0,0 +1,39 @@
+/* Miscellaneous utilies for LTO.
+
+ Copyright (C) 2008 Free Software Foundation, Inc.
+ Contributed by Doug Kwan<dougkwan@google.com>
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 2, or (at your option) any later
+ version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#ifndef GCC_LTO_UTILS_H
+#define GCC_LTO_UITLS_H
+
+bitmap lto_bitmap_alloc (void);
+
+#define LTO_VAR_FLAG_DEFINED (1<<0)
+#define LTO_VAR_FLAG_SUPPRESS_OUTPUT (1<<1)
+#define LTO_VAR_FLAG_FORCE_GLOBAL (1<<2)
+
+typedef unsigned char lto_var_flags_t;
+
+void lto_bitmap_free (bitmap);
+lto_var_flags_t lto_get_var_flags (tree);
+void lto_set_var_flags (tree, lto_var_flags_t);
+char* lto_get_section_name (int, const char *);
+
+#endif /* !GCC_LTO_UTILS_H */
Index: gcc/gcc/lto-section-out.c
===================================================================
--- gcc/gcc/lto-section-out.c (revision 141779)
+++ gcc/gcc/lto-section-out.c (working copy)
@@ -50,6 +50,7 @@ along with GCC; see the file COPYING3.
#include "pointer-set.h"
#include "stdint.h"
#include "lto-symtab.h"
+#include "lto-utils.h"
#include "bitmap.h"
static VEC(lto_out_decl_state_ptr, heap) *decl_state_stack;
@@ -57,13 +58,12 @@ static VEC(lto_out_decl_state_ptr, heap)
/* List of out decl states used by functions. We use this to
generate the decl directory later. */
-static VEC(lto_out_decl_state_ptr, heap) *function_decl_states;
+VEC(lto_out_decl_state_ptr, heap) *lto_function_decl_states;
/* Bitmap indexed by DECL_UID to indicate if a function needs to be
forced static inline. */
-static bitmap forced_static_inline;
-static bitmap_obstack lto_section_out_obstack;
+static bitmap forced_static_inline;
/* Initialize states for determining which function decls to be ouput
as static inline, regardless of the decls' own attributes. */
@@ -71,8 +71,7 @@ static bitmap_obstack lto_section_out_ob
void
lto_new_static_inline_states (void)
{
- bitmap_obstack_initialize (<o_section_out_obstack);
- forced_static_inline = BITMAP_ALLOC (<o_section_out_obstack);
+ forced_static_inline = lto_bitmap_alloc ();
}
/* Releasing resources use for states to determine which function decls
@@ -81,9 +80,8 @@ lto_new_static_inline_states (void)
void
lto_delete_static_inline_states (void)
{
- BITMAP_FREE (forced_static_inline);
+ lto_bitmap_free (forced_static_inline);
forced_static_inline = NULL;
- bitmap_obstack_release (<o_section_out_obstack);
}
/* Force FN_DECL to be output as static inline. */
@@ -209,47 +207,6 @@ lto_eq_global_slot_node (const void *p1,
return ds1->t == ds2->t;
}
-
-/* Get a section name for a particular type or name. The NAME field
- is only used if SECTION_TYPE is LTO_section_function_body or
- lto_static_initializer. For all others it is ignored. The callee
- of this function is responcible to free the returned name. */
-
-char *
-lto_get_section_name (enum lto_section_type section_type, const char *name)
-{
- switch (section_type)
- {
- case LTO_section_function_body:
- return concat (LTO_SECTION_NAME_PREFIX, name, NULL);
-
- case LTO_section_static_initializer:
- return concat (LTO_SECTION_NAME_PREFIX, ".statics", NULL);
-
- case LTO_section_symtab:
- return concat (LTO_SECTION_NAME_PREFIX, ".symtab", NULL);
-
- case LTO_section_decls:
- return concat (LTO_SECTION_NAME_PREFIX, ".decls", NULL);
-
- case LTO_section_cgraph:
- return concat (LTO_SECTION_NAME_PREFIX, ".cgraph", NULL);
-
- case LTO_section_ipa_pure_const:
- return concat (LTO_SECTION_NAME_PREFIX, ".pureconst", NULL);
-
- case LTO_section_ipa_reference:
- return concat (LTO_SECTION_NAME_PREFIX, ".reference", NULL);
-
- case LTO_section_wpa_fixup:
- return concat (LTO_SECTION_NAME_PREFIX, ".wpa_fixup", NULL);
-
- default:
- gcc_unreachable ();
- }
-}
-
-
/*****************************************************************************
Output routines shared by all of the serialization passes.
*****************************************************************************/
@@ -789,7 +746,8 @@ lto_record_function_out_decl_state (tree
state->streams[i].tree_hash_table = NULL;
}
state->fn_decl = fn_decl;
- VEC_safe_push (lto_out_decl_state_ptr, heap, function_decl_states, state);
+ VEC_safe_push (lto_out_decl_state_ptr, heap, lto_function_decl_states,
+ state);
}
/* Return a reference index for tree node T from hash table H. If
@@ -1200,7 +1158,8 @@ write_symbols_of_kind (lto_decl_stream_e
{
struct lto_out_decl_state *out_state;
struct lto_output_stream stream;
- unsigned num_fns = VEC_length (lto_out_decl_state_ptr, function_decl_states);
+ unsigned num_fns =
+ VEC_length (lto_out_decl_state_ptr, lto_function_decl_states);
unsigned idx;
memset (&stream, 0, sizeof (stream));
@@ -1210,7 +1169,7 @@ write_symbols_of_kind (lto_decl_stream_e
for (idx = 0; idx < num_fns; idx++)
{
out_state =
- VEC_index (lto_out_decl_state_ptr, function_decl_states, idx);
+ VEC_index (lto_out_decl_state_ptr, lto_function_decl_states, idx);
write_symbol_vec (hash, &stream, out_state->streams[kind].trees, seen);
}
@@ -1229,13 +1188,11 @@ produce_symtab (htab_t hash)
lto_begin_section (section_name);
free (section_name);
- bitmap_obstack_initialize (NULL);
- seen = BITMAP_ALLOC (NULL);
+ seen = lto_bitmap_alloc ();
write_symbols_of_kind (LTO_DECL_STREAM_FN_DECL, hash, seen);
write_symbols_of_kind (LTO_DECL_STREAM_VAR_DECL, hash, seen);
+ lto_bitmap_free (seen);
- BITMAP_FREE (seen);
- bitmap_obstack_release (NULL);
lto_end_section ();
}
@@ -1246,7 +1203,7 @@ produce_symtab (htab_t hash)
recover these on other side. */
static void
-produce_asm_for_decls (cgraph_node_set set ATTRIBUTE_UNUSED)
+produce_asm_for_decls (cgraph_node_set set)
{
struct lto_out_decl_state *out_state = lto_get_out_decl_state ();
struct lto_out_decl_state *fn_out_state;
@@ -1262,6 +1219,10 @@ produce_asm_for_decls (cgraph_node_set s
ob->main_hash_table = htab_create (37, lto_hash_global_slot_node,
lto_eq_global_slot_node, free);
+ /* Write out constructors and init. We defer doing this until now so that
+ we can write out only what is needed. */
+ output_constructors_and_inits (set);
+
/* Assign reference indices for predefined trees. These need not be
serialized. */
preload_common_nodes (ob);
@@ -1277,12 +1238,12 @@ produce_asm_for_decls (cgraph_node_set s
/* Write the global var decls. */
LTO_SET_DEBUGGING_STREAM (debug_main_stream, main_data);
- num_fns = VEC_length (lto_out_decl_state_ptr, function_decl_states);
+ num_fns = VEC_length (lto_out_decl_state_ptr, lto_function_decl_states);
lto_output_decl_state_streams (ob, out_state);
for (idx = 0; idx < num_fns; idx++)
{
fn_out_state =
- VEC_index (lto_out_decl_state_ptr, function_decl_states, idx);
+ VEC_index (lto_out_decl_state_ptr, lto_function_decl_states, idx);
lto_output_decl_state_streams (ob, fn_out_state);
}
@@ -1300,7 +1261,7 @@ produce_asm_for_decls (cgraph_node_set s
for (idx = 0; idx < num_fns; idx++)
{
fn_out_state =
- VEC_index (lto_out_decl_state_ptr, function_decl_states, idx);
+ VEC_index (lto_out_decl_state_ptr, lto_function_decl_states, idx);
decl_state_size += lto_out_decl_state_written_size (fn_out_state);
}
header.decl_state_size = decl_state_size;
@@ -1328,7 +1289,7 @@ produce_asm_for_decls (cgraph_node_set s
for (idx = 0; idx < num_fns; idx++)
{
fn_out_state =
- VEC_index (lto_out_decl_state_ptr, function_decl_states, idx);
+ VEC_index (lto_out_decl_state_ptr, lto_function_decl_states, idx);
lto_output_decl_state_refs (ob, decl_state_stream, fn_out_state);
}
lto_write_stream (decl_state_stream);
@@ -1346,8 +1307,8 @@ produce_asm_for_decls (cgraph_node_set s
/* Write the symbol table. */
produce_symtab (ob->main_hash_table);
- VEC_free (lto_out_decl_state_ptr, heap, function_decl_states);
- function_decl_states = NULL;
+ VEC_free (lto_out_decl_state_ptr, heap, lto_function_decl_states);
+ lto_function_decl_states = NULL;
/* Deallocate memory and clean up. */
destroy_output_block (ob);
Index: gcc/gcc/lto-section-out.h
===================================================================
--- gcc/gcc/lto-section-out.h (revision 141779)
+++ gcc/gcc/lto-section-out.h (working copy)
@@ -103,6 +103,12 @@ typedef struct lto_out_decl_state *lto_o
DEF_VEC_P(lto_out_decl_state_ptr);
DEF_VEC_ALLOC_P(lto_out_decl_state_ptr, heap);
+/* Holds all the out decl states of functions output so far in the
+ current output file. */
+
+extern VEC(lto_out_decl_state_ptr, heap) *lto_function_decl_states;
+
+
/* A simple output block. This can be used for simple ipa passes that
do not need more than one stream. */
struct lto_simple_output_block
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH][LTO] Fix multiple symbol definition problem in WHOPR.
2008-11-12 21:50 [PATCH][LTO] Fix multiple symbol definition problem in WHOPR Doug Kwan (關振德)
@ 2008-11-13 16:35 ` Diego Novillo
0 siblings, 0 replies; 2+ messages in thread
From: Diego Novillo @ 2008-11-13 16:35 UTC (permalink / raw)
To: Doug Kwan (關振德); +Cc: gcc-patches, Rafael Espindola
On Wed, Nov 12, 2008 at 16:35, Doug Kwan (關振德) <dougkwan@google.com> wrote:
> @@ -2277,23 +2400,18 @@ output_constructors_and_inits (void)
> /* Make string 0 be a NULL string. */
> lto_output_1_stream (ob->string_stream, 0);
>
> - /* Process the global static vars that have initializers or
> - constructors. */
> - FOR_EACH_STATIC_VARIABLE (vnode)
> + /* In WPA mode. Output inits and constructors of used variables. */
Clarify that by 'used' we mean variables used in one particular file.
> @@ -2694,10 +2808,26 @@ output_function_decl (struct output_bloc
> static void
> output_var_decl (struct output_block *ob, tree decl)
> {
> + bool saved_public;
> +
> /* tag and flags */
> /* Assume static or external variable. */
> output_global_record_start (ob, NULL, NULL, LTO_var_decl1);
> - output_tree_flags (ob, 0, decl, true);
> + if (flag_wpa
> + && (lto_get_var_flags (decl) & LTO_VAR_FLAG_FORCE_GLOBAL))
> + {
> + /* This variable is a file-scope static that is now shared by
> + multiple translation units owing to IPA-inlining. We promote
> + it to a global. */
> +
> + gcc_assert (TREE_STATIC (decl) && !TREE_PUBLIC (decl));
> + saved_public = TREE_PUBLIC (decl);
No need to save TREE_PUBLIC. You are asserting that TREE_PUBLIC
is false.
> @@ -641,6 +751,9 @@ lto_wpa_write_files (void)
> decls = VEC_index (bitmap, inlined_decls, i);
> lto_force_functions_static_inline (decls);
>
> + /* Set AUX to 1 in the last LTRANS file. */
> + set = VEC_index (cgraph_node_set, lto_cgraph_node_sets, i);
> + set->aux = (void*) (i == (n_sets - 1));
s/(void*)/(void *)(intptr_t)/ to avoid int/ptr problems in 64 bit
hosts.
> +lto-utils.o: lto-utils.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
> + $(TM_H)
Missing tree.h bitmap.h vec.h lto-header.h and lto-utils.h
> @@ -0,0 +1,39 @@
> +/* Miscellaneous utilies for LTO.
> +
> + Copyright (C) 2008 Free Software Foundation, Inc.
> + Contributed by Doug Kwan<dougkwan@google.com>
Space before '<'.
The rest looks fine.
Thanks. Diego.
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2008-11-13 15:54 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-11-12 21:50 [PATCH][LTO] Fix multiple symbol definition problem in WHOPR Doug Kwan (關振德)
2008-11-13 16:35 ` Diego Novillo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).