aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/tree-ssa-dom.c21
-rw-r--r--gcc/tree-ssa-threadedge.c219
-rw-r--r--gcc/tree-ssa-threadedge.h39
-rw-r--r--gcc/tree-vrp.c16
4 files changed, 172 insertions, 123 deletions
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index c231e6c..a0df492 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -590,16 +590,18 @@ class dom_jump_threader_simplifier : public jump_threader_simplifier
public:
dom_jump_threader_simplifier (vr_values *v,
avail_exprs_stack *avails)
- : jump_threader_simplifier (v, avails) {}
+ : jump_threader_simplifier (v), m_avail_exprs_stack (avails) { }
private:
- tree simplify (gimple *, gimple *, basic_block);
+ tree simplify (gimple *, gimple *, basic_block, jt_state *) override;
+ avail_exprs_stack *m_avail_exprs_stack;
};
tree
dom_jump_threader_simplifier::simplify (gimple *stmt,
gimple *within_stmt,
- basic_block bb)
+ basic_block bb,
+ jt_state *state)
{
/* First see if the conditional is in the hash table. */
tree cached_lhs = m_avail_exprs_stack->lookup_avail_expr (stmt,
@@ -607,7 +609,7 @@ dom_jump_threader_simplifier::simplify (gimple *stmt,
if (cached_lhs)
return cached_lhs;
- return jump_threader_simplifier::simplify (stmt, within_stmt, bb);
+ return jump_threader_simplifier::simplify (stmt, within_stmt, bb, state);
}
class dom_opt_dom_walker : public dom_walker
@@ -615,12 +617,14 @@ class dom_opt_dom_walker : public dom_walker
public:
dom_opt_dom_walker (cdi_direction direction,
jump_threader *threader,
+ jt_state *state,
evrp_range_analyzer *analyzer,
const_and_copies *const_and_copies,
avail_exprs_stack *avail_exprs_stack)
: dom_walker (direction, REACHABLE_BLOCKS)
{
m_evrp_range_analyzer = analyzer;
+ m_state = state;
m_dummy_cond = gimple_build_cond (NE_EXPR, integer_zero_node,
integer_zero_node, NULL, NULL);
m_const_and_copies = const_and_copies;
@@ -651,6 +655,7 @@ private:
jump_threader *m_threader;
evrp_range_analyzer *m_evrp_range_analyzer;
+ jt_state *m_state;
};
/* Jump threading, redundancy elimination and const/copy propagation.
@@ -748,10 +753,11 @@ pass_dominator::execute (function *fun)
/* Recursively walk the dominator tree optimizing statements. */
evrp_range_analyzer analyzer (true);
dom_jump_threader_simplifier simplifier (&analyzer, avail_exprs_stack);
- jump_threader threader (const_and_copies, avail_exprs_stack,
- &simplifier, &analyzer);
+ jt_state state (const_and_copies, avail_exprs_stack, &analyzer);
+ jump_threader threader (&simplifier, &state);
dom_opt_dom_walker walker (CDI_DOMINATORS,
&threader,
+ &state,
&analyzer,
const_and_copies,
avail_exprs_stack);
@@ -1419,8 +1425,7 @@ dom_opt_dom_walker::before_dom_children (basic_block bb)
continue;
}
- /* Compute range information and optimize the stmt. */
- m_evrp_range_analyzer->record_ranges_from_stmt (gsi_stmt (gsi), false);
+ m_state->record_ranges_from_stmt (gsi_stmt (gsi), false);
bool removed_p = false;
taken_edge = this->optimize_stmt (bb, &gsi, &removed_p);
if (!removed_p)
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))
{
diff --git a/gcc/tree-ssa-threadedge.h b/gcc/tree-ssa-threadedge.h
index 48735f2..c0d3c92 100644
--- a/gcc/tree-ssa-threadedge.h
+++ b/gcc/tree-ssa-threadedge.h
@@ -20,6 +20,27 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_TREE_SSA_THREADEDGE_H
#define GCC_TREE_SSA_THREADEDGE_H
+// Class used to maintain path state in the jump threader and pass it
+// to the jump threader simplifier.
+
+class jt_state
+{
+public:
+ jt_state (class const_and_copies *,
+ class avail_exprs_stack *,
+ class evrp_range_analyzer *);
+ void push (edge);
+ void pop ();
+ void register_equiv (tree dest, tree src, bool update_range = false);
+ void register_equivs_on_edge (edge e);
+ void record_ranges_from_stmt (gimple *stmt, bool temporary);
+
+private:
+ const_and_copies *m_copies;
+ avail_exprs_stack *m_exprs;
+ evrp_range_analyzer *m_evrp;
+};
+
// This is the high level threader. The entry point is
// thread_outgoing_edges(), which calculates and registers paths to be
// threaded. When all candidates have been registered,
@@ -28,10 +49,7 @@ along with GCC; see the file COPYING3. If not see
class jump_threader
{
public:
- jump_threader (class const_and_copies *,
- avail_exprs_stack *,
- class jump_threader_simplifier *,
- class evrp_range_analyzer * = NULL);
+ jump_threader (class jump_threader_simplifier *, class jt_state *);
~jump_threader ();
void thread_outgoing_edges (basic_block);
void remove_jump_threads_including (edge_def *);
@@ -57,11 +75,9 @@ private:
// Dummy condition to avoid creating lots of throw away statements.
gcond *dummy_cond;
- const_and_copies *m_const_and_copies;
- avail_exprs_stack *m_avail_exprs_stack;
class jump_thread_path_registry *m_registry;
jump_threader_simplifier *m_simplifier;
- evrp_range_analyzer *m_evrp_range_analyzer;
+ jt_state *m_state;
};
// Statement simplifier callback for the jump threader.
@@ -69,17 +85,12 @@ private:
class jump_threader_simplifier
{
public:
- jump_threader_simplifier (class vr_values *v,
- avail_exprs_stack *avails)
- : m_vr_values (v),
- m_avail_exprs_stack (avails)
- { }
+ jump_threader_simplifier (class vr_values *v);
virtual ~jump_threader_simplifier () { }
- virtual tree simplify (gimple *, gimple *, basic_block);
+ virtual tree simplify (gimple *, gimple *, basic_block, jt_state *);
protected:
vr_values *m_vr_values;
- avail_exprs_stack *m_avail_exprs_stack;
};
extern void propagate_threaded_block_debug_into (basic_block, basic_block);
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 58111f8..d1b6910 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -4165,16 +4165,18 @@ class vrp_jump_threader_simplifier : public jump_threader_simplifier
{
public:
vrp_jump_threader_simplifier (vr_values *v, avail_exprs_stack *avails)
- : jump_threader_simplifier (v, avails) {}
+ : jump_threader_simplifier (v), m_avail_exprs_stack (avails) { }
private:
- tree simplify (gimple *, gimple *, basic_block) OVERRIDE;
+ tree simplify (gimple *, gimple *, basic_block, jt_state *) OVERRIDE;
+ avail_exprs_stack *m_avail_exprs_stack;
};
tree
vrp_jump_threader_simplifier::simplify (gimple *stmt,
gimple *within_stmt,
- basic_block bb)
+ basic_block bb,
+ jt_state *state)
{
/* First see if the conditional is in the hash table. */
tree cached_lhs = m_avail_exprs_stack->lookup_avail_expr (stmt, false, true);
@@ -4206,7 +4208,7 @@ vrp_jump_threader_simplifier::simplify (gimple *stmt,
return find_case_label_range (switch_stmt, vr);
}
- return jump_threader_simplifier::simplify (stmt, within_stmt, bb);
+ return jump_threader_simplifier::simplify (stmt, within_stmt, bb, state);
}
/* Blocks which have more than one predecessor and more than
@@ -4257,6 +4259,7 @@ private:
hash_table<expr_elt_hasher> *m_avail_exprs;
vrp_jump_threader_simplifier *m_simplifier;
jump_threader *m_threader;
+ jt_state *m_state;
};
vrp_jump_threader::vrp_jump_threader (struct function *fun, vr_values *v)
@@ -4282,11 +4285,11 @@ vrp_jump_threader::vrp_jump_threader (struct function *fun, vr_values *v)
m_vr_values = v;
m_avail_exprs = new hash_table<expr_elt_hasher> (1024);
m_avail_exprs_stack = new avail_exprs_stack (m_avail_exprs);
+ m_state = new jt_state (m_const_and_copies, m_avail_exprs_stack, NULL);
m_simplifier = new vrp_jump_threader_simplifier (m_vr_values,
m_avail_exprs_stack);
- m_threader = new jump_threader (m_const_and_copies, m_avail_exprs_stack,
- m_simplifier);
+ m_threader = new jump_threader (m_simplifier, m_state);
}
vrp_jump_threader::~vrp_jump_threader ()
@@ -4299,6 +4302,7 @@ vrp_jump_threader::~vrp_jump_threader ()
delete m_avail_exprs_stack;
delete m_simplifier;
delete m_threader;
+ delete m_state;
}
/* Called before processing dominator children of BB. We want to look