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: [tree-ssa] Another EH cfg cleanup PATCH


On Fri, 30 May 2003 09:27:09 -0600, law@redhat.com wrote:

> In message <wvlof1l400i.fsf@prospero.boston.redhat.com>, Jason Merrill writes:
>  >On Thu, 29 May 2003 19:22:36 -0600, law@redhat.com wrote:
>  >
>  >> And how would I identify such TRY_CATCH_EXPRs?  By the lack of a
>  >> CATCH_EXPR in operand 1 of the TRY_CATCH_EXPR?
>  >
>  >More or less, though you also have to check for EH_FILTER_EXPR, and the
>  >CATCH_EXPR might be wrapped in a COMPOUND_EXPR.
> Yup.  That's already handled as well.  It fell right out since I copied the
> code to detect cleanups from elsewhere.  In all it was pretty simple once
> I decided that it had to be a two step process.   You can't wire up the
> edge when building blocks (the parent cleanup will not have any blocks) and
> you don't have the nice nesting info when wiring up edges (well, maybe it
> exists via parent_stmt).  
>
> So the "obvious" solution is to record the tree node for the parent cleanup
> when building blocks since we have the nesting structure handily available
> and wire up the edge when building all the special edges.

Yep, basically the same deal as finding the edges for calls.

>  >The simplest thing would
>  >be to use get_eh_region_type from the patch I sent you.
> Given that I seem to have lost it, could you resend it so I can see if
> I'm missing anything obvious?

This patch also has a few other miscellaneous cleanups.

*** except.c.~1~	2003-05-29 16:20:30.000000000 -0400
--- except.c	2003-05-26 16:49:38.000000000 -0400
*************** struct eh_region GTY(())
*** 132,148 ****
    bitmap aka;
  
    /* Each region does exactly one thing.  */
!   enum eh_region_type
!   {
!     ERT_UNKNOWN = 0,
!     ERT_CLEANUP,
!     ERT_TRY,
!     ERT_CATCH,
!     ERT_ALLOWED_EXCEPTIONS,
!     ERT_MUST_NOT_THROW,
!     ERT_THROW,
!     ERT_FIXUP
!   } type;
  
    /* Holds the action to perform based on the preceding type.  */
    union eh_region_u {
--- 132,138 ----
    bitmap aka;
  
    /* Each region does exactly one thing.  */
!   enum eh_region_type type;
  
    /* Holds the action to perform based on the preceding type.  */
    union eh_region_u {
*************** void
*** 538,546 ****
  expand_eh_handler (handler)
       tree handler;
  {
!   tree inner = handler;
!   while (TREE_CODE (inner) == COMPOUND_EXPR)
!     inner = TREE_OPERAND (inner, 0);
  
    switch (TREE_CODE (inner))
      {
--- 528,534 ----
  expand_eh_handler (handler)
       tree handler;
  {
!   tree inner = expr_first (handler);
  
    switch (TREE_CODE (inner))
      {
*** except.h.~1~	2003-05-29 16:20:30.000000000 -0400
--- except.h	2003-05-26 16:49:38.000000000 -0400
*************** struct eh_status;
*** 32,37 ****
--- 32,48 ----
  /* Internal structure describing a region.  */
  struct eh_region;
  
+ enum eh_region_type {
+   ERT_UNKNOWN = 0,
+   ERT_CLEANUP,
+   ERT_TRY,
+   ERT_CATCH,
+   ERT_ALLOWED_EXCEPTIONS,
+   ERT_MUST_NOT_THROW,
+   ERT_THROW,
+   ERT_FIXUP
+ };
+ 
  /* Test: is exception handling turned on?  */
  extern int doing_eh			        PARAMS ((int));
  
*** tree-cfg.c.~1~	2003-05-29 16:20:30.000000000 -0400
--- tree-cfg.c	2003-05-26 16:54:02.000000000 -0400
*************** static void make_case_label_edges	PARAMS
*** 102,107 ****
--- 102,108 ----
  /* Various helpers.  */
  static basic_block successor_block	PARAMS ((basic_block));
  static basic_block first_exec_block	PARAMS ((tree *));
+ static basic_block last_exec_block	PARAMS ((tree *));
  static tree *first_exec_stmt		PARAMS ((tree *));
  static basic_block switch_parent	PARAMS ((basic_block));
  static inline bool stmt_starts_bb_p	PARAMS ((tree, tree));
*************** make_cond_expr_blocks (cond_p, next_bloc
*** 506,511 ****
--- 507,529 ----
    make_blocks (&COND_EXPR_ELSE (cond), next_block_link, cond, NULL);
  }
  
+ static enum eh_region_type
+ get_eh_region_type (tree stmt)
+ {
+   if (TREE_CODE (stmt) == TRY_FINALLY_EXPR)
+     return ERT_CLEANUP;
+   if (TREE_CODE (stmt) == TRY_CATCH_EXPR)
+     {
+       tree handler = TREE_OPERAND (stmt, 1);
+       if (TREE_CODE (expr_first (handler)) == CATCH_EXPR)
+ 	return ERT_TRY;
+       if (TREE_CODE (handler) == EH_FILTER_EXPR)
+ 	return ERT_ALLOWED_EXCEPTIONS;
+       return ERT_CLEANUP;
+     }
+   abort ();
+ }
+ 
  /* Create the blocks for the TRY_CATCH_EXPR or TRY_FINALLY_EXPR node
     pointed by expr_p.  */
  
*************** make_try_expr_blocks (expr_p, next_block
*** 535,541 ****
    /* We need to keep a stack of the handler expressions of TRY_CATCH_EXPR
       and TRY_FINALLY nodes so that we know when throwing statements should
       end a basic block.  */
!   VARRAY_PUSH_TREE (eh_stack, TREE_OPERAND (expr, 1));
  
    /* Make blocks for the TRY block.  */
    make_blocks (&TREE_OPERAND (expr, 0), next_block_link, expr, NULL);
--- 553,559 ----
    /* We need to keep a stack of the handler expressions of TRY_CATCH_EXPR
       and TRY_FINALLY nodes so that we know when throwing statements should
       end a basic block.  */
!   VARRAY_PUSH_TREE (eh_stack, expr);
  
    /* Make blocks for the TRY block.  */
    make_blocks (&TREE_OPERAND (expr, 0), next_block_link, expr, NULL);
*************** make_try_expr_blocks (expr_p, next_block
*** 545,550 ****
--- 563,576 ----
  
    /* Make blocks for the handler itself.  */
    make_blocks (&TREE_OPERAND (expr, 1), next_block_link, expr, NULL);
+ 
+   if (get_eh_region_type (expr) == ERT_CLEANUP
+       && VARRAY_ACTIVE_SIZE (eh_stack))
+     {
+       tree region = VARRAY_TOP_TREE (eh_stack);
+       if (get_eh_region_type (region) == ERT_CLEANUP)
+ 	stmt_ann (expr)->reachable_exception_handlers = TREE_OPERAND (region, 1);
+     }
  }
  
  /* Create the blocks for the CATCH_EXPR node pointed to by expr_p.  */
*************** make_edges ()
*** 862,868 ****
        int bb;
        bitmap try_blocks = BITMAP_XMALLOC ();
        bitmap try_targets = BITMAP_XMALLOC ();
-       bitmap dummy_bitmap = BITMAP_XMALLOC ();
  
        /* Get bitmaps for the basic blocks within the TRY block as
  	 well as bitmap for the blocks which the TRY block can
--- 888,893 ----
*************** make_edges ()
*** 894,906 ****
        /* We need to know the last statement in the FINALLY so that
  	 we know where to wire up the additional outgoing edges from
  	 the FINALLY block.  */
!       finally_last_p = NULL;
!       find_contained_blocks_and_edge_targets (&TREE_OPERAND (try_finally, 1),
! 		      			      dummy_bitmap,
! 					      dummy_bitmap,
! 					      &finally_last_p);
! 
!       last_bb = first_exec_block (finally_last_p);
  
        /* Find edges which exited the TRY block.  For each of those
  	 edges, we want to create a new edge from the FINALLY block
--- 919,925 ----
        /* We need to know the last statement in the FINALLY so that
  	 we know where to wire up the additional outgoing edges from
  	 the FINALLY block.  */
!       last_bb = last_exec_block (&TREE_OPERAND (try_finally, 1));
  
        /* Find edges which exited the TRY block.  For each of those
  	 edges, we want to create a new edge from the FINALLY block
*************** make_edges ()
*** 917,926 ****
  	       the end of the FINALLY to the target of edges out of the
  	       TRY block (ie the start of the FINALLY).  */
  	    if (b->index != finally_bb->index)
! 	      make_edge (last_bb, b, EDGE_ABNORMAL);
  	  });
  
-       BITMAP_XFREE (dummy_bitmap);
        BITMAP_XFREE (try_targets);
        BITMAP_XFREE (try_blocks);
      }
--- 936,944 ----
  	       the end of the FINALLY to the target of edges out of the
  	       TRY block (ie the start of the FINALLY).  */
  	    if (b->index != finally_bb->index)
! 	      make_edge (last_bb, b, 0);
  	  });
  
        BITMAP_XFREE (try_targets);
        BITMAP_XFREE (try_blocks);
      }
*************** make_ctrl_stmt_edges (bb)
*** 1074,1089 ****
      case TRY_FINALLY_EXPR:
        VARRAY_PUSH_TREE (try_finallys, last);
        if (first_exec_stmt (&TREE_OPERAND (last, 0)) == NULL)
! 	make_edge (bb, first_exec_block (&TREE_OPERAND (last, 1)), EDGE_ABNORMAL);
  
!       /* FALL THROUGH */
      case TRY_CATCH_EXPR:
        {
  	basic_block target_bb = first_exec_block (&TREE_OPERAND (last, 0));
  
  	if (target_bb)
            make_edge (bb, target_bb, EDGE_FALLTHRU);
! 	make_edge (bb, successor_block (bb), EDGE_FALLTHRU);
  	break;
        }
  
--- 1092,1120 ----
      case TRY_FINALLY_EXPR:
        VARRAY_PUSH_TREE (try_finallys, last);
        if (first_exec_stmt (&TREE_OPERAND (last, 0)) == NULL)
! 	{
! 	  make_edge (bb, first_exec_block (&TREE_OPERAND (last, 1)), EDGE_FALLTHRU);
! 	  break;
! 	}
  
!       /* else FALL THROUGH */
      case TRY_CATCH_EXPR:
        {
  	basic_block target_bb = first_exec_block (&TREE_OPERAND (last, 0));
  
  	if (target_bb)
            make_edge (bb, target_bb, EDGE_FALLTHRU);
! 	else
! 	  make_edge (bb, successor_block (bb), EDGE_FALLTHRU);
! 
! 	/* Make an edge to the next cleanup if applicable.  */
! 	if (stmt_ann (last)->reachable_exception_handlers)
! 	  {
! 	    tree handler = stmt_ann (last)->reachable_exception_handlers;
! 	    target_bb = last_exec_block (&TREE_OPERAND (last, 1));
! 	    make_edge (target_bb, first_exec_block (&handler), 0);
! 	  }
! 	    
  	break;
        }
  
*************** make_ctrl_stmt_edges (bb)
*** 1093,1099 ****
  
  	if (target_bb)
  	  make_edge (bb, target_bb, EDGE_FALLTHRU);
! 	make_edge (bb, successor_block (bb), EDGE_FALLTHRU);
  	break;
        }
  
--- 1124,1131 ----
  
  	if (target_bb)
  	  make_edge (bb, target_bb, EDGE_FALLTHRU);
! 	else
! 	  make_edge (bb, successor_block (bb), EDGE_FALLTHRU);
  	break;
        }
  
*************** make_ctrl_stmt_edges (bb)
*** 1102,1109 ****
  	basic_block target_bb = first_exec_block (&EH_FILTER_FAILURE (last));
  
  	if (target_bb)
! 	  make_edge (bb, target_bb, EDGE_ABNORMAL);
! 	make_edge (bb, successor_block (bb), EDGE_FALLTHRU);
  	break;
        }
  
--- 1134,1142 ----
  	basic_block target_bb = first_exec_block (&EH_FILTER_FAILURE (last));
  
  	if (target_bb)
! 	  make_edge (bb, target_bb, EDGE_FALLTHRU);
! 	else
! 	  make_edge (bb, successor_block (bb), EDGE_FALLTHRU);
  	break;
        }
  
*************** remove_useless_stmts_and_vars (first_p)
*** 1489,1508 ****
  	  /* If the body of a TRY_FINALLY is empty, then we can just
  	     emit the handler without the enclosing TRY_FINALLY.
                                                                                  
! 	     If the body of a TRY_CATCH is empty and the handler is
! 	     empty (it had no reachable code either), then we can
! 	     emit an empty statement without the enclosing TRY_CATCH.
  
  	     In both cases we want to apply this optimization pass
  	     again.  */
  	  if (IS_EMPTY_STMT (TREE_OPERAND (*stmt_p, 0)))
  	    {
! 	      if (code == TRY_FINALLY_EXPR
! 		  || IS_EMPTY_STMT (TREE_OPERAND (*stmt_p, 1)))
! 		{
! 		  *stmt_p = TREE_OPERAND (*stmt_p, 1);
! 		  repeat = 1;
! 		}
  	    }
  	}
        else if (code == BIND_EXPR)
--- 1522,1539 ----
  	  /* If the body of a TRY_FINALLY is empty, then we can just
  	     emit the handler without the enclosing TRY_FINALLY.
                                                                                  
! 	     If the body of a TRY_CATCH is empty, then we can throw the
! 	     whole thing away.
  
  	     In both cases we want to apply this optimization pass
  	     again.  */
  	  if (IS_EMPTY_STMT (TREE_OPERAND (*stmt_p, 0)))
  	    {
! 	      if (code == TRY_FINALLY_EXPR)
! 		*stmt_p = TREE_OPERAND (*stmt_p, 1);
! 	      else
! 		*stmt_p = build_empty_stmt ();
! 	      repeat = 1;
  	    }
  	}
        else if (code == BIND_EXPR)
*************** first_exec_block (entry_p)
*** 2948,2953 ****
--- 2979,2999 ----
    return (exec_p) ? bb_for_stmt (*exec_p) : NULL;
  }
  
+ /* Return the last basic block with executable statements in it, starting
+    at ENTRY_P.  */
+ 
+ static basic_block
+ last_exec_block (entry_p)
+      tree *entry_p;
+ {
+   bitmap dummy_bitmap = BITMAP_XMALLOC ();
+   tree *last_p = NULL;
+   find_contained_blocks_and_edge_targets (entry_p, dummy_bitmap, dummy_bitmap,
+ 					  &last_p);
+   BITMAP_XFREE (dummy_bitmap);
+   return first_exec_block (last_p);
+ }
+ 
  
  /* Return the header block for the innermost switch statement containing
     BB.  Return NULL if BB is not inside a switch statement.  */
*************** compute_reachable_eh (tree stmt)
*** 4170,4183 ****
       on a list and added to the statement's annotation.  */
    for (i = VARRAY_ACTIVE_SIZE (eh_stack) - 1; i >= 0; i--)
      {
!       tree handler = VARRAY_TREE (eh_stack, i);
!       tree tp_node;
  
!       if (TREE_CODE (handler) == CATCH_EXPR
! 	  || (TREE_CODE (handler) == COMPOUND_EXPR
! 	      && TREE_CODE (TREE_OPERAND (handler, 0)) == CATCH_EXPR))
  	{
! 	  for (si = tsi_start (&handler); !tsi_end_p (si); tsi_next (&si))
  	    {
  	      tree types;
  
--- 4216,4229 ----
       on a list and added to the statement's annotation.  */
    for (i = VARRAY_ACTIVE_SIZE (eh_stack) - 1; i >= 0; i--)
      {
!       tree region = VARRAY_TREE (eh_stack, i);
!       tree handler, tp_node;
  
!       switch (get_eh_region_type (region))
  	{
! 	case ERT_TRY:
! 	  for (si = tsi_start (&TREE_OPERAND (region, 1));
! 	       !tsi_end_p (si); tsi_next (&si))
  	    {
  	      tree types;
  
*************** compute_reachable_eh (tree stmt)
*** 4217,4228 ****
  				     reachable_handlers);
  		    }
  		}
- 
- 	      skip_cleanups = 0;
  	    }
! 	}
!       else if (TREE_CODE (handler) == EH_FILTER_EXPR)
! 	{
  	  /* This is an exception specification.  If it has
  	     no types, then it ends our search.  */
  	  if (EH_FILTER_TYPES (handler) == NULL_TREE)
--- 4263,4276 ----
  				     reachable_handlers);
  		    }
  		}
  	    }
! 
! 	  skip_cleanups = 0;
! 	  break;
! 	  
! 	case ERT_ALLOWED_EXCEPTIONS:
! 	  handler = TREE_OPERAND (region, 1);
! 
  	  /* This is an exception specification.  If it has
  	     no types, then it ends our search.  */
  	  if (EH_FILTER_TYPES (handler) == NULL_TREE)
*************** compute_reachable_eh (tree stmt)
*** 4241,4260 ****
  					  reachable_handlers);
  
  	  skip_cleanups = 0;
! 	}
!       else if (!skip_cleanups)
! 	{
  	  /* This is a cleanup and is reachable.  It does not
  	     stop our search; however, we can skip other
  	     cleanups until we run into something else.  */
  	  reachable_handlers = tree_cons (void_type_node,
  					  handler,
  					  reachable_handlers);
- #if 0
- 	  /* Actually, we can't.  At least not until we build edges from
- 	     one cleanup to the next.  */
  	  skip_cleanups = 1;
! #endif
  	}
      }
  
--- 4289,4310 ----
  					  reachable_handlers);
  
  	  skip_cleanups = 0;
! 	  break;
! 
! 	case ERT_CLEANUP:
! 	  handler = TREE_OPERAND (region, 1);
! 
  	  /* This is a cleanup and is reachable.  It does not
  	     stop our search; however, we can skip other
  	     cleanups until we run into something else.  */
  	  reachable_handlers = tree_cons (void_type_node,
  					  handler,
  					  reachable_handlers);
  	  skip_cleanups = 1;
! 	  break;
! 
! 	default:
! 	  abort ();
  	}
      }
  

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