diff options
author | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-05-16 08:05:50 +0000 |
---|---|---|
committer | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-05-16 08:05:50 +0000 |
commit | 85e9a542cbd752bca4c21cbef907d190c7d3d3e1 (patch) | |
tree | 6b4c7eeefda2e10dbce6363164cd1f14df8d78f7 | |
parent | b15c78f277e9c60d61ed596fefebbeea4e5aa669 (diff) | |
download | gcc-85e9a542cbd752bca4c21cbef907d190c7d3d3e1.tar.gz |
2014-05-16 Richard Biener <rguenther@suse.de>
* tree-ssa-sccvn.c: Include tree-cfg.h and domwalk.h.
(set_ssa_val_to): Handle unexpected sets to VN_TOP.
(visit_phi): Ignore edges marked as not executable.
(class cond_dom_walker): New.
(cond_dom_walker::before_dom_children): Value-number
control statements and mark successor edges as not
executable if possible.
(run_scc_vn): First walk all control statements in
dominator order, marking edges as not executable.
* tree-inline.c (copy_edges_for_bb): Be not confused
about random edge flags.
* gcc.dg/tree-ssa/ssa-fre-39.c: New testcase.
* gcc.dg/tree-ssa/ssa-fre-40.c: Likewise.
* gcc.dg/tree-ssa/ssa-pre-8.c: One more elimination.
* gcc.dg/tree-ssa/struct-aliasing-2.c: Scan cddce1 dump.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@210492 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-39.c | 19 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-40.c | 16 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-8.c | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/struct-aliasing-2.c | 10 | ||||
-rw-r--r-- | gcc/tree-inline.c | 3 | ||||
-rw-r--r-- | gcc/tree-ssa-sccvn.c | 192 |
8 files changed, 230 insertions, 35 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3df0bb4022e..cc0d973056f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,19 @@ 2014-05-16 Richard Biener <rguenther@suse.de> + * tree-ssa-sccvn.c: Include tree-cfg.h and domwalk.h. + (set_ssa_val_to): Handle unexpected sets to VN_TOP. + (visit_phi): Ignore edges marked as not executable. + (class cond_dom_walker): New. + (cond_dom_walker::before_dom_children): Value-number + control statements and mark successor edges as not + executable if possible. + (run_scc_vn): First walk all control statements in + dominator order, marking edges as not executable. + * tree-inline.c (copy_edges_for_bb): Be not confused + about random edge flags. + +2014-05-16 Richard Biener <rguenther@suse.de> + * tree-ssa-sccvn.c (visit_use): Also constant-fold calls. 2014-05-15 Peter Bergner <bergner@vnet.ibm.com> diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8c52f8cd9d8..66d0694e0c1 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,12 @@ 2014-05-16 Richard Biener <rguenther@suse.de> + * gcc.dg/tree-ssa/ssa-fre-39.c: New testcase. + * gcc.dg/tree-ssa/ssa-fre-40.c: Likewise. + * gcc.dg/tree-ssa/ssa-pre-8.c: One more elimination. + * gcc.dg/tree-ssa/struct-aliasing-2.c: Scan cddce1 dump. + +2014-05-16 Richard Biener <rguenther@suse.de> + * gcc.dg/tree-ssa/ssa-fre-41.c: New testcase. 2014-05-15 Martin Jambor <mjambor@suse.cz> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-39.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-39.c new file mode 100644 index 00000000000..a30926caccd --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-39.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-fre1" } */ + +int foo (int i) +{ + int k = i + 1; + int j = i + 1; + if (k != j) + k = k + 1; + if (k != j) + k = k + 1; + k = k - i; + return k; +} + +/* We should be able to value-number the final assignment to k to 1. */ + +/* { dg-final { scan-tree-dump "k_. = 1;" "fre1" } } */ +/* { dg-final { cleanup-tree-dump "fre1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-40.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-40.c new file mode 100644 index 00000000000..dd085a08770 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-40.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-fre1" } */ + +int x; +int foo (int *p) +{ + x = 0; + if (x) + *p = 1; + return x; +} + +/* The final load of x should be replaced as well as the + aliasing store via *p is not reachable. */ + +/* { dg-final { scan-tree-dump-not "= x;" "fre1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-8.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-8.c index f08ef7fde60..dab57fa391b 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-8.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-8.c @@ -17,7 +17,9 @@ foo (__SIZE_TYPE__ i, struct s *array) return 0; } /* We should eliminate two address calculations, and one load. */ +/* We also elimiate the PHI node feeding the return because the case + returning 1 is unreachable. */ /* We used to eliminate a cast but that was before POINTER_PLUS_EXPR was added. */ -/* { dg-final { scan-tree-dump-times "Eliminated: 3" 1 "fre1"} } */ +/* { dg-final { scan-tree-dump-times "Eliminated: 4" 1 "fre1"} } */ /* { dg-final { cleanup-tree-dump "fre1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/struct-aliasing-2.c b/gcc/testsuite/gcc.dg/tree-ssa/struct-aliasing-2.c index c348bdfe25b..66a5442a9ef 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/struct-aliasing-2.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/struct-aliasing-2.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-fre1" } */ +/* { dg-options "-O2 -fdump-tree-cddce1" } */ struct S { unsigned f; }; @@ -12,8 +12,8 @@ foo ( struct S *p) } -/* There should only be one load of p->f because fwprop can change - *(int *)&p->f into just (int)p->f. */ -/* { dg-final { scan-tree-dump-times "= \[^\n\]*p_.\\\(D\\\)" 1 "fre1" } } */ -/* { dg-final { cleanup-tree-dump "fre1" } } */ +/* There should only be one load of p->f because FRE removes the redundancy + by realizing it can cast the result of either to the other. */ +/* { dg-final { scan-tree-dump-times "= \[^\n\]*p_.\\\(D\\\)" 1 "cddce1" } } */ +/* { dg-final { cleanup-tree-dump "cddce1" } } */ diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 9207e9f7296..bc2b2712b05 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -1984,7 +1984,8 @@ copy_edges_for_bb (basic_block bb, gcov_type count_scale, basic_block ret_bb, flags = old_edge->flags; /* Return edges do get a FALLTHRU flag when the get inlined. */ - if (old_edge->dest->index == EXIT_BLOCK && !old_edge->flags + if (old_edge->dest->index == EXIT_BLOCK + && !(old_edge->flags & (EDGE_TRUE_VALUE|EDGE_FALSE_VALUE|EDGE_FAKE)) && old_edge->dest->aux != EXIT_BLOCK_PTR_FOR_FN (cfun)) flags |= EDGE_FALLTHRU; new_edge = make_edge (new_bb, (basic_block) old_edge->dest->aux, flags); diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index 93a7e301240..84c0d6e1feb 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -51,6 +51,8 @@ along with GCC; see the file COPYING3. If not see #include "params.h" #include "tree-ssa-propagate.h" #include "tree-ssa-sccvn.h" +#include "tree-cfg.h" +#include "domwalk.h" /* This algorithm is based on the SCC algorithm presented by Keith Cooper and L. Taylor Simpson in "SCC-Based Value numbering" @@ -2661,6 +2663,25 @@ set_ssa_val_to (tree from, tree to) tree currval = SSA_VAL (from); HOST_WIDE_INT toff, coff; + /* The only thing we allow as value numbers are ssa_names + and invariants. So assert that here. We don't allow VN_TOP + as visiting a stmt should produce a value-number other than + that. + ??? Still VN_TOP can happen for unreachable code, so force + it to varying in that case. Not all code is prepared to + get VN_TOP on valueization. */ + if (to == VN_TOP) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, "Forcing value number to varying on " + "receiving VN_TOP\n"); + to = from; + } + + gcc_assert (to != NULL_TREE + && (TREE_CODE (to) == SSA_NAME + || is_gimple_min_invariant (to))); + if (from != to) { if (currval == from) @@ -2680,13 +2701,6 @@ set_ssa_val_to (tree from, tree to) to = from; } - /* The only thing we allow as value numbers are VN_TOP, ssa_names - and invariants. So assert that here. */ - gcc_assert (to != NULL_TREE - && (to == VN_TOP - || TREE_CODE (to) == SSA_NAME - || is_gimple_min_invariant (to))); - if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, "Setting value number of "); @@ -3071,7 +3085,6 @@ visit_phi (gimple phi) tree result; tree sameval = VN_TOP; bool allsame = true; - unsigned i; /* TODO: We could check for this in init_sccvn, and replace this with a gcc_assert. */ @@ -3080,27 +3093,30 @@ visit_phi (gimple phi) /* See if all non-TOP arguments have the same value. TOP is equivalent to everything, so we can ignore it. */ - for (i = 0; i < gimple_phi_num_args (phi); i++) - { - tree def = PHI_ARG_DEF (phi, i); + edge_iterator ei; + edge e; + FOR_EACH_EDGE (e, ei, gimple_bb (phi)->preds) + if (e->flags & EDGE_EXECUTABLE) + { + tree def = PHI_ARG_DEF_FROM_EDGE (phi, e); - if (TREE_CODE (def) == SSA_NAME) - def = SSA_VAL (def); - if (def == VN_TOP) - continue; - if (sameval == VN_TOP) - { - sameval = def; - } - else - { - if (!expressions_equal_p (def, sameval)) - { - allsame = false; - break; - } - } - } + if (TREE_CODE (def) == SSA_NAME) + def = SSA_VAL (def); + if (def == VN_TOP) + continue; + if (sameval == VN_TOP) + { + sameval = def; + } + else + { + if (!expressions_equal_p (def, sameval)) + { + allsame = false; + break; + } + } + } /* If all value numbered to the same value, the phi node has that value. */ @@ -4140,6 +4156,105 @@ set_hashtable_value_ids (void) set_value_id_for_result (vr->result, &vr->value_id); } +class cond_dom_walker : public dom_walker +{ +public: + cond_dom_walker () : dom_walker (CDI_DOMINATORS), fail (false) {} + + virtual void before_dom_children (basic_block); + + bool fail; +}; + +void +cond_dom_walker::before_dom_children (basic_block bb) +{ + edge e; + edge_iterator ei; + + if (fail) + return; + + /* If any of the predecessor edges are still marked as possibly + executable consider this block reachable. */ + bool reachable = bb == ENTRY_BLOCK_PTR_FOR_FN (cfun); + FOR_EACH_EDGE (e, ei, bb->preds) + reachable |= (e->flags & EDGE_EXECUTABLE); + + /* If the block is not reachable all outgoing edges are not + executable. */ + if (!reachable) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, "Marking all outgoing edges of unreachable " + "BB %d as not executable\n", bb->index); + + FOR_EACH_EDGE (e, ei, bb->succs) + e->flags &= ~EDGE_EXECUTABLE; + return; + } + + gimple stmt = last_stmt (bb); + if (!stmt) + return; + + /* Value-number the last stmts SSA uses. */ + ssa_op_iter i; + tree op; + FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_USE) + if (VN_INFO (op)->visited == false + && !DFS (op)) + { + fail = true; + return; + } + + /* ??? We can even handle stmts with outgoing EH or ABNORMAL edges + if value-numbering can prove they are not reachable. Handling + computed gotos is also possible. */ + tree val; + switch (gimple_code (stmt)) + { + case GIMPLE_COND: + { + tree lhs = gimple_cond_lhs (stmt); + tree rhs = gimple_cond_rhs (stmt); + /* Work hard in computing the condition and take into account + the valueization of the defining stmt. */ + if (TREE_CODE (lhs) == SSA_NAME) + lhs = vn_get_expr_for (lhs); + if (TREE_CODE (rhs) == SSA_NAME) + rhs = vn_get_expr_for (rhs); + val = fold_binary (gimple_cond_code (stmt), + boolean_type_node, lhs, rhs); + break; + } + case GIMPLE_SWITCH: + val = gimple_switch_index (stmt); + break; + case GIMPLE_GOTO: + val = gimple_goto_dest (stmt); + break; + default: + val = NULL_TREE; + break; + } + if (!val) + return; + + edge taken = find_taken_edge (bb, vn_valueize (val)); + if (!taken) + return; + + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, "Marking all edges out of BB %d but (%d -> %d) as " + "not executable\n", bb->index, bb->index, taken->dest->index); + + FOR_EACH_EDGE (e, ei, bb->succs) + if (e != taken) + e->flags &= ~EDGE_EXECUTABLE; +} + /* Do SCCVN. Returns true if it finished, false if we bailed out due to resource constraints. DEFAULT_VN_WALK_KIND_ specifies how we use the alias oracle walking during the VN process. */ @@ -4147,6 +4262,7 @@ set_hashtable_value_ids (void) bool run_scc_vn (vn_lookup_kind default_vn_walk_kind_) { + basic_block bb; size_t i; tree param; @@ -4164,6 +4280,26 @@ run_scc_vn (vn_lookup_kind default_vn_walk_kind_) VN_INFO (def)->valnum = def; } + /* Mark all edges as possibly executable. */ + FOR_ALL_BB_FN (bb, cfun) + { + edge_iterator ei; + edge e; + FOR_EACH_EDGE (e, ei, bb->succs) + e->flags |= EDGE_EXECUTABLE; + } + + /* Walk all blocks in dominator order, value-numbering the last stmts + SSA uses and decide whether outgoing edges are not executable. */ + cond_dom_walker walker; + walker.walk (ENTRY_BLOCK_PTR_FOR_FN (cfun)); + if (walker.fail) + { + free_scc_vn (); + return false; + } + + /* Value-number remaining SSA names. */ for (i = 1; i < num_ssa_names; ++i) { tree name = ssa_name (i); |