From: Jeff Law Date: Thu, 9 Nov 2017 23:26:08 +0000 (-0700) Subject: vr-values.h: New file with vr_values class. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=89759031c533742283a5dbad7674563dca663ec3;p=gcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9b93a852099..0c6f9489389 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,81 @@ 2017-11-09 Jeff Law + * 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. (vrp_folder): Likewise. diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index fc9ad4adebe..7173ab22478 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -64,13 +64,10 @@ along with GCC; see the file COPYING3. If not see #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 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; @@ -87,9 +84,6 @@ live_on_edge (edge e, tree name) /* 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 { @@ -145,17 +139,6 @@ static bitmap need_assert_for; 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; @@ -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 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 }; @@ -582,8 +565,8 @@ get_value_range (const_tree var) /* 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; @@ -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 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; @@ -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 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); @@ -933,8 +916,8 @@ gimple_stmt_nonzero_p (gimple *stmt) /* 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; @@ -1260,8 +1243,8 @@ value_range_constant_singleton (value_range *vr) 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; @@ -1274,8 +1257,8 @@ op_with_constant_singleton_value_range (tree 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; @@ -1298,10 +1281,11 @@ op_with_boolean_value_range_p (tree op) /* 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; @@ -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 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); @@ -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 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); @@ -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 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; @@ -3374,9 +3358,9 @@ extract_range_from_unary_expr (value_range *vr, 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; @@ -3389,15 +3373,15 @@ extract_range_from_unary_expr (value_range *vr, enum tree_code code, 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; @@ -3430,9 +3414,9 @@ extract_range_from_cond_expr (value_range *vr, gassign *stmt) /* 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; @@ -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 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; @@ -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. 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); @@ -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 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); @@ -3956,9 +3940,9 @@ extract_range_from_assignment (value_range *vr, gassign *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; @@ -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 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); @@ -4476,7 +4459,7 @@ debug_value_range (value_range *vr) /* 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; @@ -4494,16 +4477,6 @@ dump_all_value_ranges (FILE *file) 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 '. */ @@ -6640,6 +6613,28 @@ class vrp_prop : public ssa_propagation_engine 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 @@ -6649,8 +6644,9 @@ class vrp_prop : public ssa_propagation_engine 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; @@ -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 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 @@ -6828,12 +6824,13 @@ check_array_bounds (tree *tp, int *walk_subtree, void *data) *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; } @@ -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 on them. */ -static void -check_all_array_refs (void) +void +vrp_prop::check_all_array_refs () { basic_block bb; gimple_stmt_iterator si; @@ -6871,6 +6868,8 @@ check_all_array_refs (void) memset (&wi, 0, sizeof (wi)); + wi.info = this; + walk_gimple_op (gsi_stmt (si), check_array_bounds, &wi); @@ -7121,8 +7120,7 @@ stmt_interesting_for_vrp (gimple *stmt) /* 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; @@ -7133,8 +7131,8 @@ vrp_initialize_lattice () /* Initialization required by ssa_propagate engine. */ -static void -vrp_initialize () +void +vrp_prop::vrp_initialize () { basic_block bb; @@ -7175,6 +7173,9 @@ vrp_initialize () } } +/* A hack. */ +static class vr_values *x_vr_values; + /* Return the singleton value-range for NAME or NAME. */ static inline tree @@ -7182,7 +7183,7 @@ vrp_valueize (tree 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 && (TREE_CODE (vr->min) == SSA_NAME || is_gimple_min_invariant (vr->min)) @@ -7207,7 +7208,7 @@ vrp_valueize_1 (tree name) 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; } @@ -7217,8 +7218,9 @@ vrp_valueize_1 (tree name) /* 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); @@ -7237,8 +7239,10 @@ vrp_visit_assignment_or_call (gimple *stmt, tree *output_p, value_range *vr) *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 @@ -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 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)); @@ -7289,9 +7293,9 @@ get_vr_for_comparison (int 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; @@ -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. */ -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; @@ -7489,10 +7493,9 @@ compare_names (enum tree_code comp, tree n1, tree n2, /* 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; @@ -7512,10 +7515,12 @@ vrp_evaluate_conditional_warnv_with_ops_using_ranges (enum tree_code code, /* 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) @@ -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 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; @@ -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 *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; @@ -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 *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; @@ -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 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)) @@ -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 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); @@ -9205,8 +9211,9 @@ vrp_prop::visit_phi (gphi *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; @@ -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 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; @@ -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 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); @@ -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 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); @@ -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 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); @@ -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 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); @@ -9790,8 +9800,8 @@ simplify_cond_using_ranges_1 (gcond *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); @@ -9847,8 +9857,8 @@ simplify_cond_using_ranges_2 (gcond *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; @@ -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. */ -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); @@ -10169,8 +10179,9 @@ simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi, /* 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; @@ -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 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 @@ -10306,8 +10317,8 @@ two_valued_val_range_p (tree var, tree *a, tree *b) /* 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)) @@ -10455,14 +10466,26 @@ class vrp_folder : public substitute_and_fold_engine 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; @@ -10584,6 +10607,7 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt, 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 (stmt)) { tree op0 = gimple_cond_lhs (cond_stmt); @@ -10592,8 +10616,8 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt, tree op1 = gimple_cond_rhs (cond_stmt); op1 = lhs_of_dominating_assert (op1, bb, stmt); - return 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 @@ -10607,7 +10631,7 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_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) || symbolic_range_p (vr)) return NULL_TREE; @@ -10668,7 +10692,7 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt, && (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; } @@ -10691,11 +10715,14 @@ public: 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 @@ -10748,9 +10775,11 @@ vrp_dom_walker::after_dom_children (basic_block bb) 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 (); @@ -10777,7 +10806,7 @@ vrp_dom_walker::after_dom_children (basic_block bb) for later realization. */ static void -identify_jump_threads (void) +identify_jump_threads (class vr_values *vr_values) { int i; edge e; @@ -10809,6 +10838,7 @@ identify_jump_threads (void) = 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. */ @@ -10825,8 +10855,7 @@ identify_jump_threads (void) /* Free VRP lattice. */ -static void -vrp_free_lattice () +vr_values::~vr_values () { /* Free allocated memory. */ free (vr_value); @@ -10842,48 +10871,49 @@ vrp_free_lattice () /* 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) @@ -10917,6 +10947,38 @@ public: bitmap need_eh_cleanup; auto_vec stmts_to_fixup; auto_vec 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. */ @@ -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->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; } @@ -11208,6 +11270,7 @@ evrp_dom_walker::before_dom_children (basic_block bb) /* 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) @@ -11274,13 +11337,19 @@ evrp_dom_walker::after_dom_children (basic_block bb ATTRIBUTE_UNUSED) 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 "); @@ -11290,7 +11359,7 @@ evrp_dom_walker::push_value_range (tree var, value_range *vr) 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. */ @@ -11308,7 +11377,7 @@ evrp_dom_walker::pop_value_range (tree var) 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; } @@ -11335,7 +11404,6 @@ execute_early_vrp () 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; @@ -11344,7 +11412,7 @@ execute_early_vrp () 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"); } @@ -11382,7 +11450,6 @@ execute_early_vrp () fixup_noreturn_call (stmt); } - vrp_free_lattice (); scev_finalize (); loop_optimizer_finalize (); return 0; @@ -11456,15 +11523,14 @@ execute_vrp (bool warn_array_bounds_p) /* 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 @@ -11478,11 +11544,9 @@ execute_vrp (bool warn_array_bounds_p) { gimple *last = last_stmt (bb); if (last && gimple_code (last) == GIMPLE_COND) - simplify_cond_using_ranges_2 (as_a (last)); + vrp_prop.vr_values.simplify_cond_using_ranges_2 (as_a (last)); } - vrp_free_lattice (); - free_numbers_of_iterations_estimates (cfun); /* ASSERT_EXPRs must be removed before finalizing jump threads diff --git a/gcc/vr-values.h b/gcc/vr-values.h new file mode 100644 index 00000000000..3b38ab6e941 --- /dev/null +++ b/gcc/vr-values.h @@ -0,0 +1,119 @@ +/* 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 +. */ + +#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 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 */