[tree-ssa] COND_EXPR lowering

Zdenek Dvorak rakdver@atrey.karlin.mff.cuni.cz
Sun Oct 19 18:58:00 GMT 2003


Hello,

here is the new version.  Aside of merges of changes from the last week,
it fixes the warning regressions.  Now there are no new regressions
(except for gcc.dg/old-style-asm-1.c, which is a bug in test -- see
http://gcc.gnu.org/ml/gcc-patches/2003-10/msg01642.html).

Zdenek

(gimple-low.c is unchanged)


Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.903.2.122
diff -c -3 -p -r1.903.2.122 Makefile.in
*** Makefile.in	18 Oct 2003 23:59:32 -0000	1.903.2.122
--- Makefile.in	19 Oct 2003 18:44:11 -0000
*************** OBJS-common = \
*** 867,873 ****
   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 domwalk.o tree-tailcall.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	   \
--- 867,873 ----
   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 domwalk.o tree-tailcall.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) 
*** 1573,1578 ****
--- 1573,1582 ----
     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.180
diff -c -3 -p -r1.1.4.180 tree-cfg.c
*** tree-cfg.c	18 Oct 2003 03:09:46 -0000	1.1.4.180
--- tree-cfg.c	19 Oct 2003 18:44:11 -0000
*************** static void create_block_annotation (bas
*** 92,98 ****
  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);
--- 92,97 ----
*************** static int tree_verify_flow_info (void);
*** 121,126 ****
--- 120,127 ----
  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 bool disconnect_unreachable_case_
*** 141,151 ****
  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);
--- 142,151 ----
  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 {
*** 165,171 ****
    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
--- 165,170 ----
*************** make_blocks (tree *first_p, tree next_bl
*** 537,545 ****
        if (is_computed_goto (*stmt_p))
  	found_computed_goto = true;
  
!       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)
  	{
--- 536,542 ----
        if (is_computed_goto (*stmt_p))
  	found_computed_goto = true;
  
!       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
*** 620,660 ****
    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
--- 617,622 ----
*************** make_switch_expr_blocks (tree *switch_e_
*** 674,680 ****
    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);
  
--- 636,642 ----
    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
*** 748,753 ****
--- 710,719 ----
  {
    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
*** 925,936 ****
  
        /* 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);
  	}
--- 891,897 ----
  
        /* 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
*** 1099,1105 ****
  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)
--- 1060,1067 ----
  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)
*** 1107,1126 ****
  #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
--- 1069,1081 ----
  #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)
*** 1172,1197 ****
       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);
      }
  }
  
--- 1127,1157 ----
       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)
*** 1229,1236 ****
    pdom_info = NULL;
  
    cleanup_control_flow ();
    remove_unreachable_blocks ();
-   linearize_control_structures ();
    if (pdom_info != NULL)
      {
        free_dominance_info (pdom_info);
--- 1189,1197 ----
    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)
*** 1248,1253 ****
--- 1209,1217 ----
  	clear_dom_children (bb);
      }
  
+ #ifdef ENABLE_CHECKING
+   verify_flow_info ();
+ #endif
    timevar_pop (TV_TREE_CLEANUP_CFG);
  }
  
*************** remove_unreachable_block (basic_block bb
*** 1781,1789 ****
  
  	     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);
  	}
--- 1745,1751 ----
  
  	     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);
  	}
*************** remove_bb (basic_block bb, int remove_st
*** 1838,1843 ****
--- 1800,1806 ----
    block_stmt_iterator i;
    bsi_list_p stack;
    location_t loc;
+   bool empty = true;
  
    dump_file = dump_begin (TDI_cfg, &dump_flags);
    if (dump_file)
*************** remove_bb (basic_block bb, int remove_st
*** 1860,1867 ****
          {
  	  int ctrl_struct = is_ctrl_structure (stmt);
  
! 	  loc.file = get_filename (stmt);
! 	  loc.line = get_lineno (stmt);
  	  if ((ctrl_struct && (remove_stmt_flags & REMOVE_CONTROL_STRUCTS))
  	      || (!ctrl_struct && (remove_stmt_flags & REMOVE_NON_CONTROL_STRUCTS)))
  	    bsi_remove (&i);
--- 1823,1838 ----
          {
  	  int ctrl_struct = is_ctrl_structure (stmt);
  
! 	  if (get_lineno (stmt) != -1
! 	      /* Don't warn for removed gotos.  Gotos are often removed due to jump threading,
! 		 thus resulting into bogus warnings.  Not great, since this way we lose warnings
! 		 for gotos in the original program that are indeed unreachable.  */
! 	      && TREE_CODE (stmt) != GOTO_EXPR)
! 	    {
! 	      loc.file = get_filename (stmt);
! 	      loc.line = get_lineno (stmt);
! 	      empty = false;
! 	    }
  	  if ((ctrl_struct && (remove_stmt_flags & REMOVE_CONTROL_STRUCTS))
  	      || (!ctrl_struct && (remove_stmt_flags & REMOVE_NON_CONTROL_STRUCTS)))
  	    bsi_remove (&i);
*************** remove_bb (basic_block bb, int remove_st
*** 1872,1878 ****
       block is unreachable.  We walk statements backwards in the
       loop above, so the last statement we process is the first statement
       in the block.  */
!   if (remove_stmt_flags && warn_notreached)
      warning ("%Hwill never be executed", &loc);
  
    if (bb->head_tree_p)
--- 1843,1849 ----
       block is unreachable.  We walk statements backwards in the
       loop above, so the last statement we process is the first statement
       in the block.  */
!   if (remove_stmt_flags && warn_notreached && !empty)
      warning ("%Hwill never be executed", &loc);
  
    if (bb->head_tree_p)
*************** bsi_replace (block_stmt_iterator bsi, tr
*** 2022,2029 ****
    modify_stmt (bsi_stmt (bsi));
  }
  
- 
- 
  /* Remove statement *STMT_P.
  
     Update all references associated with it.  Note that this function will
--- 1993,1998 ----
*************** cleanup_control_flow (void)
*** 2146,2186 ****
    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, last);
! 	    else if (code == SWITCH_EXPR)
! 	      cleanup_switch_expr_graph (bb, last);
! 	  }
!       }
  }
  
  
  /* Disconnect an unreachable block in the conditional expression starting
!    at block BB.
! 
!    If the predicate of the COND_EXPR node in block BB is constant,
!    disconnect the subgraph that contains the clause that is never executed.  */
  
  bool
  cleanup_cond_expr_graph (basic_block bb, tree cond_expr)
  {
    tree val;
    edge taken_edge;
    bool retval = false;
  
  #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;
--- 2115,2160 ----
    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, last);
! 	  else if (code == SWITCH_EXPR)
! 	    cleanup_switch_expr_graph (bb, last);
! 	}
!     }
  }
  
  
  /* Disconnect an unreachable block in the conditional expression starting
!    at block BB.  */
  
  bool
  cleanup_cond_expr_graph (basic_block bb, tree cond_expr)
  {
    tree val;
    edge taken_edge;
+   block_stmt_iterator bsi;
    bool retval = false;
  
  #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,
*** 2195,2201 ****
--- 2169,2184 ----
  	      retval = true;
  	    }
  	}
+ 
+       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 ();
      }
+ 
    return retval;
  }
  
*************** find_taken_edge (basic_block bb, tree va
*** 2298,2304 ****
    stmt = last_stmt (bb);
  
  #if defined ENABLE_CHECKING
!   if (stmt == NULL_TREE || !is_ctrl_structure (stmt))
      abort ();
  #endif
  
--- 2281,2287 ----
    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
*** 2343,2351 ****
  	|| ((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));
  }
  
  
--- 2326,2333 ----
  	|| ((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
*** 2427,2604 ****
    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 alternatives 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 alternative 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 exhausted 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
  ---------------------------------------------------------------------------*/
--- 2409,2444 ----
    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)
*** 2948,2955 ****
      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
--- 2788,2794 ----
      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
*** 2962,2967 ****
--- 2801,2807 ----
  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 *
*** 3714,3743 ****
    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);
  
--- 3554,3559 ----
*************** find_insert_location (basic_block src, b
*** 4035,4040 ****
--- 3851,3857 ----
  {
    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
*** 4044,4074 ****
        switch (TREE_CODE (stmt))
  	{
  	  case COND_EXPR:
! 	    /* If the ELSE block is non-existent, 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:
--- 3861,3877 ----
        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
*** 4133,4139 ****
    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;
  
--- 3936,3942 ----
    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
*** 4277,4286 ****
    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:
--- 4080,4107 ----
    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
*** 4305,4316 ****
      {
        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:
--- 4126,4134 ----
      {
        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
*** 4325,4341 ****
  	  }
  	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;
      }
--- 4143,4148 ----
*************** tree_split_edge (edge edge_in)
*** 4717,4723 ****
  static int
  tree_verify_flow_info (void)
  {
!   return 0;
  }
  
  
--- 4524,4563 ----
  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)
*** 4853,4856 ****
--- 4693,4900 ----
  
    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.131
diff -c -3 -p -r1.1.4.131 tree-flow.h
*** tree-flow.h	18 Oct 2003 18:58:41 -0000	1.1.4.131
--- tree-flow.h	19 Oct 2003 18:44:11 -0000
*************** extern basic_block tree_split_edge (edge
*** 437,442 ****
--- 437,443 ----
  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);
  extern bool cleanup_cond_expr_graph (basic_block, tree);
  extern bool cleanup_switch_expr_graph (basic_block, tree);
*************** extern bool tree_could_trap_p (tree);
*** 538,543 ****
--- 539,547 ----
  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.57
diff -c -3 -p -r1.1.4.57 tree-optimize.c
*** tree-optimize.c	18 Oct 2003 18:58:41 -0000	1.1.4.57
--- tree-optimize.c	19 Oct 2003 18:44:11 -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.49
diff -c -3 -p -r1.1.2.49 tree-pretty-print.c
*** tree-pretty-print.c	14 Oct 2003 17:31:35 -0000	1.1.2.49
--- tree-pretty-print.c	19 Oct 2003 18:44:11 -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.19
diff -c -3 -p -r1.1.2.19 tree-ssa-copyprop.c
*** tree-ssa-copyprop.c	18 Oct 2003 18:02:04 -0000	1.1.2.19
--- tree-ssa-copyprop.c	19 Oct 2003 18:44:11 -0000
*************** propagate_copy (tree *op_p, tree var, tr
*** 255,261 ****
  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.  */
--- 255,265 ----
  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)
*** 270,276 ****
  	    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));
      }
  }
--- 274,280 ----
  	    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.61
diff -c -3 -p -r1.1.2.61 tree-ssa-dce.c
*** tree-ssa-dce.c	18 Oct 2003 03:09:47 -0000	1.1.2.61
--- tree-ssa-dce.c	19 Oct 2003 18:44:11 -0000
*************** stmt_useful_p (tree stmt)
*** 276,290 ****
        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;
      }
--- 276,287 ----
        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)
*** 320,326 ****
  static void
  process_worklist (void)
  {
-   basic_block bb;
    tree i;
  
    while (VARRAY_ACTIVE_SIZE (worklist) > 0)
--- 317,322 ----
*************** process_worklist (void)
*** 336,346 ****
  	  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;
--- 332,337 ----
*************** remove_dead_phis (basic_block bb)
*** 461,467 ****
  }
  
  
! /* Remove dead statement pointed by iterator I from block BB.  */
  
  static void
  remove_dead_stmt (block_stmt_iterator *i)
--- 452,458 ----
  }
  
  
! /* 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.63
diff -c -3 -p -r1.1.2.63 tree-ssa-dom.c
*** tree-ssa-dom.c	18 Oct 2003 03:09:47 -0000	1.1.2.63
--- tree-ssa-dom.c	19 Oct 2003 18:44:11 -0000
*************** static int avail_expr_eq (const void *, 
*** 178,184 ****
  static void htab_statistics (FILE *, htab_t);
  static void record_cond_is_false (tree, varray_type *);
  static void record_cond_is_true (tree, varray_type *);
- static void thread_edge (edge, basic_block);
  static tree update_rhs_and_lookup_avail_expr (tree, tree, varray_type *,
  					      stmt_ann_t, bool);
  static tree simplify_rhs_and_lookup_avail_expr (tree, varray_type *,
--- 178,183 ----
*************** tree_ssa_dominator_optimize (tree fndecl
*** 314,325 ****
  
  	  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;
--- 313,336 ----
  
  	  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
*** 361,436 ****
    VARRAY_FREE (redirection_targets);
  
    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);
-     }
  }
  
  /* We are exiting BB, see if the target block begins with a conditional
--- 372,377 ----
Index: tree-ssa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa.c,v
retrieving revision 1.1.4.138
diff -c -3 -p -r1.1.4.138 tree-ssa.c
*** tree-ssa.c	18 Oct 2003 03:09:47 -0000	1.1.4.138
--- tree-ssa.c	19 Oct 2003 18:44:11 -0000
*************** create_temp (tree t)
*** 893,899 ****
  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);
--- 893,899 ----
  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, 
*** 912,917 ****
--- 912,935 ----
        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);
  }



More information about the Gcc-patches mailing list