Hi, while cleaning up the way small functions inliner populate the heap I made simple thinko trying to compute summary information used for badness and the badness values themselves in one loop. Since only FDO badness computation depends on summaries this has passed my non-FDO testing.
profilebootstrapped®tested x86_64-linux, comitted. Honza * ipa-inline-transform.c (save_inline_function_body): Add comments. * ipa-inline.c (inline_small_functions): Compute summaries first, populate heap later. Index: ipa-inline-transform.c =================================================================== --- ipa-inline-transform.c (revision 172740) +++ ipa-inline-transform.c (working copy) @@ -253,6 +253,9 @@ save_inline_function_body (struct cgraph /* Now node in question has no clones. */ node->clones = NULL; + /* Inline clones share decl with the function they are cloned + from. Walk the whole clone tree and redirect them all to the + new decl. */ if (first_clone->clones) for (n = first_clone->clones; n != first_clone;) { @@ -275,6 +278,8 @@ save_inline_function_body (struct cgraph tree_function_versioning (node->decl, first_clone->decl, NULL, true, NULL, NULL, NULL); + /* The function will be short lived and removed after we inline all the clones, + but make it internal so we won't confuse ourself. */ DECL_EXTERNAL (first_clone->decl) = 0; DECL_COMDAT_GROUP (first_clone->decl) = NULL_TREE; TREE_PUBLIC (first_clone->decl) = 0; Index: ipa-inline.c =================================================================== --- ipa-inline.c (revision 172740) +++ ipa-inline.c (working copy) @@ -1127,22 +1127,18 @@ inline_small_functions (void) "\nDeciding on inlining of small functions. Starting with size %i.\n", initial_size); - /* Populate the heeap with all edges we might inline. - While doing so compute overall unit size and other global - parameters used by badness metrics. */ + /* Compute overall unit size and other global parameters used by badness + metrics. */ max_count = 0; max_benefit = 0; + for (node = cgraph_nodes; node; node = node->next) if (node->analyzed && !node->global.inlined_to) { struct inline_summary *info = inline_summary (node); - if (dump_file) - fprintf (dump_file, "Enqueueing calls of %s/%i.\n", - cgraph_node_name (node), node->uid); - info->estimated_growth = INT_MIN; if (!DECL_EXTERNAL (node->decl)) @@ -1156,20 +1152,34 @@ inline_small_functions (void) max_count = edge->count; if (max_benefit < benefit) max_benefit = benefit; - if (edge->inline_failed - && can_inline_edge_p (edge, true) - && want_inline_small_function_p (edge, true) - && edge->inline_failed) - { - gcc_assert (!edge->aux); - update_edge_key (heap, edge); - } } } overall_size = initial_size; max_size = compute_max_insns (overall_size); min_size = overall_size; + + /* Populate the heeap with all edges we might inline. */ + + for (node = cgraph_nodes; node; node = node->next) + if (node->analyzed + && !node->global.inlined_to) + { + if (dump_file) + fprintf (dump_file, "Enqueueing calls of %s/%i.\n", + cgraph_node_name (node), node->uid); + + for (edge = node->callers; edge; edge = edge->next_caller) + if (edge->inline_failed + && can_inline_edge_p (edge, true) + && want_inline_small_function_p (edge, true) + && edge->inline_failed) + { + gcc_assert (!edge->aux); + update_edge_key (heap, edge); + } + } + gcc_assert (in_lto_p || !max_count || (profile_info && flag_branch_probabilities));