https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93199

--- Comment #12 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Richard Biener from comment #11)
> -   77.83%     0.45%         16118  cc1plus  cc1plus           [.]
> (anonymous namespace)::pass_cleanup_eh::execute              ▒
>    - 77.38% (anonymous namespace)::pass_cleanup_eh::execute 
>       - 77.29% cleanup_empty_eh_merge_phis              
>          - 44.55% redirect_eh_edge_1
>               30.45% last_stmt                                              
> 
>             + 4.01% lookup_stmt_eh_lp_fn                                    
> 
>             + 2.96% remove_stmt_from_eh_lp_fn                               
> 
>               2.77% gimple_block_label                                      
> 
>               0.55% get_eh_landing_pad_from_number                     
>          + 16.68% add_stmt_to_eh_lp_fn                      
>            5.34% find_edge                                     
>          + 4.58% redirect_edge_succ                          
>            0.59% gimple_execute_on_growing_pred
> 
> that last_stmt figure looks odd tho (I blame perf for this).  This is on
> the original redhat bugzilla testcase btw, will check your reduced one.

Apart from structural quadraticnesses involving edges the main hog seems
to be the quadratic updating of the RESX stmt moving here:

static void
redirect_eh_edge_1 (edge edge_in, basic_block new_bb, bool change_region)
{ 
...
  /* Maybe move the throwing statement to the new region.  */
  if (old_lp != new_lp)
    {    
      remove_stmt_from_eh_lp (throw_stmt);
      add_stmt_to_eh_lp (throw_stmt, new_lp->index);
    }   

which boils down to the very same issue.  We're also getting a very big
in-degree for the EH redirection probably because we're walking the EH
LP array when optimizing empty EH.  Thus code like

  /* Notice when we redirect the last EH edge away from OLD_BB.  */
  FOR_EACH_EDGE (e, ei, old_bb->preds)
    if (e != edge_in && (e->flags & EDGE_EH))
      break;

ends up expensive as well (we will move all EH edges anyway so the
above at least could be avoided with some care).  Not to mention

  FOR_EACH_EDGE (e, ei, old_bb->preds)
    if (find_edge (e->src, new_bb))
      return false;

which we can short-cut when new_bb has a single predecessor.

So I have some micro-optimizing things here (only).  But I wonder
whether walking the landing pads in some better order in cleanup_all_empty_eh
would fix things.  Simply walking the array in reverse already helps a
tremedous
amount!

 tree eh                            :   4.75 ( 35%)   0.01 (  3%)   4.75 ( 34%)
  16911 kB (  9%)

vs.

 tree eh                            : 182.21 ( 95%)   0.84 ( 65%) 183.07 ( 95%)
4653260 kB ( 97%)

on your testcase and 

 tree eh                            :  29.56 ( 30%)   0.05 (  1%)  29.60 ( 28%)
 246315 kB (  8%)

vs.

 tree eh                            : 626.00 ( 89%)   5.75 ( 45%) 631.88 (
88%)38736930 kB ( 93%)

on the redhat bugzilla one.

Reply via email to