Howdy.
This moves all the simplification code from vr_values into a separate
class (simplify_using_ranges). In doing so, we get rid of a bunch of
dependencies on the internals of vr_values. The goal is to (a) remove
unnecessary interdependendcies (b) be able to use this engine with any
range infrastructure, as all it needs is a method to get the range for
an SSA name (get_value_range).
I also removed as many dependencies on value_range_equiv as possible,
preferring value_range. A few value_range_equiv uses remain, but for
cases where equivalences are actually used (folding conditionals, etc).
The plan is to use it like this:
simplify_using_ranges simplifier (vr_values_thinggie);
simplifier.simplify (gsi);
OK?
Aldy
commit 753d495161942d7085c5955f47fefa7a4378562a
Author: Aldy Hernandez <al...@redhat.com>
Date: Thu Jun 18 10:37:14 2020 +0200
Move simplification of statements using ranges into its own class.
This moves all the simplification code from vr_values into a separate
class (simplify_using_ranges). In doing so, we get rid of a bunch of
dependencies on the internals of vr_values. The goal is to (a) remove
unnecessary interdependendcies (b) be able to use this engine with any
range infrastructure, as all it needs is a method to get the range for
an SSA name (get_value_range).
I also removed as many dependencies on value_range_equiv as possible,
preferring value_range. A few value_range_equiv uses remain, but for
cases where equivalences are actually used (folding conditionals, etc).
gcc/ChangeLog:
* gimple-ssa-evrp-analyze.h (vrp_visit_cond_stmt): Use
simplify_using_ranges class.
* gimple-ssa-evrp.c (class evrp_folder): New simplify_using_ranges
field. Adjust all methods to use new field.
* tree-ssa-dom.c (simplify_stmt_for_jump_threading): Use
simplify_using_ranges class.
* tree-vrp.c (class vrp_folder): New simplify_using_ranges
field. Adjust all methods to use new field.
(simplify_stmt_for_jump_threading): Use simplify_using_ranges class.
(vrp_prop::vrp_finalize): New vrp_folder argument.
(execute_vrp): Pass folder to vrp_finalize. Use
simplify_using_ranges class.
Remove cleanup_edges_and_switches call.
* vr-values.c (vr_values::op_with_boolean_value_range_p): Change
value_range_equiv uses to value_range.
(simplify_using_ranges::op_with_boolean_value_range_p): Use
simplify_using_ranges class.
(check_for_binary_op_overflow): Make static.
(vr_values::extract_range_basic): Pass this to
check_for_binary_op_overflow.
(compare_range_with_value): Change value_range_equiv uses to
value_range.
(vr_values::vr_values): Initialize simplifier field.
Remove uses of to_remove_edges and to_update_switch_stmts.
(vr_values::~vr_values): Remove uses of to_remove_edges and
to_update_switch_stmts.
(vr_values::get_vr_for_comparison): Move to simplify_using_ranges
class.
(vr_values::compare_name_with_value): Same.
(vr_values::compare_names): Same.
(vr_values::vrp_evaluate_conditional_warnv_with_ops): Same.
(vr_values::vrp_evaluate_conditional): Same.
(vr_values::vrp_visit_cond_stmt): Same.
(find_case_label_ranges): Change value_range_equiv uses to
value_range.
(vr_values::extract_range_from_stmt): Use simplify_using_ranges class.
(vr_values::simplify_truth_ops_using_ranges): Move to
simplify_using_ranges class.
(vr_values::simplify_div_or_mod_using_ranges): Same.
(vr_values::simplify_min_or_max_using_ranges): Same.
(vr_values::simplify_abs_using_ranges): Same.
(vr_values::simplify_bit_ops_using_ranges): Same.
(test_for_singularity): Change value_range_equiv uses to
value_range.
(range_fits_type_p): Same.
(vr_values::simplify_cond_using_ranges_1): Same.
(vr_values::simplify_cond_using_ranges_2): Make extern.
(vr_values::fold_cond): Move to simplify_using_ranges class.
(vr_values::simplify_switch_using_ranges): Same.
(vr_values::cleanup_edges_and_switches): Same.
(vr_values::simplify_float_conversion_using_ranges): Same.
(vr_values::simplify_internal_call_using_ranges): Same.
(vr_values::two_valued_val_range_p): Same.
(vr_values::simplify_stmt_using_ranges): Move to...
(simplify_using_ranges::simplify): ...here.
* vr-values.h (class vr_values): Move all the simplification of
statements using ranges methods and code from here...
(class simplify_using_ranges): ...to here.
(simplify_cond_using_ranges_2): New extern prototype.
diff --git a/gcc/gimple-ssa-evrp-analyze.h b/gcc/gimple-ssa-evrp-analyze.h
index d16279f89b9..8abbbe3180d 100644
--- a/gcc/gimple-ssa-evrp-analyze.h
+++ b/gcc/gimple-ssa-evrp-analyze.h
@@ -50,7 +50,10 @@ class evrp_range_analyzer
/* A bit of a wart. This should ideally go away. */
void vrp_visit_cond_stmt (gcond *cond, edge *e)
- { return vr_values->vrp_visit_cond_stmt (cond, e); }
+ {
+ simplify_using_ranges simpl (vr_values);
+ 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.
diff --git a/gcc/gimple-ssa-evrp.c b/gcc/gimple-ssa-evrp.c
index af780fd0519..e8fde63aa34 100644
--- a/gcc/gimple-ssa-evrp.c
+++ b/gcc/gimple-ssa-evrp.c
@@ -46,14 +46,13 @@ 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 ())
+ m_vr_values (m_range_analyzer.get_vr_values ()),
+ simplifier (m_vr_values)
{
}
~evrp_folder ()
{
- m_vr_values->cleanup_edges_and_switches ();
-
if (dump_file)
{
fprintf (dump_file, "\nValue ranges after Early VRP:\n\n");
@@ -86,7 +85,7 @@ public:
bool fold_stmt (gimple_stmt_iterator *gsi) OVERRIDE
{
- return m_vr_values->simplify_stmt_using_ranges (gsi);
+ return simplifier.simplify (gsi);
}
void post_fold_bb (basic_block bb) OVERRIDE
@@ -96,13 +95,15 @@ public:
void post_new_stmt (gimple *stmt) OVERRIDE
{
- m_vr_values->set_defs_to_varying (stmt);
+ m_range_analyzer.get_vr_values ()->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;
+
+ simplify_using_ranges simplifier;
};
/* Main entry point for the early vrp pass which is a simplified non-iterative
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index 864c984f636..69eaec345bf 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -887,12 +887,11 @@ simplify_stmt_for_jump_threading (gimple *stmt,
copy in tree-vrp is scheduled for removal in gcc-9. */
if (gcond *cond_stmt = dyn_cast <gcond *> (stmt))
{
- cached_lhs
- = x_vr_values->vrp_evaluate_conditional (gimple_cond_code (cond_stmt),
- gimple_cond_lhs (cond_stmt),
- gimple_cond_rhs (cond_stmt),
- within_stmt);
- return cached_lhs;
+ simplify_using_ranges simplifier (x_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))
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index c39a6f5e374..7193ca4ad5e 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -3373,7 +3373,7 @@ public:
struct function *fun;
void vrp_initialize (struct function *);
- void vrp_finalize (bool);
+ void vrp_finalize (class vrp_folder *, bool);
class vr_values vr_values;
@@ -3938,23 +3938,28 @@ vrp_prop::visit_phi (gphi *phi)
class vrp_folder : public substitute_and_fold_engine
{
-public:
- vrp_folder () : substitute_and_fold_engine (/* Fold all stmts. */ true) { }
+ public:
+ vrp_folder (vr_values *v)
+ : 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;
- class vr_values *vr_values;
+ class vr_values *m_vr_values;
private:
bool fold_predicate_in (gimple_stmt_iterator *);
/* Delegators. */
tree vrp_evaluate_conditional (tree_code code, tree op0,
tree op1, gimple *stmt)
- { return vr_values->vrp_evaluate_conditional (code, op0, op1, stmt); }
+ { return simplifier.vrp_evaluate_conditional (code, op0, op1, stmt); }
bool simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
- { return vr_values->simplify_stmt_using_ranges (gsi); }
+ { return simplifier.simplify (gsi); }
tree op_with_constant_singleton_value_range (tree op)
- { return vr_values->op_with_constant_singleton_value_range (op); }
+ { return m_vr_values->op_with_constant_singleton_value_range (op); }
+
+ simplify_using_ranges simplifier;
};
/* If the statement pointed by SI has a predicate whose value can be
@@ -4096,7 +4101,8 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt,
tree op1 = gimple_cond_rhs (cond_stmt);
op1 = lhs_of_dominating_assert (op1, bb, stmt);
- return vr_values->vrp_evaluate_conditional (gimple_cond_code (cond_stmt),
+ simplify_using_ranges simplifier (vr_values);
+ return simplifier.vrp_evaluate_conditional (gimple_cond_code (cond_stmt),
op0, op1, within_stmt);
}
@@ -4332,7 +4338,7 @@ identify_jump_threads (struct function *fun, class vr_values *vr_values)
/* Traverse all the blocks folding conditionals with known ranges. */
void
-vrp_prop::vrp_finalize (bool warn_array_bounds_p)
+vrp_prop::vrp_finalize (vrp_folder *folder, bool warn_array_bounds_p)
{
size_t i;
@@ -4376,9 +4382,7 @@ vrp_prop::vrp_finalize (bool warn_array_bounds_p)
if (warn_array_bounds && warn_array_bounds_p)
set_all_edges_as_executable (fun);
- class vrp_folder vrp_folder;
- vrp_folder.vr_values = &vr_values;
- vrp_folder.substitute_and_fold ();
+ folder->substitute_and_fold ();
if (warn_array_bounds && warn_array_bounds_p)
{
@@ -4453,7 +4457,10 @@ execute_vrp (struct function *fun, bool warn_array_bounds_p)
class vrp_prop vrp_prop;
vrp_prop.vrp_initialize (fun);
vrp_prop.ssa_propagate ();
- vrp_prop.vrp_finalize (warn_array_bounds_p);
+ /* Instantiate the folder here, so that edge cleanups happen at the
+ end of this function. */
+ vrp_folder folder (&vrp_prop.vr_values);
+ vrp_prop.vrp_finalize (&folder, warn_array_bounds_p);
/* We must identify jump threading opportunities before we release
the datastructures built by VRP. */
@@ -4471,7 +4478,8 @@ execute_vrp (struct function *fun, bool warn_array_bounds_p)
{
gimple *last = last_stmt (bb);
if (last && gimple_code (last) == GIMPLE_COND)
- vrp_prop.vr_values.simplify_cond_using_ranges_2 (as_a <gcond *> (last));
+ simplify_cond_using_ranges_2 (&vrp_prop.vr_values,
+ as_a <gcond *> (last));
}
free_numbers_of_iterations_estimates (fun);
@@ -4496,7 +4504,6 @@ execute_vrp (struct function *fun, bool warn_array_bounds_p)
processing by the pass manager. */
thread_through_all_blocks (false);
- vrp_prop.vr_values.cleanup_edges_and_switches ();
threadedge_finalize_values ();
scev_finalize ();
diff --git a/gcc/vr-values.c b/gcc/vr-values.c
index e95df78870a..d0303599002 100644
--- a/gcc/vr-values.c
+++ b/gcc/vr-values.c
@@ -435,10 +435,8 @@ vr_values::op_with_constant_singleton_value_range (tree op)
/* Return true if op is in a boolean [0, 1] value-range. */
bool
-vr_values::op_with_boolean_value_range_p (tree op)
+simplify_using_ranges::op_with_boolean_value_range_p (tree op)
{
- const value_range_equiv *vr;
-
if (TYPE_PRECISION (TREE_TYPE (op)) == 1)
return true;
@@ -449,7 +447,7 @@ vr_values::op_with_boolean_value_range_p (tree op)
if (TREE_CODE (op) != SSA_NAME)
return false;
- vr = get_value_range (op);
+ const value_range *vr = get_value_range (op);
return (vr->kind () == VR_RANGE
&& integer_zerop (vr->min ())
&& integer_onep (vr->max ()));
@@ -976,10 +974,9 @@ vr_values::extract_range_from_comparison (value_range_equiv *vr,
tree type, tree op0, tree op1)
{
bool sop;
- tree val;
-
- val = vrp_evaluate_conditional_warnv_with_ops (code, op0, op1, false, &sop,
- NULL);
+ tree val
+ = simplifier.vrp_evaluate_conditional_warnv_with_ops (code, op0, op1,
+ false, &sop, NULL);
if (val)
{
/* Since this expression was found on the RHS of an assignment,
@@ -1002,20 +999,21 @@ vr_values::extract_range_from_comparison (value_range_equiv *vr,
always overflow. Set *OVF to true if it is known to always
overflow. */
-bool
-vr_values::check_for_binary_op_overflow (enum tree_code subcode, tree type,
- tree op0, tree op1, bool *ovf)
+static bool
+check_for_binary_op_overflow (vr_values *store,
+ enum tree_code subcode, tree type,
+ tree op0, tree op1, bool *ovf)
{
value_range vr0, vr1;
if (TREE_CODE (op0) == SSA_NAME)
- vr0 = *get_value_range (op0);
+ vr0 = *store->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 = *get_value_range (op1);
+ vr1 = *store->get_value_range (op1);
else if (TREE_CODE (op1) == INTEGER_CST)
vr1.set (op1);
else
@@ -1395,7 +1393,7 @@ vr_values::extract_range_basic (value_range_equiv *vr, gimple *stmt)
if (code == IMAGPART_EXPR)
{
bool ovf = false;
- if (check_for_binary_op_overflow (subcode, type,
+ if (check_for_binary_op_overflow (this, subcode, type,
op0, op1, &ovf))
vr->set (build_int_cst (type, ovf));
else if (TYPE_PRECISION (type) == 1
@@ -1636,7 +1634,7 @@ compare_ranges (enum tree_code comp, const value_range_equiv *vr0,
assumed signed overflow is undefined. */
static tree
-compare_range_with_value (enum tree_code comp, const value_range_equiv *vr,
+compare_range_with_value (enum tree_code comp, const value_range *vr,
tree val, bool *strict_overflow_p)
{
if (vr->varying_p () || vr->undefined_p ())
@@ -1946,15 +1944,14 @@ vr_values::dump_all_value_ranges (FILE *file)
/* Initialize VRP lattice. */
-vr_values::vr_values () : vrp_value_range_pool ("Tree VRP value ranges")
+vr_values::vr_values () : vrp_value_range_pool ("Tree VRP value ranges"),
+ simplifier (this)
{
values_propagated = false;
num_vr_values = num_ssa_names * 2;
vr_value = XCNEWVEC (value_range_equiv *, num_vr_values);
vr_phi_edge_counts = XCNEWVEC (int, num_ssa_names);
bitmap_obstack_initialize (&vrp_equiv_obstack);
- to_remove_edges = vNULL;
- to_update_switch_stmts = vNULL;
}
/* Free VRP lattice. */
@@ -1971,12 +1968,6 @@ vr_values::~vr_values ()
and not available. */
vr_value = NULL;
vr_phi_edge_counts = NULL;
-
- /* If there are entries left in TO_REMOVE_EDGES or TO_UPDATE_SWITCH_STMTS
- then an EVRP client did not clean up properly. Catch it now rather
- than seeing something more obscure later. */
- gcc_assert (to_remove_edges.is_empty ()
- && to_update_switch_stmts.is_empty ());
}
@@ -2094,7 +2085,7 @@ vr_values::vrp_visit_assignment_or_call (gimple *stmt, tree *output_p,
is varying or undefined. Uses TEM as storage for the alternate range. */
const value_range_equiv *
-vr_values::get_vr_for_comparison (int i, value_range_equiv *tem)
+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));
@@ -2117,8 +2108,9 @@ vr_values::get_vr_for_comparison (int i, value_range_equiv *tem)
*STRICT_OVERFLOW_P. */
tree
-vr_values::compare_name_with_value (enum tree_code comp, tree var, tree val,
- bool *strict_overflow_p, bool use_equiv_p)
+simplify_using_ranges::compare_name_with_value
+ (enum tree_code comp, tree var, tree val,
+ bool *strict_overflow_p, bool use_equiv_p)
{
/* Get the set of equivalences for VAR. */
bitmap e = get_value_range (var)->equiv ();
@@ -2196,8 +2188,8 @@ vr_values::compare_name_with_value (enum tree_code comp, tree var, tree val,
tree
-vr_values::compare_names (enum tree_code comp, tree n1, tree n2,
- bool *strict_overflow_p)
+simplify_using_ranges::compare_names (enum tree_code comp, tree n1, tree n2,
+ bool *strict_overflow_p)
{
/* Compare the ranges of every name equivalent to N1 against the
ranges of every name equivalent to N2. */
@@ -2310,7 +2302,7 @@ vr_values::compare_names (enum tree_code comp, tree n1, tree n2,
optimizers. */
tree
-vr_values::vrp_evaluate_conditional_warnv_with_ops_using_ranges
+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;
@@ -2331,11 +2323,12 @@ vr_values::vrp_evaluate_conditional_warnv_with_ops_using_ranges
/* Helper function for vrp_evaluate_conditional_warnv. */
tree
-vr_values::vrp_evaluate_conditional_warnv_with_ops (enum tree_code code,
- tree op0, tree op1,
- bool use_equiv_p,
- bool *strict_overflow_p,
- bool *only_ranges)
+simplify_using_ranges::vrp_evaluate_conditional_warnv_with_ops
+ (enum tree_code code,
+ tree op0, tree op1,
+ bool use_equiv_p,
+ bool *strict_overflow_p,
+ bool *only_ranges)
{
tree ret;
if (only_ranges)
@@ -2438,8 +2431,8 @@ vr_values::vrp_evaluate_conditional_warnv_with_ops (enum tree_code code,
appropriate. */
tree
-vr_values::vrp_evaluate_conditional (tree_code code, tree op0,
- tree op1, gimple *stmt)
+simplify_using_ranges::vrp_evaluate_conditional (tree_code code, tree op0,
+ tree op1, gimple *stmt)
{
bool sop;
tree ret;
@@ -2531,7 +2524,7 @@ vr_values::vrp_evaluate_conditional (tree_code code, tree op0,
*TAKEN_EDGE_P. Otherwise, set *TAKEN_EDGE_P to NULL. */
void
-vr_values::vrp_visit_cond_stmt (gcond *stmt, edge *taken_edge_p)
+simplify_using_ranges::vrp_visit_cond_stmt (gcond *stmt, edge *taken_edge_p)
{
tree val;
@@ -2551,7 +2544,7 @@ vr_values::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, vr_value[SSA_NAME_VERSION (use)]);
+ dump_value_range (dump_file, get_value_range (use));
}
fprintf (dump_file, "\n");
@@ -2624,7 +2617,7 @@ vr_values::vrp_visit_cond_stmt (gcond *stmt, edge *taken_edge_p)
Returns true if the default label is not needed. */
static bool
-find_case_label_ranges (gswitch *stmt, const value_range_equiv *vr,
+find_case_label_ranges (gswitch *stmt, const value_range *vr,
size_t *min_idx1, size_t *max_idx1,
size_t *min_idx2, size_t *max_idx2)
{
@@ -2808,7 +2801,7 @@ vr_values::extract_range_from_stmt (gimple *stmt, edge *taken_edge_p,
else if (is_gimple_assign (stmt) || is_gimple_call (stmt))
vrp_visit_assignment_or_call (stmt, output_p, vr);
else if (gimple_code (stmt) == GIMPLE_COND)
- vrp_visit_cond_stmt (as_a <gcond *> (stmt), taken_edge_p);
+ simplifier.vrp_visit_cond_stmt (as_a <gcond *> (stmt), taken_edge_p);
else if (gimple_code (stmt) == GIMPLE_SWITCH)
vrp_visit_switch_stmt (as_a <gswitch *> (stmt), taken_edge_p);
}
@@ -3029,8 +3022,9 @@ update_range:
/* Simplify boolean operations if the source is known
to be already a boolean. */
bool
-vr_values::simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi,
- gimple *stmt)
+simplify_using_ranges::simplify_truth_ops_using_ranges
+ (gimple_stmt_iterator *gsi,
+ gimple *stmt)
{
enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
tree lhs, op0, op1;
@@ -3106,8 +3100,9 @@ vr_values::simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi,
modulo. */
bool
-vr_values::simplify_div_or_mod_using_ranges (gimple_stmt_iterator *gsi,
- gimple *stmt)
+simplify_using_ranges::simplify_div_or_mod_using_ranges
+ (gimple_stmt_iterator *gsi,
+ gimple *stmt)
{
enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
tree val = NULL;
@@ -3115,7 +3110,7 @@ vr_values::simplify_div_or_mod_using_ranges (gimple_stmt_iterator *gsi,
tree op1 = gimple_assign_rhs2 (stmt);
tree op0min = NULL_TREE, op0max = NULL_TREE;
tree op1min = op1;
- const value_range_equiv *vr = NULL;
+ const value_range *vr = NULL;
if (TREE_CODE (op0) == INTEGER_CST)
{
@@ -3231,8 +3226,9 @@ vr_values::simplify_div_or_mod_using_ranges (gimple_stmt_iterator *gsi,
disjoint. Return true if we do simplify. */
bool
-vr_values::simplify_min_or_max_using_ranges (gimple_stmt_iterator *gsi,
- gimple *stmt)
+simplify_using_ranges::simplify_min_or_max_using_ranges
+ (gimple_stmt_iterator *gsi,
+ gimple *stmt)
{
tree op0 = gimple_assign_rhs1 (stmt);
tree op1 = gimple_assign_rhs2 (stmt);
@@ -3279,10 +3275,11 @@ vr_values::simplify_min_or_max_using_ranges (gimple_stmt_iterator *gsi,
ABS_EXPR into a NEGATE_EXPR. */
bool
-vr_values::simplify_abs_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
+simplify_using_ranges::simplify_abs_using_ranges (gimple_stmt_iterator *gsi,
+ gimple *stmt)
{
tree op = gimple_assign_rhs1 (stmt);
- const value_range_equiv *vr = get_value_range (op);
+ const value_range *vr = get_value_range (op);
if (vr)
{
@@ -3359,8 +3356,9 @@ vr_set_zero_nonzero_bits (const tree expr_type,
operation is redundant. */
bool
-vr_values::simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi,
- gimple *stmt)
+simplify_using_ranges::simplify_bit_ops_using_ranges
+ (gimple_stmt_iterator *gsi,
+ gimple *stmt)
{
tree op0 = gimple_assign_rhs1 (stmt);
tree op1 = gimple_assign_rhs2 (stmt);
@@ -3444,7 +3442,7 @@ vr_values::simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi,
static tree
test_for_singularity (enum tree_code cond_code, tree op0,
- tree op1, const value_range_equiv *vr)
+ tree op1, const value_range *vr)
{
tree min = NULL;
tree max = NULL;
@@ -3502,7 +3500,7 @@ test_for_singularity (enum tree_code cond_code, tree op0,
by PRECISION and UNSIGNED_P. */
static bool
-range_fits_type_p (const value_range_equiv *vr,
+range_fits_type_p (const value_range *vr,
unsigned dest_precision, signop dest_sgn)
{
tree src_type;
@@ -3554,7 +3552,7 @@ range_fits_type_p (const value_range_equiv *vr,
conditional as such, and return TRUE. */
bool
-vr_values::fold_cond (gcond *cond)
+simplify_using_ranges::fold_cond (gcond *cond)
{
/* ?? vrp_folder::fold_predicate_in() is a superset of this. At
some point we should merge all variants of this code. */
@@ -3579,7 +3577,7 @@ vr_values::fold_cond (gcond *cond)
the original conditional. */
bool
-vr_values::simplify_cond_using_ranges_1 (gcond *stmt)
+simplify_using_ranges::simplify_cond_using_ranges_1 (gcond *stmt)
{
tree op0 = gimple_cond_lhs (stmt);
tree op1 = gimple_cond_rhs (stmt);
@@ -3594,7 +3592,7 @@ vr_values::simplify_cond_using_ranges_1 (gcond *stmt)
&& INTEGRAL_TYPE_P (TREE_TYPE (op0))
&& is_gimple_min_invariant (op1))
{
- const value_range_equiv *vr = get_value_range (op0);
+ const value_range *vr = get_value_range (op0);
/* If we have range information for OP0, then we might be
able to simplify this conditional. */
@@ -3667,7 +3665,7 @@ vr_values::simplify_cond_using_ranges_1 (gcond *stmt)
subsequent passes. */
void
-vr_values::simplify_cond_using_ranges_2 (gcond *stmt)
+simplify_cond_using_ranges_2 (vr_values *store, gcond *stmt)
{
tree op0 = gimple_cond_lhs (stmt);
tree op1 = gimple_cond_rhs (stmt);
@@ -3697,7 +3695,7 @@ vr_values::simplify_cond_using_ranges_2 (gcond *stmt)
&& !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (innerop)
&& desired_pro_or_demotion_p (TREE_TYPE (innerop), TREE_TYPE (op0)))
{
- const value_range_equiv *vr = get_value_range (innerop);
+ const value_range *vr = store->get_value_range (innerop);
if (range_int_cst_p (vr)
&& range_fits_type_p (vr,
@@ -3724,10 +3722,10 @@ vr_values::simplify_cond_using_ranges_2 (gcond *stmt)
argument. */
bool
-vr_values::simplify_switch_using_ranges (gswitch *stmt)
+simplify_using_ranges::simplify_switch_using_ranges (gswitch *stmt)
{
tree op = gimple_switch_index (stmt);
- const value_range_equiv *vr = NULL;
+ const value_range *vr = NULL;
bool take_default;
edge e;
edge_iterator ei;
@@ -3905,7 +3903,7 @@ vr_values::simplify_switch_using_ranges (gswitch *stmt)
}
void
-vr_values::cleanup_edges_and_switches (void)
+simplify_using_ranges::cleanup_edges_and_switches (void)
{
int i;
edge e;
@@ -4023,11 +4021,12 @@ simplify_conversion_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
/* Simplify a conversion from integral SSA name to float in STMT. */
bool
-vr_values::simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi,
- gimple *stmt)
+simplify_using_ranges::simplify_float_conversion_using_ranges
+ (gimple_stmt_iterator *gsi,
+ gimple *stmt)
{
tree rhs1 = gimple_assign_rhs1 (stmt);
- const value_range_equiv *vr = get_value_range (rhs1);
+ const value_range *vr = get_value_range (rhs1);
scalar_float_mode fltmode
= SCALAR_FLOAT_TYPE_MODE (TREE_TYPE (gimple_assign_lhs (stmt)));
scalar_int_mode mode;
@@ -4085,8 +4084,9 @@ vr_values::simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi,
/* Simplify an internal fn call using ranges if possible. */
bool
-vr_values::simplify_internal_call_using_ranges (gimple_stmt_iterator *gsi,
- gimple *stmt)
+simplify_using_ranges::simplify_internal_call_using_ranges
+ (gimple_stmt_iterator *gsi,
+ gimple *stmt)
{
enum tree_code subcode;
bool is_ubsan = false;
@@ -4131,7 +4131,7 @@ vr_values::simplify_internal_call_using_ranges (gimple_stmt_iterator *gsi,
return false;
else
type = TREE_TYPE (TREE_TYPE (gimple_call_lhs (stmt)));
- if (!check_for_binary_op_overflow (subcode, type, op0, op1, &ovf)
+ if (!check_for_binary_op_overflow (store, subcode, type, op0, op1, &ovf)
|| (is_ubsan && ovf))
return false;
@@ -4188,9 +4188,9 @@ vr_values::simplify_internal_call_using_ranges (gimple_stmt_iterator *gsi,
two-values when it is true. Return false otherwise. */
bool
-vr_values::two_valued_val_range_p (tree var, tree *a, tree *b)
+simplify_using_ranges::two_valued_val_range_p (tree var, tree *a, tree *b)
{
- const value_range_equiv *vr = get_value_range (var);
+ const value_range *vr = get_value_range (var);
if (vr->varying_p ()
|| vr->undefined_p ()
|| TREE_CODE (vr->min ()) != INTEGER_CST
@@ -4220,10 +4220,22 @@ vr_values::two_valued_val_range_p (tree var, tree *a, tree *b)
return false;
}
+simplify_using_ranges::simplify_using_ranges (vr_values *store)
+ : store (store)
+{
+ to_remove_edges = vNULL;
+ to_update_switch_stmts = vNULL;
+}
+
+simplify_using_ranges::~simplify_using_ranges ()
+{
+ cleanup_edges_and_switches ();
+}
+
/* Simplify STMT using ranges if possible. */
bool
-vr_values::simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
+simplify_using_ranges::simplify (gimple_stmt_iterator *gsi)
{
gimple *stmt = gsi_stmt (*gsi);
if (is_gimple_assign (stmt))
diff --git a/gcc/vr-values.h b/gcc/vr-values.h
index ac25139762a..62a20218c6d 100644
--- a/gcc/vr-values.h
+++ b/gcc/vr-values.h
@@ -22,6 +22,65 @@ along with GCC; see the file COPYING3. If not see
#include "value-range-equiv.h"
+// 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:
+ simplify_using_ranges (class vr_values *);
+ ~simplify_using_ranges ();
+ bool simplify (gimple_stmt_iterator *);
+
+ // ?? These should be cleaned, merged, and made private.
+ tree vrp_evaluate_conditional (tree_code, tree, tree, gimple *);
+ void vrp_visit_cond_stmt (gcond *, edge *);
+ tree vrp_evaluate_conditional_warnv_with_ops (enum tree_code,
+ tree, tree, bool,
+ bool *, bool *);
+
+private:
+ const value_range_equiv *get_value_range (const_tree op);
+ 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 *);
+ bool simplify_bit_ops_using_ranges (gimple_stmt_iterator *, gimple *);
+ bool simplify_min_or_max_using_ranges (gimple_stmt_iterator *, gimple *);
+ bool simplify_cond_using_ranges_1 (gcond *);
+ bool fold_cond (gcond *);
+ bool simplify_switch_using_ranges (gswitch *);
+ bool simplify_float_conversion_using_ranges (gimple_stmt_iterator *,
+ gimple *);
+ bool simplify_internal_call_using_ranges (gimple_stmt_iterator *, gimple *);
+
+ bool two_valued_val_range_p (tree, tree *, tree *);
+ bool op_with_boolean_value_range_p (tree);
+ tree compare_name_with_value (enum tree_code, tree, tree, bool *, bool);
+ tree compare_names (enum tree_code, tree, tree, bool *);
+ const value_range_equiv *get_vr_for_comparison (int, value_range_equiv *);
+ tree vrp_evaluate_conditional_warnv_with_ops_using_ranges (enum tree_code,
+ tree, tree,
+ bool *);
+ void cleanup_edges_and_switches (void);
+
+ /* Vectors of edges that need removing and switch statements that
+ need updating. It is expected that a pass using the simplification
+ routines will, at the end of the pass, clean up the edges and
+ switch statements. The class dtor will try to detect cases
+ that do not follow that expectation. */
+ struct switch_update {
+ gswitch *stmt;
+ tree vec;
+ };
+
+ vec<edge> to_remove_edges;
+ vec<switch_update> to_update_switch_stmts;
+ class vr_values *store;
+};
+
/* The VR_VALUES class holds the current view of range information
for all the SSA_NAMEs in the IL.
@@ -52,7 +111,6 @@ class vr_values
tree op_with_constant_singleton_value_range (tree);
void adjust_range_with_scev (value_range_equiv *, class loop *,
gimple *, tree);
- tree vrp_evaluate_conditional (tree_code, tree, tree, gimple *);
void dump_all_value_ranges (FILE *);
void extract_range_for_var_from_comparison_expr (tree, enum tree_code,
@@ -62,11 +120,6 @@ class vr_values
void extract_range_basic (value_range_equiv *, gimple *);
void extract_range_from_stmt (gimple *, edge *, tree *, value_range_equiv *);
- void vrp_visit_cond_stmt (gcond *, edge *);
-
- void simplify_cond_using_ranges_2 (gcond *);
- bool simplify_stmt_using_ranges (gimple_stmt_iterator *);
-
/* Indicate that propagation through the lattice is complete. */
void set_lattice_propagation_complete (void) { values_propagated = true; }
@@ -76,24 +129,9 @@ class vr_values
void free_value_range (value_range_equiv *vr)
{ vrp_value_range_pool.remove (vr); }
- /* */
- void cleanup_edges_and_switches (void);
-
private:
value_range_equiv *get_lattice_entry (const_tree);
bool vrp_stmt_computes_nonzero (gimple *);
- bool op_with_boolean_value_range_p (tree);
- bool check_for_binary_op_overflow (enum tree_code, tree, tree, tree, bool *);
- const value_range_equiv *get_vr_for_comparison (int, value_range_equiv *);
- tree compare_name_with_value (enum tree_code, tree, tree, bool *, bool);
- tree compare_names (enum tree_code, tree, tree, bool *);
- bool two_valued_val_range_p (tree, tree *, tree *);
- tree vrp_evaluate_conditional_warnv_with_ops_using_ranges (enum tree_code,
- tree, tree,
- bool *);
- tree vrp_evaluate_conditional_warnv_with_ops (enum tree_code,
- tree, tree, bool,
- bool *, bool *);
void extract_range_from_assignment (value_range_equiv *, gassign *);
void extract_range_from_assert (value_range_equiv *, tree);
void extract_range_from_ssa_name (value_range_equiv *, tree);
@@ -106,17 +144,6 @@ class vr_values
tree, tree, tree);
void vrp_visit_assignment_or_call (gimple*, tree *, value_range_equiv *);
void vrp_visit_switch_stmt (gswitch *, edge *);
- 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 *);
- bool simplify_bit_ops_using_ranges (gimple_stmt_iterator *, gimple *);
- bool simplify_min_or_max_using_ranges (gimple_stmt_iterator *, gimple *);
- bool simplify_cond_using_ranges_1 (gcond *);
- bool fold_cond (gcond *);
- bool simplify_switch_using_ranges (gswitch *);
- bool simplify_float_conversion_using_ranges (gimple_stmt_iterator *,
- gimple *);
- bool simplify_internal_call_using_ranges (gimple_stmt_iterator *, gimple *);
/* Allocation pools for value_range objects. */
object_allocator<value_range_equiv> vrp_value_range_pool;
@@ -136,20 +163,18 @@ class vr_values
number of executable edges we saw the last time we visited the
node. */
int *vr_phi_edge_counts;
-
- /* Vectors of edges that need removing and switch statements that
- need updating. It is expected that a pass using the simplification
- routines will, at the end of the pass, clean up the edges and
- switch statements. The class dtor will try to detect cases
- that do not follow that expectation. */
- struct switch_update {
- gswitch *stmt;
- tree vec;
- };
-
- vec<edge> to_remove_edges;
- vec<switch_update> to_update_switch_stmts;
+ simplify_using_ranges simplifier;
};
+inline const value_range_equiv *
+simplify_using_ranges::get_value_range (const_tree op)
+{
+ return store->get_value_range (op);
+}
+
extern tree get_output_for_vrp (gimple *);
+
+// FIXME: Move this to tree-vrp.c.
+void simplify_cond_using_ranges_2 (class vr_values *, gcond *);
+
#endif /* GCC_VR_VALUES_H */