This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
[tree-ssa] Improve eliminate_useless_stmts_and_vars [Was Re: Dead-code elimination can't remove string copy insns? ]
- From: law at redhat dot com
- To: gcc-patches at gcc dot gnu dot org
- Cc: Diego Novillo <dnovillo at redhat dot com>
- Cc: Zack Weinberg <zack at codesourcery dot com>, Michael Matz <matz at suse dot de>, "gcc at gcc dot gnu dot org" <gcc at gcc dot gnu dot org>
- Date: Tue, 13 May 2003 13:35:05 -0600
- Subject: [tree-ssa] Improve eliminate_useless_stmts_and_vars [Was Re: Dead-code elimination can't remove string copy insns? ]
- Reply-to: law at redhat dot com
In message <20030513170722.GA7112@tornado.toronto.redhat.com>, Diego Novillo wr
ites:
>On Tue, May 13, 2003 at 09:40:33AM -0700, Zack Weinberg wrote:
>
>> gcc.dg/const-elim-1.c. On an x86, compile it with -march=i386 -O2;
>> rs6000-ibm-aix5 and arm-elf also show the problem.
>>
>Yup, tree-ssa handles it. The original program in GIMPLE form is
>on the left. The optimized version is on the right (we still
>don't linearize GOTO_EXPRs).
Here's the patch to allow us to eliminate the unnecessary GOTOs in
const-elim-1.c.
* tree-cfg.c (cleanup_tree_cfg): Update comments. Set repeat
anytime we remove a control structure.
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.88
diff -c -3 -p -r1.1.4.88 tree-cfg.c
*** tree-cfg.c 13 May 2003 02:16:38 -0000 1.1.4.88
--- tree-cfg.c 13 May 2003 18:36:20 -0000
*************** cleanup_tree_cfg ()
*** 1382,1395 ****
* Empty statement nodes are removed
* Some unnecessary BIND_EXPRs are removed
Clearly more work could be done. The trick is doing the analysis
and removal fast enough to be a net improvement in compile times.
Note that when we remove a control structure such as a COND_EXPR
! or BIND_EXPR, we will need to repeat this optimization pass to
! ensure we eliminate all the useless code. */
int
remove_useless_stmts_and_vars (first_p)
--- 1382,1399 ----
* Empty statement nodes are removed
+ * Unnecessary TRY_FINALLY and TRY_CATCH blocks are removed
+
+ * Unnecessary COND_EXPRs are removed
+
* Some unnecessary BIND_EXPRs are removed
Clearly more work could be done. The trick is doing the analysis
and removal fast enough to be a net improvement in compile times.
Note that when we remove a control structure such as a COND_EXPR
! BIND_EXPR, or TRY block, we will need to repeat this optimization pass
! to ensure we eliminate all the useless code. */
int
remove_useless_stmts_and_vars (first_p)
*************** remove_useless_stmts_and_vars (first_p)
*** 1436,1451 ****
label in one arm. If the label has since become unreachable
then we may be able to zap the entire conditional here.
! If this causes us to replace the COND_EXPR with an
! empty statement, then we will need to repeat this pass. */
if (integer_nonzerop (cond) && IS_EMPTY_STMT (else_clause))
! *stmt_p = then_clause;
if (integer_zerop (cond) && IS_EMPTY_STMT (then_clause))
! *stmt_p = else_clause;
!
! /* This can happen if both arms were ultimately empty. */
! if (IS_EMPTY_STMT (*stmt_p))
! repeat = 1;
}
else if (code == SWITCH_EXPR)
repeat |= remove_useless_stmts_and_vars (&SWITCH_BODY (*stmt_p));
--- 1440,1457 ----
label in one arm. If the label has since become unreachable
then we may be able to zap the entire conditional here.
! If so, replace the COND_EXPR and set up to repeat this
! optimization pass. */
if (integer_nonzerop (cond) && IS_EMPTY_STMT (else_clause))
! {
! *stmt_p = then_clause;
! repeat = 1;
! }
if (integer_zerop (cond) && IS_EMPTY_STMT (then_clause))
! {
! *stmt_p = else_clause;
! repeat = 1;
! }
}
else if (code == SWITCH_EXPR)
repeat |= remove_useless_stmts_and_vars (&SWITCH_BODY (*stmt_p));
*************** remove_useless_stmts_and_vars (first_p)
*** 1463,1479 ****
If the body of a TRY_CATCH is empty and the handler is
empty (it had no reachable code either), then we can
! emit an empty statement without the enclosing TRY_CATCH. */
if (IS_EMPTY_STMT (TREE_OPERAND (*stmt_p, 0)))
{
if (code == TRY_FINALLY_EXPR
|| IS_EMPTY_STMT (TREE_OPERAND (*stmt_p, 1)))
! *stmt_p = TREE_OPERAND (*stmt_p, 1);
!
! /* If we replaced this statement with an empty statement,
! then we'll need to repeat this optimization. */
! if (IS_EMPTY_STMT (*stmt_p))
! repeat = 1;
}
}
else if (code == BIND_EXPR)
--- 1469,1486 ----
If the body of a TRY_CATCH is empty and the handler is
empty (it had no reachable code either), then we can
! emit an empty statement without the enclosing TRY_CATCH.
!
! In both cases we want to apply this optimization pass
! again. */
if (IS_EMPTY_STMT (TREE_OPERAND (*stmt_p, 0)))
{
if (code == TRY_FINALLY_EXPR
|| IS_EMPTY_STMT (TREE_OPERAND (*stmt_p, 1)))
! {
! *stmt_p = TREE_OPERAND (*stmt_p, 1);
! repeat = 1;
! }
}
}
else if (code == BIND_EXPR)
*************** remove_useless_stmts_and_vars (first_p)
*** 1485,1491 ****
/* If the BIND_EXPR has no variables, then we can pull everything
up one level and remove the BIND_EXPR, unless this is the
toplevel BIND_EXPR for the current function or an inlined
! function. */
block = BIND_EXPR_BLOCK (*stmt_p);
if (BIND_EXPR_VARS (*stmt_p) == NULL_TREE
&& *stmt_p != DECL_SAVED_TREE (current_function_decl)
--- 1492,1501 ----
/* If the BIND_EXPR has no variables, then we can pull everything
up one level and remove the BIND_EXPR, unless this is the
toplevel BIND_EXPR for the current function or an inlined
! function.
!
! When this situation occurs we will want to apply this
! optimization again. */
block = BIND_EXPR_BLOCK (*stmt_p);
if (BIND_EXPR_VARS (*stmt_p) == NULL_TREE
&& *stmt_p != DECL_SAVED_TREE (current_function_decl)
*************** remove_useless_stmts_and_vars (first_p)
*** 1493,1505 ****
|| ! BLOCK_ABSTRACT_ORIGIN (block)
|| (TREE_CODE (BLOCK_ABSTRACT_ORIGIN (block))
!= FUNCTION_DECL)))
! *stmt_p = BIND_EXPR_BODY (*stmt_p);
!
! /* If we removed the BIND_EXPR completely and were left with
! an empty statement, then we'll need to repeat this
! optimization. */
! if (IS_EMPTY_STMT (*stmt_p))
! repeat = 1;
}
else if (code == GOTO_EXPR)
{
--- 1503,1512 ----
|| ! 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)
{