This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [tree-ssa] New regressions as of 2003-11-04
- From: Zdenek Dvorak <rakdver at atrey dot karlin dot mff dot cuni dot cz>
- To: gcc-patches at gcc dot gnu dot org
- Cc: law at redhat dot com, Jan Hubicka <jh at suse dot cz>,Daniel Berlin <dberlin at dberlin dot org>,Diego Novillo <dnovillo at redhat dot com>
- Date: Thu, 6 Nov 2003 18:29:01 +0100
- Subject: Re: [tree-ssa] New regressions as of 2003-11-04
- References: <200311042051.hA4KpfNw017019@speedy.slc.redhat.com> <5ACBA442-0F09-11D8-AC8B-000A95AF1FAE@dberlin.org>
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);
}