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.
This commit is contained in:
Aldy Hernandez 2020-06-18 10:37:14 +02:00
parent aed3ab253d
commit fc36b97af0
6 changed files with 190 additions and 143 deletions

View file

@ -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.

View file

@ -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

View file

@ -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))

View file

@ -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 ();

View file

@ -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))

View file

@ -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 */