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_remove_useless_stmts


This is Zdenek's code to implement a CFG-aware version of remove_useless_stmts
which fixes 20030814-4 and 20030814-5.

The only changes since Zdenek's last publicly posted version are that
it avoids munging GOTO_EXPRs when their associated edges are abnormal
(say for a nonlocal goto).

The libjava problems I was having were due to a problem with the exec-shield
capabilities in Red Hat's kernels.  Ugh.   Turning off exec-shield allowed
me to get a regression test with libjava.

I've bootstrapped and regression tested this on i686-pc-linux-gnu.




	* tree-cfg.c (cfg_remove_useless_stmts): New function.
	(cfg_remove_useless_stmts_bb): Likewise.
	* tree-flow.h (cfg_remove_useless_stmts): Prototype.
	* tree-ssa.c (rewrite_out_of_ssa): Use cfg_remove_useless_stmts
	instead of remove_useless_stmts.

Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.209
diff -c -3 -p -r1.1.4.209 tree-cfg.c
*** tree-cfg.c	12 Nov 2003 22:06:25 -0000	1.1.4.209
--- tree-cfg.c	12 Nov 2003 23:28:57 -0000
*************** remove_useless_stmts (tree *first_p)
*** 1247,1252 ****
--- 1247,1407 ----
    factored_computed_goto_label = NULL;
  }
  
+ /* Remove obviously useless statements in basic block BB.  */
+ 
+ static void
+ cfg_remove_useless_stmts_bb (basic_block bb)
+ {
+   block_stmt_iterator bsi;
+   tree stmt;
+   tree *gotos[2], *pstmt;
+   int n_gotos, n_rem_gotos;
+   tree cond, var = NULL_TREE, val = NULL_TREE;
+   struct var_ann_d *ann;
+ 
+   /* Check whether we come here from a condition, and if so, get the
+      condition.  */
+   if (bb->pred && !bb->pred->pred_next
+       && (bb->pred->flags & (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE)))
+     {
+       cond = COND_EXPR_COND (last_stmt (bb->pred->src));
+       if (bb->pred->flags & EDGE_FALSE_VALUE)
+ 	cond = invert_truthvalue (cond);
+ 
+       if (TREE_CODE (cond) == VAR_DECL
+ 	  || TREE_CODE (cond) == PARM_DECL)
+ 	{
+ 	  var = cond;
+ 	  val = convert (TREE_TYPE (cond), integer_zero_node);
+ 	}
+       else if ((TREE_CODE (cond) == EQ_EXPR)
+ 	       && (TREE_CODE (TREE_OPERAND (cond, 0)) == VAR_DECL
+ 		   || TREE_CODE (TREE_OPERAND (cond, 0)) == PARM_DECL)
+ 	       && TREE_CONSTANT (TREE_OPERAND (cond, 1)))
+ 	{
+ 	  var = TREE_OPERAND (cond, 0);
+ 	  val = TREE_OPERAND (cond, 1);
+ 	}
+ 
+       if (var)
+ 	{
+ 	  /* Only work for normal local variables.  */
+ 	  ann = var_ann (var);
+ 	  if (!ann
+ 	      || ann->may_aliases
+ 	      || TREE_ADDRESSABLE (var))
+ 	    var = NULL_TREE;
+ 	}
+ 
+       /* Ignore floating point variables, since comparison behaves weird for
+ 	 them.  */
+       if (var
+ 	  && FLOAT_TYPE_P (TREE_TYPE (var)))
+ 	var = NULL_TREE;
+     }
+ 
+   for (bsi = bsi_start (bb); !bsi_end_p (bsi);)
+     {
+       stmt = bsi_stmt (bsi);
+ 
+       if (!var)
+ 	{
+ 	  bsi_next (&bsi);
+ 	  continue;
+ 	}
+ 
+       /* 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.  */
+       if (TREE_CODE (stmt) == MODIFY_EXPR
+ 	  && TREE_OPERAND (stmt, 0) == var
+ 	  && operand_equal_p (val, TREE_OPERAND (stmt, 1), 1))
+ 	{
+ 	  bsi_remove (&bsi);
+ 	  continue;
+ 	}
+ 
+       /* Invalidate the var if we encounter something that could modify it.  
*/
+       if (TREE_CODE (stmt) == ASM_EXPR
+ 	  || TREE_CODE (stmt) == VA_ARG_EXPR
+ 	  || (TREE_CODE (stmt) == MODIFY_EXPR
+ 	      && (TREE_OPERAND (stmt, 0) == var
+ 		  || TREE_CODE (TREE_OPERAND (stmt, 1)) == VA_ARG_EXPR)))
+ 	var = NULL_TREE;
+   
+       bsi_next (&bsi);
+     }
+ 
+   if (!stmt)
+     return;
+ 
+   /* Remove useless GOTOs from COND_EXPRs.  Other useless gotos could be
+      removed by cfg cleanup, but it is not done currently, so do it here
+      also.  */
+   if (TREE_CODE (stmt) == GOTO_EXPR
+       && (bb->succ->flags & EDGE_ABNORMAL) == 0)
+     {
+       gotos[0] = &stmt;
+       n_gotos = 1;
+     }
+   else if (TREE_CODE (stmt) == COND_EXPR
+ 	   && (bb->succ->flags & EDGE_ABNORMAL) == 0
+ 	   && (bb->succ->succ_next->flags & EDGE_ABNORMAL) == 0)
+     {
+       gotos[0] = &COND_EXPR_THEN (stmt);
+       gotos[1] = &COND_EXPR_ELSE (stmt);
+       n_gotos = 2;
+     }
+   else
+     return;
+ 
+   n_rem_gotos = n_gotos;
+   while (n_gotos--)
+     {
+       pstmt = gotos[n_gotos];
+       stmt = *pstmt;
+ 
+       if (TREE_CODE (GOTO_DESTINATION (stmt)) != LABEL_DECL)
+ 	continue;
+ 
+       if (label_to_block (GOTO_DESTINATION (stmt)) != bb->next_bb)
+ 	continue;
+ 
+       *pstmt = build_empty_stmt ();
+       n_rem_gotos--;
+     }
+ 
+   /* The statement does nothing, remove it completely.  */
+   if (!n_rem_gotos)
+     {
+       bsi = bsi_last (bb);
+       bsi_remove (&bsi);
+ 
+       if (bb->succ->succ_next)
+ 	abort ();
+ 
+       bb->succ->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
+       bb->succ->flags |= EDGE_FALLTHRU;
+     }
+ }
+ 
+ /* A cfg-aware version of remove_useless_stmts_and_vars.  */
+ 
+ void
+ cfg_remove_useless_stmts (void)
+ {
+   basic_block bb;
+ 
+ #ifdef ENABLE_CHECKING
+   verify_flow_info ();
+ #endif
+ 
+   FOR_EACH_BB (bb)
+     {
+       cfg_remove_useless_stmts_bb (bb);
+     }
+ }
+ 
  /* Delete all unreachable basic blocks.  Return true if any unreachable
     blocks were detected and removed.  */
  
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.146
diff -c -3 -p -r1.1.4.146 tree-flow.h
*** tree-flow.h	12 Nov 2003 22:06:26 -0000	1.1.4.146
--- tree-flow.h	12 Nov 2003 23:28:57 -0000
*************** extern tree *last_stmt_ptr (basic_block)
*** 435,440 ****
--- 435,441 ----
  extern edge find_taken_edge (basic_block, tree);
  extern int call_expr_flags (tree);
  extern void remove_useless_stmts (tree *);
+ extern void cfg_remove_useless_stmts (void);
  extern basic_block tree_split_edge (edge);
  extern edge thread_edge (edge, basic_block);
  extern basic_block label_to_block (tree);
Index: tree-ssa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa.c,v
retrieving revision 1.1.4.150
diff -c -3 -p -r1.1.4.150 tree-ssa.c
*** tree-ssa.c	12 Nov 2003 22:06:26 -0000	1.1.4.150
--- tree-ssa.c	12 Nov 2003 23:29:00 -0000
*************** rewrite_out_of_ssa (tree fndecl, enum tr
*** 1888,1894 ****
  
    /* Do some cleanups which reduce the amount of data the
       tree->rtl expanders deal with.  */
!   remove_useless_stmts (&DECL_SAVED_TREE (fndecl));
  
    /* Remove unnecesary variables.  */
    remove_useless_vars ();
--- 1888,1894 ----
  
    /* Do some cleanups which reduce the amount of data the
       tree->rtl expanders deal with.  */
!   cfg_remove_useless_stmts ();
  
    /* Remove unnecesary variables.  */
    remove_useless_vars ();



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