This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: pretty-ipa merge 14: EH region label sharing code


On Fri, 24 Apr 2009, Jan Hubicka wrote:

> Hi,
> this is last EH redirection preparation bit.  It makes code happy about case
> where two regions share same label. This happens by EH redirection but also by
> cfgcleanup and such.
> 
> While this is generally easy to maintain linked list of regions sharing
> label, tricky part is eh cleanup where we now can have empty cleanup reached by
> multiple EH handlers and none of them must be same as the one resuming it.
> This is hanled by removing all the reaching EH handlers and replacing them by
> outer handler of the resuming one.
> 
> It is also possible that other control flow reaches the empty handler and in
> this case BB is no longer removed and resuming EH is kept in place. This
> happens sometimes when EH region proves to be empty over some paths only
> after edge splitting.
> 
> I also bundled in remove_eh_handler_and_replace change that allows removing
> try region without associated catch and also to update prev_try pointers.  This
> is really needed for EH merging, but it is bit difficult to split it out of
> the patch.
> 
> Bootstrapped/regtested x86_64-linux, OK?
> 	* tree-eh.c (tree_remove_unreachable_handlers): Handle shared labels.
> 	(tree_empty_eh_handler_p): Allow non-EH predecestors; allow region
> 	to be reached by different label than left.
> 	(update_eh_edges): Update comment; remove edge_to_remove if possible
> 	and return true if suceeded.
> 	(cleanup_empty_eh): Accept sharing map; handle shared regions.
> 	(cleanup_eh): Compute sharing map.
> 	* except.c (remove_eh_handler_and_replace): Add argument if we should
> 	update regions.
> 	(remove_unreachable_regions): Update for label sharing.
> 	(label_to_region_map): Likewise.
> 	(get_next_region_sharing_label): New function.
> 	(remove_eh_handler_and_replace): Add update_catch_try parameter; update
> 	prev_try pointers.
> 	(remove_eh_handler): Update.
> 	(remove_eh_region_and_replace_by_outer_of): New function.
> 	* except.h (struct eh_region): Add next_region_sharing_label.
> 	(remove_eh_region_and_replace_by_outer_of,
> 	get_next_region_sharing_label): Declare.
> 	* tree-cfgcleanup.c (tree_forwarder_block_p): Simplify.
> *** /aux/hubicka/trunk-write/gcc/tree-eh.c	Wed Apr  8 17:08:50 2009
> --- tree-eh.c	Fri Apr 24 13:56:55 2009
> *************** tree_remove_unreachable_handlers (void)
> *** 2695,2702 ****
>   	if (gimple_code (stmt) == GIMPLE_LABEL && has_eh_preds)
>   	  {
>   	    int uid = LABEL_DECL_UID (gimple_label_label (stmt));
> ! 	    int region = VEC_index (int, label_to_region, uid);
> ! 	    SET_BIT (reachable, region);
>   	  }
>   	if (gimple_code (stmt) == GIMPLE_RESX)
>   	  SET_BIT (reachable, gimple_resx_region (stmt));
> --- 2738,2748 ----
>   	if (gimple_code (stmt) == GIMPLE_LABEL && has_eh_preds)
>   	  {
>   	    int uid = LABEL_DECL_UID (gimple_label_label (stmt));
> ! 	    int region;
> ! 
> ! 	    for (region = VEC_index (int, label_to_region, uid);
> ! 		 region; region = get_next_region_sharing_label (region))
> ! 	      SET_BIT (reachable, region);
>   	  }
>   	if (gimple_code (stmt) == GIMPLE_RESX)
>   	  SET_BIT (reachable, gimple_resx_region (stmt));
> *************** tree_empty_eh_handler_p (basic_block bb)
> *** 2743,2750 ****
> --- 2789,2799 ----
>   {
>     gimple_stmt_iterator gsi;
>     int region;
> +   edge_iterator ei;
> +   edge e;
>     use_operand_p imm_use;
>     gimple use_stmt;
> +   bool found = false;
>   
>     gsi = gsi_last_bb (bb);
>   
> *************** tree_empty_eh_handler_p (basic_block bb)
> *** 2815,2829 ****
>         if (gsi_end_p (gsi))
>   	return 0;
>       }
> !   while (gimple_code (gsi_stmt (gsi)) == GIMPLE_LABEL)
> !     {
> !       if (gimple_label_label (gsi_stmt (gsi))
> !       	  == get_eh_region_no_tree_label (region))
> !         return region;
> !       gsi_prev (&gsi);
> !       if (gsi_end_p (gsi))
> ! 	return 0;
> !     }
>     return 0;
>   }
>   
> --- 2864,2880 ----
>         if (gsi_end_p (gsi))
>   	return 0;
>       }
> !   if (gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
> !     return 0;
> ! 
> !   /* Be sure that there is at least on EH region reaching the block directly.
> !      After EH edge redirection, it is possible that block is reached by one handler
> !      but resumed by different.  */
> !   FOR_EACH_EDGE (e, ei, bb->preds)
> !     if ((e->flags & EDGE_EH))
> !       found = true;
> !   if (found)
> !     return region;
>     return 0;
>   }
>   
> *************** make_eh_edge_and_update_phi (struct eh_r
> *** 2955,2963 ****
>   
>   /* Make EH edges corresponding to STMT while updating PHI nodes after removal
>      empty cleanup BB_TO_REMOVE joined to BB containing STMT
> !    by EDGE_TO_REMOVE.  */
>   
> ! static void
>   update_eh_edges (gimple stmt, basic_block bb_to_remove, edge edge_to_remove)
>   {
>     int region_nr;
> --- 3006,3017 ----
>   
>   /* Make EH edges corresponding to STMT while updating PHI nodes after removal
>      empty cleanup BB_TO_REMOVE joined to BB containing STMT
> !    by EDGE_TO_REMOVE.
>   
> !    Return if EDGE_TO_REMOVE was really removed.  It might stay reachable when
> !    not all EH regions are cleaned up.  */
> ! 
> ! static bool
>   update_eh_edges (gimple stmt, basic_block bb_to_remove, edge edge_to_remove)
>   {
>     int region_nr;
> *************** update_eh_edges (gimple stmt, basic_bloc
> *** 2967,2972 ****
> --- 3021,3027 ----
>     edge_iterator ei;
>     edge e;
>     int probability_sum = 0;
> +   bool removed = false;
>   
>     info.bb_to_remove = bb_to_remove;
>     info.bb = gimple_bb (stmt);
> *************** update_eh_edges (gimple stmt, basic_bloc
> *** 2980,2987 ****
>     else
>       {
>         region_nr = lookup_stmt_eh_region (stmt);
> -       if (region_nr < 0)
> - 	return;

This doesn't look correct.  foreach_reachable_handler will then index
with negative region_nr into the region array.

>         is_resx = false;
>         inlinable = inlinable_call_p (stmt);
>       }
> --- 3035,3040 ----
> *************** update_eh_edges (gimple stmt, basic_bloc
> *** 2993,3001 ****
>     /* And remove edges we didn't marked. */
>     for (ei = ei_start (info.bb->succs); (e = ei_safe_edge (ei)); )
>       {
> !       if ((e->flags & EDGE_EH) && !e->aux && e != edge_to_remove)
>   	{
>   	  dominance_info_invalidated = true;
>   	  remove_edge (e);
>   	}
>         else
> --- 3046,3056 ----
>     /* And remove edges we didn't marked. */
>     for (ei = ei_start (info.bb->succs); (e = ei_safe_edge (ei)); )
>       {
> !       if ((e->flags & EDGE_EH) && !e->aux)
>   	{
>   	  dominance_info_invalidated = true;
> + 	  if (e == edge_to_remove)
> + 	    removed = true;
>   	  remove_edge (e);
>   	}
>         else
> *************** update_eh_edges (gimple stmt, basic_bloc
> *** 3011,3026 ****
>        we get fewer consistency errors in the dumps.  */
>     if (is_resx && EDGE_COUNT (info.bb->succs) && !probability_sum)
>       EDGE_SUCC (info.bb, 0)->probability = REG_BR_PROB_BASE;
>   }
>
>   /* Look for basic blocks containing empty exception handler and remove them.
>      This is similar to jump forwarding, just across EH edges.  */
>   
>   static bool
> ! cleanup_empty_eh (basic_block bb)
>   {
>     int region;
>     gimple_stmt_iterator si;
>   
>     /* When handler of EH region winds up to be empty, we can safely
>        remove it.  This leads to inner EH regions to be redirected
> --- 3066,3083 ----
>        we get fewer consistency errors in the dumps.  */
>     if (is_resx && EDGE_COUNT (info.bb->succs) && !probability_sum)
>       EDGE_SUCC (info.bb, 0)->probability = REG_BR_PROB_BASE;
> +   return removed;
>   }
>   
>   /* Look for basic blocks containing empty exception handler and remove them.
>      This is similar to jump forwarding, just across EH edges.  */
>   
>   static bool
> ! cleanup_empty_eh (basic_block bb, VEC(int,heap) * label_to_region)
>   {
>     int region;
>     gimple_stmt_iterator si;
> +   edge_iterator ei;
>   
>     /* When handler of EH region winds up to be empty, we can safely
>        remove it.  This leads to inner EH regions to be redirected
> *************** cleanup_empty_eh (basic_block bb)
> *** 3030,3048 ****
>         && all_phis_safe_to_merge (bb))
>       {
>         edge e;
>   
> !       remove_eh_region (region);
>   
> !       while ((e = ei_safe_edge (ei_start (bb->preds))))
>   	{
>   	  basic_block src = e->src;
> ! 	  gcc_assert (e->flags & EDGE_EH);
>   	  if (stmt_can_throw_internal (last_stmt (src)))
> ! 	    update_eh_edges (last_stmt (src), bb, e);
> ! 	  remove_edge (e);
>   	}
> -       if (dump_file)
> - 	fprintf (dump_file, "Empty EH handler %i removed\n", region);
>   
>         /* Verify that we eliminated all uses of PHI we are going to remove.
>            If we didn't, rebuild SSA on affected variable (this is allowed only
> --- 3087,3153 ----
>         && all_phis_safe_to_merge (bb))
>       {
>         edge e;
> +       bool found = false, removed_some = false, has_non_eh_preds = false;
> +       gimple_stmt_iterator gsi;
>

Please add a comment what the following loop(s) want to do.  EH code
is hard to follow anyway.
   
> !       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
> !         if (gimple_code (gsi_stmt (gsi)) == GIMPLE_LABEL)
> ! 	  {
> ! 	    int uid = LABEL_DECL_UID (gimple_label_label (gsi_stmt (gsi)));
> ! 	    int r = VEC_index (int, label_to_region, uid);
> ! 	    int next;
>   
> ! 	    while (r)
> ! 	      {
> ! 		next = get_next_region_sharing_label (r);
> ! 		if (r == region)
> ! 		  found = true;
> ! 		else
> ! 		  {
> ! 		     removed_some = true;
> ! 		     remove_eh_region_and_replace_by_outer_of (r, region);
> ! 		     if (dump_file)

&& (dump_flags & TDF_details)

> ! 		       fprintf (dump_file, "Empty EH handler %i removed and "
> ! 		       		"replaced by %i\n", r, region);
> ! 		  }
> ! 		r = next;
> ! 	      }
> ! 	  }
> ! 	else
> ! 	  break;

Add vertical space here.

> !       gcc_assert (found || removed_some);
> !       FOR_EACH_EDGE (e, ei, bb->preds)
> ! 	if (!(e->flags & EDGE_EH))
> ! 	  has_non_eh_preds = true;
> ! 
> !       /* When block is empty EH cleanup, but it is reachable via non-EH code too,
> ! 	 we can not remove the region it is resumed via, because doing so will
> ! 	 lead to redirection of its RESX edges.
> ! 
> ! 	 This case will be handled later after edge forwarding if the EH cleanup
> ! 	 is really dead.  */
> ! 
> !       if (found && !has_non_eh_preds)
> !         remove_eh_region (region);
> !       else if (!removed_some)
> !         return false;
> ! 
> !       for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei)); )
>   	{
>   	  basic_block src = e->src;
> ! 	  if (!(e->flags & EDGE_EH))
> ! 	    {
> ! 	      ei_next (&ei);
> ! 	      continue;
> ! 	    }
>   	  if (stmt_can_throw_internal (last_stmt (src)))
> ! 	    {
> ! 	      if (!update_eh_edges (last_stmt (src), bb, e))
> ! 	        ei_next (&ei);
> ! 	    }
> ! 	  else
> ! 	    remove_edge (e);
>   	}
>   
>         /* Verify that we eliminated all uses of PHI we are going to remove.
>            If we didn't, rebuild SSA on affected variable (this is allowed only
> *************** cleanup_empty_eh (basic_block bb)
> *** 3091,3097 ****
>   		}
>   	    }
>   	}
> !       delete_basic_block (bb);
>         return true;
>       }
>     return false;
> --- 3196,3203 ----
>   		}
>   	    }
>   	}
> !       if (!ei_safe_edge (ei_start (bb->preds)))
> !         delete_basic_block (bb);
>         return true;
>       }
>     return false;
> *************** cleanup_eh (void)
> *** 3111,3116 ****
> --- 3217,3223 ----
>   {
>     bool changed = false;
>     basic_block bb;
> +   VEC(int,heap) * label_to_region;
>     int i;
>   
>     if (!cfun->eh)
> *************** cleanup_eh (void)
> *** 3123,3136 ****
>   
>     if (optimize)
>       {
>         dominance_info_invalidated = false;
>         /* We cannot use FOR_EACH_BB, since the basic blocks may get removed.  */
>         for (i = NUM_FIXED_BLOCKS; i < last_basic_block; i++)
>   	{
>   	  bb = BASIC_BLOCK (i);
>   	  if (bb)
> ! 	    changed |= cleanup_empty_eh (bb);
>   	}
>         if (dominance_info_invalidated)
>   	{
>   	  free_dominance_info (CDI_DOMINATORS);
> --- 3230,3245 ----
>   
>     if (optimize)
>       {
> +       label_to_region = label_to_region_map ();
>         dominance_info_invalidated = false;
>         /* We cannot use FOR_EACH_BB, since the basic blocks may get removed.  */
>         for (i = NUM_FIXED_BLOCKS; i < last_basic_block; i++)
>   	{
>   	  bb = BASIC_BLOCK (i);
>   	  if (bb)
> ! 	    changed |= cleanup_empty_eh (bb, label_to_region);
>   	}
> +       VEC_free (int, heap, label_to_region);
>         if (dominance_info_invalidated)
>   	{
>   	  free_dominance_info (CDI_DOMINATORS);
> *** /aux/hubicka/trunk-write/gcc/except.c	Wed Apr 22 15:38:18 2009
> --- except.c	Wed Apr 22 20:07:02 2009
> *************** static void sjlj_build_landing_pads (voi
> *** 146,152 ****
>   
>   static void remove_eh_handler (struct eh_region *);
>   static void remove_eh_handler_and_replace (struct eh_region *,
> ! 					   struct eh_region *);
>   
>   /* The return value of reachable_next_level.  */
>   enum reachable_code
> --- 147,153 ----
>   
>   static void remove_eh_handler (struct eh_region *);
>   static void remove_eh_handler_and_replace (struct eh_region *,
> ! 					   struct eh_region *, bool);
>   
>   /* The return value of reachable_next_level.  */
>   enum reachable_code
> *************** remove_unreachable_regions (sbitmap reac
> *** 743,754 ****
>   	    fprintf (dump_file, "Replacing MUST_NOT_THROW region %i by %i\n",
>   		     r->region_number,
>   		     first_must_not_throw->region_number);
> ! 	  remove_eh_handler_and_replace (r, first_must_not_throw);
>   	  first_must_not_throw->may_contain_throw |= r->may_contain_throw;
>   	}
>         else
>   	bring_to_root (r);
>       }
>   #ifdef ENABLE_CHECKING
>     verify_eh_tree (cfun);
>   #endif
> --- 979,990 ----
>   	    fprintf (dump_file, "Replacing MUST_NOT_THROW region %i by %i\n",
>   		     r->region_number,
>   		     first_must_not_throw->region_number);
> ! 	  remove_eh_handler_and_replace (r, first_must_not_throw, false);
>   	  first_must_not_throw->may_contain_throw |= r->may_contain_throw;
>   	}
>         else
>   	bring_to_root (r);
>       }
>   #ifdef ENABLE_CHECKING
>     verify_eh_tree (cfun);
>   #endif
> *************** remove_unreachable_regions (sbitmap reac
> *** 758,768 ****
>   /* Return array mapping LABEL_DECL_UID to region such that region's tree_label
>      is identical to label.  */
>   
> ! VEC(int,heap) *
>   label_to_region_map (void)
>   {
> !   VEC(int,heap) * label_to_region = NULL;
>     int i;
>   
>     VEC_safe_grow_cleared (int, heap, label_to_region,
>   			 cfun->cfg->last_label_uid + 1);
> --- 995,1006 ----
>   /* Return array mapping LABEL_DECL_UID to region such that region's tree_label
>      is identical to label.  */
>   
> ! VEC (int, heap) *
>   label_to_region_map (void)
>   {
> !   VEC (int, heap) * label_to_region = NULL;
>     int i;
> +   int idx;
>   
>     VEC_safe_grow_cleared (int, heap, label_to_region,
>   			 cfun->cfg->last_label_uid + 1);
> *************** label_to_region_map (void)
> *** 770,777 ****
>       {
>         struct eh_region *r = VEC_index (eh_region, cfun->eh->region_array, i);
>         if (r && r->region_number == i
> !       	  && r->tree_label && LABEL_DECL_UID (r->tree_label) >= 0)
>   	{
>   	  VEC_replace (int, label_to_region, LABEL_DECL_UID (r->tree_label),
>   		       i);
>   	}
> --- 1008,1021 ----
>       {
>         struct eh_region *r = VEC_index (eh_region, cfun->eh->region_array, i);
>         if (r && r->region_number == i
> ! 	  && r->tree_label && LABEL_DECL_UID (r->tree_label) >= 0)
>   	{
> + 	  if ((idx = VEC_index (int, label_to_region,
> + 				LABEL_DECL_UID (r->tree_label))) != 0)
> + 	      r->next_region_sharing_label =
> + 	      VEC_index (eh_region, cfun->eh->region_array, idx);
> + 	  else
> + 	    r->next_region_sharing_label = NULL;
>   	  VEC_replace (int, label_to_region, LABEL_DECL_UID (r->tree_label),
>   		       i);
>   	}
> *************** num_eh_regions (void)
> *** 786,791 ****
> --- 1030,1049 ----
>     return cfun->eh->last_region_number + 1;
>   }
>   
> + /* Return next region sharing same label as REGION.  */
> + 
> + int
> + get_next_region_sharing_label (int region)
> + {
> +   struct eh_region *r;
> +   if (!region)
> +     return 0;
> +   r = VEC_index (eh_region, cfun->eh->region_array, region);
> +   if (!r || !r->next_region_sharing_label)
> +     return 0;
> +   return r->next_region_sharing_label->region_number;
> + }
> + 
>   /* Set up EH labels for RTL.  */
>   
>   void
> *************** finish_eh_generation (void)
> *** 2163,2178 ****
>   
>   /* This section handles removing dead code for flow.  */
>   
> ! /* Splice REGION from the region tree and replace it by REPLACE etc.  */
>   
>   static void
>   remove_eh_handler_and_replace (struct eh_region *region,
> ! 			       struct eh_region *replace)
>   {
>     struct eh_region **pp, **pp_start, *p, *outer, *inner;
>     rtx lab;
>   
>     outer = region->outer;
>     /* For the benefit of efficiently handling REG_EH_REGION notes,
>        replace this region in the region array with its containing
>        region.  Note that previous region deletions may result in
> --- 2718,2763 ----
>   
>   /* This section handles removing dead code for flow.  */
>   
> ! /* Splice REGION from the region tree and replace it by REPLACE etc.
> !    When UPDATE_CATCH_TRY is true mind updating links from catch to try
> !    region.*/
>   
>   static void
>   remove_eh_handler_and_replace (struct eh_region *region,
> ! 			       struct eh_region *replace,
> ! 			       bool update_catch_try)
>   {
>     struct eh_region **pp, **pp_start, *p, *outer, *inner;
>     rtx lab;
>   
>     outer = region->outer;
> + 
> +   /* When we are moving the region in EH tree, update prev_try pointers.  */
> +   if (outer != replace && region->inner)
> +     {
> +       struct eh_region *prev_try = find_prev_try (replace);
> +       p = region->inner;
> +       while (p != region)
> +         {
> + 	  if (p->type == ERT_CLEANUP)
> + 	    p->u.cleanup.prev_try = prev_try;
> +           if (p->type != ERT_TRY
> + 	      && p->type != ERT_MUST_NOT_THROW
> + 	      && (p->type != ERT_ALLOWED_EXCEPTIONS
> + 	          || p->u.allowed.type_list)
> + 	      && p->inner)
> + 	    p = p->inner;
> + 	  else if (p->next_peer)
> + 	    p = p->next_peer;
> + 	  else
> + 	    {
> + 	      while (p != region && !p->next_peer)
> + 	        p = p->outer;
> + 	      if (p != region)
> + 		p = p->next_peer;
> + 	    }
> + 	}
> +     }

Either the patch has or your mailer garbles whitespace here.  Please
make sure to have consistent TAB / space usage.

>     /* For the benefit of efficiently handling REG_EH_REGION notes,
>        replace this region in the region array with its containing
>        region.  Note that previous region deletions may result in
> *************** remove_eh_handler_and_replace (struct eh
> *** 2228,2234 ****
>         *pp_start = inner;
>       }
>   
> !   if (region->type == ERT_CATCH)
>       {
>         struct eh_region *eh_try, *next, *prev;
>   
> --- 2813,2820 ----
>         *pp_start = inner;
>       }
>   
> !   if (region->type == ERT_CATCH
> !       && update_catch_try)
>       {
>         struct eh_region *eh_try, *next, *prev;
>   
> *************** remove_eh_handler_and_replace (struct eh
> *** 2262,2268 ****
>   static void
>   remove_eh_handler (struct eh_region *region)
>   {
> !   remove_eh_handler_and_replace (region, region->outer);
>   }
>   
>   /* Remove Eh region R that has turned out to have no code in its handler.  */
> --- 2848,2854 ----
>   static void
>   remove_eh_handler (struct eh_region *region)
>   {
> !   remove_eh_handler_and_replace (region, region->outer, true);
>   }
>   
>   /* Remove Eh region R that has turned out to have no code in its handler.  */
> *************** remove_eh_region (int r)
> *** 2276,2281 ****
> --- 2862,2880 ----
>     remove_eh_handler (region);
>   }
>   
> + /* Remove Eh region R that has turned out to have no code in its handler
> +    and replace in by R2.  */
> + 
> + void
> + remove_eh_region_and_replace_by_outer_of (int r, int r2)
> + {
> +   struct eh_region *region, *region2;
> + 
> +   region = VEC_index (eh_region, cfun->eh->region_array, r);
> +   region2 = VEC_index (eh_region, cfun->eh->region_array, r2);
> +   remove_eh_handler_and_replace (region, region2->outer, true);
> + }
> + 
>   /* Invokes CALLBACK for every exception handler label.  Only used by old
>      loop hackery; should not be used by new code.  */
>   
> *** /aux/hubicka/trunk-write/gcc/except.h	Wed Apr 22 15:38:18 2009
> --- except.h	Sun Apr 19 19:53:37 2009
> *************** struct eh_region GTY(())
> *** 34,39 ****
> --- 34,42 ----
>     struct eh_region *inner;
>     struct eh_region *next_peer;
>   
> +   /* List of regions sharing label.  */
> +   struct eh_region *next_region_sharing_label;
> + 
>     /* An identifier for this region.  */
>     int region_number;
>   
> *************** extern bool can_throw_external (const_rt
> *** 151,161 ****
> --- 154,164 ----
>   /* Set TREE_NOTHROW and cfun->all_throwers_are_sibcalls.  */
>   extern unsigned int set_nothrow_function_flags (void);
>   
>   extern void init_eh (void);
>   extern void init_eh_for_function (void);
>   
>   extern rtx reachable_handlers (rtx);
>   void remove_eh_region (int);
> + void remove_eh_region_and_replace_by_outer_of (int, int);
>   
>   extern void convert_from_eh_region_ranges (void);
>   extern unsigned int convert_to_eh_region_ranges (void);
> *************** struct throw_stmt_node GTY(())
> *** 269,277 ****
> --- 277,286 ----
>     gimple stmt;
>     int region_nr;
>   };
>   
>   extern struct htab *get_eh_throw_stmt_table (struct function *);
>   extern void set_eh_throw_stmt_table (struct function *, struct htab *);
>   extern void remove_unreachable_regions (sbitmap, sbitmap);
>   extern VEC(int,heap) * label_to_region_map (void);
>   extern int num_eh_regions (void);
> + extern int get_next_region_sharing_label (int);
> *** /aux/hubicka/trunk-write/gcc/tree-cfgcleanup.c	Mon Feb 23 13:04:19 2009
> --- tree-cfgcleanup.c	Thu Apr  9 01:25:26 2009
> *************** static bool
> *** 221,229 ****
>   tree_forwarder_block_p (basic_block bb, bool phi_wanted)
>   {
>     gimple_stmt_iterator gsi;
> -   edge_iterator ei;
> -   edge e, succ;
> -   basic_block dest;
>   
>     /* BB must have a single outgoing edge.  */
>     if (single_succ_p (bb) != 1
> --- 221,226 ----
> *************** tree_forwarder_block_p (basic_block bb, 
> *** 274,296 ****
>         if (dest->loop_father->header == dest)
>   	return false;
>       }
> - 
> -   /* If we have an EH edge leaving this block, make sure that the
> -      destination of this block has only one predecessor.  This ensures
> -      that we don't get into the situation where we try to remove two
> -      forwarders that go to the same basic block but are handlers for
> -      different EH regions.  */
> -   succ = single_succ_edge (bb);
> -   dest = succ->dest;
> -   FOR_EACH_EDGE (e, ei, bb->preds)
> -     {
> -       if (e->flags & EDGE_EH)
> -         {
> - 	  if (!single_pred_p (dest))
> - 	    return false;
> - 	}
> -     }
> - 
>     return true;
>   }
>   
> --- 271,276 ----
> 
> 


The rest of the patch looks ok.  I am somewhat concerned that with all
the EH cleanup and optimizations you implemented we didn't get a single
testcase that verifies the code is working.

_Please_ consider adding some.

Thanks,
Richard.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]