The following manages to avoid high EH indegree of landing pads during the sequence of cleaning up empty EH with a chain of those. By walking the landing pads in reverse order we mimic walking of the EH tree depth-first (which I am too lazy to write...). It looks like EH build assures that this is effectively the same.
Bootstrapped on x86_64-unknown-linux-gnu, testing in progress. OK? With this the RedHat bugzilla testcase is down to a "flat" profile: parser function body : 14.60 ( 17%) 1.77 ( 31%) 16.37 ( 18%) 720798 kB ( 23%) tree eh : 14.80 ( 17%) 0.06 ( 1%) 14.87 ( 16%) 246315 kB ( 8%) integrated RA : 13.08 ( 15%) 0.30 ( 5%) 13.40 ( 15%) 227799 kB ( 7%) TOTAL : 85.07 5.68 90.77 3183334 kB and memory usage is down as well to 4GB (it's actually this very patch that helps here for reasons I have not investigated - maybe we never shrink some EH data structures, who knows). Thanks, Richard. 2020-01-10 Richard Biener <rguent...@suse.de> PR middle-end/93199 * tree-eh.c (redirect_eh_edge_1): Avoid some work if possible. (cleanup_all_empty_eh): Walk landing pads in reverse order to avoid quadraticness. Index: gcc/tree-eh.c =================================================================== --- gcc/tree-eh.c (revision 280097) +++ gcc/tree-eh.c (working copy) @@ -2310,7 +2310,7 @@ redirect_eh_edge_1 (edge edge_in, basic_ old_lp = get_eh_landing_pad_from_number (old_lp_nr); throw_stmt = last_stmt (edge_in->src); - gcc_assert (lookup_stmt_eh_lp (throw_stmt) == old_lp_nr); + gcc_checking_assert (lookup_stmt_eh_lp (throw_stmt) == old_lp_nr); new_label = gimple_block_label (new_bb); @@ -4307,9 +4307,10 @@ cleanup_empty_eh_merge_phis (basic_block | | EH <..> which CFG verification would choke on. See PR45172 and PR51089. */ - FOR_EACH_EDGE (e, ei, old_bb->preds) - if (find_edge (e->src, new_bb)) - return false; + if (!single_pred_p (new_bb)) + FOR_EACH_EDGE (e, ei, old_bb->preds) + if (find_edge (e->src, new_bb)) + return false; FOR_EACH_EDGE (e, ei, old_bb->preds) redirect_edge_var_map_clear (e); @@ -4698,9 +4699,15 @@ cleanup_all_empty_eh (void) eh_landing_pad lp; int i; - for (i = 1; vec_safe_iterate (cfun->eh->lp_array, i, &lp); ++i) - if (lp) - changed |= cleanup_empty_eh (lp); + /* Ideally we'd walk the region tree and process LPs inner to outer + to avoid quadraticness in EH redirection. Walking the LP array + in reverse seems to be an approximation of that. */ + for (i = vec_safe_length (cfun->eh->lp_array) - 1; i >= 1; --i) + { + lp = (*cfun->eh->lp_array)[i]; + if (lp) + changed |= cleanup_empty_eh (lp); + } return changed; }