Commit 89759031 by Jeff Law Committed by Jeff Law

vr-values.h: New file with vr_values class.

	* vr-values.h: New file with vr_values class.
	* tree-vrp.c: Include vr-values.h
	(vrp_value_range_pool, vrp_equiv_obstack, num_vr_values): Move static
	data objects into the vr_values class.
	(vr_value, values_propagated, vr_phi_edge_counts): Likewise.
	(get_value_range): Make it a member function within vr_values class.
	(set_defs_to_varying, update_value_range, add_equivalence): Likewise.
	(vrp_stmt_computes_nonzero_p, op_with_boolean_value_range_p): Likewise.
	(op_with_constant_singleton_value_range): Likewise.
	(extract_range_for_var_from_comparison_expr): Likewise.
	(extract_range_from_assert, extract_range_from_ssa_name): Likewise.
	(extract_range_from_binary_expr): Likewise.
	(extract_range_from_unary_expr): Likewise.
	(extract_range_from_cond_expr, extrat_range_from_comparison): Likewise.
	(check_for_binary_op_overflow, extract_range_basic): Likewise.
	(extract_range_from_assignment, adjust_range_with_scev): Likewise.
	(dump_all_value_ranges, get_vr_for_comparison): Likewise.
	(compare_name_with_value, compare_names): Likewise.
	(vrp_evaluate_conditional_warnv_with_ops_using_ranges): Likewise.
	(vrp_evaluate_conditional_warnv_with_ops): Likewise.  Remove prototype.
	(vrp_evaluate_conditional, vrp_visit_cond_stmt): Likewise.
	(vrp_visit_switch_stmt, extract_range_from_stmt): Likewise.
	(extract_range_from_phi_node): Likewise.
	(simplify_truth_ops_using_ranges): Likewise.
	(simplify_div_or_mod_using_ranges): Likewise.
	(simplify_min_or_max_using_ranges, simplify_abs_using_ranges): Likewise.
	(simplify_bit_ops_using_ranges, simplify_cond_using_ranges_1): Likewise.
	(simplify_cond_using_ranges_2, simplify_switch_using_ranges): Likewise.
	(simplify_float_conversion_using_ranges): Likewise.
	(simplify_internal_call_using_ranges): Likewise.
	(two_valued_val_range_p, simplify_stmt_using_ranges): Likewise.
	(vrp_visit_assignment_or_call): Likewise.  Smuggle class instance
	poitner via x_vr_values for calls into gimple folder.
	(vrp_initialize_lattice): Make this the vr_values ctor.
	(vrp_free_lattice): Make this the vr_values dtor.
	(set_vr_value): New function.
	(class vrp_prop): Add vr_values data member.  Add various member
	functions as well as member functions that delegate to vr_values.
	(check_array_ref): Make a member function within vrp_prop class.
	(search_for_addr_array, vrp_initialize): Likewise.
	(vrp_finalize): Likewise.  Revamp to avoid direct access to
	vr_value, values_propagated, etc.
	(check_array_bounds): Extract vrp_prop class instance pointer from
	walk info structure.  Use it to call member functions.
	(check_all_array_refs): Make a member function within vrp_prop class.
	Smuggle class instance pointer via walk info structure.
	(x_vr_values): New local static.
	(vrp_valueize): Use x_vr_values to get class instance.
	(vr_valueize_1): Likewise.
	(class vrp_folder): Add vr_values data member.  Add various member
	functions as well as member functions that delegate to vr_values.
	(fold_predicate_in): Make a mber fucntion within vrp_folder class.
	(simplify_stmt_for_jump_threading): Extract smuggled vr_values
	class instance from vr_values.  Use it to call member functions.
	(vrp_dom_walker): Add vr_values data member.
	(vrp_dom_walker::after_dom_children): Smuggle vr_values class
	instance via x_vr_values.
	(identify_jump_threads): Accept vr_values as argument.  Store
	it into the walker structure.
	(evrp_dom_walker): Add vr_values class data member.  Add various
	delegators.
	(evrp_dom_walker::try_find_new_range): Use vr_values data
	member to access the memory allocator.
	(evrp_dom_walker::before_dom_children): Store vr_values class
	instance into the vrp_folder class.
	(evrp_dom_walker::push_value_range): Rework to avoid direct
	access to num_vr_values and vr_value.
	(evrp_dom_walker::pop_value_range): Likewise.
	(execute_early_vrp): Remove call to vrp_initialize_lattice.
	Use vr_values to get to dump_all_value_ranges member function.
	Remove call to vrp_free_lattice.  Call vrp_initialize, vrp_finalize,
	and simplify_cond_using_ranges_2 via vrp_prop class instance.
	Pass vr_values class instance down to identify_jump_threads.
	Remove call to vrp_free_lattice.
	(debug_all_value_ranges): Remove.

From-SVN: r254613
parent f2a7f77b
2017-11-09 Jeff Law <law@redhat.com> 2017-11-09 Jeff Law <law@redhat.com>
* vr-values.h: New file with vr_values class.
* tree-vrp.c: Include vr-values.h
(vrp_value_range_pool, vrp_equiv_obstack, num_vr_values): Move static
data objects into the vr_values class.
(vr_value, values_propagated, vr_phi_edge_counts): Likewise.
(get_value_range): Make it a member function within vr_values class.
(set_defs_to_varying, update_value_range, add_equivalence): Likewise.
(vrp_stmt_computes_nonzero_p, op_with_boolean_value_range_p): Likewise.
(op_with_constant_singleton_value_range): Likewise.
(extract_range_for_var_from_comparison_expr): Likewise.
(extract_range_from_assert, extract_range_from_ssa_name): Likewise.
(extract_range_from_binary_expr): Likewise.
(extract_range_from_unary_expr): Likewise.
(extract_range_from_cond_expr, extrat_range_from_comparison): Likewise.
(check_for_binary_op_overflow, extract_range_basic): Likewise.
(extract_range_from_assignment, adjust_range_with_scev): Likewise.
(dump_all_value_ranges, get_vr_for_comparison): Likewise.
(compare_name_with_value, compare_names): Likewise.
(vrp_evaluate_conditional_warnv_with_ops_using_ranges): Likewise.
(vrp_evaluate_conditional_warnv_with_ops): Likewise. Remove prototype.
(vrp_evaluate_conditional, vrp_visit_cond_stmt): Likewise.
(vrp_visit_switch_stmt, extract_range_from_stmt): Likewise.
(extract_range_from_phi_node): Likewise.
(simplify_truth_ops_using_ranges): Likewise.
(simplify_div_or_mod_using_ranges): Likewise.
(simplify_min_or_max_using_ranges, simplify_abs_using_ranges): Likewise.
(simplify_bit_ops_using_ranges, simplify_cond_using_ranges_1): Likewise.
(simplify_cond_using_ranges_2, simplify_switch_using_ranges): Likewise.
(simplify_float_conversion_using_ranges): Likewise.
(simplify_internal_call_using_ranges): Likewise.
(two_valued_val_range_p, simplify_stmt_using_ranges): Likewise.
(vrp_visit_assignment_or_call): Likewise. Smuggle class instance
poitner via x_vr_values for calls into gimple folder.
(vrp_initialize_lattice): Make this the vr_values ctor.
(vrp_free_lattice): Make this the vr_values dtor.
(set_vr_value): New function.
(class vrp_prop): Add vr_values data member. Add various member
functions as well as member functions that delegate to vr_values.
(check_array_ref): Make a member function within vrp_prop class.
(search_for_addr_array, vrp_initialize): Likewise.
(vrp_finalize): Likewise. Revamp to avoid direct access to
vr_value, values_propagated, etc.
(check_array_bounds): Extract vrp_prop class instance pointer from
walk info structure. Use it to call member functions.
(check_all_array_refs): Make a member function within vrp_prop class.
Smuggle class instance pointer via walk info structure.
(x_vr_values): New local static.
(vrp_valueize): Use x_vr_values to get class instance.
(vr_valueize_1): Likewise.
(class vrp_folder): Add vr_values data member. Add various member
functions as well as member functions that delegate to vr_values.
(fold_predicate_in): Make a mber fucntion within vrp_folder class.
(simplify_stmt_for_jump_threading): Extract smuggled vr_values
class instance from vr_values. Use it to call member functions.
(vrp_dom_walker): Add vr_values data member.
(vrp_dom_walker::after_dom_children): Smuggle vr_values class
instance via x_vr_values.
(identify_jump_threads): Accept vr_values as argument. Store
it into the walker structure.
(evrp_dom_walker): Add vr_values class data member. Add various
delegators.
(evrp_dom_walker::try_find_new_range): Use vr_values data
member to access the memory allocator.
(evrp_dom_walker::before_dom_children): Store vr_values class
instance into the vrp_folder class.
(evrp_dom_walker::push_value_range): Rework to avoid direct
access to num_vr_values and vr_value.
(evrp_dom_walker::pop_value_range): Likewise.
(execute_early_vrp): Remove call to vrp_initialize_lattice.
Use vr_values to get to dump_all_value_ranges member function.
Remove call to vrp_free_lattice. Call vrp_initialize, vrp_finalize,
and simplify_cond_using_ranges_2 via vrp_prop class instance.
Pass vr_values class instance down to identify_jump_threads.
Remove call to vrp_free_lattice.
(debug_all_value_ranges): Remove.
* tree-vrp.c (vrp_prop): Move class to earlier point in the file. * tree-vrp.c (vrp_prop): Move class to earlier point in the file.
(vrp_folder): Likewise. (vrp_folder): Likewise.
...@@ -64,13 +64,10 @@ along with GCC; see the file COPYING3. If not see ...@@ -64,13 +64,10 @@ along with GCC; see the file COPYING3. If not see
#include "tree-cfgcleanup.h" #include "tree-cfgcleanup.h"
#include "stringpool.h" #include "stringpool.h"
#include "attribs.h" #include "attribs.h"
#include "vr-values.h"
#define VR_INITIALIZER { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL } #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 /* Set of SSA names found live during the RPO traversal of the function
for still active basic-blocks. */ for still active basic-blocks. */
static sbitmap *live; static sbitmap *live;
...@@ -87,9 +84,6 @@ live_on_edge (edge e, tree name) ...@@ -87,9 +84,6 @@ live_on_edge (edge e, tree name)
/* Local functions. */ /* Local functions. */
static int compare_values (tree val1, tree val2); static int compare_values (tree val1, tree val2);
static int compare_values_warnv (tree val1, tree val2, bool *); 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 struct assert_info
{ {
...@@ -145,17 +139,6 @@ static bitmap need_assert_for; ...@@ -145,17 +139,6 @@ static bitmap need_assert_for;
ASSERT_EXPRs for SSA name N_I should be inserted. */ ASSERT_EXPRs for SSA name N_I should be inserted. */
static assert_locus **asserts_for; 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 { struct switch_update {
gswitch *stmt; gswitch *stmt;
tree vec; tree vec;
...@@ -509,8 +492,8 @@ abs_extent_range (value_range *vr, tree min, tree max) ...@@ -509,8 +492,8 @@ abs_extent_range (value_range *vr, tree min, tree max)
If we have no values ranges recorded (ie, VRP is not running), then 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. */ return NULL. Otherwise create an empty range if none existed for VAR. */
static value_range * value_range *
get_value_range (const_tree var) vr_values::get_value_range (const_tree var)
{ {
static const value_range vr_const_varying static const value_range vr_const_varying
= { VR_VARYING, NULL_TREE, NULL_TREE, NULL }; = { VR_VARYING, NULL_TREE, NULL_TREE, NULL };
...@@ -582,8 +565,8 @@ get_value_range (const_tree var) ...@@ -582,8 +565,8 @@ get_value_range (const_tree var)
/* Set value-ranges of all SSA names defined by STMT to varying. */ /* Set value-ranges of all SSA names defined by STMT to varying. */
static void void
set_defs_to_varying (gimple *stmt) vr_values::set_defs_to_varying (gimple *stmt)
{ {
ssa_op_iter i; ssa_op_iter i;
tree def; tree def;
...@@ -631,8 +614,8 @@ vrp_bitmap_equal_p (const_bitmap b1, const_bitmap b2) ...@@ -631,8 +614,8 @@ vrp_bitmap_equal_p (const_bitmap b1, const_bitmap b2)
this function. Do not call update_value_range when NEW_VR this function. Do not call update_value_range when NEW_VR
is the range object associated with another SSA name. */ is the range object associated with another SSA name. */
static inline bool bool
update_value_range (const_tree var, value_range *new_vr) vr_values::update_value_range (const_tree var, value_range *new_vr)
{ {
value_range *old_vr; value_range *old_vr;
bool is_new; bool is_new;
...@@ -690,8 +673,8 @@ update_value_range (const_tree var, value_range *new_vr) ...@@ -690,8 +673,8 @@ update_value_range (const_tree var, value_range *new_vr)
/* Add VAR and VAR's equivalence set to EQUIV. This is the central /* Add VAR and VAR's equivalence set to EQUIV. This is the central
point where equivalence processing can be turned on/off. */ point where equivalence processing can be turned on/off. */
static void void
add_equivalence (bitmap *equiv, const_tree var) vr_values::add_equivalence (bitmap *equiv, const_tree var)
{ {
unsigned ver = SSA_NAME_VERSION (var); unsigned ver = SSA_NAME_VERSION (var);
value_range *vr = get_value_range (var); value_range *vr = get_value_range (var);
...@@ -933,8 +916,8 @@ gimple_stmt_nonzero_p (gimple *stmt) ...@@ -933,8 +916,8 @@ gimple_stmt_nonzero_p (gimple *stmt)
/* Like tree_expr_nonzero_p, but this function uses value ranges /* Like tree_expr_nonzero_p, but this function uses value ranges
obtained so far. */ obtained so far. */
static bool bool
vrp_stmt_computes_nonzero (gimple *stmt) vr_values::vrp_stmt_computes_nonzero (gimple *stmt)
{ {
if (gimple_stmt_nonzero_p (stmt)) if (gimple_stmt_nonzero_p (stmt))
return true; return true;
...@@ -1260,8 +1243,8 @@ value_range_constant_singleton (value_range *vr) ...@@ -1260,8 +1243,8 @@ value_range_constant_singleton (value_range *vr)
otherwise return NULL_TREE. This returns OP itself if OP is a otherwise return NULL_TREE. This returns OP itself if OP is a
constant. */ constant. */
static tree tree
op_with_constant_singleton_value_range (tree op) vr_values::op_with_constant_singleton_value_range (tree op)
{ {
if (is_gimple_min_invariant (op)) if (is_gimple_min_invariant (op))
return op; return op;
...@@ -1274,8 +1257,8 @@ op_with_constant_singleton_value_range (tree op) ...@@ -1274,8 +1257,8 @@ op_with_constant_singleton_value_range (tree op)
/* Return true if op is in a boolean [0, 1] value-range. */ /* Return true if op is in a boolean [0, 1] value-range. */
static bool bool
op_with_boolean_value_range_p (tree op) vr_values::op_with_boolean_value_range_p (tree op)
{ {
value_range *vr; value_range *vr;
...@@ -1298,10 +1281,11 @@ op_with_boolean_value_range_p (tree op) ...@@ -1298,10 +1281,11 @@ op_with_boolean_value_range_p (tree op)
/* Extract value range information for VAR when (OP COND_CODE LIMIT) is /* Extract value range information for VAR when (OP COND_CODE LIMIT) is
true and store it in *VR_P. */ true and store it in *VR_P. */
static void void
extract_range_for_var_from_comparison_expr (tree var, enum tree_code cond_code, vr_values::extract_range_for_var_from_comparison_expr (tree var,
tree op, tree limit, enum tree_code cond_code,
value_range *vr_p) tree op, tree limit,
value_range *vr_p)
{ {
tree min, max, type; tree min, max, type;
value_range *limit_vr; value_range *limit_vr;
...@@ -1545,8 +1529,8 @@ extract_range_for_var_from_comparison_expr (tree var, enum tree_code cond_code, ...@@ -1545,8 +1529,8 @@ extract_range_for_var_from_comparison_expr (tree var, enum tree_code cond_code,
/* Extract value range information from an ASSERT_EXPR EXPR and store /* Extract value range information from an ASSERT_EXPR EXPR and store
it in *VR_P. */ it in *VR_P. */
static void void
extract_range_from_assert (value_range *vr_p, tree expr) vr_values::extract_range_from_assert (value_range *vr_p, tree expr)
{ {
tree var = ASSERT_EXPR_VAR (expr); tree var = ASSERT_EXPR_VAR (expr);
tree cond = ASSERT_EXPR_COND (expr); tree cond = ASSERT_EXPR_COND (expr);
...@@ -1591,8 +1575,8 @@ extract_range_from_assert (value_range *vr_p, tree expr) ...@@ -1591,8 +1575,8 @@ extract_range_from_assert (value_range *vr_p, tree expr)
Even if y_5 is deemed VARYING, we can determine that x_3 > y_5 is Even if y_5 is deemed VARYING, we can determine that x_3 > y_5 is
always false. */ always false. */
static void void
extract_range_from_ssa_name (value_range *vr, tree var) vr_values::extract_range_from_ssa_name (value_range *vr, tree var)
{ {
value_range *var_vr = get_value_range (var); value_range *var_vr = get_value_range (var);
...@@ -3027,10 +3011,10 @@ extract_range_from_binary_expr_1 (value_range *vr, ...@@ -3027,10 +3011,10 @@ extract_range_from_binary_expr_1 (value_range *vr,
the ranges of each of its operands with resulting type EXPR_TYPE. the ranges of each of its operands with resulting type EXPR_TYPE.
The resulting range is stored in *VR. */ The resulting range is stored in *VR. */
static void void
extract_range_from_binary_expr (value_range *vr, vr_values::extract_range_from_binary_expr (value_range *vr,
enum tree_code code, enum tree_code code,
tree expr_type, tree op0, tree op1) tree expr_type, tree op0, tree op1)
{ {
value_range vr0 = VR_INITIALIZER; value_range vr0 = VR_INITIALIZER;
value_range vr1 = VR_INITIALIZER; value_range vr1 = VR_INITIALIZER;
...@@ -3374,9 +3358,9 @@ extract_range_from_unary_expr (value_range *vr, ...@@ -3374,9 +3358,9 @@ extract_range_from_unary_expr (value_range *vr,
the range of its operand with resulting type TYPE. the range of its operand with resulting type TYPE.
The resulting range is stored in *VR. */ The resulting range is stored in *VR. */
static void void
extract_range_from_unary_expr (value_range *vr, enum tree_code code, vr_values::extract_range_from_unary_expr (value_range *vr, enum tree_code code,
tree type, tree op0) tree type, tree op0)
{ {
value_range vr0 = VR_INITIALIZER; value_range vr0 = VR_INITIALIZER;
...@@ -3389,15 +3373,15 @@ extract_range_from_unary_expr (value_range *vr, enum tree_code code, ...@@ -3389,15 +3373,15 @@ extract_range_from_unary_expr (value_range *vr, enum tree_code code,
else else
set_value_range_to_varying (&vr0); 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 /* Extract range information from a conditional expression STMT based on
the ranges of each of its operands and the expression code. */ the ranges of each of its operands and the expression code. */
static void void
extract_range_from_cond_expr (value_range *vr, gassign *stmt) vr_values::extract_range_from_cond_expr (value_range *vr, gassign *stmt)
{ {
tree op0, op1; tree op0, op1;
value_range vr0 = VR_INITIALIZER; value_range vr0 = VR_INITIALIZER;
...@@ -3430,9 +3414,9 @@ extract_range_from_cond_expr (value_range *vr, gassign *stmt) ...@@ -3430,9 +3414,9 @@ extract_range_from_cond_expr (value_range *vr, gassign *stmt)
/* Extract range information from a comparison expression EXPR based /* Extract range information from a comparison expression EXPR based
on the range of its operand and the expression code. */ on the range of its operand and the expression code. */
static void void
extract_range_from_comparison (value_range *vr, enum tree_code code, vr_values::extract_range_from_comparison (value_range *vr, enum tree_code code,
tree type, tree op0, tree op1) tree type, tree op0, tree op1)
{ {
bool sop; bool sop;
tree val; tree val;
...@@ -3461,9 +3445,9 @@ extract_range_from_comparison (value_range *vr, enum tree_code code, ...@@ -3461,9 +3445,9 @@ extract_range_from_comparison (value_range *vr, enum tree_code code,
always overflow. Set *OVF to true if it is known to always always overflow. Set *OVF to true if it is known to always
overflow. */ overflow. */
static bool bool
check_for_binary_op_overflow (enum tree_code subcode, tree type, vr_values::check_for_binary_op_overflow (enum tree_code subcode, tree type,
tree op0, tree op1, bool *ovf) tree op0, tree op1, bool *ovf)
{ {
value_range vr0 = VR_INITIALIZER; value_range vr0 = VR_INITIALIZER;
value_range vr1 = VR_INITIALIZER; value_range vr1 = VR_INITIALIZER;
...@@ -3566,8 +3550,8 @@ check_for_binary_op_overflow (enum tree_code subcode, tree type, ...@@ -3566,8 +3550,8 @@ check_for_binary_op_overflow (enum tree_code subcode, tree type,
primarily on generic routines in fold in conjunction with range data. primarily on generic routines in fold in conjunction with range data.
Store the result in *VR */ Store the result in *VR */
static void void
extract_range_basic (value_range *vr, gimple *stmt) vr_values::extract_range_basic (value_range *vr, gimple *stmt)
{ {
bool sop; bool sop;
tree type = gimple_expr_type (stmt); tree type = gimple_expr_type (stmt);
...@@ -3917,8 +3901,8 @@ extract_range_basic (value_range *vr, gimple *stmt) ...@@ -3917,8 +3901,8 @@ extract_range_basic (value_range *vr, gimple *stmt)
/* Try to compute a useful range out of assignment STMT and store it /* Try to compute a useful range out of assignment STMT and store it
in *VR. */ in *VR. */
static void void
extract_range_from_assignment (value_range *vr, gassign *stmt) vr_values::extract_range_from_assignment (value_range *vr, gassign *stmt)
{ {
enum tree_code code = gimple_assign_rhs_code (stmt); enum tree_code code = gimple_assign_rhs_code (stmt);
...@@ -3956,9 +3940,9 @@ extract_range_from_assignment (value_range *vr, gassign *stmt) ...@@ -3956,9 +3940,9 @@ extract_range_from_assignment (value_range *vr, gassign *stmt)
would be profitable to adjust VR using scalar evolution information would be profitable to adjust VR using scalar evolution information
for VAR. If so, update VR with the new limits. */ for VAR. If so, update VR with the new limits. */
static void void
adjust_range_with_scev (value_range *vr, struct loop *loop, vr_values::adjust_range_with_scev (value_range *vr, struct loop *loop,
gimple *stmt, tree var) gimple *stmt, tree var)
{ {
tree init, step, chrec, tmin, tmax, min, max, type, tem; tree init, step, chrec, tmin, tmax, min, max, type, tem;
enum ev_direction dir; enum ev_direction dir;
...@@ -4402,7 +4386,6 @@ compare_range_with_value (enum tree_code comp, value_range *vr, tree val, ...@@ -4402,7 +4386,6 @@ compare_range_with_value (enum tree_code comp, value_range *vr, tree val,
void dump_value_range (FILE *, const value_range *); void dump_value_range (FILE *, const value_range *);
void debug_value_range (value_range *); void debug_value_range (value_range *);
void dump_all_value_ranges (FILE *); void dump_all_value_ranges (FILE *);
void debug_all_value_ranges (void);
void dump_vr_equiv (FILE *, bitmap); void dump_vr_equiv (FILE *, bitmap);
void debug_vr_equiv (bitmap); void debug_vr_equiv (bitmap);
...@@ -4476,7 +4459,7 @@ debug_value_range (value_range *vr) ...@@ -4476,7 +4459,7 @@ debug_value_range (value_range *vr)
/* Dump value ranges of all SSA_NAMEs to FILE. */ /* Dump value ranges of all SSA_NAMEs to FILE. */
void void
dump_all_value_ranges (FILE *file) vr_values::dump_all_value_ranges (FILE *file)
{ {
size_t i; size_t i;
...@@ -4494,16 +4477,6 @@ dump_all_value_ranges (FILE *file) ...@@ -4494,16 +4477,6 @@ dump_all_value_ranges (FILE *file)
fprintf (file, "\n"); 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, /* 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 create a new SSA name N and return the assertion assignment
'N = ASSERT_EXPR <V, V OP W>'. */ 'N = ASSERT_EXPR <V, V OP W>'. */
...@@ -6640,6 +6613,28 @@ class vrp_prop : public ssa_propagation_engine ...@@ -6640,6 +6613,28 @@ class vrp_prop : public ssa_propagation_engine
public: public:
enum ssa_prop_result visit_stmt (gimple *, edge *, tree *) FINAL OVERRIDE; enum ssa_prop_result visit_stmt (gimple *, edge *, tree *) FINAL OVERRIDE;
enum ssa_prop_result visit_phi (gphi *) 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 /* Checks one ARRAY_REF in REF, located at LOCUS. Ignores flexible arrays
...@@ -6649,8 +6644,9 @@ class vrp_prop : public ssa_propagation_engine ...@@ -6649,8 +6644,9 @@ class vrp_prop : public ssa_propagation_engine
non-overlapping with valid range. non-overlapping with valid range.
IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside a ADDR_EXPR. */ IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside a ADDR_EXPR. */
static void void
check_array_ref (location_t location, tree ref, bool ignore_off_by_one) vrp_prop::check_array_ref (location_t location, tree ref,
bool ignore_off_by_one)
{ {
value_range *vr = NULL; value_range *vr = NULL;
tree low_sub, up_sub; tree low_sub, up_sub;
...@@ -6742,8 +6738,8 @@ check_array_ref (location_t location, tree ref, bool ignore_off_by_one) ...@@ -6742,8 +6738,8 @@ check_array_ref (location_t location, tree ref, bool ignore_off_by_one)
/* Searches if the expr T, located at LOCATION computes /* Searches if the expr T, located at LOCATION computes
address of an ARRAY_REF, and call check_array_ref on it. */ address of an ARRAY_REF, and call check_array_ref on it. */
static void void
search_for_addr_array (tree t, location_t location) vrp_prop::search_for_addr_array (tree t, location_t location)
{ {
/* Check each ARRAY_REFs in the reference chain. */ /* Check each ARRAY_REFs in the reference chain. */
do do
...@@ -6828,12 +6824,13 @@ check_array_bounds (tree *tp, int *walk_subtree, void *data) ...@@ -6828,12 +6824,13 @@ check_array_bounds (tree *tp, int *walk_subtree, void *data)
*walk_subtree = TRUE; *walk_subtree = TRUE;
vrp_prop *vrp_prop = (class vrp_prop *)wi->info;
if (TREE_CODE (t) == ARRAY_REF) 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) 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_subtree = FALSE;
} }
...@@ -6843,8 +6840,8 @@ check_array_bounds (tree *tp, int *walk_subtree, void *data) ...@@ -6843,8 +6840,8 @@ check_array_bounds (tree *tp, int *walk_subtree, void *data)
/* Walk over all statements of all reachable BBs and call check_array_bounds /* Walk over all statements of all reachable BBs and call check_array_bounds
on them. */ on them. */
static void void
check_all_array_refs (void) vrp_prop::check_all_array_refs ()
{ {
basic_block bb; basic_block bb;
gimple_stmt_iterator si; gimple_stmt_iterator si;
...@@ -6871,6 +6868,8 @@ check_all_array_refs (void) ...@@ -6871,6 +6868,8 @@ check_all_array_refs (void)
memset (&wi, 0, sizeof (wi)); memset (&wi, 0, sizeof (wi));
wi.info = this;
walk_gimple_op (gsi_stmt (si), walk_gimple_op (gsi_stmt (si),
check_array_bounds, check_array_bounds,
&wi); &wi);
...@@ -7121,8 +7120,7 @@ stmt_interesting_for_vrp (gimple *stmt) ...@@ -7121,8 +7120,7 @@ stmt_interesting_for_vrp (gimple *stmt)
/* Initialize VRP lattice. */ /* Initialize VRP lattice. */
static void vr_values::vr_values () : vrp_value_range_pool ("Tree VRP value ranges")
vrp_initialize_lattice ()
{ {
values_propagated = false; values_propagated = false;
num_vr_values = num_ssa_names; num_vr_values = num_ssa_names;
...@@ -7133,8 +7131,8 @@ vrp_initialize_lattice () ...@@ -7133,8 +7131,8 @@ vrp_initialize_lattice ()
/* Initialization required by ssa_propagate engine. */ /* Initialization required by ssa_propagate engine. */
static void void
vrp_initialize () vrp_prop::vrp_initialize ()
{ {
basic_block bb; basic_block bb;
...@@ -7175,6 +7173,9 @@ vrp_initialize () ...@@ -7175,6 +7173,9 @@ vrp_initialize ()
} }
} }
/* A hack. */
static class vr_values *x_vr_values;
/* Return the singleton value-range for NAME or NAME. */ /* Return the singleton value-range for NAME or NAME. */
static inline tree static inline tree
...@@ -7182,7 +7183,7 @@ vrp_valueize (tree name) ...@@ -7182,7 +7183,7 @@ vrp_valueize (tree name)
{ {
if (TREE_CODE (name) == SSA_NAME) 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 if (vr->type == VR_RANGE
&& (TREE_CODE (vr->min) == SSA_NAME && (TREE_CODE (vr->min) == SSA_NAME
|| is_gimple_min_invariant (vr->min)) || is_gimple_min_invariant (vr->min))
...@@ -7207,7 +7208,7 @@ vrp_valueize_1 (tree name) ...@@ -7207,7 +7208,7 @@ vrp_valueize_1 (tree name)
if (!gimple_nop_p (def_stmt) if (!gimple_nop_p (def_stmt)
&& prop_simulate_again_p (def_stmt)) && prop_simulate_again_p (def_stmt))
return NULL_TREE; 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)) if (range_int_cst_singleton_p (vr))
return vr->min; return vr->min;
} }
...@@ -7217,8 +7218,9 @@ vrp_valueize_1 (tree name) ...@@ -7217,8 +7218,9 @@ vrp_valueize_1 (tree name)
/* Visit assignment STMT. If it produces an interesting range, record /* Visit assignment STMT. If it produces an interesting range, record
the range in VR and set LHS to OUTPUT_P. */ the range in VR and set LHS to OUTPUT_P. */
static void void
vrp_visit_assignment_or_call (gimple *stmt, tree *output_p, value_range *vr) vr_values::vrp_visit_assignment_or_call (gimple *stmt, tree *output_p,
value_range *vr)
{ {
tree lhs; tree lhs;
enum gimple_code code = gimple_code (stmt); enum gimple_code code = gimple_code (stmt);
...@@ -7237,8 +7239,10 @@ vrp_visit_assignment_or_call (gimple *stmt, tree *output_p, value_range *vr) ...@@ -7237,8 +7239,10 @@ vrp_visit_assignment_or_call (gimple *stmt, tree *output_p, value_range *vr)
*output_p = lhs; *output_p = lhs;
/* Try folding the statement to a constant first. */ /* Try folding the statement to a constant first. */
x_vr_values = this;
tree tem = gimple_fold_stmt_to_constant_1 (stmt, vrp_valueize, tree tem = gimple_fold_stmt_to_constant_1 (stmt, vrp_valueize,
vrp_valueize_1); vrp_valueize_1);
x_vr_values = NULL;
if (tem) if (tem)
{ {
if (TREE_CODE (tem) == SSA_NAME if (TREE_CODE (tem) == SSA_NAME
...@@ -7266,8 +7270,8 @@ vrp_visit_assignment_or_call (gimple *stmt, tree *output_p, value_range *vr) ...@@ -7266,8 +7270,8 @@ vrp_visit_assignment_or_call (gimple *stmt, tree *output_p, value_range *vr)
or a symbolic range containing the SSA_NAME only if the value range or a symbolic range containing the SSA_NAME only if the value range
is varying or undefined. */ is varying or undefined. */
static inline value_range value_range
get_vr_for_comparison (int i) vr_values::get_vr_for_comparison (int i)
{ {
value_range vr = *get_value_range (ssa_name (i)); value_range vr = *get_value_range (ssa_name (i));
...@@ -7289,9 +7293,9 @@ get_vr_for_comparison (int i) ...@@ -7289,9 +7293,9 @@ get_vr_for_comparison (int i)
compare_range_with_value, including the setting of compare_range_with_value, including the setting of
*STRICT_OVERFLOW_P. */ *STRICT_OVERFLOW_P. */
static tree tree
compare_name_with_value (enum tree_code comp, tree var, tree val, vr_values::compare_name_with_value (enum tree_code comp, tree var, tree val,
bool *strict_overflow_p, bool use_equiv_p) bool *strict_overflow_p, bool use_equiv_p)
{ {
bitmap_iterator bi; bitmap_iterator bi;
unsigned i; unsigned i;
...@@ -7374,9 +7378,9 @@ compare_name_with_value (enum tree_code comp, tree var, tree val, ...@@ -7374,9 +7378,9 @@ compare_name_with_value (enum tree_code comp, tree var, tree val,
whether we relied on undefined signed overflow in the comparison. */ whether we relied on undefined signed overflow in the comparison. */
static tree tree
compare_names (enum tree_code comp, tree n1, tree n2, vr_values::compare_names (enum tree_code comp, tree n1, tree n2,
bool *strict_overflow_p) bool *strict_overflow_p)
{ {
tree t, retval; tree t, retval;
bitmap e1, e2; bitmap e1, e2;
...@@ -7489,10 +7493,9 @@ compare_names (enum tree_code comp, tree n1, tree n2, ...@@ -7489,10 +7493,9 @@ compare_names (enum tree_code comp, tree n1, tree n2,
/* Helper function for vrp_evaluate_conditional_warnv & other /* Helper function for vrp_evaluate_conditional_warnv & other
optimizers. */ optimizers. */
static tree tree
vrp_evaluate_conditional_warnv_with_ops_using_ranges (enum tree_code code, vr_values::vrp_evaluate_conditional_warnv_with_ops_using_ranges
tree op0, tree op1, (enum tree_code code, tree op0, tree op1, bool * strict_overflow_p)
bool * strict_overflow_p)
{ {
value_range *vr0, *vr1; value_range *vr0, *vr1;
...@@ -7512,10 +7515,12 @@ vrp_evaluate_conditional_warnv_with_ops_using_ranges (enum tree_code code, ...@@ -7512,10 +7515,12 @@ vrp_evaluate_conditional_warnv_with_ops_using_ranges (enum tree_code code,
/* Helper function for vrp_evaluate_conditional_warnv. */ /* Helper function for vrp_evaluate_conditional_warnv. */
static tree tree
vrp_evaluate_conditional_warnv_with_ops (enum tree_code code, tree op0, vr_values::vrp_evaluate_conditional_warnv_with_ops (enum tree_code code,
tree op1, bool use_equiv_p, tree op0, tree op1,
bool *strict_overflow_p, bool *only_ranges) bool use_equiv_p,
bool *strict_overflow_p,
bool *only_ranges)
{ {
tree ret; tree ret;
if (only_ranges) if (only_ranges)
...@@ -7584,8 +7589,9 @@ vrp_evaluate_conditional_warnv_with_ops (enum tree_code code, tree op0, ...@@ -7584,8 +7589,9 @@ vrp_evaluate_conditional_warnv_with_ops (enum tree_code code, tree op0,
based on undefined signed overflow, issue a warning if based on undefined signed overflow, issue a warning if
appropriate. */ appropriate. */
static tree tree
vrp_evaluate_conditional (tree_code code, tree op0, tree op1, gimple *stmt) vr_values::vrp_evaluate_conditional (tree_code code, tree op0,
tree op1, gimple *stmt)
{ {
bool sop; bool sop;
tree ret; tree ret;
...@@ -7676,8 +7682,8 @@ vrp_evaluate_conditional (tree_code code, tree op0, tree op1, gimple *stmt) ...@@ -7676,8 +7682,8 @@ vrp_evaluate_conditional (tree_code code, tree op0, tree op1, gimple *stmt)
will be taken out of STMT's basic block, record it in will be taken out of STMT's basic block, record it in
*TAKEN_EDGE_P. Otherwise, set *TAKEN_EDGE_P to NULL. */ *TAKEN_EDGE_P. Otherwise, set *TAKEN_EDGE_P to NULL. */
static void void
vrp_visit_cond_stmt (gcond *stmt, edge *taken_edge_p) vr_values::vrp_visit_cond_stmt (gcond *stmt, edge *taken_edge_p)
{ {
tree val; tree val;
...@@ -7960,8 +7966,8 @@ find_case_label_ranges (gswitch *stmt, value_range *vr, size_t *min_idx1, ...@@ -7960,8 +7966,8 @@ find_case_label_ranges (gswitch *stmt, value_range *vr, size_t *min_idx1,
will be taken out of STMT's basic block, record it in will be taken out of STMT's basic block, record it in
*TAKEN_EDGE_P. Otherwise, *TAKEN_EDGE_P set to NULL. */ *TAKEN_EDGE_P. Otherwise, *TAKEN_EDGE_P set to NULL. */
static void void
vrp_visit_switch_stmt (gswitch *stmt, edge *taken_edge_p) vr_values::vrp_visit_switch_stmt (gswitch *stmt, edge *taken_edge_p)
{ {
tree op, val; tree op, val;
value_range *vr; value_range *vr;
...@@ -8052,9 +8058,9 @@ vrp_visit_switch_stmt (gswitch *stmt, edge *taken_edge_p) ...@@ -8052,9 +8058,9 @@ vrp_visit_switch_stmt (gswitch *stmt, edge *taken_edge_p)
If STMT is a conditional branch and we can determine its truth If STMT is a conditional branch and we can determine its truth
value, the taken edge is recorded in *TAKEN_EDGE_P. */ value, the taken edge is recorded in *TAKEN_EDGE_P. */
static void void
extract_range_from_stmt (gimple *stmt, edge *taken_edge_p, vr_values::extract_range_from_stmt (gimple *stmt, edge *taken_edge_p,
tree *output_p, value_range *vr) tree *output_p, value_range *vr)
{ {
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
...@@ -8960,8 +8966,8 @@ vrp_meet (value_range *vr0, const value_range *vr1) ...@@ -8960,8 +8966,8 @@ vrp_meet (value_range *vr0, const value_range *vr1)
edges. If a valid value range can be derived from all the incoming edges. If a valid value range can be derived from all the incoming
value ranges, set a new range in VR_RESULT. */ value ranges, set a new range in VR_RESULT. */
static void void
extract_range_from_phi_node (gphi *phi, value_range *vr_result) vr_values::extract_range_from_phi_node (gphi *phi, value_range *vr_result)
{ {
size_t i; size_t i;
tree lhs = PHI_RESULT (phi); tree lhs = PHI_RESULT (phi);
...@@ -9205,8 +9211,9 @@ vrp_prop::visit_phi (gphi *phi) ...@@ -9205,8 +9211,9 @@ vrp_prop::visit_phi (gphi *phi)
/* Simplify boolean operations if the source is known /* Simplify boolean operations if the source is known
to be already a boolean. */ to be already a boolean. */
static bool bool
simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt) vr_values::simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi,
gimple *stmt)
{ {
enum tree_code rhs_code = gimple_assign_rhs_code (stmt); enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
tree lhs, op0, op1; tree lhs, op0, op1;
...@@ -9281,8 +9288,9 @@ simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt) ...@@ -9281,8 +9288,9 @@ simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
[-op1min + 1, op1min - 1] for signed and [0, op1min - 1] for unsigned [-op1min + 1, op1min - 1] for signed and [0, op1min - 1] for unsigned
modulo. */ modulo. */
static bool bool
simplify_div_or_mod_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt) vr_values::simplify_div_or_mod_using_ranges (gimple_stmt_iterator *gsi,
gimple *stmt)
{ {
enum tree_code rhs_code = gimple_assign_rhs_code (stmt); enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
tree val = NULL; tree val = NULL;
...@@ -9405,8 +9413,9 @@ simplify_div_or_mod_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt) ...@@ -9405,8 +9413,9 @@ simplify_div_or_mod_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
/* Simplify a min or max if the ranges of the two operands are /* Simplify a min or max if the ranges of the two operands are
disjoint. Return true if we do simplify. */ disjoint. Return true if we do simplify. */
static bool bool
simplify_min_or_max_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt) vr_values::simplify_min_or_max_using_ranges (gimple_stmt_iterator *gsi,
gimple *stmt)
{ {
tree op0 = gimple_assign_rhs1 (stmt); tree op0 = gimple_assign_rhs1 (stmt);
tree op1 = gimple_assign_rhs2 (stmt); tree op1 = gimple_assign_rhs2 (stmt);
...@@ -9452,8 +9461,8 @@ simplify_min_or_max_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt) ...@@ -9452,8 +9461,8 @@ simplify_min_or_max_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
ABS_EXPR. If the operand is <= 0, then simplify the ABS_EXPR. If the operand is <= 0, then simplify the
ABS_EXPR into a NEGATE_EXPR. */ ABS_EXPR into a NEGATE_EXPR. */
static bool bool
simplify_abs_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt) vr_values::simplify_abs_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
{ {
tree op = gimple_assign_rhs1 (stmt); tree op = gimple_assign_rhs1 (stmt);
value_range *vr = get_value_range (op); value_range *vr = get_value_range (op);
...@@ -9508,8 +9517,9 @@ simplify_abs_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt) ...@@ -9508,8 +9517,9 @@ simplify_abs_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
set by | are already known to be one from VR, the bit set by | are already known to be one from VR, the bit
operation is redundant. */ operation is redundant. */
static bool bool
simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt) vr_values::simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi,
gimple *stmt)
{ {
tree op0 = gimple_assign_rhs1 (stmt); tree op0 = gimple_assign_rhs1 (stmt);
tree op1 = gimple_assign_rhs2 (stmt); tree op1 = gimple_assign_rhs2 (stmt);
...@@ -9705,8 +9715,8 @@ range_fits_type_p (value_range *vr, unsigned dest_precision, signop dest_sgn) ...@@ -9705,8 +9715,8 @@ range_fits_type_p (value_range *vr, unsigned dest_precision, signop dest_sgn)
test if the range information indicates only one value can satisfy test if the range information indicates only one value can satisfy
the original conditional. */ the original conditional. */
static bool bool
simplify_cond_using_ranges_1 (gcond *stmt) vr_values::simplify_cond_using_ranges_1 (gcond *stmt)
{ {
tree op0 = gimple_cond_lhs (stmt); tree op0 = gimple_cond_lhs (stmt);
tree op1 = gimple_cond_rhs (stmt); tree op1 = gimple_cond_rhs (stmt);
...@@ -9790,8 +9800,8 @@ simplify_cond_using_ranges_1 (gcond *stmt) ...@@ -9790,8 +9800,8 @@ simplify_cond_using_ranges_1 (gcond *stmt)
of the type conversion. Doing so makes the conversion dead which helps of the type conversion. Doing so makes the conversion dead which helps
subsequent passes. */ subsequent passes. */
static void void
simplify_cond_using_ranges_2 (gcond *stmt) vr_values::simplify_cond_using_ranges_2 (gcond *stmt)
{ {
tree op0 = gimple_cond_lhs (stmt); tree op0 = gimple_cond_lhs (stmt);
tree op1 = gimple_cond_rhs (stmt); tree op1 = gimple_cond_rhs (stmt);
...@@ -9847,8 +9857,8 @@ simplify_cond_using_ranges_2 (gcond *stmt) ...@@ -9847,8 +9857,8 @@ simplify_cond_using_ranges_2 (gcond *stmt)
/* Simplify a switch statement using the value range of the switch /* Simplify a switch statement using the value range of the switch
argument. */ argument. */
static bool bool
simplify_switch_using_ranges (gswitch *stmt) vr_values::simplify_switch_using_ranges (gswitch *stmt)
{ {
tree op = gimple_switch_index (stmt); tree op = gimple_switch_index (stmt);
value_range *vr = NULL; value_range *vr = NULL;
...@@ -10105,9 +10115,9 @@ simplify_conversion_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt) ...@@ -10105,9 +10115,9 @@ simplify_conversion_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
/* Simplify a conversion from integral SSA name to float in STMT. */ /* Simplify a conversion from integral SSA name to float in STMT. */
static bool bool
simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi, vr_values::simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi,
gimple *stmt) gimple *stmt)
{ {
tree rhs1 = gimple_assign_rhs1 (stmt); tree rhs1 = gimple_assign_rhs1 (stmt);
value_range *vr = get_value_range (rhs1); value_range *vr = get_value_range (rhs1);
...@@ -10169,8 +10179,9 @@ simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi, ...@@ -10169,8 +10179,9 @@ simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi,
/* Simplify an internal fn call using ranges if possible. */ /* Simplify an internal fn call using ranges if possible. */
static bool bool
simplify_internal_call_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt) vr_values::simplify_internal_call_using_ranges (gimple_stmt_iterator *gsi,
gimple *stmt)
{ {
enum tree_code subcode; enum tree_code subcode;
bool is_ubsan = false; bool is_ubsan = false;
...@@ -10271,8 +10282,8 @@ simplify_internal_call_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt) ...@@ -10271,8 +10282,8 @@ simplify_internal_call_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
/* Return true if VAR is a two-valued variable. Set a and b with the /* Return true if VAR is a two-valued variable. Set a and b with the
two-values when it is true. Return false otherwise. */ two-values when it is true. Return false otherwise. */
static bool bool
two_valued_val_range_p (tree var, tree *a, tree *b) vr_values::two_valued_val_range_p (tree var, tree *a, tree *b)
{ {
value_range *vr = get_value_range (var); value_range *vr = get_value_range (var);
if ((vr->type != VR_RANGE if ((vr->type != VR_RANGE
...@@ -10306,8 +10317,8 @@ two_valued_val_range_p (tree var, tree *a, tree *b) ...@@ -10306,8 +10317,8 @@ two_valued_val_range_p (tree var, tree *a, tree *b)
/* Simplify STMT using ranges if possible. */ /* Simplify STMT using ranges if possible. */
static bool bool
simplify_stmt_using_ranges (gimple_stmt_iterator *gsi) vr_values::simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
{ {
gimple *stmt = gsi_stmt (*gsi); gimple *stmt = gsi_stmt (*gsi);
if (is_gimple_assign (stmt)) if (is_gimple_assign (stmt))
...@@ -10455,14 +10466,26 @@ class vrp_folder : public substitute_and_fold_engine ...@@ -10455,14 +10466,26 @@ class vrp_folder : public substitute_and_fold_engine
public: public:
tree get_value (tree) FINAL OVERRIDE; tree get_value (tree) FINAL OVERRIDE;
bool fold_stmt (gimple_stmt_iterator *) 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 /* If the statement pointed by SI has a predicate whose value can be
computed using the value range information computed by VRP, compute computed using the value range information computed by VRP, compute
its value and return true. Otherwise, return false. */ its value and return true. Otherwise, return false. */
static bool bool
fold_predicate_in (gimple_stmt_iterator *si) vrp_folder::fold_predicate_in (gimple_stmt_iterator *si)
{ {
bool assignment_p = false; bool assignment_p = false;
tree val; tree val;
...@@ -10584,6 +10607,7 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt, ...@@ -10584,6 +10607,7 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt,
if (cached_lhs && is_gimple_min_invariant (cached_lhs)) if (cached_lhs && is_gimple_min_invariant (cached_lhs))
return cached_lhs; return cached_lhs;
vr_values *vr_values = x_vr_values;
if (gcond *cond_stmt = dyn_cast <gcond *> (stmt)) if (gcond *cond_stmt = dyn_cast <gcond *> (stmt))
{ {
tree op0 = gimple_cond_lhs (cond_stmt); tree op0 = gimple_cond_lhs (cond_stmt);
...@@ -10592,8 +10616,8 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt, ...@@ -10592,8 +10616,8 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt,
tree op1 = gimple_cond_rhs (cond_stmt); tree op1 = gimple_cond_rhs (cond_stmt);
op1 = lhs_of_dominating_assert (op1, bb, stmt); op1 = lhs_of_dominating_assert (op1, bb, stmt);
return vrp_evaluate_conditional (gimple_cond_code (cond_stmt), return vr_values->vrp_evaluate_conditional (gimple_cond_code (cond_stmt),
op0, op1, within_stmt); op0, op1, within_stmt);
} }
/* We simplify a switch statement by trying to determine which case label /* We simplify a switch statement by trying to determine which case label
...@@ -10607,7 +10631,7 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt, ...@@ -10607,7 +10631,7 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt,
op = lhs_of_dominating_assert (op, bb, stmt); 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) if ((vr->type != VR_RANGE && vr->type != VR_ANTI_RANGE)
|| symbolic_range_p (vr)) || symbolic_range_p (vr))
return NULL_TREE; return NULL_TREE;
...@@ -10668,7 +10692,7 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt, ...@@ -10668,7 +10692,7 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt,
&& (INTEGRAL_TYPE_P (TREE_TYPE (lhs)) && (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
|| POINTER_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)) if (range_int_cst_singleton_p (&new_vr))
return new_vr.min; return new_vr.min;
} }
...@@ -10691,11 +10715,14 @@ public: ...@@ -10691,11 +10715,14 @@ public:
virtual edge before_dom_children (basic_block); virtual edge before_dom_children (basic_block);
virtual void after_dom_children (basic_block); virtual void after_dom_children (basic_block);
class vr_values *vr_values;
private: private:
class const_and_copies *m_const_and_copies; class const_and_copies *m_const_and_copies;
class avail_exprs_stack *m_avail_exprs_stack; class avail_exprs_stack *m_avail_exprs_stack;
gcond *m_dummy_cond; gcond *m_dummy_cond;
}; };
/* Called before processing dominator children of BB. We want to look /* Called before processing dominator children of BB. We want to look
...@@ -10748,9 +10775,11 @@ vrp_dom_walker::after_dom_children (basic_block bb) ...@@ -10748,9 +10775,11 @@ vrp_dom_walker::after_dom_children (basic_block bb)
integer_zero_node, integer_zero_node, integer_zero_node, integer_zero_node,
NULL, NULL); NULL, NULL);
x_vr_values = vr_values;
thread_outgoing_edges (bb, m_dummy_cond, m_const_and_copies, thread_outgoing_edges (bb, m_dummy_cond, m_const_and_copies,
m_avail_exprs_stack, m_avail_exprs_stack,
simplify_stmt_for_jump_threading); simplify_stmt_for_jump_threading);
x_vr_values = NULL;
m_avail_exprs_stack->pop_to_marker (); m_avail_exprs_stack->pop_to_marker ();
m_const_and_copies->pop_to_marker (); m_const_and_copies->pop_to_marker ();
...@@ -10777,7 +10806,7 @@ vrp_dom_walker::after_dom_children (basic_block bb) ...@@ -10777,7 +10806,7 @@ vrp_dom_walker::after_dom_children (basic_block bb)
for later realization. */ for later realization. */
static void static void
identify_jump_threads (void) identify_jump_threads (class vr_values *vr_values)
{ {
int i; int i;
edge e; edge e;
...@@ -10809,6 +10838,7 @@ identify_jump_threads (void) ...@@ -10809,6 +10838,7 @@ identify_jump_threads (void)
= new class avail_exprs_stack (avail_exprs); = new class avail_exprs_stack (avail_exprs);
vrp_dom_walker walker (CDI_DOMINATORS, equiv_stack, avail_exprs_stack); vrp_dom_walker walker (CDI_DOMINATORS, equiv_stack, avail_exprs_stack);
walker.vr_values = vr_values;
walker.walk (cfun->cfg->x_entry_block_ptr); walker.walk (cfun->cfg->x_entry_block_ptr);
/* Clear EDGE_IGNORE. */ /* Clear EDGE_IGNORE. */
...@@ -10825,8 +10855,7 @@ identify_jump_threads (void) ...@@ -10825,8 +10855,7 @@ identify_jump_threads (void)
/* Free VRP lattice. */ /* Free VRP lattice. */
static void vr_values::~vr_values ()
vrp_free_lattice ()
{ {
/* Free allocated memory. */ /* Free allocated memory. */
free (vr_value); free (vr_value);
...@@ -10842,48 +10871,49 @@ vrp_free_lattice () ...@@ -10842,48 +10871,49 @@ vrp_free_lattice ()
/* Traverse all the blocks folding conditionals with known ranges. */ /* Traverse all the blocks folding conditionals with known ranges. */
static void void
vrp_finalize (bool warn_array_bounds_p) vrp_prop::vrp_finalize (bool warn_array_bounds_p)
{ {
size_t i; size_t i;
values_propagated = true; vr_values.values_propagated = true;
if (dump_file) if (dump_file)
{ {
fprintf (dump_file, "\nValue ranges after VRP:\n\n"); 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"); fprintf (dump_file, "\n");
} }
/* Set value range to non pointer SSA_NAMEs. */ /* Set value range to non pointer SSA_NAMEs. */
for (i = 0; i < num_vr_values; i++) for (i = 0; i < num_ssa_names; i++)
if (vr_value[i]) {
{ tree name = ssa_name (i);
tree name = ssa_name (i); if (!name)
continue;
if (!name value_range *vr = get_value_range (name);
|| (vr_value[i]->type == VR_VARYING) if (!name
|| (vr_value[i]->type == VR_UNDEFINED) || (vr->type == VR_VARYING)
|| (TREE_CODE (vr_value[i]->min) != INTEGER_CST) || (vr->type == VR_UNDEFINED)
|| (TREE_CODE (vr_value[i]->max) != INTEGER_CST)) || (TREE_CODE (vr->min) != INTEGER_CST)
continue; || (TREE_CODE (vr->max) != INTEGER_CST))
continue;
if (POINTER_TYPE_P (TREE_TYPE (name)) if (POINTER_TYPE_P (TREE_TYPE (name))
&& ((vr_value[i]->type == VR_RANGE && ((vr->type == VR_RANGE
&& range_includes_zero_p (vr_value[i]->min, && range_includes_zero_p (vr->min, vr->max) == 0)
vr_value[i]->max) == 0) || (vr->type == VR_ANTI_RANGE
|| (vr_value[i]->type == VR_ANTI_RANGE && range_includes_zero_p (vr->min, vr->max) == 1)))
&& range_includes_zero_p (vr_value[i]->min, set_ptr_nonnull (name);
vr_value[i]->max) == 1))) else if (!POINTER_TYPE_P (TREE_TYPE (name)))
set_ptr_nonnull (name); set_range_info (name, vr->type,
else if (!POINTER_TYPE_P (TREE_TYPE (name))) wi::to_wide (vr->min),
set_range_info (name, vr_value[i]->type, wi::to_wide (vr->max));
wi::to_wide (vr_value[i]->min), }
wi::to_wide (vr_value[i]->max));
}
class vrp_folder vrp_folder; class vrp_folder vrp_folder;
vrp_folder.vr_values = &vr_values;
vrp_folder.substitute_and_fold (); vrp_folder.substitute_and_fold ();
if (warn_array_bounds && warn_array_bounds_p) if (warn_array_bounds && warn_array_bounds_p)
...@@ -10917,6 +10947,38 @@ public: ...@@ -10917,6 +10947,38 @@ public:
bitmap need_eh_cleanup; bitmap need_eh_cleanup;
auto_vec<gimple *> stmts_to_fixup; auto_vec<gimple *> stmts_to_fixup;
auto_vec<gimple *> stmts_to_remove; 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. */ /* Find new range for NAME such that (OP CODE LIMIT) is true. */
...@@ -10939,7 +11001,7 @@ evrp_dom_walker::try_find_new_range (tree name, ...@@ -10939,7 +11001,7 @@ evrp_dom_walker::try_find_new_range (tree name,
&& vrp_operand_equal_p (old_vr->min, vr.min) && vrp_operand_equal_p (old_vr->min, vr.min)
&& vrp_operand_equal_p (old_vr->max, vr.max)) && vrp_operand_equal_p (old_vr->max, vr.max))
return NULL; 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; *new_vr = vr;
return new_vr; return new_vr;
} }
...@@ -11208,6 +11270,7 @@ evrp_dom_walker::before_dom_children (basic_block bb) ...@@ -11208,6 +11270,7 @@ evrp_dom_walker::before_dom_children (basic_block bb)
/* Try folding stmts with the VR discovered. */ /* Try folding stmts with the VR discovered. */
class vrp_folder vrp_folder; class vrp_folder vrp_folder;
vrp_folder.vr_values = &vr_values;
bool did_replace = vrp_folder.replace_uses_in (stmt); bool did_replace = vrp_folder.replace_uses_in (stmt);
if (fold_stmt (&gsi, follow_single_use_edges) if (fold_stmt (&gsi, follow_single_use_edges)
|| did_replace) || did_replace)
...@@ -11274,13 +11337,19 @@ evrp_dom_walker::after_dom_children (basic_block bb ATTRIBUTE_UNUSED) ...@@ -11274,13 +11337,19 @@ evrp_dom_walker::after_dom_children (basic_block bb ATTRIBUTE_UNUSED)
stack.pop (); 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. */ /* Push the Value Range of VAR to the stack and update it with new VR. */
void void
evrp_dom_walker::push_value_range (tree var, value_range *vr) 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)) if (dump_file && (dump_flags & TDF_DETAILS))
{ {
fprintf (dump_file, "pushing new range for "); fprintf (dump_file, "pushing new range for ");
...@@ -11290,7 +11359,7 @@ evrp_dom_walker::push_value_range (tree var, value_range *vr) ...@@ -11290,7 +11359,7 @@ evrp_dom_walker::push_value_range (tree var, value_range *vr)
fprintf (dump_file, "\n"); fprintf (dump_file, "\n");
} }
stack.safe_push (std::make_pair (var, get_value_range (var))); 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. */ /* Pop the Value Range from the vrp_stack and update VAR with it. */
...@@ -11308,7 +11377,7 @@ evrp_dom_walker::pop_value_range (tree var) ...@@ -11308,7 +11377,7 @@ evrp_dom_walker::pop_value_range (tree var)
dump_value_range (dump_file, vr); dump_value_range (dump_file, vr);
fprintf (dump_file, "\n"); fprintf (dump_file, "\n");
} }
vr_value[SSA_NAME_VERSION (var)] = vr; set_vr_value (var, vr);
stack.pop (); stack.pop ();
return vr; return vr;
} }
...@@ -11335,7 +11404,6 @@ execute_early_vrp () ...@@ -11335,7 +11404,6 @@ execute_early_vrp ()
FOR_EACH_EDGE (e, ei, bb->preds) FOR_EACH_EDGE (e, ei, bb->preds)
e->flags |= EDGE_EXECUTABLE; e->flags |= EDGE_EXECUTABLE;
} }
vrp_initialize_lattice ();
/* Walk stmts in dominance order and propagate VRP. */ /* Walk stmts in dominance order and propagate VRP. */
evrp_dom_walker walker; evrp_dom_walker walker;
...@@ -11344,7 +11412,7 @@ execute_early_vrp () ...@@ -11344,7 +11412,7 @@ execute_early_vrp ()
if (dump_file) if (dump_file)
{ {
fprintf (dump_file, "\nValue ranges after Early VRP:\n\n"); 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"); fprintf (dump_file, "\n");
} }
...@@ -11382,7 +11450,6 @@ execute_early_vrp () ...@@ -11382,7 +11450,6 @@ execute_early_vrp ()
fixup_noreturn_call (stmt); fixup_noreturn_call (stmt);
} }
vrp_free_lattice ();
scev_finalize (); scev_finalize ();
loop_optimizer_finalize (); loop_optimizer_finalize ();
return 0; return 0;
...@@ -11456,15 +11523,14 @@ execute_vrp (bool warn_array_bounds_p) ...@@ -11456,15 +11523,14 @@ execute_vrp (bool warn_array_bounds_p)
/* For visiting PHI nodes we need EDGE_DFS_BACK computed. */ /* For visiting PHI nodes we need EDGE_DFS_BACK computed. */
mark_dfs_back_edges (); mark_dfs_back_edges ();
vrp_initialize_lattice ();
vrp_initialize ();
class vrp_prop vrp_prop; class vrp_prop vrp_prop;
vrp_prop.vrp_initialize ();
vrp_prop.ssa_propagate (); 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 /* We must identify jump threading opportunities before we release
the datastructures built by VRP. */ 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 /* 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 was set by a type conversion can often be rewritten to use the
...@@ -11478,11 +11544,9 @@ execute_vrp (bool warn_array_bounds_p) ...@@ -11478,11 +11544,9 @@ execute_vrp (bool warn_array_bounds_p)
{ {
gimple *last = last_stmt (bb); gimple *last = last_stmt (bb);
if (last && gimple_code (last) == GIMPLE_COND) 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); free_numbers_of_iterations_estimates (cfun);
/* ASSERT_EXPRs must be removed before finalizing jump threads /* ASSERT_EXPRs must be removed before finalizing jump threads
......
/* Support routines for Value Range Propagation (VRP).
Copyright (C) 2016-2017 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#ifndef GCC_VR_VALUES_H
#define GCC_VR_VALUES_H
/* The VR_VALUES class holds the current view of range information
for all the SSA_NAMEs in the IL.
It can be used to hold context sensitive range information during
a dominator walk or it may be used to hold range information in the
standard VRP pass as ranges are propagated through the lattice to a
steady state.
This information is independent of the range information that gets
attached to SSA_NAMEs. A pass such as VRP may choose to transfer
the global information it produces into global range information that
gets attached to an SSA_NAME. It's unclear how useful that global
information will be in a world where we can compute context sensitive
range information fast or perform on-demand queries. */
class vr_values
{
public:
vr_values (void);
~vr_values (void);
/* Value range array. After propagation, VR_VALUE[I] holds the range
of values that SSA name N_I may take. */
unsigned int num_vr_values;
value_range **vr_value;
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. */
int *vr_phi_edge_counts;
/* Allocation pools for tree-vrp allocations. */
object_allocator<value_range> vrp_value_range_pool;
bitmap_obstack vrp_equiv_obstack;
value_range *get_value_range (const_tree);
void set_vr_value (tree, value_range *);
void set_defs_to_varying (gimple *);
bool update_value_range (const_tree, value_range *);
void add_equivalence (bitmap *, const_tree);
bool vrp_stmt_computes_nonzero (gimple *);
tree op_with_constant_singleton_value_range (tree);
bool op_with_boolean_value_range_p (tree);
bool check_for_binary_op_overflow (enum tree_code, tree, tree, tree, bool *);
void adjust_range_with_scev (value_range *, struct loop *, gimple *, tree);
value_range get_vr_for_comparison (int);
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 *);
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,
tree, tree, value_range *);
void extract_range_from_assert (value_range *, tree);
void extract_range_from_ssa_name (value_range *, tree);
void extract_range_from_binary_expr (value_range *, enum tree_code,
tree, tree, tree);
void extract_range_from_unary_expr (value_range *, enum tree_code,
tree, tree);
void extract_range_from_phi_node (gphi *, value_range *);
void extract_range_from_cond_expr (value_range *, gassign *);
void extract_range_basic (value_range *, gimple *);
void extract_range_from_assignment (value_range *, gassign *);
void extract_range_from_stmt (gimple *, edge *, tree *, value_range *);
void extract_range_from_comparison (value_range *, enum tree_code,
tree, tree, tree);
void vrp_visit_assignment_or_call (gimple*, tree *, value_range *);
void vrp_visit_switch_stmt (gswitch *, edge *);
void vrp_visit_cond_stmt (gcond *, 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 *);
void simplify_cond_using_ranges_2 (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 simplify_stmt_using_ranges (gimple_stmt_iterator *);
};
#endif /* GCC_VR_VALUES_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment