aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-dom.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-ssa-dom.c')
-rw-r--r--gcc/tree-ssa-dom.c151
1 files changed, 131 insertions, 20 deletions
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index 49d8f96..a8a5b34 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -585,31 +585,137 @@ record_edge_info (basic_block bb)
}
}
-class dom_jump_threader_simplifier : public jump_threader_simplifier
+class dom_jt_state : public jt_state
{
public:
- dom_jump_threader_simplifier (vr_values *v,
- avail_exprs_stack *avails)
- : jump_threader_simplifier (v), m_avail_exprs_stack (avails) { }
+ dom_jt_state (const_and_copies *copies, avail_exprs_stack *avails,
+ evrp_range_analyzer *evrp)
+ : m_copies (copies), m_avails (avails), m_evrp (evrp)
+ {
+ }
+ void push (edge e) override
+ {
+ m_copies->push_marker ();
+ m_avails->push_marker ();
+ m_evrp->push_marker ();
+ jt_state::push (e);
+ }
+ void pop () override
+ {
+ m_copies->pop_to_marker ();
+ m_avails->pop_to_marker ();
+ m_evrp->pop_to_marker ();
+ jt_state::pop ();
+ }
+ void register_equivs_edge (edge e) override
+ {
+ record_temporary_equivalences (e, m_copies, m_avails);
+ }
+ void record_ranges_from_stmt (gimple *stmt, bool temporary) override
+ {
+ m_evrp->record_ranges_from_stmt (stmt, temporary);
+ }
+ void register_equiv (tree dest, tree src, bool update) override;
+private:
+ const_and_copies *m_copies;
+ avail_exprs_stack *m_avails;
+ evrp_range_analyzer *m_evrp;
+};
+
+void
+dom_jt_state::register_equiv (tree dest, tree src, bool update)
+{
+ m_copies->record_const_or_copy (dest, src);
+
+ /* If requested, update the value range associated with DST, using
+ the range from SRC. */
+ if (update)
+ {
+ /* 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 (dest, new_vr);
+ }
+}
+
+class dom_jt_simplifier : public jt_simplifier
+{
+public:
+ dom_jt_simplifier (vr_values *v, avail_exprs_stack *avails)
+ : m_vr_values (v), m_avails (avails) { }
private:
tree simplify (gimple *, gimple *, basic_block, jt_state *) override;
- avail_exprs_stack *m_avail_exprs_stack;
+ vr_values *m_vr_values;
+ avail_exprs_stack *m_avails;
};
tree
-dom_jump_threader_simplifier::simplify (gimple *stmt,
- gimple *within_stmt,
- basic_block bb,
- jt_state *state)
+dom_jt_simplifier::simplify (gimple *stmt, gimple *within_stmt,
+ basic_block, jt_state *)
{
/* First see if the conditional is in the hash table. */
- tree cached_lhs = m_avail_exprs_stack->lookup_avail_expr (stmt,
- false, true);
+ tree cached_lhs = m_avails->lookup_avail_expr (stmt, false, true);
if (cached_lhs)
return cached_lhs;
- return jump_threader_simplifier::simplify (stmt, within_stmt, bb, state);
+ if (gcond *cond_stmt = dyn_cast <gcond *> (stmt))
+ {
+ simplify_using_ranges simplifier (m_vr_values);
+ return simplifier.vrp_evaluate_conditional (gimple_cond_code (cond_stmt),
+ gimple_cond_lhs (cond_stmt),
+ gimple_cond_rhs (cond_stmt),
+ within_stmt);
+ }
+ if (gswitch *switch_stmt = dyn_cast <gswitch *> (stmt))
+ {
+ tree op = gimple_switch_index (switch_stmt);
+ if (TREE_CODE (op) != SSA_NAME)
+ return NULL_TREE;
+
+ const value_range_equiv *vr = m_vr_values->get_value_range (op);
+ return find_case_label_range (switch_stmt, vr);
+ }
+ if (gassign *assign_stmt = dyn_cast <gassign *> (stmt))
+ {
+ tree lhs = gimple_assign_lhs (assign_stmt);
+ if (TREE_CODE (lhs) == SSA_NAME
+ && (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
+ || POINTER_TYPE_P (TREE_TYPE (lhs)))
+ && stmt_interesting_for_vrp (stmt))
+ {
+ edge dummy_e;
+ tree dummy_tree;
+ value_range_equiv new_vr;
+ m_vr_values->extract_range_from_stmt (stmt, &dummy_e, &dummy_tree,
+ &new_vr);
+ tree singleton;
+ if (new_vr.singleton_p (&singleton))
+ return singleton;
+ }
+ }
+ return NULL;
}
class dom_opt_dom_walker : public dom_walker
@@ -752,8 +858,8 @@ 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);
- jt_state state (const_and_copies, avail_exprs_stack, &analyzer);
+ dom_jt_simplifier simplifier (&analyzer, avail_exprs_stack);
+ dom_jt_state state (const_and_copies, avail_exprs_stack, &analyzer);
jump_threader threader (&simplifier, &state);
dom_opt_dom_walker walker (CDI_DOMINATORS,
&threader,
@@ -1704,7 +1810,7 @@ record_equivalences_from_stmt (gimple *stmt, int may_optimize_p,
CONST_AND_COPIES. */
static void
-cprop_operand (gimple *stmt, use_operand_p op_p, vr_values *vr_values)
+cprop_operand (gimple *stmt, use_operand_p op_p, range_query *query)
{
tree val;
tree op = USE_FROM_PTR (op_p);
@@ -1714,7 +1820,12 @@ cprop_operand (gimple *stmt, use_operand_p op_p, vr_values *vr_values)
CONST_AND_COPIES. */
val = SSA_NAME_VALUE (op);
if (!val)
- val = vr_values->op_with_constant_singleton_value_range (op);
+ {
+ value_range r;
+ tree single;
+ if (query->range_of_expr (r, op, stmt) && r.singleton_p (&single))
+ val = single;
+ }
if (val && val != op)
{
@@ -1772,7 +1883,7 @@ cprop_operand (gimple *stmt, use_operand_p op_p, vr_values *vr_values)
vdef_ops of STMT. */
static void
-cprop_into_stmt (gimple *stmt, vr_values *vr_values)
+cprop_into_stmt (gimple *stmt, range_query *query)
{
use_operand_p op_p;
ssa_op_iter iter;
@@ -1789,7 +1900,7 @@ cprop_into_stmt (gimple *stmt, vr_values *vr_values)
operands. */
if (old_op != last_copy_propagated_op)
{
- cprop_operand (stmt, op_p, vr_values);
+ cprop_operand (stmt, op_p, query);
tree new_op = USE_FROM_PTR (op_p);
if (new_op != old_op && TREE_CODE (new_op) == SSA_NAME)
@@ -2097,8 +2208,8 @@ dom_opt_dom_walker::optimize_stmt (basic_block bb, gimple_stmt_iterator *si,
SSA_NAMES. */
update_stmt_if_modified (stmt);
edge taken_edge = NULL;
- m_evrp_range_analyzer->vrp_visit_cond_stmt
- (as_a <gcond *> (stmt), &taken_edge);
+ simplify_using_ranges simpl (m_evrp_range_analyzer);
+ simpl.vrp_visit_cond_stmt (as_a <gcond *> (stmt), &taken_edge);
if (taken_edge)
{
if (taken_edge->flags & EDGE_TRUE_VALUE)