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:
parent
aed3ab253d
commit
fc36b97af0
6 changed files with 190 additions and 143 deletions
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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 ();
|
||||
|
|
154
gcc/vr-values.c
154
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))
|
||||
|
|
115
gcc/vr-values.h
115
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 */
|
||||
|
|
Loading…
Add table
Reference in a new issue