diff options
Diffstat (limited to 'gcc/ipa-prop.c')
-rw-r--r-- | gcc/ipa-prop.c | 102 |
1 files changed, 75 insertions, 27 deletions
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index abf21c98215..62d7a3c5e84 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -78,6 +78,21 @@ struct ipa_cst_ref_desc static alloc_pool ipa_refdesc_pool; +/* Return true if DECL_FUNCTION_SPECIFIC_OPTIMIZATION of the decl associated + with NODE should prevent us from analyzing it for the purposes of IPA-CP. */ + +static bool +ipa_func_spec_opts_forbid_analysis_p (struct cgraph_node *node) +{ + tree fs_opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (node->symbol.decl); + struct cl_optimization *os; + + if (!fs_opts) + return false; + os = TREE_OPTIMIZATION (fs_opts); + return !os->x_optimize || !os->x_flag_ipa_cp; +} + /* Return index of the formal whose tree is PTREE in function which corresponds to INFO. */ @@ -288,8 +303,9 @@ ipa_print_node_jump_functions (FILE *f, struct cgraph_node *node) ii = cs->indirect_info; if (ii->agg_contents) - fprintf (f, " indirect aggregate callsite, calling param %i, " + fprintf (f, " indirect %s callsite, calling param %i, " "offset " HOST_WIDE_INT_PRINT_DEC ", %s", + ii->member_ptr ? "member ptr" : "aggregate", ii->param_index, ii->offset, ii->by_ref ? "by reference" : "by_value"); else @@ -1327,7 +1343,9 @@ determine_known_aggregate_parts (gimple call, tree arg, lhs = gimple_assign_lhs (stmt); rhs = gimple_assign_rhs1 (stmt); - if (!is_gimple_reg_type (rhs)) + if (!is_gimple_reg_type (rhs) + || TREE_CODE (lhs) == BIT_FIELD_REF + || contains_bitfld_component_ref_p (lhs)) break; lhs_base = get_ref_base_and_extent (lhs, &lhs_offset, &lhs_size, @@ -1418,6 +1436,7 @@ determine_known_aggregate_parts (gimple call, tree arg, { struct ipa_agg_jf_item item; item.offset = list->offset - arg_offset; + gcc_assert ((item.offset % BITS_PER_UNIT) == 0); item.value = unshare_expr_without_location (list->constant); jfunc->agg.items->quick_push (item); } @@ -1443,6 +1462,9 @@ ipa_compute_jump_functions_for_edge (struct param_analysis_info *parms_ainfo, return; vec_safe_grow_cleared (args->jump_functions, arg_num); + if (ipa_func_spec_opts_forbid_analysis_p (cs->caller)) + return; + for (n = 0; n < arg_num; n++) { struct ipa_jump_func *jfunc = ipa_get_ith_jump_func (args, n); @@ -1518,7 +1540,7 @@ ipa_compute_jump_functions (struct cgraph_node *node, NULL); /* We do not need to bother analyzing calls to unknown functions unless they may become known during lto/whopr. */ - if (!callee->analyzed && !flag_lto) + if (!callee->symbol.definition && !flag_lto) continue; ipa_compute_jump_functions_for_edge (parms_ainfo, cs); } @@ -1605,6 +1627,7 @@ ipa_note_param_call (struct cgraph_node *node, int param_index, gimple stmt) cs->indirect_info->offset = 0; cs->indirect_info->polymorphic = 0; cs->indirect_info->agg_contents = 0; + cs->indirect_info->member_ptr = 0; return cs; } @@ -1798,6 +1821,7 @@ ipa_analyze_indirect_call_uses (struct cgraph_node *node, struct cgraph_edge *cs = ipa_note_param_call (node, index, call); cs->indirect_info->offset = offset; cs->indirect_info->agg_contents = 1; + cs->indirect_info->member_ptr = 1; } return; @@ -1933,6 +1957,17 @@ ipa_analyze_params_uses (struct cgraph_node *node, if (ipa_get_param_count (info) == 0 || info->uses_analysis_done) return; + info->uses_analysis_done = 1; + if (ipa_func_spec_opts_forbid_analysis_p (node)) + { + for (i = 0; i < ipa_get_param_count (info); i++) + { + ipa_set_param_used (info, i, true); + ipa_set_controlled_uses (info, i, IPA_UNDESCRIBED_USE); + } + return; + } + for (i = 0; i < ipa_get_param_count (info); i++) { tree parm = ipa_get_param (info, i); @@ -1989,8 +2024,6 @@ ipa_analyze_params_uses (struct cgraph_node *node, visit_ref_for_mod_analysis, visit_ref_for_mod_analysis); } - - info->uses_analysis_done = 1; } /* Free stuff in PARMS_AINFO, assume there are PARAM_COUNT parameters. */ @@ -2209,6 +2242,10 @@ ipa_make_edge_direct_to_target (struct cgraph_edge *ie, tree target) target = canonicalize_constructor_val (target, NULL); if (!target || TREE_CODE (target) != FUNCTION_DECL) { + if (ie->indirect_info->member_ptr) + /* Member pointer call that goes through a VMT lookup. */ + return NULL; + if (dump_file) fprintf (dump_file, "ipa-prop: Discovered direct call to non-function" " in %s/%i, making it unreachable.\n", @@ -2465,8 +2502,9 @@ update_indirect_edges_after_inlining (struct cgraph_edge *cs, new_direct_edge->indirect_inlining_edge = 1; if (new_direct_edge->call_stmt) new_direct_edge->call_stmt_cannot_inline_p - = !gimple_check_call_matching_types (new_direct_edge->call_stmt, - new_direct_edge->callee->symbol.decl); + = !gimple_check_call_matching_types ( + new_direct_edge->call_stmt, + new_direct_edge->callee->symbol.decl, false); if (new_edges) { new_edges->safe_push (new_direct_edge); @@ -2680,9 +2718,6 @@ ipa_propagate_indirect_call_infos (struct cgraph_edge *cs, propagate_controlled_uses (cs); changed = propagate_info_to_inlined_callees (cs, cs->callee, new_edges); - /* We do not keep jump functions of inlined edges up to date. Better to free - them so we do not access them accidentally. */ - ipa_free_edge_args_substructures (IPA_EDGE_REF (cs)); return changed; } @@ -2812,9 +2847,12 @@ ipa_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst, dst_rdesc = (struct ipa_cst_ref_desc *) pool_alloc (ipa_refdesc_pool); dst_rdesc->cs = dst; - dst_rdesc->next_duplicate = src_rdesc->next_duplicate; - src_rdesc->next_duplicate = dst_rdesc; dst_rdesc->refcount = src_rdesc->refcount; + if (dst->caller->global.inlined_to) + { + dst_rdesc->next_duplicate = src_rdesc->next_duplicate; + src_rdesc->next_duplicate = dst_rdesc; + } dst_jf->value.constant.rdesc = dst_rdesc; } else @@ -2829,13 +2867,10 @@ ipa_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst, for (dst_rdesc = src_rdesc->next_duplicate; dst_rdesc; dst_rdesc = dst_rdesc->next_duplicate) - { - gcc_assert (dst_rdesc->cs->caller->global.inlined_to); - if (dst_rdesc->cs->caller->global.inlined_to - == dst->caller->global.inlined_to) - break; - } - + if (dst_rdesc->cs->caller->global.inlined_to + == dst->caller->global.inlined_to) + break; + gcc_assert (dst_rdesc); dst_jf->value.constant.rdesc = dst_rdesc; } } @@ -2975,7 +3010,7 @@ ipa_print_node_params (FILE *f, struct cgraph_node *node) tree temp; struct ipa_node_params *info; - if (!node->analyzed) + if (!node->symbol.definition) return; info = IPA_NODE_REF (node); fprintf (f, " function %s/%i parameter descriptors:\n", @@ -3216,18 +3251,22 @@ void ipa_modify_call_arguments (struct cgraph_edge *cs, gimple stmt, ipa_parm_adjustment_vec adjustments) { + struct cgraph_node *current_node = cgraph_get_node (current_function_decl); vec<tree> vargs; vec<tree, va_gc> **debug_args = NULL; gimple new_stmt; - gimple_stmt_iterator gsi; + gimple_stmt_iterator gsi, prev_gsi; tree callee_decl; int i, len; len = adjustments.length (); vargs.create (len); callee_decl = !cs ? gimple_call_fndecl (stmt) : cs->callee->symbol.decl; + ipa_remove_stmt_references ((symtab_node) current_node, stmt); gsi = gsi_for_stmt (stmt); + prev_gsi = gsi; + gsi_prev (&prev_gsi); for (i = 0; i < len; i++) { struct ipa_parm_adjustment *adj; @@ -3422,6 +3461,14 @@ ipa_modify_call_arguments (struct cgraph_edge *cs, gimple stmt, gsi_replace (&gsi, new_stmt, true); if (cs) cgraph_set_call_stmt (cs, new_stmt); + do + { + ipa_record_stmt_references (current_node, gsi_stmt (gsi)); + gsi_prev (&gsi); + } + while ((gsi_end_p (prev_gsi) && !gsi_end_p (gsi)) + || (!gsi_end_p (prev_gsi) && gsi_stmt (gsi) == gsi_stmt (prev_gsi))); + update_ssa (TODO_update_ssa); free_dominance_info (CDI_DOMINATORS); } @@ -3752,6 +3799,7 @@ ipa_write_indirect_edge_info (struct output_block *ob, bp = bitpack_create (ob->main_stream); bp_pack_value (&bp, ii->polymorphic, 1); bp_pack_value (&bp, ii->agg_contents, 1); + bp_pack_value (&bp, ii->member_ptr, 1); bp_pack_value (&bp, ii->by_ref, 1); streamer_write_bitpack (&bp); @@ -3778,6 +3826,7 @@ ipa_read_indirect_edge_info (struct lto_input_block *ib, bp = streamer_read_bitpack (ib); ii->polymorphic = bp_unpack_value (&bp, 1); ii->agg_contents = bp_unpack_value (&bp, 1); + ii->member_ptr = bp_unpack_value (&bp, 1); ii->by_ref = bp_unpack_value (&bp, 1); if (ii->polymorphic) { @@ -3849,9 +3898,9 @@ ipa_read_node_info (struct lto_input_block *ib, struct cgraph_node *node, info->uses_analysis_done = true; info->node_enqueued = false; for (k = 0; k < ipa_get_param_count (info); k++) - ipa_set_controlled_uses (info, k, streamer_read_hwi (ib)); - for (k = 0; k < ipa_get_param_count (info); k++) ipa_set_param_used (info, k, bp_unpack_value (&bp, 1)); + for (k = 0; k < ipa_get_param_count (info); k++) + ipa_set_controlled_uses (info, k, streamer_read_hwi (ib)); for (e = node->callees; e; e = e->next_callee) { struct ipa_edge_args *args = IPA_EDGE_REF (e); @@ -3957,7 +4006,7 @@ ipa_prop_read_section (struct lto_file_decl_data *file_data, const char *data, index = streamer_read_uhwi (&ib_main); encoder = file_data->symtab_node_encoder; node = cgraph (lto_symtab_encoder_deref (encoder, index)); - gcc_assert (node->analyzed); + gcc_assert (node->symbol.definition); ipa_read_node_info (&ib_main, node, data_in); } lto_free_section_data (file_data, LTO_section_jump_functions, NULL, data, @@ -4001,8 +4050,7 @@ ipa_update_after_lto_read (void) ipa_check_create_edge_args (); FOR_EACH_DEFINED_FUNCTION (node) - if (node->analyzed) - ipa_initialize_node_params (node); + ipa_initialize_node_params (node); } void @@ -4139,7 +4187,7 @@ read_replacements_section (struct lto_file_decl_data *file_data, index = streamer_read_uhwi (&ib_main); encoder = file_data->symtab_node_encoder; node = cgraph (lto_symtab_encoder_deref (encoder, index)); - gcc_assert (node->analyzed); + gcc_assert (node->symbol.definition); read_agg_replacement_chain (&ib_main, node, data_in); } lto_free_section_data (file_data, LTO_section_jump_functions, NULL, data, |