long num_re;
long num_const_prop;
long num_copy_prop;
+ long num_iterations;
};
static struct opt_stats_d opt_stats;
if (cfg_altered)
free_dominance_info (CDI_DOMINATORS);
- cfg_altered = cleanup_tree_cfg ();
+ /* Only iterate if we threaded jumps AND the CFG cleanup did
+ something interesting. Other cases generate far fewer
+ optimization opportunities and thus are not worth another
+ full DOM iteration. */
+ cfg_altered &= cleanup_tree_cfg ();
if (rediscover_loops_after_threading)
{
if (value && !is_gimple_min_invariant (value))
SSA_NAME_VALUE (name) = NULL;
}
+
+ opt_stats.num_iterations++;
}
while (optimize > 1 && cfg_altered);
statements. This does not prevent threading through E->dest. */
for (bsi = bsi_start (e->dest); ! bsi_end_p (bsi); bsi_next (&bsi))
{
- tree cached_lhs;
+ tree cached_lhs = NULL;
stmt = bsi_stmt (bsi);
else
{
/* Copy the operands. */
- tree *copy;
+ tree *copy, pre_fold_expr;
ssa_op_iter iter;
use_operand_p use_p;
unsigned int num, i = 0;
/* Try to fold/lookup the new expression. Inserting the
expression into the hash table is unlikely to help
- simplify anything later, so just query the hashtable. */
- cached_lhs = fold (TREE_OPERAND (stmt, 1));
- if (TREE_CODE (cached_lhs) != SSA_NAME
- && !is_gimple_min_invariant (cached_lhs))
- cached_lhs = lookup_avail_expr (stmt, false);
+ Sadly, we have to handle conditional assignments specially
+ here, because fold expects all the operands of an expression
+ to be folded before the expression itself is folded, but we
+ can't just substitute the folded condition here. */
+ if (TREE_CODE (TREE_OPERAND (stmt, 1)) == COND_EXPR)
+ {
+ tree cond = COND_EXPR_COND (TREE_OPERAND (stmt, 1));
+ cond = fold (cond);
+ if (cond == boolean_true_node)
+ pre_fold_expr = COND_EXPR_THEN (TREE_OPERAND (stmt, 1));
+ else if (cond == boolean_false_node)
+ pre_fold_expr = COND_EXPR_ELSE (TREE_OPERAND (stmt, 1));
+ else
+ pre_fold_expr = TREE_OPERAND (stmt, 1);
+ }
+ else
+ pre_fold_expr = TREE_OPERAND (stmt, 1);
+ if (pre_fold_expr)
+ {
+ cached_lhs = fold (pre_fold_expr);
+ if (TREE_CODE (cached_lhs) != SSA_NAME
+ && !is_gimple_min_invariant (cached_lhs))
+ cached_lhs = lookup_avail_expr (stmt, false);
+ }
/* Restore the statement's original uses/defs. */
i = 0;
{
struct edge_info *edge_info;
- update_bb_profile_for_threading (e->dest, EDGE_FREQUENCY (e),
- e->count, taken_edge);
if (e->aux)
edge_info = e->aux;
else
}
/* Given an expression EXPR (a relational expression or a statement),
- initialize the hash table element pointed by by ELEMENT. */
+ initialize the hash table element pointed to by ELEMENT. */
static void
initialize_hash_element (tree expr, tree lhs, struct expr_hash_elt *element)
{
tree last;
- /* If we are at a leaf node in the dominator tree, see if we can thread
- the edge from BB through its successor.
-
- Do this before we remove entries from our equivalence tables. */
+ /* If we have an outgoing edge to a block with multiple incoming and
+ outgoing edges, then we may be able to thread the edge. ie, we
+ may be able to statically determine which of the outgoing edges
+ will be traversed when the incoming edge from BB is traversed. */
if (single_succ_p (bb)
&& (single_succ_edge (bb)->flags & EDGE_ABNORMAL) == 0
- && (get_immediate_dominator (CDI_DOMINATORS, single_succ (bb)) != bb
- || phi_nodes (single_succ (bb))))
+ && !single_pred_p (single_succ (bb))
+ && !single_succ_p (single_succ (bb)))
{
thread_across_edge (walk_data, single_succ_edge (bb));
extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
- /* If the THEN arm is the end of a dominator tree or has PHI nodes,
- then try to thread through its edge. */
- if (get_immediate_dominator (CDI_DOMINATORS, true_edge->dest) != bb
- || phi_nodes (true_edge->dest))
+ /* Only try to thread the edge if it reaches a target block with
+ more than one predecessor and more than one successor. */
+ if (!single_pred_p (true_edge->dest) && !single_succ_p (true_edge->dest))
{
struct edge_info *edge_info;
unsigned int i;
}
/* Similarly for the ELSE arm. */
- if (get_immediate_dominator (CDI_DOMINATORS, false_edge->dest) != bb
- || phi_nodes (false_edge->dest))
+ if (!single_pred_p (false_edge->dest) && !single_succ_p (false_edge->dest))
{
struct edge_info *edge_info;
unsigned int i;
fprintf (file, " Copies propagated: %6ld\n",
opt_stats.num_copy_prop);
+ fprintf (file, "\nTotal number of DOM iterations: %6ld\n",
+ opt_stats.num_iterations);
+
fprintf (file, "\nHash table statistics:\n");
fprintf (file, " avail_exprs: ");
}
-/* Optimize the statement pointed by iterator SI.
+/* Optimize the statement pointed to by iterator SI.
We try to perform some simplistic global redundancy elimination and
constant propagation:
NULL_TREE.
Also, when an expression is first inserted in the AVAIL_EXPRS table, it
- is also added to the stack pointed by BLOCK_AVAIL_EXPRS_P, so that they
+ is also added to the stack pointed to by BLOCK_AVAIL_EXPRS_P, so that they
can be removed when we finish processing this block and its children.
NOTE: This function assumes that STMT is a MODIFY_EXPR node that