diff options
author | Richard Biener <rguenther@suse.de> | 2023-09-14 09:31:23 +0200 |
---|---|---|
committer | Richard Biener <rguenther@suse.de> | 2023-09-14 13:15:10 +0200 |
commit | 9ea74d235c7e7816b996a17c61288f02ef767985 (patch) | |
tree | 788217d9123e7e4dca940886495f91d8b21b9ea2 /gcc | |
parent | 0f1f6cf872a03d82ab1973780b37bb8572e96f58 (diff) | |
download | gcc-9ea74d235c7e7816b996a17c61288f02ef767985.zip gcc-9ea74d235c7e7816b996a17c61288f02ef767985.tar.gz gcc-9ea74d235c7e7816b996a17c61288f02ef767985.tar.bz2 |
tree-optimization/111294 - better DCE after forwprop
The following adds more aggressive DCE to forwprop to clean up dead
stmts when folding a stmt leaves some operands unused. The patch
uses simple_dce_from_worklist for this purpose, queueing original
operands before substitution and folding, but only if we folded the
stmt.
This removes one dead stmt biasing threading costs in a later pass
but it doesn't resolve the optimization issue in the PR yet.
PR tree-optimization/111294
* tree-ssa-forwprop.cc (pass_forwprop::execute): Track
operands that eventually become dead and use simple_dce_from_worklist
to remove their definitions if they did so.
* gcc.dg/tree-ssa/evrp10.c: Adjust.
* gcc.dg/tree-ssa/evrp6.c: Likewise.
* gcc.dg/tree-ssa/forwprop-31.c: Likewise.
* gcc.dg/tree-ssa/neg-cast-3.c: Likewise.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/evrp10.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/evrp6.c | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/forwprop-31.c | 3 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/neg-cast-3.c | 4 | ||||
-rw-r--r-- | gcc/tree-ssa-forwprop.cc | 27 |
5 files changed, 28 insertions, 13 deletions
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/evrp10.c b/gcc/testsuite/gcc.dg/tree-ssa/evrp10.c index 6ca00e4..776c80c 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/evrp10.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/evrp10.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-evrp" }*/ +/* { dg-options "-O2 -fdump-tree-evrp -fno-tree-forwprop" }*/ typedef __INT32_TYPE__ int32_t; diff --git a/gcc/testsuite/gcc.dg/tree-ssa/evrp6.c b/gcc/testsuite/gcc.dg/tree-ssa/evrp6.c index aaeec68..0f9561b 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/evrp6.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/evrp6.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-evrp-details" } */ +/* { dg-options "-O2 -fdump-tree-evrp-details -fdump-tree-mergephi1" } */ extern void abort (void); @@ -18,4 +18,5 @@ foo (int k, int j) return j; } -/* { dg-final { scan-tree-dump "\\\[12, \\+INF" "evrp" } } */ +/* { dg-final { scan-tree-dump "\\\[11, \\+INF" "evrp" } } */ +/* { dg-final { scan-tree-dump-not "abort" "mergephi1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-31.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-31.c index edf8026..40cc863 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-31.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-31.c @@ -9,6 +9,5 @@ int foo (int x) return w - z; /* becomes 0 */ } -/* Only z = x + 1 is retained. */ -/* { dg-final { scan-tree-dump-times " = " 1 "forwprop1" } } */ +/* { dg-final { scan-tree-dump-times " = " 0 "forwprop1" } } */ /* { dg-final { scan-tree-dump "return 0;" "forwprop1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/neg-cast-3.c b/gcc/testsuite/gcc.dg/tree-ssa/neg-cast-3.c index 7b23ca8..61b8940 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/neg-cast-3.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/neg-cast-3.c @@ -10,6 +10,4 @@ unsigned f(_Bool a) } /* There should be no cast to int at all. */ -/* Forwprop1 does not remove all of the statements. */ -/* { dg-final { scan-tree-dump-not "\\\(int\\\)" "forwprop1" { xfail *-*-* } } } */ -/* { dg-final { scan-tree-dump-not "\\\(int\\\)" "optimized" } } */ +/* { dg-final { scan-tree-dump-not "\\\(int\\\)" "forwprop1" } } */ diff --git a/gcc/tree-ssa-forwprop.cc b/gcc/tree-ssa-forwprop.cc index 94ca47a..d4e9202 100644 --- a/gcc/tree-ssa-forwprop.cc +++ b/gcc/tree-ssa-forwprop.cc @@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see #include "cgraph.h" #include "tree-ssa.h" #include "gimple-range.h" +#include "tree-ssa-dce.h" /* This pass propagates the RHS of assignment statements into use sites of the LHS of the assignment. It's basically a specialized @@ -3502,8 +3503,9 @@ pass_forwprop::execute (function *fun) |= EDGE_EXECUTABLE; auto_vec<gimple *, 4> to_fixup; auto_vec<gimple *, 32> to_remove; + auto_bitmap simple_dce_worklist; + auto_bitmap need_ab_cleanup; to_purge = BITMAP_ALLOC (NULL); - bitmap need_ab_cleanup = BITMAP_ALLOC (NULL); for (int i = 0; i < postorder_num; ++i) { gimple_stmt_iterator gsi; @@ -3902,10 +3904,14 @@ pass_forwprop::execute (function *fun) { tree use = USE_FROM_PTR (usep); tree val = fwprop_ssa_val (use); - if (val && val != use && may_propagate_copy (use, val)) + if (val && val != use) { - propagate_value (usep, val); - substituted_p = true; + bitmap_set_bit (simple_dce_worklist, SSA_NAME_VERSION (use)); + if (may_propagate_copy (use, val)) + { + propagate_value (usep, val); + substituted_p = true; + } } } if (substituted_p @@ -3925,6 +3931,11 @@ pass_forwprop::execute (function *fun) && gimple_call_noreturn_p (stmt)); changed = false; + auto_vec<tree, 8> uses; + FOR_EACH_SSA_USE_OPERAND (usep, stmt, iter, SSA_OP_USE) + if (uses.space (1)) + uses.quick_push (USE_FROM_PTR (usep)); + if (fold_stmt (&gsi, fwprop_ssa_val)) { changed = true; @@ -3935,6 +3946,12 @@ pass_forwprop::execute (function *fun) if (gimple_cond_true_p (cond) || gimple_cond_false_p (cond)) cfg_changed = true; + /* Queue old uses for simple DCE. */ + for (tree use : uses) + if (TREE_CODE (use) == SSA_NAME + && !SSA_NAME_IS_DEFAULT_DEF (use)) + bitmap_set_bit (simple_dce_worklist, + SSA_NAME_VERSION (use)); } if (changed || substituted_p) @@ -4115,6 +4132,7 @@ pass_forwprop::execute (function *fun) release_defs (stmt); } } + simple_dce_from_worklist (simple_dce_worklist, to_purge); /* Fixup stmts that became noreturn calls. This may require splitting blocks and thus isn't possible during the walk. Do this @@ -4135,7 +4153,6 @@ pass_forwprop::execute (function *fun) cfg_changed |= gimple_purge_all_dead_eh_edges (to_purge); cfg_changed |= gimple_purge_all_dead_abnormal_call_edges (need_ab_cleanup); BITMAP_FREE (to_purge); - BITMAP_FREE (need_ab_cleanup); if (get_range_query (fun) != get_global_range_query ()) disable_ranger (fun); |