summaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-pre.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-ssa-pre.c')
-rw-r--r--gcc/tree-ssa-pre.c93
1 files changed, 88 insertions, 5 deletions
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index ed326e40303..54770c8eea9 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -2597,6 +2597,7 @@ can_PRE_operation (tree op)
for performing quick dead code elimination of insertions we made
that didn't turn out to be necessary. */
static VEC(gimple,heap) *inserted_exprs;
+static bitmap inserted_phi_names;
/* Pool allocated fake store expressions are placed onto this
worklist, which, after performing dead code elimination, is walked
@@ -3242,6 +3243,8 @@ insert_into_preds_of_block (basic_block block, unsigned int exprnum,
VN_INFO_GET (gimple_phi_result (phi))->valnum = gimple_phi_result (phi);
VN_INFO (gimple_phi_result (phi))->value_id = val;
VEC_safe_push (gimple, heap, inserted_exprs, phi);
+ bitmap_set_bit (inserted_phi_names,
+ SSA_NAME_VERSION (gimple_phi_result (phi)));
FOR_EACH_EDGE (pred, ei, block->preds)
{
pre_expr ae = avail[pred->src->index];
@@ -4129,16 +4132,95 @@ eliminate (void)
}
}
}
+
+ for (gsi = gsi_start_phis (b); !gsi_end_p (gsi);)
+ {
+ gimple stmt, phi = gsi_stmt (gsi);
+ tree sprime = NULL_TREE, res = PHI_RESULT (phi);
+ pre_expr sprimeexpr, resexpr;
+ gimple_stmt_iterator gsi2;
+
+ /* We want to perform redundant PHI elimination. Do so by
+ replacing the PHI with a single copy if possible.
+ Do not touch inserted, single-argument or virtual PHIs. */
+ if (gimple_phi_num_args (phi) == 1
+ || !is_gimple_reg (res)
+ || bitmap_bit_p (inserted_phi_names, SSA_NAME_VERSION (res)))
+ {
+ gsi_next (&gsi);
+ continue;
+ }
+
+ resexpr = get_or_alloc_expr_for_name (res);
+ sprimeexpr = bitmap_find_leader (AVAIL_OUT (b),
+ get_expr_value_id (resexpr), NULL);
+ if (sprimeexpr)
+ {
+ if (sprimeexpr->kind == CONSTANT)
+ sprime = PRE_EXPR_CONSTANT (sprimeexpr);
+ else if (sprimeexpr->kind == NAME)
+ sprime = PRE_EXPR_NAME (sprimeexpr);
+ else
+ gcc_unreachable ();
+ }
+ if (!sprimeexpr
+ || sprime == res)
+ {
+ gsi_next (&gsi);
+ continue;
+ }
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Replaced redundant PHI node defining ");
+ print_generic_expr (dump_file, res, 0);
+ fprintf (dump_file, " with ");
+ print_generic_expr (dump_file, sprime, 0);
+ fprintf (dump_file, "\n");
+ }
+
+ remove_phi_node (&gsi, false);
+
+ stmt = gimple_build_assign (res, sprime);
+ SSA_NAME_DEF_STMT (res) = stmt;
+ if (TREE_CODE (sprime) == SSA_NAME)
+ gimple_set_plf (SSA_NAME_DEF_STMT (sprime),
+ NECESSARY, true);
+ gsi2 = gsi_after_labels (b);
+ gsi_insert_before (&gsi2, stmt, GSI_NEW_STMT);
+ /* Queue the copy for eventual removal. */
+ VEC_safe_push (gimple, heap, to_remove, stmt);
+ pre_stats.eliminations++;
+ }
}
/* We cannot remove stmts during BB walk, especially not release SSA
- names there as this confuses the VN machinery. */
+ names there as this confuses the VN machinery. The stmts ending
+ up in to_remove are either stores or simple copies. */
for (i = 0; VEC_iterate (gimple, to_remove, i, stmt); ++i)
{
- gsi = gsi_for_stmt (stmt);
- unlink_stmt_vdef (stmt);
- gsi_remove (&gsi, true);
- release_defs (stmt);
+ tree lhs = gimple_assign_lhs (stmt);
+ use_operand_p use_p;
+ gimple use_stmt;
+
+ /* If there is a single use only, propagate the equivalency
+ instead of keeping the copy. */
+ if (TREE_CODE (lhs) == SSA_NAME
+ && single_imm_use (lhs, &use_p, &use_stmt))
+ {
+ SET_USE (use_p, gimple_assign_rhs1 (stmt));
+ update_stmt (use_stmt);
+ }
+
+ /* If this is a store or a now unused copy, remove it. */
+ if (TREE_CODE (lhs) != SSA_NAME
+ || has_zero_uses (lhs))
+ {
+ gsi = gsi_for_stmt (stmt);
+ unlink_stmt_vdef (stmt);
+ gsi_remove (&gsi, true);
+ release_defs (stmt);
+ }
}
VEC_free (gimple, heap, to_remove);
@@ -4296,6 +4378,7 @@ init_pre (bool do_fre)
calculate_dominance_info (CDI_DOMINATORS);
bitmap_obstack_initialize (&grand_bitmap_obstack);
+ inserted_phi_names = BITMAP_ALLOC (&grand_bitmap_obstack);
phi_translate_table = htab_create (5110, expr_pred_trans_hash,
expr_pred_trans_eq, free);
expression_to_id = htab_create (num_ssa_names * 3,