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] COND_EXPR lowering


Hello,

here is the updated version of the patch.  To make it bootstrap you need
the attached hack (it workarounds the recently discussed problem with
gc x bb annotations).  It causes several new test failures wrto clean
tree-ssa, mostly bogus line numbers in warnings; I will investigate
tomorrow.

Zdenek

Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.903.2.118
diff -c -3 -p -r1.903.2.118 Makefile.in
*** Makefile.in	6 Oct 2003 17:36:03 -0000	1.903.2.118
--- Makefile.in	8 Oct 2003 22:36:19 -0000
*************** OBJS-common = \
*** 866,872 ****
   tree-alias-type.o gimplify.o tree-nomudflap.o tree-pretty-print.o         \
   tree-alias-common.o tree-ssa-ccp.o tree-browser.o @ANDER@ tree-ssa-dce.o  \
   tree-ssa-pre.o tree-ssa-copyprop.o tree-ssa-live.o tree-must-alias.o	   \
!  tree-ssa-dom.o								   \
   alias.o bb-reorder.o bitmap.o builtins.o caller-save.o calls.o	  	   \
   cfg.o cfganal.o cfgbuild.o cfgcleanup.o cfglayout.o cfgloop.o		   \
   cfgloopanal.o cfgloopmanip.o loop-init.o loop-unswitch.o loop-unroll.o	   \
--- 866,872 ----
   tree-alias-type.o gimplify.o tree-nomudflap.o tree-pretty-print.o         \
   tree-alias-common.o tree-ssa-ccp.o tree-browser.o @ANDER@ tree-ssa-dce.o  \
   tree-ssa-pre.o tree-ssa-copyprop.o tree-ssa-live.o tree-must-alias.o	   \
!  tree-ssa-dom.o gimple-low.o						   \
   alias.o bb-reorder.o bitmap.o builtins.o caller-save.o calls.o	  	   \
   cfg.o cfganal.o cfgbuild.o cfgcleanup.o cfglayout.o cfgloop.o		   \
   cfgloopanal.o cfgloopmanip.o loop-init.o loop-unswitch.o loop-unroll.o	   \
*************** c-simplify.o : c-simplify.c $(CONFIG_H) 
*** 1566,1571 ****
--- 1566,1575 ----
     langhooks.h toplev.h rtl.h $(TREE_FLOW_H) langhooks-def.h \
     $(TM_H) coretypes.h $(C_PRETTY_PRINT_H)
  gimplify.o : gimplify.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) errors.h \
+    diagnostic.h $(TREE_SIMPLE_H) tree-inline.h varray.h langhooks.h \
+    langhooks-def.h $(TREE_FLOW_H) $(TIMEVAR_H) $(TM_H) coretypes.h except.h \
+    flags.h $(RTL_H)
+ gimple-low.o : gimple-low.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) errors.h \
     diagnostic.h $(TREE_SIMPLE_H) tree-inline.h varray.h langhooks.h \
     langhooks-def.h $(TREE_FLOW_H) $(TIMEVAR_H) $(TM_H) coretypes.h except.h \
     flags.h $(RTL_H)
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.173
diff -c -3 -p -r1.1.4.173 tree-cfg.c
*** tree-cfg.c	6 Oct 2003 14:34:25 -0000	1.1.4.173
--- tree-cfg.c	8 Oct 2003 22:36:19 -0000
*************** static void create_block_annotation (bas
*** 80,86 ****
  static void free_blocks_annotations (void);
  static void clear_blocks_annotations (void);
  static basic_block make_blocks (tree *, tree, tree, basic_block, tree);
- static void make_cond_expr_blocks (tree *, tree, basic_block, tree);
  static void make_switch_expr_blocks (tree *, tree, basic_block, tree);
  static basic_block make_bind_expr_blocks (tree *, tree, basic_block, tree,
  					  tree);
--- 80,85 ----
*************** static int tree_verify_flow_info (void);
*** 108,113 ****
--- 107,114 ----
  static basic_block tree_make_forwarder_block (basic_block, int, int, edge, int);
  static struct loops *tree_loop_optimizer_init (FILE *);
  static void tree_loop_optimizer_finalize (struct loops *, FILE *);
+ static void thread_jumps (void);
+ static bool tree_forwarder_block_p (basic_block);
  
  /* Flowgraph optimization and cleanup.  */
  
*************** static void disconnect_unreachable_case_
*** 130,140 ****
  static edge find_taken_edge_cond_expr (basic_block, tree);
  static edge find_taken_edge_switch_expr (basic_block, tree);
  static bool value_matches_some_label (edge, tree, edge *);
- static void linearize_control_structures (void);
- static bool linearize_cond_expr (tree *, basic_block);
  static void replace_stmt (tree *, tree *);
  static void move_outgoing_edges (basic_block, basic_block);
! static void merge_tree_blocks (basic_block, basic_block);
  static bool remap_stmts (basic_block, basic_block, tree *);
  static tree *handle_switch_split (basic_block, basic_block);
  static tree *handle_switch_fallthru (tree, basic_block, basic_block);
--- 131,140 ----
  static edge find_taken_edge_cond_expr (basic_block, tree);
  static edge find_taken_edge_switch_expr (basic_block, tree);
  static bool value_matches_some_label (edge, tree, edge *);
  static void replace_stmt (tree *, tree *);
  static void move_outgoing_edges (basic_block, basic_block);
! static void merge_tree_blocks (basic_block, basic_block) ATTRIBUTE_UNUSED;
! static int phi_alternatives_equal (basic_block, edge, edge);
  static bool remap_stmts (basic_block, basic_block, tree *);
  static tree *handle_switch_split (basic_block, basic_block);
  static tree *handle_switch_fallthru (tree, basic_block, basic_block);
*************** enum find_location_action {
*** 154,160 ****
    EDGE_INSERT_LOCATION_AFTER,
    EDGE_INSERT_LOCATION_THEN,
    EDGE_INSERT_LOCATION_ELSE,
-   EDGE_INSERT_LOCATION_NEW_ELSE,
    EDGE_INSERT_LOCATION_BSI_AFTER };
  
  static tree_stmt_iterator find_insert_location
--- 154,159 ----
*************** make_blocks (tree *first_p, tree next_bl
*** 419,427 ****
        append_stmt_to_bb (stmt_p, bb, parent_stmt);
        get_stmt_ann (stmt)->scope = scope;
  
!       if (code == COND_EXPR)
! 	make_cond_expr_blocks (stmt_p, next_block_link, bb, scope);
!       else if (code == SWITCH_EXPR)
  	make_switch_expr_blocks (stmt_p, next_block_link, bb, scope);
        else if (code == BIND_EXPR)
  	{
--- 418,424 ----
        append_stmt_to_bb (stmt_p, bb, parent_stmt);
        get_stmt_ann (stmt)->scope = scope;
  
!       if (code == SWITCH_EXPR)
  	make_switch_expr_blocks (stmt_p, next_block_link, bb, scope);
        else if (code == BIND_EXPR)
  	{
*************** make_blocks (tree *first_p, tree next_bl
*** 502,542 ****
    return NULL;
  }
  
- /* Create the blocks for the COND_EXPR node pointed by COND_P.
- 
-    NEXT_BLOCK_LINK is the first statement of the successor basic block for
-       the block holding *COND_P.  If *COND_P is the last statement inside a
-       lexical scope, this will be the statement that comes after COND_P's
-       container (see the documentation for NEXT_BLOCK_LINK).
- 
-    ENTRY is the block whose last statement is *COND_P.
-    
-    SCOPE is the BIND_EXPR node holding *COND_P.  */
- 
- static void
- make_cond_expr_blocks (tree *cond_p, tree next_block_link,
- 		       basic_block entry, tree scope)
- {
-   tree_stmt_iterator si;
-   tree cond = *cond_p;
-   entry->flags |= BB_CONTROL_STRUCTURE;
- 
-   /* Determine NEXT_BLOCK_LINK for statements inside the COND_EXPR body.  */
-   si = tsi_start (cond_p);
-   tsi_next (&si);
- 
-   /* Ignore any empty statements at the tail of this tree.  */
-   while (!tsi_end_p (si) && tsi_stmt (si) == NULL)
-     tsi_next (&si);
- 
-   if (!tsi_end_p (si) && tsi_stmt (si) != NULL_TREE)
-     next_block_link = *(tsi_container (si));
- 
-   STRIP_CONTAINERS (cond);
-   make_blocks (&COND_EXPR_THEN (cond), next_block_link, cond, NULL, scope);
-   make_blocks (&COND_EXPR_ELSE (cond), next_block_link, cond, NULL, scope);
- }
- 
  /* Create the blocks for the SWITCH_EXPR node pointed by SWITCH_E_P.
  
     NEXT_BLOCK_LINK is the first statement of the successor basic block for
--- 499,504 ----
*************** make_switch_expr_blocks (tree *switch_e_
*** 556,562 ****
    tree switch_e = *switch_e_p;
    entry->flags |= BB_CONTROL_STRUCTURE;
  
!   /* Determine NEXT_BLOCK_LINK for statements inside the COND_EXPR body.  */
    si = tsi_start (switch_e_p);
    tsi_next (&si);
  
--- 518,524 ----
    tree switch_e = *switch_e_p;
    entry->flags |= BB_CONTROL_STRUCTURE;
  
!   /* Determine NEXT_BLOCK_LINK for statements inside the SWITCH_EXPR body.  */
    si = tsi_start (switch_e_p);
    tsi_next (&si);
  
*************** set_parent_stmt (tree *stmt_p, tree pare
*** 630,635 ****
--- 592,601 ----
  {
    tree t;
  
+   if (parent_stmt
+       && TREE_CODE (parent_stmt) == COND_EXPR)
+     abort ();
+ 
    /* Associate *STMT_P (and the trees it contains) to its control parent.  */
    t = *stmt_p;
    do
*************** find_contained_blocks (tree *stmt_p, bit
*** 807,818 ****
  
        /* And recurse down into control structures.  */
        code = TREE_CODE (stmt);
!       if (code == COND_EXPR)
! 	{
! 	  find_contained_blocks (&COND_EXPR_THEN (stmt), my_blocks, last_p);
! 	  find_contained_blocks (&COND_EXPR_ELSE (stmt), my_blocks, last_p);
! 	}
!       else if (code == CATCH_EXPR)
  	{
  	  find_contained_blocks (&CATCH_BODY (stmt), my_blocks, last_p);
  	}
--- 773,779 ----
  
        /* And recurse down into control structures.  */
        code = TREE_CODE (stmt);
!       if (code == CATCH_EXPR)
  	{
  	  find_contained_blocks (&CATCH_BODY (stmt), my_blocks, last_p);
  	}
*************** static void
*** 981,987 ****
  make_cond_expr_edges (basic_block bb)
  {
    tree entry = last_stmt (bb);
!   basic_block successor_bb, then_bb, else_bb;
  
  #if defined ENABLE_CHECKING
    if (entry == NULL_TREE || TREE_CODE (entry) != COND_EXPR)
--- 942,949 ----
  make_cond_expr_edges (basic_block bb)
  {
    tree entry = last_stmt (bb);
!   basic_block then_bb, else_bb;
!   tree then_label, else_label;
  
  #if defined ENABLE_CHECKING
    if (entry == NULL_TREE || TREE_CODE (entry) != COND_EXPR)
*************** make_cond_expr_edges (basic_block bb)
*** 989,1008 ****
  #endif
  
    /* Entry basic blocks for each component.  */
!   then_bb = bb_for_stmt (COND_EXPR_THEN (entry));
!   else_bb = bb_for_stmt (COND_EXPR_ELSE (entry));
!   successor_bb = successor_block (bb);
! 
!   if (then_bb)
!     make_edge (bb, then_bb, EDGE_TRUE_VALUE);
! 
!   if (else_bb)
!     make_edge (bb, else_bb, EDGE_FALSE_VALUE);
! 
!   /* If conditional is missing one of the clauses, make an edge between the
!      entry block and the first block outside the conditional.  */
!   if (!then_bb || !else_bb)
!     make_edge (bb, successor_bb, 0);
  }
  
  basic_block
--- 951,963 ----
  #endif
  
    /* Entry basic blocks for each component.  */
!   then_label = GOTO_DESTINATION (COND_EXPR_THEN (entry));
!   else_label = GOTO_DESTINATION (COND_EXPR_ELSE (entry));
!   then_bb = VARRAY_BB (label_to_block_map, LABEL_DECL_INDEX (then_label));
!   else_bb = VARRAY_BB (label_to_block_map, LABEL_DECL_INDEX (else_label));
! 
!   make_edge (bb, then_bb, EDGE_TRUE_VALUE);
!   make_edge (bb, else_bb, EDGE_FALSE_VALUE);
  }
  
  basic_block
*************** make_goto_expr_edges (basic_block bb)
*** 1054,1079 ****
       in the CFG.  */
    FOR_EACH_BB (target_bb)
      {
!       tree target = first_stmt (target_bb);
  
!       if (target == NULL_TREE)
!         continue;
  
!       /* Computed GOTOs.  Make an edge to every label block that has
! 	 been marked as a potential target for a computed goto.  */
!       if (TREE_CODE (dest) != LABEL_DECL
! 	       && TREE_CODE (target) == LABEL_EXPR
! 	       && FORCED_LABEL (LABEL_EXPR_LABEL (target))
! 	       && for_call == 0)
! 	make_edge (bb, target_bb, edge_flags);
! 
!       /* Nonlocal GOTO target.  Make an edge to every label block that has
! 	 been marked as a potential target for a nonlocal goto.  */
!       else if (TREE_CODE (dest) != LABEL_DECL
! 	       && TREE_CODE (target) == LABEL_EXPR
! 	       && NONLOCAL_LABEL (LABEL_EXPR_LABEL (target))
! 	       && for_call == 1)
! 	make_edge (bb, target_bb, edge_flags);
      }
  }
  
--- 1009,1039 ----
       in the CFG.  */
    FOR_EACH_BB (target_bb)
      {
!       block_stmt_iterator bsi;
  
!       for (bsi = bsi_start (target_bb); !bsi_end_p (bsi); bsi_next (&bsi))
! 	{
! 	  tree target = bsi_stmt (bsi);
! 
! 	  if (TREE_CODE (target) != LABEL_EXPR)
! 	    break;
  
! 	  /* Computed GOTOs.  Make an edge to every label block that has
! 	     been marked as a potential target for a computed goto.  */
! 	  if (TREE_CODE (dest) != LABEL_DECL
! 	      && TREE_CODE (target) == LABEL_EXPR
! 	      && FORCED_LABEL (LABEL_EXPR_LABEL (target))
! 	      && for_call == 0)
! 	    make_edge (bb, target_bb, edge_flags);
! 
! 	  /* Nonlocal GOTO target.  Make an edge to every label block that has
! 	     been marked as a potential target for a nonlocal goto.  */
! 	  else if (TREE_CODE (dest) != LABEL_DECL
! 		   && TREE_CODE (target) == LABEL_EXPR
! 		   && NONLOCAL_LABEL (LABEL_EXPR_LABEL (target))
! 		   && for_call == 1)
! 	    make_edge (bb, target_bb, edge_flags);
! 	}
      }
  }
  
*************** cleanup_tree_cfg (void)
*** 1111,1118 ****
    pdom_info = NULL;
  
    cleanup_control_flow ();
    remove_unreachable_blocks ();
-   linearize_control_structures ();
    if (pdom_info != NULL)
      {
        free_dominance_info (pdom_info);
--- 1071,1079 ----
    pdom_info = NULL;
  
    cleanup_control_flow ();
+   thread_jumps ();
+   cleanup_control_flow ();
    remove_unreachable_blocks ();
    if (pdom_info != NULL)
      {
        free_dominance_info (pdom_info);
*************** cleanup_tree_cfg (void)
*** 1130,1135 ****
--- 1091,1099 ----
  	clear_dom_children (bb);
      }
  
+ #ifdef ENABLE_CHECKING
+   verify_flow_info ();
+ #endif
    timevar_pop (TV_TREE_CLEANUP_CFG);
  }
  
*************** remove_unreachable_block (basic_block bb
*** 1644,1652 ****
  
  	     So cleanup any variable references in toplevel control
  	     structures.  This may or may not be sufficient.  */
! 	  if (TREE_CODE (*last_p) == COND_EXPR)
! 	    COND_EXPR_COND (*last_p) = integer_zero_node;
! 	  else if (TREE_CODE (*last_p) == SWITCH_EXPR)
  	    SWITCH_COND (*last_p) = integer_zero_node;
  	  remove_bb (bb, REMOVE_NON_CONTROL_STRUCTS);
  	}
--- 1608,1614 ----
  
  	     So cleanup any variable references in toplevel control
  	     structures.  This may or may not be sufficient.  */
! 	  if (TREE_CODE (*last_p) == SWITCH_EXPR)
  	    SWITCH_COND (*last_p) = integer_zero_node;
  	  remove_bb (bb, REMOVE_NON_CONTROL_STRUCTS);
  	}
*************** bsi_replace (block_stmt_iterator bsi, tr
*** 1885,1892 ****
    modify_stmt (bsi_stmt (bsi));
  }
  
- 
- 
  /* Remove statement *STMT_P.
  
     Update all references associated with it.  Note that this function will
--- 1847,1852 ----
*************** cleanup_control_flow (void)
*** 2008,2025 ****
    basic_block bb;
  
    FOR_EACH_BB (bb)
!     if (bb->flags & BB_CONTROL_STRUCTURE)
!       {
! 	tree last = last_stmt (bb);
! 	if (last)
! 	  {
! 	    enum tree_code code = TREE_CODE (last);
! 	    if (code == COND_EXPR)
! 	      cleanup_cond_expr_graph (bb);
! 	    else if (code == SWITCH_EXPR)
! 	      cleanup_switch_expr_graph (bb);
! 	  }
!       }
  }
  
  
--- 1968,1984 ----
    basic_block bb;
  
    FOR_EACH_BB (bb)
!     {
!       tree last = last_stmt (bb);
!       if (last)
! 	{
! 	  enum tree_code code = TREE_CODE (last);
! 	  if (code == COND_EXPR)
! 	    cleanup_cond_expr_graph (bb);
! 	  else if (code == SWITCH_EXPR)
! 	    cleanup_switch_expr_graph (bb);
! 	}
!     }
  }
  
  
*************** cleanup_cond_expr_graph (basic_block bb)
*** 2035,2048 ****
    tree cond_expr = last_stmt (bb);
    tree val;
    edge taken_edge;
  
  #if defined ENABLE_CHECKING
!   if (cond_expr == NULL_TREE || TREE_CODE (cond_expr) != COND_EXPR)
      abort ();
  #endif
  
!   val = COND_EXPR_COND (cond_expr);
!   taken_edge = find_taken_edge (bb, val);
    if (taken_edge)
      {
        edge e, next;
--- 1994,2016 ----
    tree cond_expr = last_stmt (bb);
    tree val;
    edge taken_edge;
+   block_stmt_iterator 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)
!     {
!       val = COND_EXPR_COND (cond_expr);
!       taken_edge = find_taken_edge (bb, val);
!     }
!   else
!     taken_edge = bb->succ;
! 
    if (taken_edge)
      {
        edge e, next;
*************** cleanup_cond_expr_graph (basic_block bb)
*** 2054,2059 ****
--- 2022,2035 ----
  	  if (e != taken_edge)
  	    ssa_remove_edge (e);
  	}
+ 
+       bsi = bsi_last (bb);
+       if (taken_edge->flags & EDGE_TRUE_VALUE)
+ 	bsi_replace (bsi, COND_EXPR_THEN (cond_expr));
+       else if (taken_edge->flags & EDGE_FALSE_VALUE)
+ 	bsi_replace (bsi, COND_EXPR_ELSE (cond_expr));
+       else
+ 	abort ();
      }
  }
  
*************** find_taken_edge (basic_block bb, tree va
*** 2150,2156 ****
    stmt = last_stmt (bb);
  
  #if defined ENABLE_CHECKING
!   if (stmt == NULL_TREE || !is_ctrl_structure (stmt))
      abort ();
  #endif
  
--- 2126,2132 ----
    stmt = last_stmt (bb);
  
  #if defined ENABLE_CHECKING
!   if (stmt == NULL_TREE || !is_ctrl_stmt (stmt))
      abort ();
  #endif
  
*************** find_taken_edge_cond_expr (basic_block b
*** 2195,2203 ****
  	|| ((e->flags & EDGE_FALSE_VALUE) && always_false))
        return e;
  
!   /* If E is not going to the THEN nor the ELSE clause, then it's
!      the fallthru edge to the successor block of the if() block.  */
!   return find_edge (bb, successor_block (bb));
  }
  
  
--- 2171,2178 ----
  	|| ((e->flags & EDGE_FALSE_VALUE) && always_false))
        return e;
  
!   /* There always should be an edge that is taken.  */
!   abort ();
  }
  
  
*************** value_matches_some_label (edge dest_edge
*** 2279,2456 ****
    return false;
  }
  
! 
! /* Convert control structures into linear code whenever possible.  */
! 
! static void
! linearize_control_structures (void)
! {
!   basic_block bb;
! 
!   FOR_EACH_BB (bb)
!     {
!       tree *entry_p;
! 
!       if (!(bb->flags & BB_CONTROL_STRUCTURE))
! 	continue;
! 
!       /* After converting the current COND_EXPR into straight line code it
! 	 may happen that the block that was merged into BB also ends in a
! 	 COND_EXPR (nested conditionals).  Therefore, we need to iterate
! 	 until we either fail to linearize the conditional or BB ends in
! 	 something other than a conditional.  */
!       entry_p = last_stmt_ptr (bb);
!       while (entry_p
! 	     && TREE_CODE (*entry_p) == COND_EXPR
! 	     && linearize_cond_expr (entry_p, bb))
! 	entry_p = last_stmt_ptr (bb);
!     }
! }
! 
! /* If all the phi nodes in PHI have alternatives for BB1 and BB2 and
     those alterantives are equal in each of the PHI nodes, then return
     nonzero, else return zero.  */
  
  static int
! phi_alternatives_equal (tree phi, basic_block bb1, basic_block bb2)
  {
!   /* Walk through each PHI nodes on the chain.  */
!   for ( ; phi ; phi = TREE_CHAIN (phi))
      {
!       int i;
!       tree val1 = NULL;
!       tree val2 = NULL;
  
!       /* Find the alterantive associated with BB1 and BB2.  Quit when we
! 	 have found both or we exhaust the alternatives.  */
!       for (i = 0; i < PHI_NUM_ARGS (phi); i++)
! 	{
! 	  if (PHI_ARG_EDGE (phi, i)->src == bb1)
! 	    val1 = PHI_ARG_DEF (phi, i);
! 	  if (PHI_ARG_EDGE (phi, i)->src == bb2)
! 	    val2 = PHI_ARG_DEF (phi, i);
  
! 	  if (val1 && val2)
! 	    break;
! 	}
  
!       /* If we exhaused the alternatives or the alternatives found are
! 	 not equal, then return false.  */
!       if (i == PHI_NUM_ARGS (phi)
! 	  || ! operand_equal_p (val1, val2, 0))
  	return false;
      }
  
    return true;
  }
  
- /* Convert conditional expressions of the form 'if (1)' and 'if (0)' into
-    straight line code.  ENTRY_P is a pointer to the COND_EXPR statement to
-    check.  Return true if the conditional was modified.  */
- 
- static bool
- linearize_cond_expr (tree *entry_p, basic_block bb)
- {
-   basic_block pdom_bb;
-   tree entry = *entry_p;
-   tree pred = COND_EXPR_COND (entry);
-   tree then_clause = COND_EXPR_THEN (entry);
-   tree else_clause = COND_EXPR_ELSE (entry);
-   basic_block then_block = bb_for_stmt (then_clause);
-   basic_block else_block = bb_for_stmt (else_clause);
-   int always_true = (simple_cst_equal (pred, integer_one_node) == 1);
-   int always_false = (simple_cst_equal (pred, integer_zero_node) == 1);
- 
-   /* Remove the conditional if both branches have been removed.  */
-   if (body_is_empty (then_clause) && body_is_empty (else_clause))
-     {
-       /* Calculate dominance info, if it hasn't been computed yet.  */
-       if (pdom_info == NULL)
- 	pdom_info = calculate_dominance_info (CDI_POST_DOMINATORS);
-       pdom_bb = get_immediate_dominator (pdom_info, bb);
- 
-       /* If there is no post dominator, or the post dominator has no
- 	 PHI nodes, or the PHI node alternatives are equal, then we
- 	 can eliminate this conditional.  */
-       if (!pdom_bb
- 	  || !phi_nodes (pdom_bb)
- 	  || phi_alternatives_equal (phi_nodes (pdom_bb),
- 				     then_block, else_block))
-         {
- 	  /* While neither arm of the conditional has any code, there
- 	     may still be important edges attached to those arms such
- 	     as the backedge in a loop, or exception handling related
- 	     edges (the common characteristic is they are edges implied
- 	     by control structures which are not explicitly represented
- 	     in the IL).  */
- 	  if ((always_true || ! always_false) && then_block)
- 	    move_outgoing_edges (bb, then_block);
- 
- 	  if ((always_false || ! always_true) && else_block)
- 	    move_outgoing_edges (bb, else_block);
- 
- 	  /* Now that we've moved all the edges, go ahead and remove
- 	     the disconnected blocks.  Note this will remove any edges
- 	     from BB to the disconnected blocks.  */
- 	  if (then_block)
- 	    remove_bb (then_block, REMOVE_NO_STMTS);
- 	  if (else_block)
- 	    remove_bb (else_block, REMOVE_NO_STMTS);
- 
- 	  /* And finally remove the useless statement.  */
- 	  remove_stmt (entry_p, true);
- 	  return true;
- 	}
-     }
- 
-   /* There should be no other entry edges into the branches, otherwise
-      merging the blocks would be an error.  */
-   if ((then_block && then_block->pred->pred_next)
-       || (else_block && else_block->pred->pred_next))
-     return false;
-   
-   /* Linearize 'if (1)'.  */
-   if (always_true && body_is_empty (else_clause))
-     {
-       /* If there is no THEN_CLAUSE, remove the conditional.  */
-       if (body_is_empty (then_clause))
- 	{
- 	  if (then_block)
- 	    {
- 	      move_outgoing_edges (bb, then_block);
- 	      remove_bb (then_block, REMOVE_NO_STMTS);
- 	    }
- 	  remove_stmt (entry_p, true);
- 	}
-       else
- 	merge_tree_blocks (bb, bb_for_stmt (then_clause));
- 
-       return true;
-     }
- 
-   /* Linearize 'if (0)'.  */
-   if (always_false && body_is_empty (then_clause))
-     {
-       /* If there is no ELSE_CLAUSE, remove the conditional.  */
-       if (body_is_empty (else_clause))
- 	{
- 	  if (else_block)
- 	    {
- 	      move_outgoing_edges (bb, else_block);
- 	      remove_bb (else_block, REMOVE_NO_STMTS);
- 	    }
- 	  remove_stmt (entry_p, true);
- 	}
-       else
- 	merge_tree_blocks (bb, bb_for_stmt (else_clause));
- 
-       return true;
-     }
- 
-   return false;
- }
- 
- 
  /*---------------------------------------------------------------------------
  			 Code insertion and replacement
  ---------------------------------------------------------------------------*/
--- 2254,2289 ----
    return false;
  }
  
! /* If all the phi nodes in DEST have alternatives for E1 and E2 and
     those alterantives are equal in each of the PHI nodes, then return
     nonzero, else return zero.  */
  
  static int
! phi_alternatives_equal (basic_block dest, edge e1, edge e2)
  {
!   tree phi, val1, val2;
!   int n1, n2;
! 
!   for (phi = phi_nodes (dest); phi; phi = TREE_CHAIN (phi))
      {
!       n1 = phi_arg_from_edge (phi, e1);
!       n2 = phi_arg_from_edge (phi, e2);
  
! #ifdef ENABLE_CHECKING
!       if (n1 < 0 || n2 < 0)
! 	abort ();
! #endif
  
!       val1 = PHI_ARG_DEF (phi, n1);
!       val2 = PHI_ARG_DEF (phi, n2);
  
!       if (!operand_equal_p (val1, val2, false))
  	return false;
      }
  
    return true;
  }
  
  /*---------------------------------------------------------------------------
  			 Code insertion and replacement
  ---------------------------------------------------------------------------*/
*************** is_ctrl_structure (tree t)
*** 2827,2834 ****
      abort ();
  #endif
  
!   return (TREE_CODE (t) == COND_EXPR
! 	  || TREE_CODE (t) == CATCH_EXPR
  	  || TREE_CODE (t) == EH_FILTER_EXPR
  	  || TREE_CODE (t) == TRY_CATCH_EXPR
  	  || TREE_CODE (t) == TRY_FINALLY_EXPR
--- 2660,2666 ----
      abort ();
  #endif
  
!   return (TREE_CODE (t) == CATCH_EXPR
  	  || TREE_CODE (t) == EH_FILTER_EXPR
  	  || TREE_CODE (t) == TRY_CATCH_EXPR
  	  || TREE_CODE (t) == TRY_FINALLY_EXPR
*************** bool
*** 2841,2846 ****
--- 2673,2679 ----
  is_ctrl_stmt (tree t)
  {
    return (is_ctrl_structure (t)
+ 	  || TREE_CODE (t) == COND_EXPR
  	  || TREE_CODE (t) == GOTO_EXPR
  	  || TREE_CODE (t) == RETURN_EXPR
  	  || TREE_CODE (t) == RESX_EXPR);
*************** bsi_insert_before (block_stmt_iterator *
*** 3593,3622 ****
    tsi_link_before (&inserted_tsi, t, TSI_NEW_STMT);
    add_stmt_to_bb (tsi_container (inserted_tsi), curr_bb, parent);
  
-   if (curr_container == curr_bb->head_tree_p)
-     {
-       curr_bb->head_tree_p = tsi_container (inserted_tsi);
-       /* If the parent block is a COND_EXPR, check if this
- 	 is the block which they point to and update if necessary.  */
-       if (parent)
-         {
- 	  tree insert_container = *tsi_container (inserted_tsi);
- 	  switch (TREE_CODE (parent))
- 	    {
- 	      case COND_EXPR:
- 		if (bb_for_stmt (COND_EXPR_THEN (parent)) == curr_bb)
- 		  COND_EXPR_THEN (parent) = insert_container;
- 		else
- 		  if (bb_for_stmt (COND_EXPR_ELSE (parent)) == curr_bb)
- 		    COND_EXPR_ELSE (parent) = insert_container;
- 		break;
- 
- 	      default:
- 		break;
- 	    }
- 	}
-     }
- 
    same_tsi = inserted_tsi;
    tsi_next (&same_tsi);
  
--- 3426,3431 ----
*************** find_insert_location (basic_block src, b
*** 3885,3890 ****
--- 3694,3700 ----
  {
    block_stmt_iterator bsi;
    tree *ret, stmt;
+   edge e;
  
    *location = EDGE_INSERT_LOCATION_BEFORE;
    bsi = bsi_last (src);
*************** find_insert_location (basic_block src, b
*** 3894,3924 ****
        switch (TREE_CODE (stmt))
  	{
  	  case COND_EXPR:
! 	    /* If the ELSE block is non-existant, and this is an edge from the
! 	       COND_EXPR to a block other than the THEN block, then we create
! 	       a new ELSE clause.  */
! 	    if (bb_for_stmt (COND_EXPR_ELSE (stmt)) == NULL)
! 	      if (bb_for_stmt (COND_EXPR_THEN (stmt)) != dest)
! 		{
! 		  ret = &COND_EXPR_ELSE (stmt);
! 		  *location = EDGE_INSERT_LOCATION_NEW_ELSE;
! 		  break;
! 		}
  
! 	    /* It must be an edge from the COND_EXPR to either the THEN or
! 	       ELSE block. We will need to insert a new stmt in front of the
! 	       first stmt in the block, *and* update the pointer to the
! 	       THEN or ELSE clause.  */
! 	    if (bb_for_stmt (COND_EXPR_THEN (stmt)) == dest)
! 	      {
! 		ret = &COND_EXPR_THEN (stmt);
! 		*location = EDGE_INSERT_LOCATION_THEN;
! 	      }
  	    else
! 	      {
! 		ret = &COND_EXPR_ELSE (stmt);
! 		*location = EDGE_INSERT_LOCATION_ELSE;
! 	      }
  	    break;
  
  	  case TRY_CATCH_EXPR:
--- 3704,3720 ----
        switch (TREE_CODE (stmt))
  	{
  	  case COND_EXPR:
! 	    e = find_edge (src, new_block);
! 	    if (!e)
! 	      abort ();
! 	    ret = src->end_tree_p;
  
! 	    if (e->flags & EDGE_TRUE_VALUE)
! 	      *location = EDGE_INSERT_LOCATION_THEN;
! 	    else if (e->flags & EDGE_FALSE_VALUE)
! 	      *location = EDGE_INSERT_LOCATION_ELSE;
  	    else
! 	      abort ();
  	    break;
  
  	  case TRY_CATCH_EXPR:
*************** bsi_insert_on_edge_immediate (edge e, tr
*** 3983,3989 ****
    tree_stmt_iterator tsi;
    int num_exit, num_entry;
    enum find_location_action location;
!   tree first, last, inserted_stmt, parent;
    bb_ann_t ann;
    edge e2;
  
--- 3779,3785 ----
    tree_stmt_iterator tsi;
    int num_exit, num_entry;
    enum find_location_action location;
!   tree first, last, inserted_stmt, parent, label, gto, old_gto;
    bb_ann_t ann;
    edge e2;
  
*************** bsi_insert_on_edge_immediate (edge e, tr
*** 4127,4136 ****
    switch (location)
      {
        case EDGE_INSERT_LOCATION_BEFORE:
        case EDGE_INSERT_LOCATION_THEN:
        case EDGE_INSERT_LOCATION_ELSE:
!       case EDGE_INSERT_LOCATION_NEW_ELSE:
! 	tsi_link_before (&tsi, stmt, TSI_NEW_STMT);
  	break;
  
        case EDGE_INSERT_LOCATION_AFTER:
--- 3923,3950 ----
    switch (location)
      {
        case EDGE_INSERT_LOCATION_BEFORE:
+ 	tsi_link_before (&tsi, stmt, TSI_NEW_STMT);
+ 	break;
+ 
        case EDGE_INSERT_LOCATION_THEN:
        case EDGE_INSERT_LOCATION_ELSE:
! 	new_bb->succ->flags &= ~EDGE_FALLTHRU;
! 	label = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
! 	gto = build_and_jump (&LABEL_EXPR_LABEL (label));
! 	if (location == EDGE_INSERT_LOCATION_THEN)
! 	  {
! 	    old_gto = COND_EXPR_THEN (tsi_stmt (tsi));
! 	    COND_EXPR_THEN (tsi_stmt (tsi)) = gto;
! 	  }
! 	else
! 	  {
! 	    old_gto = COND_EXPR_ELSE (tsi_stmt (tsi));
! 	    COND_EXPR_ELSE (tsi_stmt (tsi)) = gto;
! 	  }
! 	tsi_link_after (&tsi, label, TSI_NEW_STMT);
! 	append_stmt_to_bb (tsi_container (tsi), new_bb, parent);
! 	tsi_link_after (&tsi, stmt, TSI_NEW_STMT);
! 	tsi_link_after (&tsi, old_gto, TSI_SAME_STMT);
  	break;
  
        case EDGE_INSERT_LOCATION_AFTER:
*************** bsi_insert_on_edge_immediate (edge e, tr
*** 4155,4166 ****
      {
        case EDGE_INSERT_LOCATION_THEN:
        case EDGE_INSERT_LOCATION_ELSE:
! 	stmt = last_stmt (src);
! 	if (location == EDGE_INSERT_LOCATION_THEN)
! 	  COND_EXPR_THEN (stmt) = *tsi_container (tsi);
! 	else
! 	  COND_EXPR_ELSE (stmt) = *tsi_container (tsi);
! 	/* Fallthru.  */
  
        case EDGE_INSERT_LOCATION_BEFORE:
        case EDGE_INSERT_LOCATION_AFTER:
--- 3969,3977 ----
      {
        case EDGE_INSERT_LOCATION_THEN:
        case EDGE_INSERT_LOCATION_ELSE:
! 	tsi_next (&tsi);
! 	append_stmt_to_bb (tsi_container (tsi), new_bb, parent);
! 	break;
  
        case EDGE_INSERT_LOCATION_BEFORE:
        case EDGE_INSERT_LOCATION_AFTER:
*************** bsi_insert_on_edge_immediate (edge e, tr
*** 4175,4191 ****
  	  }
  	break;
  
-       case EDGE_INSERT_LOCATION_NEW_ELSE:
- 	/* This causes a new stmt chain to be formed, and the ELSE clause needs
- 	   to be set.  Set the block number for the empty stmt which might
- 	   follow this stmt as well.  */
- 	stmt = last_stmt (src);
- 	COND_EXPR_ELSE (stmt) = inserted_stmt;
- 	tsi_next (&tsi);
- 	if (tsi_container (tsi))
- 	  append_stmt_to_bb (tsi_container (tsi), new_bb, parent);
- 	break;
- 
        case EDGE_INSERT_LOCATION_BSI_AFTER:
          break;
      }
--- 3986,3991 ----
*************** tree_split_edge (edge edge_in)
*** 4567,4573 ****
  static int
  tree_verify_flow_info (void)
  {
!   return 0;
  }
  
  
--- 4367,4406 ----
  static int
  tree_verify_flow_info (void)
  {
!   int err = 0;
!   basic_block bb;
!   block_stmt_iterator bsi;
!   tree stmt;
! 
!   FOR_EACH_BB (bb)
!     {
!       bsi = bsi_last (bb);
!       if (bsi_end_p (bsi))
! 	continue;
! 
!       stmt = bsi_stmt (bsi);
!       switch (TREE_CODE (stmt))
! 	{
! 	case COND_EXPR:
! 	  if (TREE_CODE (COND_EXPR_THEN (stmt)) != GOTO_EXPR
! 	      || TREE_CODE (COND_EXPR_ELSE (stmt)) != GOTO_EXPR)
! 	    {
! 	      fprintf (stderr, "Structured COND_EXPR at end of bb %d\n",
! 		       bb->index);
! 	      err = 1;
! 	    }
! 	  if (bb->flags & BB_CONTROL_STRUCTURE)
! 	    {
! 	      fprintf (stderr, "COND_EXPR in BB_CONTROL_STRUCTURE bb %d\n",
! 		       bb->index);
! 	      err = 1;
! 	    }
! 	  break;
! 	default: ;
! 	}
!     }
! 
!   return err;
  }
  
  
*************** assign_vars_to_scope (tree scope)
*** 4703,4706 ****
--- 4536,4743 ----
  
    for (var = BIND_EXPR_VARS (scope); var; var = TREE_CHAIN (var))
      get_var_ann (var)->scope = scope;
+ }
+ 
+ /* Checks whether the basic block BB does nothing except for jump.  */
+ static bool
+ tree_forwarder_block_p (basic_block bb)
+ {
+   block_stmt_iterator bsi;
+ 
+   if (!bb->succ
+       || bb->succ->succ_next
+       || (bb->succ->flags & EDGE_ABNORMAL)
+       || bb == ENTRY_BLOCK_PTR)
+     return false; 
+ 
+   if (phi_nodes (bb))
+     return false;
+ 
+   for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
+     switch (TREE_CODE (bsi_stmt (bsi)))
+       {
+       case LABEL_EXPR:
+       case GOTO_EXPR:
+ 	break;
+ 
+       default:
+ 	return false;
+       }
+ 
+   return true;
+ }
+ 
+ /* Threads jumps over empty statements.  Later we may add threading over
+    obviously equivalent conditions (this of course is already handled by
+    dominator optimization, but it might be useful to clean up things created
+    later).  */
+ static void
+ thread_jumps ()
+ {
+   edge e, next, last, old;
+   basic_block bb, dest, slow;
+   int set_slow;
+   tree phi, stmt;
+   int arg;
+ 
+   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
+     {
+       /* Don't waste time on unreachable blocks.  */
+       if (!bb->pred)
+ 	continue;
+ 
+       /* Nor on forwarders.  */
+       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)
+ 	continue;
+ 
+       for (e = bb->succ; e; e = next)
+ 	{
+ 	  next = e->succ_next;
+ 
+ 	  if ((e->flags & EDGE_ABNORMAL)
+ 	      || e->dest == EXIT_BLOCK_PTR
+ 	      || !tree_forwarder_block_p (e->dest)
+ 	      || e->dest->succ->dest == EXIT_BLOCK_PTR)
+ 	    continue;
+ 
+ 	  slow = e->dest;
+ 	  set_slow = 0;
+ 
+ 	  last = e->dest->succ;
+ 	  for (dest = e->dest->succ->dest;
+ 	       tree_forwarder_block_p (dest);
+ 	       last = dest->succ,
+ 	       dest = dest->succ->dest,
+ 	       set_slow ^= 1)
+ 	    {
+ 	      /* Infinite loop detected.  */
+ 	      if (slow == dest)
+ 		break;
+ 	      if (set_slow)
+ 		slow = slow->succ->dest;
+ 
+ 	      if (dest->succ->dest == EXIT_BLOCK_PTR)
+ 		break;
+ 	    }
+ 
+ 	  if (dest == e->dest)
+ 	    continue;
+ 	      
+ 	  old = find_edge (bb, dest);
+ 	  if (old)
+ 	    {
+ 	      /* If there already is an edge, check whether the values
+ 		 in phi nodes differ.  */
+ 	      if (!phi_alternatives_equal (dest, last, old))
+ 		{
+ 		  /* The previous block is forwarder, so there are no
+ 		     phi nodes to update.  */
+ 		  dest = last->src;
+ 	  
+ 		  if (dest == e->dest)
+ 		    continue;
+ 		  old = find_edge (bb, dest);
+ 		}
+ 	    }
+ 
+ 	  /* If the target starts with case label, it would be difficult to
+ 	     do the redirection.  Since we are going to lower switch_exprs
+ 	     soon, I don't want to spend too much time on it.  */
+ 	  if (first_stmt (dest)
+ 	      && TREE_CODE (first_stmt (dest)) == CASE_LABEL_EXPR)
+ 	    continue;
+ 
+ 	  /* Perform the redirection.  */
+ 	  e = thread_edge (e, dest);
+ 	  if (!old)
+ 	    {
+ 	      /* Update phi nodes.  */
+ 	      for (phi = phi_nodes (dest); phi; phi = TREE_CHAIN (phi))
+ 		{
+ 		  arg = phi_arg_from_edge (phi, last);
+ 		  if (arg < 0)
+ 		    abort ();
+ 		  add_phi_arg (&phi, PHI_ARG_DEF (phi, arg), e);
+ 		}
+ 	    }
+ 	}
+     }
+ }
+ 
+ /* Redirects edge E to basic block DEST.  Returns the new edge to DEST.  */
+ edge
+ thread_edge (edge e, basic_block dest)
+ {
+   block_stmt_iterator dest_iterator = bsi_start (dest);
+   tree dest_stmt = first_stmt (dest);
+   tree label, goto_stmt, stmt;
+   basic_block bb = e->src, new_bb;
+   int flags;
+ 
+   /* We need a label at our final destination.  If it does not already exist,
+      create it.  */
+   if (!dest_stmt
+       || TREE_CODE (dest_stmt) != LABEL_EXPR)
+     {
+       if (dest_stmt && TREE_CODE (dest_stmt) == CASE_LABEL_EXPR)
+ 	abort ();
+ 
+       label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
+       DECL_CONTEXT (label) = current_function_decl;
+       dest_stmt = build1 (LABEL_EXPR, void_type_node, label);
+       bsi_insert_before (&dest_iterator, dest_stmt, BSI_SAME_STMT);
+     }
+   else
+     label = LABEL_EXPR_LABEL (dest_stmt);
+ 
+   /* If our block does not end with a GOTO, then create one.  Otherwise redirect
+      the existing GOTO_EXPR to LABEL.  */
+   stmt = last_stmt (bb);
+   if (stmt && TREE_CODE (stmt) == COND_EXPR)
+     {
+       stmt = (e->flags & EDGE_TRUE_VALUE
+ 	      ? COND_EXPR_THEN (stmt)
+ 	      : COND_EXPR_ELSE (stmt));
+       flags = e->flags;
+       if (TREE_CODE (stmt) != GOTO_EXPR)
+ 	abort ();
+     }
+   else
+     flags = 0;
+ 
+   if (!stmt || TREE_CODE (stmt) != GOTO_EXPR)
+     {
+       goto_stmt = build1 (GOTO_EXPR, void_type_node, label);
+       bsi_insert_on_edge_immediate (e, goto_stmt, NULL, &new_bb);
+     }
+   else
+     {
+       GOTO_DESTINATION (stmt) = label;
+       new_bb = NULL;
+     }
+ 
+   /* Update/insert PHI nodes as necessary.  */
+ 
+   /* Now update the edges in the CFG.  */
+   if (new_bb)
+     {
+       ssa_remove_edge (new_bb->succ);
+       return make_edge (new_bb, dest, 0);
+     }
+   else
+     {
+       ssa_remove_edge (e);
+       return make_edge (bb, dest, flags);
+     }
  }
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.124
diff -c -3 -p -r1.1.4.124 tree-flow.h
*** tree-flow.h	6 Oct 2003 19:39:45 -0000	1.1.4.124
--- tree-flow.h	8 Oct 2003 22:36:19 -0000
*************** extern basic_block tree_split_edge (edge
*** 433,438 ****
--- 433,439 ----
  extern void bsi_move_before (block_stmt_iterator, block_stmt_iterator);
  extern void bsi_move_after (block_stmt_iterator, block_stmt_iterator);
  extern void bsi_move_to_bb_end (block_stmt_iterator, basic_block);
+ extern edge thread_edge (edge, basic_block);
  extern basic_block label_to_block (tree);
  
  /* In tree-dfa.c  */
*************** extern bool tree_could_trap_p (tree);
*** 532,537 ****
--- 533,541 ----
  extern bool tree_could_throw_p (tree);
  extern bool tree_can_throw_internal (tree);
  extern bool tree_can_throw_external (tree);
+ 
+ /* In gimple-low.c  */
+ void lower_function_body (tree *);
  
  #include "tree-flow-inline.h"
  
Index: tree-optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-optimize.c,v
retrieving revision 1.1.4.54
diff -c -3 -p -r1.1.4.54 tree-optimize.c
*** tree-optimize.c	30 Sep 2003 21:21:17 -0000	1.1.4.54
--- tree-optimize.c	8 Oct 2003 22:36:19 -0000
*************** optimize_function_tree (tree fndecl)
*** 58,63 ****
--- 58,66 ----
    if (errorcount || sorrycount)
      return;
  
+   /* Lower the structured statements.  */
+   lower_function_body (&DECL_SAVED_TREE (fndecl));
+ 
    /* Build the flowgraph.  */
    init_flow ();
  
Index: tree-pretty-print.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-pretty-print.c,v
retrieving revision 1.1.2.46
diff -c -3 -p -r1.1.2.46 tree-pretty-print.c
*** tree-pretty-print.c	28 Sep 2003 06:06:37 -0000	1.1.2.46
--- tree-pretty-print.c	8 Oct 2003 22:36:19 -0000
*************** dump_generic_node (pretty_printer *buffe
*** 693,699 ****
  	  pp_string (buffer, "if (");
  	  dump_generic_node (buffer, COND_EXPR_COND (node), spc, flags);
  	  pp_character (buffer, ')');
! 	  if (!(flags & TDF_SLIM))
  	    {
  	      /* Output COND_EXPR_THEN.  */
  	      if (COND_EXPR_THEN (node))
--- 693,704 ----
  	  pp_string (buffer, "if (");
  	  dump_generic_node (buffer, COND_EXPR_COND (node), spc, flags);
  	  pp_character (buffer, ')');
! 	  if (!(flags & TDF_SLIM)
! 	      /* The lowered cond_exprs should always be printed in full.  */
! 	      || (COND_EXPR_THEN (node)
! 		  && TREE_CODE (COND_EXPR_THEN (node)) == GOTO_EXPR
! 		  && COND_EXPR_ELSE (node)
! 		  && TREE_CODE (COND_EXPR_ELSE (node)) == GOTO_EXPR))
  	    {
  	      /* Output COND_EXPR_THEN.  */
  	      if (COND_EXPR_THEN (node))
Index: tree-ssa-copyprop.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-copyprop.c,v
retrieving revision 1.1.2.15
diff -c -3 -p -r1.1.2.15 tree-ssa-copyprop.c
*** tree-ssa-copyprop.c	21 Sep 2003 22:14:27 -0000	1.1.2.15
--- tree-ssa-copyprop.c	8 Oct 2003 22:36:19 -0000
*************** propagate_copy (tree *op_p, tree var, tr
*** 244,250 ****
  void
  fixup_var_scope (tree var, tree scope)
  {
!   tree old_scope = var_ann (SSA_NAME_VAR (var))->scope;
  
    /* If there is no old_scope, it is a newly created temporary, i.e. it is
       in the topmost bind_expr and we have nothing to do.  */
--- 244,254 ----
  void
  fixup_var_scope (tree var, tree scope)
  {
!   tree old_scope;
!   
!   if (TREE_CODE (var) == SSA_NAME)
!     var = SSA_NAME_VAR (var);
!   old_scope = var_ann (var)->scope;
  
    /* If there is no old_scope, it is a newly created temporary, i.e. it is
       in the topmost bind_expr and we have nothing to do.  */
*************** fixup_var_scope (tree var, tree scope)
*** 259,265 ****
  	    scope = stmt_ann (scope)->scope;
  	}
        if (scope != old_scope)
! 	move_var_to_scope (SSA_NAME_VAR (var), old_scope,
  			   DECL_SAVED_TREE (current_function_decl));
      }
  }
--- 263,269 ----
  	    scope = stmt_ann (scope)->scope;
  	}
        if (scope != old_scope)
! 	move_var_to_scope (var, old_scope,
  			   DECL_SAVED_TREE (current_function_decl));
      }
  }
Index: tree-ssa-dce.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-dce.c,v
retrieving revision 1.1.2.56
diff -c -3 -p -r1.1.2.56 tree-ssa-dce.c
*** tree-ssa-dce.c	25 Sep 2003 13:48:13 -0000	1.1.2.56
--- tree-ssa-dce.c	8 Oct 2003 22:36:19 -0000
*************** stmt_useful_p (tree stmt)
*** 259,273 ****
        break;
  
      case COND_EXPR:
!       if (TREE_CODE (COND_EXPR_THEN (stmt)) == GOTO_EXPR
! 	  && TREE_CODE (COND_EXPR_ELSE (stmt)) == GOTO_EXPR)
!         {
! 	  /* Check if the dest labels are the same. If they are, the condition
! 	     is useless.  */
! 	  if (GOTO_DESTINATION (COND_EXPR_THEN (stmt))
! 	      == GOTO_DESTINATION (COND_EXPR_ELSE (stmt)))
! 	    return false;
! 	}
      default:
        break;
      }
--- 259,270 ----
        break;
  
      case COND_EXPR:
!       /* Check if the dest labels are the same. If they are, the condition
! 	 is useless.  */
!       if (GOTO_DESTINATION (COND_EXPR_THEN (stmt))
! 	  == GOTO_DESTINATION (COND_EXPR_ELSE (stmt)))
! 	return false;
! 
      default:
        break;
      }
*************** stmt_useful_p (tree stmt)
*** 302,308 ****
  static void
  process_worklist (void)
  {
-   basic_block bb;
    tree i;
  
    while (VARRAY_ACTIVE_SIZE (worklist) > 0)
--- 299,304 ----
*************** process_worklist (void)
*** 318,328 ****
  	  fprintf (dump_file, "\n");
  	}
  
-       /* Find any predecessor which 'goto's this block, and mark the goto
- 	 as necessary since it is control flow.  A block's predecessors only
- 	 need to be checked once.  */
-       bb = bb_for_stmt (i);
-       
        if (TREE_CODE (i) == PHI_NODE)
  	{
  	  int k;
--- 314,319 ----
*************** remove_dead_phis (basic_block bb)
*** 441,447 ****
  }
  
  
! /* Remove dead statement pointed by iterator I from block BB.  */
  
  static void
  remove_dead_stmt (block_stmt_iterator *i)
--- 432,438 ----
  }
  
  
! /* Remove dead statement pointed by iterator I.  */
  
  static void
  remove_dead_stmt (block_stmt_iterator *i)
Index: tree-ssa-dom.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-dom.c,v
retrieving revision 1.1.2.53
diff -c -3 -p -r1.1.2.53 tree-ssa-dom.c
*** tree-ssa-dom.c	1 Oct 2003 18:44:36 -0000	1.1.2.53
--- tree-ssa-dom.c	8 Oct 2003 22:36:19 -0000
*************** static int avail_expr_eq (const void *, 
*** 145,151 ****
  static void htab_statistics (FILE *, htab_t);
  static void record_cond_is_false (tree, varray_type *, varray_type);
  static void record_cond_is_true (tree, varray_type *, varray_type);
- static void thread_edge (edge, basic_block);
  static tree update_rhs_and_lookup_avail_expr (tree, tree, varray_type *,
  					      varray_type, stmt_ann_t, bool);
  static tree simplify_rhs_and_lookup_avail_expr (tree, varray_type *,
--- 145,150 ----
*************** tree_ssa_dominator_optimize (tree fndecl
*** 233,244 ****
  
  	  while (VARRAY_ACTIVE_SIZE (edges_to_redirect) > 0)
  	    {
  	      e = VARRAY_TOP_EDGE (edges_to_redirect);
  	      tgt = VARRAY_TOP_BB (redirection_targets);
  	      VARRAY_POP (edges_to_redirect);
  	      VARRAY_POP (redirection_targets);
  
! 	      thread_edge (e, tgt);
  	    }
  
  	  cfg_altered = true;
--- 232,255 ----
  
  	  while (VARRAY_ACTIVE_SIZE (edges_to_redirect) > 0)
  	    {
+ 	      basic_block src;
+ 
  	      e = VARRAY_TOP_EDGE (edges_to_redirect);
  	      tgt = VARRAY_TOP_BB (redirection_targets);
  	      VARRAY_POP (edges_to_redirect);
  	      VARRAY_POP (redirection_targets);
  
! 	      if (dump_file && (dump_flags & TDF_DETAILS))
! 		fprintf (dump_file, "  Threaded jump %d --> %d to %d\n",
! 			 e->src->index, e->dest->index, tgt->index);
! 
! 	      src = e->src;
! 	      e = thread_edge (e, tgt);
! 	      
! 	      if ((dump_file && (dump_flags & TDF_DETAILS))
!     		  && e->src != src)
! 		fprintf (dump_file, "    basic block %d created\n",
! 			 e->src->index);
  	    }
  
  	  cfg_altered = true;
*************** tree_ssa_dominator_optimize (tree fndecl
*** 282,357 ****
    timevar_pop (TV_TREE_SSA_DOMINATOR_OPTS);
  }
  
- 
- /* Redirects edge E to basic block DEST.  */
- 
- static void
- thread_edge (edge e, basic_block dest)
- {
-   block_stmt_iterator dest_iterator = bsi_start (dest);
-   tree dest_stmt = first_stmt (dest);
-   tree label, goto_stmt, stmt;
-   basic_block bb = e->src, new_bb;
-   int flags = e->flags;
- 
-   if (e != bb->succ
-       || bb->succ->succ_next)
-     abort ();
- 
-   /* Remove EDGE_FALLTHRU from the edge (by convention, control edges are
-      not fallthru).  */
-   flags &= ~EDGE_FALLTHRU;
- 
-   /* We need a label at our final destination.  If it does not already exist,
-      create it.  */
-   if (!dest_stmt
-       || TREE_CODE (dest_stmt) != LABEL_EXPR)
-     {
-       label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
-       DECL_CONTEXT (label) = current_function_decl;
-       dest_stmt = build1 (LABEL_EXPR, void_type_node, label);
-       bsi_insert_before (&dest_iterator, dest_stmt, BSI_NEW_STMT);
-     }
-   else
-     label = LABEL_EXPR_LABEL (dest_stmt);
- 
-   /* If our block does not end with a GOTO, then create one.  Otherwise
-      redirect the existing GOTO_EXPR to LABEL.  */
-   stmt = last_stmt (bb);
-   if (!stmt || TREE_CODE (stmt) != GOTO_EXPR)
-     {
-       goto_stmt = build1 (GOTO_EXPR, void_type_node, label);
-       bsi_insert_on_edge_immediate (e, goto_stmt, NULL, &new_bb);
-     }
-   else
-     {
-       GOTO_DESTINATION (stmt) = label;
-       new_bb = NULL;
-     }
- 
-   /* Update/insert PHI nodes as necessary.  */
- 
-   /* Now update the edges in the CFG.  */
-   if (dump_file && (dump_flags & TDF_DETAILS))
-     {
-       fprintf (dump_file, "  Threaded jump %d --> %d to %d\n",
- 	       e->src->index, e->dest->index, dest->index);
-       if (new_bb)
- 	fprintf (dump_file, "    basic block %d created\n", new_bb->index);
-     }
- 
-   if (new_bb)
-     {
-       ssa_remove_edge (new_bb->succ);
-       make_edge (new_bb, dest, 0);
-     }
-   else
-     {
-       ssa_remove_edge (e);
-       make_edge (bb, dest, flags);
-     }
- }
- 
  /* Perform a depth-first traversal of the dominator tree looking for
     redundant expressions and copy/constant propagation opportunities. 
  
--- 293,298 ----
*************** optimize_block (basic_block bb, tree par
*** 642,684 ****
    children = dom_children (bb);
    if (children)
      {
!       if (bb->flags & BB_CONTROL_STRUCTURE)
! 	{
! 	  tree last = last_stmt (bb);
! 	  EXECUTE_IF_SET_IN_BITMAP (children, 0, i,
! 	    {
! 	      basic_block dest = BASIC_BLOCK (i);
  
! 	      /* The destination block may have become unreachable, in
! 		 which case there's no point in optimizing it.  */
! 	      if (dest->pred)
! 		{
! 		  /* Ensure that we only take the condition into account
! 		     if there is no other way how to reach the target basic
! 		     block.  The fact that we have exactly one predecessor
! 		     also ensures that the predecessor is BB.  */
! 		  if (!dest->pred->pred_next)
! 		    optimize_block (dest, last, dest->pred->flags,
! 				    vars_to_rename, cfg_altered);
! 		  else
! 		    optimize_block (dest, NULL_TREE, 0, vars_to_rename,
! 				    cfg_altered);
! 		}
! 	    });
! 	}
!       else
  	{
! 	  EXECUTE_IF_SET_IN_BITMAP (children, 0, i,
! 	    {
! 	      basic_block dest = BASIC_BLOCK (i);
  
! 	      /* The destination block may have become unreachable, in
! 		 which case there's no point in optimizing it. */
! 	      if (dest->pred)
! 		optimize_block (dest, NULL_TREE, 0, vars_to_rename,
! 				cfg_altered);
! 	    });
! 	}
      }
  
    /* If we have a single successor, then we may be able to thread
--- 583,612 ----
    children = dom_children (bb);
    if (children)
      {
!       tree last = last_stmt (bb);
!       int has_control_expr = last && (TREE_CODE (last) == COND_EXPR
! 				      || TREE_CODE (last) == SWITCH_EXPR);
  
!       EXECUTE_IF_SET_IN_BITMAP (children, 0, i,
  	{
! 	  basic_block dest = BASIC_BLOCK (i);
  
! 	  /* The destination block may have become unreachable, in
! 	     which case there's no point in optimizing it.  */
! 	  if (dest->pred)
! 	    {
! 	      /* Ensure that we only take the condition into account
! 		 if there is no other way how to reach the target basic
! 		 block.  The fact that we have exactly one predecessor
! 		 also ensures that the predecessor is BB.  */
! 	      if (has_control_expr
! 		  && !dest->pred->pred_next)
! 		optimize_block (dest, last, dest->pred->flags,
! 				vars_to_rename, cfg_altered);
! 	      else
! 		optimize_block (dest, NULL_TREE, 0, vars_to_rename, cfg_altered);
! 	    }
!        	});
      }
  
    /* If we have a single successor, then we may be able to thread
Index: tree-ssa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa.c,v
retrieving revision 1.1.4.131
diff -c -3 -p -r1.1.4.131 tree-ssa.c
*** tree-ssa.c	3 Oct 2003 11:52:49 -0000	1.1.4.131
--- tree-ssa.c	8 Oct 2003 22:36:19 -0000
*************** create_temp (tree t)
*** 856,862 ****
  static void
  insert_copy_on_edge (edge e, tree dest, tree src)
  {
!   tree copy;
  
    copy = build (MODIFY_EXPR, TREE_TYPE (dest), dest, src);
    set_is_used (dest);
--- 856,862 ----
  static void
  insert_copy_on_edge (edge e, tree dest, tree src)
  {
!   tree copy, scope, s1, s2;
  
    copy = build (MODIFY_EXPR, TREE_TYPE (dest), dest, src);
    set_is_used (dest);
*************** insert_copy_on_edge (edge e, tree dest, 
*** 871,876 ****
--- 871,894 ----
        print_generic_expr (dump_file, copy, dump_flags);
        fprintf (dump_file, "\n");
      }
+   /* If we are inserting a variable on boundaries of scopes, rather reset
+      the scope completely, since we don't know for sure where it should
+      be placed.  */
+   s1 = last_stmt (e->src);
+   s2 = last_stmt (e->dest);
+   if (!s1
+       || !s2
+       || !stmt_ann (s1)->scope
+       || !stmt_ann (s2)->scope
+       || stmt_ann (s1)->scope != stmt_ann (s2)->scope)
+     scope = NULL_TREE;
+   else
+     scope = stmt_ann (s1)->scope;
+ 
+   if (TREE_CODE (src) == VAR_DECL)
+     fixup_var_scope (src, scope);
+   fixup_var_scope (dest, scope);
+ 
    bsi_insert_on_edge (e, copy);
  }
  

Attachment: diff_ggc.diff
Description: Text document

/* Tree lowering pass.  Lowers GIMPLE into unstructured form.

   Copyright (C) 2003 Free Software Foundation, Inc.

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.

GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING.  If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.  */

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
#include "rtl.h"
#include "errors.h"
#include "varray.h"
#include "tree-simple.h"
#include "tree-inline.h"
#include "diagnostic.h"
#include "langhooks.h"
#include "langhooks-def.h"
#include "tree-flow.h"
#include "timevar.h"
#include "except.h"
#include "hashtab.h"
#include "flags.h"
#include "function.h"
#include "expr.h"
#include "toplev.h"

struct lower_data
{
  void *dummy;		/* To get rid of an empty structure warning.  */
};

static void lower_stmt_body (tree *, struct lower_data *);
static void lower_stmt (tree_stmt_iterator *, struct lower_data *);
static void lower_bind_expr (tree_stmt_iterator *, struct lower_data *);
static void lower_cond_expr (tree_stmt_iterator *, struct lower_data *);
static void lower_switch_expr (tree_stmt_iterator *, struct lower_data *);
static void lower_case_label_expr (tree_stmt_iterator *, struct lower_data *);
static bool simple_goto_p (tree);

/* Lowers the BODY.  */
void
lower_function_body (tree *body)
{
  struct lower_data data;

  if (TREE_CODE (*body) != BIND_EXPR)
    abort ();

  lower_stmt_body (&BIND_EXPR_BODY (*body), &data);
}

/* Lowers the EXPR.  Unlike gimplification the statements are not relowered
   when they are changed -- if this has to be done, the lowering routine must
   do it explicitly.  DATA is passed through the recursion.  */

static void
lower_stmt_body (tree *expr, struct lower_data *data)
{
  tree_stmt_iterator tsi;

  for (tsi = tsi_start (expr); !tsi_end_p (tsi); )
    lower_stmt (&tsi, data);
}

/* Lowers statement TSI.  DATA is passed through the recursion.  */
static void
lower_stmt (tree_stmt_iterator *tsi, struct lower_data *data)
{
  tree stmt = tsi_stmt (*tsi);

  switch (TREE_CODE (stmt))
    {
    case BIND_EXPR:
      lower_bind_expr (tsi, data);
      break;

    case COMPOUND_EXPR:
      abort ();

    case NOP_EXPR:
    case ASM_EXPR:
    case RETURN_EXPR:
    case MODIFY_EXPR:
    case CALL_EXPR:
    case GOTO_EXPR:
    case LABEL_EXPR:
    case VA_ARG_EXPR:
    case RESX_EXPR:
      break;

    case COND_EXPR:
      lower_cond_expr (tsi, data);
      break;

    case SWITCH_EXPR:
      lower_switch_expr (tsi, data);
      break;

    case CASE_LABEL_EXPR:
      lower_case_label_expr (tsi, data);
      break;

    default:
      print_node_brief (stderr, "", tsi_stmt (*tsi), 0);
      abort ();
    }

  tsi_next (tsi);
}

/* Lowers a bind_expr TSI.  DATA is passed through the recursion.  */

static void
lower_bind_expr (tree_stmt_iterator *tsi, struct lower_data *data)
{
  tree stmt = tsi_stmt (*tsi);

  lower_stmt_body (&BIND_EXPR_BODY (stmt), data);
}

/* Checks whether EXPR is a simple local goto.  */

static bool
simple_goto_p (tree expr)
{
  return  (TREE_CODE (expr) == GOTO_EXPR
	   && TREE_CODE (GOTO_DESTINATION (expr)) == LABEL_DECL
	   && ! NONLOCAL_LABEL (GOTO_DESTINATION (expr))
	   && (decl_function_context (GOTO_DESTINATION (expr))
	       == current_function_decl));
}

/* Lowers a cond_expr TSI.  DATA is passed through the recursion.  */

static void
lower_cond_expr (tree_stmt_iterator *tsi, struct lower_data *data)
{
  tree stmt = tsi_stmt (*tsi);
  bool then_is_goto, else_is_goto;
  tree then_branch, else_branch, then_label, else_label, end_label;
  
  lower_stmt_body (&COND_EXPR_THEN (stmt), data);
  lower_stmt_body (&COND_EXPR_ELSE (stmt), data);

  /* Find out whether the branches are ordinary local gotos.  */
  then_branch = COND_EXPR_THEN (stmt);
  else_branch = COND_EXPR_ELSE (stmt);

  then_is_goto = simple_goto_p (then_branch);
  else_is_goto = simple_goto_p (else_branch);

  if (then_is_goto && else_is_goto)
    return;
 
  /* Replace the cond_expr with explicit gotos.  */
  if (!then_is_goto)
    {
      then_label = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
      COND_EXPR_THEN (stmt) = build_and_jump (&LABEL_EXPR_LABEL (then_label));
    }
  else
    then_label = NULL_TREE;

  if (!else_is_goto)
    {
      else_label = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
      COND_EXPR_ELSE (stmt) = build_and_jump (&LABEL_EXPR_LABEL (else_label));
    }
  else
    else_label = NULL_TREE;

  end_label = NULL_TREE;
  if (then_label)
    {
      tsi_link_after (tsi, then_label, TSI_CONTINUE_LINKING);
      tsi_link_chain_after (tsi, then_branch, TSI_CONTINUE_LINKING);
  
      if (else_label)
	{
	  end_label = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
	  tsi_link_after (tsi, build_and_jump (&LABEL_EXPR_LABEL (end_label)),
			  TSI_CONTINUE_LINKING);
	}
    }
  
  if (else_label)
    {
      tsi_link_after (tsi, else_label, TSI_CONTINUE_LINKING);
      tsi_link_chain_after (tsi, else_branch, TSI_CONTINUE_LINKING);
    }

  if (end_label)
    tsi_link_after (tsi, end_label, TSI_CONTINUE_LINKING);
}

/* Lowers a switch_expr TSI.  DATA is passed through the recursion.  */

static void
lower_switch_expr (tree_stmt_iterator *tsi, struct lower_data *data)
{
  tree stmt = tsi_stmt (*tsi);

  lower_stmt_body (&SWITCH_BODY (stmt), data);
}

/* Lowers a case_label_expr TSI.  DATA is passed through the recursion.  */

static void
lower_case_label_expr (tree_stmt_iterator *tsi ATTRIBUTE_UNUSED,
		       struct lower_data *data ATTRIBUTE_UNUSED)
{
}

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