#include "tree-cfgcleanup.h"
#include "stringpool.h"
#include "attribs.h"
+#include "vr-values.h"
#define VR_INITIALIZER { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL }
-/* Allocation pools for tree-vrp allocations. */
-static object_allocator<value_range> vrp_value_range_pool ("Tree VRP value ranges");
-static bitmap_obstack vrp_equiv_obstack;
-
/* Set of SSA names found live during the RPO traversal of the function
for still active basic-blocks. */
static sbitmap *live;
/* Local functions. */
static int compare_values (tree val1, tree val2);
static int compare_values_warnv (tree val1, tree val2, bool *);
-static tree vrp_evaluate_conditional_warnv_with_ops (enum tree_code,
- tree, tree, bool, bool *,
- bool *);
struct assert_info
{
ASSERT_EXPRs for SSA name N_I should be inserted. */
static assert_locus **asserts_for;
-/* Value range array. After propagation, VR_VALUE[I] holds the range
- of values that SSA name N_I may take. */
-static unsigned num_vr_values;
-static value_range **vr_value;
-static bool values_propagated;
-
-/* For a PHI node which sets SSA name N_I, VR_COUNTS[I] holds the
- number of executable edges we saw the last time we visited the
- node. */
-static int *vr_phi_edge_counts;
-
struct switch_update {
gswitch *stmt;
tree vec;
If we have no values ranges recorded (ie, VRP is not running), then
return NULL. Otherwise create an empty range if none existed for VAR. */
-static value_range *
-get_value_range (const_tree var)
+value_range *
+vr_values::get_value_range (const_tree var)
{
static const value_range vr_const_varying
= { VR_VARYING, NULL_TREE, NULL_TREE, NULL };
/* Set value-ranges of all SSA names defined by STMT to varying. */
-static void
-set_defs_to_varying (gimple *stmt)
+void
+vr_values::set_defs_to_varying (gimple *stmt)
{
ssa_op_iter i;
tree def;
this function. Do not call update_value_range when NEW_VR
is the range object associated with another SSA name. */
-static inline bool
-update_value_range (const_tree var, value_range *new_vr)
+bool
+vr_values::update_value_range (const_tree var, value_range *new_vr)
{
value_range *old_vr;
bool is_new;
/* Add VAR and VAR's equivalence set to EQUIV. This is the central
point where equivalence processing can be turned on/off. */
-static void
-add_equivalence (bitmap *equiv, const_tree var)
+void
+vr_values::add_equivalence (bitmap *equiv, const_tree var)
{
unsigned ver = SSA_NAME_VERSION (var);
value_range *vr = get_value_range (var);
/* Like tree_expr_nonzero_p, but this function uses value ranges
obtained so far. */
-static bool
-vrp_stmt_computes_nonzero (gimple *stmt)
+bool
+vr_values::vrp_stmt_computes_nonzero (gimple *stmt)
{
if (gimple_stmt_nonzero_p (stmt))
return true;
otherwise return NULL_TREE. This returns OP itself if OP is a
constant. */
-static tree
-op_with_constant_singleton_value_range (tree op)
+tree
+vr_values::op_with_constant_singleton_value_range (tree op)
{
if (is_gimple_min_invariant (op))
return op;
/* Return true if op is in a boolean [0, 1] value-range. */
-static bool
-op_with_boolean_value_range_p (tree op)
+bool
+vr_values::op_with_boolean_value_range_p (tree op)
{
value_range *vr;
/* Extract value range information for VAR when (OP COND_CODE LIMIT) is
true and store it in *VR_P. */
-static void
-extract_range_for_var_from_comparison_expr (tree var, enum tree_code cond_code,
- tree op, tree limit,
- value_range *vr_p)
+void
+vr_values::extract_range_for_var_from_comparison_expr (tree var,
+ enum tree_code cond_code,
+ tree op, tree limit,
+ value_range *vr_p)
{
tree min, max, type;
value_range *limit_vr;
/* Extract value range information from an ASSERT_EXPR EXPR and store
it in *VR_P. */
-static void
-extract_range_from_assert (value_range *vr_p, tree expr)
+void
+vr_values::extract_range_from_assert (value_range *vr_p, tree expr)
{
tree var = ASSERT_EXPR_VAR (expr);
tree cond = ASSERT_EXPR_COND (expr);
Even if y_5 is deemed VARYING, we can determine that x_3 > y_5 is
always false. */
-static void
-extract_range_from_ssa_name (value_range *vr, tree var)
+void
+vr_values::extract_range_from_ssa_name (value_range *vr, tree var)
{
value_range *var_vr = get_value_range (var);
the ranges of each of its operands with resulting type EXPR_TYPE.
The resulting range is stored in *VR. */
-static void
-extract_range_from_binary_expr (value_range *vr,
- enum tree_code code,
- tree expr_type, tree op0, tree op1)
+void
+vr_values::extract_range_from_binary_expr (value_range *vr,
+ enum tree_code code,
+ tree expr_type, tree op0, tree op1)
{
value_range vr0 = VR_INITIALIZER;
value_range vr1 = VR_INITIALIZER;
the range of its operand with resulting type TYPE.
The resulting range is stored in *VR. */
-static void
-extract_range_from_unary_expr (value_range *vr, enum tree_code code,
- tree type, tree op0)
+void
+vr_values::extract_range_from_unary_expr (value_range *vr, enum tree_code code,
+ tree type, tree op0)
{
value_range vr0 = VR_INITIALIZER;
else
set_value_range_to_varying (&vr0);
- extract_range_from_unary_expr (vr, code, type, &vr0, TREE_TYPE (op0));
+ ::extract_range_from_unary_expr (vr, code, type, &vr0, TREE_TYPE (op0));
}
/* Extract range information from a conditional expression STMT based on
the ranges of each of its operands and the expression code. */
-static void
-extract_range_from_cond_expr (value_range *vr, gassign *stmt)
+void
+vr_values::extract_range_from_cond_expr (value_range *vr, gassign *stmt)
{
tree op0, op1;
value_range vr0 = VR_INITIALIZER;
/* Extract range information from a comparison expression EXPR based
on the range of its operand and the expression code. */
-static void
-extract_range_from_comparison (value_range *vr, enum tree_code code,
- tree type, tree op0, tree op1)
+void
+vr_values::extract_range_from_comparison (value_range *vr, enum tree_code code,
+ tree type, tree op0, tree op1)
{
bool sop;
tree val;
always overflow. Set *OVF to true if it is known to always
overflow. */
-static bool
-check_for_binary_op_overflow (enum tree_code subcode, tree type,
- tree op0, tree op1, bool *ovf)
+bool
+vr_values::check_for_binary_op_overflow (enum tree_code subcode, tree type,
+ tree op0, tree op1, bool *ovf)
{
value_range vr0 = VR_INITIALIZER;
value_range vr1 = VR_INITIALIZER;
primarily on generic routines in fold in conjunction with range data.
Store the result in *VR */
-static void
-extract_range_basic (value_range *vr, gimple *stmt)
+void
+vr_values::extract_range_basic (value_range *vr, gimple *stmt)
{
bool sop;
tree type = gimple_expr_type (stmt);
/* Try to compute a useful range out of assignment STMT and store it
in *VR. */
-static void
-extract_range_from_assignment (value_range *vr, gassign *stmt)
+void
+vr_values::extract_range_from_assignment (value_range *vr, gassign *stmt)
{
enum tree_code code = gimple_assign_rhs_code (stmt);
would be profitable to adjust VR using scalar evolution information
for VAR. If so, update VR with the new limits. */
-static void
-adjust_range_with_scev (value_range *vr, struct loop *loop,
- gimple *stmt, tree var)
+void
+vr_values::adjust_range_with_scev (value_range *vr, struct loop *loop,
+ gimple *stmt, tree var)
{
tree init, step, chrec, tmin, tmax, min, max, type, tem;
enum ev_direction dir;
void dump_value_range (FILE *, const value_range *);
void debug_value_range (value_range *);
void dump_all_value_ranges (FILE *);
-void debug_all_value_ranges (void);
void dump_vr_equiv (FILE *, bitmap);
void debug_vr_equiv (bitmap);
/* Dump value ranges of all SSA_NAMEs to FILE. */
void
-dump_all_value_ranges (FILE *file)
+vr_values::dump_all_value_ranges (FILE *file)
{
size_t i;
fprintf (file, "\n");
}
-
-/* Dump all value ranges to stderr. */
-
-DEBUG_FUNCTION void
-debug_all_value_ranges (void)
-{
- dump_all_value_ranges (stderr);
-}
-
-
/* Given a COND_EXPR COND of the form 'V OP W', and an SSA name V,
create a new SSA name N and return the assertion assignment
'N = ASSERT_EXPR <V, V OP W>'. */
public:
enum ssa_prop_result visit_stmt (gimple *, edge *, tree *) FINAL OVERRIDE;
enum ssa_prop_result visit_phi (gphi *) FINAL OVERRIDE;
+
+ void vrp_initialize (void);
+ void vrp_finalize (bool);
+ void check_all_array_refs (void);
+ void check_array_ref (location_t, tree, bool);
+ void search_for_addr_array (tree, location_t);
+
+ class vr_values vr_values;
+ /* Temporary delegator to minimize code churn. */
+ value_range *get_value_range (const_tree op)
+ { return vr_values.get_value_range (op); }
+ void set_defs_to_varying (gimple *stmt)
+ { return vr_values.set_defs_to_varying (stmt); }
+ void extract_range_from_stmt (gimple *stmt, edge *taken_edge_p,
+ tree *output_p, value_range *vr)
+ { vr_values.extract_range_from_stmt (stmt, taken_edge_p, output_p, vr); }
+ bool update_value_range (const_tree op, value_range *vr)
+ { return vr_values.update_value_range (op, vr); }
+ void extract_range_basic (value_range *vr, gimple *stmt)
+ { vr_values.extract_range_basic (vr, stmt); }
+ void extract_range_from_phi_node (gphi *phi, value_range *vr)
+ { vr_values.extract_range_from_phi_node (phi, vr); }
};
/* Checks one ARRAY_REF in REF, located at LOCUS. Ignores flexible arrays
non-overlapping with valid range.
IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside a ADDR_EXPR. */
-static void
-check_array_ref (location_t location, tree ref, bool ignore_off_by_one)
+void
+vrp_prop::check_array_ref (location_t location, tree ref,
+ bool ignore_off_by_one)
{
value_range *vr = NULL;
tree low_sub, up_sub;
/* Searches if the expr T, located at LOCATION computes
address of an ARRAY_REF, and call check_array_ref on it. */
-static void
-search_for_addr_array (tree t, location_t location)
+void
+vrp_prop::search_for_addr_array (tree t, location_t location)
{
/* Check each ARRAY_REFs in the reference chain. */
do
*walk_subtree = TRUE;
+ vrp_prop *vrp_prop = (class vrp_prop *)wi->info;
if (TREE_CODE (t) == ARRAY_REF)
- check_array_ref (location, t, false /*ignore_off_by_one*/);
+ vrp_prop->check_array_ref (location, t, false /*ignore_off_by_one*/);
else if (TREE_CODE (t) == ADDR_EXPR)
{
- search_for_addr_array (t, location);
+ vrp_prop->search_for_addr_array (t, location);
*walk_subtree = FALSE;
}
/* Walk over all statements of all reachable BBs and call check_array_bounds
on them. */
-static void
-check_all_array_refs (void)
+void
+vrp_prop::check_all_array_refs ()
{
basic_block bb;
gimple_stmt_iterator si;
memset (&wi, 0, sizeof (wi));
+ wi.info = this;
+
walk_gimple_op (gsi_stmt (si),
check_array_bounds,
&wi);
/* Initialize VRP lattice. */
-static void
-vrp_initialize_lattice ()
+vr_values::vr_values () : vrp_value_range_pool ("Tree VRP value ranges")
{
values_propagated = false;
num_vr_values = num_ssa_names;
/* Initialization required by ssa_propagate engine. */
-static void
-vrp_initialize ()
+void
+vrp_prop::vrp_initialize ()
{
basic_block bb;
}
}
+/* A hack. */
+static class vr_values *x_vr_values;
+
/* Return the singleton value-range for NAME or NAME. */
static inline tree
{
if (TREE_CODE (name) == SSA_NAME)
{
- value_range *vr = get_value_range (name);
+ value_range *vr = x_vr_values->get_value_range (name);
if (vr->type == VR_RANGE
&& (TREE_CODE (vr->min) == SSA_NAME
|| is_gimple_min_invariant (vr->min))
if (!gimple_nop_p (def_stmt)
&& prop_simulate_again_p (def_stmt))
return NULL_TREE;
- value_range *vr = get_value_range (name);
+ value_range *vr = x_vr_values->get_value_range (name);
if (range_int_cst_singleton_p (vr))
return vr->min;
}
/* Visit assignment STMT. If it produces an interesting range, record
the range in VR and set LHS to OUTPUT_P. */
-static void
-vrp_visit_assignment_or_call (gimple *stmt, tree *output_p, value_range *vr)
+void
+vr_values::vrp_visit_assignment_or_call (gimple *stmt, tree *output_p,
+ value_range *vr)
{
tree lhs;
enum gimple_code code = gimple_code (stmt);
*output_p = lhs;
/* Try folding the statement to a constant first. */
+ x_vr_values = this;
tree tem = gimple_fold_stmt_to_constant_1 (stmt, vrp_valueize,
vrp_valueize_1);
+ x_vr_values = NULL;
if (tem)
{
if (TREE_CODE (tem) == SSA_NAME
or a symbolic range containing the SSA_NAME only if the value range
is varying or undefined. */
-static inline value_range
-get_vr_for_comparison (int i)
+value_range
+vr_values::get_vr_for_comparison (int i)
{
value_range vr = *get_value_range (ssa_name (i));
compare_range_with_value, including the setting of
*STRICT_OVERFLOW_P. */
-static tree
-compare_name_with_value (enum tree_code comp, tree var, tree val,
- bool *strict_overflow_p, bool use_equiv_p)
+tree
+vr_values::compare_name_with_value (enum tree_code comp, tree var, tree val,
+ bool *strict_overflow_p, bool use_equiv_p)
{
bitmap_iterator bi;
unsigned i;
whether we relied on undefined signed overflow in the comparison. */
-static tree
-compare_names (enum tree_code comp, tree n1, tree n2,
- bool *strict_overflow_p)
+tree
+vr_values::compare_names (enum tree_code comp, tree n1, tree n2,
+ bool *strict_overflow_p)
{
tree t, retval;
bitmap e1, e2;
/* Helper function for vrp_evaluate_conditional_warnv & other
optimizers. */
-static tree
-vrp_evaluate_conditional_warnv_with_ops_using_ranges (enum tree_code code,
- tree op0, tree op1,
- bool * strict_overflow_p)
+tree
+vr_values::vrp_evaluate_conditional_warnv_with_ops_using_ranges
+ (enum tree_code code, tree op0, tree op1, bool * strict_overflow_p)
{
value_range *vr0, *vr1;
/* Helper function for vrp_evaluate_conditional_warnv. */
-static tree
-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
+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)
{
tree ret;
if (only_ranges)
based on undefined signed overflow, issue a warning if
appropriate. */
-static tree
-vrp_evaluate_conditional (tree_code code, tree op0, tree op1, gimple *stmt)
+tree
+vr_values::vrp_evaluate_conditional (tree_code code, tree op0,
+ tree op1, gimple *stmt)
{
bool sop;
tree ret;
will be taken out of STMT's basic block, record it in
*TAKEN_EDGE_P. Otherwise, set *TAKEN_EDGE_P to NULL. */
-static void
-vrp_visit_cond_stmt (gcond *stmt, edge *taken_edge_p)
+void
+vr_values::vrp_visit_cond_stmt (gcond *stmt, edge *taken_edge_p)
{
tree val;
will be taken out of STMT's basic block, record it in
*TAKEN_EDGE_P. Otherwise, *TAKEN_EDGE_P set to NULL. */
-static void
-vrp_visit_switch_stmt (gswitch *stmt, edge *taken_edge_p)
+void
+vr_values::vrp_visit_switch_stmt (gswitch *stmt, edge *taken_edge_p)
{
tree op, val;
value_range *vr;
If STMT is a conditional branch and we can determine its truth
value, the taken edge is recorded in *TAKEN_EDGE_P. */
-static void
-extract_range_from_stmt (gimple *stmt, edge *taken_edge_p,
- tree *output_p, value_range *vr)
+void
+vr_values::extract_range_from_stmt (gimple *stmt, edge *taken_edge_p,
+ tree *output_p, value_range *vr)
{
if (dump_file && (dump_flags & TDF_DETAILS))
edges. If a valid value range can be derived from all the incoming
value ranges, set a new range in VR_RESULT. */
-static void
-extract_range_from_phi_node (gphi *phi, value_range *vr_result)
+void
+vr_values::extract_range_from_phi_node (gphi *phi, value_range *vr_result)
{
size_t i;
tree lhs = PHI_RESULT (phi);
/* Simplify boolean operations if the source is known
to be already a boolean. */
-static bool
-simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
+bool
+vr_values::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;
[-op1min + 1, op1min - 1] for signed and [0, op1min - 1] for unsigned
modulo. */
-static bool
-simplify_div_or_mod_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
+bool
+vr_values::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;
/* Simplify a min or max if the ranges of the two operands are
disjoint. Return true if we do simplify. */
-static bool
-simplify_min_or_max_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
+bool
+vr_values::simplify_min_or_max_using_ranges (gimple_stmt_iterator *gsi,
+ gimple *stmt)
{
tree op0 = gimple_assign_rhs1 (stmt);
tree op1 = gimple_assign_rhs2 (stmt);
ABS_EXPR. If the operand is <= 0, then simplify the
ABS_EXPR into a NEGATE_EXPR. */
-static bool
-simplify_abs_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
+bool
+vr_values::simplify_abs_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
{
tree op = gimple_assign_rhs1 (stmt);
value_range *vr = get_value_range (op);
set by | are already known to be one from VR, the bit
operation is redundant. */
-static bool
-simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
+bool
+vr_values::simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi,
+ gimple *stmt)
{
tree op0 = gimple_assign_rhs1 (stmt);
tree op1 = gimple_assign_rhs2 (stmt);
test if the range information indicates only one value can satisfy
the original conditional. */
-static bool
-simplify_cond_using_ranges_1 (gcond *stmt)
+bool
+vr_values::simplify_cond_using_ranges_1 (gcond *stmt)
{
tree op0 = gimple_cond_lhs (stmt);
tree op1 = gimple_cond_rhs (stmt);
of the type conversion. Doing so makes the conversion dead which helps
subsequent passes. */
-static void
-simplify_cond_using_ranges_2 (gcond *stmt)
+void
+vr_values::simplify_cond_using_ranges_2 (gcond *stmt)
{
tree op0 = gimple_cond_lhs (stmt);
tree op1 = gimple_cond_rhs (stmt);
/* Simplify a switch statement using the value range of the switch
argument. */
-static bool
-simplify_switch_using_ranges (gswitch *stmt)
+bool
+vr_values::simplify_switch_using_ranges (gswitch *stmt)
{
tree op = gimple_switch_index (stmt);
value_range *vr = NULL;
/* Simplify a conversion from integral SSA name to float in STMT. */
-static bool
-simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi,
- gimple *stmt)
+bool
+vr_values::simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi,
+ gimple *stmt)
{
tree rhs1 = gimple_assign_rhs1 (stmt);
value_range *vr = get_value_range (rhs1);
/* Simplify an internal fn call using ranges if possible. */
-static bool
-simplify_internal_call_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
+bool
+vr_values::simplify_internal_call_using_ranges (gimple_stmt_iterator *gsi,
+ gimple *stmt)
{
enum tree_code subcode;
bool is_ubsan = false;
/* Return true if VAR is a two-valued variable. Set a and b with the
two-values when it is true. Return false otherwise. */
-static bool
-two_valued_val_range_p (tree var, tree *a, tree *b)
+bool
+vr_values::two_valued_val_range_p (tree var, tree *a, tree *b)
{
value_range *vr = get_value_range (var);
if ((vr->type != VR_RANGE
/* Simplify STMT using ranges if possible. */
-static bool
-simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
+bool
+vr_values::simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
{
gimple *stmt = gsi_stmt (*gsi);
if (is_gimple_assign (stmt))
public:
tree get_value (tree) FINAL OVERRIDE;
bool fold_stmt (gimple_stmt_iterator *) FINAL OVERRIDE;
+ bool fold_predicate_in (gimple_stmt_iterator *);
+
+ class vr_values *vr_values;
+
+ /* Delegators. */
+ tree vrp_evaluate_conditional (tree_code code, tree op0,
+ tree op1, gimple *stmt)
+ { return vr_values->vrp_evaluate_conditional (code, op0, op1, stmt); }
+ bool simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
+ { return vr_values->simplify_stmt_using_ranges (gsi); }
+ tree op_with_constant_singleton_value_range (tree op)
+ { return vr_values->op_with_constant_singleton_value_range (op); }
};
/* If the statement pointed by SI has a predicate whose value can be
computed using the value range information computed by VRP, compute
its value and return true. Otherwise, return false. */
-static bool
-fold_predicate_in (gimple_stmt_iterator *si)
+bool
+vrp_folder::fold_predicate_in (gimple_stmt_iterator *si)
{
bool assignment_p = false;
tree val;
if (cached_lhs && is_gimple_min_invariant (cached_lhs))
return cached_lhs;
+ vr_values *vr_values = x_vr_values;
if (gcond *cond_stmt = dyn_cast <gcond *> (stmt))
{
tree op0 = gimple_cond_lhs (cond_stmt);
tree op1 = gimple_cond_rhs (cond_stmt);
op1 = lhs_of_dominating_assert (op1, bb, stmt);
- return vrp_evaluate_conditional (gimple_cond_code (cond_stmt),
- op0, op1, within_stmt);
+ return vr_values->vrp_evaluate_conditional (gimple_cond_code (cond_stmt),
+ op0, op1, within_stmt);
}
/* We simplify a switch statement by trying to determine which case label
op = lhs_of_dominating_assert (op, bb, stmt);
- value_range *vr = get_value_range (op);
+ value_range *vr = vr_values->get_value_range (op);
if ((vr->type != VR_RANGE && vr->type != VR_ANTI_RANGE)
|| symbolic_range_p (vr))
return NULL_TREE;
&& (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
|| POINTER_TYPE_P (TREE_TYPE (lhs))))
{
- extract_range_from_assignment (&new_vr, assign_stmt);
+ vr_values->extract_range_from_assignment (&new_vr, assign_stmt);
if (range_int_cst_singleton_p (&new_vr))
return new_vr.min;
}
virtual edge before_dom_children (basic_block);
virtual void after_dom_children (basic_block);
+ class vr_values *vr_values;
+
private:
class const_and_copies *m_const_and_copies;
class avail_exprs_stack *m_avail_exprs_stack;
gcond *m_dummy_cond;
+
};
/* Called before processing dominator children of BB. We want to look
integer_zero_node, integer_zero_node,
NULL, NULL);
+ x_vr_values = vr_values;
thread_outgoing_edges (bb, m_dummy_cond, m_const_and_copies,
m_avail_exprs_stack,
simplify_stmt_for_jump_threading);
+ x_vr_values = NULL;
m_avail_exprs_stack->pop_to_marker ();
m_const_and_copies->pop_to_marker ();
for later realization. */
static void
-identify_jump_threads (void)
+identify_jump_threads (class vr_values *vr_values)
{
int i;
edge e;
= new class avail_exprs_stack (avail_exprs);
vrp_dom_walker walker (CDI_DOMINATORS, equiv_stack, avail_exprs_stack);
+ walker.vr_values = vr_values;
walker.walk (cfun->cfg->x_entry_block_ptr);
/* Clear EDGE_IGNORE. */
/* Free VRP lattice. */
-static void
-vrp_free_lattice ()
+vr_values::~vr_values ()
{
/* Free allocated memory. */
free (vr_value);
/* Traverse all the blocks folding conditionals with known ranges. */
-static void
-vrp_finalize (bool warn_array_bounds_p)
+void
+vrp_prop::vrp_finalize (bool warn_array_bounds_p)
{
size_t i;
- values_propagated = true;
+ vr_values.values_propagated = true;
if (dump_file)
{
fprintf (dump_file, "\nValue ranges after VRP:\n\n");
- dump_all_value_ranges (dump_file);
+ vr_values.dump_all_value_ranges (dump_file);
fprintf (dump_file, "\n");
}
/* Set value range to non pointer SSA_NAMEs. */
- for (i = 0; i < num_vr_values; i++)
- if (vr_value[i])
- {
- tree name = ssa_name (i);
+ for (i = 0; i < num_ssa_names; i++)
+ {
+ tree name = ssa_name (i);
+ if (!name)
+ continue;
- if (!name
- || (vr_value[i]->type == VR_VARYING)
- || (vr_value[i]->type == VR_UNDEFINED)
- || (TREE_CODE (vr_value[i]->min) != INTEGER_CST)
- || (TREE_CODE (vr_value[i]->max) != INTEGER_CST))
- continue;
+ value_range *vr = get_value_range (name);
+ if (!name
+ || (vr->type == VR_VARYING)
+ || (vr->type == VR_UNDEFINED)
+ || (TREE_CODE (vr->min) != INTEGER_CST)
+ || (TREE_CODE (vr->max) != INTEGER_CST))
+ continue;
- if (POINTER_TYPE_P (TREE_TYPE (name))
- && ((vr_value[i]->type == VR_RANGE
- && range_includes_zero_p (vr_value[i]->min,
- vr_value[i]->max) == 0)
- || (vr_value[i]->type == VR_ANTI_RANGE
- && range_includes_zero_p (vr_value[i]->min,
- vr_value[i]->max) == 1)))
- set_ptr_nonnull (name);
- else if (!POINTER_TYPE_P (TREE_TYPE (name)))
- set_range_info (name, vr_value[i]->type,
- wi::to_wide (vr_value[i]->min),
- wi::to_wide (vr_value[i]->max));
- }
+ if (POINTER_TYPE_P (TREE_TYPE (name))
+ && ((vr->type == VR_RANGE
+ && range_includes_zero_p (vr->min, vr->max) == 0)
+ || (vr->type == VR_ANTI_RANGE
+ && range_includes_zero_p (vr->min, vr->max) == 1)))
+ set_ptr_nonnull (name);
+ else if (!POINTER_TYPE_P (TREE_TYPE (name)))
+ set_range_info (name, vr->type,
+ wi::to_wide (vr->min),
+ wi::to_wide (vr->max));
+ }
class vrp_folder vrp_folder;
+ vrp_folder.vr_values = &vr_values;
vrp_folder.substitute_and_fold ();
if (warn_array_bounds && warn_array_bounds_p)
bitmap need_eh_cleanup;
auto_vec<gimple *> stmts_to_fixup;
auto_vec<gimple *> stmts_to_remove;
+
+ class vr_values vr_values;
+
+ /* Temporary delegators. */
+ value_range *get_value_range (const_tree op)
+ { return vr_values.get_value_range (op); }
+ bool update_value_range (const_tree op, value_range *vr)
+ { return vr_values.update_value_range (op, vr); }
+ void extract_range_from_phi_node (gphi *phi, value_range *vr)
+ { vr_values.extract_range_from_phi_node (phi, vr); }
+ void extract_range_for_var_from_comparison_expr (tree var,
+ enum tree_code cond_code,
+ tree op, tree limit,
+ value_range *vr_p)
+ { vr_values.extract_range_for_var_from_comparison_expr (var, cond_code,
+ op, limit, vr_p); }
+ void adjust_range_with_scev (value_range *vr, struct loop *loop,
+ gimple *stmt, tree var)
+ { vr_values.adjust_range_with_scev (vr, loop, stmt, var); }
+ tree op_with_constant_singleton_value_range (tree op)
+ { return vr_values.op_with_constant_singleton_value_range (op); }
+ void extract_range_from_stmt (gimple *stmt, edge *taken_edge_p,
+ tree *output_p, value_range *vr)
+ { vr_values.extract_range_from_stmt (stmt, taken_edge_p, output_p, vr); }
+ void set_defs_to_varying (gimple *stmt)
+ { return vr_values.set_defs_to_varying (stmt); }
+ void set_vr_value (tree name, value_range *vr)
+ { vr_values.set_vr_value (name, vr); }
+ void simplify_cond_using_ranges_2 (gcond *stmt)
+ { vr_values.simplify_cond_using_ranges_2 (stmt); }
+ void vrp_visit_cond_stmt (gcond *cond, edge *e)
+ { vr_values.vrp_visit_cond_stmt (cond, e); }
};
/* Find new range for NAME such that (OP CODE LIMIT) is true. */
&& vrp_operand_equal_p (old_vr->min, vr.min)
&& vrp_operand_equal_p (old_vr->max, vr.max))
return NULL;
- value_range *new_vr = vrp_value_range_pool.allocate ();
+ value_range *new_vr = vr_values.vrp_value_range_pool.allocate ();
*new_vr = vr;
return new_vr;
}
/* Try folding stmts with the VR discovered. */
class vrp_folder vrp_folder;
+ vrp_folder.vr_values = &vr_values;
bool did_replace = vrp_folder.replace_uses_in (stmt);
if (fold_stmt (&gsi, follow_single_use_edges)
|| did_replace)
stack.pop ();
}
+void
+vr_values::set_vr_value (tree var, value_range *vr)
+{
+ if (SSA_NAME_VERSION (var) >= num_vr_values)
+ return;
+ vr_value[SSA_NAME_VERSION (var)] = vr;
+}
+
/* Push the Value Range of VAR to the stack and update it with new VR. */
void
evrp_dom_walker::push_value_range (tree var, value_range *vr)
{
- if (SSA_NAME_VERSION (var) >= num_vr_values)
- return;
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "pushing new range for ");
fprintf (dump_file, "\n");
}
stack.safe_push (std::make_pair (var, get_value_range (var)));
- vr_value[SSA_NAME_VERSION (var)] = vr;
+ set_vr_value (var, vr);
}
/* Pop the Value Range from the vrp_stack and update VAR with it. */
dump_value_range (dump_file, vr);
fprintf (dump_file, "\n");
}
- vr_value[SSA_NAME_VERSION (var)] = vr;
+ set_vr_value (var, vr);
stack.pop ();
return vr;
}
FOR_EACH_EDGE (e, ei, bb->preds)
e->flags |= EDGE_EXECUTABLE;
}
- vrp_initialize_lattice ();
/* Walk stmts in dominance order and propagate VRP. */
evrp_dom_walker walker;
if (dump_file)
{
fprintf (dump_file, "\nValue ranges after Early VRP:\n\n");
- dump_all_value_ranges (dump_file);
+ walker.vr_values.dump_all_value_ranges (dump_file);
fprintf (dump_file, "\n");
}
fixup_noreturn_call (stmt);
}
- vrp_free_lattice ();
scev_finalize ();
loop_optimizer_finalize ();
return 0;
/* For visiting PHI nodes we need EDGE_DFS_BACK computed. */
mark_dfs_back_edges ();
- vrp_initialize_lattice ();
- vrp_initialize ();
class vrp_prop vrp_prop;
+ vrp_prop.vrp_initialize ();
vrp_prop.ssa_propagate ();
- vrp_finalize (warn_array_bounds_p);
+ vrp_prop.vrp_finalize (warn_array_bounds_p);
/* We must identify jump threading opportunities before we release
the datastructures built by VRP. */
- identify_jump_threads ();
+ identify_jump_threads (&vrp_prop.vr_values);
/* A comparison of an SSA_NAME against a constant where the SSA_NAME
was set by a type conversion can often be rewritten to use the
{
gimple *last = last_stmt (bb);
if (last && gimple_code (last) == GIMPLE_COND)
- simplify_cond_using_ranges_2 (as_a <gcond *> (last));
+ vrp_prop.vr_values.simplify_cond_using_ranges_2 (as_a <gcond *> (last));
}
- vrp_free_lattice ();
-
free_numbers_of_iterations_estimates (cfun);
/* ASSERT_EXPRs must be removed before finalizing jump threads