diff options
Diffstat (limited to 'gcc/ipa-prop.cc')
-rw-r--r-- | gcc/ipa-prop.cc | 191 |
1 files changed, 160 insertions, 31 deletions
diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc index a120f94..0398d69 100644 --- a/gcc/ipa-prop.cc +++ b/gcc/ipa-prop.cc @@ -60,6 +60,7 @@ along with GCC; see the file COPYING3. If not see #include "gimple-range.h" #include "value-range-storage.h" #include "vr-values.h" +#include "lto-streamer.h" /* Function summary where the parameter infos are actually stored. */ ipa_node_params_t *ipa_node_params_sum = NULL; @@ -454,7 +455,11 @@ ipa_dump_jump_function (FILE *f, ipa_jump_func *jump_func, if (jump_func->value.pass_through.operation != NOP_EXPR) { fprintf (f, " "); - print_generic_expr (f, jump_func->value.pass_through.operand); + if (jump_func->value.pass_through.operand) + print_generic_expr (f, jump_func->value.pass_through.operand); + fprintf (f, " (in type "); + print_generic_expr (f, jump_func->value.pass_through.op_type); + fprintf (f, ")"); } if (jump_func->value.pass_through.agg_preserved) fprintf (f, ", agg_preserved"); @@ -510,7 +515,11 @@ ipa_dump_jump_function (FILE *f, ipa_jump_func *jump_func, if (item->value.pass_through.operation != NOP_EXPR) { fprintf (f, " "); - print_generic_expr (f, item->value.pass_through.operand); + if (item->value.pass_through.operand) + print_generic_expr (f, item->value.pass_through.operand); + fprintf (f, " (in type "); + print_generic_expr (f, jump_func->value.pass_through.op_type); + fprintf (f, ")"); } } else if (item->jftype == IPA_JF_CONST) @@ -682,6 +691,7 @@ ipa_set_jf_simple_pass_through (struct ipa_jump_func *jfunc, int formal_id, { jfunc->type = IPA_JF_PASS_THROUGH; jfunc->value.pass_through.operand = NULL_TREE; + jfunc->value.pass_through.op_type = NULL_TREE; jfunc->value.pass_through.formal_id = formal_id; jfunc->value.pass_through.operation = NOP_EXPR; jfunc->value.pass_through.agg_preserved = agg_preserved; @@ -692,10 +702,11 @@ ipa_set_jf_simple_pass_through (struct ipa_jump_func *jfunc, int formal_id, static void ipa_set_jf_unary_pass_through (struct ipa_jump_func *jfunc, int formal_id, - enum tree_code operation) + enum tree_code operation, tree op_type) { jfunc->type = IPA_JF_PASS_THROUGH; jfunc->value.pass_through.operand = NULL_TREE; + jfunc->value.pass_through.op_type = op_type; jfunc->value.pass_through.formal_id = formal_id; jfunc->value.pass_through.operation = operation; jfunc->value.pass_through.agg_preserved = false; @@ -705,10 +716,12 @@ ipa_set_jf_unary_pass_through (struct ipa_jump_func *jfunc, int formal_id, static void ipa_set_jf_arith_pass_through (struct ipa_jump_func *jfunc, int formal_id, - tree operand, enum tree_code operation) + tree operand, enum tree_code operation, + tree op_type) { jfunc->type = IPA_JF_PASS_THROUGH; jfunc->value.pass_through.operand = unshare_expr_without_location (operand); + jfunc->value.pass_through.op_type = op_type; jfunc->value.pass_through.formal_id = formal_id; jfunc->value.pass_through.operation = operation; jfunc->value.pass_through.agg_preserved = false; @@ -1513,6 +1526,9 @@ compute_complex_assign_jump_func (struct ipa_func_body_info *fbi, if (index >= 0) { + if (lto_variably_modified_type_p (TREE_TYPE (name))) + return; + switch (gimple_assign_rhs_class (stmt)) { case GIMPLE_BINARY_RHS: @@ -1526,7 +1542,8 @@ compute_complex_assign_jump_func (struct ipa_func_body_info *fbi, return; ipa_set_jf_arith_pass_through (jfunc, index, op2, - gimple_assign_rhs_code (stmt)); + gimple_assign_rhs_code (stmt), + TREE_TYPE (name)); break; } case GIMPLE_SINGLE_RHS: @@ -1539,7 +1556,8 @@ compute_complex_assign_jump_func (struct ipa_func_body_info *fbi, case GIMPLE_UNARY_RHS: if (!CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt))) ipa_set_jf_unary_pass_through (jfunc, index, - gimple_assign_rhs_code (stmt)); + gimple_assign_rhs_code (stmt), + TREE_TYPE (name)); default:; } return; @@ -1912,6 +1930,7 @@ analyze_agg_content_value (struct ipa_func_body_info *fbi, if (!is_gimple_assign (stmt)) break; + lhs = gimple_assign_lhs (stmt); rhs1 = gimple_assign_rhs1 (stmt); } @@ -1931,7 +1950,8 @@ analyze_agg_content_value (struct ipa_func_body_info *fbi, PASS-THROUGH jump function with ASSERT_EXPR operation whith operand 1 (the constant from the PHI node). */ - if (gimple_phi_num_args (phi) != 2) + if (gimple_phi_num_args (phi) != 2 + || lto_variably_modified_type_p (TREE_TYPE (lhs))) return; tree arg0 = gimple_phi_arg_def (phi, 0); tree arg1 = gimple_phi_arg_def (phi, 1); @@ -1956,6 +1976,7 @@ analyze_agg_content_value (struct ipa_func_body_info *fbi, code = ASSERT_EXPR; agg_value->pass_through.operand = operand; + agg_value->pass_through.op_type = TREE_TYPE (lhs); } else if (is_gimple_assign (stmt)) { @@ -1980,10 +2001,12 @@ analyze_agg_content_value (struct ipa_func_body_info *fbi, with one operand, here we only allow tc_unary operation to avoid possible problem. Then we can use (opclass == tc_unary) or not to distinguish unary and binary. */ - if (TREE_CODE_CLASS (code) != tcc_unary || CONVERT_EXPR_CODE_P (code)) + if (TREE_CODE_CLASS (code) != tcc_unary || CONVERT_EXPR_CODE_P (code) + || lto_variably_modified_type_p (TREE_TYPE (lhs))) return; rhs1 = get_ssa_def_if_simple_copy (rhs1, &stmt); + agg_value->pass_through.op_type = TREE_TYPE (lhs); break; case GIMPLE_BINARY_RHS: @@ -1992,12 +2015,16 @@ analyze_agg_content_value (struct ipa_func_body_info *fbi, gimple *rhs2_stmt = stmt; tree rhs2 = gimple_assign_rhs2 (stmt); + if (lto_variably_modified_type_p (TREE_TYPE (lhs))) + return; + rhs1 = get_ssa_def_if_simple_copy (rhs1, &rhs1_stmt); rhs2 = get_ssa_def_if_simple_copy (rhs2, &rhs2_stmt); if (is_gimple_ip_invariant (rhs2)) { agg_value->pass_through.operand = rhs2; + agg_value->pass_through.op_type = TREE_TYPE (lhs); stmt = rhs1_stmt; } else if (is_gimple_ip_invariant (rhs1)) @@ -2008,6 +2035,7 @@ analyze_agg_content_value (struct ipa_func_body_info *fbi, return; agg_value->pass_through.operand = rhs1; + agg_value->pass_through.op_type = TREE_TYPE (lhs); stmt = rhs2_stmt; rhs1 = rhs2; } @@ -3520,12 +3548,17 @@ update_jump_functions_after_inlining (struct cgraph_edge *cs, ipa_set_jf_simple_pass_through (dst, formal_id, agg_p); } else if (TREE_CODE_CLASS (operation) == tcc_unary) - ipa_set_jf_unary_pass_through (dst, formal_id, operation); + { + tree op_t = ipa_get_jf_pass_through_op_type (src); + ipa_set_jf_unary_pass_through (dst, formal_id, operation, + op_t); + } else { tree operand = ipa_get_jf_pass_through_operand (src); + tree op_t = ipa_get_jf_pass_through_op_type (src); ipa_set_jf_arith_pass_through (dst, formal_id, operand, - operation); + operation, op_t); } break; } @@ -4935,9 +4968,13 @@ ipa_write_jump_function (struct output_block *ob, } else if (TREE_CODE_CLASS (jump_func->value.pass_through.operation) == tcc_unary) - streamer_write_uhwi (ob, jump_func->value.pass_through.formal_id); + { + stream_write_tree (ob, jump_func->value.pass_through.op_type, true); + streamer_write_uhwi (ob, jump_func->value.pass_through.formal_id); + } else { + stream_write_tree (ob, jump_func->value.pass_through.op_type, true); stream_write_tree (ob, jump_func->value.pass_through.operand, true); streamer_write_uhwi (ob, jump_func->value.pass_through.formal_id); } @@ -4979,6 +5016,8 @@ ipa_write_jump_function (struct output_block *ob, case IPA_JF_LOAD_AGG: streamer_write_uhwi (ob, item->value.pass_through.operation); streamer_write_uhwi (ob, item->value.pass_through.formal_id); + if (item->value.pass_through.operation != NOP_EXPR) + stream_write_tree (ob, item->value.pass_through.op_type, true); if (TREE_CODE_CLASS (item->value.pass_through.operation) != tcc_unary) stream_write_tree (ob, item->value.pass_through.operand, true); @@ -5047,15 +5086,18 @@ ipa_read_jump_function (class lto_input_block *ib, } else if (TREE_CODE_CLASS (operation) == tcc_unary) { + tree op_type = stream_read_tree (ib, data_in); int formal_id = streamer_read_uhwi (ib); - ipa_set_jf_unary_pass_through (jump_func, formal_id, operation); + ipa_set_jf_unary_pass_through (jump_func, formal_id, operation, + op_type); } else { + tree op_type = stream_read_tree (ib, data_in); tree operand = stream_read_tree (ib, data_in); int formal_id = streamer_read_uhwi (ib); ipa_set_jf_arith_pass_through (jump_func, formal_id, operand, - operation); + operation, op_type); } break; case IPA_JF_ANCESTOR: @@ -5103,6 +5145,10 @@ ipa_read_jump_function (class lto_input_block *ib, operation = (enum tree_code) streamer_read_uhwi (ib); item.value.pass_through.operation = operation; item.value.pass_through.formal_id = streamer_read_uhwi (ib); + if (operation != NOP_EXPR) + item.value.pass_through.op_type = stream_read_tree (ib, data_in); + else + item.value.pass_through.op_type = NULL_TREE; if (TREE_CODE_CLASS (operation) == tcc_unary) item.value.pass_through.operand = NULL_TREE; else @@ -5393,6 +5439,49 @@ ipa_read_node_info (class lto_input_block *ib, struct cgraph_node *node, } } +/* Stream out ipa_return_summary. */ +static void +ipa_write_return_summaries (output_block *ob) +{ + if (!ipa_return_value_sum) + { + streamer_write_uhwi (ob, 0); + return; + } + + lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder; + unsigned int count = 0; + for (int i = 0; i < lto_symtab_encoder_size (encoder); i++) + { + symtab_node *snode = lto_symtab_encoder_deref (encoder, i); + cgraph_node *cnode = dyn_cast <cgraph_node *> (snode); + ipa_return_value_summary *v; + + if (cnode && cnode->definition && !cnode->alias + && (v = ipa_return_value_sum->get (cnode)) + && v->vr) + count++; + } + streamer_write_uhwi (ob, count); + + for (int i = 0; i < lto_symtab_encoder_size (encoder); i++) + { + symtab_node *snode = lto_symtab_encoder_deref (encoder, i); + cgraph_node *cnode = dyn_cast <cgraph_node *> (snode); + ipa_return_value_summary *v; + + if (cnode && cnode->definition && !cnode->alias + && (v = ipa_return_value_sum->get (cnode)) + && v->vr) + { + streamer_write_uhwi + (ob, + lto_symtab_encoder_encode (encoder, cnode)); + v->vr->streamer_write (ob); + } + } +} + /* Write jump functions for nodes in SET. */ void @@ -5429,11 +5518,58 @@ ipa_prop_write_jump_functions (void) && ipa_node_params_sum->get (node) != NULL) ipa_write_node_info (ob, node); } - streamer_write_char_stream (ob->main_stream, 0); + ipa_write_return_summaries (ob); produce_asm (ob); destroy_output_block (ob); } +/* Record that return value range of N is VAL. */ + +static void +ipa_record_return_value_range_1 (cgraph_node *n, value_range val) +{ + if (!ipa_return_value_sum) + { + if (!ipa_vr_hash_table) + ipa_vr_hash_table = hash_table<ipa_vr_ggc_hash_traits>::create_ggc (37); + ipa_return_value_sum = new (ggc_alloc_no_dtor <ipa_return_value_sum_t> ()) + ipa_return_value_sum_t (symtab, true); + ipa_return_value_sum->disable_insertion_hook (); + } + ipa_return_value_sum->get_create (n)->vr = ipa_get_value_range (val); + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "Recording return range of %s:", n->dump_name ()); + val.dump (dump_file); + fprintf (dump_file, "\n"); + } +} + +/* Stream out ipa_return_summary. */ +static void +ipa_read_return_summaries (lto_input_block *ib, + struct lto_file_decl_data *file_data, + class data_in *data_in) +{ + unsigned int f_count = streamer_read_uhwi (ib); + for (unsigned int i = 0; i < f_count; i++) + { + unsigned int index = streamer_read_uhwi (ib); + lto_symtab_encoder_t encoder = file_data->symtab_node_encoder; + struct cgraph_node *node + = dyn_cast <cgraph_node *> + (lto_symtab_encoder_deref (encoder, index)); + ipa_vr rvr; + rvr.streamer_read (ib, data_in); + if (node->prevailing_p ()) + { + value_range tmp; + rvr.get_vrange (tmp); + ipa_record_return_value_range_1 (node, tmp); + } + } +} + /* Read section in file FILE_DATA of length LEN with data DATA. */ static void @@ -5470,6 +5606,7 @@ ipa_prop_read_section (struct lto_file_decl_data *file_data, const char *data, gcc_assert (node->definition); ipa_read_node_info (&ib_main, node, data_in); } + ipa_read_return_summaries (&ib_main, file_data, data_in); lto_free_section_data (file_data, LTO_section_jump_functions, NULL, data, len); lto_data_in_delete (data_in); @@ -5589,6 +5726,7 @@ read_ipcp_transformation_info (lto_input_block *ib, cgraph_node *node, } } + /* Write all aggregate replacement for nodes in set. */ void @@ -5627,7 +5765,7 @@ ipcp_write_transformation_summaries (void) && lto_symtab_encoder_encode_body_p (encoder, cnode)) write_ipcp_transformation_info (ob, cnode, ts); } - streamer_write_char_stream (ob->main_stream, 0); + ipa_write_return_summaries (ob); produce_asm (ob); destroy_output_block (ob); } @@ -5668,6 +5806,7 @@ read_replacements_section (struct lto_file_decl_data *file_data, index)); read_ipcp_transformation_info (&ib_main, node, data_in); } + ipa_read_return_summaries (&ib_main, file_data, data_in); lto_free_section_data (file_data, LTO_section_jump_functions, NULL, data, len); lto_data_in_delete (data_in); @@ -6148,22 +6287,8 @@ ipcp_transform_function (struct cgraph_node *node) void ipa_record_return_value_range (value_range val) { - cgraph_node *n = cgraph_node::get (current_function_decl); - if (!ipa_return_value_sum) - { - if (!ipa_vr_hash_table) - ipa_vr_hash_table = hash_table<ipa_vr_ggc_hash_traits>::create_ggc (37); - ipa_return_value_sum = new (ggc_alloc_no_dtor <ipa_return_value_sum_t> ()) - ipa_return_value_sum_t (symtab, true); - ipa_return_value_sum->disable_insertion_hook (); - } - ipa_return_value_sum->get_create (n)->vr = ipa_get_value_range (val); - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "Recording return range "); - val.dump (dump_file); - fprintf (dump_file, "\n"); - } + ipa_record_return_value_range_1 + (cgraph_node::get (current_function_decl), val); } /* Return true if value range of DECL is known and if so initialize RANGE. */ @@ -6224,6 +6349,10 @@ ipa_agg_pass_through_jf_equivalent_p (ipa_pass_through_data *ipt1, || ipt1->formal_id != ipt2->formal_id || (!agg_jf && (ipt1->agg_preserved != ipt2->agg_preserved))) return false; + if (ipt1->operation != NOP_EXPR + && (TYPE_MAIN_VARIANT (ipt1->op_type) + != TYPE_MAIN_VARIANT (ipt2->op_type))) + return false; if (((ipt1->operand != NULL_TREE) != (ipt2->operand != NULL_TREE)) || (ipt1->operand && !values_equal_for_ipcp_p (ipt1->operand, ipt2->operand))) |