summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog15
-rw-r--r--gcc/tree-ssa-pre.c188
2 files changed, 51 insertions, 152 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 695cf011845..5df398caea7 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,18 @@
+2017-09-06 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-pre.c (NECESSARY): Remove.
+ (create_expression_by_pieces): Do not touch pass-local flags.
+ (insert_into_preds_of_block): Likewise.
+ (do_pre_regular_insertion): Likewise.
+ (eliminate_insert): Likewise.
+ (eliminate_dom_walker::before_dom_children): Likewise.
+ (fini_eliminate): Do not look at inserted_exprs.
+ (mark_operand_necessary): Remove.
+ (remove_dead_inserted_code): Replace with simple work-list
+ algorithm based on inserted_exprs and SSA uses.
+ (pass_pre::execute): Re-order fini_eliminate and
+ remove_dead_inserted_code.
+
2017-09-06 Olivier Hainque <hainque@adacore.com>
* config/powerpcspe/vxworks.h (VXCPU_FOR_8548): Correct definition
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index f6fa3bbddc0..1ca68d44d22 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -2753,8 +2753,6 @@ find_or_generate_expression (basic_block block, tree op, gimple_seq *stmts)
return NULL_TREE;
}
-#define NECESSARY GF_PLF_1
-
/* Create an expression in pieces, so that we can handle very complex
expressions that may be ANTIC, but not necessary GIMPLE.
BLOCK is the basic block the expression will be inserted into,
@@ -2972,7 +2970,6 @@ create_expression_by_pieces (basic_block block, pre_expr expr,
}
bitmap_set_bit (inserted_exprs, SSA_NAME_VERSION (forcedname));
- gimple_set_plf (stmt, NECESSARY, false);
}
gimple_seq_add_seq (stmts, forced_stmts);
}
@@ -3095,7 +3092,6 @@ insert_into_preds_of_block (basic_block block, unsigned int exprnum,
temp = make_temp_ssa_name (type, NULL, "prephitmp");
phi = create_phi_node (temp, block);
- gimple_set_plf (phi, NECESSARY, false);
VN_INFO_GET (temp)->value_id = val;
VN_INFO (temp)->valnum = sccvn_valnum_from_value_id (val);
if (VN_INFO (temp)->valnum == NULL_TREE)
@@ -3342,7 +3338,6 @@ do_pre_regular_insertion (basic_block block, basic_block dom)
gimple_stmt_iterator gsi = gsi_after_labels (block);
gsi_insert_before (&gsi, assign, GSI_NEW_STMT);
- gimple_set_plf (assign, NECESSARY, false);
VN_INFO_GET (temp)->value_id = val;
VN_INFO (temp)->valnum = sccvn_valnum_from_value_id (val);
if (VN_INFO (temp)->valnum == NULL_TREE)
@@ -4204,9 +4199,6 @@ eliminate_insert (gimple_stmt_iterator *gsi, tree val)
{
gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
VN_INFO_GET (res)->valnum = val;
-
- if (TREE_CODE (leader) == SSA_NAME)
- gimple_set_plf (SSA_NAME_DEF_STMT (leader), NECESSARY, true);
}
pre_stats.insertions++;
@@ -4291,17 +4283,9 @@ eliminate_dom_walker::before_dom_children (basic_block b)
remove_phi_node (&gsi, false);
- if (inserted_exprs
- && !bitmap_bit_p (inserted_exprs, SSA_NAME_VERSION (res))
- && TREE_CODE (sprime) == SSA_NAME)
- gimple_set_plf (SSA_NAME_DEF_STMT (sprime), NECESSARY, true);
-
if (!useless_type_conversion_p (TREE_TYPE (res), TREE_TYPE (sprime)))
sprime = fold_convert (TREE_TYPE (res), sprime);
gimple *stmt = gimple_build_assign (res, sprime);
- /* ??? It cannot yet be necessary (DOM walk). */
- gimple_set_plf (stmt, NECESSARY, gimple_plf (phi, NECESSARY));
-
gimple_stmt_iterator gsi2 = gsi_after_labels (b);
gsi_insert_before (&gsi2, stmt, GSI_NEW_STMT);
continue;
@@ -4478,10 +4462,6 @@ eliminate_dom_walker::before_dom_children (basic_block b)
print_gimple_stmt (dump_file, stmt, 0);
}
- if (TREE_CODE (sprime) == SSA_NAME)
- gimple_set_plf (SSA_NAME_DEF_STMT (sprime),
- NECESSARY, true);
-
pre_stats.eliminations++;
gimple *orig_stmt = stmt;
if (!useless_type_conversion_p (TREE_TYPE (lhs),
@@ -4615,10 +4595,6 @@ eliminate_dom_walker::before_dom_children (basic_block b)
{
propagate_value (use_p, sprime);
modified = true;
- if (TREE_CODE (sprime) == SSA_NAME
- && !is_gimple_debug (stmt))
- gimple_set_plf (SSA_NAME_DEF_STMT (sprime),
- NECESSARY, true);
}
}
@@ -4787,11 +4763,7 @@ eliminate_dom_walker::before_dom_children (basic_block b)
continue;
tree sprime = eliminate_avail (arg);
if (sprime && may_propagate_copy (arg, sprime))
- {
- propagate_value (use_p, sprime);
- if (TREE_CODE (sprime) == SSA_NAME)
- gimple_set_plf (SSA_NAME_DEF_STMT (sprime), NECESSARY, true);
- }
+ propagate_value (use_p, sprime);
}
return NULL;
}
@@ -4853,18 +4825,6 @@ fini_eliminate (void)
{
stmt = el_to_remove.pop ();
- tree lhs;
- if (gimple_code (stmt) == GIMPLE_PHI)
- lhs = gimple_phi_result (stmt);
- else
- lhs = gimple_get_lhs (stmt);
-
- if (inserted_exprs
- && lhs
- && TREE_CODE (lhs) == SSA_NAME
- && bitmap_bit_p (inserted_exprs, SSA_NAME_VERSION (lhs)))
- continue;
-
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Removing dead stmt ");
@@ -4926,36 +4886,9 @@ fini_eliminate (void)
return todo;
}
-/* Borrow a bit of tree-ssa-dce.c for the moment.
- XXX: In 4.1, we should be able to just run a DCE pass after PRE, though
- this may be a bit faster, and we may want critical edges kept split. */
-
-/* If OP's defining statement has not already been determined to be necessary,
- mark that statement necessary. Return the stmt, if it is newly
- necessary. */
-
-static inline gimple *
-mark_operand_necessary (tree op)
-{
- gimple *stmt;
-
- gcc_assert (op);
-
- if (TREE_CODE (op) != SSA_NAME)
- return NULL;
+/* Cheap DCE of a known set of possibly dead stmts.
- stmt = SSA_NAME_DEF_STMT (op);
- gcc_assert (stmt);
-
- if (gimple_plf (stmt, NECESSARY)
- || gimple_nop_p (stmt))
- return NULL;
-
- gimple_set_plf (stmt, NECESSARY, true);
- return stmt;
-}
-
-/* Because we don't follow exactly the standard PRE algorithm, and decide not
+ Because we don't follow exactly the standard PRE algorithm, and decide not
to insert PHI nodes sometimes, and because value numbering of casts isn't
perfect, we sometimes end up inserting dead code. This simple DCE-like
pass removes any insertions we made that weren't actually used. */
@@ -4963,99 +4896,50 @@ mark_operand_necessary (tree op)
static void
remove_dead_inserted_code (void)
{
- unsigned i;
- bitmap_iterator bi;
- gimple *t;
-
- auto_bitmap worklist;
- EXECUTE_IF_SET_IN_BITMAP (inserted_exprs, 0, i, bi)
+ /* ??? Re-use inserted_exprs as worklist not only as initial set.
+ This may end up removing non-inserted code as well. If we
+ keep inserted_exprs unchanged we could restrict new worklist
+ elements to members of inserted_exprs. */
+ bitmap worklist = inserted_exprs;
+ while (! bitmap_empty_p (worklist))
{
- t = SSA_NAME_DEF_STMT (ssa_name (i));
- if (gimple_plf (t, NECESSARY))
- bitmap_set_bit (worklist, i);
- }
- while (!bitmap_empty_p (worklist))
- {
- i = bitmap_first_set_bit (worklist);
+ /* Pop item. */
+ unsigned i = bitmap_first_set_bit (worklist);
bitmap_clear_bit (worklist, i);
- t = SSA_NAME_DEF_STMT (ssa_name (i));
-
- /* PHI nodes are somewhat special in that each PHI alternative has
- data and control dependencies. All the statements feeding the
- PHI node's arguments are always necessary. */
- if (gimple_code (t) == GIMPLE_PHI)
- {
- unsigned k;
- for (k = 0; k < gimple_phi_num_args (t); k++)
- {
- tree arg = PHI_ARG_DEF (t, k);
- if (TREE_CODE (arg) == SSA_NAME)
- {
- gimple *n = mark_operand_necessary (arg);
- if (n)
- bitmap_set_bit (worklist, SSA_NAME_VERSION (arg));
- }
- }
- }
- else
- {
- /* Propagate through the operands. Examine all the USE, VUSE and
- VDEF operands in this statement. Mark all the statements
- which feed this statement's uses as necessary. */
- ssa_op_iter iter;
- tree use;
+ tree def = ssa_name (i);
+ /* Removed by somebody else or still in use. */
+ if (! def || ! has_zero_uses (def))
+ continue;
- /* The operands of VDEF expressions are also needed as they
- represent potential definitions that may reach this
- statement (VDEF operands allow us to follow def-def
- links). */
+ gimple *t = SSA_NAME_DEF_STMT (def);
- FOR_EACH_SSA_TREE_OPERAND (use, t, iter, SSA_OP_ALL_USES)
- {
- gimple *n = mark_operand_necessary (use);
- if (n)
- bitmap_set_bit (worklist, SSA_NAME_VERSION (use));
- }
+ /* Add uses to the worklist. */
+ ssa_op_iter iter;
+ use_operand_p use_p;
+ FOR_EACH_PHI_OR_STMT_USE (use_p, t, iter, SSA_OP_USE)
+ {
+ tree use = USE_FROM_PTR (use_p);
+ if (TREE_CODE (use) == SSA_NAME
+ && ! SSA_NAME_IS_DEFAULT_DEF (use))
+ bitmap_set_bit (worklist, SSA_NAME_VERSION (use));
}
- }
- unsigned int to_clear = -1U;
- EXECUTE_IF_SET_IN_BITMAP (inserted_exprs, 0, i, bi)
- {
- if (to_clear != -1U)
+ /* Remove stmt. */
+ if (dump_file && (dump_flags & TDF_DETAILS))
{
- bitmap_clear_bit (inserted_exprs, to_clear);
- to_clear = -1U;
+ fprintf (dump_file, "Removing unnecessary insertion:");
+ print_gimple_stmt (dump_file, t, 0);
}
- t = SSA_NAME_DEF_STMT (ssa_name (i));
- if (!gimple_plf (t, NECESSARY))
+ gimple_stmt_iterator gsi = gsi_for_stmt (t);
+ if (gimple_code (t) == GIMPLE_PHI)
+ remove_phi_node (&gsi, true);
+ else
{
- gimple_stmt_iterator gsi;
-
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "Removing unnecessary insertion:");
- print_gimple_stmt (dump_file, t, 0);
- }
-
- gsi = gsi_for_stmt (t);
- if (gimple_code (t) == GIMPLE_PHI)
- remove_phi_node (&gsi, true);
- else
- {
- gsi_remove (&gsi, true);
- release_defs (t);
- }
+ gsi_remove (&gsi, true);
+ release_defs (t);
}
- else
- /* eliminate_fini will skip stmts marked for removal if we
- already removed it and uses inserted_exprs for this, so
- clear those we didn't end up removing. */
- to_clear = i;
}
- if (to_clear != -1U)
- bitmap_clear_bit (inserted_exprs, to_clear);
}
@@ -5196,10 +5080,10 @@ pass_pre::execute (function *fun)
statistics_counter_event (fun, "Eliminated", pre_stats.eliminations);
clear_expression_ids ();
- remove_dead_inserted_code ();
scev_finalize ();
todo |= fini_eliminate ();
+ remove_dead_inserted_code ();
fini_pre ();
loop_optimizer_finalize ();