This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [tree-ssa] BIND_EXPR removal


Hello,

> > > +   expand_vars (BIND_EXPR_VARS (*body), false);
> > >     lower_stmt_body (&BIND_EXPR_BODY (*body), &data);
> > 
> > No.  We need to handle this without messing with RTL during
> > the tree optimizers.
> 
> Indeed, we've done no dead code or variable elimination at this 
> point, so we're definitely expanding more stuff than we need.

OK, the second attempt.  It just records the variables in the gimple
lowering phase, then expands those of them that were not optimized
out afterwards (the code to determine this is taken from
remove_unused_... in tree-cfg.c, so it should do exactly what we
do now).

Zdenek

Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.467.2.60
diff -c -3 -p -r1.467.2.60 expr.c
*** expr.c	30 Oct 2003 02:49:40 -0000	1.467.2.60
--- expr.c	2 Nov 2003 11:24:55 -0000
*************** find_placeholder (tree exp, tree *plist)
*** 6119,6124 ****
--- 6119,6188 ----
    return 0;
  }
  
+ /* Expands variable VAR.  */
+ 
+ void
+ expand_var (tree var)
+ {
+   if (DECL_EXTERNAL (var))
+     return;
+ 
+   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))
+     {
+       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 ();
+     }
+ }
+ 
+ /* Expands declarations of variables in list VARS.  */
+ 
+ static void
+ expand_vars (tree vars)
+ {
+   for (; vars; vars = TREE_CHAIN (vars))
+     {
+       tree var = vars;
+ 
+       if (DECL_EXTERNAL (var))
+ 	continue;
+ 
+       expand_var (var);
+       expand_decl_init (var);
+     }
+ }
+ 
  /* Subroutine of expand_expr.  Expand the two operands of a binary
     expression EXP0 and EXP1 placing the results in OP0 and OP1.
     The value may be stored in TARGET if TARGET is nonzero.  The
*************** expand_expr_1 (tree exp, rtx target, enu
*** 6779,6830 ****
  	  }
  
  	/* If VARS have not yet been expanded, expand them now.  */
! 	for (vars = BIND_EXPR_VARS (exp); 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))
! 	      {
! 		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 ();
! 	      }
! 	    expand_decl_init (var);
! 	  }
  
  	/* TARGET was clobbered early in this function.  The correct
  	   indicator or whether or not we need the value of this 
--- 6843,6849 ----
  	  }
  
  	/* If VARS have not yet been expanded, expand them now.  */
! 	expand_vars (BIND_EXPR_VARS (exp));
  
  	/* TARGET was clobbered early in this function.  The correct
  	   indicator or whether or not we need the value of this 
Index: expr.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.h,v
retrieving revision 1.117.2.19
diff -c -3 -p -r1.117.2.19 expr.h
*** expr.h	31 Oct 2003 07:29:42 -0000	1.117.2.19
--- expr.h	2 Nov 2003 11:24:55 -0000
*************** extern tree find_placeholder (tree, tree
*** 500,505 ****
--- 500,507 ----
     In the case of a void EXP, const0_rtx is returned.  */
  extern rtx expand_expr (tree, rtx, enum machine_mode, enum expand_modifier);
  
+ extern void expand_var (tree);
+ 
  /* At the start of a function, record that we have no previously-pushed
     arguments waiting to be popped.  */
  extern void init_pending_stack_adjust (void);
Index: gimple-low.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/gimple-low.c,v
retrieving revision 1.1.4.3
diff -c -3 -p -r1.1.4.3 gimple-low.c
*** gimple-low.c	30 Oct 2003 02:49:40 -0000	1.1.4.3
--- gimple-low.c	2 Nov 2003 11:24:55 -0000
*************** static void lower_stmt (tree_stmt_iterat
*** 52,57 ****
--- 52,60 ----
  static void lower_bind_expr (tree_stmt_iterator *, struct lower_data *);
  static void lower_cond_expr (tree_stmt_iterator *, struct lower_data *);
  static bool simple_goto_p (tree);
+ static void record_vars (tree);
+ 
+ tree unexpanded_var_list;
  
  /* Lowers the BODY.  */
  void
*************** lower_function_body (tree *body)
*** 66,71 ****
--- 69,76 ----
    BLOCK_SUBBLOCKS (data.block) = NULL_TREE;
    BLOCK_CHAIN (data.block) = NULL_TREE;
  
+   unexpanded_var_list = NULL_TREE;
+   record_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
*** 100,106 ****
      {
      case BIND_EXPR:
        lower_bind_expr (tsi, data);
!       break;
  
      case COMPOUND_EXPR:
        abort ();
--- 105,113 ----
      {
      case BIND_EXPR:
        lower_bind_expr (tsi, data);
!       /* Avoid moving the tsi -- it has already been moved by delinking the
! 	 statement.  */
!       return;
  
      case COMPOUND_EXPR:
        abort ();
*************** lower_stmt (tree_stmt_iterator *tsi, str
*** 129,134 ****
--- 136,159 ----
    tsi_next (tsi);
  }
  
+ /* Record the variables in VARS.  */
+ 
+ static void
+ record_vars (tree vars)
+ {
+   for (; vars; vars = TREE_CHAIN (vars))
+     {
+       tree var = vars;
+ 
+       /* Nothing to do in this case.  */
+       if (DECL_EXTERNAL (var))
+ 	continue;
+ 
+       /* Record the variable.  */
+       unexpanded_var_list = tree_cons (NULL_TREE, var, unexpanded_var_list);
+     }
+ }
+ 
  /* Lowers a bind_expr TSI.  DATA is passed through the recursion.  */
  
  static void
*************** lower_bind_expr (tree_stmt_iterator *tsi
*** 149,154 ****
--- 174,181 ----
        BLOCK_SUBBLOCKS (data->block) = NULL_TREE;
        BLOCK_SUPERCONTEXT (data->block) = old_block;
      }
+ 
+   record_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
*** 160,165 ****
--- 187,197 ----
  	      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.  */
*************** lower_cond_expr (tree_stmt_iterator *tsi
*** 235,238 ****
--- 267,306 ----
  
    if (end_label)
      tsi_link_after (tsi, end_label, TSI_CONTINUE_LINKING);
+ }
+ 
+ /* Expand those variables in the unexpanded_var_list that are used.  */
+ 
+ void
+ expand_used_vars (void)
+ {
+   tree var, cell;
+ 
+   unexpanded_var_list = nreverse (unexpanded_var_list);
+ 
+   for (cell = unexpanded_var_list; cell; cell = TREE_CHAIN (cell))
+     {
+       var = TREE_VALUE (cell);
+ 
+       if (TREE_CODE (var) == VAR_DECL)
+ 	{
+ 	  struct var_ann_d *ann = var_ann (var);
+ 
+ 	  /* Remove all unused, unaliased temporaries.  Also remove
+ 	     unused, unaliased local variables during highly
+ 	     optimizing compilations.  */
+ 	  ann = var_ann (var);
+ 	  if (ann
+ 	      && ! ann->may_aliases
+ 	      && ! ann->used
+ 	      && ! ann->has_hidden_use
+ 	      && ! TREE_ADDRESSABLE (var)
+ 	      && (DECL_ARTIFICIAL (var) || optimize >= 2))
+ 	    continue;
+ 	}
+ 
+       expand_var (var);
+     }
+ 
+   unexpanded_var_list = NULL_TREE;
  }
Index: tree-alias-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-alias-common.c,v
retrieving revision 1.1.2.40
diff -c -3 -p -r1.1.2.40 tree-alias-common.c
*** tree-alias-common.c	18 Oct 2003 03:09:46 -0000	1.1.2.40
--- tree-alias-common.c	2 Nov 2003 11:24:55 -0000
*************** create_alias_vars (tree fndecl)
*** 915,920 ****
--- 915,922 ----
    tree fnbody;
  #endif
    size_t i;
+   tree block;
+ 
    currptadecl = fndecl;
    create_global_var ();
  
*************** create_alias_vars (tree fndecl)
*** 953,958 ****
--- 955,984 ----
        find_func_decls, NULL);*/
    walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
  				find_func_aliases, NULL);
+ 
+ 
+   /* Visit also the variables inside blocks (whose bind_exprs are no longer
+      in the tree).  */
+   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);
+     }
+ 
    global_var = NULL_TREE;
  }
  
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.189
diff -c -3 -p -r1.1.4.189 tree-cfg.c
*** tree-cfg.c	1 Nov 2003 20:27:15 -0000	1.1.4.189
--- tree-cfg.c	2 Nov 2003 11:24:55 -0000
*************** static void create_blocks_annotations (v
*** 90,97 ****
  static void create_block_annotation (basic_block);
  static void free_blocks_annotations (void);
  static void clear_blocks_annotations (void);
! static basic_block make_blocks (tree *, tree, basic_block, tree);
! static basic_block make_bind_expr_blocks (tree *, tree, basic_block, tree);
  static inline void append_stmt_to_bb (tree *, basic_block);
  static inline void prepend_stmt_to_bb (tree *, basic_block);
  static void factor_computed_gotos (void);
--- 90,96 ----
  static void create_block_annotation (basic_block);
  static void free_blocks_annotations (void);
  static void clear_blocks_annotations (void);
! static basic_block make_blocks (tree *, basic_block);
  static inline void append_stmt_to_bb (tree *, basic_block);
  static inline void prepend_stmt_to_bb (tree *, basic_block);
  static void factor_computed_gotos (void);
*************** static void make_switch_expr_edges (basi
*** 105,112 ****
  static void make_goto_expr_edges (basic_block);
  
  /* Various helpers.  */
- static void assign_vars_to_scope (tree);
- static basic_block successor_block (basic_block);
  static tree *first_exec_stmt (tree *);
  static inline bool stmt_starts_bb_p (tree, tree);
  static inline bool stmt_ends_bb_p (tree);
--- 104,109 ----
*************** static tree_stmt_iterator bsi_link_after
*** 151,176 ****
    } while (0)
  
  
- /* NEXT_BLOCK_LINK is used to store the successor statement of the entry
-    statement to a lexical or control block.  This allows successor_block to
-    find the block that should come after the last statement of the last
-    block inside a lexical scope.  For instance,
- 
- 	    1	if (...)
- 	    2	  {
- 	    3	    s1;
- 	    4	    {
- 	    5	      s2;
- 	    6	      s3;
- 	    7	    }
- 	    8	  }
- 	    9	s4;
- 
-   When make_blocks starts processing the if() at line 1, it sets
-   NEXT_BLOCK_LINK to be 's4'.  This way, when it finishes the basic block
-   at line 6, it sets NEXT_BLOCK_LINK (s3) to 's4'.  */
- #define NEXT_BLOCK_LINK(STMT)	TREE_CHAIN (STMT)
- 
  /* 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 = {
--- 148,153 ----
*************** build_tree_cfg (tree fnbody)
*** 230,236 ****
    if (first_p)
      {
        found_computed_goto = 0;
!       make_blocks (first_p, NULL_TREE, NULL, fnbody);
  
        /* Computed gotos are hell to deal with, especially if there are
  	 lots of them with a large number of destinations.  So we factor
--- 207,213 ----
    if (first_p)
      {
        found_computed_goto = 0;
!       make_blocks (first_p, NULL);
  
        /* Computed gotos are hell to deal with, especially if there are
  	 lots of them with a large number of destinations.  So we factor
*************** factor_computed_gotos (void)
*** 362,368 ****
  
  	      /* Put the new statements into a new basic block.  This must
  		 be done before we link them into the statement chain!  */
! 	      make_blocks (&TREE_OPERAND (compound, 0), NULL, NULL, NULL);
  
  	      /* Now it is safe to link in the new statements.  */
  	      tsi_link_chain_after (&tsi,
--- 339,345 ----
  
  	      /* Put the new statements into a new basic block.  This must
  		 be done before we link them into the statement chain!  */
! 	      make_blocks (&TREE_OPERAND (compound, 0), NULL);
  
  	      /* Now it is safe to link in the new statements.  */
  	      tsi_link_chain_after (&tsi,
*************** clear_blocks_annotations (void)
*** 448,461 ****
     BB is the block where the statements should be added to.  If BB is NULL,
        a new basic block will be created for the statements.
  
-    SCOPE is the BIND_EXPR block containing *FIRST_P.
- 
     Return the last basic block added to the graph.  This is used to know if
     a recursive invocation built a sub-graph whose last block can accept
     more statements or not.  */
  
  static basic_block
! make_blocks (tree *first_p, tree next_block_link, basic_block bb, tree scope)
  {
    tree_stmt_iterator i;
    tree stmt, last;
--- 425,436 ----
     BB is the block where the statements should be added to.  If BB is NULL,
        a new basic block will be created for the statements.
  
     Return the last basic block added to the graph.  This is used to know if
     a recursive invocation built a sub-graph whose last block can accept
     more statements or not.  */
  
  static basic_block
! make_blocks (tree *first_p, basic_block bb)
  {
    tree_stmt_iterator i;
    tree stmt, last;
*************** make_blocks (tree *first_p, tree next_bl
*** 485,558 ****
  	  start_new_block = false;
  	}
  
-       NEXT_BLOCK_LINK (stmt) = NULL_TREE;
        code = TREE_CODE (stmt);
  
        /* Now add STMT to BB and create the subgraphs for special statement
  	 codes.  */
        append_stmt_to_bb (stmt_p, bb);
-       get_stmt_ann (stmt)->scope = scope;
  
        if (is_computed_goto (*stmt_p))
  	found_computed_goto = true;
  
        if (code == BIND_EXPR)
! 	{
! 	  int num_blocks_before;
! 	  basic_block last_bb;
! 
! 	  /* BIND_EXPR nodes are a special case.  We neither force a new
! 	     block for their bodies, nor force a new block after creating
! 	     the subgraph.  On return from make_bind_expr_blocks, LAST_BB
! 	     will be the last basic block of the BIND_EXPR's subgraph.  We
! 	     point STMT to LAST_BB's last statement to determine if we
! 	     should start a new block or not.  */
!  	  num_blocks_before = n_basic_blocks;
! 	  assign_vars_to_scope (stmt);
! 	  get_stmt_ann (stmt)->scope_level =
! 		  get_stmt_ann (scope)->scope_level + 1;
! 
! 	  last_bb = make_bind_expr_blocks (stmt_p, next_block_link, bb, stmt);
! 	  if (last_bb)
! 	    {
! 	      bb = last_bb;
! 	      stmt = last_stmt (bb);
! 	    }
! 
! 	  /* FIXME.  Obscene hack to work around iterator limitations.  If
! 	     during processing of the BIND_EXPR body we were forced to
! 	     create new blocks (i.e., the BIND_EXPR body contains control
! 	     flow structures), then force the creation of a new basic block
! 	     for the next iteration.  This avoids the following problem
! 	     (assume that all the Si statements are regular GIMPLE
! 	     statements):
! 
! 		    1	s1;		<-- BLOCK #0
! 		    2	{
! 		    3	  s2;
! 		    4	  s3;
! 		    5	  if ()
! 		    6	    s4;		<-- BLOCK #1
! 		    7	  s5;		<-- BLOCK #2
! 		    8	}
! 		    9	s6;
! 
! 	     Since s5 and s6 are two regular statements, they could both be
! 	     in block #2.  However, if we started an iterator on block #2,
! 	     the iterator would have no way of knowing how to go from
! 	     statement s5 to statement s6 because the iterator was started
! 	     in the middle of its BIND_EXPR's body, so bsi_step_in_bb() has
! 	     not enough context to determine how to get to s6.  */
! 	  if (n_basic_blocks > num_blocks_before)
! 	    {
! 	      start_new_block = true;
! 
! 	      /* If we are starting the new block just to work around
! 		 iterator limitations, keep track of it.  */
! 	      if (!stmt || !stmt_ends_bb_p (stmt))
! 		cfg_stats.num_failed_bind_expr_merges++;
! 	    }
! 	}
  
        /* If STMT is a basic block terminator, set START_NEW_BLOCK for the
  	 next iteration.  Also compute any reachable exception handlers
--- 460,477 ----
  	  start_new_block = false;
  	}
  
        code = TREE_CODE (stmt);
  
        /* Now add STMT to BB and create the subgraphs for special statement
  	 codes.  */
        append_stmt_to_bb (stmt_p, bb);
  
        if (is_computed_goto (*stmt_p))
  	found_computed_goto = true;
  
+       /* All BIND_EXPRs except for the outermost one are lowered already.  */
        if (code == BIND_EXPR)
! 	abort ();
  
        /* If STMT is a basic block terminator, set START_NEW_BLOCK for the
  	 next iteration.  Also compute any reachable exception handlers
*************** make_blocks (tree *first_p, tree next_bl
*** 563,629 ****
        last = stmt;
      }
  
-   /* If LAST is set, link it to NEXT_BLOCK_LINK.  This allows making edges
-      from the last block inside a lexical scope (see successor_block).  */
    if (last)
!     {
!       NEXT_BLOCK_LINK (last) = next_block_link;
!       return bb_for_stmt (last);
!     }
  
    return NULL;
  }
  
- /* Create the blocks for the BIND_EXPR node pointed by BIND_P.  In contrast
-    with the other make_*_blocks functions, this function will not start a
-    new basic block for the statements in the BIND_EXPR body.  Rather, the
-    statements in the BIND_EXPR body are added to the block ENTRY.
- 
-    NEXT_BLOCK_LINK is the first statement of the successor basic block for
-       the block holding *BIND_P.  If *BIND_P is the last statement inside a
-       lexical scope, this will be the statement that comes after *BIND_P's
-       container (see the documentation for NEXT_BLOCK_LINK).
- 
-    ENTRY is the block whose last statement is *SWITCH_E_P.
- 
-    Return the last basic block added to the BIND_EXPR's subgraph.  This
-    allows the caller to determine whether a new block should be started or
-    not.
-    
-    SCOPE is the BIND_EXPR node holding *BIND_P (in fact it is equal to
-    *BIND_P).  */
- 
- static basic_block
- make_bind_expr_blocks (tree *bind_p, tree next_block_link, basic_block entry,
- 		       tree scope)
- {
-   tree_stmt_iterator si;
-   tree bind = *bind_p;
- 
-   /* Determine NEXT_BLOCK_LINK for statements inside the BIND_EXPR
-      body.  */
-   si = tsi_start (bind_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));
- 
-   /* By passing the current block ENTRY to make_blocks, we will keep adding
-      statements to ENTRY until we find a block terminating statement inside
-      the body of the BIND_EXPR.  On return from make_blocks, our caller
-      will start a new basic block only if the body of the BIND_EXPR node
-      ends with a block terminating statement.  */
-   STRIP_CONTAINERS (bind);
-   return make_blocks (&BIND_EXPR_BODY (bind), next_block_link, entry, scope);
- }
- 
- 
- /* Add statement pointed by STMT_P to basic block BB and update BB's
-    boundaries accordingly.  */
  
  static inline void
  append_stmt_to_bb (tree *stmt_p, basic_block bb)
--- 482,493 ----
        last = stmt;
      }
  
    if (last)
!     return bb_for_stmt (last);
  
    return NULL;
  }
  
  
  static inline void
  append_stmt_to_bb (tree *stmt_p, basic_block bb)
*************** make_edges (void)
*** 721,727 ****
        /* Finally, if no edges were created above, this is a regular
  	 basic block that only needs a fallthru edge.  */
        if (bb->succ == NULL)
! 	make_edge (bb, successor_block (bb), EDGE_FALLTHRU);
      }
  
    /* We do not care about fake edges, so remove any that the CFG
--- 585,591 ----
        /* Finally, if no edges were created above, this is a regular
  	 basic block that only needs a fallthru edge.  */
        if (bb->succ == NULL)
! 	make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
      }
  
    /* We do not care about fake edges, so remove any that the CFG
*************** make_exit_edges (basic_block bb)
*** 822,828 ****
  	}
  
        /* Don't forget the fall-thru edge.  */
!       make_edge (bb, successor_block (bb), EDGE_FALLTHRU);
        break;
  
      case MODIFY_EXPR:
--- 686,692 ----
  	}
  
        /* Don't forget the fall-thru edge.  */
!       make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
        break;
  
      case MODIFY_EXPR:
*************** make_exit_edges (basic_block bb)
*** 834,840 ****
  	make_goto_expr_edges (bb);
  
        make_eh_edges (last);
!       make_edge (bb, successor_block (bb), EDGE_FALLTHRU);
        break;
  
      default:
--- 698,704 ----
  	make_goto_expr_edges (bb);
  
        make_eh_edges (last);
!       make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
        break;
  
      default:
*************** remove_useless_stmts_and_vars_goto (tree
*** 1352,1382 ****
  	  return;
  	}
      }
-   else
-     {
-       /* We are at the end of this tree, we may still have
- 	 an unnecessary GOTO_EXPR if NEXT_BLOCK_LINK
- 	 points to the target label.  */
-       tree next_block_link = NEXT_BLOCK_LINK (*stmt_p);
- 
-       if (next_block_link)
- 	{
- 	  tree next_stmt;
- 
- 	  /* Get the statement at NEXT_BLOCK_LINK and see if it
- 	     is our target label.  */
- 	  next_stmt = tsi_stmt (tsi_start (&next_block_link));
- 	  if (next_stmt
- 	      && TREE_CODE (next_stmt) == LABEL_EXPR
- 	      && (LABEL_EXPR_LABEL (next_stmt)
- 		  == GOTO_DESTINATION (*stmt_p)))
- 	    {
- 	      data->repeat = true;
- 	      *stmt_p = build_empty_stmt ();
- 	      return;
- 	    }
- 	}
-     }
  
    data->may_branch = true;
  }
--- 1216,1221 ----
*************** tree_cfg2dot (FILE *file)
*** 2441,2497 ****
  			     Miscellaneous helpers
  ---------------------------------------------------------------------------*/
  
- /* Return the successor block for BB.  If the block has no successors we
-    try the enclosing control structure until we find one.  If we reached
-    nesting level 0, return the exit block.  */
- 
- static basic_block
- successor_block (basic_block bb)
- {
-   basic_block succ_bb;
-   tree_stmt_iterator i;
-   tree last_stmt;
-   tree *container_p;
- 
- #if defined ENABLE_CHECKING
-   if (bb == NULL)
-     abort ();
- #endif
- 
-   /* By default, the successor block will be the block for the statement
-      following BB's last statement.  */
-   i = tsi_start (bb->end_tree_p);
-   last_stmt = tsi_stmt (i);
- 
-   /* Special case.  If the block ends in a BIND_EXPR node, the successor
-      block will be inside the BIND_EXPR's body.  */
-   if (last_stmt && TREE_CODE (last_stmt) == BIND_EXPR)
-     i = tsi_start (&BIND_EXPR_BODY (last_stmt));
-   else
-     tsi_next (&i);
- 
-   container_p = tsi_container (i);
-   if (container_p)
-     {
-       succ_bb = bb_for_stmt (*container_p);
-       if (succ_bb)
- 	return succ_bb;
-     }
- 
-   /* We couldn't find a successor for BB.  This means that BB is the last
-      block inside a control structure or lexical scope.  Use the
-      NEXT_BLOCK_LINK for BB's last statement.  If NEXT_BLOCK_LINK is still
-      NULL, then BB is the last basic block in the function.  In which case
-      we have reached the end of the flowgraph and return EXIT_BLOCK_PTR.  */
-   if (last_stmt == NULL_TREE)
-     last_stmt = *bb->end_tree_p;
- 
-   if (NEXT_BLOCK_LINK (last_stmt))
-     return bb_for_stmt (NEXT_BLOCK_LINK (last_stmt));
-   else
-     return EXIT_BLOCK_PTR;
- }
- 
  /* Return true if T represents a stmt that always transfers control.  */
  
  bool
--- 2280,2285 ----
*************** last_stmt_ptr (basic_block bb)
*** 2706,2719 ****
  
  /* Initialize a block stmt iterator with a container that contains stmt's
     in a specified basic block. If the first real stmt is not in the
!    specified basic block, then return an empty iterator.  If the first
!    real stmt is contained in a BIND_EXPR, descend into the BIND_EXPR and
!    set up the context chains properly. */
  
  static block_stmt_iterator
  bsi_init (tree *tp, basic_block bb)
  {
!   block_stmt_iterator i, bind;
    tree stmt;
  
    i.tp = tp;
--- 2494,2505 ----
  
  /* Initialize a block stmt iterator with a container that contains stmt's
     in a specified basic block. If the first real stmt is not in the
!    specified basic block, then return an empty iterator.  */
  
  static block_stmt_iterator
  bsi_init (tree *tp, basic_block bb)
  {
!   block_stmt_iterator i;
    tree stmt;
  
    i.tp = tp;
*************** bsi_init (tree *tp, basic_block bb)
*** 2724,2759 ****
        stmt = bsi_stmt (i);
        if (stmt == NULL_TREE)
  	bsi_next_in_bb (&i, bb);
-       else
-         if (TREE_CODE (stmt) == BIND_EXPR)
- 	  {
- 	    bind = bsi_init (&BIND_EXPR_BODY (stmt), bb);
- 
- 	    /* If the basic block of the child is the same as this block,
- 	       then add this context to the end, and use that iterator.  */
- 	    if (bind.tp != NULL)
- 	      {
- 		tree tmp, end;
- 
- 	        tmp = build_tree_list  (NULL_TREE, (tree) i.tp);
- 	        if (bind.context)
- 		  {
- 		    for (end = bind.context;
- 			 TREE_PURPOSE (end) != NULL;
- 			 end = TREE_PURPOSE (end))
- 		      ;
- 		    TREE_PURPOSE (end) = tmp;
- 		  }
- 		else
- 		  bind.context = tmp;
- 
- 		return bind;
- 	      }
- 	    else
- 	      /* If the children of the BIND_EXPR are no good, try the next
- 	         statement.  */
- 	      bsi_next_in_bb (&i, bb);
- 	  }
      }
  
    /* Now check that its the right basic block.  */
--- 2510,2515 ----
*************** void
*** 2774,2780 ****
  bsi_next_in_bb (block_stmt_iterator *i, basic_block bb)
  {
    tree t, stmt = NULL_TREE;
-   block_stmt_iterator bind;
  
    /* Go to the next statement skipping over empty statements we may find.  */
    do
--- 2530,2535 ----
*************** bsi_next_in_bb (block_stmt_iterator *i, 
*** 2797,2826 ****
    if (i->tp && bb_for_stmt (stmt) != bb)
      i->tp = NULL;
  
-   if (i->tp && TREE_CODE (stmt) == BIND_EXPR)
-     {
-       bind = bsi_init (&BIND_EXPR_BODY (stmt), bb);
- 
-       /* If the basic block of the child is the same as this block, then push
- 	 this context, and add it to the end of the new iterator.  */
-       if (bind.tp != NULL)
- 	{
- 	  tree tmp, end;
- 	  tmp = build_tree_list (i->context, (tree) i->tp);
- 	  if (bind.context)
- 	    {
- 	      for (end = bind.context;
- 		   TREE_PURPOSE (end) != NULL;
- 		   end = TREE_PURPOSE (end))
- 		;
- 	      TREE_PURPOSE (end) = tmp;
- 	    }
- 	  else
- 	    bind.context = tmp;
- 	}
-       *i = bind;
-     }
- 
    if (i->tp == NULL && i->context != NULL_TREE)
      {
        /* If we haven't got a statement, and we have context, pop the state and
--- 2552,2557 ----
*************** bsi_prev (block_stmt_iterator *i)
*** 2936,2946 ****
  /* Initialize a block_stmt_iterator with a statement pointed to by a tree
     iterator. If this cannot be done, a NULL iterator is returned.  */
  
- /* Note this routine is a bit ugly. Since BIND_EXPRs dont cause new block,
-    the block iterator keeps a stack of BIND_EXPRs which have been descended
-    into.  In order to create this stack properly, this routine traverses
-    through the block until it finds the specified tsi stmt.  */
- 
  block_stmt_iterator
  bsi_from_tsi (tree_stmt_iterator ti)
  {
--- 2667,2672 ----
*************** pop_bsi (bsi_list_p *list)
*** 3634,3641 ****
     individual statements.
  
     If TP1 is pointing to a COMPOUND_EXPR node, only its LHS operand will be
!    replaced. If TP2 points to a COMPOUND_EXPR, a new BIND_EXPR will be
!    created to wrap the whole chain of statements into a single block.  */
  
  void
  replace_stmt (tree *tp1, tree *tp2)
--- 3360,3366 ----
     individual statements.
  
     If TP1 is pointing to a COMPOUND_EXPR node, only its LHS operand will be
!    replaced. TP2 may not point to a COMPOUND_EXPR.  */
  
  void
  replace_stmt (tree *tp1, tree *tp2)
*************** replace_stmt (tree *tp1, tree *tp2)
*** 3643,3658 ****
    tree t;
  
    if (TREE_CODE (*tp2) == COMPOUND_EXPR)
!     {
!       /* If TP2 points to a COMPOUND_EXPR, create a BIND_EXPR to hold the
! 	 chain of statements.  */
!       t = build (BIND_EXPR, void_type_node, NULL_TREE, *tp2, NULL_TREE);
!     }
!   else
!     {
!       /* Otherwise use TP2 statement directly.  */
!       t = *tp2;
!     }
  
    /* Relocate annotations for the replacement statement.  */
    SET_EXPR_LOCUS (t, EXPR_LOCUS (*tp1));
--- 3368,3376 ----
    tree t;
  
    if (TREE_CODE (*tp2) == COMPOUND_EXPR)
!     abort ();
!       
!   t = *tp2;
  
    /* Relocate annotations for the replacement statement.  */
    SET_EXPR_LOCUS (t, EXPR_LOCUS (*tp1));
*************** tree_loop_optimizer_finalize (struct loo
*** 3865,3880 ****
  #ifdef ENABLE_CHECKING
    verify_flow_info ();
  #endif
- }
- 
- /* Assigns a scope to variables defined in bind_expr SCOPE.  */
- static void
- assign_vars_to_scope (tree scope)
- {
-   tree var;
- 
-   for (var = BIND_EXPR_VARS (scope); var; var = TREE_CHAIN (var))
-     get_var_ann (var)->scope = scope;
  }
  
  /* Return true if basic block BB does nothing except pass control
--- 3583,3588 ----
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.136
diff -c -3 -p -r1.1.4.136 tree-flow.h
*** tree-flow.h	1 Nov 2003 20:27:15 -0000	1.1.4.136
--- tree-flow.h	2 Nov 2003 11:24:55 -0000
*************** struct var_ann_d GTY(())
*** 121,129 ****
    /* Used by the root-var object in tree-ssa-live.[ch].  */
    unsigned root_index;
  
-   /* The BIND_EXPR in that the variable is declared.  */
-   tree 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
--- 121,126 ----
*************** struct stmt_ann_d GTY(())
*** 234,245 ****
  
    /* Array of variables that have had their address taken in the statement.  */
    varray_type addresses_taken;
- 
-   /* The BIND_EXPR to that the statement belongs.  */
-   tree scope;
- 
-   /* For BIND_EXPR, its level in the tree of BIND_EXPRs.  */
-   int scope_level;
  };
  
  
--- 231,236 ----
*************** extern GTY(()) tree global_var;
*** 387,392 ****
--- 378,386 ----
  /* Array of all variables that are call clobbered in the function.  */
  extern GTY(()) varray_type call_clobbered_vars;
  
+ /* List of the variables found during gimple lowering pass.  */
+ extern GTY(()) tree unexpanded_var_list;
+ 
  #define num_call_clobbered_vars	VARRAY_ACTIVE_SIZE (call_clobbered_vars)
  #define add_call_clobbered_var(v) VARRAY_PUSH_TREE (call_clobbered_vars, v)
  #define call_clobbered_var(i) VARRAY_TREE (call_clobbered_vars, i)
*************** extern void mark_new_vars_to_rename (tre
*** 484,489 ****
--- 478,484 ----
  
  /* In gimple-low.c  */
  void lower_function_body (tree *);
+ void expand_used_vars (void);
  
  /* In tree-ssa.c  */
  extern void init_tree_ssa (void);
*************** void tree_ssa_dce (tree, enum tree_dump_
*** 522,529 ****
  
  /* In tree-ssa-copyprop.c  */
  void tree_ssa_copyprop (tree, enum tree_dump_index);
! void propagate_copy (tree *, tree, tree);
! void fixup_var_scope (tree, tree);
  
  /* In tree-flow-inline.h  */
  static inline int phi_arg_from_edge (tree, edge);
--- 517,523 ----
  
  /* 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);
Index: tree-must-alias.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-must-alias.c,v
retrieving revision 1.1.2.5
diff -c -3 -p -r1.1.2.5 tree-must-alias.c
*** tree-must-alias.c	12 Oct 2003 19:43:32 -0000	1.1.2.5
--- tree-must-alias.c	2 Nov 2003 11:24:55 -0000
*************** tree_compute_must_alias (tree fndecl, sb
*** 97,102 ****
--- 97,103 ----
  	  && !POINTER_TYPE_P (TREE_TYPE (var))
  	  && TREE_CODE (TREE_TYPE (var)) != ARRAY_TYPE
  	  && decl_function_context (var) == current_function_decl
+ 	  && !DECL_NONLOCAL (var)
  	  && !TEST_BIT (addresses_needed, var_ann (var)->uid))
  	promote_var (var, vars_to_rename);
      }
Index: tree-optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-optimize.c,v
retrieving revision 1.1.4.66
diff -c -3 -p -r1.1.4.66 tree-optimize.c
*** tree-optimize.c	2 Nov 2003 09:57:20 -0000	1.1.4.66
--- tree-optimize.c	2 Nov 2003 11:24:56 -0000
*************** tree_rest_of_compilation (tree fndecl, b
*** 313,318 ****
--- 313,321 ----
    /* Set up parameters and prepare for return, for the function.  */
    expand_function_start (fndecl, 0);
  
+   /* Expand the variables recorded during gimple lowering.  */
+   expand_used_vars ();
+ 
    /* 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.20
diff -c -3 -p -r1.1.2.20 tree-ssa-copyprop.c
*** tree-ssa-copyprop.c	25 Oct 2003 17:48:24 -0000	1.1.2.20
--- tree-ssa-copyprop.c	2 Nov 2003 11:24:56 -0000
*************** static int dump_flags;
*** 45,51 ****
  static void copyprop_stmt (tree);
  static void copyprop_phi (tree);
  static inline tree get_original (tree);
- static void move_var_to_scope (tree, tree, tree);
  
  
  /* Main entry point to the copy propagator.  The algorithm is a simple
--- 45,50 ----
*************** copyprop_stmt (tree stmt)
*** 128,134 ****
  	      fprintf (dump_file, "\n");
  	    }
  
! 	  propagate_copy (use_p, orig, ann->scope);
  	  modified = true;
  	}
      }
--- 127,133 ----
  	      fprintf (dump_file, "\n");
  	    }
  
! 	  propagate_copy (use_p, orig);
  	  modified = true;
  	}
      }
*************** get_original (tree var)
*** 219,230 ****
  
  /* Replace the operand pointed to by OP_P with variable VAR.  If *OP_P is a
     pointer, copy the memory tag used originally by *OP_P into VAR.  This is
!    needed in cases where VAR had never been dereferenced in the program.
!    
!    SCOPE is the bind block in that the *OP_P occurs.  */
     
  void
! propagate_copy (tree *op_p, tree var, tree scope)
  {
  #if defined ENABLE_CHECKING
    if (!may_propagate_copy (*op_p, var))
--- 218,227 ----
  
  /* Replace the operand pointed to by OP_P with variable VAR.  If *OP_P is a
     pointer, copy the memory tag used originally by *OP_P into VAR.  This is
!    needed in cases where VAR had never been dereferenced in the program.  */
     
  void
! propagate_copy (tree *op_p, tree var)
  {
  #if defined ENABLE_CHECKING
    if (!may_propagate_copy (*op_p, var))
*************** propagate_copy (tree *op_p, tree var, tr
*** 247,316 ****
      }
  
    *op_p = var;
-  
-   fixup_var_scope (var, scope);
- }
- 
- /* Fixes scope of variable VAR if it does not currently belong to SCOPE.  */
- 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.  */
-   if (old_scope)
-     {
-       if (!scope)
- 	scope = DECL_SAVED_TREE (current_function_decl);
-       else
- 	{
- 	  while (stmt_ann (scope)->scope_level
- 		 > stmt_ann (old_scope)->scope_level)
- 	    scope = stmt_ann (scope)->scope;
- 	}
-       if (scope != old_scope)
- 	move_var_to_scope (var, old_scope,
- 			   DECL_SAVED_TREE (current_function_decl));
-     }
- }
- 
- /* Moves variable VAR from OLD_SCOPE to SCOPE.  */
- static void
- move_var_to_scope (tree var, tree old_scope, tree scope)
- {
-   tree avar, prev;
-   tree block = BIND_EXPR_BLOCK (old_scope);
- 
-   prev = NULL_TREE;
-   for (avar = BIND_EXPR_VARS (old_scope);
-        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) = TREE_CHAIN (avar);
- 
-   TREE_CHAIN (var) = BIND_EXPR_VARS (scope);
-   BIND_EXPR_VARS (scope) = 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.  */
-   if (!TREE_STATIC (var))
-     DECL_ABSTRACT_ORIGIN (var) = NULL_TREE;
  }
--- 244,247 ----
Index: tree-ssa-dom.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-dom.c,v
retrieving revision 1.1.2.71
diff -c -3 -p -r1.1.2.71 tree-ssa-dom.c
*** tree-ssa-dom.c	31 Oct 2003 20:57:41 -0000	1.1.2.71
--- tree-ssa-dom.c	2 Nov 2003 11:24:56 -0000
*************** cprop_into_stmt (tree stmt)
*** 1645,1651 ****
  	      may_have_exposed_new_symbols = true;
  
  	    if (TREE_CODE (val) == SSA_NAME)
! 	      propagate_copy (op_p, val, stmt_ann (stmt)->scope);
  	    else
  	      *op_p = val;
  
--- 1645,1651 ----
  	      may_have_exposed_new_symbols = true;
  
  	    if (TREE_CODE (val) == SSA_NAME)
! 	      propagate_copy (op_p, val);
  	    else
  	      *op_p = val;
  
*************** eliminate_redundant_computations (tree s
*** 1830,1840 ****
  	abort ();
  #endif
  
!       if (TREE_CODE (cached_lhs) == SSA_NAME)
! 	fixup_var_scope (cached_lhs, ann->scope);
!       else if (TREE_CODE (cached_lhs) == ADDR_EXPR
! 	       || (POINTER_TYPE_P (TREE_TYPE (*expr_p))
! 		   && is_gimple_min_invariant (cached_lhs)))
  	retval = true;
  
        *expr_p = cached_lhs;
--- 1830,1838 ----
  	abort ();
  #endif
  
!       if (TREE_CODE (cached_lhs) == ADDR_EXPR
! 	  || (POINTER_TYPE_P (TREE_TYPE (*expr_p))
! 	      && is_gimple_min_invariant (cached_lhs)))
  	retval = true;
  
        *expr_p = cached_lhs;
Index: tree-ssa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa.c,v
retrieving revision 1.1.4.141
diff -c -3 -p -r1.1.4.141 tree-ssa.c
*** tree-ssa.c	25 Oct 2003 17:48:24 -0000	1.1.4.141
--- tree-ssa.c	2 Nov 2003 11:24:56 -0000
*************** create_temp (tree t)
*** 915,921 ****
  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);
--- 915,921 ----
  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);
*************** insert_copy_on_edge (edge e, tree dest, 
*** 934,956 ****
        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);
  }
--- 934,939 ----


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