[tree-ssa] Removal of unused vars

law@redhat.com law@redhat.com
Thu Jun 26 05:05:00 GMT 2003


This patch allows us to eliminate a large number of the unused variables
before handing the function off to the tree->rtl translators.

Note I don't say "all the unused variables".  There are some cases that
can slip through, particularly if a variable has may aliases and via
optimizations becomes unused.  This will likely be improved once we figure
out a better way to handling aliasing, ADDR_EXPRs and the like.

This is a minor compile-time improvement.

This has gone through the usual battery of tests.

	* tree-cfg.c (remove_useless_stmts_and_vars): On the first
	iteration, remove unused variables from BIND_EXPRs.
	* tree-flow.h (var_ann_d): Add new field USED.
	(set_is_used): Prototype.
	(remove_useless_stmts_and_vars): Update prototype.
	* tree-ssa-live.c (create_ssa_var_map): Note which variables
	are used so that we can delete those which are not used.
	* tree-ssa.c (create_temp): Mark the new temporary as being used.
	(rewrite_out_of_ssa): Note if the call to remove_useless_stmts_and_vars
	is the first iteration or not.
	(set_is_used): New function.

Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.119
diff -c -3 -p -r1.1.4.119 tree-cfg.c
*** tree-cfg.c	25 Jun 2003 02:37:31 -0000	1.1.4.119
--- tree-cfg.c	26 Jun 2003 01:01:54 -0000
*************** cleanup_tree_cfg (void)
*** 1420,1426 ****
     to ensure we eliminate all the useless code.  */
    
  int
! remove_useless_stmts_and_vars (tree *first_p)
  {
    tree_stmt_iterator i;
    int repeat = 0;
--- 1420,1426 ----
     to ensure we eliminate all the useless code.  */
    
  int
! remove_useless_stmts_and_vars (tree *first_p, int first_iteration)
  {
    tree_stmt_iterator i;
    int repeat = 0;
*************** remove_useless_stmts_and_vars (tree *fir
*** 1447,1458 ****
        stmt_p = tsi_stmt_ptr (i);
        code = TREE_CODE (*stmt_p);
        if (code == LOOP_EXPR)
! 	repeat |= remove_useless_stmts_and_vars (&LOOP_EXPR_BODY (*stmt_p));
        else if (code == COND_EXPR)
  	{
  	  tree then_clause, else_clause, cond;
! 	  repeat |= remove_useless_stmts_and_vars (&COND_EXPR_THEN (*stmt_p));
! 	  repeat |= remove_useless_stmts_and_vars (&COND_EXPR_ELSE (*stmt_p));
  
  	  then_clause = COND_EXPR_THEN (*stmt_p);
  	  else_clause = COND_EXPR_ELSE (*stmt_p);
--- 1447,1461 ----
        stmt_p = tsi_stmt_ptr (i);
        code = TREE_CODE (*stmt_p);
        if (code == LOOP_EXPR)
! 	repeat |= remove_useless_stmts_and_vars (&LOOP_EXPR_BODY (*stmt_p),
! 						 first_iteration);
        else if (code == COND_EXPR)
  	{
  	  tree then_clause, else_clause, cond;
! 	  repeat |= remove_useless_stmts_and_vars (&COND_EXPR_THEN (*stmt_p),
! 						   first_iteration);
! 	  repeat |= remove_useless_stmts_and_vars (&COND_EXPR_ELSE (*stmt_p),
! 						   first_iteration);
  
  	  then_clause = COND_EXPR_THEN (*stmt_p);
  	  else_clause = COND_EXPR_ELSE (*stmt_p);
*************** remove_useless_stmts_and_vars (tree *fir
*** 1485,1499 ****
  	    }
  	}
        else if (code == SWITCH_EXPR)
! 	repeat |= remove_useless_stmts_and_vars (&SWITCH_BODY (*stmt_p));
        else if (code == CATCH_EXPR)
! 	repeat |= remove_useless_stmts_and_vars (&CATCH_BODY (*stmt_p));
        else if (code == EH_FILTER_EXPR)
! 	repeat |= remove_useless_stmts_and_vars (&EH_FILTER_FAILURE (*stmt_p));
        else if (code == TRY_CATCH_EXPR || code == TRY_FINALLY_EXPR)
  	{
! 	  repeat |= remove_useless_stmts_and_vars (&TREE_OPERAND (*stmt_p, 0));
! 	  repeat |= remove_useless_stmts_and_vars (&TREE_OPERAND (*stmt_p, 1));
  
  	  /* If the handler of a TRY_CATCH or TRY_FINALLY is empty, then
  	     we can emit the TRY block without the enclosing TRY_CATCH_EXPR
--- 1488,1507 ----
  	    }
  	}
        else if (code == SWITCH_EXPR)
! 	repeat |= remove_useless_stmts_and_vars (&SWITCH_BODY (*stmt_p),
! 						 first_iteration);
        else if (code == CATCH_EXPR)
! 	repeat |= remove_useless_stmts_and_vars (&CATCH_BODY (*stmt_p),
! 						 first_iteration);
        else if (code == EH_FILTER_EXPR)
! 	repeat |= remove_useless_stmts_and_vars (&EH_FILTER_FAILURE (*stmt_p),
! 						 first_iteration);
        else if (code == TRY_CATCH_EXPR || code == TRY_FINALLY_EXPR)
  	{
! 	  repeat |= remove_useless_stmts_and_vars (&TREE_OPERAND (*stmt_p, 0),
! 						   first_iteration);
! 	  repeat |= remove_useless_stmts_and_vars (&TREE_OPERAND (*stmt_p, 1),
! 						   first_iteration);
  
  	  /* If the handler of a TRY_CATCH or TRY_FINALLY is empty, then
  	     we can emit the TRY block without the enclosing TRY_CATCH_EXPR
*************** remove_useless_stmts_and_vars (tree *fir
*** 1527,1533 ****
  	{
  	  tree block;
  	  /* First remove anything underneath the BIND_EXPR.  */
! 	  repeat |= remove_useless_stmts_and_vars (&BIND_EXPR_BODY (*stmt_p));
  
  	  /* If the BIND_EXPR has no variables, then we can pull everything
  	     up one level and remove the BIND_EXPR, unless this is the
--- 1535,1542 ----
  	{
  	  tree block;
  	  /* First remove anything underneath the BIND_EXPR.  */
! 	  repeat |= remove_useless_stmts_and_vars (&BIND_EXPR_BODY (*stmt_p),
! 						   first_iteration);
  
  	  /* If the BIND_EXPR has no variables, then we can pull everything
  	     up one level and remove the BIND_EXPR, unless this is the
*************** remove_useless_stmts_and_vars (tree *fir
*** 1546,1551 ****
--- 1555,1622 ----
  	    {
  	      *stmt_p = BIND_EXPR_BODY (*stmt_p);
  	      repeat = 1;
+ 	    }
+ 	  else if (first_iteration)
+ 	    {
+ 	      /* 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;
+ 		    }
+ 
+ 		  /* If the variable is not aliased and has no uses, then
+ 		     it can be eliminated.  */
+ 		  ann = var_ann (vars);
+ 		  if (ann
+ 		      && ! ann->may_aliases
+ 		      && ! ann->used
+ 		      && ! ann->has_hidden_use)
+ 		    {
+ 		      /* 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);
+ 		  repeat = 1;
+ 		}
  	    }
  	}
        else if (code == GOTO_EXPR)
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.86
diff -c -3 -p -r1.1.4.86 tree-flow.h
*** tree-flow.h	24 Jun 2003 02:13:57 -0000	1.1.4.86
--- tree-flow.h	26 Jun 2003 01:01:57 -0000
*************** struct var_ann_d GTY(())
*** 103,108 ****
--- 103,112 ----
       operand using add_use or set_def.  */
    unsigned has_real_refs : 1;
  
+   /* Nonzero if this variable was used after SSA optimizations were
+      applied.  We set this when translating out of SSA form.  */
+   unsigned used : 1;
+ 
    /* A VAR_DECL used to associated pointers with the memory location that
       they are pointing to.  If IS_MEM_TAG is nonzero, then MEM_TAG is the
       pointer associated to this memory tag.  If IS_MEM_TAG is zero, then
*************** extern tree *last_stmt_ptr (basic_block)
*** 412,418 ****
  extern basic_block is_latch_block_for (basic_block);
  extern edge find_taken_edge (basic_block, tree);
  extern int call_expr_flags (tree);
! extern int remove_useless_stmts_and_vars (tree *);
  extern int could_trap_p (tree);
  
  /* In tree-dfa.c  */
--- 416,422 ----
  extern basic_block is_latch_block_for (basic_block);
  extern edge find_taken_edge (basic_block, tree);
  extern int call_expr_flags (tree);
! extern int remove_useless_stmts_and_vars (tree *, int);
  extern int could_trap_p (tree);
  
  /* In tree-dfa.c  */
*************** extern void debug_def_blocks (void);
*** 464,469 ****
--- 468,474 ----
  extern void dump_tree_ssa_stats (FILE *);
  extern void debug_tree_ssa_stats (void);
  extern void ssa_remove_edge (edge);
+ extern void set_is_used (tree);
  
  /* In tree-ssa-pre.c  */
  extern void tree_perform_ssapre		PARAMS ((tree));
Index: tree-ssa-live.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-live.c,v
retrieving revision 1.1.2.8
diff -c -3 -p -r1.1.2.8 tree-ssa-live.c
*** tree-ssa-live.c	16 Jun 2003 18:54:00 -0000	1.1.2.8
--- tree-ssa-live.c	26 Jun 2003 01:01:59 -0000
*************** create_ssa_var_map (void)
*** 306,318 ****
--- 306,335 ----
  	    {
  	      use = VARRAY_GENERIC_PTR (ops, x);
  	      register_ssa_partition (map, *use);
+ 	      set_is_used (*use);
  	    }
  
  	  dest = def_op (stmt);
  	  if (dest)
  	    {
  	      register_ssa_partition (map, *dest);
+ 	      set_is_used (*dest);
  	    }
+ 
+ 	  /* While we do not care about virtual operands for
+ 	     out of SSA, we do need to look at them to make sure
+ 	     we mark all the variables which are used.  */
+ 	  ops = vuse_ops (stmt);
+ 	  for (x = 0; ops && x < VARRAY_ACTIVE_SIZE (ops); x++)
+ 	    set_is_used (VARRAY_TREE (ops, x));
+ 
+ 	  ops = vdef_ops (stmt);
+ 	  for (x = 0; ops && x < VARRAY_ACTIVE_SIZE (ops); x++)
+ 	    {
+ 	      set_is_used (VDEF_OP (VARRAY_TREE (ops, x)));
+ 	      set_is_used (VDEF_RESULT (VARRAY_TREE (ops, x)));
+ 	    }
+ 	  
  	}
  
        /* Now register elements of PHI nodes.  */
*************** create_ssa_var_map (void)
*** 324,331 ****
  	  if (var_ann (var)->has_real_refs)
  	    {
  	      register_ssa_partition (map, var);
  	      for (i = 0; i < PHI_NUM_ARGS (phi); i++)
! 		register_ssa_partition (map, PHI_ARG_DEF (phi, i));
  	    }
  	}
      }
--- 341,352 ----
  	  if (var_ann (var)->has_real_refs)
  	    {
  	      register_ssa_partition (map, var);
+ 	      set_is_used (PHI_RESULT (phi));
  	      for (i = 0; i < PHI_NUM_ARGS (phi); i++)
! 		{
! 		  register_ssa_partition (map, PHI_ARG_DEF (phi, i));
! 		  set_is_used (PHI_ARG_DEF (phi, i));
! 		}
  	    }
  	}
      }
Index: tree-ssa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa.c,v
retrieving revision 1.1.4.97
diff -c -3 -p -r1.1.4.97 tree-ssa.c
*** tree-ssa.c	25 Jun 2003 02:50:01 -0000	1.1.4.97
--- tree-ssa.c	26 Jun 2003 01:02:10 -0000
*************** create_temp (tree t)
*** 877,882 ****
--- 877,883 ----
      name = "temp";
    tmp = create_tmp_var (type, name);
    create_var_ann (tmp);
+   set_is_used (tmp);
    return tmp;
  }
  
*************** rewrite_out_of_ssa (tree fndecl)
*** 1575,1581 ****
    var_map map;
    tree phi, next;
    elim_graph g;
!   int repeat;
  
    timevar_push (TV_TREE_SSA_TO_NORMAL);
  
--- 1576,1582 ----
    var_map map;
    tree phi, next;
    elim_graph g;
!   int repeat, first_iteration;
  
    timevar_push (TV_TREE_SSA_TO_NORMAL);
  
*************** rewrite_out_of_ssa (tree fndecl)
*** 1688,1696 ****
  
    /* Do some cleanups which reduce the amount of data the
       tree->rtl expanders deal with.  */
    do
      {
!       repeat = remove_useless_stmts_and_vars (&DECL_SAVED_TREE (fndecl));
      }
    while (repeat);
    
--- 1689,1700 ----
  
    /* Do some cleanups which reduce the amount of data the
       tree->rtl expanders deal with.  */
+   first_iteration = 1;
    do
      {
!       repeat = remove_useless_stmts_and_vars (&DECL_SAVED_TREE (fndecl),
! 					      first_iteration);
!       first_iteration = 0;
      }
    while (repeat);
    
*************** rewrite_stmt (block_stmt_iterator si, va
*** 2298,2303 ****
--- 2302,2318 ----
        register_new_def (SSA_NAME_VAR (VDEF_RESULT (vdef)), 
  			VDEF_RESULT (vdef), block_defs_p);
      }
+ }
+ 
+ /* Set the USED bit in the annotation for T.  */
+ 
+ void
+ set_is_used (tree t)
+ {
+   t = get_base_symbol (t);
+   if (TREE_CODE (t) == SSA_NAME)
+     t = SSA_NAME_VAR (t);
+   var_ann (t)->used = 1;
  }
  
  








More information about the Gcc-patches mailing list