From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 17151 invoked by alias); 1 Aug 2007 13:30:53 -0000 Received: (qmail 17128 invoked by uid 22791); 1 Aug 2007 13:30:49 -0000 X-Spam-Check-By: sourceware.org Received: from mail3.panix.com (HELO mail3.panix.com) (166.84.1.74) by sourceware.org (qpsmtpd/0.31) with ESMTP; Wed, 01 Aug 2007 13:30:38 +0000 Received: from mailspool3.panix.com (mailspool3.panix.com [166.84.1.78]) by mail3.panix.com (Postfix) with ESMTP id C86E413A8E8; Wed, 1 Aug 2007 09:30:26 -0400 (EDT) Received: from [192.168.1.60] (pool-70-104-131-212.nycmny.fios.verizon.net [70.104.131.212]) by mailspool3.panix.com (Postfix) with ESMTP id 9DBF016975; Wed, 1 Aug 2007 09:30:26 -0400 (EDT) Message-ID: <46B08AF2.3000901@naturalbridge.com> Date: Wed, 01 Aug 2007 13:30:00 -0000 From: Kenneth Zadeck User-Agent: Thunderbird 1.5.0.12 (X11/20060911) MIME-Version: 1.0 To: gcc-patches , Mark Mitchell , "Hubicha, Jan" , Daniel Berlin Subject: [LTO] patch committed to get SSA properly started and other bugs. Content-Type: multipart/mixed; boundary="------------040509040509060009060308" Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2007-08/txt/msg00037.txt.bz2 This is a multi-part message in MIME format. --------------040509040509060009060308 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Content-length: 3682 This patch gets the compiler on the receiving end mostly started up properly. A lot of work has been done to get ssa form properly started. The current code may be overkill, but that is not important now. The current code exposes one known bug, that dannyb is looking into: ================ extern int foo (int); int foo (int a) { return a * 6; } ================= This program seems to serialize fine, but blows up in the expander trying to expand the parm_decl. It is possible that this is caused by me failing to serialize something, or i could be just not initializing something properly. I have run a couple of other small examples thru. ================ extern int foo (void); int foo (void) { int a,b = 2; for (a = 0; a < 10; a++) b = 6 * a; return b * 6; } ================= now works fine. I am starting to work on larger programs. Mark claims that everything on his end should work except for static initializers so we may be ready for some larger scale testing as soon as the above bug is tracked down. Committed as revision 127125. Kenny 2007-07-31 Kenneth Zadeck * tree-into-ssa.c (rebuild_ssa_for_lto): New function. (pass_rebuild_ssa_for_lto): New pass. * cgraph_build.c (tree_opt_pass pass_rebuild_cgraph): Added some dumping. * lto-tree-flags.def (tcc_declaration): Added used_flag to serialized list. (SSA_NAME): Added nothrow_flag and volatile_flag to serialized list. * tree-pass.h (pass_early_lto_passes, pass_rebuild_ssa_for_lto): New passes. * lto-function-out.c (output_tree_flags): Added code to properly control writing of flags. Also added new parameter to pass in the tree code. (output_record_start, output_local_vars): Added param to output_tree_flags. (output_tree_list, output_eh_cleanup, output_eh_try, output_eh_catch, output_eh_allowed, output_eh_must_not_throw, output_eh_regions): Added missing debugging undent. (output_expr_operand): Added assert that there was no rtl and code to properly handle COND_EXPR. Fixed the outputing of types and flags for many tree codes. (output_phi): Fixed the outputing of types and flags. Generalized to handle parameters to phi that are not SSA_NAMES. (output_bb, LTO_SET_DEBUGGING_STREAM): Added assert to check for proper debug stream usage. (lto_static_init): Changed the outputting of flags and types for various tree codes. (pass_ipa_lto_out): Added dumping. * ipa-inline.c (pass_inline_parameters): Added dumping. * lto-tree-tags.def (COND_EXPR): Changed processing options. * lto-tags.h: Changed define into enum. * ipa.c (gate_ipa_fun_and_var_visibility): Always execute this pass. * tree.def (COND_EXEC): Properly documented this code. * tree-dfa.c (find_referenced_vars): Added code to walk phi functions. (pass_referenced_vars): Added name and dump flag. (find_vars_r): Now handles SSA_NAMES. * tree-optimize.c (gate_early_lto_passes): New function. (pass_early_lto_passes): New pass. * passes.c (pass_early_lto_passes): New pass. (dump_properties, debug_properties): New debugging function. * tree-ssanames.c (pass_release_ssa_names): Added dumping. 2007-07-31 Kenneth Zadeck * lto-read.c (input_expr_operand): Fixed code for COND_EXEC, RETURN_EXPR, MODIFY_EXPR and processing of flags. (input_phi): Made work with operands other than SSA_NAMES and fixed processing of flags. (input_ssa_names): Initialize SSA_NAME_DEF_STMT to empty stmt. (input_flags): New function. * lto-lang.c (lto_init): Changed state of in_lto_p. --------------040509040509060009060308 Content-Type: text/x-patch; name="postmerge5.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="postmerge5.diff" Content-length: 40229 Index: tree-into-ssa.c =================================================================== --- tree-into-ssa.c (revision 127112) +++ tree-into-ssa.c (working copy) @@ -3362,3 +3362,51 @@ done: timevar_pop (TV_TREE_SSA_INCREMENTAL); } + + +static unsigned int +rebuild_ssa_for_lto (void) +{ + block_stmt_iterator bsi; + basic_block bb; + referenced_var_iterator rvi; + tree var; + + init_ssa_operands (); + FOR_EACH_BB (bb) + for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi)) + update_stmt_if_modified (bsi_stmt (bsi)); + + FOR_EACH_REFERENCED_VAR (var, rvi) + { + if (dump_file) + print_node (dump_file, "\nmarking symbol for renaming ", var, 0); + mark_sym_for_renaming (var); + } + + update_ssa (TODO_update_ssa); + return 1; + +} + + +struct tree_opt_pass pass_rebuild_ssa_for_lto = +{ + "rebuild_ssa", /* name */ + NULL, /* gate */ + rebuild_ssa_for_lto, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + 0, /* tv_id */ + PROP_cfg | PROP_referenced_vars, /* properties_required */ + PROP_ssa, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func + | TODO_verify_ssa + | TODO_remove_unused_locals, /* todo_flags_finish */ + 0 /* letter */ +}; + + Index: cgraphbuild.c =================================================================== --- cgraphbuild.c (revision 127112) +++ cgraphbuild.c (working copy) @@ -252,6 +252,6 @@ struct tree_opt_pass pass_rebuild_cgraph 0, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ - 0, /* todo_flags_finish */ + TODO_dump_func, /* todo_flags_finish */ 0 /* letter */ }; Index: lto-tree-flags.def =================================================================== --- lto-tree-flags.def (revision 127112) +++ lto-tree-flags.def (working copy) @@ -66,6 +66,7 @@ ADD_CLASS_FLAG (constant_flag) ADD_CLASS_FLAG (unsigned_flag) ADD_CLASS_FLAG (deprecated_flag) + ADD_CLASS_FLAG (used_flag) END_CLASS_CASE (tcc_declaration) START_CLASS_CASE (tcc_exceptional) @@ -608,6 +609,8 @@ START_EXPR_CASE (SSA_NAME) ADD_EXPR_FLAG (asm_written_flag) + ADD_EXPR_FLAG (nothrow_flag) + ADD_EXPR_FLAG (volatile_flag) END_EXPR_CASE (SSA_NAME) START_EXPR_CASE (STATEMENT_LIST) Index: tree-pass.h =================================================================== --- tree-pass.h (revision 127112) +++ tree-pass.h (working copy) @@ -342,6 +342,9 @@ extern struct tree_opt_pass pass_free_da extern struct tree_opt_pass pass_init_datastructures; extern struct tree_opt_pass pass_fixup_cfg; +extern struct tree_opt_pass pass_early_lto_passes; +extern struct tree_opt_pass pass_rebuild_ssa_for_lto; + extern struct tree_opt_pass pass_init_function; extern struct tree_opt_pass pass_jump; extern struct tree_opt_pass pass_rtl_eh; Index: lto-function-out.c =================================================================== --- lto-function-out.c (revision 127112) +++ lto-function-out.c (working copy) @@ -594,14 +594,16 @@ output_decl_index (struct output_stream static void -output_tree_flags (struct output_block *ob, tree expr) +output_tree_flags (struct output_block *ob, enum tree_code code, tree expr) { int flags = 0; const char *file_to_write = NULL; int line_to_write = -1; const char *current_file; - LTO_DEBUG_TOKEN ("flags") + if (code == 0 || TEST_BIT (lto_flags_needed_for, code)) + { + LTO_DEBUG_TOKEN ("flags") #define START_CLASS_SWITCH() \ { \ @@ -650,43 +652,44 @@ output_tree_flags (struct output_block * #undef END_EXPR_CASE #undef END_EXPR_SWITCH - /* Add two more bits onto the flag if this is a tree node that can - have a line number. The first bit is true if this node changes - files and the second is set if this node changes lines. */ - if (expr && EXPR_P (expr)) - { - flags <<= 2; - if (EXPR_HAS_LOCATION (expr)) - { - LOC current_loc = EXPR_LOC (expr); - const int current_line = LOC_LINE (current_loc); - current_file = LOC_FILE (current_loc); - if (ob->last_file != current_file) + /* Add two more bits onto the flag if this is a tree node that can + have a line number. The first bit is true if this node changes + files and the second is set if this node changes lines. */ + if (expr && EXPR_P (expr)) + { + flags <<= 2; + if (EXPR_HAS_LOCATION (expr)) { - file_to_write = current_file; - ob->last_file = current_file; - flags |= 0x2; - } - if (ob->last_line != current_line) - { - line_to_write = current_line; - ob->last_line = current_line; - flags |= 0x1; + LOC current_loc = EXPR_LOC (expr); + const int current_line = LOC_LINE (current_loc); + current_file = LOC_FILE (current_loc); + if (ob->last_file != current_file) + { + file_to_write = current_file; + ob->last_file = current_file; + flags |= 0x2; + } + if (ob->last_line != current_line) + { + line_to_write = current_line; + ob->last_line = current_line; + flags |= 0x1; + } } } - } - output_uleb128 (ob, flags); - if (file_to_write) - { - LTO_DEBUG_TOKEN ("file") - output_string (ob, ob->main_stream, - file_to_write, strlen (file_to_write)); - } - if (line_to_write != -1) - { - LTO_DEBUG_TOKEN ("line") - output_uleb128 (ob, line_to_write); + output_uleb128 (ob, flags); + if (file_to_write) + { + LTO_DEBUG_TOKEN ("file") + output_string (ob, ob->main_stream, + file_to_write, strlen (file_to_write)); + } + if (line_to_write != -1) + { + LTO_DEBUG_TOKEN ("line") + output_uleb128 (ob, line_to_write); + } } } @@ -773,7 +776,7 @@ output_record_start (struct output_block enum tree_code code = TREE_CODE (expr); if (value && TEST_BIT (lto_types_needed_for, code)) output_type_ref (ob, TREE_TYPE (value)); - output_tree_flags (ob, expr); + output_tree_flags (ob, code, expr); } } @@ -821,6 +824,7 @@ output_tree_list (struct output_block *o for (tl = list; tl; tl = TREE_CHAIN (tl)) if (TREE_VALUE (tl) != NULL_TREE) output_expr_operand (ob, TREE_VALUE (tl)); + LTO_DEBUG_UNDENT () } else output_zero (ob); @@ -846,6 +850,7 @@ output_eh_cleanup (void *obv, output_sleb128 (ob, prev_try); if (!has_peer) output_zero (ob); + LTO_DEBUG_UNDENT () } @@ -870,6 +875,7 @@ output_eh_try (void *obv, output_sleb128 (ob, last_catch); if (!has_peer) output_zero (ob); + LTO_DEBUG_UNDENT () } @@ -895,6 +901,7 @@ output_eh_catch (void *obv, output_type_list (ob, type_list); if (!has_peer) output_zero (ob); + LTO_DEBUG_UNDENT () } /* Output an eh_allowed_exceptions region with REGION_NUMBER. @@ -916,6 +923,7 @@ output_eh_allowed (void *obv, output_type_list (ob, type_list); if (!has_peer) output_zero (ob); + LTO_DEBUG_UNDENT () } @@ -937,6 +945,7 @@ output_eh_must_not_throw (void *obv, output_sleb128 (ob, region_number); if (!has_peer) output_zero (ob); + LTO_DEBUG_UNDENT () } @@ -954,6 +963,7 @@ output_eh_regions (struct output_block * output_eh_catch, output_eh_allowed, output_eh_must_not_throw); + LTO_DEBUG_UNDENT () } /* The 0 either terminates the record or indicates that there are no eh_records at all. */ @@ -1164,6 +1174,7 @@ output_expr_operand (struct output_block break; case PARM_DECL: + gcc_assert (!DECL_RTL_SET_P (expr)); output_record_start (ob, NULL, NULL, tag); output_local_decl_ref (ob, expr); break; @@ -1178,8 +1189,23 @@ output_expr_operand (struct output_block output_label_ref (ob, TREE_OPERAND (expr, 0)); break; + case COND_EXPR: + if (TREE_OPERAND (expr, 1)) + { + output_record_start (ob, expr, expr, LTO_cond_expr0); + output_expr_operand (ob, TREE_OPERAND (expr, 0)); + output_expr_operand (ob, TREE_OPERAND (expr, 1)); + output_expr_operand (ob, TREE_OPERAND (expr, 2)); + } + else + { + output_record_start (ob, expr, expr, LTO_cond_expr1); + output_expr_operand (ob, TREE_OPERAND (expr, 0)); + } + break; + case RESULT_DECL: - output_record_start (ob, expr, NULL, tag); + output_record_start (ob, expr, expr, tag); break; case COMPONENT_REF: @@ -1300,13 +1326,13 @@ output_expr_operand (struct output_block if (t == NULL) { /* Form return. */ - output_record_start (ob, expr, NULL, + output_record_start (ob, expr, expr, LTO_return_expr0); } else if (TREE_CODE (t) == MODIFY_EXPR) { /* Form return a = b; */ - output_record_start (ob, expr, NULL, + output_record_start (ob, expr, expr, LTO_return_expr2); output_expr_operand (ob, TREE_OPERAND (t, 0)); output_expr_operand (ob, TREE_OPERAND (t, 1)); @@ -1314,7 +1340,7 @@ output_expr_operand (struct output_block else { /* Form return a; */ - output_record_start (ob, expr, NULL, + output_record_start (ob, expr, expr, LTO_return_expr1); output_expr_operand (ob, t); } @@ -1355,7 +1381,7 @@ output_expr_operand (struct output_block #undef TREE_SINGLE_MECHANICAL_TRUE #undef SET_NAME output_record_start (ob, expr, expr, tag); - for (i = 0; i< TREE_CODE_LENGTH (TREE_CODE (expr)); i++) + for (i = 0; i < TREE_CODE_LENGTH (TREE_CODE (expr)); i++) output_expr_operand (ob, TREE_OPERAND (expr, i)); break; } @@ -1454,7 +1480,7 @@ output_local_vars (struct output_block * if (!is_var) output_type_ref (ob, DECL_ARG_TYPE (decl)); - output_tree_flags (ob, decl); + output_tree_flags (ob, 0, decl); LTO_DEBUG_TOKEN ("align") output_uleb128 (ob, DECL_ALIGN (decl)); @@ -1523,6 +1549,8 @@ output_ssa_names (struct output_block *o output_uleb128 (ob, i); output_expr_operand (ob, SSA_NAME_VAR (ptr)); + /* Lie about the type of object to get the flags out. */ + output_tree_flags (ob, 0, ptr); } output_uleb128 (ob, 0); @@ -1578,14 +1606,15 @@ output_phi (struct output_block *ob, tre int len = PHI_NUM_ARGS (expr); int i; - output_record_start (ob, expr, NULL, LTO_phi_node); + output_record_start (ob, expr, expr, LTO_phi_node); output_uleb128 (ob, SSA_NAME_VERSION (PHI_RESULT (expr))); for (i = 0; i < len; i++) { - output_uleb128 (ob, SSA_NAME_VERSION (PHI_ARG_DEF (expr, i))); + output_expr_operand (ob, PHI_ARG_DEF (expr, i)); output_uleb128 (ob, PHI_ARG_EDGE (expr, i)->src->index); } + LTO_DEBUG_UNDENT () } @@ -1649,6 +1678,10 @@ output_bb (struct output_block *ob, basi } LTO_DEBUG_UNDENT() + +#ifdef LTO_STREAM_DEBUGGING + gcc_assert (lto_debug_context.indent == 1); +#endif } @@ -1788,10 +1821,11 @@ lto_static_init (void) lto_flags_needed_for = sbitmap_alloc (NUM_TREE_CODES); sbitmap_ones (lto_flags_needed_for); RESET_BIT (lto_flags_needed_for, FIELD_DECL); + RESET_BIT (lto_flags_needed_for, FIELD_DECL); RESET_BIT (lto_flags_needed_for, FUNCTION_DECL); - RESET_BIT (lto_flags_needed_for, VAR_DECL); RESET_BIT (lto_flags_needed_for, PARM_DECL); - RESET_BIT (lto_flags_needed_for, FIELD_DECL); + RESET_BIT (lto_flags_needed_for, SSA_NAME); + RESET_BIT (lto_flags_needed_for, VAR_DECL); lto_types_needed_for = sbitmap_alloc (NUM_TREE_CODES); @@ -1805,9 +1839,9 @@ lto_static_init (void) RESET_BIT (lto_types_needed_for, LABEL_EXPR); RESET_BIT (lto_types_needed_for, MODIFY_EXPR); RESET_BIT (lto_types_needed_for, PARM_DECL); - RESET_BIT (lto_types_needed_for, RESULT_DECL); + RESET_BIT (lto_types_needed_for, PHI_NODE); RESET_BIT (lto_types_needed_for, RESX_EXPR); - RESET_BIT (lto_types_needed_for, RETURN_EXPR); + RESET_BIT (lto_types_needed_for, SSA_NAME); RESET_BIT (lto_types_needed_for, STRING_CST); RESET_BIT (lto_types_needed_for, SWITCH_EXPR); RESET_BIT (lto_types_needed_for, VAR_DECL); @@ -1868,6 +1902,7 @@ static int function_num; ob-> STREAM = xcalloc (1, sizeof (struct output_stream)); \ lto_debug_context. CONTEXT = ob-> STREAM; \ lto_debug_context.current_data = ob-> STREAM; \ + gcc_assert (lto_debug_context.indent == 0); \ } #else #define LTO_SET_DEBUGGING_STREAM(STREAM,CONTEXT) @@ -2015,7 +2050,7 @@ struct tree_opt_pass pass_ipa_lto_out = 0, /* properties_required */ 0, /* properties_provided */ 0, /* properties_destroyed */ - 0, /* todo_flags_start */ + TODO_dump_func, /* todo_flags_start */ 0, /* todo_flags_finish */ 0 /* letter */ }; Index: cgraphunit.c =================================================================== --- cgraphunit.c (revision 127112) +++ cgraphunit.c (working copy) @@ -529,7 +529,7 @@ cgraph_finalize_function (tree decl, boo if (node->lowered) { DECL_STRUCT_FUNCTION (decl)->curr_properties - |= (PROP_gimple_leh | PROP_cfg | PROP_referenced_vars + |= (PROP_gimple_leh | PROP_cfg | PROP_referenced_vars | PROP_gimple_lomp | PROP_gimple_any | PROP_gimple_lcf); } record_cdtor_fn (node->decl); Index: ipa-inline.c =================================================================== --- ipa-inline.c (revision 127112) +++ ipa-inline.c (working copy) @@ -1558,7 +1558,7 @@ struct tree_opt_pass pass_inline_paramet PROP_cfg, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ - 0, /* todo_flags_finish */ + TODO_dump_func, /* todo_flags_finish */ 0 /* letter */ }; Index: lto-tree-tags.def =================================================================== --- lto-tree-tags.def (revision 127112) +++ lto-tree-tags.def (working copy) @@ -55,6 +55,7 @@ MAP_EXPR_TAGS(BIT_FIELD_REF, LTO_bit_field_ref0, 2) MAP_EXPR_TAGS(CALL_EXPR, LTO_call_expr0, 2) MAP_EXPR_TAGS(CASE_LABEL_EXPR, LTO_case_label_expr0, 4) + MAP_EXPR_TAGS(COND_EXPR, LTO_cond_expr0, 2) MAP_EXPR_TAGS(COMPLEX_CST, LTO_complex_cst0, 2) MAP_EXPR_TAGS(RETURN_EXPR, LTO_return_expr0, 3) MAP_EXPR_TAGS(VAR_DECL, LTO_var_decl0, 2) @@ -98,7 +99,6 @@ MAP_EXPR_TAG(CEIL_MOD_EXPR, LTO_ceil_mod_expr) MAP_EXPR_TAG(COMPLEX_EXPR, LTO_complex_expr) MAP_EXPR_TAG(COMPOUND_EXPR, LTO_compound_expr) - MAP_EXPR_TAG(COND_EXPR, LTO_cond_expr) MAP_EXPR_TAG(CONJ_EXPR, LTO_conj_expr) MAP_EXPR_TAG(CONVERT_EXPR, LTO_convert_expr) MAP_EXPR_TAG(DOT_PROD_EXPR, LTO_dot_prod_expr) @@ -196,7 +196,8 @@ SET_NAME (LTO_complex_expr, "complex_expr") SET_NAME (LTO_component_ref, "component_ref") SET_NAME (LTO_compound_expr, "compound_expr") - SET_NAME (LTO_cond_expr, "cond_expr") + SET_NAME (LTO_cond_expr0, "cond_expr0") + SET_NAME (LTO_cond_expr1, "cond_expr1") SET_NAME (LTO_conj_expr, "conj_expr") SET_NAME (LTO_const_decl, "const_decl") SET_NAME (LTO_constructor, "constructor") Index: lto-tags.h =================================================================== --- lto-tags.h (revision 127112) +++ lto-tags.h (working copy) @@ -253,182 +253,197 @@ struct lto_function_header type codes. */ #define REDUNDANT_TYPE_SYSTEM 1 +enum LTO_tags { + /* The 1 variant indicates that the basic block is not empty. */ -#define LTO_bb0 0x001 -#define LTO_bb1 0x002 + LTO_bb0 = 1, + LTO_bb1, /* Variant 1 is used to set region to no zero value. */ -#define LTO_set_eh0 0x003 -#define LTO_set_eh1 0x004 + LTO_set_eh0, + LTO_set_eh1, /* All of the expression types that we can see. */ -#define LTO_abs_expr 0x005 -#define LTO_addr_expr 0x006 -#define LTO_align_indirect_ref 0x007 -#define LTO_array_range_ref 0x008 -#define LTO_array_ref 0x009 -#define LTO_asm_expr 0x00A -#define LTO_assert_expr 0x00B -#define LTO_bit_and_expr 0x00C -#define LTO_bit_ior_expr 0x00D + LTO_abs_expr, + LTO_addr_expr, + LTO_align_indirect_ref, + LTO_array_range_ref, + LTO_array_ref, + LTO_asm_expr, + LTO_assert_expr, + LTO_bit_and_expr, + LTO_bit_ior_expr, + /* Variant 1 is used if both operands 1 and 2 are constant ints. */ -#define LTO_bit_field_ref0 0x00E -#define LTO_bit_field_ref1 0x00F -#define LTO_bit_not_expr 0x010 -#define LTO_bit_xor_expr 0x011 + LTO_bit_field_ref0, + LTO_bit_field_ref1, + LTO_bit_not_expr, + LTO_bit_xor_expr, + /* Call_exprs are terminated by a 0 to indicate the end of the parameter list. Variant 1 indicates the presence of a call chain. */ -#define LTO_call_expr0 0x012 -#define LTO_call_expr1 0x013 + LTO_call_expr0, + LTO_call_expr1, + /* Variant 1 and 3 are if CASE_LOW exists and variant 2 and 3 are if CASE_HIGH exists. */ -#define LTO_case_label_expr0 0x014 -#define LTO_case_label_expr1 0x015 -#define LTO_case_label_expr2 0x016 -#define LTO_case_label_expr3 0x017 -#define LTO_ceil_div_expr 0x018 -#define LTO_ceil_mod_expr 0x019 -#define LTO_change_dynamic_type_expr 0x01A -/* 1 if the elements are reals and 0 if the elements are ints. */ -#define LTO_complex_cst0 0x01B -#define LTO_complex_cst1 0x01C -#define LTO_complex_expr 0x01D -#define LTO_component_ref 0x01E -#define LTO_compound_expr 0x01F -#define LTO_cond_expr 0x020 -#define LTO_conj_expr 0x021 -#define LTO_const_decl 0x022 + LTO_case_label_expr0, + LTO_case_label_expr1, + LTO_case_label_expr2, + LTO_case_label_expr3, + LTO_ceil_div_expr, + LTO_ceil_mod_expr, + LTO_change_dynamic_type_expr, + +/* Variant 1 if the elements are reals and 0 if the elements are ints. */ + LTO_complex_cst0, + LTO_complex_cst1, + LTO_complex_expr, + LTO_component_ref, + LTO_compound_expr, + +/* Variant 1 if operands 1 and 2 are NULL. */ + LTO_cond_expr0, + LTO_cond_expr1, + LTO_conj_expr, + LTO_const_decl, + /* This form is terminated by a zero. */ -#define LTO_constructor 0x023 -#define LTO_constructor_range 0x024 -#define LTO_convert_expr 0x025 -#define LTO_dot_prod_expr 0x026 -#define LTO_eq_expr 0x027 -#define LTO_exact_div_expr 0x028 -#define LTO_exc_ptr_expr 0x029 -#define LTO_field_decl 0x02A -#define LTO_filter_expr 0x02B -#define LTO_fix_ceil_expr 0x02C -#define LTO_fix_floor_expr 0x02D -#define LTO_fix_round_expr 0x02E -#define LTO_fix_trunc_expr 0x02F -#define LTO_float_expr 0x030 -#define LTO_floor_div_expr 0x031 -#define LTO_floor_mod_expr 0x032 -#define LTO_function_decl 0x033 -#define LTO_ge_expr 0x034 -#define LTO_gimple_modify_stmt 0x035 -#define LTO_goto_expr 0x036 -#define LTO_gt_expr 0x037 -#define LTO_imagpart_expr 0x038 -#define LTO_indirect_ref 0x039 -#define LTO_integer_cst 0x03A -#define LTO_label_decl 0x03B -#define LTO_label_expr 0x03C -#define LTO_le_expr 0x03D -#define LTO_lrotate_expr 0x03E -#define LTO_lshift_expr 0x03F -#define LTO_lt_expr 0x040 -#define LTO_ltgt_expr 0x041 -#define LTO_max_expr 0x042 -#define LTO_min_expr 0x043 -#define LTO_minus_expr 0x044 -#define LTO_misaligned_indirect_ref 0x045 -#define LTO_modify_expr 0x046 -#define LTO_mult_expr 0x047 -#define LTO_ne_expr 0x048 -#define LTO_negate_expr 0x049 -#define LTO_non_lvalue_expr 0x04A -#define LTO_nop_expr 0x04B -#define LTO_obj_type_ref 0x04C -#define LTO_ordered_expr 0x04D -#define LTO_parm_decl 0x04E -#define LTO_phi_node 0x04F -#define LTO_pointer_plus_expr 0x050 -#define LTO_plus_expr 0x051 -#define LTO_range_expr 0x052 -#define LTO_rdiv_expr 0x053 -#define LTO_real_cst 0x054 -#define LTO_realign_load_expr 0x055 -#define LTO_realpart_expr 0x056 -#define LTO_reduc_max_expr 0x057 -#define LTO_reduc_min_expr 0x058 -#define LTO_reduc_plus_expr 0x059 -#define LTO_result_decl 0x05A + LTO_constructor, + LTO_constructor_range, + LTO_convert_expr, + LTO_dot_prod_expr, + LTO_eq_expr, + LTO_exact_div_expr, + LTO_exc_ptr_expr, + LTO_field_decl, + LTO_filter_expr, + LTO_fix_ceil_expr, + LTO_fix_floor_expr, + LTO_fix_round_expr, + LTO_fix_trunc_expr, + LTO_float_expr, + LTO_floor_div_expr, + LTO_floor_mod_expr, + LTO_function_decl, + LTO_ge_expr, + LTO_gimple_modify_stmt, + LTO_goto_expr, + LTO_gt_expr, + LTO_imagpart_expr, + LTO_indirect_ref, + LTO_integer_cst, + LTO_label_decl, + LTO_label_expr, + LTO_le_expr, + LTO_lrotate_expr, + LTO_lshift_expr, + LTO_lt_expr, + LTO_ltgt_expr, + LTO_max_expr, + LTO_min_expr, + LTO_minus_expr, + LTO_misaligned_indirect_ref, + LTO_modify_expr, + LTO_mult_expr, + LTO_ne_expr, + LTO_negate_expr, + LTO_non_lvalue_expr, + LTO_nop_expr, + LTO_obj_type_ref, + LTO_ordered_expr, + LTO_parm_decl, + LTO_phi_node, + LTO_pointer_plus_expr, + LTO_plus_expr, + LTO_range_expr, + LTO_rdiv_expr, + LTO_real_cst, + LTO_realign_load_expr, + LTO_realpart_expr, + LTO_reduc_max_expr, + LTO_reduc_min_expr, + LTO_reduc_plus_expr, + LTO_result_decl, + /* Form "return;" */ -#define LTO_return_expr0 0x05B + LTO_return_expr0, + /* Form "return x;" */ -#define LTO_return_expr1 0x05C + LTO_return_expr1, + /* Form "return x=y;" */ -#define LTO_return_expr2 0x05D -#define LTO_resx_expr 0x05E -#define LTO_round_div_expr 0x05F -#define LTO_round_mod_expr 0x060 -#define LTO_rrotate_expr 0x061 -#define LTO_rshift_expr 0x062 -#define LTO_ssa_name 0x063 -#define LTO_string_cst 0x064 + LTO_return_expr2, + LTO_resx_expr, + LTO_round_div_expr, + LTO_round_mod_expr, + LTO_rrotate_expr, + LTO_rshift_expr, + LTO_ssa_name, + LTO_string_cst, + /* Cases are terminated a zero. */ -#define LTO_switch_expr 0x065 -#define LTO_trunc_div_expr 0x066 -#define LTO_trunc_mod_expr 0x067 -#define LTO_truth_and_expr 0x068 -#define LTO_truth_not_expr 0x069 -#define LTO_truth_or_expr 0x06A -#define LTO_truth_xor_expr 0x06B -#define LTO_uneq_expr 0x06C -#define LTO_unge_expr 0x070 -#define LTO_ungt_expr 0x071 -#define LTO_unle_expr 0x072 -#define LTO_unlt_expr 0x073 -#define LTO_unordered_expr 0x074 + LTO_switch_expr, + LTO_trunc_div_expr, + LTO_trunc_mod_expr, + LTO_truth_and_expr, + LTO_truth_not_expr, + LTO_truth_or_expr, + LTO_truth_xor_expr, + LTO_uneq_expr, + LTO_unge_expr, + LTO_ungt_expr, + LTO_unle_expr, + LTO_unlt_expr, + LTO_unordered_expr, + /* 1 for static or extern and 0 for local. */ -#define LTO_var_decl0 0x075 -#define LTO_var_decl1 0x076 -#define LTO_vec_cond_expr 0x077 -#define LTO_vec_lshift_expr 0x078 -#define LTO_vec_rshift_expr 0x079 -/* 1 if the elements are reals and 0 if the elements are ints. */ -#define LTO_vector_cst0 0x07A -#define LTO_vector_cst1 0x07B -#define LTO_view_convert_expr 0x07C -#define LTO_widen_mult_expr 0x07D -#define LTO_widen_sum_expr 0x07E -#define LTO_with_size_expr 0x080 + LTO_var_decl0, + LTO_var_decl1, + LTO_vec_cond_expr, + LTO_vec_lshift_expr, + LTO_vec_rshift_expr, +/* 1 if the elements are reals and 0 if the elements are ints. */ + LTO_vector_cst0, + LTO_vector_cst1, + LTO_view_convert_expr, + LTO_widen_mult_expr, + LTO_widen_sum_expr, + LTO_with_size_expr, /* All of the statement types that do not also appear as expressions. */ -#define LTO_asm_inputs 0x090 -#define LTO_asm_outputs 0x091 -#define LTO_asm_clobbers 0x092 - -#define LTO_function 0x093 -#define LTO_attribute_list 0x094 -#define LTO_eh_table 0x095 + LTO_asm_inputs, + LTO_asm_outputs, + LTO_asm_clobbers, + + LTO_function, + LTO_attribute_list, + LTO_eh_table, /* Each of these requires 4 variants. 1 and 3 are have_inner and 2 and 3 are may_contain_throw. */ -#define LTO_eh_table_cleanup0 0x0A0 -#define LTO_eh_table_cleanup1 0x0A1 -#define LTO_eh_table_cleanup2 0x0A2 -#define LTO_eh_table_cleanup3 0x0A3 -#define LTO_eh_table_try0 0x0A4 -#define LTO_eh_table_try1 0x0A5 -#define LTO_eh_table_try2 0x0A6 -#define LTO_eh_table_try3 0x0A7 -#define LTO_eh_table_catch0 0x0A8 -#define LTO_eh_table_catch1 0x0A9 -#define LTO_eh_table_catch2 0x0AA -#define LTO_eh_table_catch3 0x0AB -#define LTO_eh_table_allowed0 0x0AC -#define LTO_eh_table_allowed1 0x0AD -#define LTO_eh_table_allowed2 0x0AE -#define LTO_eh_table_allowed3 0x0AF -#define LTO_eh_table_must_not_throw0 0x0B0 -#define LTO_eh_table_must_not_throw1 0x0B1 -#define LTO_eh_table_must_not_throw2 0x0B2 -#define LTO_eh_table_must_not_throw3 0x0B3 + LTO_eh_table_cleanup0, + LTO_eh_table_cleanup1, + LTO_eh_table_cleanup2, + LTO_eh_table_cleanup3, + LTO_eh_table_try0, + LTO_eh_table_try1, + LTO_eh_table_try2, + LTO_eh_table_try3, + LTO_eh_table_catch0, + LTO_eh_table_catch1, + LTO_eh_table_catch2, + LTO_eh_table_catch3, + LTO_eh_table_allowed0, + LTO_eh_table_allowed1, + LTO_eh_table_allowed2, + LTO_eh_table_allowed3, + LTO_eh_table_must_not_throw0, + LTO_eh_table_must_not_throw1, + LTO_eh_table_must_not_throw2, + LTO_eh_table_must_not_throw3, /* There are 16 variants of the following decl bodies depending on the subtrees that may or may not be there in the decl_common part of @@ -441,9 +456,11 @@ struct lto_function_header These next two tags must have their last hex digit be 0. */ -#define LTO_local_var_decl_body0 0x0C0 -#define LTO_parm_decl_body0 0x0D0 -#define LTO_last_tag 0x0E0 + LTO_local_var_decl_body0 = 0x0C0, + LTO_parm_decl_body0 = 0x0D0, + LTO_last_tag = 0x0E0 +}; + /* The string that is prepended on the DECL_ASSEMBLER_NAME to make the section name for the function. */ #define LTO_SECTION_NAME_PREFIX ".gnu.lto_" Index: ipa.c =================================================================== --- ipa.c (revision 127112) +++ ipa.c (working copy) @@ -281,7 +281,7 @@ function_and_variable_visibility (void) static bool gate_ipa_fun_and_var_visibility (void) { - return !in_lto_p; + return true; } Index: tree.def =================================================================== --- tree.def (revision 127112) +++ tree.def (working copy) @@ -485,7 +485,10 @@ DEFTREECODE (TARGET_EXPR, "target_expr", Operand 1 must have the same type as the entire expression, unless it unconditionally throws an exception, in which case it should have VOID_TYPE. The same constraints apply to operand 2. The - condition in operand 0 must be of integral type. */ + condition in operand 0 must be of integral type. + + In cfg gimple, if you do not have a selection expression, operands + 1 and 2 are NULL. The operands are then taken from the cfg edges. */ DEFTREECODE (COND_EXPR, "cond_expr", tcc_expression, 3) /* Vector conditional expression. It is like COND_EXPR, but with Index: tree-dfa.c =================================================================== --- tree-dfa.c (revision 127112) +++ tree-dfa.c (working copy) @@ -85,20 +85,26 @@ find_referenced_vars (void) { basic_block bb; block_stmt_iterator si; + tree phi; FOR_EACH_BB (bb) - for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si)) - { - tree *stmt_p = bsi_stmt_ptr (si); - walk_tree (stmt_p, find_vars_r, NULL, NULL); - } + { + for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si)) + { + tree *stmt_p = bsi_stmt_ptr (si); + walk_tree (stmt_p, find_vars_r, NULL, NULL); + } + + for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi)) + walk_tree (&phi, find_vars_r, NULL, NULL); + } return 0; } struct tree_opt_pass pass_referenced_vars = { - NULL, /* name */ + "referenced-vars", /* name */ NULL, /* gate */ find_referenced_vars, /* execute */ NULL, /* sub */ @@ -109,7 +115,7 @@ struct tree_opt_pass pass_referenced_var PROP_referenced_vars, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ - 0, /* todo_flags_finish */ + TODO_dump_func, /* todo_flags_finish */ 0 /* letter */ }; @@ -616,9 +622,14 @@ collect_dfa_stats_r (tree *tp, int *walk static tree find_vars_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) { + /* If we are reading the lto info back in, we need to rescan the + referenced vars. */ + if (TREE_CODE (*tp) == SSA_NAME) + add_referenced_var (SSA_NAME_VAR (*tp)); + /* If T is a regular variable that the optimizers are interested in, add it to the list of variables. */ - if (SSA_VAR_P (*tp)) + else if (SSA_VAR_P (*tp)) add_referenced_var (*tp); /* Type, _DECL and constant nodes have no interesting children. Index: lto/lto-read.c =================================================================== --- lto/lto-read.c (revision 127112) +++ lto/lto-read.c (working copy) @@ -384,6 +384,24 @@ process_flags (tree expr, unsigned HOST_ } +/* Read the flags for CODE from IB. */ + +static unsigned int +input_flags (struct input_block *ib, enum tree_code code) +{ + unsigned int flags; + + if (TEST_BIT (lto_flags_needed_for, code)) + { + LTO_DEBUG_TOKEN ("flags") + flags = input_uleb128 (ib); + } + else + flags = 0; + return flags; +} + + /* Read a node in the gimple tree from IB. The TAG has already been read. */ @@ -402,13 +420,7 @@ input_expr_operand (struct input_block * if (TEST_BIT (lto_types_needed_for, code)) type = get_type_ref (fun_in, ib); - if (TEST_BIT (lto_flags_needed_for, code)) - { - LTO_DEBUG_TOKEN ("flags") - flags = input_uleb128 (ib); - } - else - flags = 0; + flags = input_flags (ib, code); /* FIXME! need to figure out how to set the file and line number. */ if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))) @@ -606,8 +618,32 @@ input_expr_operand (struct input_block * result = build1 (code, void_type_node, get_label_decl (fun_in, ib)); break; + case COND_EXPR: + if (tag == LTO_cond_expr0) + { + tree op0; + tree op1; + tree op2; + op0 = input_expr_operand (ib, fun_in, fn, + input_record_start (ib)); + op1 = input_expr_operand (ib, fun_in, fn, + input_record_start (ib)); + op2 = input_expr_operand (ib, fun_in, fn, + input_record_start (ib)); + result = build3 (code, type, op0, op1, op2); + } + else + { + tree op0; + op0 = input_expr_operand (ib, fun_in, fn, + input_record_start (ib)); + result = build3 (code, type, op0, NULL, NULL); + } + break; + + case RESULT_DECL: - result = build0 (code, NULL_TREE); + result = build0 (code, type); break; case COMPONENT_REF: @@ -711,11 +747,11 @@ input_expr_operand (struct input_block * switch (tag) { case LTO_return_expr0: - result = build1 (code, NULL_TREE, NULL_TREE); + result = build1 (code, type, NULL_TREE); break; case LTO_return_expr1: - result = build1 (code, NULL_TREE, + result = build1 (code, type, input_expr_operand (ib, fun_in, fn, input_record_start (ib))); break; @@ -726,7 +762,7 @@ input_expr_operand (struct input_block * input_record_start (ib)); tree op1 = input_expr_operand (ib, fun_in, fn, input_record_start (ib)); - result = build1 (code, NULL_TREE, + result = build1 (code, type, build2 (MODIFY_EXPR, NULL_TREE, op0, op1)); } break; @@ -838,7 +874,8 @@ input_expr_operand (struct input_block * } LTO_DEBUG_UNDENT() - process_flags (result, flags); + if (flags) + process_flags (result, flags); return result; } @@ -1136,8 +1173,11 @@ input_cfg (struct input_block *ib, struc /* Input the next phi function for BB. */ static tree -input_phi (struct input_block *ib, basic_block bb, struct function *fn) +input_phi (struct input_block *ib, basic_block bb, + struct fun_in *fun_in, struct function *fn) { + unsigned int flags = input_flags (ib, PHI_NODE); + tree phi_result = VEC_index (tree, SSANAMES (fn), input_uleb128 (ib)); int len = EDGE_COUNT (bb->preds); int i; @@ -1147,7 +1187,7 @@ input_phi (struct input_block *ib, basic for (i = 0; i < len; i++) { - tree def = VEC_index (tree, SSANAMES (fn), input_uleb128 (ib)); + tree def = input_expr_operand (ib, fun_in, fn, input_record_start (ib)); int src_index = input_uleb128 (ib); basic_block sbb = BASIC_BLOCK_FOR_FUNCTION (fn, src_index); @@ -1163,6 +1203,12 @@ input_phi (struct input_block *ib, basic add_phi_arg (result, def, e); } + + if (flags) + process_flags (result, flags); + + LTO_DEBUG_UNDENT() + return result; } @@ -1181,11 +1227,20 @@ input_ssa_names (struct fun_in *fun_in, while (i) { + tree ssa_name; + tree name; + unsigned int flags; + /* Skip over the elements that had been freed. */ while (VEC_length (tree, SSANAMES (fn)) < i) VEC_quick_push (tree, SSANAMES (fn), NULL_TREE); - make_ssa_name (input_expr_operand (ib, fun_in, fn, input_record_start (ib)), NULL); + name = input_expr_operand (ib, fun_in, fn, input_record_start (ib)); + ssa_name = make_ssa_name (name, build_empty_stmt ()); + + LTO_DEBUG_TOKEN ("flags") + flags = input_uleb128 (ib); + process_flags (ssa_name, flags); i = input_uleb128 (ib); } @@ -1196,7 +1251,7 @@ input_ssa_names (struct fun_in *fun_in, static void input_bb (struct input_block *ib, unsigned int tag, - struct function *fn, struct fun_in *fun_in) + struct fun_in *fun_in, struct function *fn) { unsigned int index; basic_block bb; @@ -1229,7 +1284,7 @@ input_bb (struct input_block *ib, unsign tag = input_record_start (ib); while (tag) { - input_phi (ib, bb, fn); + input_phi (ib, bb, fun_in, fn); LTO_DEBUG_INDENT_TOKEN ("phi") tag = input_record_start (ib); } @@ -1255,7 +1310,7 @@ input_function (tree fn_decl, struct fun tag = input_record_start (ib); while (tag) { - input_bb (ib, tag, fn, fun_in); + input_bb (ib, tag, fun_in, fn); tag = input_record_start (ib); } Index: lto/lto-lang.c =================================================================== --- lto/lto-lang.c (revision 127112) +++ lto/lto-lang.c (working copy) @@ -136,7 +136,6 @@ lto_init (void) /* Always operate in unit-at-time mode so that we can defer decisions about what to output. */ flag_unit_at_a_time = 1; - in_lto_p = false; /* Create the basic integer types. */ build_common_tree_nodes (flag_signed_char, @@ -153,6 +152,7 @@ lto_init (void) /* Initialize LTO-specific data structures. */ lto_global_var_decls = VEC_alloc (tree, gc, 256); + in_lto_p = true; return true; } Index: tree-optimize.c =================================================================== --- tree-optimize.c (revision 127112) +++ tree-optimize.c (working copy) @@ -139,6 +139,35 @@ struct tree_opt_pass pass_all_early_opti 0 /* letter */ }; + +/* Control the early passes that are run if this is the lto front end. + This cannot be in the lto front end because that must be linked + separately. */ + +static bool +gate_early_lto_passes (void) +{ + /* Don't bother doing anything if the program has errors. */ + return (!errorcount && !sorrycount && in_lto_p); +} + +struct tree_opt_pass pass_early_lto_passes = +{ + "early_lto_passes", /* name */ + gate_early_lto_passes, /* gate */ + NULL, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + 0, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ + 0 /* letter */ +}; + /* Pass: cleanup the CFG just before expanding trees to RTL. This is just a round of label cleanups and case node grouping because after the tree optimizers have run such cleanups may Index: passes.c =================================================================== --- passes.c (revision 127112) +++ passes.c (working copy) @@ -533,6 +533,12 @@ init_optimization_passes (void) NEXT_PASS (pass_rebuild_cgraph_edges); NEXT_PASS (pass_inline_parameters); } + NEXT_PASS (pass_early_lto_passes); + { + struct tree_opt_pass **p = &pass_early_lto_passes.sub; + NEXT_PASS (pass_referenced_vars); + NEXT_PASS (pass_rebuild_ssa_for_lto); + } NEXT_PASS (pass_ipa_lto_out); NEXT_PASS (pass_ipa_increase_alignment); NEXT_PASS (pass_ipa_matrix_reorg); @@ -1200,4 +1206,39 @@ execute_ipa_pass_list (struct tree_opt_p } while (pass); } + +extern void debug_properties (unsigned int); +extern void dump_properties (FILE *, unsigned int); +void +dump_properties (FILE *dump, unsigned int props) +{ + fprintf (dump, "Properties:\n"); + if (props & PROP_gimple_any) + fprintf (dump, "PROP_gimple_any\n"); + if (props & PROP_gimple_lcf) + fprintf (dump, "PROP_gimple_lcf\n"); + if (props & PROP_gimple_leh) + fprintf (dump, "PROP_gimple_leh\n"); + if (props & PROP_cfg) + fprintf (dump, "PROP_cfg\n"); + if (props & PROP_referenced_vars) + fprintf (dump, "PROP_referenced_vars\n"); + if (props & PROP_pta) + fprintf (dump, "PROP_pta\n"); + if (props & PROP_ssa) + fprintf (dump, "PROP_ssa\n"); + if (props & PROP_no_crit_edges) + fprintf (dump, "PROP_no_crit_edges\n"); + if (props & PROP_rtl) + fprintf (dump, "PROP_rtl\n"); + if (props & PROP_alias) + fprintf (dump, "PROP_alias\n"); + if (props & PROP_gimple_lomp) + fprintf (dump, "PROP_gimple_lomp\n"); +} + void +debug_properties (unsigned int props) +{ + dump_properties (stderr, props); +} #include "gt-passes.h" Index: tree-ssanames.c =================================================================== --- tree-ssanames.c (revision 127112) +++ tree-ssanames.c (working copy) @@ -359,6 +359,6 @@ struct tree_opt_pass pass_release_ssa_na 0, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ - 0, /* todo_flags_finish */ + TODO_dump_func, /* todo_flags_finish */ 0 /* letter */ }; --------------040509040509060009060308--