mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-03 04:25:26 +08:00
Convert vr-values to value query class.
gcc/ChangeLog: * gimple-loop-versioning.cc (lv_dom_walker::before_dom_children): Pass m_range_analyzer instead of get_vr_values. (loop_versioning::name_prop::get_value): Rename to... (loop_versioning::name_prop::value_of_expr): ...this. * gimple-ssa-evrp-analyze.c (evrp_range_analyzer::evrp_range_analyzer): Adjust for evrp_range_analyzer inheriting from vr_values. (evrp_range_analyzer::try_find_new_range): Same. (evrp_range_analyzer::record_ranges_from_incoming_edge): Same. (evrp_range_analyzer::record_ranges_from_phis): Same. (evrp_range_analyzer::record_ranges_from_stmt): Same. (evrp_range_analyzer::push_value_range): Same. (evrp_range_analyzer::pop_value_range): Same. * gimple-ssa-evrp-analyze.h (class evrp_range_analyzer): Inherit from vr_values. Adjust accordingly. * gimple-ssa-evrp.c: Adjust for evrp_range_analyzer inheriting from vr_values. (evrp_folder::value_of_evrp): Rename from get_value. * tree-ssa-ccp.c (class ccp_folder): Rename get_value to value_of_expr. (ccp_folder::get_value): Rename to... (ccp_folder::value_of_expr): ...this. * tree-ssa-copy.c (class copy_folder): Rename get_value to value_of_expr. (copy_folder::get_value): Rename to... (copy_folder::value_of_expr): ...this. * tree-ssa-dom.c (dom_opt_dom_walker::after_dom_children): Adjust for evrp_range_analyzer inheriting from vr_values. (dom_opt_dom_walker::optimize_stmt): Same. * tree-ssa-propagate.c (substitute_and_fold_engine::replace_uses_in): Call value_of_* instead of get_value. (substitute_and_fold_engine::replace_phi_args_in): Same. (substitute_and_fold_engine::propagate_into_phi_args): Same. (substitute_and_fold_dom_walker::before_dom_children): Same. * tree-ssa-propagate.h: Include value-query.h. (class substitute_and_fold_engine): Inherit from value_query. * tree-ssa-strlen.c (strlen_dom_walker::before_dom_children): Adjust for evrp_range_analyzer inheriting from vr_values. * tree-ssa-threadedge.c (record_temporary_equivalences_from_phis): Same. * tree-vrp.c (class vrp_folder): Same. (vrp_folder::get_value): Rename to value_of_expr. * vr-values.c (vr_values::get_lattice_entry): Adjust for vr_values inheriting from range_query. (vr_values::range_of_expr): New. (vr_values::value_of_expr): New. (vr_values::value_on_edge): New. (vr_values::value_of_stmt): New. (simplify_using_ranges::op_with_boolean_value_range_p): Call get_value_range through query. (check_for_binary_op_overflow): Rename store to query. (vr_values::vr_values): Remove vrp_value_range_pool. (vr_values::~vr_values): Same. (simplify_using_ranges::get_vr_for_comparison): Call get_value_range through query. (simplify_using_ranges::compare_names): Same. (simplify_using_ranges::vrp_evaluate_conditional): Same. (simplify_using_ranges::vrp_visit_cond_stmt): Same. (simplify_using_ranges::simplify_abs_using_ranges): Same. (simplify_using_ranges::simplify_cond_using_ranges_1): Same. (simplify_cond_using_ranges_2): Same. (simplify_using_ranges::simplify_switch_using_ranges): Same. (simplify_using_ranges::two_valued_val_range_p): Same. (simplify_using_ranges::simplify_using_ranges): Rename store to query. (simplify_using_ranges::simplify): Assert that we have a query. * vr-values.h (class range_query): Remove. (class simplify_using_ranges): Remove inheritance of range_query. (class vr_values): Add virtuals for range_of_expr, value_of_expr, value_on_edge, value_of_stmt, and get_value_range. Call range_query allocator instead of using vrp_value_range_pool. Remove vrp_value_range_pool. (simplify_using_ranges::get_value_range): Remove.
This commit is contained in:
parent
04b99da898
commit
a889e06ac6
@ -277,7 +277,7 @@ private:
|
||||
{
|
||||
public:
|
||||
name_prop (loop_info &li) : m_li (li) {}
|
||||
tree get_value (tree, gimple *) FINAL OVERRIDE;
|
||||
tree value_of_expr (tree name, gimple *) FINAL OVERRIDE;
|
||||
|
||||
private:
|
||||
/* Information about the versioning we've performed on the loop. */
|
||||
@ -512,8 +512,7 @@ loop_versioning::lv_dom_walker::before_dom_children (basic_block bb)
|
||||
m_range_analyzer.enter (bb);
|
||||
|
||||
if (bb == bb->loop_father->header)
|
||||
m_lv.prune_loop_conditions (bb->loop_father,
|
||||
m_range_analyzer.get_vr_values ());
|
||||
m_lv.prune_loop_conditions (bb->loop_father, &m_range_analyzer);
|
||||
|
||||
for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si);
|
||||
gsi_next (&si))
|
||||
@ -534,8 +533,7 @@ loop_versioning::lv_dom_walker::after_dom_children (basic_block bb)
|
||||
Return the new value if so, otherwise return null. */
|
||||
|
||||
tree
|
||||
loop_versioning::name_prop::get_value (tree val,
|
||||
gimple *stmt ATTRIBUTE_UNUSED)
|
||||
loop_versioning::name_prop::value_of_expr (tree val, gimple *)
|
||||
{
|
||||
if (TREE_CODE (val) == SSA_NAME
|
||||
&& bitmap_bit_p (&m_li.unity_names, SSA_NAME_VERSION (val)))
|
||||
|
@ -54,7 +54,6 @@ evrp_range_analyzer::evrp_range_analyzer (bool update_global_ranges)
|
||||
FOR_EACH_EDGE (e, ei, bb->preds)
|
||||
e->flags |= EDGE_EXECUTABLE;
|
||||
}
|
||||
vr_values = new class vr_values;
|
||||
}
|
||||
|
||||
/* Push an unwinding marker onto the unwinding stack. */
|
||||
@ -87,15 +86,14 @@ evrp_range_analyzer::try_find_new_range (tree name,
|
||||
const value_range_equiv *old_vr = get_value_range (name);
|
||||
|
||||
/* Discover VR when condition is true. */
|
||||
vr_values->extract_range_for_var_from_comparison_expr (name, code, op,
|
||||
limit, &vr);
|
||||
extract_range_for_var_from_comparison_expr (name, code, op, limit, &vr);
|
||||
/* If we found any usable VR, set the VR to ssa_name and create a
|
||||
PUSH old value in the stack with the old VR. */
|
||||
if (!vr.undefined_p () && !vr.varying_p ())
|
||||
{
|
||||
if (old_vr->equal_p (vr, /*ignore_equivs=*/true))
|
||||
return NULL;
|
||||
value_range_equiv *new_vr = vr_values->allocate_value_range_equiv ();
|
||||
value_range_equiv *new_vr = allocate_value_range_equiv ();
|
||||
new_vr->move (&vr);
|
||||
return new_vr;
|
||||
}
|
||||
@ -214,7 +212,7 @@ evrp_range_analyzer::record_ranges_from_incoming_edge (basic_block bb)
|
||||
tem.intersect (vrs[i].second);
|
||||
if (tem.equal_p (*old_vr))
|
||||
{
|
||||
vr_values->free_value_range (vrs[i].second);
|
||||
free_value_range (vrs[i].second);
|
||||
continue;
|
||||
}
|
||||
push_value_range (vrs[i].first, vrs[i].second);
|
||||
@ -261,7 +259,7 @@ evrp_range_analyzer::record_ranges_from_phis (basic_block bb)
|
||||
value_range_equiv vr_result;
|
||||
bool interesting = stmt_interesting_for_vrp (phi);
|
||||
if (!has_unvisited_preds && interesting)
|
||||
vr_values->extract_range_from_phi_node (phi, &vr_result);
|
||||
extract_range_from_phi_node (phi, &vr_result);
|
||||
else
|
||||
{
|
||||
vr_result.set_varying (TREE_TYPE (lhs));
|
||||
@ -274,9 +272,9 @@ evrp_range_analyzer::record_ranges_from_phis (basic_block bb)
|
||||
&& interesting
|
||||
&& (l = loop_containing_stmt (phi))
|
||||
&& l->header == gimple_bb (phi))
|
||||
vr_values->adjust_range_with_scev (&vr_result, l, phi, lhs);
|
||||
adjust_range_with_scev (&vr_result, l, phi, lhs);
|
||||
}
|
||||
vr_values->update_value_range (lhs, &vr_result);
|
||||
update_value_range (lhs, &vr_result);
|
||||
|
||||
/* Set the SSA with the value range. */
|
||||
if (m_update_global_ranges)
|
||||
@ -303,7 +301,7 @@ evrp_range_analyzer::record_ranges_from_stmt (gimple *stmt, bool temporary)
|
||||
{
|
||||
edge taken_edge;
|
||||
value_range_equiv vr;
|
||||
vr_values->extract_range_from_stmt (stmt, &taken_edge, &output, &vr);
|
||||
extract_range_from_stmt (stmt, &taken_edge, &output, &vr);
|
||||
if (output)
|
||||
{
|
||||
/* Set the SSA with the value range. There are two cases to
|
||||
@ -321,7 +319,7 @@ evrp_range_analyzer::record_ranges_from_stmt (gimple *stmt, bool temporary)
|
||||
{
|
||||
/* Case one. We can just update the underlying range
|
||||
information as well as the global information. */
|
||||
vr_values->update_value_range (output, &vr);
|
||||
update_value_range (output, &vr);
|
||||
if (m_update_global_ranges)
|
||||
set_ssa_range_info (output, &vr);
|
||||
}
|
||||
@ -332,18 +330,17 @@ evrp_range_analyzer::record_ranges_from_stmt (gimple *stmt, bool temporary)
|
||||
a new range and push the old range onto the stack. We
|
||||
also have to be very careful about sharing the underlying
|
||||
bitmaps. Ugh. */
|
||||
value_range_equiv *new_vr
|
||||
= vr_values->allocate_value_range_equiv ();
|
||||
value_range_equiv *new_vr = allocate_value_range_equiv ();
|
||||
new_vr->set (vr.min (), vr.max (), NULL, vr.kind ());
|
||||
vr.equiv_clear ();
|
||||
push_value_range (output, new_vr);
|
||||
}
|
||||
}
|
||||
else
|
||||
vr_values->set_defs_to_varying (stmt);
|
||||
set_defs_to_varying (stmt);
|
||||
}
|
||||
else
|
||||
vr_values->set_defs_to_varying (stmt);
|
||||
set_defs_to_varying (stmt);
|
||||
|
||||
/* See if we can derive a range for any of STMT's operands. */
|
||||
tree op;
|
||||
@ -429,7 +426,7 @@ evrp_range_analyzer::push_value_range (tree var, value_range_equiv *vr)
|
||||
dump_value_range (dump_file, vr);
|
||||
fprintf (dump_file, "\n");
|
||||
}
|
||||
value_range_equiv *old_vr = vr_values->swap_vr_value (var, vr);
|
||||
value_range_equiv *old_vr = swap_vr_value (var, vr);
|
||||
stack.safe_push (std::make_pair (var, old_vr));
|
||||
}
|
||||
|
||||
@ -451,7 +448,7 @@ evrp_range_analyzer::pop_value_range ()
|
||||
}
|
||||
/* We saved off a lattice entry, now give it back and release
|
||||
the one we popped. */
|
||||
value_range_equiv *popped_vr = vr_values->swap_vr_value (var, vr);
|
||||
value_range_equiv *popped_vr = swap_vr_value (var, vr);
|
||||
if (popped_vr)
|
||||
vr_values->free_value_range (popped_vr);
|
||||
free_value_range (popped_vr);
|
||||
}
|
||||
|
@ -20,13 +20,12 @@ along with GCC; see the file COPYING3. If not see
|
||||
#ifndef GCC_GIMPLE_SSA_EVRP_ANALYZE_H
|
||||
#define GCC_GIMPLE_SSA_EVRP_ANALYZE_H
|
||||
|
||||
class evrp_range_analyzer
|
||||
class evrp_range_analyzer : public vr_values
|
||||
{
|
||||
public:
|
||||
evrp_range_analyzer (bool update_global_ranges);
|
||||
~evrp_range_analyzer (void)
|
||||
{
|
||||
delete vr_values;
|
||||
stack.release ();
|
||||
}
|
||||
|
||||
@ -36,34 +35,18 @@ class evrp_range_analyzer
|
||||
void leave (basic_block);
|
||||
void record_ranges_from_stmt (gimple *, bool);
|
||||
|
||||
/* Main interface to retrieve range information. */
|
||||
const value_range_equiv *get_value_range (const_tree op)
|
||||
{ return vr_values->get_value_range (op); }
|
||||
|
||||
/* Record a new unwindable range. */
|
||||
void push_value_range (tree var, value_range_equiv *vr);
|
||||
|
||||
/* Dump all the current value ranges. This is primarily
|
||||
a debugging interface. */
|
||||
void dump_all_value_ranges (FILE *fp)
|
||||
{ vr_values->dump_all_value_ranges (fp); }
|
||||
|
||||
/* A bit of a wart. This should ideally go away. */
|
||||
void vrp_visit_cond_stmt (gcond *cond, edge *e)
|
||||
{
|
||||
simplify_using_ranges simpl (vr_values);
|
||||
simplify_using_ranges simpl (this);
|
||||
simpl.vrp_visit_cond_stmt (cond, e);
|
||||
}
|
||||
|
||||
/* Get the underlying vr_values class instance. If TRANSFER is
|
||||
true, then we are transferring ownership. Else we keep ownership.
|
||||
|
||||
This should be converted to a unique_ptr. */
|
||||
class vr_values *get_vr_values (void) { return vr_values; }
|
||||
|
||||
private:
|
||||
DISABLE_COPY_AND_ASSIGN (evrp_range_analyzer);
|
||||
class vr_values *vr_values;
|
||||
|
||||
void pop_value_range ();
|
||||
value_range_equiv *try_find_new_range (tree, tree op, tree_code code,
|
||||
|
@ -45,11 +45,11 @@ along with GCC; see the file COPYING3. If not see
|
||||
class evrp_folder : public substitute_and_fold_engine
|
||||
{
|
||||
public:
|
||||
evrp_folder () : m_range_analyzer (/*update_global_ranges=*/true),
|
||||
m_vr_values (m_range_analyzer.get_vr_values ()),
|
||||
simplifier (m_vr_values)
|
||||
{
|
||||
}
|
||||
evrp_folder () :
|
||||
substitute_and_fold_engine (),
|
||||
m_range_analyzer (/*update_global_ranges=*/true),
|
||||
simplifier (&m_range_analyzer)
|
||||
{ }
|
||||
|
||||
~evrp_folder ()
|
||||
{
|
||||
@ -61,9 +61,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
tree get_value (tree op, gimple *stmt ATTRIBUTE_UNUSED) OVERRIDE
|
||||
tree value_of_expr (tree name, gimple *stmt) OVERRIDE
|
||||
{
|
||||
return m_vr_values->op_with_constant_singleton_value_range (op);
|
||||
return m_range_analyzer.value_of_expr (name, stmt);
|
||||
}
|
||||
|
||||
void pre_fold_bb (basic_block bb) OVERRIDE
|
||||
@ -95,14 +95,12 @@ public:
|
||||
|
||||
void post_new_stmt (gimple *stmt) OVERRIDE
|
||||
{
|
||||
m_range_analyzer.get_vr_values ()->set_defs_to_varying (stmt);
|
||||
m_range_analyzer.set_defs_to_varying (stmt);
|
||||
}
|
||||
|
||||
private:
|
||||
DISABLE_COPY_AND_ASSIGN (evrp_folder);
|
||||
class evrp_range_analyzer m_range_analyzer;
|
||||
class vr_values *m_vr_values;
|
||||
|
||||
evrp_range_analyzer m_range_analyzer;
|
||||
simplify_using_ranges simplifier;
|
||||
};
|
||||
|
||||
|
@ -946,7 +946,7 @@ do_dbg_cnt (void)
|
||||
class ccp_folder : public substitute_and_fold_engine
|
||||
{
|
||||
public:
|
||||
tree get_value (tree, gimple *) FINAL OVERRIDE;
|
||||
tree value_of_expr (tree, gimple *) FINAL OVERRIDE;
|
||||
bool fold_stmt (gimple_stmt_iterator *) FINAL OVERRIDE;
|
||||
};
|
||||
|
||||
@ -955,7 +955,7 @@ class ccp_folder : public substitute_and_fold_engine
|
||||
of calling member functions. */
|
||||
|
||||
tree
|
||||
ccp_folder::get_value (tree op, gimple *stmt ATTRIBUTE_UNUSED)
|
||||
ccp_folder::value_of_expr (tree op, gimple *)
|
||||
{
|
||||
return get_constant_value (op);
|
||||
}
|
||||
|
@ -492,13 +492,13 @@ init_copy_prop (void)
|
||||
class copy_folder : public substitute_and_fold_engine
|
||||
{
|
||||
public:
|
||||
tree get_value (tree, gimple *) FINAL OVERRIDE;
|
||||
tree value_of_expr (tree name, gimple *) FINAL OVERRIDE;
|
||||
};
|
||||
|
||||
/* Callback for substitute_and_fold to get at the final copy-of values. */
|
||||
|
||||
tree
|
||||
copy_folder::get_value (tree name, gimple *stmt ATTRIBUTE_UNUSED)
|
||||
copy_folder::value_of_expr (tree name, gimple *)
|
||||
{
|
||||
tree val;
|
||||
if (SSA_NAME_VERSION (name) >= n_copy_of)
|
||||
|
@ -1500,7 +1500,7 @@ dom_opt_dom_walker::before_dom_children (basic_block bb)
|
||||
void
|
||||
dom_opt_dom_walker::after_dom_children (basic_block bb)
|
||||
{
|
||||
x_vr_values = evrp_range_analyzer.get_vr_values ();
|
||||
x_vr_values = &evrp_range_analyzer;
|
||||
thread_outgoing_edges (bb, m_dummy_cond, m_const_and_copies,
|
||||
m_avail_exprs_stack,
|
||||
&evrp_range_analyzer,
|
||||
@ -1970,7 +1970,7 @@ dom_opt_dom_walker::optimize_stmt (basic_block bb, gimple_stmt_iterator *si,
|
||||
opt_stats.num_stmts++;
|
||||
|
||||
/* Const/copy propagate into USES, VUSES and the RHS of VDEFs. */
|
||||
cprop_into_stmt (stmt, evrp_range_analyzer.get_vr_values ());
|
||||
cprop_into_stmt (stmt, &evrp_range_analyzer);
|
||||
|
||||
/* If the statement has been modified with constant replacements,
|
||||
fold its RHS before checking for redundant computations. */
|
||||
|
@ -868,7 +868,7 @@ substitute_and_fold_engine::replace_uses_in (gimple *stmt)
|
||||
FOR_EACH_SSA_USE_OPERAND (use, stmt, iter, SSA_OP_USE)
|
||||
{
|
||||
tree tuse = USE_FROM_PTR (use);
|
||||
tree val = get_value (tuse, stmt);
|
||||
tree val = value_of_expr (tuse, stmt);
|
||||
|
||||
if (val == tuse || val == NULL_TREE)
|
||||
continue;
|
||||
@ -909,12 +909,11 @@ substitute_and_fold_engine::replace_phi_args_in (gphi *phi)
|
||||
|
||||
if (TREE_CODE (arg) == SSA_NAME)
|
||||
{
|
||||
tree val = get_value (arg, phi);
|
||||
edge e = gimple_phi_arg_edge (phi, i);
|
||||
tree val = value_on_edge (e, arg);
|
||||
|
||||
if (val && val != arg && may_propagate_copy (arg, val))
|
||||
{
|
||||
edge e = gimple_phi_arg_edge (phi, i);
|
||||
|
||||
if (TREE_CODE (val) != SSA_NAME)
|
||||
prop_stats.num_const_prop++;
|
||||
else
|
||||
@ -1036,7 +1035,7 @@ substitute_and_fold_engine::propagate_into_phi_args (basic_block bb)
|
||||
if (TREE_CODE (arg) != SSA_NAME
|
||||
|| virtual_operand_p (arg))
|
||||
continue;
|
||||
tree val = get_value (arg, phi);
|
||||
tree val = value_on_edge (e, arg);
|
||||
if (val
|
||||
&& is_gimple_min_invariant (val)
|
||||
&& may_propagate_copy (arg, val))
|
||||
@ -1070,7 +1069,7 @@ substitute_and_fold_dom_walker::before_dom_children (basic_block bb)
|
||||
}
|
||||
if (res && TREE_CODE (res) == SSA_NAME)
|
||||
{
|
||||
tree sprime = substitute_and_fold_engine->get_value (res, phi);
|
||||
tree sprime = substitute_and_fold_engine->value_of_expr (res, phi);
|
||||
if (sprime
|
||||
&& sprime != res
|
||||
&& may_propagate_copy (res, sprime))
|
||||
@ -1110,7 +1109,7 @@ substitute_and_fold_dom_walker::before_dom_children (basic_block bb)
|
||||
tree lhs = gimple_get_lhs (stmt);
|
||||
if (lhs && TREE_CODE (lhs) == SSA_NAME)
|
||||
{
|
||||
tree sprime = substitute_and_fold_engine->get_value (lhs, stmt);
|
||||
tree sprime = substitute_and_fold_engine->value_of_expr (lhs, stmt);
|
||||
if (sprime
|
||||
&& sprime != lhs
|
||||
&& may_propagate_copy (lhs, sprime)
|
||||
|
@ -22,6 +22,8 @@ along with GCC; see the file COPYING3. If not see
|
||||
#ifndef _TREE_SSA_PROPAGATE_H
|
||||
#define _TREE_SSA_PROPAGATE_H 1
|
||||
|
||||
#include "value-query.h"
|
||||
|
||||
/* If SIM_P is true, statement S will be simulated again. */
|
||||
|
||||
static inline void
|
||||
@ -97,14 +99,13 @@ class ssa_propagation_engine
|
||||
void simulate_block (basic_block);
|
||||
};
|
||||
|
||||
class substitute_and_fold_engine
|
||||
class substitute_and_fold_engine : public value_query
|
||||
{
|
||||
public:
|
||||
substitute_and_fold_engine (bool fold_all_stmts = false)
|
||||
: fold_all_stmts (fold_all_stmts) { }
|
||||
virtual ~substitute_and_fold_engine (void) { }
|
||||
virtual bool fold_stmt (gimple_stmt_iterator *) { return false; }
|
||||
virtual tree get_value (tree, gimple *) { return NULL_TREE; }
|
||||
|
||||
bool substitute_and_fold (basic_block = NULL);
|
||||
bool replace_uses_in (gimple *);
|
||||
|
@ -5860,7 +5860,7 @@ strlen_dom_walker::before_dom_children (basic_block bb)
|
||||
can be used by printf argument processing. */
|
||||
evrp.record_ranges_from_stmt (stmt, false);
|
||||
|
||||
if (check_and_optimize_stmt (&gsi, &cleanup_eh, evrp.get_vr_values ()))
|
||||
if (check_and_optimize_stmt (&gsi, &cleanup_eh, &evrp))
|
||||
gsi_next (&gsi);
|
||||
}
|
||||
|
||||
|
@ -163,8 +163,8 @@ record_temporary_equivalences_from_phis (edge e,
|
||||
{
|
||||
/* Get an empty new VR we can pass to update_value_range and save
|
||||
away in the VR stack. */
|
||||
vr_values *vr_values = evrp_range_analyzer->get_vr_values ();
|
||||
value_range_equiv *new_vr = vr_values->allocate_value_range_equiv ();
|
||||
value_range_equiv *new_vr
|
||||
= evrp_range_analyzer->allocate_value_range_equiv ();
|
||||
new (new_vr) value_range_equiv ();
|
||||
|
||||
/* There are three cases to consider:
|
||||
@ -178,7 +178,7 @@ record_temporary_equivalences_from_phis (edge e,
|
||||
Otherwise set NEW_VR to varying. This may be overly
|
||||
conservative. */
|
||||
if (TREE_CODE (src) == SSA_NAME)
|
||||
new_vr->deep_copy (vr_values->get_value_range (src));
|
||||
new_vr->deep_copy (evrp_range_analyzer->get_value_range (src));
|
||||
else if (TREE_CODE (src) == INTEGER_CST)
|
||||
new_vr->set (src);
|
||||
else
|
||||
|
@ -4010,9 +4010,12 @@ class vrp_folder : public substitute_and_fold_engine
|
||||
: substitute_and_fold_engine (/* Fold all stmts. */ true),
|
||||
m_vr_values (v), simplifier (v)
|
||||
{ }
|
||||
tree get_value (tree, gimple *stmt) FINAL OVERRIDE;
|
||||
bool fold_stmt (gimple_stmt_iterator *) FINAL OVERRIDE;
|
||||
|
||||
tree value_of_expr (tree name, gimple *stmt) OVERRIDE
|
||||
{
|
||||
return m_vr_values->value_of_expr (name, stmt);
|
||||
}
|
||||
class vr_values *m_vr_values;
|
||||
|
||||
private:
|
||||
@ -4023,8 +4026,6 @@ private:
|
||||
{ return simplifier.vrp_evaluate_conditional (code, op0, op1, stmt); }
|
||||
bool simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
|
||||
{ return simplifier.simplify (gsi); }
|
||||
tree op_with_constant_singleton_value_range (tree op)
|
||||
{ return m_vr_values->op_with_constant_singleton_value_range (op); }
|
||||
|
||||
simplify_using_ranges simplifier;
|
||||
};
|
||||
@ -4102,18 +4103,6 @@ vrp_folder::fold_stmt (gimple_stmt_iterator *si)
|
||||
return simplify_stmt_using_ranges (si);
|
||||
}
|
||||
|
||||
/* If OP has a value range with a single constant value return that,
|
||||
otherwise return NULL_TREE. This returns OP itself if OP is a
|
||||
constant.
|
||||
|
||||
Implemented as a pure wrapper right now, but this will change. */
|
||||
|
||||
tree
|
||||
vrp_folder::get_value (tree op, gimple *stmt ATTRIBUTE_UNUSED)
|
||||
{
|
||||
return op_with_constant_singleton_value_range (op);
|
||||
}
|
||||
|
||||
/* Return the LHS of any ASSERT_EXPR where OP appears as the first
|
||||
argument to the ASSERT_EXPR and in which the ASSERT_EXPR dominates
|
||||
BB. If no such ASSERT_EXPR is found, return OP. */
|
||||
|
105
gcc/vr-values.c
105
gcc/vr-values.c
@ -92,7 +92,7 @@ vr_values::get_lattice_entry (const_tree var)
|
||||
return vr;
|
||||
|
||||
/* Create a default value range. */
|
||||
vr = new (vrp_value_range_pool.allocate ()) value_range_equiv;
|
||||
vr = allocate_value_range_equiv ();
|
||||
vr_value[ver] = vr;
|
||||
|
||||
/* After propagation finished return varying. */
|
||||
@ -173,6 +173,49 @@ vr_values::get_value_range (const_tree var,
|
||||
return vr;
|
||||
}
|
||||
|
||||
bool
|
||||
vr_values::range_of_expr (irange &r, tree name, gimple *stmt)
|
||||
{
|
||||
if (const value_range *vr = get_value_range (name, stmt))
|
||||
{
|
||||
if (vr->undefined_p () || vr->varying_p () || vr->constant_p ())
|
||||
r = *vr;
|
||||
else
|
||||
{
|
||||
value_range tmp = *vr;
|
||||
tmp.normalize_symbolics ();
|
||||
r = tmp;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
tree
|
||||
vr_values::value_of_expr (tree op, gimple *)
|
||||
{
|
||||
return op_with_constant_singleton_value_range (op);
|
||||
}
|
||||
|
||||
tree
|
||||
vr_values::value_on_edge (edge, tree op)
|
||||
{
|
||||
return op_with_constant_singleton_value_range (op);
|
||||
}
|
||||
|
||||
tree
|
||||
vr_values::value_of_stmt (gimple *stmt, tree op)
|
||||
{
|
||||
if (!op)
|
||||
op = gimple_get_lhs (stmt);
|
||||
|
||||
gcc_checking_assert (!op|| op == gimple_get_lhs (stmt));
|
||||
|
||||
if (op)
|
||||
return op_with_constant_singleton_value_range (op);
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Set the lattice entry for DEF to VARYING. */
|
||||
|
||||
void
|
||||
@ -451,7 +494,7 @@ simplify_using_ranges::op_with_boolean_value_range_p (tree op)
|
||||
|
||||
/* ?? Errr, this should probably check for [0,0] and [1,1] as well
|
||||
as [0,1]. */
|
||||
const value_range *vr = get_value_range (op);
|
||||
const value_range *vr = query->get_value_range (op);
|
||||
return *vr == value_range (build_zero_cst (TREE_TYPE (op)),
|
||||
build_one_cst (TREE_TYPE (op)));
|
||||
}
|
||||
@ -1006,20 +1049,20 @@ vr_values::extract_range_from_comparison (value_range_equiv *vr,
|
||||
overflow. */
|
||||
|
||||
static bool
|
||||
check_for_binary_op_overflow (range_query *store,
|
||||
check_for_binary_op_overflow (range_query *query,
|
||||
enum tree_code subcode, tree type,
|
||||
tree op0, tree op1, bool *ovf)
|
||||
{
|
||||
value_range vr0, vr1;
|
||||
if (TREE_CODE (op0) == SSA_NAME)
|
||||
vr0 = *store->get_value_range (op0);
|
||||
vr0 = *query->get_value_range (op0);
|
||||
else if (TREE_CODE (op0) == INTEGER_CST)
|
||||
vr0.set (op0);
|
||||
else
|
||||
vr0.set_varying (TREE_TYPE (op0));
|
||||
|
||||
if (TREE_CODE (op1) == SSA_NAME)
|
||||
vr1 = *store->get_value_range (op1);
|
||||
vr1 = *query->get_value_range (op1);
|
||||
else if (TREE_CODE (op1) == INTEGER_CST)
|
||||
vr1.set (op1);
|
||||
else
|
||||
@ -1948,8 +1991,7 @@ vr_values::dump_all_value_ranges (FILE *file)
|
||||
|
||||
/* Initialize VRP lattice. */
|
||||
|
||||
vr_values::vr_values () : vrp_value_range_pool ("Tree VRP value ranges"),
|
||||
simplifier (this)
|
||||
vr_values::vr_values () : simplifier (this)
|
||||
{
|
||||
values_propagated = false;
|
||||
num_vr_values = num_ssa_names * 2;
|
||||
@ -1966,7 +2008,6 @@ vr_values::~vr_values ()
|
||||
free (vr_value);
|
||||
free (vr_phi_edge_counts);
|
||||
bitmap_obstack_release (&vrp_equiv_obstack);
|
||||
vrp_value_range_pool.release ();
|
||||
|
||||
/* So that we can distinguish between VRP data being available
|
||||
and not available. */
|
||||
@ -2092,7 +2133,7 @@ const value_range_equiv *
|
||||
simplify_using_ranges::get_vr_for_comparison (int i, value_range_equiv *tem)
|
||||
{
|
||||
/* Shallow-copy equiv bitmap. */
|
||||
const value_range_equiv *vr = get_value_range (ssa_name (i));
|
||||
const value_range_equiv *vr = query->get_value_range (ssa_name (i));
|
||||
|
||||
/* If name N_i does not have a valid range, use N_i as its own
|
||||
range. This allows us to compare against names that may
|
||||
@ -2117,7 +2158,7 @@ simplify_using_ranges::compare_name_with_value
|
||||
bool *strict_overflow_p, bool use_equiv_p)
|
||||
{
|
||||
/* Get the set of equivalences for VAR. */
|
||||
bitmap e = get_value_range (var)->equiv ();
|
||||
bitmap e = query->get_value_range (var)->equiv ();
|
||||
|
||||
/* Start at -1. Set it to 0 if we do a comparison without relying
|
||||
on overflow, or 1 if all comparisons rely on overflow. */
|
||||
@ -2197,8 +2238,8 @@ simplify_using_ranges::compare_names (enum tree_code comp, tree n1, tree n2,
|
||||
{
|
||||
/* Compare the ranges of every name equivalent to N1 against the
|
||||
ranges of every name equivalent to N2. */
|
||||
bitmap e1 = get_value_range (n1)->equiv ();
|
||||
bitmap e2 = get_value_range (n2)->equiv ();
|
||||
bitmap e1 = query->get_value_range (n1)->equiv ();
|
||||
bitmap e2 = query->get_value_range (n2)->equiv ();
|
||||
|
||||
/* Use the fake bitmaps if e1 or e2 are not available. */
|
||||
static bitmap s_e1 = NULL, s_e2 = NULL;
|
||||
@ -2310,8 +2351,8 @@ simplify_using_ranges::vrp_evaluate_conditional_warnv_with_ops_using_ranges
|
||||
(enum tree_code code, tree op0, tree op1, bool * strict_overflow_p)
|
||||
{
|
||||
const value_range_equiv *vr0, *vr1;
|
||||
vr0 = (TREE_CODE (op0) == SSA_NAME) ? get_value_range (op0) : NULL;
|
||||
vr1 = (TREE_CODE (op1) == SSA_NAME) ? get_value_range (op1) : NULL;
|
||||
vr0 = (TREE_CODE (op0) == SSA_NAME) ? query->get_value_range (op0) : NULL;
|
||||
vr1 = (TREE_CODE (op1) == SSA_NAME) ? query->get_value_range (op1) : NULL;
|
||||
|
||||
tree res = NULL_TREE;
|
||||
if (vr0 && vr1)
|
||||
@ -2390,7 +2431,7 @@ simplify_using_ranges::vrp_evaluate_conditional_warnv_with_ops
|
||||
}
|
||||
else
|
||||
gcc_unreachable ();
|
||||
const value_range_equiv *vr0 = get_value_range (op0, stmt);
|
||||
const value_range_equiv *vr0 = query->get_value_range (op0, stmt);
|
||||
/* If vro, the range for OP0 to pass the overflow test, has
|
||||
no intersection with *vr0, OP0's known range, then the
|
||||
overflow test can't pass, so return the node for false.
|
||||
@ -2496,7 +2537,7 @@ simplify_using_ranges::vrp_evaluate_conditional (tree_code code, tree op0,
|
||||
always fold regardless of the value of OP0. If -Wtype-limits
|
||||
was specified, emit a warning. */
|
||||
tree type = TREE_TYPE (op0);
|
||||
const value_range_equiv *vr0 = get_value_range (op0, stmt);
|
||||
const value_range_equiv *vr0 = query->get_value_range (op0, stmt);
|
||||
|
||||
if (vr0->varying_p ()
|
||||
&& INTEGRAL_TYPE_P (type)
|
||||
@ -2547,7 +2588,7 @@ simplify_using_ranges::vrp_visit_cond_stmt (gcond *stmt, edge *taken_edge_p)
|
||||
fprintf (dump_file, "\t");
|
||||
print_generic_expr (dump_file, use);
|
||||
fprintf (dump_file, ": ");
|
||||
dump_value_range (dump_file, get_value_range (use, stmt));
|
||||
dump_value_range (dump_file, query->get_value_range (use, stmt));
|
||||
}
|
||||
|
||||
fprintf (dump_file, "\n");
|
||||
@ -3123,7 +3164,7 @@ simplify_using_ranges::simplify_div_or_mod_using_ranges
|
||||
}
|
||||
else
|
||||
{
|
||||
vr = get_value_range (op0, stmt);
|
||||
vr = query->get_value_range (op0, stmt);
|
||||
if (range_int_cst_p (vr))
|
||||
{
|
||||
op0min = vr->min ();
|
||||
@ -3134,7 +3175,7 @@ simplify_using_ranges::simplify_div_or_mod_using_ranges
|
||||
if (rhs_code == TRUNC_MOD_EXPR
|
||||
&& TREE_CODE (op1) == SSA_NAME)
|
||||
{
|
||||
const value_range_equiv *vr1 = get_value_range (op1, stmt);
|
||||
const value_range_equiv *vr1 = query->get_value_range (op1, stmt);
|
||||
if (range_int_cst_p (vr1))
|
||||
op1min = vr1->min ();
|
||||
}
|
||||
@ -3283,7 +3324,7 @@ simplify_using_ranges::simplify_abs_using_ranges (gimple_stmt_iterator *gsi,
|
||||
gimple *stmt)
|
||||
{
|
||||
tree op = gimple_assign_rhs1 (stmt);
|
||||
const value_range *vr = get_value_range (op, stmt);
|
||||
const value_range *vr = query->get_value_range (op, stmt);
|
||||
|
||||
if (vr)
|
||||
{
|
||||
@ -3373,14 +3414,14 @@ simplify_using_ranges::simplify_bit_ops_using_ranges
|
||||
wide_int mask;
|
||||
|
||||
if (TREE_CODE (op0) == SSA_NAME)
|
||||
vr0 = *(get_value_range (op0, stmt));
|
||||
vr0 = *(query->get_value_range (op0, stmt));
|
||||
else if (is_gimple_min_invariant (op0))
|
||||
vr0.set (op0);
|
||||
else
|
||||
return false;
|
||||
|
||||
if (TREE_CODE (op1) == SSA_NAME)
|
||||
vr1 = *(get_value_range (op1, stmt));
|
||||
vr1 = *(query->get_value_range (op1, stmt));
|
||||
else if (is_gimple_min_invariant (op1))
|
||||
vr1.set (op1);
|
||||
else
|
||||
@ -3599,7 +3640,7 @@ simplify_using_ranges::simplify_cond_using_ranges_1 (gcond *stmt)
|
||||
&& INTEGRAL_TYPE_P (TREE_TYPE (op0))
|
||||
&& is_gimple_min_invariant (op1))
|
||||
{
|
||||
const value_range *vr = get_value_range (op0, stmt);
|
||||
const value_range *vr = query->get_value_range (op0, stmt);
|
||||
|
||||
/* If we have range information for OP0, then we might be
|
||||
able to simplify this conditional. */
|
||||
@ -3672,7 +3713,7 @@ simplify_using_ranges::simplify_cond_using_ranges_1 (gcond *stmt)
|
||||
subsequent passes. */
|
||||
|
||||
void
|
||||
simplify_cond_using_ranges_2 (vr_values *store, gcond *stmt)
|
||||
simplify_cond_using_ranges_2 (vr_values *query, gcond *stmt)
|
||||
{
|
||||
tree op0 = gimple_cond_lhs (stmt);
|
||||
tree op1 = gimple_cond_rhs (stmt);
|
||||
@ -3702,7 +3743,7 @@ simplify_cond_using_ranges_2 (vr_values *store, gcond *stmt)
|
||||
&& !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (innerop)
|
||||
&& desired_pro_or_demotion_p (TREE_TYPE (innerop), TREE_TYPE (op0)))
|
||||
{
|
||||
const value_range *vr = store->get_value_range (innerop);
|
||||
const value_range *vr = query->get_value_range (innerop);
|
||||
|
||||
if (range_int_cst_p (vr)
|
||||
&& range_fits_type_p (vr,
|
||||
@ -3743,7 +3784,7 @@ simplify_using_ranges::simplify_switch_using_ranges (gswitch *stmt)
|
||||
|
||||
if (TREE_CODE (op) == SSA_NAME)
|
||||
{
|
||||
vr = get_value_range (op, stmt);
|
||||
vr = query->get_value_range (op, stmt);
|
||||
|
||||
/* We can only handle integer ranges. */
|
||||
if (vr->varying_p ()
|
||||
@ -4036,7 +4077,7 @@ simplify_using_ranges::simplify_float_conversion_using_ranges
|
||||
gimple *stmt)
|
||||
{
|
||||
tree rhs1 = gimple_assign_rhs1 (stmt);
|
||||
const value_range *vr = get_value_range (rhs1, stmt);
|
||||
const value_range *vr = query->get_value_range (rhs1, stmt);
|
||||
scalar_float_mode fltmode
|
||||
= SCALAR_FLOAT_TYPE_MODE (TREE_TYPE (gimple_assign_lhs (stmt)));
|
||||
scalar_int_mode mode;
|
||||
@ -4141,7 +4182,7 @@ simplify_using_ranges::simplify_internal_call_using_ranges
|
||||
return false;
|
||||
else
|
||||
type = TREE_TYPE (TREE_TYPE (gimple_call_lhs (stmt)));
|
||||
if (!check_for_binary_op_overflow (store, subcode, type, op0, op1, &ovf)
|
||||
if (!check_for_binary_op_overflow (query, subcode, type, op0, op1, &ovf)
|
||||
|| (is_ubsan && ovf))
|
||||
return false;
|
||||
|
||||
@ -4200,7 +4241,7 @@ simplify_using_ranges::simplify_internal_call_using_ranges
|
||||
bool
|
||||
simplify_using_ranges::two_valued_val_range_p (tree var, tree *a, tree *b)
|
||||
{
|
||||
value_range vr = *get_value_range (var);
|
||||
value_range vr = *query->get_value_range (var);
|
||||
vr.normalize_symbolics ();
|
||||
if (vr.varying_p () || vr.undefined_p ())
|
||||
return false;
|
||||
@ -4217,8 +4258,8 @@ simplify_using_ranges::two_valued_val_range_p (tree var, tree *a, tree *b)
|
||||
return false;
|
||||
}
|
||||
|
||||
simplify_using_ranges::simplify_using_ranges (range_query *store)
|
||||
: store (store)
|
||||
simplify_using_ranges::simplify_using_ranges (range_query *query)
|
||||
: query (query)
|
||||
{
|
||||
to_remove_edges = vNULL;
|
||||
to_update_switch_stmts = vNULL;
|
||||
@ -4234,6 +4275,8 @@ simplify_using_ranges::~simplify_using_ranges ()
|
||||
bool
|
||||
simplify_using_ranges::simplify (gimple_stmt_iterator *gsi)
|
||||
{
|
||||
gcc_checking_assert (query);
|
||||
|
||||
gimple *stmt = gsi_stmt (*gsi);
|
||||
if (is_gimple_assign (stmt))
|
||||
{
|
||||
|
@ -21,28 +21,19 @@ along with GCC; see the file COPYING3. If not see
|
||||
#define GCC_VR_VALUES_H
|
||||
|
||||
#include "value-range-equiv.h"
|
||||
#include "value-query.h"
|
||||
|
||||
// Abstract class to return a range for a given SSA.
|
||||
|
||||
class range_query
|
||||
{
|
||||
public:
|
||||
virtual const value_range_equiv *get_value_range (const_tree,
|
||||
gimple * = NULL) = 0;
|
||||
virtual ~range_query () { }
|
||||
};
|
||||
|
||||
// Class to simplify a statement using range information.
|
||||
//
|
||||
// The constructor takes a full vr_values, but all it needs is
|
||||
// get_value_range() from it. This class could be made to work with
|
||||
// any range repository.
|
||||
|
||||
class simplify_using_ranges : public range_query
|
||||
class simplify_using_ranges
|
||||
{
|
||||
public:
|
||||
simplify_using_ranges (class range_query *);
|
||||
simplify_using_ranges (class range_query *query = NULL);
|
||||
~simplify_using_ranges ();
|
||||
void set_range_query (class range_query *q) { query = q; }
|
||||
|
||||
bool simplify (gimple_stmt_iterator *);
|
||||
|
||||
// ?? These should be cleaned, merged, and made private.
|
||||
@ -53,8 +44,6 @@ public:
|
||||
bool *, bool *);
|
||||
|
||||
private:
|
||||
const value_range_equiv *get_value_range (const_tree op,
|
||||
gimple *stmt = NULL) OVERRIDE;
|
||||
bool simplify_truth_ops_using_ranges (gimple_stmt_iterator *, gimple *);
|
||||
bool simplify_div_or_mod_using_ranges (gimple_stmt_iterator *, gimple *);
|
||||
bool simplify_abs_using_ranges (gimple_stmt_iterator *, gimple *);
|
||||
@ -89,7 +78,7 @@ private:
|
||||
|
||||
vec<edge> to_remove_edges;
|
||||
vec<switch_update> to_update_switch_stmts;
|
||||
class range_query *store;
|
||||
class range_query *query;
|
||||
};
|
||||
|
||||
/* The VR_VALUES class holds the current view of range information
|
||||
@ -112,7 +101,12 @@ class vr_values : public range_query
|
||||
vr_values (void);
|
||||
~vr_values (void);
|
||||
|
||||
const value_range_equiv *get_value_range (const_tree, gimple * = NULL);
|
||||
virtual bool range_of_expr (irange &r, tree name, gimple *stmt) OVERRIDE;
|
||||
virtual tree value_of_expr (tree, gimple * = NULL) OVERRIDE;
|
||||
virtual tree value_on_edge (edge, tree) OVERRIDE;
|
||||
virtual tree value_of_stmt (gimple *, tree = NULL_TREE) OVERRIDE;
|
||||
virtual const value_range_equiv *get_value_range (const_tree,
|
||||
gimple * = NULL) OVERRIDE;
|
||||
void set_vr_value (tree, value_range_equiv *);
|
||||
value_range_equiv *swap_vr_value (tree, value_range_equiv *);
|
||||
|
||||
@ -136,9 +130,9 @@ class vr_values : public range_query
|
||||
|
||||
/* Allocate a new value_range object. */
|
||||
value_range_equiv *allocate_value_range_equiv (void)
|
||||
{ return vrp_value_range_pool.allocate (); }
|
||||
{ return range_query::allocate_value_range_equiv (); }
|
||||
void free_value_range (value_range_equiv *vr)
|
||||
{ vrp_value_range_pool.remove (vr); }
|
||||
{ free_value_range_equiv (vr); }
|
||||
|
||||
private:
|
||||
value_range_equiv *get_lattice_entry (const_tree);
|
||||
@ -155,9 +149,6 @@ class vr_values : public range_query
|
||||
void vrp_visit_assignment_or_call (gimple*, tree *, value_range_equiv *);
|
||||
void vrp_visit_switch_stmt (gswitch *, edge *);
|
||||
|
||||
/* Allocation pools for value_range objects. */
|
||||
object_allocator<value_range_equiv> vrp_value_range_pool;
|
||||
|
||||
/* This probably belongs in the lattice rather than in here. */
|
||||
bool values_propagated;
|
||||
|
||||
@ -176,12 +167,6 @@ class vr_values : public range_query
|
||||
simplify_using_ranges simplifier;
|
||||
};
|
||||
|
||||
inline const value_range_equiv *
|
||||
simplify_using_ranges::get_value_range (const_tree op, gimple *stmt)
|
||||
{
|
||||
return store->get_value_range (op, stmt);
|
||||
}
|
||||
|
||||
extern tree get_output_for_vrp (gimple *);
|
||||
|
||||
// FIXME: Move this to tree-vrp.c.
|
||||
|
Loading…
Reference in New Issue
Block a user