[tree-ssa] cfg_remove_useless_stmts
law@redhat.com
law@redhat.com
Wed Nov 12 23:40:00 GMT 2003
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 ();
More information about the Gcc-patches
mailing list