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]

[tree-ssa-cfg] BIND_EXPR removal


Hello,

with this patch, the last structured statement (BIND_EXPR) is eliminated
from tree-ssa-cfg infrastructure and a lot of mess is cleaned up.
Finally looks the way I like :-).  Next I'm going to test whether indeed
everything works (I suspect some problems with exception handling that I
merged from tree-ssa will occur) and then attempt to make tree --> rtl
work without destroying cfg.

Zdenek

	* Makefile.in (gimple-low.o): Add EXPR_H and toplev.h dependency.
	* basic-block.h (EDGE_CONSTRUCT_ENTRY): Remove.
	* cfg.c (dump_edge_info): Remove EDGE_CONSTRUCT_ENTRY reference.
	* function.h (struct function): Add tree_containers_root field.
	* gimple-low.c: Include expr.h and toplev.h.
	(expand_vars): New.
	(lower_function_body, lower_bind_expr): Use it.
	* tree-alias-common.c (create_alias_vars): Iterate over block tree
	instead of bti.
	* tree-cfg.c (block_tree, block_tree_curr, block_tree_obstack,
	* block_tree_alloc, dump_block_tree_id, assign_vars_to_scope,
	block_tree_free, assign_vars_to_scopes): Removed.
	(build_tree_cfg, make_blocks, make_edges): Remove block_tree
	initialization.
	(remove_bb, tree_merge_blocks, dump_cfg_function_to_file,
	tree_split_edge, tree_split_block, tree_verify_flow_info,
	debug_tree_chain, tree_forwarder_block_p, thread_jumps,
	merge_seq_blocks): Remove block_tree handling.
	(bsi_insert_after, bsi_insert_before): Use tree_cell_alloc.
	(remove_useless_stmts_and_vars, remove_useless_stmts_and_vars_1,
	remove_useless_stmts_and_vars_cond, remove_useless_stmts_and_vars_tf,
	remove_useless_stmts_and_vars_tc, remove_useless_stmts_and_vars_bind):
	Readded from mainline.
	* tree-flatten.c (recreate_block_constructs): Remove.
	(append, compact_to_block, tree_flatten_statement,
	tree_unflatten_statements): Simplify.
	(dummy_verify_flow_info): Remove.
	(tree_cell_alloc): Add cell to gc list.
	* tree-flow-inline.h (add_dom_child, clear_dom_children): Don't use gc
	for dom_children.
	(bti_start, bti_end_p, bti_next): Remove.
	* tree-flow.h (enum tree_container_note): Removed.
	(struct tree_container): Note field removed, next_in_gc_chain added.
	(struct block_tree, block_tree): Removed.
	(struct var_ann_d): Remove scope field.
	(struct bb_ann_d): Remove block field.
	(bti_start, bti_end_p, bti_next, dump_block_tree, block_tree_free,
	assign_vars_to_scopes, fixup_var_scope): Declaration removed.
	(propagate_copy, tree_cell_alloc): Declaration changed.
	* tree-optimize.c (tree_rest_of_compilation): Add
	remove_useless_stmts_and_vars calls.  Reorganize due to earlier
	declaration expanding.
	* tree-ssa-copyprop.c (get_common_scope, move_var_to_scope,
	fixup_var_scope): Removed.
	(copyprop_stmt): Don't pass bb to propagate_copy.
	(propagate_copy): Don't take bb argument. Don't call fixup_var_scope.
	* tree-ssa-dom.c (optimize_stmt): Don't pass bb to propagate_copy.
	Don't call fixup_var_scope.
	* tree-ssa-pre.c (tree_perform_ssapre): Don't call ggc_collect.
	* tree-ssa.c (rewrite_out_of_ssa): Remove call to
	remove_useless_stmts_and_vars.
	* tree.c (tsi_link_after, tsi_link_chain_after): Remove parts
	concerning updating bb boundaries.

Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.903.2.109.2.3
diff -c -3 -p -r1.903.2.109.2.3 Makefile.in
*** Makefile.in	5 Oct 2003 19:25:42 -0000	1.903.2.109.2.3
--- Makefile.in	6 Oct 2003 23:15:44 -0000
*************** gimplify.o : gimplify.c $(CONFIG_H) $(SY
*** 1573,1579 ****
  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) function.h
  tree-browser.o : tree-browser.c tree-browser.def $(CONFIG_H) $(SYSTEM_H) \
     $(TREE_H) errors.h tree-inline.h diagnostic.h $(HASHTAB_H) \
     $(TM_H) coretypes.h
--- 1573,1579 ----
  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) function.h $(EXPR_H) toplev.h
  tree-browser.o : tree-browser.c tree-browser.def $(CONFIG_H) $(SYSTEM_H) \
     $(TREE_H) errors.h tree-inline.h diagnostic.h $(HASHTAB_H) \
     $(TM_H) coretypes.h
Index: basic-block.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/basic-block.h,v
retrieving revision 1.153.2.28.2.2
diff -c -3 -p -r1.153.2.28.2.2 basic-block.h
*** basic-block.h	16 Aug 2003 21:11:08 -0000	1.153.2.28.2.2
--- basic-block.h	6 Oct 2003 23:15:44 -0000
*************** typedef struct edge_def {
*** 159,166 ****
  					   predicate is zero.  */
  #define EDGE_EXECUTABLE		4096	/* Edge is executable.  Only
  					   valid during SSA-CCP.  */
! #define EDGE_CONSTRUCT_ENTRY	8192	/* An entry of block.  */
! #define EDGE_ALL_FLAGS		16383
  
  #define EDGE_COMPLEX	(EDGE_ABNORMAL | EDGE_ABNORMAL_CALL | EDGE_EH)
  
--- 159,165 ----
  					   predicate is zero.  */
  #define EDGE_EXECUTABLE		4096	/* Edge is executable.  Only
  					   valid during SSA-CCP.  */
! #define EDGE_ALL_FLAGS		8191
  
  #define EDGE_COMPLEX	(EDGE_ABNORMAL | EDGE_ABNORMAL_CALL | EDGE_EH)
  
Index: cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfg.c,v
retrieving revision 1.34.2.11.2.3
diff -c -3 -p -r1.34.2.11.2.3 cfg.c
*** cfg.c	2 Oct 2003 22:02:04 -0000	1.34.2.11.2.3
--- cfg.c	6 Oct 2003 23:15:44 -0000
*************** dump_edge_info (FILE *file, edge e, int 
*** 640,646 ****
        static const char * const bitnames[] = {
  	"fallthru", "ab", "abcall", "eh", "fake", "dfs_back",
  	"can_fallthru", "irreducible", "sibcall", "loop_exit",
! 	"true", "false", "exec", "construct_entry"
        };
        int comma = 0;
        int i, flags = e->flags;
--- 640,646 ----
        static const char * const bitnames[] = {
  	"fallthru", "ab", "abcall", "eh", "fake", "dfs_back",
  	"can_fallthru", "irreducible", "sibcall", "loop_exit",
! 	"true", "false", "exec"
        };
        int comma = 0;
        int i, flags = e->flags;
Index: function.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/function.h,v
retrieving revision 1.83.2.11.2.3
diff -c -3 -p -r1.83.2.11.2.3 function.h
*** function.h	5 Oct 2003 19:25:44 -0000	1.83.2.11.2.3
--- function.h	6 Oct 2003 23:15:44 -0000
*************** struct function GTY(())
*** 416,421 ****
--- 416,425 ----
    /* Array mapping insn uids to blocks.  */
    struct varray_head_tag *ib_boundaries_block;
  
+   /* Tree container cell list (so that garbage collector keeps them alive);
+      not really a great solution.  */
+   struct tree_container *tree_containers_root;
+ 
    /* Collected bit flags.  */
  
    /* Nonzero if function being compiled needs to be given an address
Index: gimple-low.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/gimple-low.c,v
retrieving revision 1.1.2.3
diff -c -3 -p -r1.1.2.3 gimple-low.c
*** gimple-low.c	6 Oct 2003 00:55:01 -0000	1.1.2.3
--- gimple-low.c	6 Oct 2003 23:15:44 -0000
*************** Software Foundation, 59 Temple Place - S
*** 38,43 ****
--- 38,45 ----
  #include "hashtab.h"
  #include "flags.h"
  #include "function.h"
+ #include "expr.h"
+ #include "toplev.h"
  
  struct lower_data
  {
*************** static void lower_cond_expr (tree_stmt_i
*** 56,61 ****
--- 58,64 ----
  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);
+ static void expand_vars (tree);
  
  /* Lowers the BODY.  */
  void
*************** lower_function_body (tree *body)
*** 70,75 ****
--- 73,79 ----
    BLOCK_SUBBLOCKS (data.block) = NULL_TREE;
    BLOCK_CHAIN (data.block) = NULL_TREE;
  
+   expand_vars (BIND_EXPR_VARS (*body));
    lower_stmt_body (&BIND_EXPR_BODY (*body), &data);
  
    if (data.block != DECL_INITIAL (current_function_decl))
*************** lower_stmt (tree_stmt_iterator *tsi, str
*** 104,110 ****
      {
      case BIND_EXPR:
        lower_bind_expr (tsi, data);
!       break;
  
      case COMPOUND_EXPR:
        abort ();
--- 108,116 ----
      {
      case BIND_EXPR:
        lower_bind_expr (tsi, data);
!       /* Avoid moving the tsi -- it is moved by delinking the statement
! 	 already.  */
!       return;
  
      case COMPOUND_EXPR:
        abort ();
*************** lower_stmt (tree_stmt_iterator *tsi, str
*** 142,147 ****
--- 148,208 ----
    tsi_next (tsi);
  }
  
+ /* Expands declarations of variables in list VARS.  */
+ 
+ static void
+ expand_vars (tree vars)
+ {
+   /* Expand the variables.  Copied from expr.c.  Expanding initializers is
+      omitted, as it should be expressed explicitly in gimple.  */
+ 
+   for (; vars; vars = TREE_CHAIN (vars))
+     {
+       tree var = vars;
+ 
+       if (DECL_EXTERNAL (var))
+ 	continue;
+ 
+       if (TREE_STATIC (var))
+ 	/* If this is an inlined copy of a static local variable,
+ 	   look up the original decl.  */
+ 	var = DECL_ORIGIN (var);
+ 
+       if (TREE_STATIC (var)
+ 	  ? TREE_ASM_WRITTEN (var)
+ 	  : DECL_RTL_SET_P (var))
+ 	continue;
+ 
+       if (TREE_CODE (var) == VAR_DECL && DECL_DEFER_OUTPUT (var))
+ 	{
+ 	  /* Prepare a mem & address for the decl.  */
+ 	  rtx x;
+ 		    
+ 	  if (TREE_STATIC (var))
+ 	    abort ();
+ 
+ 	  x = gen_rtx_MEM (DECL_MODE (var),
+ 			   gen_reg_rtx (Pmode));
+ 
+ 	  set_mem_attributes (x, var, 1);
+ 	  SET_DECL_RTL (var, x);
+ 	}
+       else if ((*lang_hooks.expand_decl) (var))
+ 	/* OK.  */;
+       else if (TREE_CODE (var) == VAR_DECL && !TREE_STATIC (var))
+ 	expand_decl (var);
+       else if (TREE_CODE (var) == VAR_DECL && TREE_STATIC (var))
+ 	rest_of_decl_compilation (var, NULL, 0, 0);
+       else if (TREE_CODE (var) == TYPE_DECL
+ 	       || TREE_CODE (var) == CONST_DECL
+ 	       || TREE_CODE (var) == FUNCTION_DECL
+ 	       || TREE_CODE (var) == LABEL_DECL)
+ 	/* No expansion needed.  */;
+       else
+ 	abort ();
+     }
+ }
+ 
  /* Lowers a bind_expr TSI.  DATA is passed through the recursion.  */
  
  static void
*************** lower_bind_expr (tree_stmt_iterator *tsi
*** 162,167 ****
--- 223,231 ----
        BLOCK_SUBBLOCKS (data->block) = NULL_TREE;
        BLOCK_SUPERCONTEXT (data->block) = old_block;
      }
+ 
+   expand_vars (BIND_EXPR_VARS (stmt));
+   
    lower_stmt_body (&BIND_EXPR_BODY (stmt), data);
  
    if (BIND_EXPR_BLOCK (stmt))
*************** lower_bind_expr (tree_stmt_iterator *tsi
*** 173,178 ****
--- 237,247 ----
  	      blocks_nreverse (BLOCK_SUBBLOCKS (data->block));
        data->block = old_block;
      }
+ 
+   /* The BIND_EXPR no longer carries any useful information, so get rid
+      of it.  */
+   tsi_link_chain_before (tsi, BIND_EXPR_BODY (stmt), TSI_SAME_STMT);
+   tsi_delink (tsi);
  }
  
  /* Checks whether EXPR is a simple local goto.  */
Index: tree-alias-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-alias-common.c,v
retrieving revision 1.1.2.34.2.2
diff -c -3 -p -r1.1.2.34.2.2 tree-alias-common.c
*** tree-alias-common.c	2 Oct 2003 22:02:27 -0000	1.1.2.34.2.2
--- tree-alias-common.c	6 Oct 2003 23:15:44 -0000
*************** create_alias_vars (tree fndecl)
*** 960,967 ****
  #endif
    size_t i;
    basic_block bb;
    block_stmt_iterator bsi;
-   struct block_tree *block;
    we_created_global_var = false;
    currptadecl = fndecl;
  
--- 960,967 ----
  #endif
    size_t i;
    basic_block bb;
+   tree block;
    block_stmt_iterator bsi;
    we_created_global_var = false;
    currptadecl = fndecl;
  
*************** create_alias_vars (tree fndecl)
*** 1008,1016 ****
  					find_func_aliases, NULL);
  	}
      }
!   for (block = bti_start (); !bti_end_p (block); bti_next (&block))
!     walk_tree_without_duplicates (&BIND_EXPR_VARS (block->bind),
! 				  find_func_aliases, NULL);
  
    if (we_created_global_var)
      {  
--- 1008,1033 ----
  					find_func_aliases, NULL);
  	}
      }
! 
!   block = DECL_INITIAL (fndecl);
!   while (1)
!     {
!       walk_tree_without_duplicates (&BLOCK_VARS (block),
! 				    find_func_aliases, NULL);
! 
!       if (BLOCK_SUBBLOCKS (block))
! 	{
! 	  block = BLOCK_SUBBLOCKS (block);
! 	  continue;
! 	}
!       while (block && !BLOCK_CHAIN (block))
! 	block = BLOCK_SUPERCONTEXT (block);
!       
!       if (!block)
! 	break;
! 
!       block = BLOCK_CHAIN (block);
!     }
  
    if (we_created_global_var)
      {  
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.145.2.6
diff -c -3 -p -r1.1.4.145.2.6 tree-cfg.c
*** tree-cfg.c	6 Oct 2003 00:55:01 -0000	1.1.4.145.2.6
--- tree-cfg.c	6 Oct 2003 23:15:45 -0000
*************** Boston, MA 02111-1307, USA.  */
*** 75,89 ****
     New blocks may be created on fallthru edges, and edges may be removed
     when they become unreachable.  The function tree_cleanup_edges fixes
     these issues (but it is ugly too.  The optimizations should be fixed
!    to keep the state consistent.)
!    
!    To handle bind_exprs and eh handling, there is kept a tree of blocks
!    (block_tree).  Some basic blocks are entry blocks of such constructs.
!    They must be kept unless the whole construct is to be removed.  One of
!    the entry edges may be marked with EDGE_CONSTRUCT_ENTRY flag; it then
!    is assumed to be the entry and it will be turned into fallthru when
!    the constructs are recreated.  All other edges should come from
!    inside of the construct.  */
  
  /* Local declarations.  */
  
--- 75,81 ----
     New blocks may be created on fallthru edges, and edges may be removed
     when they become unreachable.  The function tree_cleanup_edges fixes
     these issues (but it is ugly too.  The optimizations should be fixed
!    to keep the state consistent.)  */
  
  /* Local declarations.  */
  
*************** static dominance_info pdom_info = NULL;
*** 113,123 ****
  
  static struct cfg_stats_d cfg_stats;
  
- struct block_tree *block_tree;
- static struct block_tree *block_tree_curr;
- 
- static struct obstack block_tree_obstack;
- 
  static struct obstack block_ann_obstack;
  static void *first_block_ann_obj = 0;
  
--- 105,110 ----
*************** static void make_switch_expr_edges (basi
*** 140,146 ****
  static bool tree_redirect_edge_and_branch (edge, basic_block);
  
  /* Various helpers.  */
- static struct block_tree *block_tree_alloc (struct block_tree *);
  static inline bool stmt_starts_bb_p (tree, tree);
  static inline bool stmt_ends_bb_p (tree);
  static int tree_verify_flow_info (void);
--- 127,132 ----
*************** static edge find_taken_edge_switch_expr 
*** 158,165 ****
  static tree find_edge_goto (tree, edge);
  static bool value_matches_label (edge, tree, tree, edge *);
  static void tree_cleanup_edges (void);
- static void dump_block_tree_id (FILE *, struct block_tree *);
- static void assign_vars_to_scope (struct block_tree *);
  static void remove_superfluous_labels (void);
  static void thread_jumps (void);
  static bool tree_forwarder_block_p (basic_block);
--- 144,149 ----
*************** CASE_GOTO (tree_stmt_iterator tsi)
*** 185,191 ****
  #define CASE_DESTINATION(TSI) (GOTO_DESTINATION (CASE_GOTO (TSI)))
  #define CASE_CASE(TSI) (tsi_stmt(TSI))
  #define CASE_EDGE(TSI) (get_stmt_ann (CASE_CASE (TSI))->case_edge)
!      
  /* FIXME These need to be filled in with appropriate pointers.  But this
     implies an ABI change in some functions.  */
  struct cfg_hooks tree_cfg_hooks = {
--- 169,175 ----
  #define CASE_DESTINATION(TSI) (GOTO_DESTINATION (CASE_GOTO (TSI)))
  #define CASE_CASE(TSI) (tsi_stmt(TSI))
  #define CASE_EDGE(TSI) (get_stmt_ann (CASE_CASE (TSI))->case_edge)
! 
  /* FIXME These need to be filled in with appropriate pointers.  But this
     implies an ABI change in some functions.  */
  struct cfg_hooks tree_cfg_hooks = {
*************** build_tree_cfg (tree_cell fnbody)
*** 241,256 ****
        return;
      }
  
-   gcc_obstack_init (&block_tree_obstack);
-   block_tree = NULL;
-   block_tree_curr = NULL;
- 
    /* Create block annotations.  */
    create_blocks_annotations ();
  
    make_blocks (fnbody);
-   if (block_tree_curr)
-     abort ();
  
    if (n_basic_blocks > 0)
      {
--- 225,234 ----
*************** make_blocks (tree_cell stmt)
*** 370,376 ****
    tree_cell act, next;
    basic_block bb = NULL;
    tree prev_stmt;
-   struct block_tree *eht;
  
    if (stmt == NULL
        || stmt->stmt == error_mark_node)
--- 348,353 ----
*************** make_blocks (tree_cell stmt)
*** 380,415 ****
      {
        next = act->next;
  
-       if (act->note != TCN_STATEMENT)
- 	{
- 	  if (bb && bb->end_tree)
- 	    bb->end_tree->next = NULL;
- 	  if (act->next)
- 	    act->next->prev = NULL;
- 	  bb = create_bb ();
- 
- 	  switch (act->note)
- 	    {
- 	    case TCN_BIND:
- 	      eht = block_tree_alloc (block_tree_curr);
- 	      eht->entry = bb;
- 	      eht->bind = act->stmt;
- 	      block_tree_curr = eht;
- 	      bb_ann (bb)->block = block_tree_curr;
- 	      break;
- 
- 	    case TCN_UNBIND:
- 	      bb_ann (bb)->block = block_tree_curr;
- 	      block_tree_curr = block_tree_curr->outer;
- 	      break;
- 
- 	    default:
- 	      abort ();
- 	    }
- 	  bb = NULL;
- 	  continue;
- 	}
- 
        prev_stmt = act->prev ? act->prev->stmt : NULL_TREE;
        if (!bb || stmt_starts_bb_p (act->stmt, prev_stmt))
  	{
--- 357,362 ----
*************** make_blocks (tree_cell stmt)
*** 417,423 ****
  	    act->prev->next = NULL;
  	  act->prev = NULL;
  	  bb = create_bb ();
- 	  bb_ann (bb)->block = block_tree_curr;
  	}
  
        append_stmt_to_bb (act, bb);
--- 364,369 ----
*************** static void
*** 485,492 ****
  make_edges (void)
  {
    basic_block bb;
-   struct block_tree *bti;
-   edge e;
  
    /* Create an edge from entry to the first block with executable
       statements in it.  */
--- 431,436 ----
*************** make_edges (void)
*** 518,535 ****
    /* We do not care about fake edges, so remove any that the CFG
       builder inserted for completeness.  */
    remove_fake_edges ();
- 
-   /* Mark special edges of constructs.  */
-   for (bti = bti_start (); !bti_end_p (bti); bti_next (&bti))
-     if (bti->entry)
-       {
- 	for (e = bti->entry->pred; e; e = e->pred_next)
- 	  if (e->flags & EDGE_FALLTHRU)
- 	    break;
- 
- 	if (e)
- 	  e->flags |= EDGE_CONSTRUCT_ENTRY;
-       }
  }
  
  /* Create edges for control statement at basic block BB.  */
--- 462,467 ----
*************** remove_bb (basic_block bb)
*** 981,991 ****
    if (pdom_info)
      delete_from_dominance_info (pdom_info, bb);
  
-   /* If it is a special block of a block structure, remove the
-      reference.  */
-   if (bb_ann (bb)->block->entry == bb)
-     bb_ann (bb)->block->entry = NULL;
- 
    /* Remove the basic block from the array.  */
    expunge_block (bb);
  }
--- 913,918 ----
*************** tree_merge_blocks (basic_block a, basic_
*** 1066,1074 ****
    for (e = a->succ; e; e = e->succ_next)
      e->src = a;
  
-   if (bb_ann (b)->block->entry == b)
-     abort ();
- 
    /* Remove B.  */
    delete_basic_block (b);
  }
--- 993,998 ----
*************** dump_cfg_function_to_file (tree fn, FILE
*** 1480,1492 ****
  	    IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fn)));
    fprintf (file, "\n");
  
-   if (show_bb_headers)
-     {
-       fprintf (file, "\n# Block tree:\n");
-       dump_block_tree (file, 3, block_tree);
-       fprintf (file, "\n");
-     }
- 
    fprintf (file, "%s (", (*lang_hooks.decl_printable_name) (fn, 2));
  
    arg = DECL_ARGUMENTS (fn);
--- 1404,1409 ----
*************** dump_cfg_function_to_file (tree fn, FILE
*** 1503,1513 ****
      {
        if (show_bb_headers)
  	{
! 	  fprintf (file, "# BLOCK %d\n# CONSTRUCT ", bb->index);
! 	  dump_block_tree_id (file, bb_ann (bb)->block);
! 	  if (bb_ann (bb)->block->entry == bb)
! 	    fprintf (file, "(entry)");
! 	  fprintf (file, "\n# PRED");
  	  for (e = bb->pred; e; e = e->pred_next)
  	    dump_edge_info (file, e, 0);
  	  putc ('\n', file);
--- 1420,1427 ----
      {
        if (show_bb_headers)
  	{
! 	  fprintf (file, "# BLOCK %d\n ", bb->index);
! 	  fprintf (file, "# PRED");
  	  for (e = bb->pred; e; e = e->pred_next)
  	    dump_edge_info (file, e, 0);
  	  putc ('\n', file);
*************** is_computed_goto (tree t)
*** 1787,1827 ****
            && TREE_CODE (GOTO_DESTINATION (t)) != LABEL_DECL);
  }
  
- /* Allocates a block_tree node with outer node OUTER.  */
- static struct block_tree *
- block_tree_alloc (struct block_tree *outer)
- {
-   struct block_tree *nw = obstack_alloc (&block_tree_obstack,
- 					 sizeof (struct block_tree));
- 
-   nw->outer = outer;
-   nw->subtree = NULL;
-   nw->entry = NULL;
-   nw->bind = NULL_TREE;
- 
-   if (outer)
-     {
-       nw->next = outer->subtree;
-       outer->subtree = nw;
-       nw->level = outer->level + 1;
-     }
-   else
-     {
-       block_tree = nw;
-       nw->next = NULL;
-       nw->level = 0;
-     }
- 
-   return nw;
- }
- 
- /* Releases the block_tree obstack.  */
- void
- block_tree_free ()
- {
-   obstack_free (&block_tree_obstack, NULL);
- }
- 
  /* Return true if T should start a new basic block.  PREV_T is the
     statement preceding T.  It is used when T is a label or a case label.
     Labels should only start a new basic block if their previous statement
--- 1701,1706 ----
*************** bsi_insert_after (block_stmt_iterator *c
*** 2029,2039 ****
  		  enum bsi_iterator_update mode)
  {
    basic_block bb = curr_bsi->bb;
!   tree_cell curr, nw = ggc_alloc (sizeof (struct tree_container));
  
    set_bb_for_stmt (t, bb);
    curr = bsi_cell (*curr_bsi);
-   nw->stmt = t;
  
    if (!curr)
      {
--- 1908,1917 ----
  		  enum bsi_iterator_update mode)
  {
    basic_block bb = curr_bsi->bb;
!   tree_cell curr, nw = tree_cell_alloc (t);
  
    set_bb_for_stmt (t, bb);
    curr = bsi_cell (*curr_bsi);
  
    if (!curr)
      {
*************** bsi_insert_before (block_stmt_iterator *
*** 2074,2084 ****
  		   enum bsi_iterator_update mode)
  {
    basic_block bb = curr_bsi->bb;
!   tree_cell curr, nw = xmalloc (sizeof (struct tree_container));
  
    set_bb_for_stmt (t, bb);
    curr = bsi_cell (*curr_bsi);
-   nw->stmt = t;
  
    if (!curr)
      {
--- 1952,1961 ----
  		   enum bsi_iterator_update mode)
  {
    basic_block bb = curr_bsi->bb;
!   tree_cell curr, nw = tree_cell_alloc (t);
  
    set_bb_for_stmt (t, bb);
    curr = bsi_cell (*curr_bsi);
  
    if (!curr)
      {
*************** tree_split_edge (edge edge_in)
*** 2370,2376 ****
  
    dest = edge_in->dest;
    new_bb = create_bb ();
-   bb_ann (new_bb)->block = bb_ann (edge_in->src)->block;
  
    new_edge = make_edge (new_bb, dest, EDGE_FALLTHRU);
    /* Find all the PHI arguments on the original edge, and change them to
--- 2247,2252 ----
*************** tree_split_block (basic_block bb, block_
*** 2444,2451 ****
    for (e = new_bb->pred; e; e = e->pred_next)
      e->dest = new_bb;
  
-   bb_ann (new_bb)->block = bb_ann (bb)->block;
- 
    return make_edge (new_bb, bb, EDGE_FALLTHRU);
  }
  
--- 2320,2325 ----
*************** tree_verify_flow_info (void)
*** 2478,2484 ****
    tree t, l, label, phi;
    block_stmt_iterator si;
    edge e, le, te, fe;
-   struct block_tree *bti;
    int err = 0, degree;
  
    FOR_EACH_BB (bb)
--- 2352,2357 ----
*************** tree_verify_flow_info (void)
*** 2694,2708 ****
        degree = 0;
        for (e = bb->pred; e; e = e->pred_next)
  	{
- 	  if (bb != bb_ann (bb)->block->entry
- 	      && (e->flags & EDGE_CONSTRUCT_ENTRY))
- 	    {
- 	      fprintf (stderr,
- 		       "Construct entry edge not entering construct entry: %d\n",
- 		       bb->index);
- 	      err = 1;
- 	    }
- 
  	  for (phi = phi_nodes (bb); phi; phi = TREE_CHAIN (phi))
  	    if (phi_arg_from_edge (phi, e) < 0)
  	      {
--- 2567,2572 ----
*************** tree_verify_flow_info (void)
*** 2749,2773 ****
  	le = e;
        }
  
-   /* Check special edges of constructs.  */
-   for (bti = bti_start (); !bti_end_p (bti); bti_next (&bti))
-     if (bti->entry)
-       {
- 	le = NULL;
- 	for (e = bti->entry->pred; e; e = e->pred_next)
- 	  if (e->flags & EDGE_CONSTRUCT_ENTRY)
- 	    {
- 	      if (le)
- 		{
- 		  fprintf (stderr, "More than one construct %p entry\n",
- 			   (void *) bti);
- 		  err = 1;
- 		  break;
- 		}
- 	      le = e;
- 	    }
-       }
- 
    return err;
  }
  
--- 2613,2618 ----
*************** tree_register_cfg_hooks ()
*** 2996,3058 ****
  void
  debug_tree_chain (tree_cell start)
  {
-   tree op;
- 
    for (; start; start = start->next)
!     {
!       switch (start->note)
! 	{
! 	case TCN_STATEMENT:
! 	  debug_generic_stmt (start->stmt);
! 	  break;
! 
! 	case TCN_BIND:
! 	  fprintf (stderr, "{\n");
! 	  for (op = BIND_EXPR_VARS (start->stmt); op; op = TREE_CHAIN (op))
! 	    debug_generic_stmt (op);
! 	  break;
! 
! 	case TCN_UNBIND:
! 	  fprintf (stderr, "}\n");
! 	  break;
! 
! 	default:
! 	  abort ();
! 	}
!     }
! }
! 
! /* Dumps identification of BLOCK to FILE.  */
! static void
! dump_block_tree_id (FILE *file, struct block_tree *block)
! {
!   fprintf (file, "BIND %p", (void *) block);
! }
! 
! /* Dumps information about block tree BLOCK to FILE, indenting INDENT spaces.  */
! void
! dump_block_tree (FILE *file, int indent, struct block_tree *block)
! {
!   int i;
!   tree var;
! 
!   for (i = 0; i < indent; i++)
!     fprintf (file, " ");
!   dump_block_tree_id (file, block);
! 
!   fprintf (file, " vars");
!   for (var = BIND_EXPR_VARS (block->bind); var; var = TREE_CHAIN (var))
!     {
!       fprintf (file, " ");
!       print_generic_stmt (file, var, 0);
!     }
! 
!   if (block->entry)
!     fprintf (file, " entry %d", block->entry->index);
! 
!   fprintf (file, "\n");
!   for (block = block->subtree; block; block = block->next)
!     dump_block_tree (file, indent + 2, block);
  }
  
  /* Initialize loop optimizer.  */
--- 2841,2848 ----
  void
  debug_tree_chain (tree_cell start)
  {
    for (; start; start = start->next)
!     debug_generic_stmt (start->stmt);
  }
  
  /* Initialize loop optimizer.  */
*************** tree_loop_optimizer_finalize (struct loo
*** 3114,3139 ****
  #endif
  }
  
- /* Assigns a scope to variables defined in block SCOPE.  */
- static void
- assign_vars_to_scope (struct block_tree *scope)
- {
-   tree var;
- 
-   for (var = BIND_EXPR_VARS (scope->bind); var; var = TREE_CHAIN (var))
-     get_var_ann (var)->scope = scope;
- }
- 
- /* Assigns a scope in that it is defined to each variable.  */
- void
- assign_vars_to_scopes ()
- {
-   struct block_tree *act;
- 
-   for (act = bti_start (); !bti_end_p (act); bti_next (&act))
-     assign_vars_to_scope (act);
- }
- 
  /* Ensures that there are not useless labels.  It makes all jumps to
     the block to target one label (non-artificial ones are preferred),
     and removes all other artificial labels (the named ones are left
--- 2904,2909 ----
*************** tree_forwarder_block_p (basic_block bb)
*** 3231,3237 ****
    if (!bb->succ
        || bb->succ->succ_next
        || (bb->succ->flags & EDGE_ABNORMAL)
-       || (bb->succ->flags & EDGE_CONSTRUCT_ENTRY)
        || bb == ENTRY_BLOCK_PTR)
      return false; 
  
--- 3001,3006 ----
*************** thread_jumps ()
*** 3278,3284 ****
  	  next = e->succ_next;
  
  	  if ((e->flags & EDGE_ABNORMAL)
- 	      || (e->flags & EDGE_CONSTRUCT_ENTRY)
  	      || e->dest == EXIT_BLOCK_PTR
  	      || !tree_forwarder_block_p (e->dest)
  	      || e->dest->succ->dest == EXIT_BLOCK_PTR)
--- 3047,3052 ----
*************** find_edge_goto (tree stmt, edge e)
*** 3377,3402 ****
      }
  }
  
! /* Removes unneccesary variables.  */
! void 
! remove_useless_stmts_and_vars ()
  {
!   struct block_tree *bti;
!   tree vars, prev;
!   struct var_ann_d *ann;
  
!   for (bti = bti_start (); !bti_end_p (bti); bti_next (&bti))
      {
!       prev = NULL_TREE;
!       for (vars = BIND_EXPR_VARS (bti->bind);
  	   vars;
  	   vars = TREE_CHAIN (vars))
  	{
  	  /* We could have function declarations and the like
  	     on this list.  Ignore them.  */
  	  if (TREE_CODE (vars) != VAR_DECL)
  	    {
! 	      prev = vars;
  	      continue;
  	    }
  
--- 3145,3432 ----
      }
  }
  
! /* Merges blocks if possible.  */
! static void
! merge_seq_blocks ()
  {
!   basic_block bb;
  
!   for (bb = ENTRY_BLOCK_PTR->next_bb; bb != EXIT_BLOCK_PTR; )
      {
!       if (
! 	  /* It must have a single succesor.  */
! 	  bb->succ
! 	  && !bb->succ->succ_next
! 	  && !(bb->succ->flags & EDGE_ABNORMAL)
! 	  && bb->succ->dest != EXIT_BLOCK_PTR
! 	  && bb->succ->dest != bb
! 	  /* That has a single predecessor.  */
! 	  && !bb->succ->dest->pred->pred_next)
! 	{
! 	  /* Merge the blocks and retry.  */
! 	  merge_blocks (bb, bb->succ->dest);
! 	  continue;
! 	}
! 
!       bb = bb->next_bb;
!     }
! }
! 
! /* Non-cfg cleanup.  */
! 
! /* Walk the function tree removing unnecessary statements and
!    variables.
! 
!      * Empty statement nodes are removed
! 
!      * Unnecessary TRY_FINALLY and TRY_CATCH blocks are removed
! 
!      * Unnecessary COND_EXPRs are removed
! 
!      * Some unnecessary BIND_EXPRs are removed
! 
!    Clearly more work could be done.  The trick is doing the analysis
!    and removal fast enough to be a net improvement in compile times.
! 
!    Note that when we remove a control structure such as a COND_EXPR
!    BIND_EXPR, or TRY block, we will need to repeat this optimization pass
!    to ensure we eliminate all the useless code.  */
! 
! struct rusv_data
! {
!   bool repeat;
!   bool remove_unused_vars;
!   bool may_throw;
!   bool may_branch;
! };
! 
! static void remove_useless_stmts_and_vars_1 (tree *, struct rusv_data *);
! 
! static void
! remove_useless_stmts_and_vars_cond (tree *stmt_p, struct rusv_data *data)
! {
!   tree then_clause, else_clause, cond;
! 
!   remove_useless_stmts_and_vars_1 (&COND_EXPR_THEN (*stmt_p), data);
!   remove_useless_stmts_and_vars_1 (&COND_EXPR_ELSE (*stmt_p), data);
! 
!   then_clause = COND_EXPR_THEN (*stmt_p);
!   else_clause = COND_EXPR_ELSE (*stmt_p);
!   cond = COND_EXPR_COND (*stmt_p);
! 
!   /* We may not have been able to completely optimize away the condition
!      previously due to the existence of a label in one arm.  If the label
!      has since become unreachable then we may be able to zap the entire
!      conditional here.  If so, replace the COND_EXPR and set up to repeat
!      this optimization pass.  */
!   if (integer_nonzerop (cond) && IS_EMPTY_STMT (else_clause))
!     {
!       *stmt_p = then_clause;
!        data->repeat = true;
!     }
!   else if (integer_zerop (cond) && IS_EMPTY_STMT (then_clause))
!     {
!       *stmt_p = else_clause;
!       data->repeat = true;
!     }
! 
!   /* Notice branches to a common destination.  */
!   else if (TREE_CODE (then_clause) == GOTO_EXPR
! 	   && TREE_CODE (else_clause) == GOTO_EXPR
! 	   && (GOTO_DESTINATION (then_clause)
! 	       == GOTO_DESTINATION (else_clause)))
!     {
!       *stmt_p = then_clause;
!       data->repeat = true;
!     }
! 
!   /* If the THEN/ELSE clause merely assigns a value to a variable/parameter
!      which is already known to contain that value, then remove the useless
!      THEN/ELSE clause.  */
!   else if (TREE_CODE (cond) == VAR_DECL || TREE_CODE (cond) == PARM_DECL)
!     {
!       if (TREE_CODE (else_clause) == MODIFY_EXPR
! 	  && TREE_OPERAND (else_clause, 0) == cond
! 	  && integer_zerop (TREE_OPERAND (else_clause, 1)))
! 	COND_EXPR_ELSE (*stmt_p) = build_empty_stmt ();
!     }
!   else if ((TREE_CODE (cond) == EQ_EXPR || TREE_CODE (cond) == NE_EXPR)
! 	   && (TREE_CODE (TREE_OPERAND (cond, 0)) == VAR_DECL
! 	       || TREE_CODE (TREE_OPERAND (cond, 0)) == PARM_DECL)
! 	   && TREE_CONSTANT (TREE_OPERAND (cond, 1)))
!     {
!       tree clause = (TREE_CODE (cond) == EQ_EXPR
! 		     ? then_clause : else_clause);
!       tree *location = (TREE_CODE (cond) == EQ_EXPR
! 			? &COND_EXPR_THEN (*stmt_p)
! 			: &COND_EXPR_ELSE (*stmt_p));
! 
!       if (TREE_CODE (clause) == MODIFY_EXPR
! 	  && TREE_OPERAND (clause, 0) == TREE_OPERAND (cond, 0)
! 	  && TREE_OPERAND (clause, 1) == TREE_OPERAND (cond, 1))
! 	*location = build_empty_stmt ();
!     }
! }
! 
! static void
! remove_useless_stmts_and_vars_tf (tree *stmt_p, struct rusv_data *data)
! {
!   bool save_may_branch, save_may_throw;
!   bool this_may_branch, this_may_throw;
! 
!   /* Collect may_branch and may_throw information for the body only.  */
!   save_may_branch = data->may_branch;
!   save_may_throw = data->may_throw;
!   data->may_branch = false;
!   data->may_throw = false;
! 
!   remove_useless_stmts_and_vars_1 (&TREE_OPERAND (*stmt_p, 0), data);
! 
!   this_may_branch = data->may_branch;
!   this_may_throw = data->may_throw;
!   data->may_branch |= save_may_branch;
!   data->may_throw |= save_may_throw;
! 
!   remove_useless_stmts_and_vars_1 (&TREE_OPERAND (*stmt_p, 1), data);
! 
!   /* If the body is empty, then we can emit the FINALLY block without
!      the enclosing TRY_FINALLY_EXPR.  */
!   if (IS_EMPTY_STMT (TREE_OPERAND (*stmt_p, 0)))
!     {
!       *stmt_p = TREE_OPERAND (*stmt_p, 1);
!       data->repeat = true;
!     }
! 
!   /* If the handler is empty, then we can emit the TRY block without
!      the enclosing TRY_FINALLY_EXPR.  */
!   else if (IS_EMPTY_STMT (TREE_OPERAND (*stmt_p, 1)))
!     {
!       *stmt_p = TREE_OPERAND (*stmt_p, 0);
!       data->repeat = true;
!     }
! 
!   /* If the body neither throws, nor branches, then we can safely string
!      the TRY and FINALLY blocks together.  We'll reassociate this in the
!      main body of remove_useless_stmts_and_vars.  */
!   else if (!this_may_branch && !this_may_throw)
!     TREE_SET_CODE (*stmt_p, COMPOUND_EXPR);
! }
! 
! static void
! remove_useless_stmts_and_vars_tc (tree *stmt_p, struct rusv_data *data)
! {
!   bool save_may_throw, this_may_throw;
!   tree_stmt_iterator i;
!   tree stmt;
! 
!   /* Collect may_throw information for the body only.  */
!   save_may_throw = data->may_throw;
!   data->may_throw = false;
! 
!   remove_useless_stmts_and_vars_1 (&TREE_OPERAND (*stmt_p, 0), data);
! 
!   this_may_throw = data->may_throw;
!   data->may_throw = save_may_throw;
! 
!   /* If the body cannot throw, then we can drop the entire TRY_CATCH_EXPR.  */
!   if (!this_may_throw)
!     {
!       *stmt_p = TREE_OPERAND (*stmt_p, 0);
!       data->repeat = true;
!       return;
!     }
! 
!   /* Process the catch clause specially.  We may be able to tell that
!      no exceptions propagate past this point.  */
! 
!   this_may_throw = true;
!   i = tsi_start (&TREE_OPERAND (*stmt_p, 1));
!   stmt = tsi_stmt (i);
! 
!   switch (TREE_CODE (stmt))
!     {
!     case CATCH_EXPR:
!       for (; !tsi_end_p (i); tsi_next (&i))
! 	{
! 	  stmt = tsi_stmt (i);
! 	  /* If we catch all exceptions, then the body does not
! 	     propagate exceptions past this point.  */
! 	  if (CATCH_TYPES (stmt) == NULL)
! 	    this_may_throw = false;
! 	  remove_useless_stmts_and_vars_1 (&CATCH_BODY (stmt), data);
! 	}
!       break;
! 
!     case EH_FILTER_EXPR:
!       if (EH_FILTER_MUST_NOT_THROW (stmt))
! 	this_may_throw = false;
!       else if (EH_FILTER_TYPES (stmt) == NULL)
! 	this_may_throw = false;
!       remove_useless_stmts_and_vars_1 (&EH_FILTER_FAILURE (stmt), data);
!       break;
! 
!     default:
!       /* Otherwise this is a cleanup.  */
!       remove_useless_stmts_and_vars_1 (&TREE_OPERAND (*stmt_p, 1), data);
! 
!       /* If the cleanup is empty, then we can emit the TRY block without
! 	 the enclosing TRY_CATCH_EXPR.  */
!       if (IS_EMPTY_STMT (TREE_OPERAND (*stmt_p, 1)))
! 	{
! 	  *stmt_p = TREE_OPERAND (*stmt_p, 0);
! 	  data->repeat = true;
! 	}
!       break;
!     }
!   data->may_throw |= this_may_throw;
! }
! 
! static void
! remove_useless_stmts_and_vars_bind (tree *stmt_p, struct rusv_data *data)
! {
!   tree block;
! 
!   /* First remove anything underneath the BIND_EXPR.  */
!   remove_useless_stmts_and_vars_1 (&BIND_EXPR_BODY (*stmt_p), data);
! 
!   /* If the BIND_EXPR has no variables, then we can pull everything
!      up one level and remove the BIND_EXPR, unless this is the toplevel
!      BIND_EXPR for the current function or an inlined function.
! 
!      When this situation occurs we will want to apply this
!      optimization again.  */
!   block = BIND_EXPR_BLOCK (*stmt_p);
!   if (BIND_EXPR_VARS (*stmt_p) == NULL_TREE
!       && *stmt_p != DECL_SAVED_TREE (current_function_decl)
!       && (! block
! 	  || ! BLOCK_ABSTRACT_ORIGIN (block)
! 	  || (TREE_CODE (BLOCK_ABSTRACT_ORIGIN (block))
! 	      != FUNCTION_DECL)))
!     {
!       *stmt_p = BIND_EXPR_BODY (*stmt_p);
!       data->repeat = true;
!     }
!   else if (data->remove_unused_vars)
!     {
!       /* If we were unable to completely eliminate the BIND_EXPR,
! 	 go ahead and prune out any unused variables.  We do not
! 	 want to expand them as that is a waste of time.  If we
! 	 happen to remove all the variables, then we may be able
! 	 to eliminate the BIND_EXPR as well.  */
!       tree vars, prev_var;
! 
!       /* Walk all the variables associated with the BIND_EXPR.  */
!       for (prev_var = NULL, vars = BIND_EXPR_VARS (*stmt_p);
  	   vars;
  	   vars = TREE_CHAIN (vars))
  	{
+ 	  struct var_ann_d *ann;
+ 
  	  /* We could have function declarations and the like
  	     on this list.  Ignore them.  */
  	  if (TREE_CODE (vars) != VAR_DECL)
  	    {
! 	      prev_var = vars;
  	      continue;
  	    }
  
*************** remove_useless_stmts_and_vars ()
*** 3411,3460 ****
  	      && ! TREE_ADDRESSABLE (vars)
  	      && (DECL_ARTIFICIAL (vars) || optimize >= 2))
  	    {
! 	      tree block = BIND_EXPR_BLOCK (bti->bind);
! 
  	      if (block)
! 		remove_decl (vars, block);
! 	      else
! 		remove_decl (vars, DECL_INITIAL (current_function_decl));
! 
! 	      if (prev)
! 		TREE_CHAIN (prev) = TREE_CHAIN (vars);
  	      else
! 		BIND_EXPR_VARS (bti->bind) = TREE_CHAIN (vars);
  	    }
  	  else
! 	    prev = vars;
  	}
      }
  }
  
- /* Merges blocks if possible.  */
  static void
! merge_seq_blocks ()
  {
!   basic_block bb;
  
!   for (bb = ENTRY_BLOCK_PTR->next_bb; bb != EXIT_BLOCK_PTR; )
      {
!       if (
! 	  /* It must have a single succesor.  */
! 	  bb->succ
! 	  && !bb->succ->succ_next
! 	  && !(bb->succ->flags & EDGE_ABNORMAL)
! 	  && !(bb->succ->flags & EDGE_CONSTRUCT_ENTRY)
! 	  && bb->succ->dest != EXIT_BLOCK_PTR
! 	  && bb->succ->dest != bb
! 	  /* That has a single predecessor.  */
! 	  && !bb->succ->dest->pred->pred_next
! 	  /* Don't merge blocks from different contexts.  */
! 	  && bb_ann (bb)->block == bb_ann (bb->succ->dest)->block)
  	{
! 	  /* Merge the blocks and retry.  */
! 	  merge_blocks (bb, bb->succ->dest);
! 	  continue;
  	}
  
!       bb = bb->next_bb;
      }
  }
--- 3441,3583 ----
  	      && ! TREE_ADDRESSABLE (vars)
  	      && (DECL_ARTIFICIAL (vars) || optimize >= 2))
  	    {
! 	      /* Remove the variable from the BLOCK structures.  */
  	      if (block)
! 		remove_decl (vars,
! 			     (block
! 			      ? block
! 			      : DECL_INITIAL (current_function_decl)));
! 
! 	      /* And splice the variable out of BIND_EXPR_VARS.  */
! 	      if (prev_var)
! 		TREE_CHAIN (prev_var) = TREE_CHAIN (vars);
  	      else
! 		BIND_EXPR_VARS (*stmt_p) = TREE_CHAIN (vars);
  	    }
  	  else
! 	    prev_var = vars;
! 	}
! 
!       /* If there are no variables left after removing unused
! 	 variables, then go ahead and remove this BIND_EXPR.  */
!       if (BIND_EXPR_VARS (*stmt_p) == NULL_TREE
! 	  && *stmt_p != DECL_SAVED_TREE (current_function_decl)
! 	  && (! block
! 	      || ! BLOCK_ABSTRACT_ORIGIN (block)
! 	      || (TREE_CODE (BLOCK_ABSTRACT_ORIGIN (block))
! 		  != FUNCTION_DECL)))
! 	{
! 	  *stmt_p = BIND_EXPR_BODY (*stmt_p);
! 	  data->repeat = true;
  	}
      }
  }
  
  static void
! remove_useless_stmts_and_vars_goto (tree_stmt_iterator i, tree *stmt_p,
! 				    struct rusv_data *data)
  {
!   tree_stmt_iterator tsi = i;
  
!   /* Step past the GOTO_EXPR statement.  */
!   tsi_next (&tsi);
!   if (! tsi_end_p (tsi))
      {
!       /* If we are not at the end of this tree, then see if
! 	 we are at the target label.  If so, then this jump
! 	 is not needed.  */
!       tree label;
! 
!       label = tsi_stmt (tsi);
!       if (TREE_CODE (label) == LABEL_EXPR
! 	  && LABEL_EXPR_LABEL (label) == GOTO_DESTINATION (*stmt_p))
  	{
! 	  data->repeat = true;
! 	  *stmt_p = build_empty_stmt ();
! 	  return;
  	}
+     }
  
!   data->may_branch = true;
! }
! 
! static void
! remove_useless_stmts_and_vars_1 (tree *first_p, struct rusv_data *data)
! {
!   tree_stmt_iterator i;
! 
!   for (i = tsi_start (first_p); !tsi_end_p (i); tsi_next (&i))
!     {
!       tree *container_p = tsi_container (i);
!       tree *stmt_p;
!       enum tree_code code;
! 
!       while (TREE_CODE (*container_p) == COMPOUND_EXPR)
! 	{
! 	  /* If either operand of a COMPOUND_EXPR is an empty statement,
! 	     then remove the empty statement and the COMPOUND_EXPR itself.  */
! 	  if (IS_EMPTY_STMT (TREE_OPERAND (*container_p, 1)))
! 	    *container_p = TREE_OPERAND (*container_p, 0);
! 	  else if (IS_EMPTY_STMT (TREE_OPERAND (*container_p, 0)))
! 	    *container_p = TREE_OPERAND (*container_p, 1);
! 	  else
! 	    break;
! 	}
! 
!       /* Dive into control structures.  */
!       stmt_p = tsi_stmt_ptr (i);
!       code = TREE_CODE (*stmt_p);
!       switch (code)
! 	{
! 	case COND_EXPR:
! 	  remove_useless_stmts_and_vars_cond (stmt_p, data);
! 	  break;
! 	case SWITCH_EXPR:
! 	  remove_useless_stmts_and_vars_1 (&SWITCH_BODY (*stmt_p), data);
! 	  break;
! 	case TRY_FINALLY_EXPR:
! 	  remove_useless_stmts_and_vars_tf (stmt_p, data);
! 	  break;
! 	case TRY_CATCH_EXPR:
! 	  remove_useless_stmts_and_vars_tc (stmt_p, data);
! 	  break;
! 	case BIND_EXPR:
! 	  remove_useless_stmts_and_vars_bind (stmt_p, data);
! 	  break;
! 	case GOTO_EXPR:
! 	  remove_useless_stmts_and_vars_goto (i, stmt_p, data);
! 	  break;
! 	case RETURN_EXPR:
! 	  data->may_branch = true;
! 	  break;
! 	case MODIFY_EXPR:
! 	case CALL_EXPR:
! 	  if (tree_could_throw_p (*stmt_p))
! 	    data->may_throw = true;
! 	  break;
! 	default:
! 	  break;
! 	}
! 
!       /* We need to keep the tree in gimple form, so we may have to
! 	 re-rationalize COMPOUND_EXPRs.  */
!       if (TREE_CODE (*container_p) == COMPOUND_EXPR
! 	  && TREE_CODE (TREE_OPERAND (*container_p, 0)) == COMPOUND_EXPR)
! 	*container_p = rationalize_compound_expr (*container_p);
!     }
! }
! 
! void
! remove_useless_stmts_and_vars (tree *first_p, bool remove_unused_vars)
! {
!   struct rusv_data data;
!   do
!     {
!       memset (&data, 0, sizeof (data));
!       data.remove_unused_vars = remove_unused_vars;
!       remove_unused_vars = false;
! 
!       remove_useless_stmts_and_vars_1 (first_p, &data);
      }
+   while (data.repeat);
  }
Index: tree-flatten.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flatten.c,v
retrieving revision 1.1.2.5
diff -c -3 -p -r1.1.2.5 tree-flatten.c
*** tree-flatten.c	6 Oct 2003 00:55:02 -0000	1.1.2.5
--- tree-flatten.c	6 Oct 2003 23:15:45 -0000
*************** Boston, MA 02111-1307, USA.  */
*** 45,74 ****
  #include "except.h"
  #include "cfgloop.h"
  
! static void append (tree_cell *, tree, enum tree_container_note);
! static void recreate_block_constructs (struct block_tree *);
! static basic_block compact_to_block (struct block_tree *);
  static void link_consec_statements (basic_block, basic_block);
- static int dummy_verify_flow_info (void);
  
! /* Allocate a new tree_cell for tree T with NOTE.  */
  tree_cell
! tree_cell_alloc (tree t, enum tree_container_note note)
  {
    tree_cell nw = ggc_alloc (sizeof (struct tree_container));
  
    nw->stmt = t;
-   nw->note = note;
    nw->prev = nw->next = NULL;
  
    return nw;
  }
  
! /* Appends statement STMT with NOTE to the end of list AFTER.  */
  static void
! append (tree_cell *after, tree stmt, enum tree_container_note note)
  {
!   tree_cell nw = tree_cell_alloc (stmt, note);
  
    nw->next = NULL;
    nw->prev = *after;
--- 45,73 ----
  #include "except.h"
  #include "cfgloop.h"
  
! static void append (tree_cell *, tree);
! static basic_block compact_to_block (void);
  static void link_consec_statements (basic_block, basic_block);
  
! /* Allocate a new tree_cell for tree T.  */
  tree_cell
! tree_cell_alloc (tree t)
  {
    tree_cell nw = ggc_alloc (sizeof (struct tree_container));
  
    nw->stmt = t;
    nw->prev = nw->next = NULL;
+   nw->next_in_gc_chain = cfun->tree_containers_root;
+   cfun->tree_containers_root = nw;
  
    return nw;
  }
  
! /* Appends statement STMT to the end of list AFTER.  */
  static void
! append (tree_cell *after, tree stmt)
  {
!   tree_cell nw = tree_cell_alloc (stmt);
  
    nw->next = NULL;
    nw->prev = *after;
*************** tree_flatten_statement (tree stmt, tree_
*** 84,109 ****
  {
    switch (TREE_CODE (stmt))
      {
-     case BIND_EXPR:
-       {
- 	/* Do not record empty BIND_EXPRs, unless they are top-level ones
- 	   (or top-level ones of inlined functions).  */
- 	tree block = BIND_EXPR_BLOCK (stmt);
- 	int record = (BIND_EXPR_VARS (stmt)
- 		      || stmt == DECL_SAVED_TREE (current_function_decl)
- 		      || (block
- 			  && BLOCK_ABSTRACT_ORIGIN (block)
- 			  && (TREE_CODE (BLOCK_ABSTRACT_ORIGIN (block))
- 			      == FUNCTION_DECL)));
- 
- 	if (record)
- 	  append (after, stmt, TCN_BIND);
- 	tree_flatten_statement (BIND_EXPR_BODY (stmt), after, enclosing_switch);
- 	if (record)
- 	  append (after, NULL_TREE, TCN_UNBIND);
-       }
-       break;
- 
      case COMPOUND_EXPR:
        tree_flatten_statement (TREE_OPERAND (stmt, 0), after, enclosing_switch);
        tree_flatten_statement (TREE_OPERAND (stmt, 1), after, enclosing_switch);
--- 83,88 ----
*************** tree_flatten_statement (tree stmt, tree_
*** 122,128 ****
      case RESX_EXPR:
      case COND_EXPR:
      case SWITCH_EXPR:
!       append (after, stmt, TCN_STATEMENT);
        break;
  
      default:
--- 101,107 ----
      case RESX_EXPR:
      case COND_EXPR:
      case SWITCH_EXPR:
!       append (after, stmt);
        break;
  
      default:
*************** link_consec_statements (basic_block from
*** 211,343 ****
    bsi_insert_after (&bsi, top, BSI_NEW_STMT);
  }
  
! /* Compacts the whole block corresponding to NODE to single basic block with
!    single statement. The basic block is returned.
     
     TODO -- before compacting the blocks, we should sort them so that the
     number of jumps is decreased, and to remove those jumps.  Concretely
     if we have a basic ending with COND_EXPR, we should try to put the
     else branch bb immediately after the block.  */
  static basic_block
! compact_to_block (struct block_tree *node)
  {
!   basic_block entry, last, act, next;
  
!   if (!node->outer)
!     {
!       entry = ENTRY_BLOCK_PTR->next_bb;
!       last = EXIT_BLOCK_PTR->prev_bb;
!     }
!   else
!     {
!       /* Make the blocks of the node to be consecutive.  */
!       if (node->entry)
! 	entry = node->entry;
!       else
! 	{
! 	  FOR_EACH_BB (entry)
! 	    {
! 	      if (bb_ann (entry)->block == node)
! 		break;
! 	    }
! 	  if (entry == EXIT_BLOCK_PTR)
! 	    return NULL;
! 	}
!       last = entry;
! 
!       for (act = ENTRY_BLOCK_PTR->next_bb; act != EXIT_BLOCK_PTR; act = next)
! 	{
! 	  next = act->next_bb;
! 
! 	  if (act == entry)
! 	    {
! 	      next = last->next_bb;
! 	      continue;
! 	    }
! 
! 	  if (bb_ann (act)->block != node)
! 	    continue;
! 
! 	  tree_move_block_after (act, last, true);
! 	  last = act;
! 	}
! 
!       /* Ensure that the block is entered through its entry edge as
! 	 fallthru.  */
!       if (node->entry)
! 	{
! 	  edge e;
! 
! 	  for (e = node->entry->pred; e; e = e->pred_next)
! 	    if (e->flags & EDGE_CONSTRUCT_ENTRY)
! 	      break;
! 	  if (e)
! 	    {
! 	      if (entry->prev_bb != e->src)
! 		tree_move_block_after (e->src, entry->prev_bb, false);
! 
! 	      if (!(e->flags & EDGE_FALLTHRU))
! 		{
! 		  act = split_edge (e);
! 		  tree_move_block_after (act, entry->prev_bb, false);
! 	      
! 		  if (!(act->succ->flags & EDGE_FALLTHRU))
! 		    abort ();
! 		}
! 	    }
! 	}
!     }
  
    link_consec_statements (entry, last);
-   bb_ann (entry)->block = node->outer;
-   node->entry = NULL;
  
    return entry;
  }
  
! /* Recreates block structures for block tree NODE.  */
! static void
! recreate_block_constructs (struct block_tree *node)
! {
!   struct block_tree *son;
!   basic_block bb;
!   block_stmt_iterator bsi;
!   tree construct;
!   tree block;
! 
!   for (son = node->subtree; son; son = son->next)
!     recreate_block_constructs (son);
! 
!   bb = compact_to_block (node);
! 
!   if (!bb)
!     return;
! 
!   construct = node->bind;
!   /* Do not create useless bind_exprs.  */
!   if (construct
!       && (BIND_EXPR_VARS (construct)
! 	  || !node->outer
! 	  || ((block = BIND_EXPR_BLOCK (construct))
! 	      && BLOCK_ABSTRACT_ORIGIN (block)
! 	      && (TREE_CODE (BLOCK_ABSTRACT_ORIGIN (block))
! 		  == FUNCTION_DECL))))
!     {
!       BIND_EXPR_BODY (construct) = last_stmt (bb);
!       TREE_SIDE_EFFECTS (construct) = 1;
!       bsi = bsi_last (bb);
!       bsi_replace (bsi, construct);
!     }
! }
! 
! /* Dummy function for verify_flow_info.  */
! static int
! dummy_verify_flow_info ()
! {
!   return 0;
! }
! 
! /* Recreate a simple block structure.  */
  tree
  tree_unflatten_statements ()
  {
--- 190,216 ----
    bsi_insert_after (&bsi, top, BSI_NEW_STMT);
  }
  
! /* Compacts the whole chain to a single basic block with single statement. The
!    basic block is returned.
     
     TODO -- before compacting the blocks, we should sort them so that the
     number of jumps is decreased, and to remove those jumps.  Concretely
     if we have a basic ending with COND_EXPR, we should try to put the
     else branch bb immediately after the block.  */
  static basic_block
! compact_to_block ()
  {
!   basic_block entry, last;
  
!   entry = ENTRY_BLOCK_PTR->next_bb;
!   last = EXIT_BLOCK_PTR->prev_bb;
  
    link_consec_statements (entry, last);
  
    return entry;
  }
  
! /* Plug the statements back into toplevel BIND_EXPR.  */
  tree
  tree_unflatten_statements ()
  {
*************** tree_unflatten_statements ()
*** 345,356 ****
    edge e, next;
    block_stmt_iterator bsi;
    tree stmts;
-   int (*old_cfgh_verify_flow_info) (void);
- 
-   /* Cfg -- code correspondence is not going to work; still we would
-      like to be able to check consistency of cfg.  A bit hacky.  */
-   old_cfgh_verify_flow_info = cfg_hooks->cfgh_verify_flow_info;
-   cfg_hooks->cfgh_verify_flow_info = dummy_verify_flow_info;
  
    /* Remove abnormal edges; they are no longer needed nor used, and
       it is faster to remove them now than to handle them later.  */
--- 218,223 ----
*************** tree_unflatten_statements ()
*** 394,408 ****
        tree_cleanup_block_edges (bb, true);
      }
  
!   recreate_block_constructs (block_tree);
    if (n_basic_blocks != 1)
      abort ();
    stmts = last_stmt (ENTRY_BLOCK_PTR->next_bb);
    if (stmts != first_stmt (ENTRY_BLOCK_PTR->next_bb))
      abort ();
  
-   block_tree_free ();
-   cfg_hooks->cfgh_verify_flow_info = old_cfgh_verify_flow_info;
    delete_tree_cfg ();
  
    return stmts;
--- 261,273 ----
        tree_cleanup_block_edges (bb, true);
      }
  
!   compact_to_block ();
    if (n_basic_blocks != 1)
      abort ();
    stmts = last_stmt (ENTRY_BLOCK_PTR->next_bb);
    if (stmts != first_stmt (ENTRY_BLOCK_PTR->next_bb))
      abort ();
  
    delete_tree_cfg ();
  
    return stmts;
Index: tree-flow-inline.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow-inline.h,v
retrieving revision 1.1.2.47.2.2
diff -c -3 -p -r1.1.2.47.2.2 tree-flow-inline.h
*** tree-flow-inline.h	2 Oct 2003 22:02:29 -0000	1.1.2.47.2.2
--- tree-flow-inline.h	6 Oct 2003 23:15:45 -0000
*************** add_dom_child (basic_block bb, basic_blo
*** 317,323 ****
  {
    bb_ann_t ann = bb_ann (bb);
    if (ann->dom_children == NULL)
!     ann->dom_children = BITMAP_GGC_ALLOC ();
    bitmap_set_bit (ann->dom_children, child_bb->index);
  }
  
--- 317,323 ----
  {
    bb_ann_t ann = bb_ann (bb);
    if (ann->dom_children == NULL)
!     ann->dom_children = BITMAP_XMALLOC ();
    bitmap_set_bit (ann->dom_children, child_bb->index);
  }
  
*************** remove_dom_child (basic_block bb, basic_
*** 337,380 ****
  static inline void
  clear_dom_children (basic_block bb)
  {
!   bb_ann (bb)->dom_children = NULL;
  }
  
  static inline bitmap
  dom_children (basic_block bb)
  {
    return bb_ann (bb)->dom_children;
- }
- 
- /*  -----------------------------------------------------------------------  */
- 
- static inline struct block_tree *
- bti_start ()
- {
-   return block_tree;
- }
- 
- static inline bool
- bti_end_p (struct block_tree *block)
- {
-   return !block;
- }
- 
- static inline void
- bti_next (struct block_tree **block)
- {
-   struct block_tree *act = *block;
- 
-   if (act->subtree)
-     {
-       *block = act->subtree;
-       return;
-     }
- 
-   while (act->outer && !act->next)
-     act = act->outer;
- 
-   *block = act->next;
  }
  
  static inline bool
--- 337,353 ----
  static inline void
  clear_dom_children (basic_block bb)
  {
!   if (bb_ann (bb)->dom_children)
!     {
!       BITMAP_XFREE (bb_ann (bb)->dom_children);
!       bb_ann (bb)->dom_children = NULL;
!     }
  }
  
  static inline bitmap
  dom_children (basic_block bb)
  {
    return bb_ann (bb)->dom_children;
  }
  
  static inline bool
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.101.2.4
diff -c -3 -p -r1.1.4.101.2.4 tree-flow.h
*** tree-flow.h	5 Oct 2003 19:25:44 -0000	1.1.4.101.2.4
--- tree-flow.h	6 Oct 2003 23:15:45 -0000
*************** struct basic_block_def;
*** 36,71 ****
  typedef struct basic_block_def *basic_block;
  #endif
  
- /* A list of containers in that statements are stored.  */
- enum tree_container_note
- {
-   TCN_STATEMENT,
-   TCN_BIND,
-   TCN_UNBIND
- };
- 
  struct tree_container GTY (())
  {
    struct tree_container *prev;
    struct tree_container *next;
    tree stmt;
-   enum tree_container_note note;
  };
  
  typedef struct tree_container *tree_cell;
  
- extern struct block_tree
- {
-   basic_block entry;
- 
-   tree bind;			/* The corresponding bindings.  */
-  
-   int level;
-   struct block_tree *outer;
-   struct block_tree *subtree;
-   struct block_tree *next;
- } *block_tree;
- 
  /*---------------------------------------------------------------------------
  		   Tree annotations stored in tree_common.ann
  ---------------------------------------------------------------------------*/
--- 36,51 ----
  typedef struct basic_block_def *basic_block;
  #endif
  
  struct tree_container GTY (())
  {
    struct tree_container *prev;
    struct tree_container *next;
+   struct tree_container *next_in_gc_chain;
    tree stmt;
  };
  
  typedef struct tree_container *tree_cell;
  
  /*---------------------------------------------------------------------------
  		   Tree annotations stored in tree_common.ann
  ---------------------------------------------------------------------------*/
*************** struct var_ann_d GTY(())
*** 151,159 ****
    /* Used by the root-var object in tree-ssa-live.[ch].  */
    unsigned root_index;
  
-   /* Scope in that the variable is defined.  */
-   struct block_tree * GTY ((skip (""))) scope;
- 
    /* Default definition for this symbol.  If this field is not NULL, it
       means that the first reference to this variable in the function is a
       USE or a VUSE.  In those cases, the SSA renamer creates an SSA name
--- 131,136 ----
*************** struct bb_ann_d
*** 332,340 ****
  
    /* Set of blocks immediately dominated by this node.  */
    bitmap dom_children;
- 
-   /* Block it belongs to.  */
-   struct block_tree *block;
  };
  
  typedef struct bb_ann_d *bb_ann_t;
--- 309,314 ----
*************** static inline tree phi_nodes (basic_bloc
*** 345,355 ****
  static inline void add_dom_child (basic_block, basic_block);
  static inline bitmap dom_children (basic_block);
  
- /* Iterator for traversing block tree.  */
- static inline struct block_tree *bti_start (void);
- static inline bool bti_end_p (struct block_tree *);
- static inline void bti_next (struct block_tree **);
- 
  /*---------------------------------------------------------------------------
  		 Iterators for statements inside a basic block
  ---------------------------------------------------------------------------*/
--- 319,324 ----
*************** extern GTY(()) varray_type call_clobbere
*** 437,443 ****
  ---------------------------------------------------------------------------*/
  /* In tree-cfg.c  */
  extern void build_tree_cfg (tree_cell);
- extern void dump_block_tree (FILE *, int, struct block_tree *);
  extern void delete_tree_cfg (void);
  extern bool is_ctrl_stmt (tree);
  extern bool is_ctrl_altering_stmt (tree);
--- 406,411 ----
*************** extern void dump_cfg_stats (FILE *);
*** 452,458 ****
  extern void debug_cfg_stats (void);
  extern void tree_cfg2dot (FILE *);
  extern void cleanup_tree_cfg (int);
- extern void remove_useless_stmts_and_vars (void);
  extern void remove_phi_nodes_and_edges_for_unreachable_block (basic_block);
  extern tree first_stmt (basic_block);
  extern tree last_stmt (basic_block);
--- 420,425 ----
*************** extern tree *last_stmt_ptr (basic_block)
*** 460,475 ****
  extern edge find_taken_edge (basic_block, tree);
  extern int call_expr_flags (tree);
  extern basic_block tree_split_edge (edge);
- extern void block_tree_free (void);
  extern void tree_move_block_after (basic_block, basic_block, int);
  extern edge tree_split_block (basic_block, block_stmt_iterator);
  extern void tree_cleanup_block_edges (basic_block, int);
- extern void assign_vars_to_scopes (void);
  extern tree build_new_label (void);
  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 basic_block label_to_block (tree);
  
  /* In tree-dfa.c  */
  void find_referenced_vars (tree);
--- 427,441 ----
  extern edge find_taken_edge (basic_block, tree);
  extern int call_expr_flags (tree);
  extern basic_block tree_split_edge (edge);
  extern void tree_move_block_after (basic_block, basic_block, int);
  extern edge tree_split_block (basic_block, block_stmt_iterator);
  extern void tree_cleanup_block_edges (basic_block, int);
  extern tree build_new_label (void);
  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 basic_block label_to_block (tree);
+ extern void remove_useless_stmts_and_vars (tree *, bool);
  
  /* In tree-dfa.c  */
  void find_referenced_vars (tree);
*************** void tree_ssa_dce (tree, enum tree_dump_
*** 553,560 ****
  
  /* In tree-ssa-copyprop.c  */
  void tree_ssa_copyprop (tree, enum tree_dump_index);
! void propagate_copy (basic_block, tree *, tree);
! void fixup_var_scope (basic_block, tree);
  
  /* In tree-flow-inline.h  */
  static inline int phi_arg_from_edge (tree, edge);
--- 519,525 ----
  
  /* In tree-ssa-copyprop.c  */
  void tree_ssa_copyprop (tree, enum tree_dump_index);
! void propagate_copy (tree *, tree);
  
  /* In tree-flow-inline.h  */
  static inline int phi_arg_from_edge (tree, edge);
*************** static inline bool may_propagate_copy (t
*** 566,572 ****
  void tree_compute_must_alias (tree, sbitmap, enum tree_dump_index);
  
  /* In tree-flatten.c.  */
! tree_cell tree_cell_alloc (tree, enum tree_container_note);
  void tree_flatten_statement (tree, tree_cell *, tree);
  tree tree_unflatten_statements (void);
  
--- 531,537 ----
  void tree_compute_must_alias (tree, sbitmap, enum tree_dump_index);
  
  /* In tree-flatten.c.  */
! tree_cell tree_cell_alloc (tree);
  void tree_flatten_statement (tree, tree_cell *, tree);
  tree tree_unflatten_statements (void);
  
Index: tree-optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-optimize.c,v
retrieving revision 1.1.4.43.2.4
diff -c -3 -p -r1.1.4.43.2.4 tree-optimize.c
*** tree-optimize.c	5 Oct 2003 19:25:44 -0000	1.1.4.43.2.4
--- tree-optimize.c	6 Oct 2003 23:15:45 -0000
*************** optimize_function_tree (tree fndecl)
*** 71,77 ****
    /* Flatten the trees.  */
    head.prev = head.next = NULL;
    last = &head;
!   tree_flatten_statement (fnbody, &last, NULL_TREE);
    first = head.next;
  
    if (!first)
--- 71,77 ----
    /* Flatten the trees.  */
    head.prev = head.next = NULL;
    last = &head;
!   tree_flatten_statement (BIND_EXPR_BODY (fnbody), &last, NULL_TREE);
    first = head.next;
  
    if (!first)
*************** optimize_function_tree (tree fndecl)
*** 83,88 ****
--- 83,91 ----
  
    first->prev = NULL;
  
+   /* Let the garbage collector release now unnecesary containers.  */
+   BIND_EXPR_BODY (fnbody) = NULL_TREE;
+ 
    /* Build the flowgraph.  */
    init_flow ();
    build_tree_cfg (first);
*************** optimize_function_tree (tree fndecl)
*** 101,107 ****
  
        /* Find all the variables referenced in the function.  */
        find_referenced_vars (fndecl);
-       assign_vars_to_scopes ();
  
        /* Compute aliasing information for all the variables referenced in
  	 the function.  */
--- 104,109 ----
*************** optimize_function_tree (tree fndecl)
*** 198,204 ****
      }
  
    fnbody = tree_unflatten_statements ();
!   DECL_SAVED_TREE (fndecl) = fnbody;
  
    /* Debugging dump after optimization.  */
    dump_function (TDI_optimized, fndecl);
--- 200,206 ----
      }
  
    fnbody = tree_unflatten_statements ();
!   BIND_EXPR_BODY (DECL_SAVED_TREE (fndecl)) = fnbody;
  
    /* Debugging dump after optimization.  */
    dump_function (TDI_optimized, fndecl);
*************** tree_rest_of_compilation (tree fndecl, b
*** 269,274 ****
--- 271,277 ----
  {
    location_t saved_loc;
    tree saved_tree = NULL;
+   bool do_optimize;
  
    /* Don't bother doing anything if there are errors.  */
    if (errorcount || sorrycount)
*************** tree_rest_of_compilation (tree fndecl, b
*** 310,322 ****
  
    /* Gimplify the function.  Don't try to optimize the function if
       gimplification failed.  */
!   if (!flag_disable_gimple
!       && (keep_function_tree_in_gimple_form (fndecl)
!           || gimplify_function_tree (fndecl)))
      {
        /* Debugging dump after gimplification.  */
        dump_function (TDI_gimple, fndecl);
  
        {
  	int flags;
  	FILE *file = dump_begin (TDI_useless, &flags);
--- 313,346 ----
  
    /* Gimplify the function.  Don't try to optimize the function if
       gimplification failed.  */
!   do_optimize = (!flag_disable_gimple
! 		 && (keep_function_tree_in_gimple_form (fndecl)
! 		     || gimplify_function_tree (fndecl)));
! 
! 
!   /* Do these start-of-function steps now, so that declare_nonlocal_label
!      (called from gimple-low.c during variable expansion) is happy.  */
!   
!   /* If the function has a variably modified type, there may be
!      SAVE_EXPRs in the parameter types.  Their context must be set to
!      refer to this function; they cannot be expanded in the containing
!      function.  */
!   if (decl_function_context (fndecl)
!       && variably_modified_type_p (TREE_TYPE (fndecl)))
!     walk_tree (&TREE_TYPE (fndecl), set_save_expr_context, fndecl,
! 	       NULL);
! 
!   /* Set up parameters and prepare for return, for the function.  */
!   expand_function_start (fndecl, 0);
! 
!   if (do_optimize)
      {
        /* Debugging dump after gimplification.  */
        dump_function (TDI_gimple, fndecl);
  
+       /* Run a pass over the statements deleting any obviously useless
+ 	 statements before we build the CFG.  */
+       remove_useless_stmts_and_vars (&DECL_SAVED_TREE (fndecl), false);
        {
  	int flags;
  	FILE *file = dump_begin (TDI_useless, &flags);
*************** tree_rest_of_compilation (tree fndecl, b
*** 334,352 ****
        /* Invoke the SSA tree optimizer.  */
        if (optimize >= 1 && !flag_disable_tree_ssa)
          optimize_function_tree (fndecl);
      }
- 
-   /* If the function has a variably modified type, there may be
-      SAVE_EXPRs in the parameter types.  Their context must be set to
-      refer to this function; they cannot be expanded in the containing
-      function.  */
-   if (decl_function_context (fndecl)
-       && variably_modified_type_p (TREE_TYPE (fndecl)))
-     walk_tree (&TREE_TYPE (fndecl), set_save_expr_context, fndecl,
- 	       NULL);
- 
-   /* Set up parameters and prepare for return, for the function.  */
-   expand_function_start (fndecl, 0);
  
    /* Allow language dialects to perform special processing.  */
    (*lang_hooks.rtl_expand.start) ();
--- 358,368 ----
        /* Invoke the SSA tree optimizer.  */
        if (optimize >= 1 && !flag_disable_tree_ssa)
          optimize_function_tree (fndecl);
+   
+       /* Do some cleanups which reduce the amount of data the
+ 	 tree->rtl expanders deal with.  */
+       remove_useless_stmts_and_vars (&DECL_SAVED_TREE (fndecl), true);
      }
  
    /* Allow language dialects to perform special processing.  */
    (*lang_hooks.rtl_expand.start) ();
Index: tree-ssa-copyprop.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-copyprop.c,v
retrieving revision 1.1.2.11.2.3
diff -c -3 -p -r1.1.2.11.2.3 tree-ssa-copyprop.c
*** tree-ssa-copyprop.c	2 Oct 2003 22:02:30 -0000	1.1.2.11.2.3
--- tree-ssa-copyprop.c	6 Oct 2003 23:15:45 -0000
*************** static int dump_flags;
*** 45,53 ****
  static void copyprop_stmt (tree);
  static void copyprop_phi (tree);
  static inline tree get_original (tree);
- static struct block_tree *get_common_scope (struct block_tree *,
- 					    struct block_tree *);
- static void move_var_to_scope (tree, struct block_tree *);
  
  /* Main entry point to the copy propagator.  The algorithm is a simple
     linear scan of the flowgraph.  For every variable X_i used in the
--- 45,50 ----
*************** copyprop_stmt (tree stmt)
*** 98,104 ****
    varray_type uses;
    size_t i;
    bool modified;
-   basic_block bb = bb_for_stmt (stmt);
  
    if (dump_file && (dump_flags & TDF_DETAILS))
      {
--- 95,100 ----
*************** copyprop_stmt (tree stmt)
*** 128,134 ****
  	      fprintf (dump_file, "\n");
  	    }
  
! 	  propagate_copy (bb, use_p, orig);
  	  modified = true;
  	}
      }
--- 124,130 ----
  	      fprintf (dump_file, "\n");
  	    }
  
! 	  propagate_copy (use_p, orig);
  	  modified = true;
  	}
      }
*************** get_original (tree var)
*** 214,220 ****
     The propagation occurs in basic block BB.  */
  
  void
! propagate_copy (basic_block bb, tree *op_p, tree var)
  {
  #if defined ENABLE_CHECKING
    if (!may_propagate_copy (*op_p, var))
--- 210,216 ----
     The propagation occurs in basic block BB.  */
  
  void
! propagate_copy (tree *op_p, tree var)
  {
  #if defined ENABLE_CHECKING
    if (!may_propagate_copy (*op_p, var))
*************** propagate_copy (basic_block bb, tree *op
*** 237,320 ****
      }
  
    *op_p = var;
- 
-   fixup_var_scope (bb, var);
- }
- 
- /* Moves variable VAR high enough in scope tree so that basic block BB is in
-    scope.  */
- void
- fixup_var_scope (basic_block bb, tree var)
- {
-   struct block_tree *scope, *old_scope;
- 
-   /* Update scope of var.  */
-   old_scope = var_ann (SSA_NAME_VAR (var))->scope;
-   if (old_scope)
-     {
-       scope = get_common_scope (bb_ann (bb)->block, old_scope);
-       if (scope != old_scope)
- 	move_var_to_scope (SSA_NAME_VAR (var), scope);
-     }
- }
- 
- /* Finds common scope for S1 and S2.  */
- static struct block_tree *
- get_common_scope (struct block_tree *s1, struct block_tree *s2)
- {
-   struct block_tree *tmp;
- 
-   if (s1->level > s2->level)
-     {
-       tmp = s1;
-       s1 = s2;
-       s2 = tmp;
-     }
- 
-   while (s1->level < s2->level)
-     s2 = s2->outer;
- 
-   while (s1 != s2)
-     {
-       s1 = s1->outer;
-       s2 = s2->outer;
-     }
- 
-   return s1;
- }
- 
- /* Moves variable VAR to a SCOPE.  */
- static void
- move_var_to_scope (tree var, struct block_tree *scope)
- {
-   struct block_tree *old_scope = var_ann (var)->scope;
-   tree avar, prev;
-   tree block = BIND_EXPR_BLOCK (old_scope->bind);
- 
-   prev = NULL_TREE;
-   for (avar = BIND_EXPR_VARS (old_scope->bind);
-        avar;
-        prev = avar, avar = TREE_CHAIN (avar))
-     if (avar == var)
-       break;
-   if (!avar)
-     abort ();
- 
-   if (block)
-     remove_decl (avar, block);
-   else
-     remove_decl (avar, DECL_INITIAL (current_function_decl));
- 
-   if (prev)
-     TREE_CHAIN (prev) = TREE_CHAIN (avar);
-   else
-     BIND_EXPR_VARS (old_scope->bind) = TREE_CHAIN (avar);
- 
-   TREE_CHAIN (var) = BIND_EXPR_VARS (scope->bind);
-   BIND_EXPR_VARS (scope->bind) = var;
-   var_ann (var)->scope = scope;
- 
-   /* Dwarf2out ices (in add_abstract_origin_attribute) when it encounters
-      variable that is not declared, but has DECL_ABSTRACT_ORIGIN set.  */
-   DECL_ABSTRACT_ORIGIN (var) = NULL_TREE;
  }
--- 233,236 ----
Index: tree-ssa-dom.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-dom.c,v
retrieving revision 1.1.2.21.2.3
diff -c -3 -p -r1.1.2.21.2.3 tree-ssa-dom.c
*** tree-ssa-dom.c	2 Oct 2003 22:02:30 -0000	1.1.2.21.2.3
--- tree-ssa-dom.c	6 Oct 2003 23:15:45 -0000
*************** optimize_stmt (block_stmt_iterator si, v
*** 1408,1414 ****
  	      may_have_exposed_new_symbols = true;
  
  	    if (TREE_CODE (val) == SSA_NAME)
! 	      propagate_copy (bb_for_stmt (stmt), op_p, val);
  	    else
  	      *op_p = val;
  
--- 1408,1414 ----
  	      may_have_exposed_new_symbols = true;
  
  	    if (TREE_CODE (val) == SSA_NAME)
! 	      propagate_copy (op_p, val);
  	    else
  	      *op_p = val;
  
*************** optimize_stmt (block_stmt_iterator si, v
*** 1524,1534 ****
  	    abort ();
  #endif
  
! 	  if (TREE_CODE (cached_lhs) == SSA_NAME)
! 	    fixup_var_scope (bb_for_stmt (stmt), cached_lhs);
! 	  else if (TREE_CODE (cached_lhs) == ADDR_EXPR
! 		   || (POINTER_TYPE_P (TREE_TYPE (*expr_p))
! 		       && is_unchanging_value (cached_lhs)))
  	    may_have_exposed_new_symbols = true;
  
  	  *expr_p = cached_lhs;
--- 1524,1532 ----
  	    abort ();
  #endif
  
! 	  if (TREE_CODE (cached_lhs) == ADDR_EXPR
! 	      || (POINTER_TYPE_P (TREE_TYPE (*expr_p))
! 		  && is_unchanging_value (cached_lhs)))
  	    may_have_exposed_new_symbols = true;
  
  	  *expr_p = cached_lhs;
Index: tree-ssa-pre.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-pre.c,v
retrieving revision 1.1.4.71.2.2
diff -c -3 -p -r1.1.4.71.2.2 tree-ssa-pre.c
*** tree-ssa-pre.c	2 Oct 2003 22:02:30 -0000	1.1.4.71.2.2
--- tree-ssa-pre.c	6 Oct 2003 23:15:45 -0000
*************** static void split_critical_edges (void);
*** 257,263 ****
  static bitmap created_phi_preds;
  
  /* PRE dominance info.  */
! static dominance_info pre_idom;
  
  /* PRE dominance frontiers.  */
  static bitmap *pre_dfs;
--- 257,263 ----
  static bitmap created_phi_preds;
  
  /* PRE dominance info.  */
! static struct dominance_info *pre_idom;
  
  /* PRE dominance frontiers.  */
  static bitmap *pre_dfs;
*************** tree_perform_ssapre (tree fndecl, enum t
*** 3001,3007 ****
  	  htab_delete (ephi_pindex_htab);
  	  ephi_pindex_htab = NULL;
  	}
!       ggc_collect (); 
        if (redo_dominators)
  	{
  	  redo_dominators = false;
--- 3001,3007 ----
  	  htab_delete (ephi_pindex_htab);
  	  ephi_pindex_htab = NULL;
  	}
! /*      ggc_collect ();  */ /* This causes whole lot of trouble with temporary structures.  */
        if (redo_dominators)
  	{
  	  redo_dominators = false;
Index: tree-ssa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa.c,v
retrieving revision 1.1.4.115.2.4
diff -c -3 -p -r1.1.4.115.2.4 tree-ssa.c
*** tree-ssa.c	3 Oct 2003 09:35:22 -0000	1.1.4.115.2.4
--- tree-ssa.c	6 Oct 2003 23:15:45 -0000
*************** rewrite_out_of_ssa (tree fndecl, enum tr
*** 1732,1738 ****
    bsi_commit_edge_inserts (0, NULL);
  
    cleanup_tree_cfg (true);
-   remove_useless_stmts_and_vars ();
  
    if (dump_file && (dump_flags & TDF_DETAILS))
      dump_tree_cfg (dump_file, dump_flags & ~TDF_DETAILS);
--- 1732,1737 ----
Index: tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.c,v
retrieving revision 1.263.2.44.2.3
diff -c -3 -p -r1.263.2.44.2.3 tree.c
*** tree.c	5 Oct 2003 19:25:45 -0000	1.263.2.44.2.3
--- tree.c	6 Oct 2003 23:15:45 -0000
*************** tsi_link_after (tree_stmt_iterator *i, t
*** 5242,5265 ****
        /* Create a new node with the same 'next' link as the current one.  */
        ce = build (COMPOUND_EXPR, void_type_node, t, next);
  
- #if 0
-       /* bsi_... iterators should be used for this!!!  */
-       /* If the 'next' statement is a COMPOUND_EXPR and was the first
- 	 statement of a basic block, we need to adjust the 'head_tree_p'
- 	 field of that block because we are about to move the statement one
- 	 position down in the CE chain.  */
-       {
- 	basic_block bb = bb_for_stmt (next);
- 	if (bb && bb->head_tree_p == &TREE_OPERAND (cur, 1))
- 	  {
- 	    /* We may also need to update end_tree_p.  */
- 	    if (bb->head_tree_p == bb->end_tree_p)
- 	      bb->end_tree_p = &TREE_OPERAND (ce, 1);
- 	    bb->head_tree_p = &TREE_OPERAND (ce, 1);
- 	  }
-       }
- #endif
- 
        /* Make the current one's 'next' link point to our new stmt.  */
        TREE_OPERAND (cur, 1) = ce;
  
--- 5242,5247 ----
*************** tsi_link_chain_after (tree_stmt_iterator
*** 5373,5396 ****
  
        /* Create a new node with the same 'next' link as the current one.  */
        ce = build (COMPOUND_EXPR, void_type_node, *last, next);
- 
- #if 0
-       /* bsi_... iterators should be used for this!!!  */
-       /* If the 'next' statement is a COMPOUND_EXPR and was the first
- 	 statement of a basic block, we need to adjust the 'head_tree_p'
- 	 field of that block because we are about to move the statement one
- 	 position down in the CE chain.  */
-       {
- 	basic_block bb = bb_for_stmt (next);
- 	if (bb && bb->head_tree_p == nextp)
- 	  {
- 	    /* We may also need to update end_tree_p.  */
- 	    if (bb->head_tree_p == bb->end_tree_p)
- 	      bb->end_tree_p = &TREE_OPERAND (ce, 1);
- 	    bb->head_tree_p = &TREE_OPERAND (ce, 1);
- 	  }
-       }
- #endif
  
        *last = ce;
        TREE_OPERAND (cur, 1) = t;
--- 5355,5360 ----


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