aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-threadedge.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-ssa-threadedge.c')
-rw-r--r--gcc/tree-ssa-threadedge.c219
1 files changed, 124 insertions, 95 deletions
diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
index 6ce3264..24ccf01 100644
--- a/gcc/tree-ssa-threadedge.c
+++ b/gcc/tree-ssa-threadedge.c
@@ -61,10 +61,8 @@ set_ssa_name_value (tree name, tree value)
ssa_name_values[SSA_NAME_VERSION (name)] = value;
}
-jump_threader::jump_threader (const_and_copies *copies,
- avail_exprs_stack *avails,
- jump_threader_simplifier *simplifier,
- evrp_range_analyzer *analyzer)
+jump_threader::jump_threader (jump_threader_simplifier *simplifier,
+ jt_state *state)
{
/* Initialize the per SSA_NAME value-handles array. */
gcc_assert (!ssa_name_values.exists ());
@@ -73,11 +71,9 @@ jump_threader::jump_threader (const_and_copies *copies,
dummy_cond = gimple_build_cond (NE_EXPR, integer_zero_node,
integer_zero_node, NULL, NULL);
- m_const_and_copies = copies;
- m_avail_exprs_stack = avails;
m_registry = new jump_thread_path_registry ();
m_simplifier = simplifier;
- m_evrp_range_analyzer = analyzer;
+ m_state = state;
}
jump_threader::~jump_threader (void)
@@ -168,41 +164,7 @@ jump_threader::record_temporary_equivalences_from_phis (edge e)
if (!virtual_operand_p (dst))
stmt_count++;
- m_const_and_copies->record_const_or_copy (dst, src);
-
- /* Also update the value range associated with DST, using
- the range from SRC.
-
- Note that even if SRC is a constant we need to set a suitable
- output range so that VR_UNDEFINED ranges do not leak through. */
- if (m_evrp_range_analyzer)
- {
- /* Get an empty new VR we can pass to update_value_range and save
- away in the VR stack. */
- value_range_equiv *new_vr
- = m_evrp_range_analyzer->allocate_value_range_equiv ();
- new (new_vr) value_range_equiv ();
-
- /* There are three cases to consider:
-
- First if SRC is an SSA_NAME, then we can copy the value
- range from SRC into NEW_VR.
-
- Second if SRC is an INTEGER_CST, then we can just wet
- NEW_VR to a singleton range.
-
- Otherwise set NEW_VR to varying. This may be overly
- conservative. */
- if (TREE_CODE (src) == SSA_NAME)
- new_vr->deep_copy (m_evrp_range_analyzer->get_value_range (src));
- else if (TREE_CODE (src) == INTEGER_CST)
- new_vr->set (src);
- else
- new_vr->set_varying (TREE_TYPE (src));
-
- /* This is a temporary range for DST, so push it. */
- m_evrp_range_analyzer->push_value_range (dst, new_vr);
- }
+ m_state->register_equiv (dst, src, /*update_range=*/true);
}
return true;
}
@@ -304,10 +266,7 @@ jump_threader::record_temporary_equivalences_from_stmts_at_dest (edge e)
return NULL;
}
- /* These are temporary ranges, do nto reflect them back into
- the global range data. */
- if (m_evrp_range_analyzer)
- m_evrp_range_analyzer->record_ranges_from_stmt (stmt, true);
+ m_state->record_ranges_from_stmt (stmt, true);
/* If this is not a statement that sets an SSA_NAME to a new
value, then do not try to simplify this statement as it will
@@ -408,7 +367,7 @@ jump_threader::record_temporary_equivalences_from_stmts_at_dest (edge e)
SET_USE (use_p, tmp);
}
- cached_lhs = m_simplifier->simplify (stmt, stmt, e->src);
+ cached_lhs = m_simplifier->simplify (stmt, stmt, e->src, m_state);
/* Restore the statement's original uses/defs. */
i = 0;
@@ -422,8 +381,7 @@ jump_threader::record_temporary_equivalences_from_stmts_at_dest (edge e)
if (cached_lhs
&& (TREE_CODE (cached_lhs) == SSA_NAME
|| is_gimple_min_invariant (cached_lhs)))
- m_const_and_copies->record_const_or_copy (gimple_get_lhs (stmt),
- cached_lhs);
+ m_state->register_equiv (gimple_get_lhs (stmt), cached_lhs);
}
return stmt;
}
@@ -552,11 +510,12 @@ jump_threader::simplify_control_stmt_condition (edge e, gimple *stmt)
the label that is proven to be taken. */
gswitch *dummy_switch = as_a<gswitch *> (gimple_copy (stmt));
gimple_switch_set_index (dummy_switch, cached_lhs);
- cached_lhs = m_simplifier->simplify (dummy_switch, stmt, e->src);
+ cached_lhs = m_simplifier->simplify (dummy_switch, stmt, e->src,
+ m_state);
ggc_free (dummy_switch);
}
else
- cached_lhs = m_simplifier->simplify (stmt, stmt, e->src);
+ cached_lhs = m_simplifier->simplify (stmt, stmt, e->src, m_state);
}
/* We couldn't find an invariant. But, callers of this
@@ -733,7 +692,7 @@ jump_threader::simplify_control_stmt_condition_1
then use the pass specific callback to simplify the condition. */
if (!res
|| !is_gimple_min_invariant (res))
- res = m_simplifier->simplify (dummy_cond, stmt, e->src);
+ res = m_simplifier->simplify (dummy_cond, stmt, e->src, m_state);
return res;
}
@@ -880,9 +839,7 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src)
If it is threadable, add it to PATH and VISITED and recurse, ultimately
returning TRUE from the toplevel call. Otherwise do nothing and
- return false.
-
- The available expression table is referenced via AVAIL_EXPRS_STACK. */
+ return false. */
bool
jump_threader::thread_around_empty_blocks (vec<jump_thread_edge *> *path,
@@ -997,12 +954,6 @@ jump_threader::thread_around_empty_blocks (vec<jump_thread_edge *> *path,
limited in that case to avoid short-circuiting the loop
incorrectly.
- STACK is used to undo temporary equivalences created during the walk of
- E->dest.
-
- Our caller is responsible for restoring the state of the expression
- and const_and_copies stacks.
-
Positive return value is success. Zero return value is failure, but
the block can still be duplicated as a joiner in a jump thread path,
negative indicates the block should not be duplicated and thus is not
@@ -1012,8 +963,7 @@ int
jump_threader::thread_through_normal_block (vec<jump_thread_edge *> *path,
edge e, bitmap visited)
{
- /* We want to record any equivalences created by traversing E. */
- record_temporary_equivalences (e, m_const_and_copies, m_avail_exprs_stack);
+ m_state->register_equivs_on_edge (e);
/* PHIs create temporary equivalences.
Note that if we found a PHI that made the block non-threadable, then
@@ -1186,10 +1136,7 @@ jump_threader::thread_across_edge (edge e)
{
bitmap visited = BITMAP_ALLOC (NULL);
- m_const_and_copies->push_marker ();
- m_avail_exprs_stack->push_marker ();
- if (m_evrp_range_analyzer)
- m_evrp_range_analyzer->push_marker ();
+ m_state->push (e);
stmt_count = 0;
@@ -1208,10 +1155,7 @@ jump_threader::thread_across_edge (edge e)
{
propagate_threaded_block_debug_into (path->last ()->e->dest,
e->dest);
- m_const_and_copies->pop_to_marker ();
- m_avail_exprs_stack->pop_to_marker ();
- if (m_evrp_range_analyzer)
- m_evrp_range_analyzer->pop_to_marker ();
+ m_state->pop ();
BITMAP_FREE (visited);
m_registry->register_jump_thread (path);
return;
@@ -1234,10 +1178,7 @@ jump_threader::thread_across_edge (edge e)
if (threaded < 0)
{
BITMAP_FREE (visited);
- m_const_and_copies->pop_to_marker ();
- m_avail_exprs_stack->pop_to_marker ();
- if (m_evrp_range_analyzer)
- m_evrp_range_analyzer->pop_to_marker ();
+ m_state->pop ();
return;
}
}
@@ -1263,10 +1204,7 @@ jump_threader::thread_across_edge (edge e)
FOR_EACH_EDGE (taken_edge, ei, e->dest->succs)
if (taken_edge->flags & EDGE_COMPLEX)
{
- m_const_and_copies->pop_to_marker ();
- m_avail_exprs_stack->pop_to_marker ();
- if (m_evrp_range_analyzer)
- m_evrp_range_analyzer->pop_to_marker ();
+ m_state->pop ();
BITMAP_FREE (visited);
return;
}
@@ -1278,12 +1216,7 @@ jump_threader::thread_across_edge (edge e)
|| (taken_edge->flags & EDGE_DFS_BACK) != 0)
continue;
- /* Push a fresh marker so we can unwind the equivalences created
- for each of E->dest's successors. */
- m_const_and_copies->push_marker ();
- m_avail_exprs_stack->push_marker ();
- if (m_evrp_range_analyzer)
- m_evrp_range_analyzer->push_marker ();
+ m_state->push (taken_edge);
/* Avoid threading to any block we have already visited. */
bitmap_clear (visited);
@@ -1320,19 +1253,12 @@ jump_threader::thread_across_edge (edge e)
else
path->release ();
- /* And unwind the equivalence table. */
- if (m_evrp_range_analyzer)
- m_evrp_range_analyzer->pop_to_marker ();
- m_avail_exprs_stack->pop_to_marker ();
- m_const_and_copies->pop_to_marker ();
+ m_state->pop ();
}
BITMAP_FREE (visited);
}
- if (m_evrp_range_analyzer)
- m_evrp_range_analyzer->pop_to_marker ();
- m_const_and_copies->pop_to_marker ();
- m_avail_exprs_stack->pop_to_marker ();
+ m_state->pop ();
}
/* Examine the outgoing edges from BB and conditionally
@@ -1375,10 +1301,113 @@ jump_threader::thread_outgoing_edges (basic_block bb)
}
}
+jt_state::jt_state (const_and_copies *copies,
+ avail_exprs_stack *exprs,
+ evrp_range_analyzer *evrp)
+{
+ m_copies = copies;
+ m_exprs = exprs;
+ m_evrp = evrp;
+}
+
+// Record that E is being crossed.
+
+void
+jt_state::push (edge)
+{
+ m_copies->push_marker ();
+ m_exprs->push_marker ();
+ if (m_evrp)
+ m_evrp->push_marker ();
+}
+
+// Pop to the last pushed state.
+
+void
+jt_state::pop ()
+{
+ m_copies->pop_to_marker ();
+ m_exprs->pop_to_marker ();
+ if (m_evrp)
+ m_evrp->pop_to_marker ();
+}
+
+// Record an equivalence from DST to SRC. If UPDATE_RANGE is TRUE,
+// update the value range associated with DST.
+
+void
+jt_state::register_equiv (tree dst, tree src, bool update_range)
+{
+ m_copies->record_const_or_copy (dst, src);
+
+ /* If requested, update the value range associated with DST, using
+ the range from SRC. */
+ if (m_evrp && update_range)
+ {
+ /* Get new VR we can pass to push_value_range. */
+ value_range_equiv *new_vr = m_evrp->allocate_value_range_equiv ();
+ new (new_vr) value_range_equiv ();
+
+ /* There are three cases to consider:
+
+ First if SRC is an SSA_NAME, then we can copy the value range
+ from SRC into NEW_VR.
+
+ Second if SRC is an INTEGER_CST, then we can just set NEW_VR
+ to a singleton range. Note that even if SRC is a constant we
+ need to set a suitable output range so that VR_UNDEFINED
+ ranges do not leak through.
+
+ Otherwise set NEW_VR to varying. This may be overly
+ conservative. */
+ if (TREE_CODE (src) == SSA_NAME)
+ new_vr->deep_copy (m_evrp->get_value_range (src));
+ else if (TREE_CODE (src) == INTEGER_CST)
+ new_vr->set (src);
+ else
+ new_vr->set_varying (TREE_TYPE (src));
+
+ /* This is a temporary range for DST, so push it. */
+ m_evrp->push_value_range (dst, new_vr);
+ }
+}
+
+// Record any ranges calculated in STMT. If TEMPORARY is TRUE, then
+// this is a temporary equivalence and should be recorded into the
+// unwind table, instead of the global table.
+
+void
+jt_state::record_ranges_from_stmt (gimple *stmt, bool temporary)
+{
+ if (m_evrp)
+ m_evrp->record_ranges_from_stmt (stmt, temporary);
+}
+
+// Record any equivalences created by traversing E.
+
+void
+jt_state::register_equivs_on_edge (edge e)
+{
+ record_temporary_equivalences (e, m_copies, m_exprs);
+}
+
+jump_threader_simplifier::jump_threader_simplifier (vr_values *v)
+{
+ m_vr_values = v;
+}
+
+// Return the singleton that resolves STMT, if it is possible to
+// simplify it.
+//
+// STMT may be a dummy statement, not necessarily in the CFG, in which
+// case WITHIN_STMT can be used to determine the position in the CFG
+// where STMT should be evaluated as being in.
+
tree
jump_threader_simplifier::simplify (gimple *stmt,
gimple *within_stmt,
- basic_block)
+ basic_block,
+ jt_state *)
{
if (gcond *cond_stmt = dyn_cast <gcond *> (stmt))
{