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]

EH duplication infrastructure


Hi,
this patch adds the EH duplication machinery needed for CFG inliner.  The
duplicate_eh* stuff is mostly copied from old RTL inliner with the exception of
changing duplicate_eh_region_1 to do struct copy as requested by Richard.

Since the previous patch I made some (hopefully noticeable) cleanups: the
mapping from old to new regions is not done by offset returned by the
duplicate_eh_regions so we don't need to export last EH region number from the
function.  I also got rid of dubuios duplicate_eh_for_stmt function and simply
re-add it by the usual channels.  This needs to teach add_stmt_to_eh_region_fn
how to initialize the hashtable.

Last change needed is to teach label_to_block_fn about labels never inserted
into instruction stream (it already knows how to return NULL for labels
inserted but later removed again).   This happens for the duplicated EH regions
that are no longer reachable and thus their landing pads has been removed.  It
would be probably cleaner to teach remove_bb to kill dead EH regions like we do
on RTL, but this seems to need extra care so I would preffer to do this
incrementally.

Bootstrapped/regtested i686-pc-gnu-linux, OK?
Honza
2005-05-12  Steven Bosscher  <stevenb@suse.de>
	    Stuart Hastings <stuart@apple.com>
	    Jan Hubicka  <jh@suse.cz>
	    
	* except.c  (duplicate_eh_region_1, duplicate_eh_region_2,
	duplicate_eh_regions): New functions, based on old
	implementation removed with RTL inliner.
	(reachable_next_level): Modify behaviour pre-inline.
	* except.h (duplicate_eh_regions_map, duplicate_eh_regions):
	Declare.
	* function.h (struct function): Add after_inlining flag.
	* tree-optimize.c (tree_rest_of_compilation): Set it.
	* tree-eh.c (add_stmt_to_eh_region_fn): Initialize hashtable
	when needed.
	* tree-cfg.c (label_to_block_fn): Deal with cases where
	label was never insterted into code.

Index: except.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/except.c,v
retrieving revision 1.305
diff -c -3 -p -r1.305 except.c
*** except.c	11 May 2005 16:25:27 -0000	1.305
--- except.c	11 May 2005 22:44:11 -0000
*************** current_function_has_exception_handlers 
*** 853,858 ****
--- 853,1001 ----
    return false;
  }
  
+ static struct eh_region *
+ duplicate_eh_region_1 (struct eh_region *o)
+ {
+   struct eh_region *n = ggc_alloc_cleared (sizeof (struct eh_region));
+ 
+   *n = *o;
+   
+   n->region_number = o->region_number + cfun->eh->last_region_number;
+   n->type = o->type;
+   gcc_assert (!o->aka);
+   
+   return n;
+ }
+ 
+ static void
+ duplicate_eh_region_2 (struct eh_region *o, struct eh_region **n_array,
+ 		       struct eh_region *prev_try)
+ {
+   struct eh_region *n = n_array[o->region_number];
+   
+   switch (n->type)
+     {
+     case ERT_TRY:
+       if (o->u.try.catch)
+         n->u.try.catch = n_array[o->u.try.catch->region_number];
+       if (o->u.try.last_catch)
+         n->u.try.last_catch = n_array[o->u.try.last_catch->region_number];
+       break;
+       
+     case ERT_CATCH:
+       if (o->u.catch.next_catch)
+ 	n->u.catch.next_catch = n_array[o->u.catch.next_catch->region_number];
+       if (o->u.catch.prev_catch)
+ 	n->u.catch.prev_catch = n_array[o->u.catch.prev_catch->region_number];
+       break;
+ 
+     case ERT_CLEANUP:
+       if (o->u.cleanup.prev_try)
+ 	n->u.cleanup.prev_try = n_array[o->u.cleanup.prev_try->region_number];
+       else
+         n->u.cleanup.prev_try = prev_try;
+       break;
+       
+     default:
+       break;
+     }
+   
+   if (o->outer)
+     n->outer = n_array[o->outer->region_number];
+   if (o->inner)
+     n->inner = n_array[o->inner->region_number];
+   if (o->next_peer)
+     n->next_peer = n_array[o->next_peer->region_number];
+ }
+ 
+ /* Duplicate the EH regions of IFUN into current function, root the tree in
+    OUTER_REGION and remap labels using MAP callback.  */
+ int
+ duplicate_eh_regions (struct function *ifun, duplicate_eh_regions_map map,
+ 		      void *data, int outer_region)
+ {
+   int ifun_last_region_number = ifun->eh->last_region_number;
+   struct eh_region **n_array, *root, *cur, *prev_try;
+   int i;
+   
+   if (ifun_last_region_number == 0 || !ifun->eh->region_tree)
+     return 0;
+   
+   n_array = xcalloc (ifun_last_region_number + 1, sizeof (*n_array));
+   
+   /* Search for the containing ERT_TRY region to fix up
+      the prev_try short-cuts for ERT_CLEANUP regions.  */
+   prev_try = NULL;
+   if (outer_region > 0)
+     for (prev_try = cfun->eh->region_array[outer_region];
+          prev_try && prev_try->type != ERT_TRY;
+ 	 prev_try = prev_try->outer)
+       ;
+ 
+   for (i = 1; i <= ifun_last_region_number; ++i)
+     {
+       cur = ifun->eh->region_array[i];
+       if (!cur || cur->region_number != i)
+ 	continue;
+       n_array[i] = duplicate_eh_region_1 (cur);
+       if (cur->tree_label)
+ 	{
+ 	  tree newlabel = map (cur->tree_label, data);
+ 	  n_array[i]->tree_label = newlabel;
+ 	}
+       else
+ 	n_array[i]->tree_label = NULL;
+     }
+   for (i = 1; i <= ifun_last_region_number; ++i)
+     {
+       cur = ifun->eh->region_array[i];
+       if (!cur || cur->region_number != i)
+ 	continue;
+       duplicate_eh_region_2 (cur, n_array, prev_try);
+     }
+   
+   root = n_array[ifun->eh->region_tree->region_number];
+   gcc_assert (root->outer == NULL);
+   if (outer_region > 0)
+     {
+       struct eh_region *cur = cfun->eh->region_array[outer_region];
+       struct eh_region *p = cur->inner;
+ 
+       if (p)
+ 	{
+ 	  while (p->next_peer)
+ 	    p = p->next_peer;
+ 	  p->next_peer = root;
+ 	}
+       else
+         cur->inner = root;
+       for (i = 1; i <= ifun_last_region_number; ++i)
+ 	if (n_array[i] && n_array[i]->outer == NULL)
+ 	  n_array[i]->outer = cur;
+     }
+   else
+     {
+       struct eh_region *p = cfun->eh->region_tree;
+       if (p)
+ 	{
+ 	  while (p->next_peer)
+ 	    p = p->next_peer;
+ 	  p->next_peer = root;
+ 	}
+       else
+         cfun->eh->region_tree = root;
+     }
+   
+   free (n_array);
+   
+   i = cfun->eh->last_region_number;
+   cfun->eh->last_region_number = i + ifun_last_region_number;
+   
+   collect_eh_region_array ();
+   
+   return i;
+ }
+ 
  static int
  t2r_eq (const void *pentry, const void *pdata)
  {
*************** reachable_next_level (struct eh_region *
*** 2273,2280 ****
        /* Here we end our search, since no exceptions may propagate.
  	 If we've touched down at some landing pad previous, then the
  	 explicit function call we generated may be used.  Otherwise
! 	 the call is made by the runtime.  */
!       if (info && info->saw_any_handlers)
  	{
  	  add_reachable_handler (info, region, region);
  	  return RNL_CAUGHT;
--- 2416,2428 ----
        /* Here we end our search, since no exceptions may propagate.
  	 If we've touched down at some landing pad previous, then the
  	 explicit function call we generated may be used.  Otherwise
! 	 the call is made by the runtime. 
! 
!          Before inlining, do not perform this optimization.  We may
! 	 inline a subroutine that contains handlers, and that will
! 	 change the value of saw_any_handlers.  */
! 
!       if ((info && info->saw_any_handlers) || !cfun->after_inlining)
  	{
  	  add_reachable_handler (info, region, region);
  	  return RNL_CAUGHT;
Index: except.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/except.h,v
retrieving revision 1.84
diff -c -3 -p -r1.84 except.h
*** except.h	11 May 2005 16:25:28 -0000	1.84
--- except.h	11 May 2005 22:44:11 -0000
*************** extern void expand_eh_return (void);
*** 81,86 ****
--- 81,88 ----
  extern rtx expand_builtin_extend_pointer (tree);
  extern rtx get_exception_pointer (struct function *);
  extern rtx get_exception_filter (struct function *);
+ typedef tree (*duplicate_eh_regions_map) (tree, void *);
+ extern int duplicate_eh_regions (struct function *, duplicate_eh_regions_map, void *, int);
  
  extern void sjlj_emit_function_exit_after (rtx);
  
Index: function.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/function.h,v
retrieving revision 1.149
diff -c -3 -p -r1.149 function.h
*** function.h	27 Apr 2005 21:35:19 -0000	1.149
--- function.h	11 May 2005 22:44:12 -0000
*************** struct function GTY(())
*** 168,173 ****
--- 168,174 ----
  
    /* The control flow graph for this function.  */
    struct control_flow_graph *cfg;
+   bool after_inlining;
  
    /* For tree-optimize.c.  */
  
Index: tree-optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-optimize.c,v
retrieving revision 2.90
diff -c -3 -p -r2.90 tree-optimize.c
*** tree-optimize.c	11 May 2005 02:24:42 -0000	2.90
--- tree-optimize.c	11 May 2005 22:44:12 -0000
*************** tree_rest_of_compilation (tree fndecl)
*** 675,680 ****
--- 675,681 ----
       We haven't necessarily assigned RTL to all variables yet, so it's
       not safe to try to expand expressions involving them.  */
    cfun->x_dont_save_pending_sizes_p = 1;
+   cfun->after_inlining = true;
  
    node = cgraph_node (fndecl);
  
Index: tree-eh.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-eh.c,v
retrieving revision 2.34
diff -c -3 -p -r2.34 tree-eh.c
*** tree-eh.c	11 May 2005 16:25:28 -0000	2.34
--- tree-eh.c	12 May 2005 16:14:03 -0000
*************** add_stmt_to_eh_region_fn (struct functio
*** 112,117 ****
--- 112,122 ----
    n->stmt = t;
    n->region_nr = num;
  
+   if (!get_eh_throw_stmt_table (ifun))
+     set_eh_throw_stmt_table (ifun, htab_create_ggc (31, struct_ptr_hash,
+ 						    struct_ptr_eq,
+ 						    ggc_free));
+ 
    slot = htab_find_slot (get_eh_throw_stmt_table (ifun), n, INSERT);
    gcc_assert (!*slot);
    *slot = n;
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-cfg.c,v
retrieving revision 2.185
diff -c -3 -p -r2.185 tree-cfg.c
*** tree-cfg.c	10 May 2005 22:33:27 -0000	2.185
--- tree-cfg.c	12 May 2005 16:14:02 -0000
*************** label_to_block_fn (struct function *ifun
*** 823,828 ****
--- 829,836 ----
        bsi_insert_before (&bsi, stmt, BSI_NEW_STMT);
        uid = LABEL_DECL_UID (dest);
      }
+   if (VARRAY_SIZE (ifun->cfg->x_label_to_block_map) <= (unsigned int)uid)
+     return NULL;
    return VARRAY_BB (ifun->cfg->x_label_to_block_map, uid);
  }
  


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