diff options
author | rakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-05-17 19:55:53 +0000 |
---|---|---|
committer | rakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-05-17 19:55:53 +0000 |
commit | 8171a1dd58f689ea938c7a771c5ec6020cca13d5 (patch) | |
tree | d5471dc3f0c17a518b2a28a858669d705b2a853d /gcc | |
parent | 9ba78c6a99a114f5e01304cbbebfa12e2af95057 (diff) | |
download | gcc-8171a1dd58f689ea938c7a771c5ec6020cca13d5.tar.gz |
* tree-cfg.c (tree_can_merge_blocks_p): Allow phi nodes in the
merged block.
(replace_uses_by): New function.
(tree_merge_blocks): Eliminate the phi nodes in the merged block.
* tree-flow.h (fold_stmt_inplace): Declare.
* tree-ssa-ccp.c (fold_stmt_inplace): New function.
* tree-ssa-dom.c (tree_ssa_dominator_optimize): Update dominance
info after cfg cleanup.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@99850 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/tree-cfg.c | 96 | ||||
-rw-r--r-- | gcc/tree-flow.h | 1 | ||||
-rw-r--r-- | gcc/tree-ssa-ccp.c | 26 | ||||
-rw-r--r-- | gcc/tree-ssa-dom.c | 1 |
5 files changed, 132 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 85483143181..141be32fece 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,16 @@ 2005-05-17 Zdenek Dvorak <dvorakz@suse.cz> + * tree-cfg.c (tree_can_merge_blocks_p): Allow phi nodes in the + merged block. + (replace_uses_by): New function. + (tree_merge_blocks): Eliminate the phi nodes in the merged block. + * tree-flow.h (fold_stmt_inplace): Declare. + * tree-ssa-ccp.c (fold_stmt_inplace): New function. + * tree-ssa-dom.c (tree_ssa_dominator_optimize): Update dominance + info after cfg cleanup. + +2005-05-17 Zdenek Dvorak <dvorakz@suse.cz> + * cfgloop.h (just_once_each_iteration_p): Declaration changed. * cfgloopanal.c (just_once_each_iteration_p): Make the loop argument const. diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index be7e0f53dbb..4beb0e74290 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -1261,6 +1261,7 @@ tree_can_merge_blocks_p (basic_block a, basic_block b) { tree stmt; block_stmt_iterator bsi; + tree phi; if (!single_succ_p (a)) return false; @@ -1288,9 +1289,19 @@ tree_can_merge_blocks_p (basic_block a, basic_block b) && DECL_NONLOCAL (LABEL_EXPR_LABEL (stmt))) return false; - /* There may be no PHI nodes at the start of B. */ - if (phi_nodes (b)) - return false; + /* It must be possible to eliminate all phi nodes in B. If ssa form + is not up-to-date, we cannot eliminate any phis. */ + phi = phi_nodes (b); + if (phi) + { + if (need_ssa_update_p ()) + return false; + + for (; phi; phi = PHI_CHAIN (phi)) + if (!is_gimple_reg (PHI_RESULT (phi)) + && !may_propagate_copy (PHI_RESULT (phi), PHI_ARG_DEF (phi, 0))) + return false; + } /* Do not remove user labels. */ for (bsi = bsi_start (b); !bsi_end_p (bsi); bsi_next (&bsi)) @@ -1310,6 +1321,55 @@ tree_can_merge_blocks_p (basic_block a, basic_block b) return true; } +/* Replaces all uses of NAME by VAL. */ + +static void +replace_uses_by (tree name, tree val) +{ + imm_use_iterator imm_iter; + use_operand_p use; + tree stmt; + edge e; + unsigned i; + VEC(tree,heap) *stmts = VEC_alloc (tree, heap, 20); + + FOR_EACH_IMM_USE_SAFE (use, imm_iter, name) + { + stmt = USE_STMT (use); + + SET_USE (use, val); + + if (TREE_CODE (stmt) == PHI_NODE) + { + e = PHI_ARG_EDGE (stmt, PHI_ARG_INDEX_FROM_USE (use)); + if (e->flags & EDGE_ABNORMAL) + { + /* This can only occur for virtual operands, since + for the real ones SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name)) + would prevent replacement. */ + gcc_assert (!is_gimple_reg (name)); + SSA_NAME_OCCURS_IN_ABNORMAL_PHI (val) = 1; + } + } + else + VEC_safe_push (tree, heap, stmts, stmt); + } + + /* We do not update the statements in the loop above. Consider + x = w * w; + + If we performed the update in the first loop, the statement + would be rescanned after first occurence of w is replaced, + the new uses would be placed to the beginning of the list, + and we would never process them. */ + for (i = 0; VEC_iterate (tree, stmts, i, stmt); i++) + { + fold_stmt_inplace (stmt); + update_stmt (stmt); + } + + VEC_free (tree, heap, stmts); +} /* Merge block B into block A. */ @@ -1318,10 +1378,40 @@ tree_merge_blocks (basic_block a, basic_block b) { block_stmt_iterator bsi; tree_stmt_iterator last; + tree phi; if (dump_file) fprintf (dump_file, "Merging blocks %d and %d\n", a->index, b->index); + /* Remove the phi nodes. */ + bsi = bsi_last (a); + for (phi = phi_nodes (b); phi; phi = phi_nodes (b)) + { + tree def = PHI_RESULT (phi), use = PHI_ARG_DEF (phi, 0); + tree copy; + + if (!may_propagate_copy (def, use) + /* Propagating pointers might cause the set of vops for statements + to be changed, and thus require ssa form update. */ + || (is_gimple_reg (def) + && POINTER_TYPE_P (TREE_TYPE (def)))) + { + gcc_assert (is_gimple_reg (def)); + + /* Note that just emiting the copies is fine -- there is no problem + with ordering of phi nodes. This is because A is the single + predecessor of B, therefore results of the phi nodes cannot + appear as arguments of the phi nodes. */ + copy = build2 (MODIFY_EXPR, void_type_node, def, use); + bsi_insert_after (&bsi, copy, BSI_NEW_STMT); + SET_PHI_RESULT (phi, NULL_TREE); + SSA_NAME_DEF_STMT (def) = copy; + } + else + replace_uses_by (def, use); + remove_phi_node (phi, NULL); + } + /* Ensure that B follows A. */ move_block_after (b, a); diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h index 1bf9d87db16..90bef3763f9 100644 --- a/gcc/tree-flow.h +++ b/gcc/tree-flow.h @@ -630,6 +630,7 @@ void set_current_def (tree, tree); /* In tree-ssa-ccp.c */ bool fold_stmt (tree *); +bool fold_stmt_inplace (tree); tree widen_bitfield (tree, tree, tree); /* In tree-vrp.c */ diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c index 85753bdd764..45472f402ab 100644 --- a/gcc/tree-ssa-ccp.c +++ b/gcc/tree-ssa-ccp.c @@ -2308,6 +2308,32 @@ fold_stmt (tree *stmt_p) return changed; } +/* Perform the minimal folding on statement STMT. Only operations like + *&x created by constant propagation are handled. The statement cannot + be replaced with a new one. */ + +bool +fold_stmt_inplace (tree stmt) +{ + tree old_stmt = stmt, rhs, new_rhs; + bool changed = false; + + walk_tree (&stmt, fold_stmt_r, &changed, NULL); + gcc_assert (stmt == old_stmt); + + rhs = get_rhs (stmt); + if (!rhs || rhs == stmt) + return changed; + + new_rhs = fold (rhs); + if (new_rhs == rhs) + return changed; + + changed |= set_rhs (&stmt, new_rhs); + gcc_assert (stmt == old_stmt); + + return changed; +} /* Convert EXPR into a GIMPLE value suitable for substitution on the RHS of an assignment. Insert the necessary statements before diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c index b827494b7dc..692dd705b2f 100644 --- a/gcc/tree-ssa-dom.c +++ b/gcc/tree-ssa-dom.c @@ -404,6 +404,7 @@ tree_ssa_dominator_optimize (void) /* Clean up the CFG so that any forwarder blocks created by loop canonicalization are removed. */ cleanup_tree_cfg (); + calculate_dominance_info (CDI_DOMINATORS); /* If we prove certain blocks are unreachable, then we want to repeat the dominator optimization process as PHI nodes may |