aboutsummaryrefslogtreecommitdiff
path: root/gcc/ipa-prop.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ipa-prop.cc')
-rw-r--r--gcc/ipa-prop.cc191
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)))