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] New regressions as of 2003-11-04


Hello,

> >>Lots of changes yesterday produced new regressions in C, C++, Fortran
> >>and mudflap.  I think I know what the mudflap problem is, so I'll take
> >>care of that.  Could you folks take a look at the new regressions and
> >>see if they're related to your changes?
> >>	 FAIL: gcc.dg/tree-ssa/20030814-4.c scan-tree-dump-times set = -1 0
> >>	 FAIL: gcc.dg/tree-ssa/20030814-5.c scan-tree-dump-times set = -1 0
> >OK.  After looking at these some more.  These are failures that are a
> >combination of the COND_EXPR lowering and some sillyness in PRE.

this patch adds a cfg-aware version of remove_useless_..., thus fixing
these failures.

Zdenek

	* basic-block.h (create_bb): Declaration changed.
	* tree-cfg.c (create_bb): Enable creating a block on specified place.
	(make_blocks, tree_split_edge, tree_make_forwarder_block): Use it.
	(tree_verify_flow_info): Check bbs are in the correct order.
	(cfg_remove_useless_stmts_bb, cfg_remove_useless_stmts): New.
	(remove_unreachable_blocks): Remove missleading comments.
	* tree-flow.h (cfg_remove_useless_stmts): Declare.
	* tree-ssa.c (rewrite_out_of_ssa): Use cfg_remove_useless_stmts instead
	of remove_useless_stmts_and_vars.

Index: basic-block.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/basic-block.h,v
retrieving revision 1.153.2.32
diff -c -3 -p -r1.153.2.32 basic-block.h
*** basic-block.h	1 Nov 2003 20:27:15 -0000	1.153.2.32
--- basic-block.h	6 Nov 2003 17:21:39 -0000
*************** extern void dump_edge_info (FILE *, edge
*** 384,390 ****
  extern void clear_edges (void);
  extern void mark_critical_edges (void);
  extern rtx first_insn_after_basic_block_note (basic_block);
! extern basic_block create_bb (void);
  
  /* Dominator information for basic blocks.  */
  
--- 384,390 ----
  extern void clear_edges (void);
  extern void mark_critical_edges (void);
  extern rtx first_insn_after_basic_block_note (basic_block);
! extern basic_block create_bb (basic_block);
  
  /* Dominator information for basic blocks.  */
  
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.196
diff -c -3 -p -r1.1.4.196 tree-cfg.c
*** tree-cfg.c	6 Nov 2003 15:32:41 -0000	1.1.4.196
--- tree-cfg.c	6 Nov 2003 17:21:40 -0000
*************** make_blocks (tree *first_p, basic_block 
*** 431,437 ****
  	 so now.  */
        if (start_new_block || stmt_starts_bb_p (stmt, prev_stmt))
  	{
! 	  bb = create_bb ();
  	  start_new_block = false;
  	}
  
--- 431,437 ----
  	 so now.  */
        if (start_new_block || stmt_starts_bb_p (stmt, prev_stmt))
  	{
! 	  bb = create_bb (NULL);
  	  start_new_block = false;
  	}
  
*************** prepend_stmt_to_bb (tree *stmt_p, basic_
*** 493,502 ****
  }
  
  
! /* Create and return a new basic block.  */
  
  basic_block
! create_bb (void)
  {
    basic_block bb;
  
--- 493,502 ----
  }
  
  
! /* Create and return a new basic block after bb AFTER.  */
  
  basic_block
! create_bb (basic_block after)
  {
    basic_block bb;
  
*************** create_bb (void)
*** 508,517 ****
    bb->flags = BB_NEW;
  
    /* Add the new block to the linked list of blocks.  */
!   if (n_basic_blocks > 0)
!     link_block (bb, BASIC_BLOCK (n_basic_blocks - 1));
!   else
!     link_block (bb, ENTRY_BLOCK_PTR);
  
    /* Grow the basic block array if needed.  */
    if ((size_t) n_basic_blocks == VARRAY_SIZE (basic_block_info))
--- 508,516 ----
    bb->flags = BB_NEW;
  
    /* Add the new block to the linked list of blocks.  */
!   if (!after)
!     after = EXIT_BLOCK_PTR->prev_bb;
!   link_block (bb, after);
  
    /* Grow the basic block array if needed.  */
    if ((size_t) n_basic_blocks == VARRAY_SIZE (basic_block_info))
*************** remove_useless_stmts_and_vars (tree *fir
*** 1276,1281 ****
--- 1275,1429 ----
    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) == MODIFY_EXPR
+ 	  && TREE_OPERAND (stmt, 0) == var)
+ 	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)
+     {
+       gotos[0] = &stmt;
+       n_gotos = 1;
+     }
+   else if (TREE_CODE (stmt) == COND_EXPR)
+     {
+       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.  */
  
*************** remove_unreachable_blocks (void)
*** 1288,1301 ****
  
    find_unreachable_blocks ();
  
-   /* Remove unreachable blocks in reverse.  That will expose more unnecessary
-      COMPOUND_EXPRs that we can remove.  */
    for (i = last_basic_block - 1; i >= 0; i--)
      {
        bb = BASIC_BLOCK (i);
  
-       /* The block may have been removed in a previous iteration if it was
- 	 inside an unreachable control structure.  */
        if (bb == NULL)
  	continue;
  
--- 1436,1445 ----
*************** tree_split_edge (edge edge_in)
*** 3454,3460 ****
      abort ();
  
    dest = edge_in->dest;
!   new_bb = create_bb ();
    create_block_annotation (new_bb);
    redirect_edge_succ  (edge_in, new_bb);
    new_edge = make_edge (new_bb, dest, 0);
--- 3598,3604 ----
      abort ();
  
    dest = edge_in->dest;
!   new_bb = create_bb (edge_in->src);
    create_block_annotation (new_bb);
    redirect_edge_succ  (edge_in, new_bb);
    new_edge = make_edge (new_bb, dest, 0);
*************** static int
*** 3482,3490 ****
  tree_verify_flow_info (void)
  {
    int err = 0;
!   basic_block bb;
    block_stmt_iterator bsi;
    tree stmt;
  
    FOR_EACH_BB (bb)
      {
--- 3626,3635 ----
  tree_verify_flow_info (void)
  {
    int err = 0;
!   basic_block bb, abb;
    block_stmt_iterator bsi;
    tree stmt;
+   tree_stmt_iterator tsi;
  
    FOR_EACH_BB (bb)
      {
*************** tree_verify_flow_info (void)
*** 3508,3513 ****
--- 3653,3686 ----
  	}
      }
  
+   /* Check that order of basic blocks is the same as the order of code.  */
+   bb = ENTRY_BLOCK_PTR->next_bb;
+   if (bb == EXIT_BLOCK_PTR
+       || !bb->head_tree_p)
+     return err;
+ 
+   for (tsi = tsi_start (bb->head_tree_p); !tsi_end_p (tsi); tsi_next (&tsi))
+     {
+       if (IS_EMPTY_STMT (tsi_stmt (tsi)))
+ 	continue;
+  
+       abb = bb_for_stmt (tsi_stmt (tsi));
+       if (!abb)
+ 	continue;
+ 
+       if (abb != bb)
+ 	{
+ 	  if (abb != bb->next_bb)
+ 	    {
+ 	      fprintf (stderr, "Block missordering after bb %d\n",
+ 		       bb->index);
+ 	      err = 1;
+ 	    }
+ 
+ 	  bb = abb;
+ 	}
+     }
+ 
    return err;
  }
  
*************** tree_make_forwarder_block (basic_block b
*** 3526,3532 ****
    basic_block dummy;
  
    /* Create the new basic block.  */
!   dummy = create_bb ();
    create_block_annotation (dummy);
    dummy->count = bb->count;
    dummy->frequency = bb->frequency;
--- 3699,3705 ----
    basic_block dummy;
  
    /* Create the new basic block.  */
!   dummy = create_bb (NULL);
    create_block_annotation (dummy);
    dummy->count = bb->count;
    dummy->frequency = bb->frequency;
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.141
diff -c -3 -p -r1.1.4.141 tree-flow.h
*** tree-flow.h	5 Nov 2003 13:39:23 -0000	1.1.4.141
--- tree-flow.h	6 Nov 2003 17:21:40 -0000
*************** extern tree *last_stmt_ptr (basic_block)
*** 449,454 ****
--- 449,455 ----
  extern edge find_taken_edge (basic_block, tree);
  extern int call_expr_flags (tree);
  extern void remove_useless_stmts_and_vars (tree *, bool);
+ extern void cfg_remove_useless_stmts (void);
  extern basic_block tree_split_edge (edge);
  extern void bsi_move_before (block_stmt_iterator, block_stmt_iterator);
  extern void bsi_move_after (block_stmt_iterator, block_stmt_iterator);
Index: tree-ssa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa.c,v
retrieving revision 1.1.4.145
diff -c -3 -p -r1.1.4.145 tree-ssa.c
*** tree-ssa.c	5 Nov 2003 13:39:24 -0000	1.1.4.145
--- tree-ssa.c	6 Nov 2003 17:21:40 -0000
*************** rewrite_out_of_ssa (tree fndecl, enum tr
*** 1888,1899 ****
  
    /* 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);
! 
!   /* Flush out flow graph and SSA data.  */
!   delete_tree_ssa (fndecl);
!   delete_var_map (map);
!   timevar_pop (TV_TREE_SSA_TO_NORMAL);
  
    /* Debugging dumps.  */
    if (dump_file)
--- 1888,1894 ----
  
    /* Do some cleanups which reduce the amount of data the
       tree->rtl expanders deal with.  */
!   cfg_remove_useless_stmts ();
  
    /* Debugging dumps.  */
    if (dump_file)
*************** rewrite_out_of_ssa (tree fndecl, enum tr
*** 1901,1906 ****
--- 1896,1906 ----
        dump_cfg_function_to_file (fndecl, dump_file, dump_flags);
        dump_end (phase, dump_file);
      }
+ 
+   /* Flush out flow graph and SSA data.  */
+   delete_tree_ssa (fndecl);
+   delete_var_map (map);
+   timevar_pop (TV_TREE_SSA_TO_NORMAL);
  }
  
  


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