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] Removal of gotos from cfg based ir


Hello,

> Other than that, the patch looks reasonable to me. It of course doesn't
> apply to the branch any more (:-|). can you submit a new one that
> applies with any relevent changes above for a final look?

here is the updated version; it bootstraps, but causes 3 new failures
in gcc testsuite:

> FAIL: gcc.dg/i386-cmov1.c scan-assembler sar[^\\n]*magic_namea
> FAIL: gcc.dg/i386-cmov1.c scan-assembler sar[^\\n]*magic_nameb
> FAIL: gcc.dg/i386-cmov1.c scan-assembler sar[^\\n]*magic_namec

I am investigating this now.

Zdenek

	* tree-cfg.c: (make_edges): Eliminate fallthru to exit.
	(make_ctrl_stmt_edges): Nonlocal goto handling moved to
	make_goto_expr_edges.
	(make_goto_expr_edges): Remove simple gotos.
	(cfg_remove_useless_stmts_bb): Goto removal cancelled.
	(cleanup_cond_expr_graph, cleanup_switch_expr_graph):
	Replaced by ...
	(cleanup_control_expr_graph): New.
	(cleanup_control_flow): Use it.
	(disband_implicit_edges): New.
	(tree_find_edge_insert_loc): Never insert before a control statement.
	(tree_split_edge, thread_jumps, tree_try_redirect_by_replacing_jump,
	tree_redirect_edge_and_branch): Work over no-gotos form.
	(tree_verify_flow_info): Check no-gotos form invariants.
	* tree-pretty-print.c (pp_cfg_jump, dump_implicit_edges): New.
	(dump_generic_bb_buff): Call dump_implicit_edges.
	* tree-flow.h (cleanup_cond_expr_graph, cleanup_switch_expr_graph):
	Declaration removed.
	(cleanup_control_expr_graph, delete_tree_ssa, disband_implicit_edges):
	Declare.
	* tree-optimize.c (tree_ssa_finish): New.
	(optimize_function_tree): Call it.
	* tree-ssa-dom.c (thread_jumps_walk_stmts, optimize_stmt): Use
	cleanup_control_expr_graph.
	* tree-ssa.c (delete_tree_ssa): Export, work even if there are no
	referenced_vars.
	(rewrite_out_of_ssa): Don't call it.

Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.225
diff -c -3 -p -r1.1.4.225 tree-cfg.c
*** tree-cfg.c	25 Nov 2003 05:09:07 -0000	1.1.4.225
--- tree-cfg.c	29 Nov 2003 20:45:09 -0000
*************** static void
*** 448,453 ****
--- 448,454 ----
  make_edges (void)
  {
    basic_block bb;
+   edge e;
  
    /* Create an edge from entry to the first block with executable
       statements in it.  */
*************** make_edges (void)
*** 476,481 ****
--- 477,505 ----
  	make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
      }
  
+   /* If there is a fallthru edge to exit out of the last block, transform it
+      to a return statement.  */
+   for (e = EXIT_BLOCK_PTR->prev_bb->succ; e; e = e->succ_next)
+     if (e->flags & EDGE_FALLTHRU)
+       break;
+   if (e && e->dest == EXIT_BLOCK_PTR)
+     {
+       block_stmt_iterator bsi;
+       tree x;
+ 
+       /* ??? Can we have multiple outgoing edges here?  COND_EXPR
+ 	 always has two gotos, and I can't think how one would have
+ 	 achived this via EH.  */
+       if (e != EXIT_BLOCK_PTR->prev_bb->succ || e->succ_next)
+ 	abort ();
+ 	
+       x = build (RETURN_EXPR, void_type_node, NULL_TREE);
+       bsi = bsi_last (EXIT_BLOCK_PTR->prev_bb);
+       bsi_insert_after (&bsi, x, BSI_NEW_STMT);
+ 
+       e->flags &= ~EDGE_FALLTHRU;
+     }
+ 
    /* We do not care about fake edges, so remove any that the CFG
       builder inserted for completeness.  */
    remove_fake_edges ();
*************** make_ctrl_stmt_edges (basic_block bb)
*** 505,515 ****
      {
      case GOTO_EXPR:
        make_goto_expr_edges (bb);
- 
-       /* If this is potentially a nonlocal goto, then this should also
- 	 create an edge to the exit block.   */
-       if (nonlocal_goto_p (last))
- 	make_edge (bb, EXIT_BLOCK_PTR, EDGE_ABNORMAL);
        break;
  
      case RETURN_EXPR:
--- 529,534 ----
*************** make_goto_expr_edges (basic_block bb)
*** 657,666 ****
  {
    tree goto_t, dest;
    basic_block target_bb;
-   int edge_flags;
    int for_call;
  
!   goto_t = last_stmt (bb);
  
    /* If the last statement is not a GOTO (i.e., it is a RETURN_EXPR,
       CALL_EXPR or MODIFY_EXPR), then the edge is an abnormal edge resulting
--- 676,685 ----
  {
    tree goto_t, dest;
    basic_block target_bb;
    int for_call;
+   block_stmt_iterator last = bsi_last (bb);
  
!   goto_t = bsi_stmt (last);
  
    /* If the last statement is not a GOTO (i.e., it is a RETURN_EXPR,
       CALL_EXPR or MODIFY_EXPR), then the edge is an abnormal edge resulting
*************** make_goto_expr_edges (basic_block bb)
*** 669,675 ****
      {
        dest = error_mark_node;
        for_call = 1;
-       edge_flags = EDGE_ABNORMAL;
      }
    else
      {
--- 688,693 ----
*************** make_goto_expr_edges (basic_block bb)
*** 679,691 ****
        /* A GOTO to a local label creates normal edges.  */
        if (simple_goto_p (goto_t))
  	{
! 	  make_edge (bb, label_to_block (dest), 0);
  	  return;
  	}
  
!       /* If we reach here, then we either have a computed goto or
! 	 a nonlocal goto.  */
!       edge_flags = EDGE_ABNORMAL;
      }
  
    /* Look for the block starting with the destination label.  In the
--- 697,717 ----
        /* A GOTO to a local label creates normal edges.  */
        if (simple_goto_p (goto_t))
  	{
! 	  make_edge (bb, label_to_block (dest), EDGE_FALLTHRU);
! 	  bsi_remove (&last);
  	  return;
  	}
  
!       /* If this is potentially a nonlocal goto, then this should
! 	 create an edge to the exit block.   */
!       if (nonlocal_goto_p (goto_t))
! 	make_edge (bb, EXIT_BLOCK_PTR, EDGE_ABNORMAL);
! 
!       /* Nothing more to do for nonlocal gotos. */
!       if (TREE_CODE (dest) == LABEL_DECL)
! 	return;
! 
!       /* Computed gotos remain.  */
      }
  
    /* Look for the block starting with the destination label.  In the
*************** make_goto_expr_edges (basic_block bb)
*** 702,710 ****
  	  if (TREE_CODE (target) != LABEL_EXPR)
  	    break;
  
- 	  if (TREE_CODE (dest) == LABEL_DECL)
- 	    continue;
- 
  	  if (
  	      /* Computed GOTOs.  Make an edge to every label block that has
  		 been marked as a potential target for a computed goto.  */
--- 728,733 ----
*************** make_goto_expr_edges (basic_block bb)
*** 714,720 ****
  		 goto.  */
  	      || (NONLOCAL_LABEL (LABEL_EXPR_LABEL (target)) && for_call == 1))
  	    {
! 	      make_edge (bb, target_bb, edge_flags);
  	      break;
  	    }
  	}
--- 737,743 ----
  		 goto.  */
  	      || (NONLOCAL_LABEL (LABEL_EXPR_LABEL (target)) && for_call == 1))
  	    {
! 	      make_edge (bb, target_bb, EDGE_ABNORMAL);
  	      break;
  	    }
  	}
*************** cfg_remove_useless_stmts_bb (basic_block
*** 1284,1365 ****
  {
    block_stmt_iterator bsi;
    tree stmt = NULL_TREE;
-   tree *gotos[2], *pstmt;
-   int n_gotos, n_rem_gotos;
    tree cond, var = NULL_TREE, val = NULL_TREE;
    struct var_ann_d *ann;
  
    /* Check whether we come here from a condition, and if so, get the
       condition.  */
!   if (bb->pred && !bb->pred->pred_next
!       && (bb->pred->flags & (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE)))
!     {
!       cond = COND_EXPR_COND (last_stmt (bb->pred->src));
!       if (bb->pred->flags & EDGE_FALSE_VALUE)
! 	cond = invert_truthvalue (cond);
! 
!       if (TREE_CODE (cond) == VAR_DECL
! 	  || TREE_CODE (cond) == PARM_DECL)
! 	{
! 	  var = cond;
! 	  val = convert (TREE_TYPE (cond), integer_zero_node);
! 	}
!       else if ((TREE_CODE (cond) == EQ_EXPR)
! 	       && (TREE_CODE (TREE_OPERAND (cond, 0)) == VAR_DECL
! 		   || TREE_CODE (TREE_OPERAND (cond, 0)) == PARM_DECL)
! 	       && (TREE_CODE (TREE_OPERAND (cond, 1)) == VAR_DECL
! 		   || TREE_CODE (TREE_OPERAND (cond, 1)) == PARM_DECL
! 		   || TREE_CONSTANT (TREE_OPERAND (cond, 1))))
! 	{
! 	  var = TREE_OPERAND (cond, 0);
! 	  val = TREE_OPERAND (cond, 1);
! 	}
  
!       if (var)
! 	{
! 	  /* Only work for normal local variables.  */
! 	  ann = var_ann (var);
! 	  if (!ann
! 	      || ann->may_aliases
! 	      || TREE_ADDRESSABLE (var))
! 	    {
! 	      var = NULL_TREE;
! 	      val = NULL_TREE;
! 	    }
  
! 	  if (var && ! TREE_CONSTANT (val))
! 	    {
! 	      ann = var_ann (val);
! 	      if (!ann
! 		  || ann->may_aliases
! 		  || TREE_ADDRESSABLE (val))
! 		{
! 		  val = NULL_TREE;
! 		  var = NULL_TREE;
! 		}
! 	    }
! 	}
  
!       /* Ignore floating point variables, since comparison behaves weird for
! 	 them.  */
!       if (var
! 	  && FLOAT_TYPE_P (TREE_TYPE (var)))
! 	{
! 	  var = NULL_TREE;
! 	  val = NULL_TREE;
! 	}
      }
  
    for (bsi = bsi_start (bb); !bsi_end_p (bsi);)
      {
        stmt = bsi_stmt (bsi);
  
-       if (!var)
- 	{
- 	  bsi_next (&bsi);
- 	  continue;
- 	}
- 
        /* If the THEN/ELSE clause merely assigns a value to a variable/parameter
  	 which is already known to contain that value, then remove the useless
  	 THEN/ELSE clause.  */
--- 1307,1370 ----
  {
    block_stmt_iterator bsi;
    tree stmt = NULL_TREE;
    tree cond, var = NULL_TREE, val = NULL_TREE;
    struct var_ann_d *ann;
  
    /* Check whether we come here from a condition, and if so, get the
       condition.  */
!   if (!bb->pred
!       || bb->pred->pred_next
!       || !(bb->pred->flags & (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE)))
!     return;
  
!   cond = COND_EXPR_COND (last_stmt (bb->pred->src));
!   if (bb->pred->flags & EDGE_FALSE_VALUE)
!     cond = invert_truthvalue (cond);
! 
!   if (TREE_CODE (cond) == VAR_DECL
!       || TREE_CODE (cond) == PARM_DECL)
!     {
!       var = cond;
!       val = convert (TREE_TYPE (cond), integer_zero_node);
!     }
!   else if ((TREE_CODE (cond) == EQ_EXPR)
! 	   && (TREE_CODE (TREE_OPERAND (cond, 0)) == VAR_DECL
! 	       || TREE_CODE (TREE_OPERAND (cond, 0)) == PARM_DECL)
! 	   && (TREE_CODE (TREE_OPERAND (cond, 1)) == VAR_DECL
! 	       || TREE_CODE (TREE_OPERAND (cond, 1)) == PARM_DECL
! 	       || TREE_CONSTANT (TREE_OPERAND (cond, 1))))
!     {
!       var = TREE_OPERAND (cond, 0);
!       val = TREE_OPERAND (cond, 1);
!     }
!   else
!     return;
  
!   /* Only work for normal local variables.  */
!   ann = var_ann (var);
!   if (!ann
!       || ann->may_aliases
!       || TREE_ADDRESSABLE (var))
!     return;
  
!   if (! TREE_CONSTANT (val))
!     {
!       ann = var_ann (val);
!       if (!ann
! 	  || ann->may_aliases
! 	  || TREE_ADDRESSABLE (val))
! 	return;
      }
  
+   /* Ignore floating point variables, since comparison behaves weird for
+      them.  */
+   if (FLOAT_TYPE_P (TREE_TYPE (var)))
+     return;
+ 
    for (bsi = bsi_start (bb); !bsi_end_p (bsi);)
      {
        stmt = bsi_stmt (bsi);
  
        /* If the THEN/ELSE clause merely assigns a value to a variable/parameter
  	 which is already known to contain that value, then remove the useless
  	 THEN/ELSE clause.  */
*************** cfg_remove_useless_stmts_bb (basic_block
*** 1378,1442 ****
  	      && (TREE_OPERAND (stmt, 0) == var
  		  || TREE_OPERAND (stmt, 0) == val
  		  || TREE_CODE (TREE_OPERAND (stmt, 1)) == VA_ARG_EXPR)))
! 	{
! 	  var = NULL_TREE;
! 	  val = NULL_TREE;
! 	}
    
        bsi_next (&bsi);
      }
- 
-   if (!stmt)
-     return;
- 
-   /* Remove useless GOTOs from COND_EXPRs.  Other useless gotos could be
-      removed by cfg cleanup, but it is not done currently, so do it here
-      also.  */
-   if (TREE_CODE (stmt) == GOTO_EXPR
-       && (bb->succ->flags & EDGE_ABNORMAL) == 0)
-     {
-       gotos[0] = &stmt;
-       n_gotos = 1;
-     }
-   else if (TREE_CODE (stmt) == COND_EXPR
- 	   && (bb->succ->flags & EDGE_ABNORMAL) == 0
- 	   && (bb->succ->succ_next->flags & EDGE_ABNORMAL) == 0)
-     {
-       gotos[0] = &COND_EXPR_THEN (stmt);
-       gotos[1] = &COND_EXPR_ELSE (stmt);
-       n_gotos = 2;
-     }
-   else
-     return;
- 
-   n_rem_gotos = n_gotos;
-   while (n_gotos--)
-     {
-       pstmt = gotos[n_gotos];
-       stmt = *pstmt;
- 
-       if (TREE_CODE (GOTO_DESTINATION (stmt)) != LABEL_DECL)
- 	continue;
- 
-       if (label_to_block (GOTO_DESTINATION (stmt)) != bb->next_bb)
- 	continue;
- 
-       *pstmt = build_empty_stmt ();
-       n_rem_gotos--;
-     }
- 
-   /* The statement does nothing, remove it completely.  */
-   if (!n_rem_gotos)
-     {
-       bsi = bsi_last (bb);
-       bsi_remove (&bsi);
- 
-       if (bb->succ->succ_next)
- 	abort ();
- 
-       bb->succ->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
-       bb->succ->flags |= EDGE_FALLTHRU;
-     }
  }
  
  /* A cfg-aware version of remove_useless_stmts_and_vars.  */
--- 1383,1392 ----
  	      && (TREE_OPERAND (stmt, 0) == var
  		  || TREE_OPERAND (stmt, 0) == val
  		  || TREE_CODE (TREE_OPERAND (stmt, 1)) == VA_ARG_EXPR)))
! 	return;
    
        bsi_next (&bsi);
      }
  }
  
  /* A cfg-aware version of remove_useless_stmts_and_vars.  */
*************** tree_block_forwards_to (basic_block bb)
*** 1603,1626 ****
      return NULL;
  
    /* Walk past any labels at the start of this block.  */
!   bsi = bsi_start (bb);
!   while (1)
      {
-       stmt = NULL;
-       if (bsi_end_p (bsi))
- 	break;
        stmt = bsi_stmt (bsi);
!       if (TREE_CODE (stmt) == LABEL_EXPR)
! 	bsi_next (&bsi);
!       else
  	break;
      }
  
!   /* If we reached the end of this block, or hit a GOTO_EXPR to an known
!      location, then we may be able to optimize this case.  */
!   if (!stmt
!       || (TREE_CODE (stmt) == GOTO_EXPR
! 	  && TREE_CODE (GOTO_DESTINATION (stmt)) == LABEL_DECL))
      {
        basic_block dest;
  
--- 1553,1568 ----
      return NULL;
  
    /* Walk past any labels at the start of this block.  */
!   for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
      {
        stmt = bsi_stmt (bsi);
!       if (TREE_CODE (stmt) != LABEL_EXPR)
  	break;
      }
  
!   /* If we reached the end of this block we may be able to optimize this
!      case.  */
!   if (bsi_end_p (bsi))
      {
        basic_block dest;
  
*************** cleanup_control_flow (void)
*** 1647,1692 ****
    basic_block bb;
    block_stmt_iterator bsi;
    bool retval = false;
  
    FOR_EACH_BB (bb)
      {
        bsi = bsi_last (bb);
  
!       if (!bsi_end_p (bsi))
! 	{
! 	  enum tree_code code = TREE_CODE (bsi_stmt (bsi));
! 	  if (code == COND_EXPR)
! 	    retval |= cleanup_cond_expr_graph (bb, bsi);
! 	  else if (code == SWITCH_EXPR)
! 	    retval |= cleanup_switch_expr_graph (bb, bsi);
! 	}
      }
    return retval;
  }
  
! /* Disconnect an unreachable block in the conditional expression starting
     at block BB.  */
  
  bool
! cleanup_cond_expr_graph (basic_block bb, block_stmt_iterator bsi)
  {
-   tree val;
    edge taken_edge;
    bool retval = false;
!   tree cond_expr = bsi_stmt (bsi);
! 
! #if defined ENABLE_CHECKING
!   if (cond_expr == NULL_TREE
!       || TREE_CODE (cond_expr) != COND_EXPR
!       || !bb->succ)
!     abort ();
! #endif
  
    if (bb->succ->succ_next)
      {
        edge e, next;
  
!       val = COND_EXPR_COND (cond_expr);
        taken_edge = find_taken_edge (bb, val);
        if (!taken_edge)
  	return false;
--- 1589,1641 ----
    basic_block bb;
    block_stmt_iterator bsi;
    bool retval = false;
+   tree stmt;
  
    FOR_EACH_BB (bb)
      {
        bsi = bsi_last (bb);
  
!       if (bsi_end_p (bsi))
! 	continue;
!       
!       stmt = bsi_stmt (bsi);
!       if (TREE_CODE (stmt) == COND_EXPR
! 	  || TREE_CODE (stmt) == SWITCH_EXPR)
! 	retval |= cleanup_control_expr_graph (bb, bsi);
      }
    return retval;
  }
  
! /* Disconnect an unreachable block in the control expression starting
     at block BB.  */
  
  bool
! cleanup_control_expr_graph (basic_block bb, block_stmt_iterator bsi)
  {
    edge taken_edge;
    bool retval = false;
!   tree expr = bsi_stmt (bsi), val;
  
    if (bb->succ->succ_next)
      {
        edge e, next;
  
!       switch (TREE_CODE (expr))
! 	{
! 	case COND_EXPR:
! 	  val = COND_EXPR_COND (expr);
! 	  break;
! 
! 	case SWITCH_EXPR:
! 	  val = SWITCH_COND (expr);
! 	  if (TREE_CODE (val) != INTEGER_CST)
! 	    return false;
! 	  break;
! 
! 	default:
! 	  abort ();
! 	}
! 
        taken_edge = find_taken_edge (bb, val);
        if (!taken_edge)
  	return false;
*************** cleanup_cond_expr_graph (basic_block bb,
*** 1705,1778 ****
    else
      taken_edge = bb->succ;
  
!   if (taken_edge->flags & EDGE_TRUE_VALUE)
!     bsi_replace (&bsi, COND_EXPR_THEN (cond_expr), false);
!   else if (taken_edge->flags & EDGE_FALSE_VALUE)
!     bsi_replace (&bsi, COND_EXPR_ELSE (cond_expr), false);
!   else
!     abort ();
! 
!   taken_edge->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
! 
!   return retval;
! }
! 
! /* Disconnect unreachable blocks in the 'switch' expression starting at
!    block SWITCH_BB.
! 
!    If the switch condition of the SWITCH_EXPR node in block SWITCH_BB is
!    constant, disconnect all the subgraphs for all the case labels that will
!    never be taken.  */
! 
! bool
! cleanup_switch_expr_graph (basic_block bb, block_stmt_iterator bsi)
! {
!   tree switch_expr = bsi_stmt (bsi);
!   tree switch_val, taken_case;
!   basic_block dest_bb;
!   bool retval;
! 
! #if defined ENABLE_CHECKING
!   if (switch_expr == NULL_TREE || TREE_CODE (switch_expr) != SWITCH_EXPR)
!     abort ();
! #endif
! 
!   retval = false;
!   if (bb->succ->succ_next)
!     {
!       edge e, next;
! 
!       /* Multiple destination edges.  If we've got a integer constant,
! 	 we can look up the value in the switch condition and replace.  */
!       switch_val = SWITCH_COND (switch_expr);
!       if (TREE_CODE (switch_val) != INTEGER_CST)
! 	return retval;
! 
!       taken_case = find_case_label_for_value (switch_expr, switch_val);
!       dest_bb = label_to_block (CASE_LABEL (taken_case));
! 
!       /* Remove all the edges that will never be taken.  */
!       for (e = bb->succ; e ; e = next)
! 	{
! 	  next = e->succ_next;
! 	  if (e->dest != dest_bb)
!             {
! 	      ssa_remove_edge (e);
! 	      retval = true;
! 	    }
! 	}
!     }
!   else
!     {
!       /* There is only one destination edge, which means that all of
! 	 the labels go to the same place.  */
!       dest_bb = bb->succ->dest;
!       taken_case = TREE_VEC_ELT (SWITCH_LABELS (switch_expr), 0);
!     }
! 
!   /* Simplify the SWITCH_EXPR itself.  */
!   taken_case = build (GOTO_EXPR, void_type_node, CASE_LABEL (taken_case));
!   bsi_replace (&bsi, taken_case, false);
  
    return retval;
  }
--- 1654,1661 ----
    else
      taken_edge = bb->succ;
  
!   bsi_remove (&bsi);
!   taken_edge->flags = EDGE_FALLTHRU;
  
    return retval;
  }
*************** stmt_ends_bb_p (tree t)
*** 2410,2415 ****
--- 2293,2378 ----
    return is_ctrl_stmt (t) || is_ctrl_altering_stmt (t);
  }
  
+ /* Add gotos that used to be represented implicitly in cfg.  */
+ 
+ void
+ disband_implicit_edges (void)
+ {
+   basic_block bb;
+   block_stmt_iterator last;
+   edge e;
+   tree stmt;
+ 
+   FOR_EACH_BB (bb)
+     {
+       last = bsi_last (bb);
+       stmt = last_stmt (bb);
+ 
+       if (stmt && TREE_CODE (stmt) == COND_EXPR)
+ 	{
+ 	  /* Remove superfluous gotos from COND_EXPR branches.  Moved
+ 	     from cfg_remove_useless_stmts here since it violates the
+ 	     invariants for tree--cfg correspondence and thus fits better
+ 	     here where we do it anyway.  */
+ 
+ 	  for (e = bb->succ; e; e = e->succ_next)
+ 	    {
+ 	      if (e->dest != bb->next_bb)
+ 		continue;
+ 
+ 	      if (e->flags & EDGE_TRUE_VALUE)
+ 		COND_EXPR_THEN (stmt) = build_empty_stmt ();
+ 	      else if (e->flags & EDGE_FALSE_VALUE)
+ 		COND_EXPR_ELSE (stmt) = build_empty_stmt ();
+ 	      else
+ 		abort ();
+ 	    }
+ 
+ 	  continue;
+ 	}
+ 
+       if (stmt && TREE_CODE (stmt) == RETURN_EXPR)
+ 	{
+ 	  /* Remove the RETURN_EXPR if we may fallthru to the exit
+ 	     instead.  */
+ 	  if (!bb->succ
+ 	      || bb->succ->succ_next
+ 	      || bb->succ->dest != EXIT_BLOCK_PTR)
+ 	    abort ();
+ 
+ 	  if (bb->next_bb == EXIT_BLOCK_PTR
+ 	      && !TREE_OPERAND (stmt, 0))
+ 	    {
+ 	      bsi_remove (&last);
+ 	      bb->succ->flags |= EDGE_FALLTHRU;
+ 	    }
+ 	  continue;
+ 	}
+ 
+       /* There can be no fallthru edge if the last statement is a control
+          one.  */
+       if (stmt && is_ctrl_stmt (stmt))
+ 	continue;
+ 
+       /* Find a fallthru edge and emit the goto if neccesary.  */
+       for (e = bb->succ; e; e = e->succ_next)
+ 	if (e->flags & EDGE_FALLTHRU)
+ 	  break;
+ 
+       if (!e
+ 	  || e->dest == bb->next_bb)
+ 	continue;
+ 
+       if (e->dest == EXIT_BLOCK_PTR)
+ 	abort ();
+ 
+       bsi_insert_after (&last,
+ 			build1 (GOTO_EXPR, void_type_node,
+ 				tree_block_label (e->dest)),
+ 			BSI_NEW_STMT);
+     }
+ }
+ 
  /* Remove all the blocks and edges that make up the flowgraph.  */
  
  void
*************** delete_tree_cfg (void)
*** 2417,2422 ****
--- 2380,2386 ----
  {
    if (n_basic_blocks > 0)
      free_blocks_annotations ();
+ 
    free_basic_block_vars (0);
    tree_bb_root = NULL;
  }
*************** tree_find_edge_insert_loc (edge e, block
*** 2660,2667 ****
  	return false;
      }
  
!   /* If the source has one successor and the edge is not abnormal,
!      insert there.  Except for the entry block.  */
    src = e->src;
    if ((e->flags & EDGE_ABNORMAL) == 0
        && src->succ->succ_next == NULL
--- 2624,2632 ----
  	return false;
      }
  
!   /* If the source has one successor, the edge is not abnormal and
!      the last statement does not end a basic block, insert there.
!      Except for the entry block.  */
    src = e->src;
    if ((e->flags & EDGE_ABNORMAL) == 0
        && src->succ->succ_next == NULL
*************** tree_find_edge_insert_loc (edge e, block
*** 2671,2679 ****
        if (bsi_end_p (*bsi))
  	return true;
  
-       /* Make sure we insert before a final goto statement.  */
        tmp = bsi_stmt (*bsi);
!       return !is_ctrl_stmt (tmp);
      }
  
    /* Otherwise, create a new basic block, and split this edge.  */
--- 2636,2644 ----
        if (bsi_end_p (*bsi))
  	return true;
  
        tmp = bsi_stmt (*bsi);
!       if (!stmt_ends_bb_p (tmp))
! 	return true;
      }
  
    /* Otherwise, create a new basic block, and split this edge.  */
*************** tree_split_edge (edge edge_in)
*** 2798,2851 ****
        if (!e)
  	after_bb = dest->prev_bb;
        else
! 	{
! 	  after_bb = EXIT_BLOCK_PTR->prev_bb;
! 	  for (e = after_bb->succ; e ; e = e->succ_next)
! 	    if (e->flags & EDGE_FALLTHRU)
! 	      break;
! 	  if (e)
! 	    {
! 	      block_stmt_iterator bsi;
! 	      tree x;
! 
! 	      /* We have a fallthru to exit out of the last block.
! 		 Transform this to a return statement.  */
! 	      /* ??? Can we have multiple outgoing edges here?  COND_EXPR
! 		 always has two gotos, and I can't think how one would have
! 		 achived this via EH.  */
! 	      if (e != after_bb->succ || e->succ_next)
! 		abort ();
! 	
! 	      x = build (RETURN_EXPR, void_type_node, NULL_TREE);
! 	      bsi = bsi_last (after_bb);
! 	      bsi_insert_after (&bsi, x, BSI_NEW_STMT);
! 
! 	      e->flags &= ~EDGE_FALLTHRU;
! 	    }
! 	}
      }
  
    new_bb = create_bb (NULL, after_bb);
    create_block_annotation (new_bb);
!   new_edge = make_edge (new_bb, dest, 0);
  
!   if (edge_in->flags & EDGE_FALLTHRU)
!     {
!       new_edge->flags = EDGE_FALLTHRU;
!       redirect_edge_succ (edge_in, new_bb);
!     }
!   else
!     {
!       block_stmt_iterator i;
!       tree x;
! 
!       if (!tree_redirect_edge_and_branch_1 (edge_in, new_bb, true))
! 	abort ();
! 
!       x = build (GOTO_EXPR, void_type_node, tree_block_label (dest));
!       i = bsi_last (new_bb);
!       bsi_insert_after (&i, x, BSI_NEW_STMT);
!     }
  
    /* Find all the PHI arguments on the original edge, and change them to
       the new edge.  */
--- 2763,2777 ----
        if (!e)
  	after_bb = dest->prev_bb;
        else
! 	after_bb = EXIT_BLOCK_PTR->prev_bb;
      }
  
    new_bb = create_bb (NULL, after_bb);
    create_block_annotation (new_bb);
!   new_edge = make_edge (new_bb, dest, EDGE_FALLTHRU);
  
!   if (!tree_redirect_edge_and_branch_1 (edge_in, new_bb, true))
!     abort ();
  
    /* Find all the PHI arguments on the original edge, and change them to
       the new edge.  */
*************** tree_verify_flow_info (void)
*** 2890,2895 ****
--- 2816,2822 ----
    basic_block bb;
    block_stmt_iterator bsi;
    tree stmt;
+   edge e;
  
    if (ENTRY_BLOCK_PTR->stmt_list)
      {
*************** tree_verify_flow_info (void)
*** 2902,2910 ****
        err = 1;
      }
  
    FOR_EACH_BB (bb)
      {
-       edge e;
        bool found_ctrl_stmt = false;
        tree phi;
        int i;
--- 2829,2843 ----
        err = 1;
      }
  
+   for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next)
+     if (e->flags & EDGE_FALLTHRU)
+       {
+ 	error ("Fallthru to exit from bb %d\n", e->src->index);
+ 	err = 1;
+       }
+ 
    FOR_EACH_BB (bb)
      {
        bool found_ctrl_stmt = false;
        tree phi;
        int i;
*************** tree_verify_flow_info (void)
*** 2998,3012 ****
        if (bsi_end_p (bsi))
  	continue;
  
!       for (e = bb->succ; e; e = e->succ_next)
! 	if (e->flags & EDGE_FALLTHRU && e->dest != bb->next_bb)
! 	  {
! 	    error ("Fallthru edge of bb %d does not point to following block\n", bb->index);
! 	    err = 1;
! 	  }
  
  
-       stmt = bsi_stmt (bsi);
        switch (TREE_CODE (stmt))
  	{
  	case COND_EXPR:
--- 2931,2949 ----
        if (bsi_end_p (bsi))
  	continue;
  
!       stmt = bsi_stmt (bsi);
  
+       if (is_ctrl_stmt (stmt))
+ 	{
+ 	  for (e = bb->succ; e; e = e->succ_next)
+ 	    if (e->flags & EDGE_FALLTHRU)
+ 	      {
+ 		error ("Fallthru edge after a control statement in bb %d \n",
+ 		       bb->index);
+ 		err = 1;
+ 	      }
+ 	}
  
        switch (TREE_CODE (stmt))
  	{
  	case COND_EXPR:
*************** tree_verify_flow_info (void)
*** 3045,3067 ****
  	      }
  	  }
  	  break;
  	case GOTO_EXPR:
  	  if (simple_goto_p (stmt))
  	    {
! 	      if (!bb->succ || bb->succ->succ_next
! 		  || (bb->succ->flags & (EDGE_FALLTHRU | EDGE_ABNORMAL
! 					 | EDGE_TRUE_VALUE | EDGE_FALSE_VALUE)))
! 		{
! 		  error ("Wrong outgoing edge flags at end of bb %d\n", bb->index);
! 		  err = 1;
! 		}
! 	      if (!has_label_p (bb->succ->dest, GOTO_DESTINATION (stmt)))
! 		{
! 		  error ("Label %s does not match edge at end of bb %d\n",
! 			 IDENTIFIER_POINTER (DECL_NAME (stmt)),
! 			 bb->index);
! 		  err = 1;
! 		}
  	    }
  	  else
  	    {
--- 2982,2993 ----
  	      }
  	  }
  	  break;
+ 
  	case GOTO_EXPR:
  	  if (simple_goto_p (stmt))
  	    {
! 	      error ("Explicit goto at end of bb %d\n", bb->index);
!     	      err = 1;
  	    }
  	  else
  	    {
*************** tree_verify_flow_info (void)
*** 3088,3093 ****
--- 3014,3020 ----
  		}
  	    }
  	  break;
+ 
  	case RETURN_EXPR:
  	  if (!bb->succ || bb->succ->succ_next
  	      || (bb->succ->flags & (EDGE_FALLTHRU | EDGE_ABNORMAL
*************** tree_verify_flow_info (void)
*** 3102,3107 ****
--- 3029,3035 ----
  	      err = 1;
  	    }
  	  break;
+ 
  	case SWITCH_EXPR:
  	  {
  	    edge e;
*************** tree_verify_flow_info (void)
*** 3152,3157 ****
--- 3080,3086 ----
  	    for (e = bb->succ; e; e = e->succ_next)
  	      e->dest->aux = (void *)0;
  	  }
+ 
  	default: ;
  	}
      }
*************** tree_forwarder_block_p (basic_block bb)
*** 3326,3333 ****
        return false; 
      }
  
!   /* Now walk through the statements.  We can ignore labels, gotos and
!      empty statements.  Anything else means this is not a forwarder block.  */
    for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
      {
        tree stmt = bsi_stmt (bsi);
--- 3255,3262 ----
        return false; 
      }
  
!   /* Now walk through the statements.  We can ignore labels, anything else
!      means this is not a forwarder block.  */
    for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
      {
        tree stmt = bsi_stmt (bsi);
*************** tree_forwarder_block_p (basic_block bb)
*** 3335,3341 ****
        switch (TREE_CODE (stmt))
  	{
  	case LABEL_EXPR:
- 	case GOTO_EXPR:
  	  break;
  
  	default:
--- 3264,3269 ----
*************** thread_jumps (void)
*** 3357,3363 ****
  {
    edge e, next, last, old;
    basic_block bb, dest, tmp;
!   tree phi, stmt;
    int arg;
    bool retval = false;
  
--- 3285,3291 ----
  {
    edge e, next, last, old;
    basic_block bb, dest, tmp;
!   tree phi;
    int arg;
    bool retval = false;
  
*************** thread_jumps (void)
*** 3374,3391 ****
        if (tree_forwarder_block_p (bb))
  	continue;
        
-       /* Due to limitations of ir, it is difficult to redirect edge except
- 	 in some simple cases.  Given that ir is slowly getting more sane,
- 	 don't invest too much energy into monsters of bsi_insert_on_edge
- 	 type.  */
-       stmt = last_stmt (bb);
-       if (stmt
- 	  && stmt_ends_bb_p (stmt)
- 	  && TREE_CODE (stmt) != GOTO_EXPR
- 	  && TREE_CODE (stmt) != COND_EXPR
- 	  && TREE_CODE (stmt) != SWITCH_EXPR)
- 	continue;
- 
        /* This block is now part of a forwarding path, mark it as not
  	 forwardable so that we can detect loops.   This bit will be
  	 reset below.  */
--- 3302,3307 ----
*************** tree_try_redirect_by_replacing_jump (edg
*** 3519,3525 ****
    edge tmp;
    block_stmt_iterator b;
    tree stmt;
-   int flags;
  
    /* Verify that all targets will be TARGET.  */
    for (tmp = src->succ; tmp; tmp = tmp->succ_next)
--- 3435,3440 ----
*************** tree_try_redirect_by_replacing_jump (edg
*** 3535,3556 ****
    stmt = bsi_stmt (b);
  
    if (TREE_CODE (stmt) == COND_EXPR
!       || TREE_CODE (stmt) == SWITCH_EXPR
!       || (TREE_CODE (stmt) == GOTO_EXPR && target == src->next_bb))
      {
!       if (target == src->next_bb)
! 	{
! 	  flags = EDGE_FALLTHRU;
!           bsi_remove (&b);
! 	}
!       else
! 	{
! 	  flags = 0;
!           stmt = build1 (GOTO_EXPR, void_type_node, tree_block_label (target));
!           bsi_replace (&b, stmt, false);
! 	}
        e = ssa_redirect_edge (e, target);
!       e->flags = flags;
        return e;
      }
  
--- 3450,3460 ----
    stmt = bsi_stmt (b);
  
    if (TREE_CODE (stmt) == COND_EXPR
!       || TREE_CODE (stmt) == SWITCH_EXPR)
      {
!       bsi_remove (&b);
        e = ssa_redirect_edge (e, target);
!       e->flags = EDGE_FALLTHRU;
        return e;
      }
  
*************** tree_redirect_edge_and_branch_1 (edge e,
*** 3581,3589 ****
  
    label = tree_block_label (dest);
  
-   /* If our block does not end with a GOTO, then create one.
-      Otherwise redirect the existing GOTO_EXPR to LABEL.  */
- 
    bsi = bsi_last (bb);
    stmt = bsi_end_p (bsi) ? NULL : bsi_stmt (bsi);
    flags = 0;
--- 3485,3490 ----
*************** tree_redirect_edge_and_branch_1 (edge e,
*** 3595,3606 ****
  	      ? COND_EXPR_THEN (stmt)
  	      : COND_EXPR_ELSE (stmt));
        flags = e->flags;
-       /* FALLTHRU */
- 
-     case GOTO_EXPR:
        GOTO_DESTINATION (stmt) = label;
        break;
  
      case SWITCH_EXPR:
        {
  	tree vec = SWITCH_LABELS (stmt);
--- 3496,3509 ----
  	      ? COND_EXPR_THEN (stmt)
  	      : COND_EXPR_ELSE (stmt));
        flags = e->flags;
        GOTO_DESTINATION (stmt) = label;
        break;
  
+     case GOTO_EXPR:
+       /* No nonabnormal edges should lead from a non-simple goto, and simple
+ 	 ones should be represented implicitly.  */
+       abort ();
+ 
      case SWITCH_EXPR:
        {
  	tree vec = SWITCH_LABELS (stmt);
*************** tree_redirect_edge_and_branch_1 (edge e,
*** 3615,3642 ****
        }
        break;
  
-     case CALL_EXPR:
-     case MODIFY_EXPR:
-       /* If this block ends with a statement that can alter control flow,
- 	 e.g. via throw or longjmp, then we can't just append to the 
- 	 current block.  We have to create a new block just to contain
- 	 the goto statement.  */
-       /* ??? In RTL equivalent we never create new basic blocks here.
- 	 Hopefully this will be just a temporary side case before we switch
- 	 to cfg_layout style mode with no explicit GOTO statements.  */
-       if (is_ctrl_altering_stmt (stmt))
- 	{
- 	  bb = tree_split_edge (e);
- 	  bsi = bsi_last (bb);
- 	  e = bb->succ;
- 	}
-       /* FALLTHRU */
- 
      default:
!       /* Otherwise we can just append a goto to this block.  */
!       stmt = build1 (GOTO_EXPR, void_type_node, label);
!       bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
!       e->flags &= ~EDGE_FALLTHRU;
        break;
      }
  
--- 3518,3528 ----
        }
        break;
  
      default:
!       /* Otherwise it must be a fallthru edge, and we don't need to
! 	 do anything except for redirecting it.  */
!       if (!(e->flags & EDGE_FALLTHRU))
! 	abort ();
        break;
      }
  
*************** tree_redirect_edge_and_branch (edge e, b
*** 3662,3675 ****
  }
  
  /* Simple wrapper as we always can redirect fallthru edges.  */
  static basic_block
  tree_redirect_edge_and_branch_force (edge e, basic_block dest)
  {
-   basic_block old = e->src;
    e = tree_redirect_edge_and_branch (e, dest);
    if (!e)
      abort ();
!   return e->src == old ? NULL : old;
  }
  
  /* Dump FUNCTION_DECL FN to file FILE using FLAGS (see TDF_* in tree.h)  */
--- 3548,3562 ----
  }
  
  /* Simple wrapper as we always can redirect fallthru edges.  */
+ 
  static basic_block
  tree_redirect_edge_and_branch_force (edge e, basic_block dest)
  {
    e = tree_redirect_edge_and_branch (e, dest);
    if (!e)
      abort ();
! 
!   return NULL;
  }
  
  /* Dump FUNCTION_DECL FN to file FILE using FLAGS (see TDF_* in tree.h)  */
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.160
diff -c -3 -p -r1.1.4.160 tree-flow.h
*** tree-flow.h	25 Nov 2003 05:09:08 -0000	1.1.4.160
--- tree-flow.h	29 Nov 2003 20:45:09 -0000
*************** extern void bsi_replace (const block_stm
*** 408,413 ****
--- 408,414 ----
  /* In tree-cfg.c  */
  extern void build_tree_cfg (tree *);
  extern void delete_tree_cfg (void);
+ extern void disband_implicit_edges (void);
  extern bool stmt_ends_bb_p (tree);
  extern bool is_ctrl_stmt (tree);
  extern bool is_ctrl_altering_stmt (tree);
*************** extern void cfg_remove_useless_stmts (vo
*** 436,443 ****
  extern basic_block tree_split_edge (edge);
  extern edge thread_edge (edge, basic_block);
  extern basic_block label_to_block (tree);
! extern bool cleanup_cond_expr_graph (basic_block, block_stmt_iterator);
! extern bool cleanup_switch_expr_graph (basic_block, block_stmt_iterator);
  extern void tree_optimize_tail_calls (void);
  extern basic_block tree_block_forwards_to (basic_block bb);
  extern void bsi_insert_on_edge (edge, tree);
--- 437,443 ----
  extern basic_block tree_split_edge (edge);
  extern edge thread_edge (edge, basic_block);
  extern basic_block label_to_block (tree);
! extern bool cleanup_control_expr_graph (basic_block, block_stmt_iterator);
  extern void tree_optimize_tail_calls (void);
  extern basic_block tree_block_forwards_to (basic_block bb);
  extern void bsi_insert_on_edge (edge, tree);
*************** extern edge ssa_redirect_edge (edge, bas
*** 513,518 ****
--- 513,519 ----
  extern void set_is_used (tree);
  extern bool tree_ssa_useless_type_conversion (tree);
  extern void build_dominator_tree (dominance_info);
+ extern void delete_tree_ssa (void);
  extern unsigned int highest_ssa_version;
  
  /* In tree-ssa-pre.c  */
Index: tree-optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-optimize.c,v
retrieving revision 1.1.4.80
diff -c -3 -p -r1.1.4.80 tree-optimize.c
*** tree-optimize.c	29 Nov 2003 12:43:10 -0000	1.1.4.80
--- tree-optimize.c	29 Nov 2003 20:45:09 -0000
*************** Boston, MA 02111-1307, USA.  */
*** 45,50 ****
--- 45,52 ----
  #include "tree-mudflap.h"
  #include "ggc.h"
  
+ static void tree_ssa_finish (tree *);
+ 
  /* Rewrite a function tree to the SSA form and perform the SSA-based
     optimizations on it.  */
  
*************** optimize_function_tree (tree fndecl, tre
*** 190,207 ****
        sbitmap_free (vars_to_rename);
      }
  
!   /* Re-chain the statements from the blocks.  */
!   {
!     basic_block bb;
  
!     *chain = NULL;
!     FOR_EACH_BB (bb)
        append_to_statement_list_force (bb->stmt_list, chain);
!   }
  
    delete_tree_cfg ();
  }
- 
  
  /* Called to move the SAVE_EXPRs for parameter declarations in a
     nested function into the nested function.  DATA is really the
--- 192,225 ----
        sbitmap_free (vars_to_rename);
      }
  
!   tree_ssa_finish (chain);
! }
! 
! /* Do the actions requiered to finish with tree-ssa optimization
!    passes.  Return the final chain of statements in CHAIN.  */
! 
! static void
! tree_ssa_finish (tree *chain)
! {
!   basic_block bb;
  
!   /* Emit gotos for implicit jumps.  */
!   disband_implicit_edges ();
! 
!   /* Remove the ssa structures.  Do it here since this includes statement
!      annotations that need to be intact during disband_implicit_edges.  */
!   delete_tree_ssa ();
! 
!   /* Re-chain the statements from the blocks.  */
!   *chain = NULL;
!   FOR_EACH_BB (bb)
!     {
        append_to_statement_list_force (bb->stmt_list, chain);
!     }
  
+   /* And get rid of the cfg.  */
    delete_tree_cfg ();
  }
  
  /* Called to move the SAVE_EXPRs for parameter declarations in a
     nested function into the nested function.  DATA is really the
Index: tree-pretty-print.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-pretty-print.c,v
retrieving revision 1.1.2.64
diff -c -3 -p -r1.1.2.64 tree-pretty-print.c
*** tree-pretty-print.c	22 Nov 2003 15:01:38 -0000	1.1.2.64
--- tree-pretty-print.c	29 Nov 2003 20:45:09 -0000
*************** dump_generic_node (pretty_printer *buffe
*** 1281,1286 ****
--- 1281,1287 ----
  		  dump_generic_node (buffer, elt, spc+4, flags, false);
  		  pp_string (buffer, " goto ");
  		  dump_generic_node (buffer, CASE_LABEL (elt), spc+4, flags, true);
+ 		  pp_semicolon (buffer);
  		}
  	    }
  	  newline_and_indent (buffer, spc+2);
*************** dump_phi_nodes (pretty_printer *buffer, 
*** 2144,2149 ****
--- 2145,2182 ----
      }
  }
  
+ /* Dump jump to basic block BB that is represented implicitly in the cfg
+    to BUFFER.  */
+ 
+ static void
+ pp_cfg_jump (pretty_printer *buffer, basic_block bb)
+ {
+   pp_string (buffer, "goto <bb ");
+   pp_decimal_int (buffer, bb->index);
+   pp_string (buffer, ">;");
+ }
+ 
+ /* Dump edges represented implicitly in basic block BB to BUFFER, indented
+    by INDENT spaces, with details given by FLAGS.  */
+ 
+ static void
+ dump_implicit_edges (pretty_printer *buffer, basic_block bb, int indent)
+ {
+   edge e;
+ 
+   /* If there is a fallthru edge, we may need to add an artificial goto to the
+      dump.  */
+   for (e = bb->succ; e; e = e->succ_next)
+     if (e->flags & EDGE_FALLTHRU)
+       break;
+   if (e && e->dest != bb->next_bb)
+     {
+       INDENT (indent);
+       pp_cfg_jump (buffer, e->dest);
+       pp_newline (buffer);
+     }
+ }
+ 
  /* Dumps basic block BB to buffer BUFFER with details described by FLAGS and
     indented by INDENT spaces.  */
  
*************** dump_generic_bb_buff (pretty_printer *bu
*** 2176,2181 ****
--- 2209,2216 ----
        dump_generic_node (buffer, stmt, curr_indent, flags, true);
        pp_newline (buffer);
      }
+ 
+   dump_implicit_edges (buffer, bb, indent);
  
    if (flags & TDF_BLOCKS)
      dump_bb_end (buffer, bb, indent);
Index: tree-ssa-dom.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-dom.c,v
retrieving revision 1.1.2.88
diff -c -3 -p -r1.1.2.88 tree-ssa-dom.c
*** tree-ssa-dom.c	26 Nov 2003 03:22:23 -0000	1.1.2.88
--- tree-ssa-dom.c	29 Nov 2003 20:45:09 -0000
*************** thread_jumps_walk_stmts (struct dom_walk
*** 1159,1170 ****
  	  if (TREE_CODE (stmt) == COND_EXPR)
  	    {
  	      COND_EXPR_COND (stmt) = cached_lhs;
! 	      cfg_altered = cleanup_cond_expr_graph (bb, si);
  	    }
  	  else if (TREE_CODE (stmt) == SWITCH_EXPR)
  	    {
  	      SWITCH_COND (stmt) = cached_lhs;
! 	      cfg_altered = cleanup_switch_expr_graph (bb, si);
  	    }
  
  	  continue;
--- 1159,1170 ----
  	  if (TREE_CODE (stmt) == COND_EXPR)
  	    {
  	      COND_EXPR_COND (stmt) = cached_lhs;
! 	      cfg_altered = cleanup_control_expr_graph (bb, si);
  	    }
  	  else if (TREE_CODE (stmt) == SWITCH_EXPR)
  	    {
  	      SWITCH_COND (stmt) = cached_lhs;
! 	      cfg_altered = cleanup_control_expr_graph (bb, si);
  	    }
  
  	  continue;
*************** optimize_stmt (block_stmt_iterator si,
*** 2291,2301 ****
       etc.  */
    if (ann->modified)
      {
!       if (TREE_CODE (stmt) == COND_EXPR)
! 	cfg_altered |= cleanup_cond_expr_graph (bb_for_stmt (stmt), si);
! 
!       if (TREE_CODE (stmt) == SWITCH_EXPR)
! 	cfg_altered |= cleanup_switch_expr_graph (bb_for_stmt (stmt), si);
      }
                                                                                  
    return may_have_exposed_new_symbols;
--- 2291,2299 ----
       etc.  */
    if (ann->modified)
      {
!       if (TREE_CODE (stmt) == COND_EXPR
! 	  || TREE_CODE (stmt) == SWITCH_EXPR)
! 	cfg_altered |= cleanup_control_expr_graph (bb_for_stmt (stmt), si);
      }
                                                                                  
    return may_have_exposed_new_symbols;
Index: tree-ssa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa.c,v
retrieving revision 1.1.4.168
diff -c -3 -p -r1.1.4.168 tree-ssa.c
*** tree-ssa.c	28 Nov 2003 15:38:47 -0000	1.1.4.168
--- tree-ssa.c	29 Nov 2003 20:45:09 -0000
*************** static void rewrite_initialize_block (st
*** 179,185 ****
  static void rewrite_walk_stmts (struct dom_walk_data *, basic_block, tree);
  static void rewrite_add_phi_arguments (struct dom_walk_data *,
  				       basic_block, tree);
- static void delete_tree_ssa (void);
  static void mark_def_sites (struct dom_walk_data *walk_data,
  			    basic_block bb,
  			    tree parent_block_last_stmt ATTRIBUTE_UNUSED);
--- 179,184 ----
*************** rewrite_out_of_ssa (tree fndecl, enum tr
*** 2628,2634 ****
      }
  
    /* Flush out flow graph and SSA data.  */
-   delete_tree_ssa ();
    delete_var_map (map);
    timevar_pop (TV_TREE_SSA_TO_NORMAL);
  }
--- 2627,2632 ----
*************** init_tree_ssa (void)
*** 2964,2970 ****
  
  /* Deallocate memory associated with SSA data structures for FNDECL.  */
  
! static void
  delete_tree_ssa (void)
  {
    size_t i;
--- 2962,2968 ----
  
  /* Deallocate memory associated with SSA data structures for FNDECL.  */
  
! void
  delete_tree_ssa (void)
  {
    size_t i;
*************** delete_tree_ssa (void)
*** 2977,2988 ****
        bsi_stmt (bsi)->common.ann = NULL;
  
    /* Remove annotations from every referenced variable.  */
!   for (i = 0; i < num_referenced_vars; i++)
!     referenced_var (i)->common.ann = NULL;
  
    fini_ssanames ();
  
-   referenced_vars = NULL;
    global_var = NULL_TREE;
    call_clobbered_vars = NULL;
  }
--- 2975,2989 ----
        bsi_stmt (bsi)->common.ann = NULL;
  
    /* Remove annotations from every referenced variable.  */
!   if (referenced_vars)
!     {
!       for (i = 0; i < num_referenced_vars; i++)
! 	referenced_var (i)->common.ann = NULL;
!       referenced_vars = NULL;
!     }
  
    fini_ssanames ();
  
    global_var = NULL_TREE;
    call_clobbered_vars = NULL;
  }


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