aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiego Novillo <dnovillo@google.com>2008-06-10 16:28:38 +0000
committerDiego Novillo <dnovillo@google.com>2008-06-10 16:28:38 +0000
commitb2af22c13f7028b20890ac6efd5b670703f20191 (patch)
tree7a23a535e66532fd30febdbaa2e99964d4b27e89
parentbeafeb7bd974fd8abd842a50d1f8c4cdc1b2a2b3 (diff)
2008-06-10 Diego Novillo <dnovillo@google.com>
Ollie Wild <aaw@google.com> Merge with lto. git-svn-id: https://gcc.gnu.org/svn/gcc/branches/lto-streamer@136624 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog.lto106
-rw-r--r--gcc/Makefile.in22
-rw-r--r--gcc/ipa-pure-const.c242
-rw-r--r--gcc/lto-function-in.c2
-rw-r--r--gcc/lto-function-out.c72
-rw-r--r--gcc/lto-header.h13
-rw-r--r--gcc/lto-section-in.c187
-rw-r--r--gcc/lto-section-in.h86
-rw-r--r--gcc/lto-section-out.c225
-rw-r--r--gcc/lto-section-out.h44
-rw-r--r--gcc/lto-tree-out.h1
-rw-r--r--gcc/lto/ChangeLog16
-rw-r--r--gcc/lto/Make-lang.in5
-rw-r--r--gcc/lto/lto.c183
-rw-r--r--gcc/lto/lto.h27
-rw-r--r--gcc/passes.c70
-rw-r--r--gcc/tree-pass.h23
17 files changed, 1099 insertions, 225 deletions
diff --git a/gcc/ChangeLog.lto b/gcc/ChangeLog.lto
index 67010a49aab..47fdd6912a7 100644
--- a/gcc/ChangeLog.lto
+++ b/gcc/ChangeLog.lto
@@ -1,3 +1,8 @@
+2008-06-10 Diego Novillo <dnovillo@google.com>
+ Ollie Wild <aaw@google.com>
+
+ Merge with lto.
+
2008-06-09 Bill Maddox <maddox@google.com>
* lto-tags.h: Add new tags LTO_local_type_ref
@@ -70,6 +75,107 @@
* Make-lang.in (lto.all.cross): depend on $(LTO_EXE).
+2008-05-05 Kenneth Zadeck <zadeck@naturalbridge.com>
+ Jan Hubicka <jh@suse.cz>
+
+ * tree-pass.h (ipa_opt_pass pass_ipa_lto_gimple_out,
+ pass_ipa_pure_const, pass_ipa_lto_finish_out): Changed from being
+ simple_ipa_opt_pass to ipa_opt_pass.
+ (ipa_opt_pass pass_ipa_lto_cgraph): Renamed from
+ ipa_opt_pass pass_ipa_lto_cgraph_out.
+ (ipa_write_summaries, ipa_read_summaries): New functions.
+ * lto-function-out.c (string_slot_free): New function.
+ (next_string_index): Removed.
+ (string_hash_table): Now use string_slot_free.
+ (output_string): Copy string to malloced space and properly
+ initialize slots.
+ (output_type_ref_1): Renamed to lto_output_type_ref_index and
+ moved to lto_section_out.c
+ (output_type_ref, output_function): Now calls lto_output_type_ref_index.
+ (output_expr_operand): Moved bodies of FIELD_DECL, FUNCTION_DECL,
+ VAR_DECL, TYPE_DECL, NAMESPACE_DECL to new functions in
+ lto_section_out.c.
+ (lto_output): Now returns void.
+ (pass_ipa_lto_gimple_out): Now a IPA_PASS with lto_output as
+ write_summary method.
+ * lto-function-in.c (input_string_internal): Moved initialization
+ of len to proper place.
+ * lto-cgraph.c: New file that is combination of lto-cgraph-out.c
+ lto-cgraph-in.c and cgraph.h.
+ (lto-section-in.h, lto-section-out.h): Added includes.
+ (tree-vectorizer.h, tree-iterator.h): Removed includes.
+ (LTO_cgraph_tag_names, LTO_cgraph_tags): Added from cgraph.h.
+ (create_output_block, destroy_output_block, output_uleb128,
+ output_sleb128, output_fun_decl, add_flag): Moved to
+ lto-section-out.c, renamed with "lto_" prefix and generalized.
+ (output_node, output_cgraph, input_overwrite_mode, input_cgraph):
+ Changed to call moved and renamed functions.
+ (input_overwrite_mode): Renamed from overwrite_mode.
+ (input_cgraph): Renamed from lto_input_cgraph and made private and
+ now loops over all file_datas.
+ (pass_ipa_lto_cgraph): Renamed from pass_ipa_lto_cgraph_out and
+ made into IPA_PASS.
+ * lto-cgraph.h: File deleted and all infomation moved to
+ lto-cgraph.c.
+ * lto-header.h (LTO_section_ipa_pure_const): New section type.
+ (lto_simple_header): New structure.
+ * ipa-pure-const.c (lto-section-in.h, lto-section-out.h): New
+ includes.
+ (init_state, finish_state, set_function_state, generate_summary,
+ write_summary, read_summary): New functions.
+ (scan_stmt): Renamed from scan_function. Changed to keep state in
+ local static vars rather than cgraph aux field.
+ (propagate): Renamed from static_execute. Changed to keep state in
+ local static vars rather than cgraph aux field.
+ (pass_ipa_pure_const): Changed from SIMPLE_IPA_PASS to IPA_PASS.
+ * lto-cgraph-in.c: Content moved to lto-cgraph.c.
+ * lto-section-in.c (lto_get_flag, lto_get_flags): Moved from
+ lto-cgraph-in.c and renamed from add_flag and add_flags.
+ (lto_read_section_data): Moved to lto/lto.c and modified to use
+ mmap.
+ (lto_set_in_hooks, lto_get_file_decl_data, lto_free_section_data,
+ lto_create_simple_input_block, lto_destroy_simple_input_block):
+ New functions.
+ (lto_get_section_data): Modified to call hook in lto front end.
+ * lto-section-in.h (lto_section_slot): Moved to lto.h.
+ (LTO_INIT_INPUT_BLOCK_PTR): New macro.
+ (lto_file_decl_data.fd): New field.
+ (lto_get_section_data_f, lto_free_section_data_f): New typedefs.
+ (lto_create_simple_input_block, lto_destroy_simple_input_block,
+ lto_get_flag, lto_get_flags, lto_set_in_hooks, lto_file_decl_data,
+ lto_free_section_data): New functions.
+ (lto_get_section_data): Added parms.
+ * Makefile.in (lto-cgaph.o): Combined rules from lto-cgraph-in.o
+ and lto-cgraph-out.o.
+ (lto-function-in.o, lto-function-out.o): Added dependencies.
+ * passes.c (init_optimization_passes): Reordered ipa passes.
+ (execute_ipa_summary_passes): Added check to see that pass was
+ there.
+ (ipa_write_summaries_1, ipa_write_summaries,
+ ipa_read_summaries_1): New function.
+ (execute_ipa_pass_list): Added call to ipa_write_summaries and
+ fixed bug.
+ * lto-cgraph-out.c: Content moved to lto-cgraph.c.
+ * lto-section-out.c (lto_set_flag, lto_set_flags): Functions moved
+ and renamed (with lto_ prefix) from lto-cgraph-out.c.
+ (lto_output_field_decl_index, lto_output_fn_decl_index,
+ lto_output_namespace_decl_index, lto_output_var_decl_index,
+ lto_output_type_decl_index, lto_output_type_ref_index): New
+ functions. The code for these functions was taken from
+ lto-function-out.c
+ (lto_create_simple_output_block, lto_destroy_simple_output_block):
+ New functions.
+ (produce_asm_for_decls): Now returns void.
+ (pass_ipa_lto_finish_out): Now an IPA_PASS.
+ * lto-section-out.h (lto_simple_output_block): New structure.
+ (lto_set_flag, lto_set_flags, lto_output_field_decl_index,
+ lto_output_fn_decl_index, lto_output_namespace_decl_index,
+ lto_output_var_decl_index, lto_output_type_decl_index,
+ lto_output_type_ref_index, lto_create_simple_output_block,
+ lto_destroy_simple_output_block): New functions.
+ (lto_get_out_decl_state): Removed function
+ (lto_output_decl_index): Added parms.
+
2008-06-04 Rafael Espindola <espindola@google.com>
* lto-function-out.c (output_tree): call error with the TREE_CODE name.
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 5a29bddb244..7b0effa65fa 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -836,6 +836,7 @@ DBGCNT_H = dbgcnt.h dbgcnt.def
EBIMAP_H = ebitmap.h sbitmap.h
LTO_TAGS_H = lto-tags.h tree.h sbitmap.h lto-header.h
LTO_SECTION_H = lto-section.h lto-header.h
+LTO_SECTION_IN_H = lto-section-in.h lto-header.h
TREE_VECTORIZER_H = tree-vectorizer.h $(TREE_DATA_REF_H)
#
@@ -1088,8 +1089,7 @@ OBJS-common = \
loop-unroll.o \
loop-unswitch.o \
lower-subreg.o \
- lto-cgraph-in.o \
- lto-cgraph-out.o \
+ lto-cgraph.o \
lto-function-in.o \
lto-function-out.o \
lto-section-in.o \
@@ -1985,24 +1985,18 @@ double-int.o: double-int.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H)
lto-stream-debug.o : lto-stream-debug.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
toplev.h $(FLAGS_H) $(PARAMS_H) input.h debug.h $(TREE_H) \
lto-header.h
-lto-cgraph-in.o: lto-cgraph-in.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+lto-cgraph.o: lto-cgraph.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_TAGS_H) lto-cgraph.h lto-section-in.h \
- output.h dwarf2asm.h dwarf2out.h
-lto-cgraph-out.o : lto-cgraph-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-cgraph.h lto-header.h lto-section-out.h output.h dwarf2asm.h dwarf2out.h
+ except.h debug.h $(TIMEVAR_H) $(LTO_TAGS_H) $(LTO_SECTION_IN_H) \
+ lto-section-out.h output.h dwarf2asm.h dwarf2out.h
lto-function-in.o: lto-function-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_TAGS_H) lto-section-in.h lto-tree-flags.def \
- lto-tree-tags.def lto-section-in.h output.h dwarf2asm.h dwarf2out.h
+ debug.h $(TIMEVAR_H) $(LTO_TAGS_H) lto-tree-flags.def \
+ lto-tree-tags.def $(LTO_SECTION_IN_H) output.h dwarf2asm.h dwarf2out.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 \
@@ -2013,7 +2007,7 @@ 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-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 \
diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c
index 8c7f2649ecc..78b3e821efc 100644
--- a/gcc/ipa-pure-const.c
+++ b/gcc/ipa-pure-const.c
@@ -1,5 +1,5 @@
/* Callgraph based analysis of static variables.
- Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
This file is part of GCC.
@@ -52,6 +52,8 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic.h"
#include "langhooks.h"
#include "target.h"
+#include "lto-section-in.h"
+#include "lto-section-out.h"
static struct pointer_set_t *visited_nodes;
@@ -65,26 +67,75 @@ enum pure_const_state_e
IPA_NEITHER
};
-/* Holder inserted into the ipa_dfs_info aux field to hold the
- const_state. */
+/* Holder for the const_state. There is one of these per function
+ decl. */
struct funct_state_d
{
+ /* See above. */
enum pure_const_state_e pure_const_state;
+
+ /* True if the function could possibly infinite loop. There are a
+ lot of ways that this could be determined. We are pretty
+ conservative here. While it is possible to cse pure and const
+ calls, it is not legal to have dce get rid of the call if there
+ is a possibility that the call could infinite loop since this is
+ a behavioral change. */
bool looping;
- bool state_set_in_source;
+
+ /* If the state of the function was set in the source, then assume
+ that it was done properly even if the analysis we do would be
+ more pessimestic. */
+ bool state_set_in_source;
};
typedef struct funct_state_d * funct_state;
-/* Return the function state from NODE. */
+
+/* The storage of the funct_state is abstracted because there is the
+ possibility that it may be desirable to move this to the cgraph
+ local info. */
+
+/* Array, indexed by cgraph node uid, of function states. */
+
+static funct_state *funct_state_vec;
+
+
+/* Init the function state. */
+
+static void
+init_state (void)
+{
+ funct_state_vec = XCNEWVEC (funct_state, cgraph_max_uid);
+}
+
+
+/* Init the function state. */
+
+static void
+finish_state (void)
+{
+ free (funct_state_vec);
+}
+
+
+/* Return the function state from NODE. */
static inline funct_state
get_function_state (struct cgraph_node *node)
{
- struct ipa_dfs_info * info = (struct ipa_dfs_info *) node->aux;
- return (funct_state) info->aux;
+ return funct_state_vec[node->uid];
}
+
+/* Set the function state S for NODE. */
+
+static inline void
+set_function_state (struct cgraph_node *node, funct_state s)
+{
+ funct_state_vec[node->uid] = s;
+}
+
+
/* Check to see if the use (or definition when CHECHING_WRITE is true)
variable T is legal in a function that is either pure or const. */
@@ -286,6 +337,9 @@ get_asm_expr_operands (funct_state local, tree stmt)
const char *constraint;
bool allows_mem, allows_reg, is_inout;
+ if (!memory_identifier_string)
+ memory_identifier_string = build_string(7, "memory");
+
for (i=0, link = ASM_OUTPUTS (stmt); link; ++i, link = TREE_CHAIN (link))
{
oconstraints[i] = constraint
@@ -405,9 +459,7 @@ check_call (funct_state local, tree call_expr)
should be converted to use the operand scanner. */
static tree
-scan_function (tree *tp,
- int *walk_subtrees,
- void *data)
+scan_stmt (tree *tp, int *walk_subtrees, void *data)
{
struct cgraph_node *fn = (struct cgraph_node *) data;
tree t = *tp;
@@ -417,7 +469,7 @@ scan_function (tree *tp,
{
case VAR_DECL:
if (DECL_INITIAL (t))
- walk_tree (&DECL_INITIAL (t), scan_function, fn, visited_nodes);
+ walk_tree (&DECL_INITIAL (t), scan_stmt, fn, visited_nodes);
*walk_subtrees = 0;
break;
@@ -513,17 +565,17 @@ scan_function (tree *tp,
return NULL;
}
+
/* This is the main routine for finding the reference patterns for
global variables within a function FN. */
static void
analyze_function (struct cgraph_node *fn)
{
- funct_state l = XCNEW (struct funct_state_d);
tree decl = fn->decl;
- struct ipa_dfs_info * w_info = (struct ipa_dfs_info *) fn->aux;
+ funct_state l = XCNEW (struct funct_state_d);
- w_info->aux = l;
+ set_function_state (fn, l);
l->pure_const_state = IPA_CONST;
l->state_set_in_source = false;
@@ -570,7 +622,7 @@ analyze_function (struct cgraph_node *fn)
block_stmt_iterator bsi;
for (bsi = bsi_start (this_block); !bsi_end_p (bsi); bsi_next (&bsi))
{
- walk_tree (bsi_stmt_ptr (bsi), scan_function,
+ walk_tree (bsi_stmt_ptr (bsi), scan_stmt,
fn, visited_nodes);
if (l->pure_const_state == IPA_NEITHER)
goto end;
@@ -611,24 +663,15 @@ end:
}
-/* Produce the global information by preforming a transitive closure
- on the local information that was produced by ipa_analyze_function
- and ipa_analyze_variable. */
+/* Analyze each function in the cgraph to see if it is locally PURE or
+ CONST. */
-static unsigned int
-static_execute (void)
+static void
+generate_summary (void)
{
struct cgraph_node *node;
- struct cgraph_node *w;
- struct cgraph_node **order =
- XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
- int order_pos = ipa_utils_reduced_inorder (order, true, false);
- int i;
- struct ipa_dfs_info * w_info;
-
- if (!memory_identifier_string)
- memory_identifier_string = build_string(7, "memory");
+ init_state ();
/* There are some shared nodes, in particular the initializers on
static declarations. We do not need to scan them more than once
since all we would be interested in are the addressof
@@ -641,14 +684,109 @@ static_execute (void)
is a master clone. However, we do NOT process any
AVAIL_OVERWRITABLE functions (these are never clones) we cannot
guarantee that what we learn about the one we see will be true
- for the one that overriders it.
- */
+ for the one that overriders it. */
for (node = cgraph_nodes; node; node = node->next)
if (node->analyzed && cgraph_is_master_clone (node, true))
analyze_function (node);
pointer_set_destroy (visited_nodes);
visited_nodes = NULL;
+}
+
+
+/* Serialize the info. */
+
+static void
+write_summary (void)
+{
+ struct cgraph_node *node;
+ struct lto_simple_output_block *ob
+ = lto_create_simple_output_block (LTO_section_ipa_pure_const);
+ unsigned int count = 0;
+
+ for (node = cgraph_nodes; node; node = node->next)
+ if (node->analyzed && cgraph_is_master_clone (node, true))
+ count++;
+
+ lto_output_uleb128_stream (ob->main_stream, count);
+
+ /* Process all of the functions. */
+ for (node = cgraph_nodes; node; node = node->next)
+ if (node->analyzed && cgraph_is_master_clone (node, true))
+ {
+ unsigned HOST_WIDEST_INT flags = 0;
+ funct_state fs = get_function_state (node);
+
+ lto_output_fn_decl_index (ob->decl_state, ob->main_stream, node->decl);
+
+ lto_set_flags (&flags, fs->pure_const_state, 2);
+ lto_set_flag (&flags, fs->looping);
+ lto_set_flag (&flags, fs->state_set_in_source);
+ lto_output_uleb128_stream (ob->main_stream, flags);
+ }
+ lto_destroy_simple_output_block (ob);
+}
+
+
+/* Deserialize the info. */
+
+static void
+read_summary (void)
+{
+ struct lto_file_decl_data ** file_data_vec
+ = lto_get_file_decl_data ();
+ struct lto_file_decl_data * file_data;
+ unsigned int j = 0;
+
+ while ((file_data = file_data_vec[j++]))
+ {
+ unsigned int count;
+ unsigned int i;
+ const char *data;
+ size_t len;
+ struct lto_input_block *ib
+ = lto_create_simple_input_block (file_data,
+ LTO_section_ipa_pure_const,
+ &data, &len);
+
+ init_state ();
+
+ count = lto_input_uleb128 (ib);
+ for (i = 0; i < count; i++)
+ {
+ tree fn_decl = file_data->fn_decls [lto_input_uleb128 (ib)];
+ unsigned HOST_WIDEST_INT flags = lto_input_uleb128 (ib);
+ funct_state fs = XCNEW (struct funct_state_d);
+
+ set_function_state (cgraph_node (fn_decl), fs);
+ fs->state_set_in_source = lto_get_flag (&flags);
+ fs->looping = lto_get_flag (&flags);
+ fs->pure_const_state = lto_get_flags (&flags, 2);
+ }
+
+ lto_destroy_simple_input_block (file_data,
+ LTO_section_ipa_pure_const,
+ ib, data, len);
+ }
+}
+
+/* Produce the global information by preforming a transitive closure
+ on the local information that was produced by generate_summary.
+ Note that there is no function_transform pass since this only
+ updates the function_decl. */
+
+static unsigned int
+propagate (void)
+{
+ struct cgraph_node *node;
+ struct cgraph_node *w;
+ struct cgraph_node **order =
+ XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
+ int order_pos;
+ int i;
+ struct ipa_dfs_info * w_info;
+
+ order_pos = ipa_utils_reduced_inorder (order, true, false);
if (dump_file)
{
dump_cgraph (dump_file);
@@ -723,6 +861,8 @@ static_execute (void)
if (!w_l->state_set_in_source)
{
w_l->pure_const_state = pure_const_state;
+ w_l->looping = looping;
+
switch (pure_const_state)
{
case IPA_CONST:
@@ -754,17 +894,20 @@ static_execute (void)
/* Cleanup. */
for (node = cgraph_nodes; node; node = node->next)
- /* Get rid of the aux information. */
- if (node->aux)
- {
- w_info = (struct ipa_dfs_info *) node->aux;
- if (w_info->aux)
- free (w_info->aux);
- free (node->aux);
- node->aux = NULL;
- }
-
+ {
+ /* Get rid of the aux information. */
+ if (node->aux)
+ {
+ w_info = (struct ipa_dfs_info *) node->aux;
+ free (node->aux);
+ node->aux = NULL;
+ }
+ if (node->analyzed && cgraph_is_master_clone (node, true))
+ free (get_function_state (node));
+ }
+
free (order);
+ finish_state ();
return 0;
}
@@ -776,13 +919,13 @@ gate_pure_const (void)
&& !(errorcount || sorrycount));
}
-struct simple_ipa_opt_pass pass_ipa_pure_const =
+struct ipa_opt_pass pass_ipa_pure_const =
{
{
- SIMPLE_IPA_PASS,
+ IPA_PASS,
"pure-const", /* name */
gate_pure_const, /* gate */
- static_execute, /* execute */
+ propagate, /* execute */
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
@@ -792,7 +935,12 @@ struct simple_ipa_opt_pass pass_ipa_pure_const =
0, /* properties_destroyed */
0, /* todo_flags_start */
0 /* todo_flags_finish */
- }
+ },
+ generate_summary, /* generate_summary */
+ write_summary, /* write_summary */
+ read_summary, /* read_summary */
+ NULL, /* function_read_summary */
+ 0, /* TODOs */
+ NULL, /* function_transform */
+ NULL /* variable_transform */
};
-
-
diff --git a/gcc/lto-function-in.c b/gcc/lto-function-in.c
index 821f2a26625..83e1a93fb94 100644
--- a/gcc/lto-function-in.c
+++ b/gcc/lto-function-in.c
@@ -272,7 +272,7 @@ input_type_ref_1 (struct data_in *data_in, struct lto_input_block *ib)
}
}
else
- gcc_unreachable();
+ gcc_unreachable ();
LTO_DEBUG_UNDENT();
return result;
diff --git a/gcc/lto-function-out.c b/gcc/lto-function-out.c
index c61757c9b23..3c2e0a50c89 100644
--- a/gcc/lto-function-out.c
+++ b/gcc/lto-function-out.c
@@ -128,6 +128,17 @@ eq_string_slot_node (const void *p1, const void *p2)
}
+/* Free the string slot. */
+
+static void
+string_slot_free (void *p)
+{
+ struct string_slot *slot = (struct string_slot *)p;
+ free ((void *)slot->s);
+ free (slot);
+}
+
+
/* The output stream that contains the abbrev table for all of the
functions in this compilation unit. */
static void output_expr_operand (struct output_block *, tree);
@@ -182,7 +193,7 @@ create_output_block (enum lto_section_type section_type)
}
ob->string_hash_table
- = htab_create (37, hash_string_slot_node, eq_string_slot_node, free);
+ = htab_create (37, hash_string_slot_node, eq_string_slot_node, string_slot_free);
/* The unnamed labels must all be negative. */
ob->next_unnamed_label_index = -1;
@@ -255,6 +266,7 @@ output_string (struct output_block *ob,
struct string_slot s_slot;
s_slot.s = string;
s_slot.len = len;
+ s_slot.slot_num = 0;
slot = htab_find_slot (ob->string_hash_table, &s_slot, INSERT);
if (*slot == NULL)
@@ -264,8 +276,11 @@ output_string (struct output_block *ob,
struct string_slot *new_slot
= xmalloc (sizeof (struct string_slot));
unsigned int i;
+ char *new_string = xmalloc (len);
- new_slot->s = string;
+ memcpy (new_string, string, len);
+ new_slot->s = new_string;
+ new_slot->len = len;
new_slot->slot_num = start;
*slot = new_slot;
lto_output_uleb128_stream (index_stream, start);
@@ -555,7 +570,7 @@ type_function_context (const_tree type)
with the function body, not the file scope. */
static bool
-field_decl_is_local (tree decl)
+field_decl_is_local (tree decl ATTRIBUTE_UNUSED)
{
#ifdef STREAM_LOCAL_TYPES
return (decl_function_context (decl)
@@ -571,7 +586,7 @@ field_decl_is_local (tree decl)
with the function body, not the file scope. */
static bool
-type_decl_is_local (tree decl)
+type_decl_is_local (tree decl ATTRIBUTE_UNUSED)
{
#ifdef STREAM_LOCAL_TYPES
return (decl_function_context (decl)
@@ -620,7 +635,7 @@ static void
output_type_ref (struct output_block *ob, tree node)
{
LTO_DEBUG_TOKEN ("type_ref");
- output_type_ref_1 (ob, node);
+ lto_output_type_ref_index (ob->decl_state, ob->main_stream, node);
}
@@ -1072,17 +1087,8 @@ output_expr_operand (struct output_block *ob, tree expr)
case VAR_DECL:
if (TREE_STATIC (expr) || DECL_EXTERNAL (expr))
{
- /* Static or extern VAR_DECLs. */
- unsigned int index;
- bool new;
output_record_start (ob, NULL, NULL, LTO_var_decl1);
-
- new = lto_output_decl_index (ob->main_stream,
- ob->decl_state->var_decl_hash_table,
- &ob->decl_state->next_var_decl_index,
- expr, &index);
- if (new)
- VEC_safe_push (tree, heap, ob->decl_state->var_decls, expr);
+ lto_output_var_decl_index (ob->decl_state, ob->main_stream, expr);
}
else
{
@@ -1115,18 +1121,8 @@ output_expr_operand (struct output_block *ob, tree expr)
break;
case NAMESPACE_DECL:
- {
- unsigned int index;
- bool new;
- output_record_start (ob, NULL, NULL, tag);
-
- new = lto_output_decl_index (ob->main_stream,
- ob->decl_state->namespace_decl_hash_table,
- &ob->decl_state->next_namespace_decl_index,
- expr, &index);
- if (new)
- VEC_safe_push (tree, heap, ob->decl_state->namespace_decls, expr);
- }
+ output_record_start (ob, NULL, NULL, tag);
+ lto_output_namespace_decl_index (ob->decl_state, ob->main_stream, expr);
break;
case PARM_DECL:
@@ -2143,6 +2139,7 @@ lto_static_init (void)
RESET_BIT (lto_types_needed_for, RESX_EXPR);
RESET_BIT (lto_types_needed_for, SSA_NAME);
RESET_BIT (lto_types_needed_for, VAR_DECL);
+ RESET_BIT (lto_types_needed_for, RESULT_DECL);
RESET_BIT (lto_types_needed_for, TREE_LIST);
RESET_BIT (lto_types_needed_for, TREE_VEC);
RESET_BIT (lto_types_needed_for, TYPE_DECL);
@@ -2265,7 +2262,7 @@ output_function (struct cgraph_node* node)
else if (TYPE_P (context))
{
output_record_start (ob, NULL, NULL, LTO_type);
- output_type_ref_1 (ob, context);
+ lto_output_type_ref_index (ob->decl_state, ob->main_stream, context);
LTO_DEBUG_UNDENT ();
}
else
@@ -2365,7 +2362,7 @@ output_constructors_and_inits (void)
/* Main entry point from the pass manager. */
-static unsigned int
+static void
lto_output (void)
{
struct cgraph_node *node;
@@ -2385,17 +2382,15 @@ lto_output (void)
writing lto info. */
if (saved_section)
switch_to_section (saved_section);
-
- return 0;
}
-struct simple_ipa_opt_pass pass_ipa_lto_gimple_out =
+struct ipa_opt_pass pass_ipa_lto_gimple_out =
{
{
- SIMPLE_IPA_PASS,
+ IPA_PASS,
"lto_gimple_out", /* name */
gate_lto_out, /* gate */
- lto_output, /* execute */
+ NULL, /* execute */
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
@@ -2405,7 +2400,14 @@ struct simple_ipa_opt_pass pass_ipa_lto_gimple_out =
0, /* properties_destroyed */
0, /* todo_flags_start */
TODO_dump_func /* todo_flags_finish */
- }
+ },
+ NULL, /* generate_summary */
+ lto_output, /* write_summary */
+ NULL, /* read_summary */
+ NULL, /* function_read_summary */
+ 0, /* TODOs */
+ NULL, /* function_transform */
+ NULL /* variable_transform */
};
diff --git a/gcc/lto-header.h b/gcc/lto-header.h
index 73eb587d3e4..653049ddf3f 100644
--- a/gcc/lto-header.h
+++ b/gcc/lto-header.h
@@ -41,7 +41,8 @@ enum lto_section_type
LTO_section_decls,
LTO_section_function_body,
LTO_section_static_initializer,
- LTO_section_cgraph
+ LTO_section_cgraph,
+ LTO_section_ipa_pure_const
};
struct lto_header
@@ -51,6 +52,16 @@ struct lto_header
enum lto_section_type section_type;
};
+/* The is the first part of the record in the .o file for many of the
+ ipa passes. */
+struct lto_simple_header
+{
+ struct lto_header lto_header; /* The header for all types of sections. */
+ int32_t main_size; /* Size of main gimple body of function. */
+ int32_t debug_main_size; /* Size of main stream debugging information. */
+ int32_t compressed_size;
+};
+
/* In lto-section-out.c. */
char *lto_get_section_name (enum lto_section_type, const char *);
section *lto_get_section (enum lto_section_type, const char *);
diff --git a/gcc/lto-section-in.c b/gcc/lto-section-in.c
index 02ceba3f5a4..62e54985eaa 100644
--- a/gcc/lto-section-in.c
+++ b/gcc/lto-section-in.c
@@ -51,6 +51,32 @@ Boston, MA 02110-1301, USA. */
#include <ctype.h>
#include "cpplib.h"
+
+/* Return 0 or 1 based on the last bit of FLAGS and right shift FLAGS
+ by 1. */
+
+unsigned int
+lto_get_flag (unsigned HOST_WIDEST_INT *flags)
+{
+ unsigned int result = *flags & 1;
+ *flags = *flags >> 1;
+ return result;
+}
+
+
+/* Return an integer based on the last WIDTH bits of FLAGS and right
+ shift FLAGS by WIDTH. */
+
+unsigned int
+lto_get_flags (unsigned HOST_WIDEST_INT *flags, unsigned int width)
+{
+ unsigned HOST_WIDEST_INT mask = 1 << (((unsigned HOST_WIDEST_INT)width) - 1);
+ unsigned int result = *flags & mask;
+ *flags = *flags >> width;
+ return result;
+}
+
+
unsigned char
lto_input_1_unsigned (struct lto_input_block *ib)
{
@@ -183,71 +209,128 @@ lto_input_integer (struct lto_input_block *ib, tree type)
}
}
-/*****************************************************************************/
-/* Input routines for reading sections from .o files. */
-/*****************************************************************************/
-/* Get the section data of length LEN from FILENAME starting at
- OFFSET. The data segment must be freed by the caller when the
- caller is finished. Returns NULL if all was not well. */
+/* Hooks so that the ipa passes can call into the lto front end to get
+ sections. */
+
+static struct lto_file_decl_data ** file_decl_data;
+static lto_get_section_data_f* get_section_f;
+static lto_free_section_data_f* free_section_f;
+
-static char *
-lto_read_section_data (const char *file_name, size_t offset, size_t len)
+/* This is called from the lto front end to set up the hooks that are
+ used by the ipa passes to get the data that they will
+ deserialize. */
+
+void
+lto_set_in_hooks (struct lto_file_decl_data ** data,
+ lto_get_section_data_f* get_f,
+ lto_free_section_data_f* free_f)
{
- FILE * ofile = fopen (file_name, "r");
- char * data;
- int result;
+ file_decl_data = data;
+ get_section_f = get_f;
+ free_section_f = free_f;
+}
- if (!ofile)
- return NULL;
- data = xmalloc (len);
-
- result = fseek (ofile, offset, SEEK_SET);
- if (result)
- {
- free (data);
- fclose (ofile);
- return NULL;
- }
- result = fread (data, len, 1, ofile);
- if (result == 0)
- {
- free (data);
- fclose (ofile);
- return NULL;
- }
-
- fclose (ofile);
- return data;
-}
+/* Return an array of file decl datas for all of the files passed to
+ this compilation. */
+
+struct lto_file_decl_data **
+lto_get_file_decl_data (void)
+{
+ gcc_assert (file_decl_data);
+ return file_decl_data;
+}
-/* Get the section data from FILE_DATA of SECTION_TYPE with NAME.
- NAME will be null unless the section type is for a function
- body. */
+/* Return a char pointer to the start of a data stream for an lto pass
+ or function. FILE_DATA indicates where to obtain the data.
+ SECTION_TYPE is the type of information to be obtained. NAME is
+ the name of the function and is only used when finding a function
+ body; otherwise it is NULL. LEN is the size of the data
+ returned. */
-char *
+const char*
lto_get_section_data (struct lto_file_decl_data *file_data,
enum lto_section_type section_type,
- const char *name)
+ const char *name,
+ size_t *len)
+{
+ gcc_assert (get_section_f);
+ return (get_section_f) (file_data, section_type, name, len);
+}
+
+
+/* Return the data found from the above call. The first three
+ parameters are the same as above. DATA is the data to be freed and
+ LEN is the length of that data. */
+
+void
+lto_free_section_data (struct lto_file_decl_data *file_data,
+ enum lto_section_type section_type,
+ const char *name,
+ const char *data,
+ size_t len)
{
- htab_t section_hash_table = file_data->section_hash_table;
- struct lto_section_slot *f_slot;
- struct lto_section_slot s_slot;
- char *section_name = lto_get_section_name (section_type, name);
- char * data = NULL;
-
- s_slot.name = section_name;
- f_slot = (struct lto_section_slot *)htab_find (section_hash_table, &s_slot);
- if (f_slot)
- data = lto_read_section_data (file_data->file_name, f_slot->start,
- f_slot->len);
-
- free (section_name);
- return data;
+ gcc_assert (free_section_f);
+ (free_section_f) (file_data, section_type, name, data, len);
+}
+
+
+/* Load a section of type SECTION_TYPE from FILE_DATA, parse the
+ header and then return an input block pointing to the section. The
+ raw pointer to the section is returned in DATAR and LEN. These are
+ used to free the section. */
+
+struct lto_input_block *
+lto_create_simple_input_block (struct lto_file_decl_data *file_data,
+ enum lto_section_type section_type,
+ const char **datar, size_t *len)
+{
+ const char *data = lto_get_section_data (file_data, section_type, NULL, len);
+ const struct lto_simple_header * header
+ = (const struct lto_simple_header *) data;
+ struct lto_input_block* ib_main = XNEW (struct lto_input_block);
+ int32_t main_offset = sizeof (struct lto_simple_header);
+#ifdef LTO_STREAM_DEBUGGING
+ int32_t debug_main_offset = main_offset + header->main_size;
+ struct lto_input_block *debug_main = XNEW (struct lto_input_block);
+#endif
+
+ *datar = data;
+ LTO_INIT_INPUT_BLOCK_PTR (ib_main, data + main_offset,
+ 0, header->main_size);
+#ifdef LTO_STREAM_DEBUGGING
+ lto_debug_context.out = lto_debug_in_fun;
+ LTO_INIT_INPUT_BLOCK_PTR (debug_main, data + debug_main_offset,
+ 0, header->debug_main_size);
+ lto_debug_context.current_data = debug_main;
+ lto_debug_context.indent = 0;
+#endif
+
+ return ib_main;
}
+/* Close the section returned from a call to
+ LTO_CREATE_SIMPLE_INPUT_BLOCK. IB is the input block returned from
+ that call. The FILE_DATA and SECTION_TYPE are the same as what was
+ passed to that call and the DATA and LEN are what was returned from
+ that call. */
+
+void
+lto_destroy_simple_input_block (struct lto_file_decl_data *file_data,
+ enum lto_section_type section_type,
+ struct lto_input_block *ib,
+ const char *data, size_t len)
+{
+ free (ib);
+#ifdef LTO_STREAM_DEBUGGING
+ free (lto_debug_context.current_data);
+#endif
+ lto_free_section_data (file_data, section_type, NULL, data, len);
+}
+
/*****************************************************************************/
/* Stream debugging support code. */
/*****************************************************************************/
diff --git a/gcc/lto-section-in.h b/gcc/lto-section-in.h
index ebd17db44e8..2bcbba02e27 100644
--- a/gcc/lto-section-in.h
+++ b/gcc/lto-section-in.h
@@ -21,6 +21,8 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_LTO_SECTION_IN_H
#define GCC_LTO_SECTION_IN_H
+#include "lto-header.h"
+
struct lto_input_block
{
const char *data;
@@ -35,15 +37,12 @@ struct lto_input_block
BASE.len = L; \
} while (0)
-/* Hash table entry to hold the start offset and length of an lto
- section in a .o file. */
-
-struct lto_section_slot {
- const char * name;
- unsigned int start;
- unsigned int len;
-};
-
+#define LTO_INIT_INPUT_BLOCK_PTR(BASE,D,P,L) \
+ do { \
+ BASE->data = D; \
+ BASE->p = P; \
+ BASE->len = L; \
+ } while (0)
/* One of these is allocated for each object file that being compiled
by lto. This structure contains the tables that are needed for the
@@ -70,10 +69,65 @@ struct lto_file_decl_data
have been archived. */
const char * file_name;
+ /* If the file is open, this is the fd of the mapped section. This is -1 if
+ the file has not yet been opened. */
+ int fd;
+
/* Hash table to contains the location of the lto bodies in file_name. */
htab_t section_hash_table;
};
+/* Return a char pointer to the start of a data stream for an lto pass
+ or function. The first parameter is the file data that contains
+ the information. The second parameter is the type of information
+ to be obtained. The third parameter is the name of the function
+ and is only used when finding a function body; otherwise it is
+ NULL. The fourth parameter is the length of the data returned. */
+typedef const char* (lto_get_section_data_f) (struct lto_file_decl_data *,
+ enum lto_section_type,
+ const char *,
+ size_t *);
+
+/* Return the data found from the above call. The first three
+ parameters are the same as above. The fourth parameter is the data
+ itself and the fifth is the lenght of the data. */
+typedef void (lto_free_section_data_f) (struct lto_file_decl_data *,
+ enum lto_section_type,
+ const char *,
+ const char *,
+ size_t);
+
+extern struct lto_input_block *
+lto_create_simple_input_block (struct lto_file_decl_data *,
+ enum lto_section_type, const char **, size_t *);
+extern void
+lto_destroy_simple_input_block (struct lto_file_decl_data *,
+ enum lto_section_type,
+ struct lto_input_block *, const char *, size_t);
+
+
+/* lto-function-in.c */
+
+/* FN is a FUNCTION_DECL. DATA is the LTO data written out during
+ ordinary compilation, encoding the body of FN. FILE_DATA are the
+ tables holding all of the global types and decls used by FN. Upon
+ return, DECL_SAVED_TREE for FN contains the reconstituted body of
+ FN and DECL_INITIAL contains the BLOCK tree for the function.
+ However, it is not this function's responsibility to provide FN to
+ the optimizers or code-generators; that will be done by the
+ caller. */
+extern void
+lto_input_function_body (struct lto_file_decl_data* file_data,
+ tree fn, const char *data);
+
+/* DATA is the LTO data written out during ordinary compilation,
+ encoding the initializers for the static and external vars.
+ FILE_DATA are the tables holding all of the global types and decls
+ used in that file. */
+extern void
+lto_input_constructors_and_inits (struct lto_file_decl_data* file_data,
+ const char *data);
+
/* DATA is the LTO data written out during ordinary compilation,
encoding the initializers for the static and external vars.
FILE_DATA are the tables holding all of the global types and decls
@@ -81,13 +135,23 @@ struct lto_file_decl_data
extern void
lto_input_cgraph (struct lto_file_decl_data* file_data, const char *data);
+/* lto-section-in.c */
+
+extern unsigned int lto_get_flag (unsigned HOST_WIDEST_INT *);
+extern unsigned int lto_get_flags (unsigned HOST_WIDEST_INT *, unsigned int);
+extern void lto_set_in_hooks (struct lto_file_decl_data **,
+ lto_get_section_data_f*,
+ lto_free_section_data_f*);
+extern struct lto_file_decl_data **lto_get_file_decl_data (void);
+extern const char* lto_get_section_data (struct lto_file_decl_data *, enum lto_section_type,
+ const char *, size_t *);
+extern void lto_free_section_data (struct lto_file_decl_data *, enum lto_section_type,
+ const char *, const char *, size_t);
extern unsigned char lto_input_1_unsigned (struct lto_input_block *);
extern unsigned HOST_WIDE_INT lto_input_uleb128 (struct lto_input_block *);
extern unsigned HOST_WIDEST_INT lto_input_widest_uint_uleb128 (struct lto_input_block *);
extern HOST_WIDE_INT lto_input_sleb128 (struct lto_input_block *);
extern tree lto_input_integer (struct lto_input_block *, tree);
-extern char *lto_get_section_data (struct lto_file_decl_data *, enum lto_section_type,
- const char*);
#ifdef LTO_STREAM_DEBUGGING
extern void lto_debug_in_fun (struct lto_debug_context *, char);
diff --git a/gcc/lto-section-out.c b/gcc/lto-section-out.c
index d6ddcadb48a..5d4df6ad9b7 100644
--- a/gcc/lto-section-out.c
+++ b/gcc/lto-section-out.c
@@ -53,6 +53,28 @@ along with GCC; see the file COPYING3. If not see
#include <strings.h>
+/* Add FLAG onto the end of BASE. */
+
+void
+lto_set_flag (unsigned HOST_WIDEST_INT *base, unsigned int flag)
+{
+ *base = *base << 1;
+ if (flag)
+ *base |= 1;
+}
+
+/* Add FLAGS of WIDTH onto the end of BASE. */
+
+void
+lto_set_flags (unsigned HOST_WIDEST_INT *base, unsigned int flag, unsigned int width)
+{
+ unsigned HOST_WIDEST_INT mask = 1 < (((unsigned HOST_WIDEST_INT)width) - 1);
+
+ *base = *base << width;
+ *base |= (flag & mask);
+}
+
+
/* Returns a hash code for P. */
hashval_t
@@ -158,6 +180,9 @@ lto_get_section_name (enum lto_section_type section_type, const char *name)
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);
+
default:
gcc_unreachable ();
}
@@ -178,9 +203,9 @@ lto_get_section (enum lto_section_type section_type, const char *name)
}
-/*****************************************************************************/
-/* Output routines shared by all of the serialization passes. */
-/*****************************************************************************/
+/*****************************************************************************
+ Output routines shared by all of the serialization passes.
+*****************************************************************************/
/* Write all of the chars in OBS to the assembler. Recycle the blocks
@@ -420,6 +445,179 @@ lto_output_decl_index (struct lto_output_stream *obs, htab_t table,
}
}
+
+/* Output a field DECL to OBS. */
+
+void
+lto_output_field_decl_index (struct lto_out_decl_state *decl_state,
+ struct lto_output_stream * obs, tree decl)
+{
+ unsigned int index;
+ bool new = lto_output_decl_index (obs,
+ decl_state->field_decl_hash_table,
+ &decl_state->next_field_decl_index,
+ decl, &index);
+ if (new)
+ VEC_safe_push (tree, heap, decl_state->field_decls, decl);
+}
+
+
+/* Output a function DECL to OBS. */
+
+void
+lto_output_fn_decl_index (struct lto_out_decl_state *decl_state,
+ struct lto_output_stream * obs, tree decl)
+{
+ unsigned int index;
+ bool new = lto_output_decl_index (obs,
+ decl_state->fn_decl_hash_table,
+ &decl_state->next_fn_decl_index,
+ decl, &index);
+ if (new)
+ VEC_safe_push (tree, heap, decl_state->fn_decls, decl);
+}
+
+
+/* Output a namespace DECL to OBS. */
+
+void
+lto_output_namespace_decl_index (struct lto_out_decl_state *decl_state,
+ struct lto_output_stream * obs, tree decl)
+{
+ unsigned int index;
+ bool new = lto_output_decl_index (obs,
+ decl_state->namespace_decl_hash_table,
+ &decl_state->next_namespace_decl_index,
+ decl, &index);
+ if (new)
+ VEC_safe_push (tree, heap, decl_state->namespace_decls, decl);
+}
+
+
+/* Output a static or extern var DECL to OBS. */
+
+void
+lto_output_var_decl_index (struct lto_out_decl_state *decl_state,
+ struct lto_output_stream * obs, tree decl)
+{
+ unsigned int index;
+ bool new = lto_output_decl_index (obs,
+ decl_state->var_decl_hash_table,
+ &decl_state->next_var_decl_index,
+ decl, &index);
+ if (new)
+ VEC_safe_push (tree, heap, decl_state->var_decls, decl);
+}
+
+
+/* Output a type DECL to OBS. */
+
+void
+lto_output_type_decl_index (struct lto_out_decl_state *decl_state,
+ struct lto_output_stream * obs, tree decl)
+{
+ unsigned int index;
+ bool new = lto_output_decl_index (obs,
+ decl_state->type_decl_hash_table,
+ &decl_state->next_type_decl_index,
+ decl, &index);
+ if (new)
+ VEC_safe_push (tree, heap, decl_state->type_decls, decl);
+}
+
+
+/* Output a type REF to OBS. */
+
+void
+lto_output_type_ref_index (struct lto_out_decl_state *decl_state,
+ struct lto_output_stream *obs, tree ref)
+{
+ unsigned int index;
+ bool new = lto_output_decl_index (obs,
+ decl_state->type_hash_table,
+ &decl_state->next_type_index,
+ ref, &index);
+
+ if (new)
+ VEC_safe_push (tree, heap, decl_state->types, ref);
+}
+
+
+/*****************************************************************************
+ Convenience routines used by the ipa passes to serialize their information.
+*****************************************************************************/
+
+/* Create the output block and return it. */
+
+struct lto_simple_output_block *
+lto_create_simple_output_block (enum lto_section_type section_type)
+{
+ struct lto_simple_output_block *ob
+ = xcalloc (1, sizeof (struct lto_simple_output_block));
+
+ ob->section_type = section_type;
+ ob->decl_state = lto_get_out_decl_state ();
+ ob->main_stream = xcalloc (1, sizeof (struct lto_output_stream));
+
+#ifdef LTO_STREAM_DEBUGGING
+ lto_debug_context.out = lto_debug_out_fun;
+ lto_debug_context.indent = 0;
+#endif
+
+ LTO_SET_DEBUGGING_STREAM (debug_main_stream, main_data);
+
+ return ob;
+}
+
+
+/* Produce the section that holds the cgraph. */
+
+void
+lto_destroy_simple_output_block (struct lto_simple_output_block *ob)
+{
+ struct lto_simple_header header;
+ section *saved_section = in_section;
+ section *section = lto_get_section (ob->section_type, NULL);
+
+ memset (&header, 0, sizeof (struct lto_simple_header));
+
+ /* The entire header is stream computed here. */
+ switch_to_section (section);
+
+ /* Write the header which says how to decode the pieces of the
+ t. */
+ header.lto_header.major_version = LTO_major_version;
+ header.lto_header.minor_version = LTO_minor_version;
+ header.lto_header.section_type = LTO_section_cgraph;
+
+ header.compressed_size = 0;
+
+ header.main_size = ob->main_stream->total_size;
+#ifdef LTO_STREAM_DEBUGGING
+ header.debug_main_size = ob->debug_main_stream->total_size;
+#else
+ header.debug_main_size = -1;
+#endif
+
+ assemble_string ((const char *)&header,
+ sizeof (struct lto_simple_header));
+
+ lto_write_stream (ob->main_stream);
+#ifdef LTO_STREAM_DEBUGGING
+ lto_write_stream (ob->debug_main_stream);
+#endif
+
+ /* Put back the assembly section that was there before we started
+ writing lto info. */
+ if (saved_section)
+ switch_to_section (saved_section);
+
+ free (ob->main_stream);
+ LTO_CLEAR_DEBUGGING_STREAM (debug_main_stream);
+ free (ob);
+}
+
+
/* This part is used to store all of the global decls and types that
are serialized out in this file so that a table for this file can
be built that allows the decls and types to be reconnected to the
@@ -586,7 +784,7 @@ write_global_references (struct output_block *ob, VEC(tree,heap) *v)
this file to be written in to a section that can then be read in to
recover these on other side. */
-static unsigned int
+static void
produce_asm_for_decls (void)
{
struct lto_out_decl_state *out_state = lto_get_out_decl_state ();
@@ -674,10 +872,6 @@ produce_asm_for_decls (void)
VEC_free (tree, heap, out_state->type_decls);
VEC_free (tree, heap, out_state->namespace_decls);
VEC_free (tree, heap, out_state->types);
-
- free (out_state);
-
- return 0;
}
@@ -692,13 +886,13 @@ gate_lto_out (void)
}
-struct simple_ipa_opt_pass pass_ipa_lto_finish_out =
+struct ipa_opt_pass pass_ipa_lto_finish_out =
{
{
- SIMPLE_IPA_PASS,
+ IPA_PASS,
"lto_decls_out", /* name */
gate_lto_out, /* gate */
- produce_asm_for_decls, /* execute */
+ NULL, /* execute */
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
@@ -708,7 +902,14 @@ struct simple_ipa_opt_pass pass_ipa_lto_finish_out =
0, /* properties_destroyed */
0, /* todo_flags_start */
0 /* todo_flags_finish */
- }
+ },
+ NULL, /* generate_summary */
+ produce_asm_for_decls, /* write_summary */
+ NULL, /* read_summary */
+ NULL, /* function_read_summary */
+ 0, /* TODOs */
+ NULL, /* function_transform */
+ NULL /* variable_transform */
};
#ifdef LTO_STREAM_DEBUGGING
diff --git a/gcc/lto-section-out.h b/gcc/lto-section-out.h
index c749cc7ec59..6b1d6320d62 100644
--- a/gcc/lto-section-out.h
+++ b/gcc/lto-section-out.h
@@ -115,13 +115,33 @@ struct lto_out_decl_state
VEC(tree,heap) *types;
};
+
+/* 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
+{
+ enum lto_section_type section_type;
+ struct lto_out_decl_state *decl_state;
+
+ /* The stream that the main tree codes are written to. */
+ struct lto_output_stream *main_stream;
+
+#ifdef LTO_STREAM_DEBUGGING
+ /* The stream that contains the gimple debugging information. */
+ struct lto_output_stream *debug_main_stream;
+#endif
+};
+
+
+void lto_set_flag (unsigned HOST_WIDEST_INT *, unsigned int);
+void lto_set_flags (unsigned HOST_WIDEST_INT *, unsigned int, unsigned int);
hashval_t lto_hash_decl_slot_node (const void *);
int lto_eq_decl_slot_node (const void *, const void *);
hashval_t lto_hash_type_slot_node (const void *);
int lto_eq_type_slot_node (const void *, const void *);
hashval_t lto_hash_global_slot_node (const void *);
int lto_eq_global_slot_node (const void *, const void *);
-struct lto_out_decl_state *lto_get_out_decl_state (void);
+
void lto_write_stream (struct lto_output_stream *);
void lto_output_1_stream (struct lto_output_stream *, char);
void lto_output_uleb128_stream (struct lto_output_stream *,
@@ -130,8 +150,26 @@ void lto_output_widest_uint_uleb128_stream (struct lto_output_stream *,
unsigned HOST_WIDEST_INT);
void lto_output_sleb128_stream (struct lto_output_stream *, HOST_WIDE_INT);
void lto_output_integer_stream (struct lto_output_stream *, tree);
-bool lto_output_decl_index (struct lto_output_stream *, htab_t, unsigned int *,
- tree, unsigned int *);
+bool lto_output_decl_index (struct lto_output_stream *, htab_t,
+ unsigned int *, tree, unsigned int *);
+void lto_output_field_decl_index (struct lto_out_decl_state *,
+ struct lto_output_stream *, tree);
+void lto_output_fn_decl_index (struct lto_out_decl_state *,
+ struct lto_output_stream *, tree);
+void lto_output_namespace_decl_index (struct lto_out_decl_state *,
+ struct lto_output_stream *, tree);
+void lto_output_var_decl_index (struct lto_out_decl_state *,
+ struct lto_output_stream *, tree);
+void lto_output_type_decl_index (struct lto_out_decl_state *,
+ struct lto_output_stream *, tree);
+void lto_output_type_ref_index (struct lto_out_decl_state *,
+ struct lto_output_stream *, tree);
+
+struct lto_simple_output_block *lto_create_simple_output_block (enum lto_section_type);
+void lto_destroy_simple_output_block (struct lto_simple_output_block * ob);
+
+struct lto_out_decl_state *lto_get_out_decl_state (void);
+
bool gate_lto_out (void);
#endif /* GCC_LTO_SECTION_OUT_H */
diff --git a/gcc/lto-tree-out.h b/gcc/lto-tree-out.h
index 580625ae7ef..48d0f685e5d 100644
--- a/gcc/lto-tree-out.h
+++ b/gcc/lto-tree-out.h
@@ -90,7 +90,6 @@ struct output_block
/* The hash table that contains the set of strings we have seen so
far and the indexes assigned to them. */
htab_t string_hash_table;
- unsigned int next_string_index;
/* The current cgraph_node that we are currently serializing. Null
if we are serializing something else. */
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index 266ca02b691..a288a0034ab 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -1,3 +1,19 @@
+2008-06-07 Kenneth Zadeck <zadeck@naturalbridge.com>
+ Jan Hubicka <jh@suse.cz>
+
+ * lto.c (sys/mman.h, tree-pass.h): New includes.
+ (lto_materialize_constructors_and_inits,
+ lto_materialize_function): Keeps length of section.
+ (lto_materialize_cgraph): Removed.
+ (lto_read_decls): Initialize fd field.
+ (lto_file_read): Different return type and removed much code to
+ lto_main.
+ (page_mask): New variable.
+ (lto_read_section_data, get_section_data, free_section_data): New
+ functions.
+ (lto_main): Now calls pass manager, sets the hooks so that the ipa
+ passes can get the section data.
+
2008-06-04 Ollie Wild <aaw@google.com>
* lto.c: Remove inclusion of dwarf2.h and dwarf2out.h.
diff --git a/gcc/lto/Make-lang.in b/gcc/lto/Make-lang.in
index 54305549f20..e9d2f5ff321 100644
--- a/gcc/lto/Make-lang.in
+++ b/gcc/lto/Make-lang.in
@@ -80,8 +80,9 @@ lto/lto-lang.o: lto/lto-lang.c $(CONFIG_H) coretypes.h debug.h \
flags.h $(GGC_H) langhooks.h $(LANGHOOKS_DEF_H) $(SYSTEM_H) \
$(TM_H) lto/lto-tree.h $(LTO_H) gtype-lto.h gt-lto-lto-lang.h
lto/lto.o: lto/lto.c $(CONFIG_H) $(CGRAPH_H) coretypes.h \
- $(GGC_H) opts.h $(SYSTEM_H) toplev.h $(TM_H) $(LTO_H) \
- gt-lto-lto.h lto-section.h lto-section-in.h
+ $(GGC_H) opts.h $(SYSTEM_H) toplev.h $(TM_H) $(LTO_H) langhooks.h \
+ lto/lto-tree.h dwarf2out.h tm.h tree-ssa-operands.h \
+ gt-lto-lto.h lto-section.h lto-section-in.h tree-pass.h
lto/lto-elf.o: lto/lto-elf.c $(CONFIG_H) coretypes.h $(SYSTEM_H) \
toplev.h $(LTO_H) $(TM_H)
lto/lto-symtab.o: lto/lto-symtab.c $(CONFIG_H) coretypes.h \
diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
index 4e3a55c973b..2b7e5a242e3 100644
--- a/gcc/lto/lto.c
+++ b/gcc/lto/lto.c
@@ -19,6 +19,7 @@ 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 <sys/mman.h>
#include "config.h"
#include "system.h"
#include "coretypes.h"
@@ -36,6 +37,7 @@ Boston, MA 02110-1301, USA. */
#include "lto-section-in.h"
#include "lto-tree-in.h"
#include "lto-tags.h" /* For LTO_tree_tag_names. */
+#include "tree-pass.h"
/* Read the constructors and inits. */
@@ -43,9 +45,11 @@ Boston, MA 02110-1301, USA. */
static void
lto_materialize_constructors_and_inits (struct lto_file_decl_data * file_data)
{
- const char *data = lto_get_section_data (file_data, LTO_section_static_initializer, NULL);
+ size_t len;
+ const char *data = lto_get_section_data (file_data,
+ LTO_section_static_initializer, NULL, &len);
lto_input_constructors_and_inits (file_data, data);
- free ((char *)data);
+ lto_free_section_data (file_data, LTO_section_static_initializer, NULL, data, len);
}
/* Read the function body for the function associated with NODE if possible. */
@@ -56,10 +60,12 @@ lto_materialize_function (struct cgraph_node *node)
tree decl = node->decl;
struct lto_file_decl_data *file_data = node->local.lto_file_data;
const char *data;
+ size_t len;
tree step;
+ const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
data = lto_get_section_data (file_data, LTO_section_function_body,
- IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
+ name, &len);
if (data)
{
struct function *fn;
@@ -71,7 +77,7 @@ lto_materialize_function (struct cgraph_node *node)
allocate_struct_function (decl, false);
lto_input_function_body (file_data, decl, data);
fn = DECL_STRUCT_FUNCTION (decl);
- free ((char *)data);
+ lto_free_section_data (file_data, LTO_section_function_body, name, data, len);
/* Look for initializers of constant variables and private
statics. */
@@ -98,16 +104,6 @@ lto_materialize_function (struct cgraph_node *node)
cgraph_mark_reachable_node (cgraph_node (decl));
}
-/* Read the cgraph for this file. */
-
-static void
-lto_materialize_cgraph (struct lto_file_decl_data * file_data)
-{
- const char *data = lto_get_section_data (file_data, LTO_section_cgraph, NULL);
- lto_input_cgraph (file_data, data);
- free ((char *)data);
-}
-
/* ### */
/* Initialize the globals vector with pointers to well-known trees. */
@@ -263,39 +259,146 @@ lto_read_decls (struct lto_file_decl_data *decl_data, const void *data)
/* Generate a TREE representation for all types and external decls
entities in FILE. If an entity in FILE has already been read (from
- another object file), merge the two entities. Returns TRUE iff
- FILE was successfully processed.
+ another object file), merge the two entities. Returns the
+ file_data from the last context.
+
+ FIXME, this is a bug that will go away with Maddox's streaming
+ merge since there will no longer be contexts.
Read all of the globals out of the file. Then read the cgraph
and process the .o index into the cgraph nodes so that it can open
the .o file to load the functions and ipa information. */
-static bool
+static struct lto_file_decl_data*
lto_file_read (lto_file *file)
{
struct lto_file_decl_data* file_data;
char *data;
+ size_t len;
+ htab_t section_hash_table;
file_data = xmalloc (sizeof (struct lto_file_decl_data));
file_data->file_name = file->filename;
- file_data->section_hash_table = lto_elf_build_section_table (file);
-
- data = lto_get_section_data (file_data, LTO_section_decls, NULL);
+ file_data->fd = -1;
+ section_hash_table = lto_elf_build_section_table (file);
+ file_data->section_hash_table = section_hash_table;
+
+ data = lto_get_section_data (file_data, LTO_section_decls, NULL, &len);
lto_read_decls (file_data, data);
+ lto_free_section_data (file_data, LTO_section_decls, NULL, data, len);
+
+ /* ### We never free file_data. */
- free ((char *)data);
+ return file_data;
+}
- lto_materialize_constructors_and_inits (file_data);
+/****************************************************************************
+ Input routines for reading sections from .o files.
- lto_materialize_cgraph (file_data);
+ FIXME: These routines may need to be generalized. They assume that
+ the .o file can be read into memory and the secions just mapped.
+ This may not be true if the .o file is in some form of archive.
+****************************************************************************/
+
+/* Page size of machine is used for mmap and munmap calls. */
+static size_t page_mask;
+
+/* Get the section data of length LEN from FILENAME starting at
+ OFFSET. The data segment must be freed by the caller when the
+ caller is finished. Returns NULL if all was not well. */
+
+static char *
+lto_read_section_data (struct lto_file_decl_data *file_data,
+ intptr_t offset, size_t len)
+{
+ char *result;
+ intptr_t computed_len;
+ intptr_t computed_offset;
+ intptr_t diff;
+
+ if (!page_mask)
+ {
+ size_t page_size = sysconf (_SC_PAGE_SIZE);
+ page_mask = ~(page_size - 1);
+ }
+
+ if (file_data->fd == -1)
+ file_data->fd = open (file_data->file_name, O_RDONLY);
+
+ if (file_data->fd == -1)
+ return NULL;
+
+ computed_offset = offset & page_mask;
+ diff = offset - computed_offset;
+ computed_len = len + diff;
+
+ result = mmap (NULL, computed_len, PROT_READ, MAP_PRIVATE,
+ file_data->fd, computed_offset);
+ if (result == MAP_FAILED)
+ {
+ close (file_data->fd);
+ return NULL;
+ }
+
+ return result + diff;
+}
- /* ### We never free file_data. */
- return true;
+/* Get the section data from FILE_DATA of SECTION_TYPE with NAME.
+ NAME will be null unless the section type is for a function
+ body. */
+
+static const char *
+get_section_data (struct lto_file_decl_data *file_data,
+ enum lto_section_type section_type,
+ const char *name,
+ size_t *len)
+{
+ htab_t section_hash_table = file_data->section_hash_table;
+ struct lto_section_slot *f_slot;
+ struct lto_section_slot s_slot;
+ const char *section_name = lto_get_section_name (section_type, name);
+ char * data = NULL;
+
+ s_slot.name = section_name;
+ f_slot = (struct lto_section_slot *)htab_find (section_hash_table, &s_slot);
+ if (f_slot)
+ {
+ data = lto_read_section_data (file_data, f_slot->start, f_slot->len);
+ *len = f_slot->len;
+ }
+
+ free ((char *)section_name);
+ return data;
}
+
+/* Free the section data from FILE_DATA of SECTION_TYPE with NAME that
+ starts at OFFSET and has LEN bytes. */
+
+static void
+free_section_data (struct lto_file_decl_data *file_data,
+ enum lto_section_type section_type ATTRIBUTE_UNUSED,
+ const char *name ATTRIBUTE_UNUSED,
+ const char *offset, size_t len)
+{
+ intptr_t computed_len;
+ intptr_t computed_offset;
+ intptr_t diff;
+
+ if (file_data->fd == -1)
+ return;
+
+ computed_offset = ((intptr_t)offset) & page_mask;
+ diff = (intptr_t)offset - computed_offset;
+ computed_len = len + diff;
+
+ munmap ((void *)computed_offset, computed_len);
+}
+
+
/* Needed so the garbage collector knows to root around in functions we
have not yet materialized and the huge DIE -> tree table we keep
around. */
@@ -304,9 +407,17 @@ static GTY(()) lto_file *current_lto_file;
void
lto_main (int debug_p ATTRIBUTE_UNUSED)
{
- unsigned i;
+ unsigned int i;
+ unsigned int j = 0;
tree decl;
struct cgraph_node *node;
+ struct lto_file_decl_data** all_file_decl_data
+ = XNEWVEC (struct lto_file_decl_data*, num_in_fnames + 1);
+ struct lto_file_decl_data* file_data = NULL;
+
+ /* Set the hooks so that all of the ipa passes can read in their data. */
+ lto_set_in_hooks (all_file_decl_data, get_section_data,
+ free_section_data);
/* Read all of the object files specified on the command line. */
for (i = 0; i < num_in_fnames; ++i)
@@ -314,12 +425,29 @@ lto_main (int debug_p ATTRIBUTE_UNUSED)
current_lto_file = lto_elf_file_open (in_fnames[i]);
if (!current_lto_file)
break;
- if (!lto_file_read (current_lto_file))
+ file_data = lto_file_read (current_lto_file);
+ if (!file_data)
break;
+
+ all_file_decl_data [j++] = file_data;
+
lto_elf_file_close (current_lto_file);
current_lto_file = NULL;
}
+ all_file_decl_data [j] = NULL;
+
+ /* FIXME!!! This loop needs to be changed to use the pass manager to
+ call the ipa passes directly. */
+ for (i = 0; i < j; i++)
+ {
+ struct lto_file_decl_data* file_data = all_file_decl_data [i];
+
+ lto_materialize_constructors_and_inits (file_data);
+ }
+
+ ipa_read_summaries ();
+
/* Now that we have input the cgraph, we need to clear all of the aux
nodes and read the functions.
@@ -336,7 +464,6 @@ lto_main (int debug_p ATTRIBUTE_UNUSED)
issues. */
for (node = cgraph_nodes; node; node = node->next)
{
- node->aux = NULL;
/* FIXME!!! There really needs to be some check to see if the
function is really not external here. Currently the only
check is to see if the section was defined in the file_data
diff --git a/gcc/lto/lto.h b/gcc/lto/lto.h
index 099315b34b3..7c53474a431 100644
--- a/gcc/lto/lto.h
+++ b/gcc/lto/lto.h
@@ -84,4 +84,31 @@ extern void lto_elf_file_close (lto_file *file);
/* Build and index of all lto sections in an elf file. */
extern htab_t lto_elf_build_section_table (lto_file *file);
+/* lto-symtab.c */
+
+/* The NEW_VAR (a VAR_DECL) has just been read. If there is an
+ existing variable with the same name, merge the declaration for
+ NEW_VAR with the previous declaration and return the previous
+ declaration. In this case, NEW_VAR must no longer be used by the
+ caller. All other entities referenced from NEW_VAR (including, in
+ particular, its type) must already have been merged before this
+ function is called. If the merge fails (due to inconsistencies
+ between the declarations), an error message is issued, and
+ error_mark_node is returned. If there is no previous declaration,
+ NEW_VAR is returned. */
+extern tree lto_symtab_merge_var (tree new_var);
+
+/* Like lto_symtab_merge_var, but for functions. */
+extern tree lto_symtab_merge_fn (tree new_fn);
+
+/* Hash table entry to hold the start offset and length of an lto
+ section in a .o file. */
+
+struct lto_section_slot {
+ const char * name;
+ intptr_t start;
+ size_t len;
+};
+
+
#endif /* LTO_H */
diff --git a/gcc/passes.c b/gcc/passes.c
index 20940d4c31a..269675285d4 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -569,19 +569,20 @@ init_optimization_passes (void)
}
NEXT_PASS (pass_rebuild_cgraph_edges);
}
- NEXT_PASS (pass_ipa_lto_gimple_out);
- NEXT_PASS (pass_ipa_lto_cgraph_out);
NEXT_PASS (pass_ipa_increase_alignment);
NEXT_PASS (pass_ipa_matrix_reorg);
NEXT_PASS (pass_ipa_cp);
- NEXT_PASS (pass_ipa_inline);
NEXT_PASS (pass_ipa_reference);
+ /* All regular IPA_PASSes need to be clumped together. */
+ NEXT_PASS (pass_ipa_lto_gimple_out);
+ NEXT_PASS (pass_ipa_lto_cgraph);
+ NEXT_PASS (pass_ipa_inline);
NEXT_PASS (pass_ipa_pure_const);
+ /* This must be the last IPA_PASS. */
+ NEXT_PASS (pass_ipa_lto_finish_out);
NEXT_PASS (pass_ipa_type_escape);
NEXT_PASS (pass_ipa_pta);
NEXT_PASS (pass_ipa_struct_reorg);
- /* This must be the last ipa pass. */
- NEXT_PASS (pass_ipa_lto_finish_out);
*p = NULL;
@@ -1172,7 +1173,8 @@ execute_ipa_summary_passes (struct ipa_opt_pass *ipa_pass)
/* Execute all of the IPA_PASSes in the list. */
if (ipa_pass->pass.type == IPA_PASS
- && (!pass->gate || pass->gate ()))
+ && (!pass->gate || pass->gate ())
+ && ipa_pass->generate_summary)
{
pass_init_dump_file (pass);
ipa_pass->generate_summary ();
@@ -1345,6 +1347,59 @@ execute_pass_list (struct opt_pass *pass)
/* Same as execute_pass_list but assume that subpasses of IPA passes
are local passes. */
+static void
+ipa_write_summaries_1 (struct opt_pass *pass)
+{
+ do
+ {
+ struct ipa_opt_pass *ipa_pass = (struct ipa_opt_pass *)pass;
+ gcc_assert (!current_function_decl);
+ gcc_assert (!cfun);
+ gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS);
+ if (pass->type == IPA_PASS && ipa_pass->write_summary && (!pass->gate || pass->gate ()))
+ ipa_pass->write_summary ();
+ if (pass->sub && pass->sub->type != GIMPLE_PASS)
+ ipa_write_summaries_1 (pass->sub);
+ pass = pass->next;
+ }
+ while (pass);
+}
+
+void
+ipa_write_summaries (void)
+{
+ if (flag_generate_lto && !(errorcount || sorrycount))
+ ipa_write_summaries_1 (all_ipa_passes);
+}
+
+/* Same as execute_pass_list but assume that subpasses of IPA passes
+ are local passes. */
+static void
+ipa_read_summaries_1 (struct opt_pass *pass)
+{
+ do
+ {
+ struct ipa_opt_pass *ipa_pass = (struct ipa_opt_pass *)pass;
+ gcc_assert (!current_function_decl);
+ gcc_assert (!cfun);
+ gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS);
+ if (pass->type == IPA_PASS && ipa_pass->read_summary)
+ ipa_pass->read_summary ();
+ if (pass->sub && pass->sub->type != GIMPLE_PASS)
+ ipa_read_summaries_1 (pass->sub);
+ pass = pass->next;
+ }
+ while (pass);
+}
+
+void
+ipa_read_summaries (void)
+{
+ ipa_read_summaries_1 (all_ipa_passes);
+}
+
+/* Same as execute_pass_list but assume that subpasses of IPA passes
+ are local passes. */
void
execute_ipa_pass_list (struct opt_pass *pass)
{
@@ -1361,11 +1416,10 @@ execute_ipa_pass_list (struct opt_pass *pass)
if (!quiet_flag && !cfun)
fprintf (stderr, " <summary generate>");
execute_ipa_summary_passes ((struct ipa_opt_pass *) pass);
+ ipa_write_summaries ();
}
summaries_generated = true;
}
- else
- summaries_generated = false;
if (execute_one_pass (pass) && pass->sub)
{
if (pass->sub->type == GIMPLE_PASS)
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index f9fd7d25f1c..134b848deb8 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -384,22 +384,23 @@ extern struct gimple_opt_pass pass_build_cgraph_edges;
extern struct gimple_opt_pass pass_reset_cc_flags;
/* IPA Passes */
-extern struct ipa_opt_pass pass_ipa_inline;
-extern struct simple_ipa_opt_pass pass_ipa_reference;
+extern struct simple_ipa_opt_pass pass_ipa_function_and_variable_visibility;
+extern struct simple_ipa_opt_pass pass_ipa_early_inline;
+extern struct simple_ipa_opt_pass pass_early_local_passes;
+
+extern struct ipa_opt_pass pass_ipa_lto_gimple_out;
+extern struct ipa_opt_pass pass_ipa_lto_cgraph;
+extern struct simple_ipa_opt_pass pass_ipa_increase_alignment;
extern struct simple_ipa_opt_pass pass_ipa_matrix_reorg;
extern struct simple_ipa_opt_pass pass_ipa_cp;
-extern struct simple_ipa_opt_pass pass_ipa_lto_gimple_out;
-extern struct simple_ipa_opt_pass pass_ipa_lto_cgraph_out;
-extern struct simple_ipa_opt_pass pass_ipa_early_inline;
-extern struct simple_ipa_opt_pass pass_ipa_pure_const;
+extern struct ipa_opt_pass pass_ipa_inline;
+extern struct simple_ipa_opt_pass pass_ipa_reference;
+extern struct ipa_opt_pass pass_ipa_pure_const;
extern struct simple_ipa_opt_pass pass_ipa_type_escape;
extern struct simple_ipa_opt_pass pass_ipa_pta;
extern struct simple_ipa_opt_pass pass_ipa_struct_reorg;
-extern struct simple_ipa_opt_pass pass_ipa_lto_finish_out;
-extern struct simple_ipa_opt_pass pass_early_local_passes;
-extern struct simple_ipa_opt_pass pass_ipa_increase_alignment;
-extern struct simple_ipa_opt_pass pass_ipa_function_and_variable_visibility;
+extern struct ipa_opt_pass pass_ipa_lto_finish_out;
extern struct gimple_opt_pass pass_all_optimizations;
extern struct gimple_opt_pass pass_cleanup_cfg_post_optimizing;
@@ -521,6 +522,8 @@ extern void execute_pass_list (struct opt_pass *);
extern void execute_ipa_pass_list (struct opt_pass *);
extern void print_current_pass (FILE *);
extern void debug_pass (void);
+extern void ipa_write_summaries (void);
+extern void ipa_read_summaries (void);
/* Set to true if the pass is called the first time during compilation of the
current function. Note that using this information in the optimization