Hi, this patch makes the verifier to not check caller frequency. This makes the check to be local for function being called on and allows to avoid fixup_cfg in the patch for nothrow.
The patch also resolves old FIXME about unreachable edges that found two latent bugs - one in inliner fixed by previous patch and one in cgraph_update_edges_for_call_stmt_node fixed here. I think it would make sense to move all ->caller checks to callees (so checking is O(n) in size of funciton checked), but I plan to do that incrementally, probably next stage1. Bootstrapped/regtested x86_64-linux, comitted. * cgraph.c (cgraph_update_edges_for_call_stmt_node): Do not bring dead calls back to live. (cgraph_edge::verify_count_and_frequency): Move cgraph/cfg frequency cross check to ... (cgraph_node::verify_node): ... here; verify only callee edges, not caller. Index: cgraph.c =================================================================== --- cgraph.c (revision 221703) +++ cgraph.c (working copy) @@ -1515,6 +1515,15 @@ cgraph_update_edges_for_call_stmt_node ( if (e) { + /* Keep calls marked as dead dead. */ + if (e->callee + && DECL_BUILT_IN_CLASS (e->callee->decl) == BUILT_IN_NORMAL + && DECL_FUNCTION_CODE (e->callee->decl) == BUILT_IN_UNREACHABLE) + { + node->get_edge (old_stmt)->set_call_stmt + (as_a <gcall *> (new_stmt)); + return; + } /* See if the edge is already there and has the correct callee. It might be so because of indirect inlining has already updated it. We also might've cloned and redirected the edge. */ @@ -2661,25 +2670,6 @@ cgraph_edge::verify_count_and_frequency error ("caller edge frequency is too large"); error_found = true; } - if (gimple_has_body_p (caller->decl) - && !caller->global.inlined_to - && !speculative - /* FIXME: Inline-analysis sets frequency to 0 when edge is optimized out. - Remove this once edges are actually removed from the function at that time. */ - && (frequency - || (inline_edge_summary_vec.exists () - && ((inline_edge_summary_vec.length () <= (unsigned) uid) - || !inline_edge_summary (this)->predicate))) - && (frequency - != compute_call_stmt_bb_frequency (caller->decl, - gimple_bb (call_stmt)))) - { - error ("caller edge frequency %i does not match BB frequency %i", - frequency, - compute_call_stmt_bb_frequency (caller->decl, - gimple_bb (call_stmt))); - error_found = true; - } return error_found; } @@ -2848,9 +2838,46 @@ cgraph_node::verify_node (void) error_found = true; } } + for (e = callees; e; e = e->next_callee) + { + if (e->verify_count_and_frequency ()) + error_found = true; + if (gimple_has_body_p (e->caller->decl) + && !e->caller->global.inlined_to + && !e->speculative + /* Optimized out calls are redirected to __builtin_unreachable. */ + && (e->frequency + || e->callee->decl + != builtin_decl_implicit (BUILT_IN_UNREACHABLE)) + && (e->frequency + != compute_call_stmt_bb_frequency (e->caller->decl, + gimple_bb (e->call_stmt)))) + { + error ("caller edge frequency %i does not match BB frequency %i", + e->frequency, + compute_call_stmt_bb_frequency (e->caller->decl, + gimple_bb (e->call_stmt))); + error_found = true; + } + } for (e = indirect_calls; e; e = e->next_callee) - if (e->verify_count_and_frequency ()) - error_found = true; + { + if (e->verify_count_and_frequency ()) + error_found = true; + if (gimple_has_body_p (e->caller->decl) + && !e->caller->global.inlined_to + && !e->speculative + && (e->frequency + != compute_call_stmt_bb_frequency (e->caller->decl, + gimple_bb (e->call_stmt)))) + { + error ("indirect call frequency %i does not match BB frequency %i", + e->frequency, + compute_call_stmt_bb_frequency (e->caller->decl, + gimple_bb (e->call_stmt))); + error_found = true; + } + } if (!callers && global.inlined_to) { error ("inlined_to pointer is set but no predecessors found");