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 16: EH redirection


Hi,
this is updated patch I am re-testing.
For now I left except.h/tree-flow.h split as it is and also didn't
remove tree-flow.h dependency of except.c. I am not sure adding extra
bits to redirect_eh_edge_to_label to handle label lists instead of
using gimple_block_label is going to help anything unless we really
want to do redirection on RTL land too.

Honza

	* tree.c (list_equal_p): New function.
	* tree.h (list_equal_p): Declare.
	* coretypes.h (edge_def, edge, const_edge, basic_block_def
	basic_block_def, basic_block, const_basic_block): New.
	* tree-eh.c (make_eh_edge): EH edges are not abnormal.
	(redirect_eh_edge): New function.
	(make_eh_edge_update_phi): EH edges are not abnormal.
	* except.c: Include tree-flow.h.
	(list_match): New function.
	(eh_region_replaceable_by_p): New function.
	(replace_region): New function.
	(hash_type_list): New function.
	(hash_eh_region): New function.
	(eh_regions_equal_p): New function.
	(merge_peers): New function.
	(remove_unreachable_regions): Verify EH tree when checking;
	merge peers.
	(copy_eh_region_1): New function.
	(copy_eh_region): New function.
	(push_reachable_handler): New function.
	(build_post_landing_pads, dw2_build_landing_pads): Be ready for
	regions without label but with live RESX.
	* except.h (redirect_eh_edge_to_label): New.
	* tree-flow.h (redirect_eh_edge): New.
	* coretypes.h (edge_def, edge, const_edge, basic_block_def
	basic_block_def, basic_block, const_basic_block): Remove.
	* Makefile.in (except.o): Add dependency on tree-flow.h
	* tree-cfg.c (gimple_redirect_edge_and_branch): Handle EH edges.
	* basic-block.h (edge, const_edge, basic_block, const_basic_block):
	Remove.
Index: tree.c
===================================================================
*** tree.c	(revision 146763)
--- tree.c	(working copy)
*************** block_ultimate_origin (const_tree block)
*** 9320,9323 ****
--- 9320,9335 ----
      }
  }
  
+ /* Return true if T1 and T2 are equivalent lists.  */
+ 
+ bool
+ list_equal_p (const_tree t1, const_tree t2)
+ {
+   for (; t1 && t2; t1 = TREE_CHAIN (t1) , t2 = TREE_CHAIN (t2))
+     if (TREE_VALUE (t1) != TREE_VALUE (t2))
+       return false;
+   return !t1 && !t2;
+ }
+ 
+ 
  #include "gt-tree.h"
Index: tree.h
===================================================================
*** tree.h	(revision 146763)
--- tree.h	(working copy)
*************** struct GTY(()) tree_map_base {
*** 5134,5139 ****
--- 5134,5140 ----
  extern int tree_map_base_eq (const void *, const void *);
  extern unsigned int tree_map_base_hash (const void *);
  extern int tree_map_base_marked_p (const void *);
+ extern bool list_equal_p (const_tree, const_tree);
  
  /* Map from a tree to another tree.  */
  
Index: tree-eh.c
===================================================================
*** tree-eh.c	(revision 146763)
--- tree-eh.c	(working copy)
*************** make_eh_edge (struct eh_region *region, 
*** 1962,1968 ****
    src = gimple_bb (stmt);
    dst = label_to_block (lab);
  
!   make_edge (src, dst, EDGE_ABNORMAL | EDGE_EH);
  }
  
  /* See if STMT is call that might be inlined.  */
--- 1962,1968 ----
    src = gimple_bb (stmt);
    dst = label_to_block (lab);
  
!   make_edge (src, dst, EDGE_EH);
  }
  
  /* See if STMT is call that might be inlined.  */
*************** make_eh_edges (gimple stmt)
*** 2019,2024 ****
--- 2019,2068 ----
      EDGE_SUCC (bb, 0)->probability = REG_BR_PROB_BASE;
  }
  
+ /* Redirect EH edge E to NEW_BB.  */
+ 
+ edge
+ redirect_eh_edge (edge e, basic_block new_bb)
+ {
+   gimple stmt = gsi_stmt (gsi_last_bb (e->src));
+   int region_nr, new_region_nr;
+   bool is_resx;
+   bool inlinable = false;
+   tree label = gimple_block_label (new_bb);
+   struct eh_region *r;
+ 
+   if (gimple_code (stmt) == GIMPLE_RESX)
+     {
+       region_nr = gimple_resx_region (stmt);
+       is_resx = true;
+     }
+   else
+     {
+       region_nr = lookup_stmt_eh_region (stmt);
+       gcc_assert (region_nr >= 0);
+       is_resx = false;
+       inlinable = inlinable_call_p (stmt);
+     }
+ 
+   if (dump_file && (dump_flags & TDF_DETAILS))
+     fprintf (dump_file, "Redirecting EH edge %i->%i to %i, region %i, resx %i\n",
+ 	     e->src->index, e->dest->index, new_bb->index, region_nr, is_resx);
+   r = redirect_eh_edge_to_label (e, label, is_resx, inlinable, region_nr);
+   new_region_nr = get_eh_region_number (r);
+   if (new_region_nr != region_nr)
+     {
+       if (is_resx)
+         gimple_resx_set_region (stmt, new_region_nr);
+       else
+         {
+ 	  remove_stmt_from_eh_region (stmt);
+ 	  add_stmt_to_eh_region (stmt, new_region_nr);
+         }
+     }
+   e = ssa_redirect_edge (e, new_bb);
+   return e;
+ }
+ 
  static bool mark_eh_edge_found_error;
  
  /* Mark edge make_eh_edge would create for given region by setting it aux
*************** make_eh_edge_and_update_phi (struct eh_r
*** 2937,2943 ****
      }
    dominance_info_invalidated = true;
    e2 = find_edge (info->bb_to_remove, dst);
!   e = make_edge (src, dst, EDGE_ABNORMAL | EDGE_EH);
    e->aux = e;
    gcc_assert (e2);
    for (si = gsi_start_phis (dst); !gsi_end_p (si); gsi_next (&si))
--- 2981,2987 ----
      }
    dominance_info_invalidated = true;
    e2 = find_edge (info->bb_to_remove, dst);
!   e = make_edge (src, dst, EDGE_EH);
    e->aux = e;
    gcc_assert (e2);
    for (si = gsi_start_phis (dst); !gsi_end_p (si); gsi_next (&si))
Index: coretypes.h
===================================================================
*** coretypes.h	(revision 146763)
--- coretypes.h	(working copy)
*************** enum tls_model {
*** 97,102 ****
--- 97,108 ----
    TLS_MODEL_LOCAL_EXEC
  };
  
+ struct edge_def;
+ typedef struct edge_def *edge;
+ typedef const struct edge_def *const_edge;
+ struct basic_block_def;
+ typedef struct basic_block_def *basic_block;
+ typedef const struct basic_block_def *const_basic_block;
  #else
  
  struct _dont_use_rtx_here_;
Index: except.c
===================================================================
*** except.c	(revision 146763)
--- except.c	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 77,82 ****
--- 77,83 ----
  #include "diagnostic.h"
  #include "tree-pass.h"
  #include "timevar.h"
+ #include "tree-flow.h"
  
  /* Provide defaults for stuff that may not be defined when using
     sjlj exceptions.  */
*************** bring_to_root (struct eh_region *r)
*** 628,633 ****
--- 629,866 ----
    cfun->eh->region_tree = r;
  }
  
+ /* Return true if region R2 can be replaced by R1.  */
+ 
+ static bool
+ eh_region_replaceable_by_p (const struct eh_region *r1,
+ 			    const struct eh_region *r2)
+ {
+   /* Regions are semantically same if they are of same type,
+      have same label and type.  */
+   if (r1->type != r2->type)
+     return false;
+   if (r1->tree_label != r2->tree_label)
+     return false;
+ 
+   /* Verify that also region type dependent data are the same.  */
+   switch (r1->type)
+     {
+       case ERT_MUST_NOT_THROW:
+       case ERT_CLEANUP:
+ 	break;
+       case ERT_TRY:
+ 	{
+ 	  struct eh_region *c1, *c2;
+ 	  for (c1 = r1->u.eh_try.eh_catch,
+ 	       c2 = r2->u.eh_try.eh_catch;
+ 	       c1 && c2;
+ 	       c1 = c1->u.eh_catch.next_catch,
+ 	       c2 = c2->u.eh_catch.next_catch)
+ 	    if (!eh_region_replaceable_by_p (c1, c2))
+ 	      return false;
+ 	  if (c1 || c2)
+ 	    return false;
+         }
+ 	break;
+       case ERT_CATCH:
+         if (!list_equal_p (r1->u.eh_catch.type_list, r2->u.eh_catch.type_list))
+ 	  return false;
+         if (!list_equal_p (r1->u.eh_catch.filter_list,
+ 			   r2->u.eh_catch.filter_list))
+ 	  return false;
+         break;
+       case ERT_ALLOWED_EXCEPTIONS:
+         if (!list_equal_p (r1->u.allowed.type_list, r2->u.allowed.type_list))
+ 	  return false;
+ 	if (r1->u.allowed.filter != r2->u.allowed.filter)
+ 	  return false;
+ 	break;
+       case ERT_THROW:
+ 	if (r1->u.eh_throw.type != r2->u.eh_throw.type)
+ 	  return false;
+ 	break;
+       default:
+         gcc_unreachable ();
+     }
+   if (dump_file && (dump_flags & TDF_DETAILS))
+     fprintf (dump_file, "Regions %i and %i match\n", r1->region_number,
+     						     r2->region_number);
+   return true;
+ }
+ 
+ /* Replace region R2 by R1.  */
+ 
+ static void
+ replace_region (struct eh_region *r1, struct eh_region *r2)
+ {
+   struct eh_region *next1 = r1->u.eh_try.eh_catch;
+   struct eh_region *next2 = r2->u.eh_try.eh_catch;
+   bool is_try = r1->type == ERT_TRY;
+ 
+   gcc_assert (r1->type != ERT_CATCH);
+   remove_eh_handler_and_replace (r2, r1, false);
+   if (is_try)
+     {
+       while (next1)
+ 	{
+ 	  r1 = next1;
+ 	  r2 = next2;
+ 	  gcc_assert (next1->type == ERT_CATCH);
+ 	  gcc_assert (next2->type == ERT_CATCH);
+ 	  next1 = next1->u.eh_catch.next_catch;
+ 	  next2 = next2->u.eh_catch.next_catch;
+ 	  remove_eh_handler_and_replace (r2, r1, false);
+ 	}
+     }
+ }
+ 
+ /* Return hash value of type list T.  */
+ 
+ static hashval_t
+ hash_type_list (tree t)
+ {
+   hashval_t val = 0;
+   for (; t; t = TREE_CHAIN (t))
+     val = iterative_hash_expr (TREE_VALUE (t), val);
+   return val;
+ }
+ 
+ /* Hash EH regions so semantically same regions get same hash value.  */
+ 
+ static hashval_t
+ hash_eh_region (const void *r)
+ {
+   const struct eh_region *region = (const struct eh_region *)r;
+   hashval_t val = region->type;
+ 
+   if (region->tree_label)
+     val = iterative_hash_hashval_t (LABEL_DECL_UID (region->tree_label), val);
+   switch (region->type)
+     {
+       case ERT_MUST_NOT_THROW:
+       case ERT_CLEANUP:
+ 	break;
+       case ERT_TRY:
+ 	{
+ 	  struct eh_region *c;
+ 	  for (c = region->u.eh_try.eh_catch;
+ 	       c; c = c->u.eh_catch.next_catch)
+ 	    val = iterative_hash_hashval_t (hash_eh_region (c), val);
+         }
+ 	break;
+       case ERT_CATCH:
+         val = iterative_hash_hashval_t (hash_type_list
+ 					  (region->u.eh_catch.type_list), val);
+         break;
+       case ERT_ALLOWED_EXCEPTIONS:
+         val = iterative_hash_hashval_t
+ 		(hash_type_list (region->u.allowed.type_list), val);
+         val = iterative_hash_hashval_t (region->u.allowed.filter, val);
+ 	break;
+       case ERT_THROW:
+         val |= iterative_hash_expr (region->u.eh_throw.type, val);
+ 	break;
+       default:
+         gcc_unreachable ();
+     }
+   return val;
+ }
+ 
+ /* Return true if regions R1 and R2 are equal.  */
+ 
+ static int
+ eh_regions_equal_p (const void *r1, const void *r2)
+ {
+   return eh_region_replaceable_by_p ((const struct eh_region *)r1,
+ 				     (const struct eh_region *)r2);
+ }
+ 
+ /* Walk all peers of REGION and try to merge those regions
+    that are semantically equivalent.  Look into subregions
+    recursively too.  */
+ 
+ static bool
+ merge_peers (struct eh_region *region)
+ {
+   struct eh_region *r1, *r2, *outer = NULL, *next;
+   bool merged = false;
+   int num_regions = 0;
+   if (region)
+     outer = region->outer;
+   else
+     return false;
+ 
+   /* First see if there is inner region equivalent to region
+      in question.  EH control flow is acyclic so we know we
+      can merge them.  */
+   if (outer)
+     for (r1 = region; r1; r1 = next)
+       {
+         next = r1->next_peer;
+ 	if (r1->type == ERT_CATCH)
+ 	  continue;
+         if (eh_region_replaceable_by_p (r1->outer, r1))
+ 	  {
+ 	    replace_region (r1->outer, r1);
+ 	    merged = true;
+ 	  }
+ 	else
+ 	  num_regions ++;
+       }
+ 
+   /* Get new first region and try to match the peers
+      for equivalence.  */
+   if (outer)
+     region = outer->inner;
+   else
+     region = cfun->eh->region_tree;
+ 
+   /* There are few regions to inspect:
+      N^2 loop matching each region with each region
+      will do the job well.  */
+   if (num_regions < 10)
+     {
+       for (r1 = region; r1; r1 = r1->next_peer)
+ 	{
+ 	  if (r1->type == ERT_CATCH)
+ 	    continue;
+ 	  for (r2 = r1->next_peer; r2; r2 = next)
+ 	    {
+ 	      next = r2->next_peer;
+ 	      if (eh_region_replaceable_by_p (r1, r2))
+ 		{
+ 		  replace_region (r1, r2);
+ 		  merged = true;
+ 		}
+ 	    }
+ 	}
+     }
+   /* Or use hashtable to avoid N^2 behaviour.  */
+   else
+     {
+       htab_t hash;
+       hash = htab_create (num_regions, hash_eh_region,
+ 			  eh_regions_equal_p, NULL);
+       for (r1 = region; r1; r1 = next)
+ 	{
+           void **slot;
+ 
+ 	  next = r1->next_peer;
+ 	  if (r1->type == ERT_CATCH)
+ 	    continue;
+ 	  slot = htab_find_slot (hash, r1, INSERT);
+ 	  if (!*slot)
+ 	    *slot = r1;
+ 	  else
+ 	    replace_region ((struct eh_region *)*slot, r1);
+ 	}
+       htab_delete (hash);
+     }
+   for (r1 = region; r1; r1 = r1->next_peer)
+     merged |= merge_peers (r1->inner);
+   return merged;
+ }
+ 
  /* Remove all regions whose labels are not reachable.
     REACHABLE is bitmap of all regions that are used by the function
     CONTAINS_STMT is bitmap of all regions that contains stmt (or NULL). */
*************** remove_unreachable_regions (sbitmap reac
*** 748,753 ****
--- 981,987 ----
        else
  	bring_to_root (r);
      }
+   merge_peers (cfun->eh->region_tree);
  #ifdef ENABLE_CHECKING
    verify_eh_tree (cfun);
  #endif
*************** duplicate_eh_regions (struct function *i
*** 1140,1145 ****
--- 1374,1611 ----
    return eh_offset;
  }
  
+ /* Return new copy of eh region OLD inside region NEW_OUTER.
+    Do not care about updating the tree otherwise.  */
+ 
+ static struct eh_region *
+ copy_eh_region_1 (struct eh_region *old, struct eh_region *new_outer)
+ {
+   struct eh_region *new_eh = gen_eh_region (old->type, new_outer);
+   new_eh->u = old->u;
+   new_eh->tree_label = old->tree_label;
+   new_eh->may_contain_throw = old->may_contain_throw;
+   VEC_safe_grow (eh_region, gc, cfun->eh->region_array,
+ 		 cfun->eh->last_region_number + 1);
+   VEC_replace (eh_region, cfun->eh->region_array, new_eh->region_number, new_eh);
+   if (dump_file && (dump_flags & TDF_DETAILS))
+     fprintf (dump_file, "Copying region %i to %i\n", old->region_number, new_eh->region_number);
+   return new_eh;
+ }
+ 
+ /* Return new copy of eh region OLD inside region NEW_OUTER.  
+   
+    Copy whole catch-try chain if neccesary and update cleanup region prev_try
+    pointers.
+ 
+    PREV_TRY_MAP points to outer TRY region if it was copied in trace already.  */
+ 
+ static struct eh_region *
+ copy_eh_region (struct eh_region *old, struct eh_region *new_outer,
+ 		struct eh_region *prev_try_map)
+ {
+   struct eh_region *r, *n, *old_try, *new_try, *ret = NULL;
+   VEC(eh_region,heap) *catch_list = NULL;
+ 
+   if (old->type != ERT_CATCH)
+     {
+       gcc_assert (old->type != ERT_TRY);
+       r = copy_eh_region_1 (old, new_outer);
+       if (r->type == ERT_CLEANUP && prev_try_map)
+         {
+ 	  gcc_assert (r->u.cleanup.prev_try);
+           r->u.cleanup.prev_try = prev_try_map;
+ 	}
+       return r;
+     }
+ 
+   /* Locate and copy corresponding TRY.  */
+   for (old_try = old->next_peer; old_try->type == ERT_CATCH; old_try = old_try->next_peer)
+     continue;
+   gcc_assert (old_try->type == ERT_TRY);
+   new_try = gen_eh_region_try (new_outer);
+   new_try->tree_label = old_try->tree_label;
+   new_try->may_contain_throw = old_try->may_contain_throw;
+   if (dump_file && (dump_flags & TDF_DETAILS))
+     fprintf (dump_file, "Copying try-catch regions. Try: %i to %i\n",
+     	     old_try->region_number, new_try->region_number);
+   VEC_safe_grow (eh_region, gc, cfun->eh->region_array,
+ 		 cfun->eh->last_region_number + 1);
+   VEC_replace (eh_region, cfun->eh->region_array, new_try->region_number, new_try);
+ 
+   /* In order to keep CATCH list in order, we need to copy in reverse order.  */
+   for (r = old_try->u.eh_try.last_catch; r->type == ERT_CATCH; r = r->next_peer)
+     VEC_safe_push (eh_region, heap, catch_list, r);
+ 
+   while (VEC_length (eh_region, catch_list))
+     {
+       r = VEC_pop (eh_region, catch_list);
+ 
+       /* Duplicate CATCH.  */
+       n = gen_eh_region_catch (new_try, r->u.eh_catch.type_list);
+       n->tree_label = r->tree_label;
+       n->may_contain_throw = r->may_contain_throw;
+       VEC_safe_grow (eh_region, gc, cfun->eh->region_array,
+ 		     cfun->eh->last_region_number + 1);
+       VEC_replace (eh_region, cfun->eh->region_array, n->region_number, n);
+       n->tree_label = r->tree_label;
+ 
+       if (dump_file && (dump_flags & TDF_DETAILS))
+         fprintf (dump_file, "Copying try-catch regions. Catch: %i to %i\n",
+ 	         r->region_number, n->region_number);
+       if (r == old)
+ 	ret = n;
+     }
+   VEC_free (eh_region, heap, catch_list);
+   gcc_assert (ret);
+   return ret;
+ }
+ 
+ /* Callback for forach_reachable_handler that push REGION into single VECtor DATA.  */
+ 
+ static void
+ push_reachable_handler (struct eh_region *region, void *data)
+ {
+   VEC(eh_region,heap) **trace = (VEC(eh_region,heap) **) data;
+   VEC_safe_push (eh_region, heap, *trace, region);
+ }
+ 
+ /* Redirect EH edge E that to NEW_DEST_LABEL.
+    IS_RESX, INLINABLE_CALL and REGION_NMUBER match the parameter of
+    foreach_reachable_handler.  */
+ 
+ struct eh_region *
+ redirect_eh_edge_to_label (edge e, tree new_dest_label, bool is_resx,
+ 			   bool inlinable_call, int region_number)
+ {
+   struct eh_region *outer, *prev_try_map = NULL;
+   struct eh_region *region;
+   VEC (eh_region, heap) * trace = NULL;
+   int i;
+   int start_here = -1;
+   basic_block old_bb = e->dest;
+   struct eh_region *old, *r = NULL;
+   bool update_inplace = true;
+   edge_iterator ei;
+   edge e2;
+ 
+   /* If there is only one EH edge, we don't need to duplicate;
+      just update labels in the tree.  */
+   FOR_EACH_EDGE (e2, ei, old_bb->preds)
+     if ((e2->flags & EDGE_EH) && e2 != e)
+       {
+         update_inplace = false;
+         break;
+       }
+ 
+   region = VEC_index (eh_region, cfun->eh->region_array, region_number);
+   gcc_assert (region);
+ 
+   foreach_reachable_handler (region_number, is_resx, inlinable_call,
+ 			     push_reachable_handler, &trace);
+   if (dump_file && (dump_flags & TDF_DETAILS))
+     {
+       dump_eh_tree (dump_file, cfun);
+       fprintf (dump_file, "Trace: ");
+       for (i = 0; i < (int) VEC_length (eh_region, trace); i++)
+ 	fprintf (dump_file, " %i", VEC_index (eh_region, trace, i)->region_number);
+       fprintf (dump_file, " inplace: %i\n", update_inplace);
+     }
+ 
+   if (update_inplace)
+     {
+       /* In easy route just walk trace and update all occurences of the label.  */
+       for (i = 0; i < (int) VEC_length (eh_region, trace); i++)
+ 	{
+ 	  r = VEC_index (eh_region, trace, i);
+ 	  if (r->tree_label && label_to_block (r->tree_label) == old_bb)
+ 	    {
+ 	      r->tree_label = new_dest_label;
+ 	      if (dump_file && (dump_flags & TDF_DETAILS))
+ 		fprintf (dump_file, "Updating label for region %i\n",
+ 			 r->region_number);
+ 	    }
+ 	}
+       r = region;
+     }
+   else
+     {
+       /* Now look for outermost handler that reffers to the basic block in question.
+          We start our duplication there.  */
+       for (i = 0; i < (int) VEC_length (eh_region, trace); i++)
+ 	{
+ 	  r = VEC_index (eh_region, trace, i);
+ 	  if (r->tree_label && label_to_block (r->tree_label) == old_bb)
+ 	    start_here = i;
+ 	}
+       outer = VEC_index (eh_region, trace, start_here)->outer;
+       gcc_assert (start_here >= 0);
+ 
+       /* And now do the dirty job!  */
+       for (i = start_here; i >= 0; i--)
+ 	{
+ 	  old = VEC_index (eh_region, trace, i);
+ 	  gcc_assert (!outer || old->outer != outer->outer);
+ 
+ 	  /* Copy region and update label.  */
+ 	  r = copy_eh_region (old, outer, prev_try_map);
+ 	  VEC_replace (eh_region, trace, i, r);
+ 	  if (r->tree_label && label_to_block (r->tree_label) == old_bb)
+ 	    {
+ 	      r->tree_label = new_dest_label;
+ 	      if (dump_file && (dump_flags & TDF_DETAILS))
+ 		fprintf (dump_file, "Updating label for region %i\n",
+ 			 r->region_number);
+ 	    }
+ 
+ 	  /* We got into copying CATCH.  copy_eh_region already did job
+ 	     of copying all catch blocks corresponding to the try.  Now
+ 	     we need to update labels in all of them and see trace.
+ 
+ 	     We continue nesting into TRY region corresponding to CATCH:
+ 	     When duplicating EH tree contaiing subregions of CATCH,
+ 	     the CATCH region itself is never inserted to trace so we
+ 	     never get here anyway.  */
+ 	  if (r->type == ERT_CATCH)
+ 	    {
+ 	      /* Walk other catch regions we copied and update labels as needed.  */
+ 	      for (r = r->next_peer; r->type == ERT_CATCH; r = r->next_peer)
+ 		if (r->tree_label && label_to_block (r->tree_label) == old_bb)
+ 		  {
+ 		    r->tree_label = new_dest_label;
+ 		    if (dump_file && (dump_flags & TDF_DETAILS))
+ 		      fprintf (dump_file, "Updating label for region %i\n",
+ 			       r->region_number);
+ 		  }
+ 	       gcc_assert (r->type == ERT_TRY);
+ 
+ 	       /* Skip sibling catch regions from the trace.
+ 		  They are already updated.  */
+ 	       while (i > 0 && VEC_index (eh_region, trace, i - 1)->outer == old->outer)
+ 		 {
+ 		   gcc_assert (VEC_index (eh_region, trace, i - 1)->type == ERT_CATCH);
+ 		   i--;
+ 		 }
+ 	     }
+ 
+ 	  /* Cleanup regions points to outer TRY blocks.  */
+ 	  if (r->type == ERT_TRY)
+ 	    prev_try_map = r;
+ 	  outer = r;
+ 	}
+         
+       if (is_resx || region->type == ERT_THROW)
+ 	r = copy_eh_region (region, outer, prev_try_map);
+     }
+ 
+   VEC_free (eh_region, heap, trace);
+   if (dump_file && (dump_flags & TDF_DETAILS))
+     {
+       dump_eh_tree (dump_file, cfun);
+       fprintf (dump_file, "New region: %i\n", r->region_number);
+     }
+   return r;
+ }
+ 
  /* Return region number of region that is outer to both if REGION_A and
     REGION_B in IFUN.  */
  
*************** build_post_landing_pads (void)
*** 1478,1483 ****
--- 1944,1955 ----
        switch (region->type)
  	{
  	case ERT_TRY:
+ 	  /* It is possible that TRY region is kept alive only because some of
+ 	     contained catch region still have RESX instruction but they are
+ 	     reached via their copies.  In this case we need to do nothing.  */
+ 	  if (!region->u.eh_try.eh_catch->label)
+ 	    break;
+ 
  	  /* ??? Collect the set of all non-overlapping catch handlers
  	       all the way up the chain until blocked by a cleanup.  */
  	  /* ??? Outer try regions can share landing pads with inner
*************** build_post_landing_pads (void)
*** 1537,1542 ****
--- 2009,2016 ----
  	  break;
  
  	case ERT_ALLOWED_EXCEPTIONS:
+ 	  if (!region->label)
+ 	    break;
  	  region->post_landing_pad = gen_label_rtx ();
  
  	  start_sequence ();
*************** dw2_build_landing_pads (void)
*** 1679,1684 ****
--- 2153,2161 ----
  	  && region->type != ERT_ALLOWED_EXCEPTIONS)
  	continue;
  
+       if (!region->post_landing_pad)
+ 	continue;
+ 
        start_sequence ();
  
        region->landing_pad = gen_label_rtx ();
Index: except.h
===================================================================
*** except.h	(revision 146763)
--- except.h	(working copy)
*************** extern void set_eh_throw_stmt_table (str
*** 278,281 ****
--- 278,282 ----
  extern void remove_unreachable_regions (sbitmap, sbitmap);
  extern VEC(int,heap) * label_to_region_map (void);
  extern int num_eh_regions (void);
+ extern struct eh_region *redirect_eh_edge_to_label (struct edge_def *, tree, bool, bool, int);
  extern int get_next_region_sharing_label (int);
Index: tree-flow.h
===================================================================
*** tree-flow.h	(revision 146763)
--- tree-flow.h	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 32,44 ****
  #include "ipa-reference.h"
  #include "tree-ssa-alias.h"
  
- /* Forward declare structures for the garbage collector GTY markers.  */
- #ifndef GCC_BASIC_BLOCK_H
- struct edge_def;
- typedef struct edge_def *edge;
- struct basic_block_def;
- typedef struct basic_block_def *basic_block;
- #endif
  struct static_var_ann_d;
  
  
--- 32,37 ----
*************** unsigned int execute_fixup_cfg (void);
*** 974,978 ****
--- 967,972 ----
  void swap_tree_operands (gimple, tree *, tree *);
  
  int least_common_multiple (int, int);
+ edge redirect_eh_edge (edge e, basic_block new_bb);
  
  #endif /* _TREE_FLOW_H  */
Index: Makefile.in
===================================================================
*** Makefile.in	(revision 146763)
--- Makefile.in	(working copy)
*************** except.o : except.c $(CONFIG_H) $(SYSTEM
*** 2525,2531 ****
     langhooks.h insn-config.h hard-reg-set.h $(BASIC_BLOCK_H) output.h \
     dwarf2asm.h dwarf2out.h $(TOPLEV_H) $(HASHTAB_H) intl.h $(GGC_H) \
     gt-$(EXCEPT_H) $(CGRAPH_H) $(INTEGRATE_H) $(DIAGNOSTIC_H) dwarf2.h \
!    $(TARGET_H) $(TM_P_H) $(TREE_PASS_H) $(TIMEVAR_H)
  expr.o : expr.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
     $(TREE_H) $(FLAGS_H) $(FUNCTION_H) $(REGS_H) $(EXPR_H) $(OPTABS_H) \
     libfuncs.h $(INSN_ATTR_H) insn-config.h $(RECOG_H) output.h \
--- 2525,2531 ----
     langhooks.h insn-config.h hard-reg-set.h $(BASIC_BLOCK_H) output.h \
     dwarf2asm.h dwarf2out.h $(TOPLEV_H) $(HASHTAB_H) intl.h $(GGC_H) \
     gt-$(EXCEPT_H) $(CGRAPH_H) $(INTEGRATE_H) $(DIAGNOSTIC_H) dwarf2.h \
!    $(TARGET_H) $(TM_P_H) $(TREE_PASS_H) $(TIMEVAR_H) $(TREE_FLOW_H)
  expr.o : expr.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
     $(TREE_H) $(FLAGS_H) $(FUNCTION_H) $(REGS_H) $(EXPR_H) $(OPTABS_H) \
     libfuncs.h $(INSN_ATTR_H) insn-config.h $(RECOG_H) output.h \
Index: basic-block.h
===================================================================
*** basic-block.h	(revision 146763)
--- basic-block.h	(working copy)
*************** struct GTY(()) edge_def {
*** 147,154 ****
  				   in profile.c  */
  };
  
- typedef struct edge_def *edge;
- typedef const struct edge_def *const_edge;
  DEF_VEC_P(edge);
  DEF_VEC_ALLOC_P(edge,gc);
  DEF_VEC_ALLOC_P(edge,heap);
--- 147,152 ----
*************** struct GTY(()) gimple_bb_info {
*** 277,285 ****
    gimple_seq phi_nodes;
  };
  
- typedef struct basic_block_def *basic_block;
- typedef const struct basic_block_def *const_basic_block;
- 
  DEF_VEC_P(basic_block);
  DEF_VEC_ALLOC_P(basic_block,gc);
  DEF_VEC_ALLOC_P(basic_block,heap);
--- 275,280 ----
Index: tree-cfg.c
===================================================================
*** tree-cfg.c	(revision 146763)
--- tree-cfg.c	(working copy)
*************** gimple_redirect_edge_and_branch (edge e,
*** 4800,4805 ****
--- 4800,4808 ----
    if (e->dest == dest)
      return NULL;
  
+   if (e->flags & EDGE_EH)
+     return redirect_eh_edge (e, dest);
+ 
    gsi = gsi_last_bb (bb);
    stmt = gsi_end_p (gsi) ? NULL : gsi_stmt (gsi);
  


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