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 */ };