From 11b73810a1c6d07ba5957a462549785a6c9165ea Mon Sep 17 00:00:00 2001 From: hubicka Date: Fri, 29 Aug 2008 16:41:35 +0000 Subject: [PATCH] * cgraph.c (cgraph_remove_node): Do not remove nested nodes. * cgraph.h (cgraph_maybe_hot_edge_p): Declare. * ipa-cp.c (n_cloning_candidates): New static variable. (ipcp_print_profile_data, ipcp_function_scale_print): Forward declare. (ipcp_print_all_lattices): Improve debug output. (ipcp_cloning_candidate_p): New function. (ipcp_initialize_node_lattices): Use it. (ipcp_init_stage): Do only analyzis here; prettier debug output. (ipcp_propagate_stage): Prettier debug output. (ipcp_iterate_stage): Initialize latices here; prettier debug output. (ipcp_print_all_structures): Remove. (ipcp_need_redirect_p): Test !n_cloning_candidates. (ipcp_insert_stage): Prettier debug output; call cgraph_remove_unreachable_nodes before propagating. (pass_ipa_cp): Schedule function removal pass. * ipa-inline.c (inline_indirect_intraprocedural_analysis): Better debug output. (cgraph_maybe_hot_edge_p): Move to ... * predict.c (cgraph_maybe_hot_edge_p) ... here. * opts.c (flag_ipa_cp_set, flag_ipa_cp_clone_set): New. (common_handle_option): Set them; enable ipa-cp when profiling. * ipa-prop.c (ipa_print_node_jump_functions): Prettier output. (ipa_print_all_jump_functions): Likewise. (ipa_print_all_tree_maps, ipa_print_node_param_flags): Remove. (ipa_print_node_params, ipa_print_all_params): New. * ipa-prop.h (ipa_print_all_tree_maps, ipa_print_node_param_flags, ipa_print_all_param_flags): Remove. (ipa_print_node_params, ipa_print_all_params): New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@139772 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 32 ++++++ gcc/cgraph.c | 6 +- gcc/cgraph.h | 2 + gcc/ipa-cp.c | 218 +++++++++++++++++++++++++++++-------- gcc/ipa-inline.c | 28 +---- gcc/ipa-prop.c | 53 +++------ gcc/ipa-prop.h | 5 +- gcc/opts.c | 18 ++- gcc/predict.c | 21 ++++ gcc/testsuite/ChangeLog | 4 + gcc/testsuite/gcc.dg/ipa/modif-1.c | 18 +-- 11 files changed, 279 insertions(+), 126 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 86f729cd3b0..a808305db83 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,35 @@ +2008-08-29 Jan Hubicka + + * cgraph.c (cgraph_remove_node): Do not remove nested nodes. + + * cgraph.h (cgraph_maybe_hot_edge_p): Declare. + * ipa-cp.c (n_cloning_candidates): New static variable. + (ipcp_print_profile_data, ipcp_function_scale_print): Forward declare. + (ipcp_print_all_lattices): Improve debug output. + (ipcp_cloning_candidate_p): New function. + (ipcp_initialize_node_lattices): Use it. + (ipcp_init_stage): Do only analyzis here; prettier debug output. + (ipcp_propagate_stage): Prettier debug output. + (ipcp_iterate_stage): Initialize latices here; prettier debug output. + (ipcp_print_all_structures): Remove. + (ipcp_need_redirect_p): Test !n_cloning_candidates. + (ipcp_insert_stage): Prettier debug output; call + cgraph_remove_unreachable_nodes before propagating. + (pass_ipa_cp): Schedule function removal pass. + * ipa-inline.c (inline_indirect_intraprocedural_analysis): Better + debug output. + (cgraph_maybe_hot_edge_p): Move to ... + * predict.c (cgraph_maybe_hot_edge_p) ... here. + * opts.c (flag_ipa_cp_set, flag_ipa_cp_clone_set): New. + (common_handle_option): Set them; enable ipa-cp when profiling. + * ipa-prop.c (ipa_print_node_jump_functions): Prettier output. + (ipa_print_all_jump_functions): Likewise. + (ipa_print_all_tree_maps, ipa_print_node_param_flags): Remove. + (ipa_print_node_params, ipa_print_all_params): New. + * ipa-prop.h (ipa_print_all_tree_maps, ipa_print_node_param_flags, + ipa_print_all_param_flags): Remove. + (ipa_print_node_params, ipa_print_all_params): New. + 2008-08-29 Bob Wilson * config/xtensa/xtensa.c (xtensa_secondary_reload_class): Revert diff --git a/gcc/cgraph.c b/gcc/cgraph.c index a0db5860f39..fdc156dfe33 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -857,6 +857,7 @@ cgraph_remove_node (struct cgraph_node *node) { void **slot; bool kill_body = false; + struct cgraph_node *n; cgraph_call_node_removal_hooks (node); cgraph_node_remove_callers (node); @@ -865,8 +866,9 @@ cgraph_remove_node (struct cgraph_node *node) /* Incremental inlining access removed nodes stored in the postorder list. */ node->needed = node->reachable = false; - while (node->nested) - cgraph_remove_node (node->nested); + for (n = node->nested; n; n = n->next_nested) + n->origin = NULL; + node->nested = NULL; if (node->origin) { struct cgraph_node **node2 = &node->origin->nested; diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 5fe0eea21f2..eec56a53903 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -390,6 +390,8 @@ int compute_call_stmt_bb_frequency (basic_block bb); bool cgraph_remove_unreachable_nodes (bool, FILE *); int cgraph_postorder (struct cgraph_node **); +bool cgraph_maybe_hot_edge_p (struct cgraph_edge *e); + /* In varpool.c */ extern GTY(()) struct varpool_node *varpool_nodes_queue; diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index 4b0a5f2c2db..6c3572dd51e 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -135,6 +135,21 @@ along with GCC; see the file COPYING3. If not see #include "fibheap.h" #include "params.h" +/* Number of functions identified as candidates for cloning. When not cloning + we can simplify iterate stage not forcing it to go through the decision + on what is profitable and what not. */ +static int n_cloning_candidates; + +/* Maximal count found in program. */ +static gcov_type max_count; + +/* Cgraph nodes that has been completely replaced by cloning during iterate + * stage and will be removed after ipcp is finished. */ +static bitmap dead_nodes; + +static void ipcp_print_profile_data (FILE *); +static void ipcp_function_scale_print (FILE *); + /* Get the original node field of ipa_node_params associated with node NODE. */ static inline struct cgraph_node * ipcp_get_orig_node (struct cgraph_node *node) @@ -174,7 +189,7 @@ ipcp_analyze_node (struct cgraph_node *node) } /* Recompute all local information since node might've got new - direct calls after clonning. */ + direct calls after cloning. */ static void ipcp_update_cloned_node (struct cgraph_node *new_node) { @@ -337,7 +352,7 @@ ipcp_print_all_lattices (FILE * f) struct cgraph_node *node; int i, count; - fprintf (f, "\nLATTICE PRINT\n"); + fprintf (f, "\nLattice:\n"); for (node = cgraph_nodes; node; node = node->next) { struct ipa_node_params *info; @@ -345,13 +360,13 @@ ipcp_print_all_lattices (FILE * f) if (!node->analyzed) continue; info = IPA_NODE_REF (node); - fprintf (f, "Printing lattices %s:\n", cgraph_node_name (node)); + fprintf (f, " Node: %s:\n", cgraph_node_name (node)); count = ipa_get_param_count (info); for (i = 0; i < count; i++) { struct ipcp_lattice *lat = ipcp_get_ith_lattice (info, i); - fprintf (f, " param [%d]: ", i); + fprintf (f, " param [%d]: ", i); if (lat->type == IPA_CONST_VALUE) { fprintf (f, "type is CONST "); @@ -366,6 +381,100 @@ ipcp_print_all_lattices (FILE * f) } } +/* Return true if this NODE is viable candidate for cloning. */ +static bool +ipcp_cloning_candidate_p (struct cgraph_node *node) +{ + int n_calls = 0; + int n_hot_calls = 0; + gcov_type direct_call_sum = 0; + struct cgraph_edge *e; + + /* We never clone functions that are not visible from outside. + FIXME: in future we should clone such functions when they are called with + different constants, but current ipcp implementation is not good on this. + */ + if (!node->needed || !node->analyzed) + return false; + + if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE) + { + if (dump_file) + fprintf (dump_file, "Not considering %s for cloning; body is overwrittable.\n", + cgraph_node_name (node)); + return false; + } + if (!tree_versionable_function_p (node->decl)) + { + if (dump_file) + fprintf (dump_file, "Not considering %s for cloning; body is not versionable.\n", + cgraph_node_name (node)); + return false; + } + for (e = node->callers; e; e = e->next_caller) + { + direct_call_sum += e->count; + n_calls ++; + if (cgraph_maybe_hot_edge_p (e)) + n_hot_calls ++; + } + + if (!n_calls) + { + if (dump_file) + fprintf (dump_file, "Not considering %s for cloning; no direct calls.\n", + cgraph_node_name (node)); + return false; + } + if (node->local.inline_summary.self_insns < n_calls) + { + if (dump_file) + fprintf (dump_file, "Considering %s for cloning; code would shrink.\n", + cgraph_node_name (node)); + return true; + } + + if (!flag_ipa_cp_clone) + { + if (dump_file) + fprintf (dump_file, "Not considering %s for cloning; -fipa-cp-clone disabled.\n", + cgraph_node_name (node)); + return false; + } + + if (!optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->decl))) + { + if (dump_file) + fprintf (dump_file, "Not considering %s for cloning; optimizing it for size.\n", + cgraph_node_name (node)); + return false; + } + + /* When profile is available and function is hot, propagate into it even if + calls seems cold; constant propagation can improve function's speed + significandly. */ + if (max_count) + { + if (direct_call_sum > node->count * 90 / 100) + { + if (dump_file) + fprintf (dump_file, "Considering %s for cloning; usually called directly.\n", + cgraph_node_name (node)); + return true; + } + } + if (!n_hot_calls) + { + if (dump_file) + fprintf (dump_file, "Not considering %s for cloning; no hot calls.\n", + cgraph_node_name (node)); + } + if (dump_file) + fprintf (dump_file, "Considering %s for cloning.\n", + cgraph_node_name (node)); + return true; +} + /* Initialize ipcp_lattices array. The lattices corresponding to supported types (integers, real types and Fortran constants defined as const_decls) are initialized to IPA_TOP, the rest of them to IPA_BOTTOM. */ @@ -374,18 +483,24 @@ ipcp_initialize_node_lattices (struct cgraph_node *node) { int i; struct ipa_node_params *info = IPA_NODE_REF (node); + enum ipa_lattice_type type; info->ipcp_lattices = XCNEWVEC (struct ipcp_lattice, ipa_get_param_count (info)); + if (ipa_is_called_with_var_arguments (info)) + type = IPA_BOTTOM; + else if (!node->needed) + type = IPA_TOP; /* When cloning is allowed, we can assume that externally visible functions are not called. We will compensate this by cloning later. */ - if (flag_ipa_cp_clone || !node->needed) - for (i = 0; i < ipa_get_param_count (info) ; i++) - ipcp_get_ith_lattice (info, i)->type = IPA_TOP; + else if (ipcp_cloning_candidate_p (node)) + type = IPA_TOP, n_cloning_candidates ++; else - for (i = 0; i < ipa_get_param_count (info) ; i++) - ipcp_get_ith_lattice (info, i)->type = IPA_BOTTOM; + type = IPA_BOTTOM; + + for (i = 0; i < ipa_get_param_count (info) ; i++) + ipcp_get_ith_lattice (info, i)->type = type; } /* build INTEGER_CST tree with type TREE_TYPE and value according to LAT. @@ -438,11 +553,7 @@ ipcp_init_stage (void) for (node = cgraph_nodes; node; node = node->next) if (node->analyzed) - { - ipcp_analyze_node (node); - ipcp_initialize_node_lattices (node); - ipcp_compute_node_scale (node); - } + ipcp_analyze_node (node); for (node = cgraph_nodes; node; node = node->next) { if (!node->analyzed) @@ -489,6 +600,13 @@ ipcp_change_tops_to_bottom (void) if (lat->type == IPA_TOP) { prop_again = true; + if (dump_file) + { + fprintf (dump_file, "Forcing param "); + print_generic_expr (dump_file, ipa_get_ith_param (info, i), 0); + fprintf (dump_file, " of node %s to bottom.\n", + cgraph_node_name (node)); + } lat->type = IPA_BOTTOM; } } @@ -512,6 +630,7 @@ ipcp_propagate_stage (void) ipa_check_create_node_params (); ipa_check_create_edge_args (); + /* Initialize worklist to contain all functions. */ wl = ipa_init_func_list (); while (wl) @@ -550,11 +669,37 @@ ipcp_propagate_stage (void) static void ipcp_iterate_stage (void) { + struct cgraph_node *node; + n_cloning_candidates = 0; + + if (dump_file) + fprintf (dump_file, "\nIPA iterate stage:\n\n"); + for (node = cgraph_nodes; node; node = node->next) + { + ipcp_initialize_node_lattices (node); + ipcp_compute_node_scale (node); + } + if (dump_file && (dump_flags & TDF_DETAILS)) + { + ipcp_print_all_lattices (dump_file); + ipcp_function_scale_print (dump_file); + } + ipcp_propagate_stage (); if (ipcp_change_tops_to_bottom ()) /* Some lattices have changed from IPA_TOP to IPA_BOTTOM. This change should be propagated. */ - ipcp_propagate_stage (); + { + gcc_assert (n_cloning_candidates); + ipcp_propagate_stage (); + } + if (dump_file) + { + fprintf (dump_file, "\nIPA lattices after propagation:\n"); + ipcp_print_all_lattices (dump_file); + if (dump_flags & TDF_DETAILS) + ipcp_print_profile_data (dump_file); + } } /* Check conditions to forbid constant insertion to function described by @@ -708,17 +853,6 @@ ipcp_print_bb_profiles (FILE * f) } } -/* Print all IPCP data structures to F. */ -static void -ipcp_print_all_structures (FILE * f) -{ - ipcp_print_all_lattices (f); - ipcp_function_scale_print (f); - ipa_print_all_tree_maps (f); - ipa_print_all_param_flags (f); - ipa_print_all_jump_functions (f); -} - /* Print profile info for all functions. */ static void ipcp_print_profile_data (FILE * f) @@ -771,7 +905,7 @@ ipcp_need_redirect_p (struct cgraph_edge *cs) struct ipa_jump_func *jump_func; struct cgraph_node *node = cs->callee, *orig; - if (!flag_ipa_cp_clone) + if (!n_cloning_candidates) return false; if ((orig = ipcp_get_orig_node (node)) != NULL) @@ -908,10 +1042,6 @@ ipcp_update_profiling (void) } } -/* Maximal count found in program. */ -static gcov_type max_count; -bitmap dead_nodes; - /* Return true if original clone needs to be preserved. */ static bool ipcp_need_original_clone_p (struct cgraph_node *node) @@ -1008,6 +1138,8 @@ ipcp_insert_stage (void) ipa_check_create_node_params (); ipa_check_create_edge_args (); + if (dump_file) + fprintf (dump_file, "\nIPA insert stage:\n\n"); dead_nodes = BITMAP_ALLOC (NULL); @@ -1156,18 +1288,19 @@ ipcp_insert_stage (void) static unsigned int ipcp_driver (void) { - /* 2. Do the interprocedural propagation. */ - ipcp_iterate_stage (); + cgraph_remove_unreachable_nodes (true,dump_file); if (dump_file) { - fprintf (dump_file, "\nIPA structures after propagation:\n"); - ipcp_print_all_structures (dump_file); - fprintf (dump_file, "\nProfiling info before insert stage:\n"); - ipcp_print_profile_data (dump_file); + fprintf (dump_file, "\nIPA structures before propagation:\n"); + if (dump_flags & TDF_DETAILS) + ipa_print_all_params (dump_file); + ipa_print_all_jump_functions (dump_file); } + /* 2. Do the interprocedural propagation. */ + ipcp_iterate_stage (); /* 3. Insert the constants found to the functions. */ ipcp_insert_stage (); - if (dump_file) + if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, "\nProfiling info after insert stage:\n"); ipcp_print_profile_data (dump_file); @@ -1176,7 +1309,6 @@ ipcp_driver (void) free_all_ipa_structures_after_ipa_cp (); if (dump_file) fprintf (dump_file, "\nIPA constant propagation end\n"); - cgraph_remove_unreachable_nodes (true, NULL); return 0; } @@ -1192,11 +1324,6 @@ ipcp_generate_summary (void) /* 1. Call the init stage to initialize the ipa_node_params and ipa_edge_args structures. */ ipcp_init_stage (); - if (dump_file) - { - fprintf (dump_file, "\nIPA structures before propagation:\n"); - ipcp_print_all_structures (dump_file); - } } /* Gate for IPCP optimization. */ @@ -1221,7 +1348,8 @@ struct ipa_opt_pass pass_ipa_cp = PROP_trees, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ - TODO_dump_cgraph | TODO_dump_func /* todo_flags_finish */ + TODO_dump_cgraph | TODO_dump_func | + TODO_remove_functions /* todo_flags_finish */ }, ipcp_generate_summary, /* generate_summary */ NULL, /* write_summary */ diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c index 94062f2a0f2..a85a8a3be6b 100644 --- a/gcc/ipa-inline.c +++ b/gcc/ipa-inline.c @@ -468,26 +468,6 @@ cgraph_recursive_inlining_p (struct cgraph_node *to, return recursive; } -/* Return true if the call can be hot. */ -static bool -cgraph_maybe_hot_edge_p (struct cgraph_edge *edge) -{ - if (profile_info && flag_branch_probabilities - && (edge->count - <= profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION))) - return false; - if (lookup_attribute ("cold", DECL_ATTRIBUTES (edge->callee->decl)) - || lookup_attribute ("cold", DECL_ATTRIBUTES (edge->caller->decl))) - return false; - if (lookup_attribute ("hot", DECL_ATTRIBUTES (edge->caller->decl))) - return true; - if (flag_guess_branch_prob - && edge->frequency < (CGRAPH_FREQ_MAX - / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION))) - return false; - return true; -} - /* A cost model driving the inlining heuristics in a way so the edges with smallest badness are inlined first. After each inlining is performed the costs of all caller edges of nodes affected are recomputed so the @@ -1646,9 +1626,6 @@ inline_indirect_intraprocedural_analysis (struct cgraph_node *node) } ipa_analyze_params_uses (node); - if (dump_file) - ipa_print_node_param_flags (dump_file, node); - if (!flag_ipa_cp) for (cs = node->callees; cs; cs = cs->next_callee) { @@ -1657,7 +1634,10 @@ inline_indirect_intraprocedural_analysis (struct cgraph_node *node) } if (dump_file) - ipa_print_node_jump_functions (dump_file, node); + { + ipa_print_node_params (dump_file, node); + ipa_print_node_jump_functions (dump_file, node); + } } /* Note function body size. */ diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index 9a31b024113..ffbf3adb668 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -255,13 +255,13 @@ ipa_print_node_jump_functions (FILE *f, struct cgraph_node *node) struct ipa_jump_func *jump_func; enum jump_func_type type; - fprintf (f, "JUMP FUNCTIONS OF CALLER %s:\n", cgraph_node_name (node)); + fprintf (f, " Jump functions of caller %s:\n", cgraph_node_name (node)); for (cs = node->callees; cs; cs = cs->next_callee) { if (!ipa_edge_args_info_available_for_edge_p (cs)) continue; - fprintf (f, "callsite %s ", cgraph_node_name (node)); + fprintf (f, " callsite %s ", cgraph_node_name (node)); fprintf (f, "-> %s :: \n", cgraph_node_name (cs->callee)); count = ipa_get_cs_argument_count (IPA_EDGE_REF (cs)); @@ -270,7 +270,7 @@ ipa_print_node_jump_functions (FILE *f, struct cgraph_node *node) jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i); type = jump_func->type; - fprintf (f, " param %d: ", i); + fprintf (f, " param %d: ", i); if (type == IPA_UNKNOWN) fprintf (f, "UNKNOWN\n"); else if (type == IPA_CONST) @@ -303,7 +303,7 @@ ipa_print_all_jump_functions (FILE *f) { struct cgraph_node *node; - fprintf (f, "\nCALLSITE PARAM PRINT\n"); + fprintf (f, "\nJump functions:\n"); for (node = cgraph_nodes; node; node = node->next) { ipa_print_node_jump_functions (f, node); @@ -1207,48 +1207,23 @@ free_all_ipa_structures_after_iinln (void) /* Print ipa_tree_map data structures of all functions in the callgraph to F. */ void -ipa_print_all_tree_maps (FILE * f) +ipa_print_node_params (FILE * f, struct cgraph_node *node) { int i, count; tree temp; - struct cgraph_node *node; - - fprintf (f, "\nPARAM TREE MAP PRINT\n"); - for (node = cgraph_nodes; node; node = node->next) - { - struct ipa_node_params *info; - - if (!node->analyzed) - continue; - info = IPA_NODE_REF (node); - fprintf (f, "function %s Trees :: \n", cgraph_node_name (node)); - count = ipa_get_param_count (info); - for (i = 0; i < count; i++) - { - temp = ipa_get_ith_param (info, i); - if (TREE_CODE (temp) == PARM_DECL) - fprintf (f, " param [%d] : %s\n", i, - (*lang_hooks.decl_printable_name) (temp, 2)); - } - - } -} - -/* Print param_flags data structures of the NODE to F. */ -void -ipa_print_node_param_flags (FILE * f, struct cgraph_node *node) -{ - int i, count; struct ipa_node_params *info; if (!node->analyzed) return; info = IPA_NODE_REF (node); - fprintf (f, "PARAM FLAGS of function %s: \n", cgraph_node_name (node)); + fprintf (f, " function %s Trees :: \n", cgraph_node_name (node)); count = ipa_get_param_count (info); for (i = 0; i < count; i++) { - fprintf (f, " param %d flags:", i); + temp = ipa_get_ith_param (info, i); + if (TREE_CODE (temp) == PARM_DECL) + fprintf (f, " param %d : %s", i, + (*lang_hooks.decl_printable_name) (temp, 2)); if (ipa_is_ith_param_modified (info, i)) fprintf (f, " modified"); if (ipa_is_ith_param_called (info, i)) @@ -1257,14 +1232,14 @@ ipa_print_node_param_flags (FILE * f, struct cgraph_node *node) } } -/* Print param_flags data structures of all functions in the +/* Print ipa_tree_map data structures of all functions in the callgraph to F. */ void -ipa_print_all_param_flags (FILE * f) +ipa_print_all_params (FILE * f) { struct cgraph_node *node; - fprintf (f, "\nIPA PARAM FLAGS DUMP\n"); + fprintf (f, "\nFunction parameters:\n"); for (node = cgraph_nodes; node; node = node->next) - ipa_print_node_param_flags (f, node); + ipa_print_node_params (f, node); } diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h index 967825e21f8..80b591bc2f8 100644 --- a/gcc/ipa-prop.h +++ b/gcc/ipa-prop.h @@ -381,9 +381,8 @@ void ipa_propagate_indirect_call_infos (struct cgraph_edge *cs, VEC (cgraph_edge_p, heap) *new_edges); /* Debugging interface. */ -void ipa_print_all_tree_maps (FILE *); -void ipa_print_node_param_flags (FILE * f, struct cgraph_node *node); -void ipa_print_all_param_flags (FILE *); +void ipa_print_node_params (FILE *, struct cgraph_node *node); +void ipa_print_all_params (FILE *); void ipa_print_node_jump_functions (FILE *f, struct cgraph_node *node); void ipa_print_all_jump_functions (FILE * f); diff --git a/gcc/opts.c b/gcc/opts.c index 898f1fbad73..fbe67569c2d 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -347,7 +347,7 @@ static bool profile_arc_flag_set, flag_profile_values_set; static bool flag_unroll_loops_set, flag_tracer_set; static bool flag_value_profile_transformations_set; static bool flag_peel_loops_set, flag_branch_probabilities_set; -static bool flag_inline_functions_set; +static bool flag_inline_functions_set, flag_ipa_cp_set, flag_ipa_cp_clone_set; /* Functions excluded from profiling. */ @@ -1031,9 +1031,6 @@ decode_options (unsigned int argc, const char **argv) /* We want to crossjump as much as possible. */ set_param_value ("min-crossjump-insns", 1); - - /* Do not perform clonning in ipcp. */ - flag_ipa_cp_clone = 0; } else set_param_value ("min-crossjump-insns", initial_min_crossjump_insns); @@ -1837,6 +1834,11 @@ common_handle_option (size_t scode, const char *arg, int value, flag_value_profile_transformations = value; if (!flag_inline_functions_set) flag_inline_functions = value; + if (!flag_ipa_cp_set) + flag_ipa_cp = value; + if (!flag_ipa_cp_clone_set + && value && flag_ipa_cp) + flag_ipa_cp_clone = value; break; case OPT_fprofile_generate_: @@ -1994,6 +1996,14 @@ common_handle_option (size_t scode, const char *arg, int value, flag_tracer_set = true; break; + case OPT_fipa_cp: + flag_ipa_cp_set = true; + break; + + case OPT_fipa_cp_clone: + flag_ipa_cp_clone_set = true; + break; + case OPT_funroll_loops: flag_unroll_loops_set = true; break; diff --git a/gcc/predict.c b/gcc/predict.c index 45fffd3b483..4e17b9ac676 100644 --- a/gcc/predict.c +++ b/gcc/predict.c @@ -138,6 +138,27 @@ maybe_hot_bb_p (const_basic_block bb) return maybe_hot_frequency_p (bb->frequency); } +/* Return true if the call can be hot. */ + +bool +cgraph_maybe_hot_edge_p (struct cgraph_edge *edge) +{ + if (profile_info && flag_branch_probabilities + && (edge->count + <= profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION))) + return false; + if (lookup_attribute ("cold", DECL_ATTRIBUTES (edge->callee->decl)) + || lookup_attribute ("cold", DECL_ATTRIBUTES (edge->caller->decl))) + return false; + if (lookup_attribute ("hot", DECL_ATTRIBUTES (edge->caller->decl))) + return true; + if (flag_guess_branch_prob + && edge->frequency < (CGRAPH_FREQ_MAX + / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION))) + return false; + return true; +} + /* Return true in case BB can be CPU intensive and should be optimized for maximal performance. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index bdc48206721..2aa360a9a09 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2008-08-29 Jan Hubicka + * gcc.dg/ipa/modif-1.c: Update template. + +2008-08-29 Jan Hubicka + * gcc.dg/ipa/ipa-1.c: Fix template for better debug output. * gcc.dg/ipa/ipa-2.c: Fix template for better debug output. * gcc.dg/ipa/ipa-3.c: Fix template for better debug output. diff --git a/gcc/testsuite/gcc.dg/ipa/modif-1.c b/gcc/testsuite/gcc.dg/ipa/modif-1.c index 7d160cb7e74..bc1706c5650 100644 --- a/gcc/testsuite/gcc.dg/ipa/modif-1.c +++ b/gcc/testsuite/gcc.dg/ipa/modif-1.c @@ -1,6 +1,6 @@ /* Verify that modification analysis detects modfications. */ /* { dg-do compile } */ -/* { dg-options "-O3 -c -fdump-ipa-inline -fno-early-inlining" } */ +/* { dg-options "-O3 -c -fdump-ipa-inline-details -fno-early-inlining" } */ struct whatever { @@ -33,12 +33,12 @@ void the_test (struct whatever u, struct whatever v, func4 (&l); } -/* { dg-final { scan-ipa-dump-not "param 0 flags:\[^\\n\]*modified" "inline" } } */ -/* { dg-final { scan-ipa-dump "param 1 flags:\[^\\n\]*modified" "inline" } } */ -/* { dg-final { scan-ipa-dump "param 2 flags:\[^\\n\]*modified" "inline" } } */ -/* { dg-final { scan-ipa-dump "param 3 flags:\[^\\n\]*modified" "inline" } } */ -/* { dg-final { scan-ipa-dump-not "param 4 flags:\[^\\n\]*modified" "inline" } } */ -/* { dg-final { scan-ipa-dump "param 5 flags:\[^\\n\]*modified" "inline" } } */ -/* { dg-final { scan-ipa-dump "param 6 flags:\[^\\n\]*modified" "inline" } } */ -/* { dg-final { scan-ipa-dump "param 7 flags:\[^\\n\]*modified" "inline" } } */ +/* { dg-final { scan-ipa-dump-not "param 0\[^\\n\]*modified" "inline" } } */ +/* { dg-final { scan-ipa-dump "param 1\[^\\n\]*modified" "inline" } } */ +/* { dg-final { scan-ipa-dump "param 2\[^\\n\]*modified" "inline" } } */ +/* { dg-final { scan-ipa-dump "param 3\[^\\n\]*modified" "inline" } } */ +/* { dg-final { scan-ipa-dump-not "param 4\[^\\n\]*modified" "inline" } } */ +/* { dg-final { scan-ipa-dump "param 5\[^\\n\]*modified" "inline" } } */ +/* { dg-final { scan-ipa-dump "param 6\[^\\n\]*modified" "inline" } } */ +/* { dg-final { scan-ipa-dump "param 7\[^\\n\]*modified" "inline" } } */ /* { dg-final { cleanup-ipa-dump "inline" } } */ -- 2.11.0