From: Aldy Hernandez Date: Thu, 18 Jun 2020 08:37:14 +0000 (+0200) Subject: Move simplification of statements using ranges into its own class. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=fc36b97af05ef74b0889ba49090c2f52f00e0e77;p=gcc.git Move simplification of statements using ranges into its own class. This moves all the simplification code from vr_values into a separate class (simplify_using_ranges). In doing so, we get rid of a bunch of dependencies on the internals of vr_values. The goal is to (a) remove unnecessary interdependendcies (b) be able to use this engine with any range infrastructure, as all it needs is a method to get the range for an SSA name (get_value_range). I also removed as many dependencies on value_range_equiv as possible, preferring value_range. A few value_range_equiv uses remain, but for cases where equivalences are actually used (folding conditionals, etc). gcc/ChangeLog: * gimple-ssa-evrp-analyze.h (vrp_visit_cond_stmt): Use simplify_using_ranges class. * gimple-ssa-evrp.c (class evrp_folder): New simplify_using_ranges field. Adjust all methods to use new field. * tree-ssa-dom.c (simplify_stmt_for_jump_threading): Use simplify_using_ranges class. * tree-vrp.c (class vrp_folder): New simplify_using_ranges field. Adjust all methods to use new field. (simplify_stmt_for_jump_threading): Use simplify_using_ranges class. (vrp_prop::vrp_finalize): New vrp_folder argument. (execute_vrp): Pass folder to vrp_finalize. Use simplify_using_ranges class. Remove cleanup_edges_and_switches call. * vr-values.c (vr_values::op_with_boolean_value_range_p): Change value_range_equiv uses to value_range. (simplify_using_ranges::op_with_boolean_value_range_p): Use simplify_using_ranges class. (check_for_binary_op_overflow): Make static. (vr_values::extract_range_basic): Pass this to check_for_binary_op_overflow. (compare_range_with_value): Change value_range_equiv uses to value_range. (vr_values::vr_values): Initialize simplifier field. Remove uses of to_remove_edges and to_update_switch_stmts. (vr_values::~vr_values): Remove uses of to_remove_edges and to_update_switch_stmts. (vr_values::get_vr_for_comparison): Move to simplify_using_ranges class. (vr_values::compare_name_with_value): Same. (vr_values::compare_names): Same. (vr_values::vrp_evaluate_conditional_warnv_with_ops): Same. (vr_values::vrp_evaluate_conditional): Same. (vr_values::vrp_visit_cond_stmt): Same. (find_case_label_ranges): Change value_range_equiv uses to value_range. (vr_values::extract_range_from_stmt): Use simplify_using_ranges class. (vr_values::simplify_truth_ops_using_ranges): Move to simplify_using_ranges class. (vr_values::simplify_div_or_mod_using_ranges): Same. (vr_values::simplify_min_or_max_using_ranges): Same. (vr_values::simplify_abs_using_ranges): Same. (vr_values::simplify_bit_ops_using_ranges): Same. (test_for_singularity): Change value_range_equiv uses to value_range. (range_fits_type_p): Same. (vr_values::simplify_cond_using_ranges_1): Same. (vr_values::simplify_cond_using_ranges_2): Make extern. (vr_values::fold_cond): Move to simplify_using_ranges class. (vr_values::simplify_switch_using_ranges): Same. (vr_values::cleanup_edges_and_switches): Same. (vr_values::simplify_float_conversion_using_ranges): Same. (vr_values::simplify_internal_call_using_ranges): Same. (vr_values::two_valued_val_range_p): Same. (vr_values::simplify_stmt_using_ranges): Move to... (simplify_using_ranges::simplify): ...here. * vr-values.h (class vr_values): Move all the simplification of statements using ranges methods and code from here... (class simplify_using_ranges): ...to here. (simplify_cond_using_ranges_2): New extern prototype. --- diff --git a/gcc/gimple-ssa-evrp-analyze.h b/gcc/gimple-ssa-evrp-analyze.h index d16279f89b9..8abbbe3180d 100644 --- a/gcc/gimple-ssa-evrp-analyze.h +++ b/gcc/gimple-ssa-evrp-analyze.h @@ -50,7 +50,10 @@ class evrp_range_analyzer /* A bit of a wart. This should ideally go away. */ void vrp_visit_cond_stmt (gcond *cond, edge *e) - { return vr_values->vrp_visit_cond_stmt (cond, e); } + { + simplify_using_ranges simpl (vr_values); + simpl.vrp_visit_cond_stmt (cond, e); + } /* Get the underlying vr_values class instance. If TRANSFER is true, then we are transferring ownership. Else we keep ownership. diff --git a/gcc/gimple-ssa-evrp.c b/gcc/gimple-ssa-evrp.c index af780fd0519..e8fde63aa34 100644 --- a/gcc/gimple-ssa-evrp.c +++ b/gcc/gimple-ssa-evrp.c @@ -46,14 +46,13 @@ class evrp_folder : public substitute_and_fold_engine { public: evrp_folder () : m_range_analyzer (/*update_global_ranges=*/true), - m_vr_values (m_range_analyzer.get_vr_values ()) + m_vr_values (m_range_analyzer.get_vr_values ()), + simplifier (m_vr_values) { } ~evrp_folder () { - m_vr_values->cleanup_edges_and_switches (); - if (dump_file) { fprintf (dump_file, "\nValue ranges after Early VRP:\n\n"); @@ -86,7 +85,7 @@ public: bool fold_stmt (gimple_stmt_iterator *gsi) OVERRIDE { - return m_vr_values->simplify_stmt_using_ranges (gsi); + return simplifier.simplify (gsi); } void post_fold_bb (basic_block bb) OVERRIDE @@ -96,13 +95,15 @@ public: void post_new_stmt (gimple *stmt) OVERRIDE { - m_vr_values->set_defs_to_varying (stmt); + m_range_analyzer.get_vr_values ()->set_defs_to_varying (stmt); } private: DISABLE_COPY_AND_ASSIGN (evrp_folder); class evrp_range_analyzer m_range_analyzer; class vr_values *m_vr_values; + + simplify_using_ranges simplifier; }; /* Main entry point for the early vrp pass which is a simplified non-iterative diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c index 864c984f636..69eaec345bf 100644 --- a/gcc/tree-ssa-dom.c +++ b/gcc/tree-ssa-dom.c @@ -887,12 +887,11 @@ simplify_stmt_for_jump_threading (gimple *stmt, copy in tree-vrp is scheduled for removal in gcc-9. */ if (gcond *cond_stmt = dyn_cast (stmt)) { - cached_lhs - = x_vr_values->vrp_evaluate_conditional (gimple_cond_code (cond_stmt), - gimple_cond_lhs (cond_stmt), - gimple_cond_rhs (cond_stmt), - within_stmt); - return cached_lhs; + simplify_using_ranges simplifier (x_vr_values); + return simplifier.vrp_evaluate_conditional (gimple_cond_code (cond_stmt), + gimple_cond_lhs (cond_stmt), + gimple_cond_rhs (cond_stmt), + within_stmt); } if (gswitch *switch_stmt = dyn_cast (stmt)) diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index c39a6f5e374..7193ca4ad5e 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -3373,7 +3373,7 @@ public: struct function *fun; void vrp_initialize (struct function *); - void vrp_finalize (bool); + void vrp_finalize (class vrp_folder *, bool); class vr_values vr_values; @@ -3938,23 +3938,28 @@ vrp_prop::visit_phi (gphi *phi) class vrp_folder : public substitute_and_fold_engine { -public: - vrp_folder () : substitute_and_fold_engine (/* Fold all stmts. */ true) { } + public: + vrp_folder (vr_values *v) + : substitute_and_fold_engine (/* Fold all stmts. */ true), + m_vr_values (v), simplifier (v) + { } tree get_value (tree, gimple *stmt) FINAL OVERRIDE; bool fold_stmt (gimple_stmt_iterator *) FINAL OVERRIDE; - class vr_values *vr_values; + class vr_values *m_vr_values; private: bool fold_predicate_in (gimple_stmt_iterator *); /* Delegators. */ tree vrp_evaluate_conditional (tree_code code, tree op0, tree op1, gimple *stmt) - { return vr_values->vrp_evaluate_conditional (code, op0, op1, stmt); } + { return simplifier.vrp_evaluate_conditional (code, op0, op1, stmt); } bool simplify_stmt_using_ranges (gimple_stmt_iterator *gsi) - { return vr_values->simplify_stmt_using_ranges (gsi); } + { return simplifier.simplify (gsi); } tree op_with_constant_singleton_value_range (tree op) - { return vr_values->op_with_constant_singleton_value_range (op); } + { return m_vr_values->op_with_constant_singleton_value_range (op); } + + simplify_using_ranges simplifier; }; /* If the statement pointed by SI has a predicate whose value can be @@ -4096,7 +4101,8 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt, tree op1 = gimple_cond_rhs (cond_stmt); op1 = lhs_of_dominating_assert (op1, bb, stmt); - return vr_values->vrp_evaluate_conditional (gimple_cond_code (cond_stmt), + simplify_using_ranges simplifier (vr_values); + return simplifier.vrp_evaluate_conditional (gimple_cond_code (cond_stmt), op0, op1, within_stmt); } @@ -4332,7 +4338,7 @@ identify_jump_threads (struct function *fun, class vr_values *vr_values) /* Traverse all the blocks folding conditionals with known ranges. */ void -vrp_prop::vrp_finalize (bool warn_array_bounds_p) +vrp_prop::vrp_finalize (vrp_folder *folder, bool warn_array_bounds_p) { size_t i; @@ -4376,9 +4382,7 @@ vrp_prop::vrp_finalize (bool warn_array_bounds_p) if (warn_array_bounds && warn_array_bounds_p) set_all_edges_as_executable (fun); - class vrp_folder vrp_folder; - vrp_folder.vr_values = &vr_values; - vrp_folder.substitute_and_fold (); + folder->substitute_and_fold (); if (warn_array_bounds && warn_array_bounds_p) { @@ -4453,7 +4457,10 @@ execute_vrp (struct function *fun, bool warn_array_bounds_p) class vrp_prop vrp_prop; vrp_prop.vrp_initialize (fun); vrp_prop.ssa_propagate (); - vrp_prop.vrp_finalize (warn_array_bounds_p); + /* Instantiate the folder here, so that edge cleanups happen at the + end of this function. */ + vrp_folder folder (&vrp_prop.vr_values); + vrp_prop.vrp_finalize (&folder, warn_array_bounds_p); /* We must identify jump threading opportunities before we release the datastructures built by VRP. */ @@ -4471,7 +4478,8 @@ execute_vrp (struct function *fun, bool warn_array_bounds_p) { gimple *last = last_stmt (bb); if (last && gimple_code (last) == GIMPLE_COND) - vrp_prop.vr_values.simplify_cond_using_ranges_2 (as_a (last)); + simplify_cond_using_ranges_2 (&vrp_prop.vr_values, + as_a (last)); } free_numbers_of_iterations_estimates (fun); @@ -4496,7 +4504,6 @@ execute_vrp (struct function *fun, bool warn_array_bounds_p) processing by the pass manager. */ thread_through_all_blocks (false); - vrp_prop.vr_values.cleanup_edges_and_switches (); threadedge_finalize_values (); scev_finalize (); diff --git a/gcc/vr-values.c b/gcc/vr-values.c index e95df78870a..d0303599002 100644 --- a/gcc/vr-values.c +++ b/gcc/vr-values.c @@ -435,10 +435,8 @@ vr_values::op_with_constant_singleton_value_range (tree op) /* Return true if op is in a boolean [0, 1] value-range. */ bool -vr_values::op_with_boolean_value_range_p (tree op) +simplify_using_ranges::op_with_boolean_value_range_p (tree op) { - const value_range_equiv *vr; - if (TYPE_PRECISION (TREE_TYPE (op)) == 1) return true; @@ -449,7 +447,7 @@ vr_values::op_with_boolean_value_range_p (tree op) if (TREE_CODE (op) != SSA_NAME) return false; - vr = get_value_range (op); + const value_range *vr = get_value_range (op); return (vr->kind () == VR_RANGE && integer_zerop (vr->min ()) && integer_onep (vr->max ())); @@ -976,10 +974,9 @@ vr_values::extract_range_from_comparison (value_range_equiv *vr, tree type, tree op0, tree op1) { bool sop; - tree val; - - val = vrp_evaluate_conditional_warnv_with_ops (code, op0, op1, false, &sop, - NULL); + tree val + = simplifier.vrp_evaluate_conditional_warnv_with_ops (code, op0, op1, + false, &sop, NULL); if (val) { /* Since this expression was found on the RHS of an assignment, @@ -1002,20 +999,21 @@ vr_values::extract_range_from_comparison (value_range_equiv *vr, always overflow. Set *OVF to true if it is known to always overflow. */ -bool -vr_values::check_for_binary_op_overflow (enum tree_code subcode, tree type, - tree op0, tree op1, bool *ovf) +static bool +check_for_binary_op_overflow (vr_values *store, + enum tree_code subcode, tree type, + tree op0, tree op1, bool *ovf) { value_range vr0, vr1; if (TREE_CODE (op0) == SSA_NAME) - vr0 = *get_value_range (op0); + vr0 = *store->get_value_range (op0); else if (TREE_CODE (op0) == INTEGER_CST) vr0.set (op0); else vr0.set_varying (TREE_TYPE (op0)); if (TREE_CODE (op1) == SSA_NAME) - vr1 = *get_value_range (op1); + vr1 = *store->get_value_range (op1); else if (TREE_CODE (op1) == INTEGER_CST) vr1.set (op1); else @@ -1395,7 +1393,7 @@ vr_values::extract_range_basic (value_range_equiv *vr, gimple *stmt) if (code == IMAGPART_EXPR) { bool ovf = false; - if (check_for_binary_op_overflow (subcode, type, + if (check_for_binary_op_overflow (this, subcode, type, op0, op1, &ovf)) vr->set (build_int_cst (type, ovf)); else if (TYPE_PRECISION (type) == 1 @@ -1636,7 +1634,7 @@ compare_ranges (enum tree_code comp, const value_range_equiv *vr0, assumed signed overflow is undefined. */ static tree -compare_range_with_value (enum tree_code comp, const value_range_equiv *vr, +compare_range_with_value (enum tree_code comp, const value_range *vr, tree val, bool *strict_overflow_p) { if (vr->varying_p () || vr->undefined_p ()) @@ -1946,15 +1944,14 @@ vr_values::dump_all_value_ranges (FILE *file) /* Initialize VRP lattice. */ -vr_values::vr_values () : vrp_value_range_pool ("Tree VRP value ranges") +vr_values::vr_values () : vrp_value_range_pool ("Tree VRP value ranges"), + simplifier (this) { values_propagated = false; num_vr_values = num_ssa_names * 2; vr_value = XCNEWVEC (value_range_equiv *, num_vr_values); vr_phi_edge_counts = XCNEWVEC (int, num_ssa_names); bitmap_obstack_initialize (&vrp_equiv_obstack); - to_remove_edges = vNULL; - to_update_switch_stmts = vNULL; } /* Free VRP lattice. */ @@ -1971,12 +1968,6 @@ vr_values::~vr_values () and not available. */ vr_value = NULL; vr_phi_edge_counts = NULL; - - /* If there are entries left in TO_REMOVE_EDGES or TO_UPDATE_SWITCH_STMTS - then an EVRP client did not clean up properly. Catch it now rather - than seeing something more obscure later. */ - gcc_assert (to_remove_edges.is_empty () - && to_update_switch_stmts.is_empty ()); } @@ -2094,7 +2085,7 @@ vr_values::vrp_visit_assignment_or_call (gimple *stmt, tree *output_p, is varying or undefined. Uses TEM as storage for the alternate range. */ const value_range_equiv * -vr_values::get_vr_for_comparison (int i, value_range_equiv *tem) +simplify_using_ranges::get_vr_for_comparison (int i, value_range_equiv *tem) { /* Shallow-copy equiv bitmap. */ const value_range_equiv *vr = get_value_range (ssa_name (i)); @@ -2117,8 +2108,9 @@ vr_values::get_vr_for_comparison (int i, value_range_equiv *tem) *STRICT_OVERFLOW_P. */ tree -vr_values::compare_name_with_value (enum tree_code comp, tree var, tree val, - bool *strict_overflow_p, bool use_equiv_p) +simplify_using_ranges::compare_name_with_value + (enum tree_code comp, tree var, tree val, + bool *strict_overflow_p, bool use_equiv_p) { /* Get the set of equivalences for VAR. */ bitmap e = get_value_range (var)->equiv (); @@ -2196,8 +2188,8 @@ vr_values::compare_name_with_value (enum tree_code comp, tree var, tree val, tree -vr_values::compare_names (enum tree_code comp, tree n1, tree n2, - bool *strict_overflow_p) +simplify_using_ranges::compare_names (enum tree_code comp, tree n1, tree n2, + bool *strict_overflow_p) { /* Compare the ranges of every name equivalent to N1 against the ranges of every name equivalent to N2. */ @@ -2310,7 +2302,7 @@ vr_values::compare_names (enum tree_code comp, tree n1, tree n2, optimizers. */ tree -vr_values::vrp_evaluate_conditional_warnv_with_ops_using_ranges +simplify_using_ranges::vrp_evaluate_conditional_warnv_with_ops_using_ranges (enum tree_code code, tree op0, tree op1, bool * strict_overflow_p) { const value_range_equiv *vr0, *vr1; @@ -2331,11 +2323,12 @@ vr_values::vrp_evaluate_conditional_warnv_with_ops_using_ranges /* Helper function for vrp_evaluate_conditional_warnv. */ tree -vr_values::vrp_evaluate_conditional_warnv_with_ops (enum tree_code code, - tree op0, tree op1, - bool use_equiv_p, - bool *strict_overflow_p, - bool *only_ranges) +simplify_using_ranges::vrp_evaluate_conditional_warnv_with_ops + (enum tree_code code, + tree op0, tree op1, + bool use_equiv_p, + bool *strict_overflow_p, + bool *only_ranges) { tree ret; if (only_ranges) @@ -2438,8 +2431,8 @@ vr_values::vrp_evaluate_conditional_warnv_with_ops (enum tree_code code, appropriate. */ tree -vr_values::vrp_evaluate_conditional (tree_code code, tree op0, - tree op1, gimple *stmt) +simplify_using_ranges::vrp_evaluate_conditional (tree_code code, tree op0, + tree op1, gimple *stmt) { bool sop; tree ret; @@ -2531,7 +2524,7 @@ vr_values::vrp_evaluate_conditional (tree_code code, tree op0, *TAKEN_EDGE_P. Otherwise, set *TAKEN_EDGE_P to NULL. */ void -vr_values::vrp_visit_cond_stmt (gcond *stmt, edge *taken_edge_p) +simplify_using_ranges::vrp_visit_cond_stmt (gcond *stmt, edge *taken_edge_p) { tree val; @@ -2551,7 +2544,7 @@ vr_values::vrp_visit_cond_stmt (gcond *stmt, edge *taken_edge_p) fprintf (dump_file, "\t"); print_generic_expr (dump_file, use); fprintf (dump_file, ": "); - dump_value_range (dump_file, vr_value[SSA_NAME_VERSION (use)]); + dump_value_range (dump_file, get_value_range (use)); } fprintf (dump_file, "\n"); @@ -2624,7 +2617,7 @@ vr_values::vrp_visit_cond_stmt (gcond *stmt, edge *taken_edge_p) Returns true if the default label is not needed. */ static bool -find_case_label_ranges (gswitch *stmt, const value_range_equiv *vr, +find_case_label_ranges (gswitch *stmt, const value_range *vr, size_t *min_idx1, size_t *max_idx1, size_t *min_idx2, size_t *max_idx2) { @@ -2808,7 +2801,7 @@ vr_values::extract_range_from_stmt (gimple *stmt, edge *taken_edge_p, else if (is_gimple_assign (stmt) || is_gimple_call (stmt)) vrp_visit_assignment_or_call (stmt, output_p, vr); else if (gimple_code (stmt) == GIMPLE_COND) - vrp_visit_cond_stmt (as_a (stmt), taken_edge_p); + simplifier.vrp_visit_cond_stmt (as_a (stmt), taken_edge_p); else if (gimple_code (stmt) == GIMPLE_SWITCH) vrp_visit_switch_stmt (as_a (stmt), taken_edge_p); } @@ -3029,8 +3022,9 @@ update_range: /* Simplify boolean operations if the source is known to be already a boolean. */ bool -vr_values::simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi, - gimple *stmt) +simplify_using_ranges::simplify_truth_ops_using_ranges + (gimple_stmt_iterator *gsi, + gimple *stmt) { enum tree_code rhs_code = gimple_assign_rhs_code (stmt); tree lhs, op0, op1; @@ -3106,8 +3100,9 @@ vr_values::simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi, modulo. */ bool -vr_values::simplify_div_or_mod_using_ranges (gimple_stmt_iterator *gsi, - gimple *stmt) +simplify_using_ranges::simplify_div_or_mod_using_ranges + (gimple_stmt_iterator *gsi, + gimple *stmt) { enum tree_code rhs_code = gimple_assign_rhs_code (stmt); tree val = NULL; @@ -3115,7 +3110,7 @@ vr_values::simplify_div_or_mod_using_ranges (gimple_stmt_iterator *gsi, tree op1 = gimple_assign_rhs2 (stmt); tree op0min = NULL_TREE, op0max = NULL_TREE; tree op1min = op1; - const value_range_equiv *vr = NULL; + const value_range *vr = NULL; if (TREE_CODE (op0) == INTEGER_CST) { @@ -3231,8 +3226,9 @@ vr_values::simplify_div_or_mod_using_ranges (gimple_stmt_iterator *gsi, disjoint. Return true if we do simplify. */ bool -vr_values::simplify_min_or_max_using_ranges (gimple_stmt_iterator *gsi, - gimple *stmt) +simplify_using_ranges::simplify_min_or_max_using_ranges + (gimple_stmt_iterator *gsi, + gimple *stmt) { tree op0 = gimple_assign_rhs1 (stmt); tree op1 = gimple_assign_rhs2 (stmt); @@ -3279,10 +3275,11 @@ vr_values::simplify_min_or_max_using_ranges (gimple_stmt_iterator *gsi, ABS_EXPR into a NEGATE_EXPR. */ bool -vr_values::simplify_abs_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt) +simplify_using_ranges::simplify_abs_using_ranges (gimple_stmt_iterator *gsi, + gimple *stmt) { tree op = gimple_assign_rhs1 (stmt); - const value_range_equiv *vr = get_value_range (op); + const value_range *vr = get_value_range (op); if (vr) { @@ -3359,8 +3356,9 @@ vr_set_zero_nonzero_bits (const tree expr_type, operation is redundant. */ bool -vr_values::simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi, - gimple *stmt) +simplify_using_ranges::simplify_bit_ops_using_ranges + (gimple_stmt_iterator *gsi, + gimple *stmt) { tree op0 = gimple_assign_rhs1 (stmt); tree op1 = gimple_assign_rhs2 (stmt); @@ -3444,7 +3442,7 @@ vr_values::simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi, static tree test_for_singularity (enum tree_code cond_code, tree op0, - tree op1, const value_range_equiv *vr) + tree op1, const value_range *vr) { tree min = NULL; tree max = NULL; @@ -3502,7 +3500,7 @@ test_for_singularity (enum tree_code cond_code, tree op0, by PRECISION and UNSIGNED_P. */ static bool -range_fits_type_p (const value_range_equiv *vr, +range_fits_type_p (const value_range *vr, unsigned dest_precision, signop dest_sgn) { tree src_type; @@ -3554,7 +3552,7 @@ range_fits_type_p (const value_range_equiv *vr, conditional as such, and return TRUE. */ bool -vr_values::fold_cond (gcond *cond) +simplify_using_ranges::fold_cond (gcond *cond) { /* ?? vrp_folder::fold_predicate_in() is a superset of this. At some point we should merge all variants of this code. */ @@ -3579,7 +3577,7 @@ vr_values::fold_cond (gcond *cond) the original conditional. */ bool -vr_values::simplify_cond_using_ranges_1 (gcond *stmt) +simplify_using_ranges::simplify_cond_using_ranges_1 (gcond *stmt) { tree op0 = gimple_cond_lhs (stmt); tree op1 = gimple_cond_rhs (stmt); @@ -3594,7 +3592,7 @@ vr_values::simplify_cond_using_ranges_1 (gcond *stmt) && INTEGRAL_TYPE_P (TREE_TYPE (op0)) && is_gimple_min_invariant (op1)) { - const value_range_equiv *vr = get_value_range (op0); + const value_range *vr = get_value_range (op0); /* If we have range information for OP0, then we might be able to simplify this conditional. */ @@ -3667,7 +3665,7 @@ vr_values::simplify_cond_using_ranges_1 (gcond *stmt) subsequent passes. */ void -vr_values::simplify_cond_using_ranges_2 (gcond *stmt) +simplify_cond_using_ranges_2 (vr_values *store, gcond *stmt) { tree op0 = gimple_cond_lhs (stmt); tree op1 = gimple_cond_rhs (stmt); @@ -3697,7 +3695,7 @@ vr_values::simplify_cond_using_ranges_2 (gcond *stmt) && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (innerop) && desired_pro_or_demotion_p (TREE_TYPE (innerop), TREE_TYPE (op0))) { - const value_range_equiv *vr = get_value_range (innerop); + const value_range *vr = store->get_value_range (innerop); if (range_int_cst_p (vr) && range_fits_type_p (vr, @@ -3724,10 +3722,10 @@ vr_values::simplify_cond_using_ranges_2 (gcond *stmt) argument. */ bool -vr_values::simplify_switch_using_ranges (gswitch *stmt) +simplify_using_ranges::simplify_switch_using_ranges (gswitch *stmt) { tree op = gimple_switch_index (stmt); - const value_range_equiv *vr = NULL; + const value_range *vr = NULL; bool take_default; edge e; edge_iterator ei; @@ -3905,7 +3903,7 @@ vr_values::simplify_switch_using_ranges (gswitch *stmt) } void -vr_values::cleanup_edges_and_switches (void) +simplify_using_ranges::cleanup_edges_and_switches (void) { int i; edge e; @@ -4023,11 +4021,12 @@ simplify_conversion_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt) /* Simplify a conversion from integral SSA name to float in STMT. */ bool -vr_values::simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi, - gimple *stmt) +simplify_using_ranges::simplify_float_conversion_using_ranges + (gimple_stmt_iterator *gsi, + gimple *stmt) { tree rhs1 = gimple_assign_rhs1 (stmt); - const value_range_equiv *vr = get_value_range (rhs1); + const value_range *vr = get_value_range (rhs1); scalar_float_mode fltmode = SCALAR_FLOAT_TYPE_MODE (TREE_TYPE (gimple_assign_lhs (stmt))); scalar_int_mode mode; @@ -4085,8 +4084,9 @@ vr_values::simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi, /* Simplify an internal fn call using ranges if possible. */ bool -vr_values::simplify_internal_call_using_ranges (gimple_stmt_iterator *gsi, - gimple *stmt) +simplify_using_ranges::simplify_internal_call_using_ranges + (gimple_stmt_iterator *gsi, + gimple *stmt) { enum tree_code subcode; bool is_ubsan = false; @@ -4131,7 +4131,7 @@ vr_values::simplify_internal_call_using_ranges (gimple_stmt_iterator *gsi, return false; else type = TREE_TYPE (TREE_TYPE (gimple_call_lhs (stmt))); - if (!check_for_binary_op_overflow (subcode, type, op0, op1, &ovf) + if (!check_for_binary_op_overflow (store, subcode, type, op0, op1, &ovf) || (is_ubsan && ovf)) return false; @@ -4188,9 +4188,9 @@ vr_values::simplify_internal_call_using_ranges (gimple_stmt_iterator *gsi, two-values when it is true. Return false otherwise. */ bool -vr_values::two_valued_val_range_p (tree var, tree *a, tree *b) +simplify_using_ranges::two_valued_val_range_p (tree var, tree *a, tree *b) { - const value_range_equiv *vr = get_value_range (var); + const value_range *vr = get_value_range (var); if (vr->varying_p () || vr->undefined_p () || TREE_CODE (vr->min ()) != INTEGER_CST @@ -4220,10 +4220,22 @@ vr_values::two_valued_val_range_p (tree var, tree *a, tree *b) return false; } +simplify_using_ranges::simplify_using_ranges (vr_values *store) + : store (store) +{ + to_remove_edges = vNULL; + to_update_switch_stmts = vNULL; +} + +simplify_using_ranges::~simplify_using_ranges () +{ + cleanup_edges_and_switches (); +} + /* Simplify STMT using ranges if possible. */ bool -vr_values::simplify_stmt_using_ranges (gimple_stmt_iterator *gsi) +simplify_using_ranges::simplify (gimple_stmt_iterator *gsi) { gimple *stmt = gsi_stmt (*gsi); if (is_gimple_assign (stmt)) diff --git a/gcc/vr-values.h b/gcc/vr-values.h index ac25139762a..62a20218c6d 100644 --- a/gcc/vr-values.h +++ b/gcc/vr-values.h @@ -22,6 +22,65 @@ along with GCC; see the file COPYING3. If not see #include "value-range-equiv.h" +// Class to simplify a statement using range information. +// +// The constructor takes a full vr_values, but all it needs is +// get_value_range() from it. This class could be made to work with +// any range repository. + +class simplify_using_ranges +{ +public: + simplify_using_ranges (class vr_values *); + ~simplify_using_ranges (); + bool simplify (gimple_stmt_iterator *); + + // ?? These should be cleaned, merged, and made private. + tree vrp_evaluate_conditional (tree_code, tree, tree, gimple *); + void vrp_visit_cond_stmt (gcond *, edge *); + tree vrp_evaluate_conditional_warnv_with_ops (enum tree_code, + tree, tree, bool, + bool *, bool *); + +private: + const value_range_equiv *get_value_range (const_tree op); + bool simplify_truth_ops_using_ranges (gimple_stmt_iterator *, gimple *); + bool simplify_div_or_mod_using_ranges (gimple_stmt_iterator *, gimple *); + bool simplify_abs_using_ranges (gimple_stmt_iterator *, gimple *); + bool simplify_bit_ops_using_ranges (gimple_stmt_iterator *, gimple *); + bool simplify_min_or_max_using_ranges (gimple_stmt_iterator *, gimple *); + bool simplify_cond_using_ranges_1 (gcond *); + bool fold_cond (gcond *); + bool simplify_switch_using_ranges (gswitch *); + bool simplify_float_conversion_using_ranges (gimple_stmt_iterator *, + gimple *); + bool simplify_internal_call_using_ranges (gimple_stmt_iterator *, gimple *); + + bool two_valued_val_range_p (tree, tree *, tree *); + bool op_with_boolean_value_range_p (tree); + tree compare_name_with_value (enum tree_code, tree, tree, bool *, bool); + tree compare_names (enum tree_code, tree, tree, bool *); + const value_range_equiv *get_vr_for_comparison (int, value_range_equiv *); + tree vrp_evaluate_conditional_warnv_with_ops_using_ranges (enum tree_code, + tree, tree, + bool *); + void cleanup_edges_and_switches (void); + + /* Vectors of edges that need removing and switch statements that + need updating. It is expected that a pass using the simplification + routines will, at the end of the pass, clean up the edges and + switch statements. The class dtor will try to detect cases + that do not follow that expectation. */ + struct switch_update { + gswitch *stmt; + tree vec; + }; + + vec to_remove_edges; + vec to_update_switch_stmts; + class vr_values *store; +}; + /* The VR_VALUES class holds the current view of range information for all the SSA_NAMEs in the IL. @@ -52,7 +111,6 @@ class vr_values tree op_with_constant_singleton_value_range (tree); void adjust_range_with_scev (value_range_equiv *, class loop *, gimple *, tree); - tree vrp_evaluate_conditional (tree_code, tree, tree, gimple *); void dump_all_value_ranges (FILE *); void extract_range_for_var_from_comparison_expr (tree, enum tree_code, @@ -62,11 +120,6 @@ class vr_values void extract_range_basic (value_range_equiv *, gimple *); void extract_range_from_stmt (gimple *, edge *, tree *, value_range_equiv *); - void vrp_visit_cond_stmt (gcond *, edge *); - - void simplify_cond_using_ranges_2 (gcond *); - bool simplify_stmt_using_ranges (gimple_stmt_iterator *); - /* Indicate that propagation through the lattice is complete. */ void set_lattice_propagation_complete (void) { values_propagated = true; } @@ -76,24 +129,9 @@ class vr_values void free_value_range (value_range_equiv *vr) { vrp_value_range_pool.remove (vr); } - /* */ - void cleanup_edges_and_switches (void); - private: value_range_equiv *get_lattice_entry (const_tree); bool vrp_stmt_computes_nonzero (gimple *); - bool op_with_boolean_value_range_p (tree); - bool check_for_binary_op_overflow (enum tree_code, tree, tree, tree, bool *); - const value_range_equiv *get_vr_for_comparison (int, value_range_equiv *); - tree compare_name_with_value (enum tree_code, tree, tree, bool *, bool); - tree compare_names (enum tree_code, tree, tree, bool *); - bool two_valued_val_range_p (tree, tree *, tree *); - tree vrp_evaluate_conditional_warnv_with_ops_using_ranges (enum tree_code, - tree, tree, - bool *); - tree vrp_evaluate_conditional_warnv_with_ops (enum tree_code, - tree, tree, bool, - bool *, bool *); void extract_range_from_assignment (value_range_equiv *, gassign *); void extract_range_from_assert (value_range_equiv *, tree); void extract_range_from_ssa_name (value_range_equiv *, tree); @@ -106,17 +144,6 @@ class vr_values tree, tree, tree); void vrp_visit_assignment_or_call (gimple*, tree *, value_range_equiv *); void vrp_visit_switch_stmt (gswitch *, edge *); - bool simplify_truth_ops_using_ranges (gimple_stmt_iterator *, gimple *); - bool simplify_div_or_mod_using_ranges (gimple_stmt_iterator *, gimple *); - bool simplify_abs_using_ranges (gimple_stmt_iterator *, gimple *); - bool simplify_bit_ops_using_ranges (gimple_stmt_iterator *, gimple *); - bool simplify_min_or_max_using_ranges (gimple_stmt_iterator *, gimple *); - bool simplify_cond_using_ranges_1 (gcond *); - bool fold_cond (gcond *); - bool simplify_switch_using_ranges (gswitch *); - bool simplify_float_conversion_using_ranges (gimple_stmt_iterator *, - gimple *); - bool simplify_internal_call_using_ranges (gimple_stmt_iterator *, gimple *); /* Allocation pools for value_range objects. */ object_allocator vrp_value_range_pool; @@ -136,20 +163,18 @@ class vr_values number of executable edges we saw the last time we visited the node. */ int *vr_phi_edge_counts; - - /* Vectors of edges that need removing and switch statements that - need updating. It is expected that a pass using the simplification - routines will, at the end of the pass, clean up the edges and - switch statements. The class dtor will try to detect cases - that do not follow that expectation. */ - struct switch_update { - gswitch *stmt; - tree vec; - }; - - vec to_remove_edges; - vec to_update_switch_stmts; + simplify_using_ranges simplifier; }; +inline const value_range_equiv * +simplify_using_ranges::get_value_range (const_tree op) +{ + return store->get_value_range (op); +} + extern tree get_output_for_vrp (gimple *); + +// FIXME: Move this to tree-vrp.c. +void simplify_cond_using_ranges_2 (class vr_values *, gcond *); + #endif /* GCC_VR_VALUES_H */