On Fri, Nov 10, 2017 at 11:57 PM, Jeff Law <l...@redhat.com> wrote: > > And here's the monster that pulls the vr_values class out of tree-vrp.c. > I've also pulled out the transitive closure of free routines that are > used strictly by vr-values.c. > > Like the gimple-ssa-evrp.c change, this exposes various functions and > data structures that are still shared via tree-vrp.h. It's more than > I'd like. I expect some may ultimately turn into free routines exported > by vr-values.h. Bug again, the idea here is to be as much of a > cut-n-paste as possible, so I haven't tried to rationalize the exported > goop. > > Also like the gimple-ssa-evrp.c change the bits in vr-values.c are > straight copies of the bits that were in tree-vrp.c. > > Now we can start with deeper cleanups and further breakdown of evrp into > analysis & optimization components. > > > Bootstrapped and regression tested on x86_64. OK for the trunk?
Ok. Richard. > jeff > > commit 2305155d7ad9561b267458c58071b212ee758c2a > Author: Jeff Law <l...@torsion.usersys.redhat.com> > Date: Wed Nov 8 11:53:16 2017 -0500 > > * vr-values.c: New file with contents extracted from tree-vrp.c. > * Makefile.in (OBJS): Add vr-values.o > * tree-vrp.h (set_value_range_to_nonnull): Prototype. > (set_value_range, set_and_canonicalize_value_range): Likewise. > (vrp_bitmap_equal_p, range_is_nonnull): Likewise. > (value_range_constant_singleton, symbolic_range_p): Likewise. > (compare_values, compare_values_warnv, vrp_val_is_min): Likewise. > (vrp_val_is_max, copy_value_range, set_value_range_to_value): > Likewise. > (extract_range_from_binary_expr_1, vrp_val_min, vrp_val_max): > Likewise. > (set_value_range_to_null, range_int_cst_p, opreand_less_p): > Likewise. > (find_case_label_range, find_case_label_index): Likewise. > (zero_nonzero_bits_from_vr, overflow_comparison_p): Likewise. > (range_int_cst_singleton_p, value_inside_range): Likewise. > (get_single_symbol): Likewise. > (switch_update): Move structure definition here. > (to_remove_edges, to_update_switch_stmts): Provide externs. > * tree-vrp.c: Move all methods for vr-values class to vr-values.c > (vrp_val_max, vrp_val_min, vrp_val_is_max): Make externally > visible. > (vrp_val_is_min, set_value_range): Likewise. > (set_and_canonicalize_value_range, copy_value_range): Likewise. > (set_value_range_to_value, set_value_range_to_nonnull): Likewise. > (set_value_range_to_null, vrp_bitmap_equal_p): Likewise. > (range_is_nonnull, range_int_cst_p): Likewwise. > (range_int_cst_singleton_p, symbolic_range_p): Likewise. > (get_single_symbol, operand_less_p): Likewise > (compare_values_warnv, compare_values): Likewise. > (value_inside_range, value_range_constant_singleton): Likewise. > (zero_nonzero_bitgs_from_vr): Likewise. > (extract_range_from_binary_expr_1): Likewise. > (overflow_comparison_p): Likewise. > (to_remove_edges, to_update_switch_stmts): Likewise. > (find_case_label-index, find_case_label_range): Likewise. > (switch_update, set_value_range_to_nonnegative): Remove. > (set_value_range_to_truthvalue): Likewise. > (symbolic_range_based_on_p, gimple_assign_nonzero_p): Likewise. > (gimple_stmt_nonzero_p, compare_ranges): Likewise. > (compare_range_with_value, vrp_valueize, vrp_valueize_1): > Likewise. > (find_case_label_ranges, test_for_singularity): Likewise. > (range_fits_type_p, simplify_conversion_using_ranges): LIkewise. > (x_vr_values): Move to its remaining use site. > > diff --git a/gcc/ChangeLog b/gcc/ChangeLog > index 9e5b9340fe8..778b0ada7c3 100644 > --- a/gcc/ChangeLog > +++ b/gcc/ChangeLog > @@ -5,6 +5,49 @@ > with memcpy. > (find_subframework_file): Same. > > +2017-11-10 Jeff Law <l...@redhat.com> > + > + * vr-values.c: New file with contents extracted from tree-vrp.c. > + * Makefile.in (OBJS): Add vr-values.o > + * tree-vrp.h (set_value_range_to_nonnull): Prototype. > + (set_value_range, set_and_canonicalize_value_range): Likewise. > + (vrp_bitmap_equal_p, range_is_nonnull): Likewise. > + (value_range_constant_singleton, symbolic_range_p): Likewise. > + (compare_values, compare_values_warnv, vrp_val_is_min): Likewise. > + (vrp_val_is_max, copy_value_range, set_value_range_to_value): > Likewise. > + (extract_range_from_binary_expr_1, vrp_val_min, vrp_val_max): > Likewise. > + (set_value_range_to_null, range_int_cst_p, opreand_less_p): Likewise. > + (find_case_label_range, find_case_label_index): Likewise. > + (zero_nonzero_bits_from_vr, overflow_comparison_p): Likewise. > + (range_int_cst_singleton_p, value_inside_range): Likewise. > + (get_single_symbol): Likewise. > + (switch_update): Move structure definition here. > + (to_remove_edges, to_update_switch_stmts): Provide externs. > + * tree-vrp.c: Move all methods for vr-values class to vr-values.c > + (vrp_val_max, vrp_val_min, vrp_val_is_max): Make externally visible. > + (vrp_val_is_min, set_value_range): Likewise. > + (set_and_canonicalize_value_range, copy_value_range): Likewise. > + (set_value_range_to_value, set_value_range_to_nonnull): Likewise. > + (set_value_range_to_null, vrp_bitmap_equal_p): Likewise. > + (range_is_nonnull, range_int_cst_p): Likewwise. > + (range_int_cst_singleton_p, symbolic_range_p): Likewise. > + (get_single_symbol, operand_less_p): Likewise > + (compare_values_warnv, compare_values): Likewise. > + (value_inside_range, value_range_constant_singleton): Likewise. > + (zero_nonzero_bitgs_from_vr): Likewise. > + (extract_range_from_binary_expr_1): Likewise. > + (overflow_comparison_p): Likewise. > + (to_remove_edges, to_update_switch_stmts): Likewise. > + (find_case_label-index, find_case_label_range): Likewise. > + (switch_update, set_value_range_to_nonnegative): Remove. > + (set_value_range_to_truthvalue): Likewise. > + (symbolic_range_based_on_p, gimple_assign_nonzero_p): Likewise. > + (gimple_stmt_nonzero_p, compare_ranges): Likewise. > + (compare_range_with_value, vrp_valueize, vrp_valueize_1): Likewise. > + (find_case_label_ranges, test_for_singularity): Likewise. > + (range_fits_type_p, simplify_conversion_using_ranges): LIkewise. > + (x_vr_values): Move to its remaining use site. > + > 2017-11-10 Jeff Law <l...@redhat.com> > > * vr-values.h (VR_INITIALIZER): Move #define here. > diff --git a/gcc/Makefile.in b/gcc/Makefile.in > index 824cf3e3ea0..5db78558c0c 100644 > --- a/gcc/Makefile.in > +++ b/gcc/Makefile.in > @@ -1577,6 +1577,7 @@ OBJS = \ > varasm.o \ > varpool.o \ > vmsdbgout.o \ > + vr-values.o \ > vtable-verify.o \ > web.o \ > wide-int.o \ > diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c > index 6fae6b2efb8..945b3a9935e 100644 > --- a/gcc/tree-vrp.c > +++ b/gcc/tree-vrp.c > @@ -79,10 +79,6 @@ live_on_edge (edge e, tree name) > && bitmap_bit_p (live[e->dest->index], SSA_NAME_VERSION (name))); > } > > -/* Local functions. */ > -static int compare_values (tree val1, tree val2); > -static int compare_values_warnv (tree val1, tree val2, bool *); > - > /* Location information for ASSERT_EXPRs. Each instance of this > structure describes an ASSERT_EXPR for an SSA name. Since a single > SSA name may have more than one assertion associated with it, these > @@ -122,18 +118,13 @@ static bitmap need_assert_for; > ASSERT_EXPRs for SSA name N_I should be inserted. */ > static assert_locus **asserts_for; > > -struct switch_update { > - gswitch *stmt; > - tree vec; > -}; > - > -static vec<edge> to_remove_edges; > -static vec<switch_update> to_update_switch_stmts; > +vec<edge> to_remove_edges; > +vec<switch_update> to_update_switch_stmts; > > > /* Return the maximum value for TYPE. */ > > -static inline tree > +tree > vrp_val_max (const_tree type) > { > if (!INTEGRAL_TYPE_P (type)) > @@ -144,7 +135,7 @@ vrp_val_max (const_tree type) > > /* Return the minimum value for TYPE. */ > > -static inline tree > +tree > vrp_val_min (const_tree type) > { > if (!INTEGRAL_TYPE_P (type)) > @@ -158,7 +149,7 @@ vrp_val_min (const_tree type) > C typedefs and Ada subtypes can produce types whose TYPE_MAX_VALUE > is not == to the integer constant with the same value in the type. */ > > -static inline bool > +bool > vrp_val_is_max (const_tree val) > { > tree type_max = vrp_val_max (TREE_TYPE (val)); > @@ -169,7 +160,7 @@ vrp_val_is_max (const_tree val) > > /* Return whether VAL is equal to the minimum value of its type. */ > > -static inline bool > +bool > vrp_val_is_min (const_tree val) > { > tree type_min = vrp_val_min (TREE_TYPE (val)); > @@ -203,7 +194,7 @@ set_value_range_to_varying (value_range *vr) > > /* Set value range VR to {T, MIN, MAX, EQUIV}. */ > > -static void > +void > set_value_range (value_range *vr, enum value_range_type t, tree min, > tree max, bitmap equiv) > { > @@ -263,7 +254,7 @@ set_value_range (value_range *vr, enum value_range_type > t, tree min, > This routine exists to ease canonicalization in the case where we > extract ranges from var + CST op limit. */ > > -static void > +void > set_and_canonicalize_value_range (value_range *vr, enum value_range_type t, > tree min, tree max, bitmap equiv) > { > @@ -371,7 +362,7 @@ set_and_canonicalize_value_range (value_range *vr, enum > value_range_type t, > > /* Copy value range FROM into value range TO. */ > > -static inline void > +void > copy_value_range (value_range *to, value_range *from) > { > set_value_range (to, from->type, from->min, from->max, from->equiv); > @@ -381,7 +372,7 @@ copy_value_range (value_range *to, value_range *from) > with values we get from statements, and exists to clear the > TREE_OVERFLOW flag. */ > > -static inline void > +void > set_value_range_to_value (value_range *vr, tree val, bitmap equiv) > { > gcc_assert (is_gimple_min_invariant (val)); > @@ -390,18 +381,9 @@ set_value_range_to_value (value_range *vr, tree val, > bitmap equiv) > set_value_range (vr, VR_RANGE, val, val, equiv); > } > > -/* Set value range VR to a non-negative range of type TYPE. */ > - > -static inline void > -set_value_range_to_nonnegative (value_range *vr, tree type) > -{ > - tree zero = build_int_cst (type, 0); > - set_value_range (vr, VR_RANGE, zero, vrp_val_max (type), vr->equiv); > -} > - > /* Set value range VR to a non-NULL range of type TYPE. */ > > -static inline void > +void > set_value_range_to_nonnull (value_range *vr, tree type) > { > tree zero = build_int_cst (type, 0); > @@ -411,27 +393,13 @@ set_value_range_to_nonnull (value_range *vr, tree type) > > /* Set value range VR to a NULL range of type TYPE. */ > > -static inline void > +void > set_value_range_to_null (value_range *vr, tree type) > { > set_value_range_to_value (vr, build_int_cst (type, 0), vr->equiv); > } > > > -/* Set value range VR to a range of a truthvalue of type TYPE. */ > - > -static inline void > -set_value_range_to_truthvalue (value_range *vr, tree type) > -{ > - if (TYPE_PRECISION (type) == 1) > - set_value_range_to_varying (vr); > - else > - set_value_range (vr, VR_RANGE, > - build_int_cst (type, 0), build_int_cst (type, 1), > - vr->equiv); > -} > - > - > /* If abs (min) < abs (max), set VR to [-max, max], if > abs (min) >= abs (max), set VR to [-min, min]. */ > > @@ -467,100 +435,6 @@ abs_extent_range (value_range *vr, tree min, tree max) > set_and_canonicalize_value_range (vr, VR_RANGE, min, max, NULL); > } > > - > -/* Return value range information for VAR. > - > - 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. */ > - > -value_range * > -vr_values::get_value_range (const_tree var) > -{ > - static const value_range vr_const_varying > - = { VR_VARYING, NULL_TREE, NULL_TREE, NULL }; > - value_range *vr; > - tree sym; > - unsigned ver = SSA_NAME_VERSION (var); > - > - /* If we have no recorded ranges, then return NULL. */ > - if (! vr_value) > - return NULL; > - > - /* If we query the range for a new SSA name return an unmodifiable VARYING. > - We should get here at most from the substitute-and-fold stage which > - will never try to change values. */ > - if (ver >= num_vr_values) > - return CONST_CAST (value_range *, &vr_const_varying); > - > - vr = vr_value[ver]; > - if (vr) > - return vr; > - > - /* After propagation finished do not allocate new value-ranges. */ > - if (values_propagated) > - return CONST_CAST (value_range *, &vr_const_varying); > - > - /* Create a default value range. */ > - vr_value[ver] = vr = vrp_value_range_pool.allocate (); > - memset (vr, 0, sizeof (*vr)); > - > - /* Defer allocating the equivalence set. */ > - vr->equiv = NULL; > - > - /* If VAR is a default definition of a parameter, the variable can > - take any value in VAR's type. */ > - if (SSA_NAME_IS_DEFAULT_DEF (var)) > - { > - sym = SSA_NAME_VAR (var); > - if (TREE_CODE (sym) == PARM_DECL) > - { > - /* Try to use the "nonnull" attribute to create ~[0, 0] > - anti-ranges for pointers. Note that this is only valid with > - default definitions of PARM_DECLs. */ > - if (POINTER_TYPE_P (TREE_TYPE (sym)) > - && (nonnull_arg_p (sym) > - || get_ptr_nonnull (var))) > - set_value_range_to_nonnull (vr, TREE_TYPE (sym)); > - else if (INTEGRAL_TYPE_P (TREE_TYPE (sym))) > - { > - wide_int min, max; > - value_range_type rtype = get_range_info (var, &min, &max); > - if (rtype == VR_RANGE || rtype == VR_ANTI_RANGE) > - set_value_range (vr, rtype, > - wide_int_to_tree (TREE_TYPE (var), min), > - wide_int_to_tree (TREE_TYPE (var), max), > - NULL); > - else > - set_value_range_to_varying (vr); > - } > - else > - set_value_range_to_varying (vr); > - } > - else if (TREE_CODE (sym) == RESULT_DECL > - && DECL_BY_REFERENCE (sym)) > - set_value_range_to_nonnull (vr, TREE_TYPE (sym)); > - } > - > - return vr; > -} > - > -/* Set value-ranges of all SSA names defined by STMT to varying. */ > - > -void > -vr_values::set_defs_to_varying (gimple *stmt) > -{ > - ssa_op_iter i; > - tree def; > - FOR_EACH_SSA_TREE_OPERAND (def, stmt, i, SSA_OP_DEF) > - { > - value_range *vr = get_value_range (def); > - /* Avoid writing to vr_const_varying get_value_range may return. */ > - if (vr->type != VR_VARYING) > - set_value_range_to_varying (vr); > - } > -} > - > - > /* Return true, if VAL1 and VAL2 are equal values for VRP purposes. */ > > bool > @@ -575,7 +449,7 @@ vrp_operand_equal_p (const_tree val1, const_tree val2) > > /* Return true, if the bitmaps B1 and B2 are equal. */ > > -static inline bool > +bool > vrp_bitmap_equal_p (const_bitmap b1, const_bitmap b2) > { > return (b1 == b2 > @@ -585,92 +459,9 @@ vrp_bitmap_equal_p (const_bitmap b1, const_bitmap b2) > && bitmap_equal_p (b1, b2))); > } > > -/* Update the value range and equivalence set for variable VAR to > - NEW_VR. Return true if NEW_VR is different from VAR's previous > - value. > - > - NOTE: This function assumes that NEW_VR is a temporary value range > - object created for the sole purpose of updating VAR's range. The > - storage used by the equivalence set from NEW_VR will be freed by > - this function. Do not call update_value_range when NEW_VR > - is the range object associated with another SSA name. */ > - > -bool > -vr_values::update_value_range (const_tree var, value_range *new_vr) > -{ > - value_range *old_vr; > - bool is_new; > - > - /* If there is a value-range on the SSA name from earlier analysis > - factor that in. */ > - if (INTEGRAL_TYPE_P (TREE_TYPE (var))) > - { > - wide_int min, max; > - value_range_type rtype = get_range_info (var, &min, &max); > - if (rtype == VR_RANGE || rtype == VR_ANTI_RANGE) > - { > - tree nr_min, nr_max; > - nr_min = wide_int_to_tree (TREE_TYPE (var), min); > - nr_max = wide_int_to_tree (TREE_TYPE (var), max); > - value_range nr = VR_INITIALIZER; > - set_and_canonicalize_value_range (&nr, rtype, nr_min, nr_max, NULL); > - vrp_intersect_ranges (new_vr, &nr); > - } > - } > - > - /* Update the value range, if necessary. */ > - old_vr = get_value_range (var); > - is_new = old_vr->type != new_vr->type > - || !vrp_operand_equal_p (old_vr->min, new_vr->min) > - || !vrp_operand_equal_p (old_vr->max, new_vr->max) > - || !vrp_bitmap_equal_p (old_vr->equiv, new_vr->equiv); > - > - if (is_new) > - { > - /* Do not allow transitions up the lattice. The following > - is slightly more awkward than just new_vr->type < old_vr->type > - because VR_RANGE and VR_ANTI_RANGE need to be considered > - the same. We may not have is_new when transitioning to > - UNDEFINED. If old_vr->type is VARYING, we shouldn't be > - called. */ > - if (new_vr->type == VR_UNDEFINED) > - { > - BITMAP_FREE (new_vr->equiv); > - set_value_range_to_varying (old_vr); > - set_value_range_to_varying (new_vr); > - return true; > - } > - else > - set_value_range (old_vr, new_vr->type, new_vr->min, new_vr->max, > - new_vr->equiv); > - } > - > - BITMAP_FREE (new_vr->equiv); > - > - return is_new; > -} > - > - > -/* Add VAR and VAR's equivalence set to EQUIV. This is the central > - point where equivalence processing can be turned on/off. */ > - > -void > -vr_values::add_equivalence (bitmap *equiv, const_tree var) > -{ > - unsigned ver = SSA_NAME_VERSION (var); > - value_range *vr = get_value_range (var); > - > - if (*equiv == NULL) > - *equiv = BITMAP_ALLOC (&vrp_equiv_obstack); > - bitmap_set_bit (*equiv, ver); > - if (vr && vr->equiv) > - bitmap_ior_into (*equiv, vr->equiv); > -} > - > - > /* Return true if VR is ~[0, 0]. */ > > -static inline bool > +bool > range_is_nonnull (value_range *vr) > { > return vr->type == VR_ANTI_RANGE > @@ -692,7 +483,7 @@ range_is_null (value_range *vr) > /* Return true if max and min of VR are INTEGER_CST. It's not necessary > a singleton. */ > > -static inline bool > +bool > range_int_cst_p (value_range *vr) > { > return (vr->type == VR_RANGE > @@ -702,7 +493,7 @@ range_int_cst_p (value_range *vr) > > /* Return true if VR is a INTEGER_CST singleton. */ > > -static inline bool > +bool > range_int_cst_singleton_p (value_range *vr) > { > return (range_int_cst_p (vr) > @@ -711,7 +502,7 @@ range_int_cst_singleton_p (value_range *vr) > > /* Return true if value range VR involves at least one symbol. */ > > -static inline bool > +bool > symbolic_range_p (value_range *vr) > { > return (!is_gimple_min_invariant (vr->min) > @@ -722,7 +513,7 @@ symbolic_range_p (value_range *vr) > otherwise. We only handle additive operations and set NEG to true if the > symbol is negated and INV to the invariant part, if any. */ > > -static tree > +tree > get_single_symbol (tree t, bool *neg, tree *inv) > { > bool neg_; > @@ -791,161 +582,11 @@ build_symbolic_expr (tree type, tree sym, bool neg, > tree inv) > return build2 (pointer_p ? POINTER_PLUS_EXPR : PLUS_EXPR, type, t, inv); > } > > -/* Return true if value range VR involves exactly one symbol SYM. */ > - > -static bool > -symbolic_range_based_on_p (value_range *vr, const_tree sym) > -{ > - bool neg, min_has_symbol, max_has_symbol; > - tree inv; > - > - if (is_gimple_min_invariant (vr->min)) > - min_has_symbol = false; > - else if (get_single_symbol (vr->min, &neg, &inv) == sym) > - min_has_symbol = true; > - else > - return false; > - > - if (is_gimple_min_invariant (vr->max)) > - max_has_symbol = false; > - else if (get_single_symbol (vr->max, &neg, &inv) == sym) > - max_has_symbol = true; > - else > - return false; > - > - return (min_has_symbol || max_has_symbol); > -} > - > -/* Return true if the result of assignment STMT is know to be non-zero. */ > - > -static bool > -gimple_assign_nonzero_p (gimple *stmt) > -{ > - enum tree_code code = gimple_assign_rhs_code (stmt); > - bool strict_overflow_p; > - switch (get_gimple_rhs_class (code)) > - { > - case GIMPLE_UNARY_RHS: > - return tree_unary_nonzero_warnv_p (gimple_assign_rhs_code (stmt), > - gimple_expr_type (stmt), > - gimple_assign_rhs1 (stmt), > - &strict_overflow_p); > - case GIMPLE_BINARY_RHS: > - return tree_binary_nonzero_warnv_p (gimple_assign_rhs_code (stmt), > - gimple_expr_type (stmt), > - gimple_assign_rhs1 (stmt), > - gimple_assign_rhs2 (stmt), > - &strict_overflow_p); > - case GIMPLE_TERNARY_RHS: > - return false; > - case GIMPLE_SINGLE_RHS: > - return tree_single_nonzero_warnv_p (gimple_assign_rhs1 (stmt), > - &strict_overflow_p); > - case GIMPLE_INVALID_RHS: > - gcc_unreachable (); > - default: > - gcc_unreachable (); > - } > -} > - > -/* Return true if STMT is known to compute a non-zero value. */ > - > -static bool > -gimple_stmt_nonzero_p (gimple *stmt) > -{ > - switch (gimple_code (stmt)) > - { > - case GIMPLE_ASSIGN: > - return gimple_assign_nonzero_p (stmt); > - case GIMPLE_CALL: > - { > - tree fndecl = gimple_call_fndecl (stmt); > - if (!fndecl) return false; > - if (flag_delete_null_pointer_checks && !flag_check_new > - && DECL_IS_OPERATOR_NEW (fndecl) > - && !TREE_NOTHROW (fndecl)) > - return true; > - /* References are always non-NULL. */ > - if (flag_delete_null_pointer_checks > - && TREE_CODE (TREE_TYPE (fndecl)) == REFERENCE_TYPE) > - return true; > - if (flag_delete_null_pointer_checks && > - lookup_attribute ("returns_nonnull", > - TYPE_ATTRIBUTES (gimple_call_fntype (stmt)))) > - return true; > - > - gcall *call_stmt = as_a<gcall *> (stmt); > - unsigned rf = gimple_call_return_flags (call_stmt); > - if (rf & ERF_RETURNS_ARG) > - { > - unsigned argnum = rf & ERF_RETURN_ARG_MASK; > - if (argnum < gimple_call_num_args (call_stmt)) > - { > - tree arg = gimple_call_arg (call_stmt, argnum); > - if (SSA_VAR_P (arg) > - && infer_nonnull_range_by_attribute (stmt, arg)) > - return true; > - } > - } > - return gimple_alloca_call_p (stmt); > - } > - default: > - gcc_unreachable (); > - } > -} > - > -/* Like tree_expr_nonzero_p, but this function uses value ranges > - obtained so far. */ > - > -bool > -vr_values::vrp_stmt_computes_nonzero (gimple *stmt) > -{ > - if (gimple_stmt_nonzero_p (stmt)) > - return true; > - > - /* If we have an expression of the form &X->a, then the expression > - is nonnull if X is nonnull. */ > - if (is_gimple_assign (stmt) > - && gimple_assign_rhs_code (stmt) == ADDR_EXPR) > - { > - tree expr = gimple_assign_rhs1 (stmt); > - tree base = get_base_address (TREE_OPERAND (expr, 0)); > - > - if (base != NULL_TREE > - && TREE_CODE (base) == MEM_REF > - && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME) > - { > - value_range *vr = get_value_range (TREE_OPERAND (base, 0)); > - if (range_is_nonnull (vr)) > - return true; > - } > - } > - > - return false; > -} > - > -/* Returns true if EXPR is a valid value (as expected by compare_values) -- > - a gimple invariant, or SSA_NAME +- CST. */ > - > -static bool > -valid_value_p (tree expr) > -{ > - if (TREE_CODE (expr) == SSA_NAME) > - return true; > - > - if (TREE_CODE (expr) == PLUS_EXPR > - || TREE_CODE (expr) == MINUS_EXPR) > - return (TREE_CODE (TREE_OPERAND (expr, 0)) == SSA_NAME > - && TREE_CODE (TREE_OPERAND (expr, 1)) == INTEGER_CST); > - > - return is_gimple_min_invariant (expr); > -} > - > /* Return > 1 if VAL < VAL2 > 0 if !(VAL < VAL2) > -2 if those are incomparable. */ > -static inline int > +int > operand_less_p (tree val, tree val2) > { > /* LT is folded faster than GE and others. Inline the common case. */ > @@ -987,7 +628,7 @@ operand_less_p (tree val, tree val2) > true if the return value is only valid if we assume that signed > overflow is undefined. */ > > -static int > +int > compare_values_warnv (tree val1, tree val2, bool *strict_overflow_p) > { > if (val1 == val2) > @@ -1124,7 +765,7 @@ compare_values_warnv (tree val1, tree val2, bool > *strict_overflow_p) > > /* Compare values like compare_values_warnv. */ > > -static int > +int > compare_values (tree val1, tree val2) > { > bool sop; > @@ -1139,7 +780,7 @@ compare_values (tree val1, tree val2) > Benchmark compile/20001226-1.c compilation time after changing this > function. */ > > -static inline int > +int > value_inside_range (tree val, tree min, tree max) > { > int cmp1, cmp2; > @@ -1209,7 +850,7 @@ value_range_nonnegative_p (value_range *vr) > /* If *VR has a value rante that is a single constant value return that, > otherwise return NULL_TREE. */ > > -static tree > +tree > value_range_constant_singleton (value_range *vr) > { > if (vr->type == VR_RANGE > @@ -1220,356 +861,6 @@ value_range_constant_singleton (value_range *vr) > return NULL_TREE; > } > > -/* If OP has a value range with a single constant value return that, > - otherwise return NULL_TREE. This returns OP itself if OP is a > - constant. */ > - > -tree > -vr_values::op_with_constant_singleton_value_range (tree op) > -{ > - if (is_gimple_min_invariant (op)) > - return op; > - > - if (TREE_CODE (op) != SSA_NAME) > - return NULL_TREE; > - > - return value_range_constant_singleton (get_value_range (op)); > -} > - > -/* Return true if op is in a boolean [0, 1] value-range. */ > - > -bool > -vr_values::op_with_boolean_value_range_p (tree op) > -{ > - value_range *vr; > - > - if (TYPE_PRECISION (TREE_TYPE (op)) == 1) > - return true; > - > - if (integer_zerop (op) > - || integer_onep (op)) > - return true; > - > - if (TREE_CODE (op) != SSA_NAME) > - return false; > - > - vr = get_value_range (op); > - return (vr->type == VR_RANGE > - && integer_zerop (vr->min) > - && integer_onep (vr->max)); > -} > - > -/* Extract value range information for VAR when (OP COND_CODE LIMIT) is > - true and store it in *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; > - type = TREE_TYPE (var); > - gcc_assert (limit != var); > - > - /* For pointer arithmetic, we only keep track of pointer equality > - and inequality. */ > - if (POINTER_TYPE_P (type) && cond_code != NE_EXPR && cond_code != EQ_EXPR) > - { > - set_value_range_to_varying (vr_p); > - return; > - } > - > - /* If LIMIT is another SSA name and LIMIT has a range of its own, > - try to use LIMIT's range to avoid creating symbolic ranges > - unnecessarily. */ > - limit_vr = (TREE_CODE (limit) == SSA_NAME) ? get_value_range (limit) : > NULL; > - > - /* LIMIT's range is only interesting if it has any useful information. */ > - if (! limit_vr > - || limit_vr->type == VR_UNDEFINED > - || limit_vr->type == VR_VARYING > - || (symbolic_range_p (limit_vr) > - && ! (limit_vr->type == VR_RANGE > - && (limit_vr->min == limit_vr->max > - || operand_equal_p (limit_vr->min, limit_vr->max, 0))))) > - limit_vr = NULL; > - > - /* Initially, the new range has the same set of equivalences of > - VAR's range. This will be revised before returning the final > - value. Since assertions may be chained via mutually exclusive > - predicates, we will need to trim the set of equivalences before > - we are done. */ > - gcc_assert (vr_p->equiv == NULL); > - add_equivalence (&vr_p->equiv, var); > - > - /* Extract a new range based on the asserted comparison for VAR and > - LIMIT's value range. Notice that if LIMIT has an anti-range, we > - will only use it for equality comparisons (EQ_EXPR). For any > - other kind of assertion, we cannot derive a range from LIMIT's > - anti-range that can be used to describe the new range. For > - instance, ASSERT_EXPR <x_2, x_2 <= b_4>. If b_4 is ~[2, 10], > - then b_4 takes on the ranges [-INF, 1] and [11, +INF]. There is > - no single range for x_2 that could describe LE_EXPR, so we might > - as well build the range [b_4, +INF] for it. > - One special case we handle is extracting a range from a > - range test encoded as (unsigned)var + CST <= limit. */ > - if (TREE_CODE (op) == NOP_EXPR > - || TREE_CODE (op) == PLUS_EXPR) > - { > - if (TREE_CODE (op) == PLUS_EXPR) > - { > - min = fold_build1 (NEGATE_EXPR, TREE_TYPE (TREE_OPERAND (op, 1)), > - TREE_OPERAND (op, 1)); > - max = int_const_binop (PLUS_EXPR, limit, min); > - op = TREE_OPERAND (op, 0); > - } > - else > - { > - min = build_int_cst (TREE_TYPE (var), 0); > - max = limit; > - } > - > - /* Make sure to not set TREE_OVERFLOW on the final type > - conversion. We are willingly interpreting large positive > - unsigned values as negative signed values here. */ > - min = force_fit_type (TREE_TYPE (var), wi::to_widest (min), 0, false); > - max = force_fit_type (TREE_TYPE (var), wi::to_widest (max), 0, false); > - > - /* We can transform a max, min range to an anti-range or > - vice-versa. Use set_and_canonicalize_value_range which does > - this for us. */ > - if (cond_code == LE_EXPR) > - set_and_canonicalize_value_range (vr_p, VR_RANGE, > - min, max, vr_p->equiv); > - else if (cond_code == GT_EXPR) > - set_and_canonicalize_value_range (vr_p, VR_ANTI_RANGE, > - min, max, vr_p->equiv); > - else > - gcc_unreachable (); > - } > - else if (cond_code == EQ_EXPR) > - { > - enum value_range_type range_type; > - > - if (limit_vr) > - { > - range_type = limit_vr->type; > - min = limit_vr->min; > - max = limit_vr->max; > - } > - else > - { > - range_type = VR_RANGE; > - min = limit; > - max = limit; > - } > - > - set_value_range (vr_p, range_type, min, max, vr_p->equiv); > - > - /* When asserting the equality VAR == LIMIT and LIMIT is another > - SSA name, the new range will also inherit the equivalence set > - from LIMIT. */ > - if (TREE_CODE (limit) == SSA_NAME) > - add_equivalence (&vr_p->equiv, limit); > - } > - else if (cond_code == NE_EXPR) > - { > - /* As described above, when LIMIT's range is an anti-range and > - this assertion is an inequality (NE_EXPR), then we cannot > - derive anything from the anti-range. For instance, if > - LIMIT's range was ~[0, 0], the assertion 'VAR != LIMIT' does > - not imply that VAR's range is [0, 0]. So, in the case of > - anti-ranges, we just assert the inequality using LIMIT and > - not its anti-range. > - > - If LIMIT_VR is a range, we can only use it to build a new > - anti-range if LIMIT_VR is a single-valued range. For > - instance, if LIMIT_VR is [0, 1], the predicate > - VAR != [0, 1] does not mean that VAR's range is ~[0, 1]. > - Rather, it means that for value 0 VAR should be ~[0, 0] > - and for value 1, VAR should be ~[1, 1]. We cannot > - represent these ranges. > - > - The only situation in which we can build a valid > - anti-range is when LIMIT_VR is a single-valued range > - (i.e., LIMIT_VR->MIN == LIMIT_VR->MAX). In that case, > - build the anti-range ~[LIMIT_VR->MIN, LIMIT_VR->MAX]. */ > - if (limit_vr > - && limit_vr->type == VR_RANGE > - && compare_values (limit_vr->min, limit_vr->max) == 0) > - { > - min = limit_vr->min; > - max = limit_vr->max; > - } > - else > - { > - /* In any other case, we cannot use LIMIT's range to build a > - valid anti-range. */ > - min = max = limit; > - } > - > - /* If MIN and MAX cover the whole range for their type, then > - just use the original LIMIT. */ > - if (INTEGRAL_TYPE_P (type) > - && vrp_val_is_min (min) > - && vrp_val_is_max (max)) > - min = max = limit; > - > - set_and_canonicalize_value_range (vr_p, VR_ANTI_RANGE, > - min, max, vr_p->equiv); > - } > - else if (cond_code == LE_EXPR || cond_code == LT_EXPR) > - { > - min = TYPE_MIN_VALUE (type); > - > - if (limit_vr == NULL || limit_vr->type == VR_ANTI_RANGE) > - max = limit; > - else > - { > - /* If LIMIT_VR is of the form [N1, N2], we need to build the > - range [MIN, N2] for LE_EXPR and [MIN, N2 - 1] for > - LT_EXPR. */ > - max = limit_vr->max; > - } > - > - /* If the maximum value forces us to be out of bounds, simply punt. > - It would be pointless to try and do anything more since this > - all should be optimized away above us. */ > - if (cond_code == LT_EXPR > - && compare_values (max, min) == 0) > - set_value_range_to_varying (vr_p); > - else > - { > - /* For LT_EXPR, we create the range [MIN, MAX - 1]. */ > - if (cond_code == LT_EXPR) > - { > - if (TYPE_PRECISION (TREE_TYPE (max)) == 1 > - && !TYPE_UNSIGNED (TREE_TYPE (max))) > - max = fold_build2 (PLUS_EXPR, TREE_TYPE (max), max, > - build_int_cst (TREE_TYPE (max), -1)); > - else > - max = fold_build2 (MINUS_EXPR, TREE_TYPE (max), max, > - build_int_cst (TREE_TYPE (max), 1)); > - /* Signal to compare_values_warnv this expr doesn't overflow. > */ > - if (EXPR_P (max)) > - TREE_NO_WARNING (max) = 1; > - } > - > - set_value_range (vr_p, VR_RANGE, min, max, vr_p->equiv); > - } > - } > - else if (cond_code == GE_EXPR || cond_code == GT_EXPR) > - { > - max = TYPE_MAX_VALUE (type); > - > - if (limit_vr == NULL || limit_vr->type == VR_ANTI_RANGE) > - min = limit; > - else > - { > - /* If LIMIT_VR is of the form [N1, N2], we need to build the > - range [N1, MAX] for GE_EXPR and [N1 + 1, MAX] for > - GT_EXPR. */ > - min = limit_vr->min; > - } > - > - /* If the minimum value forces us to be out of bounds, simply punt. > - It would be pointless to try and do anything more since this > - all should be optimized away above us. */ > - if (cond_code == GT_EXPR > - && compare_values (min, max) == 0) > - set_value_range_to_varying (vr_p); > - else > - { > - /* For GT_EXPR, we create the range [MIN + 1, MAX]. */ > - if (cond_code == GT_EXPR) > - { > - if (TYPE_PRECISION (TREE_TYPE (min)) == 1 > - && !TYPE_UNSIGNED (TREE_TYPE (min))) > - min = fold_build2 (MINUS_EXPR, TREE_TYPE (min), min, > - build_int_cst (TREE_TYPE (min), -1)); > - else > - min = fold_build2 (PLUS_EXPR, TREE_TYPE (min), min, > - build_int_cst (TREE_TYPE (min), 1)); > - /* Signal to compare_values_warnv this expr doesn't overflow. > */ > - if (EXPR_P (min)) > - TREE_NO_WARNING (min) = 1; > - } > - > - set_value_range (vr_p, VR_RANGE, min, max, vr_p->equiv); > - } > - } > - else > - gcc_unreachable (); > - > - /* Finally intersect the new range with what we already know about var. */ > - vrp_intersect_ranges (vr_p, get_value_range (var)); > -} > - > -/* Extract value range information from an ASSERT_EXPR EXPR and store > - it in *VR_P. */ > - > -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); > - tree limit, op; > - enum tree_code cond_code; > - gcc_assert (COMPARISON_CLASS_P (cond)); > - > - /* Find VAR in the ASSERT_EXPR conditional. */ > - if (var == TREE_OPERAND (cond, 0) > - || TREE_CODE (TREE_OPERAND (cond, 0)) == PLUS_EXPR > - || TREE_CODE (TREE_OPERAND (cond, 0)) == NOP_EXPR) > - { > - /* If the predicate is of the form VAR COMP LIMIT, then we just > - take LIMIT from the RHS and use the same comparison code. */ > - cond_code = TREE_CODE (cond); > - limit = TREE_OPERAND (cond, 1); > - op = TREE_OPERAND (cond, 0); > - } > - else > - { > - /* If the predicate is of the form LIMIT COMP VAR, then we need > - to flip around the comparison code to create the proper range > - for VAR. */ > - cond_code = swap_tree_comparison (TREE_CODE (cond)); > - limit = TREE_OPERAND (cond, 0); > - op = TREE_OPERAND (cond, 1); > - } > - extract_range_for_var_from_comparison_expr (var, cond_code, op, > - limit, vr_p); > -} > - > -/* Extract range information from SSA name VAR and store it in VR. If > - VAR has an interesting range, use it. Otherwise, create the > - range [VAR, VAR] and return it. This is useful in situations where > - we may have conditionals testing values of VARYING names. For > - instance, > - > - x_3 = y_5; > - if (x_3 > y_5) > - ... > - > - Even if y_5 is deemed VARYING, we can determine that x_3 > y_5 is > - always false. */ > - > -void > -vr_values::extract_range_from_ssa_name (value_range *vr, tree var) > -{ > - value_range *var_vr = get_value_range (var); > - > - if (var_vr->type != VR_VARYING) > - copy_value_range (vr, var_vr); > - else > - set_value_range (vr, VR_RANGE, var, var, NULL); > - > - add_equivalence (&vr->equiv, var); > -} > - > - > /* Wrapper around int_const_binop. Return true if we can compute the > result; i.e. if the operation doesn't overflow or if the overflow is > undefined. In the latter case (if the operation overflows and > @@ -1703,7 +994,7 @@ vrp_int_const_binop (enum tree_code code, tree val1, > tree val2, wide_int *res) > bitmask if some bit is set, it means for all numbers in the range > the bit is 1, otherwise it might be 0 or 1. */ > > -static bool > +bool > zero_nonzero_bits_from_vr (const tree expr_type, > value_range *vr, > wide_int *may_be_nonzero, > @@ -1893,7 +1184,7 @@ extract_range_from_multiplicative_op_1 (value_range *vr, > the ranges of each of its operands *VR0 and *VR1 with resulting > type EXPR_TYPE. The resulting range is stored in *VR. */ > > -static void > +void > extract_range_from_binary_expr_1 (value_range *vr, > enum tree_code code, tree expr_type, > value_range *vr0_, value_range *vr1_) > @@ -2988,105 +2279,6 @@ extract_range_from_binary_expr_1 (value_range *vr, > set_value_range (vr, type, min, max, NULL); > } > > -/* Extract range information from a binary expression OP0 CODE OP1 based on > - the ranges of each of its operands with resulting type EXPR_TYPE. > - The resulting range is stored in *VR. */ > - > -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; > - > - /* Get value ranges for each operand. For constant operands, create > - a new value range with the operand to simplify processing. */ > - if (TREE_CODE (op0) == SSA_NAME) > - vr0 = *(get_value_range (op0)); > - else if (is_gimple_min_invariant (op0)) > - set_value_range_to_value (&vr0, op0, NULL); > - else > - set_value_range_to_varying (&vr0); > - > - if (TREE_CODE (op1) == SSA_NAME) > - vr1 = *(get_value_range (op1)); > - else if (is_gimple_min_invariant (op1)) > - set_value_range_to_value (&vr1, op1, NULL); > - else > - set_value_range_to_varying (&vr1); > - > - extract_range_from_binary_expr_1 (vr, code, expr_type, &vr0, &vr1); > - > - /* Try harder for PLUS and MINUS if the range of one operand is symbolic > - and based on the other operand, for example if it was deduced from a > - symbolic comparison. When a bound of the range of the first operand > - is invariant, we set the corresponding bound of the new range to INF > - in order to avoid recursing on the range of the second operand. */ > - if (vr->type == VR_VARYING > - && (code == PLUS_EXPR || code == MINUS_EXPR) > - && TREE_CODE (op1) == SSA_NAME > - && vr0.type == VR_RANGE > - && symbolic_range_based_on_p (&vr0, op1)) > - { > - const bool minus_p = (code == MINUS_EXPR); > - value_range n_vr1 = VR_INITIALIZER; > - > - /* Try with VR0 and [-INF, OP1]. */ > - if (is_gimple_min_invariant (minus_p ? vr0.max : vr0.min)) > - set_value_range (&n_vr1, VR_RANGE, vrp_val_min (expr_type), op1, > NULL); > - > - /* Try with VR0 and [OP1, +INF]. */ > - else if (is_gimple_min_invariant (minus_p ? vr0.min : vr0.max)) > - set_value_range (&n_vr1, VR_RANGE, op1, vrp_val_max (expr_type), > NULL); > - > - /* Try with VR0 and [OP1, OP1]. */ > - else > - set_value_range (&n_vr1, VR_RANGE, op1, op1, NULL); > - > - extract_range_from_binary_expr_1 (vr, code, expr_type, &vr0, &n_vr1); > - } > - > - if (vr->type == VR_VARYING > - && (code == PLUS_EXPR || code == MINUS_EXPR) > - && TREE_CODE (op0) == SSA_NAME > - && vr1.type == VR_RANGE > - && symbolic_range_based_on_p (&vr1, op0)) > - { > - const bool minus_p = (code == MINUS_EXPR); > - value_range n_vr0 = VR_INITIALIZER; > - > - /* Try with [-INF, OP0] and VR1. */ > - if (is_gimple_min_invariant (minus_p ? vr1.max : vr1.min)) > - set_value_range (&n_vr0, VR_RANGE, vrp_val_min (expr_type), op0, > NULL); > - > - /* Try with [OP0, +INF] and VR1. */ > - else if (is_gimple_min_invariant (minus_p ? vr1.min : vr1.max)) > - set_value_range (&n_vr0, VR_RANGE, op0, vrp_val_max (expr_type), > NULL); > - > - /* Try with [OP0, OP0] and VR1. */ > - else > - set_value_range (&n_vr0, VR_RANGE, op0, op0, NULL); > - > - extract_range_from_binary_expr_1 (vr, code, expr_type, &n_vr0, &vr1); > - } > - > - /* If we didn't derive a range for MINUS_EXPR, and > - op1's range is ~[op0,op0] or vice-versa, then we > - can derive a non-null range. This happens often for > - pointer subtraction. */ > - if (vr->type == VR_VARYING > - && code == MINUS_EXPR > - && TREE_CODE (op0) == SSA_NAME > - && ((vr0.type == VR_ANTI_RANGE > - && vr0.min == op1 > - && vr0.min == vr0.max) > - || (vr1.type == VR_ANTI_RANGE > - && vr1.min == op0 > - && vr1.min == vr1.max))) > - set_value_range_to_nonnull (vr, TREE_TYPE (op0)); > -} > - > /* Extract range information from a unary operation CODE based on > the range of its operand *VR0 with type OP0_TYPE with resulting type TYPE. > The resulting range is stored in *VR. */ > @@ -3334,1034 +2526,6 @@ extract_range_from_unary_expr (value_range *vr, > return; > } > > - > -/* Extract range information from a unary expression CODE OP0 based on > - the range of its operand with resulting type TYPE. > - The resulting range is stored in *VR. */ > - > -void > -vr_values::extract_range_from_unary_expr (value_range *vr, enum tree_code > code, > - tree type, tree op0) > -{ > - value_range vr0 = VR_INITIALIZER; > - > - /* Get value ranges for the operand. For constant operands, create > - a new value range with the operand to simplify processing. */ > - if (TREE_CODE (op0) == SSA_NAME) > - vr0 = *(get_value_range (op0)); > - else if (is_gimple_min_invariant (op0)) > - set_value_range_to_value (&vr0, op0, NULL); > - else > - set_value_range_to_varying (&vr0); > - > - ::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. */ > - > -void > -vr_values::extract_range_from_cond_expr (value_range *vr, gassign *stmt) > -{ > - tree op0, op1; > - value_range vr0 = VR_INITIALIZER; > - value_range vr1 = VR_INITIALIZER; > - > - /* Get value ranges for each operand. For constant operands, create > - a new value range with the operand to simplify processing. */ > - op0 = gimple_assign_rhs2 (stmt); > - if (TREE_CODE (op0) == SSA_NAME) > - vr0 = *(get_value_range (op0)); > - else if (is_gimple_min_invariant (op0)) > - set_value_range_to_value (&vr0, op0, NULL); > - else > - set_value_range_to_varying (&vr0); > - > - op1 = gimple_assign_rhs3 (stmt); > - if (TREE_CODE (op1) == SSA_NAME) > - vr1 = *(get_value_range (op1)); > - else if (is_gimple_min_invariant (op1)) > - set_value_range_to_value (&vr1, op1, NULL); > - else > - set_value_range_to_varying (&vr1); > - > - /* The resulting value range is the union of the operand ranges */ > - copy_value_range (vr, &vr0); > - vrp_meet (vr, &vr1); > -} > - > - > -/* Extract range information from a comparison expression EXPR based > - on the range of its operand and the expression code. */ > - > -void > -vr_values::extract_range_from_comparison (value_range *vr, enum tree_code > code, > - tree type, tree op0, tree op1) > -{ > - bool sop; > - tree val; > - > - val = 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, > - its type may be different from _Bool. Convert VAL to EXPR's > - type. */ > - val = fold_convert (type, val); > - if (is_gimple_min_invariant (val)) > - set_value_range_to_value (vr, val, vr->equiv); > - else > - set_value_range (vr, VR_RANGE, val, val, vr->equiv); > - } > - else > - /* The result of a comparison is always true or false. */ > - set_value_range_to_truthvalue (vr, type); > -} > - > -/* Helper function for simplify_internal_call_using_ranges and > - extract_range_basic. Return true if OP0 SUBCODE OP1 for > - SUBCODE {PLUS,MINUS,MULT}_EXPR is known to never overflow or > - 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) > -{ > - value_range vr0 = VR_INITIALIZER; > - value_range vr1 = VR_INITIALIZER; > - if (TREE_CODE (op0) == SSA_NAME) > - vr0 = *get_value_range (op0); > - else if (TREE_CODE (op0) == INTEGER_CST) > - set_value_range_to_value (&vr0, op0, NULL); > - else > - set_value_range_to_varying (&vr0); > - > - if (TREE_CODE (op1) == SSA_NAME) > - vr1 = *get_value_range (op1); > - else if (TREE_CODE (op1) == INTEGER_CST) > - set_value_range_to_value (&vr1, op1, NULL); > - else > - set_value_range_to_varying (&vr1); > - > - if (!range_int_cst_p (&vr0) > - || TREE_OVERFLOW (vr0.min) > - || TREE_OVERFLOW (vr0.max)) > - { > - vr0.min = vrp_val_min (TREE_TYPE (op0)); > - vr0.max = vrp_val_max (TREE_TYPE (op0)); > - } > - if (!range_int_cst_p (&vr1) > - || TREE_OVERFLOW (vr1.min) > - || TREE_OVERFLOW (vr1.max)) > - { > - vr1.min = vrp_val_min (TREE_TYPE (op1)); > - vr1.max = vrp_val_max (TREE_TYPE (op1)); > - } > - *ovf = arith_overflowed_p (subcode, type, vr0.min, > - subcode == MINUS_EXPR ? vr1.max : vr1.min); > - if (arith_overflowed_p (subcode, type, vr0.max, > - subcode == MINUS_EXPR ? vr1.min : vr1.max) != *ovf) > - return false; > - if (subcode == MULT_EXPR) > - { > - if (arith_overflowed_p (subcode, type, vr0.min, vr1.max) != *ovf > - || arith_overflowed_p (subcode, type, vr0.max, vr1.min) != *ovf) > - return false; > - } > - if (*ovf) > - { > - /* So far we found that there is an overflow on the boundaries. > - That doesn't prove that there is an overflow even for all values > - in between the boundaries. For that compute widest_int range > - of the result and see if it doesn't overlap the range of > - type. */ > - widest_int wmin, wmax; > - widest_int w[4]; > - int i; > - w[0] = wi::to_widest (vr0.min); > - w[1] = wi::to_widest (vr0.max); > - w[2] = wi::to_widest (vr1.min); > - w[3] = wi::to_widest (vr1.max); > - for (i = 0; i < 4; i++) > - { > - widest_int wt; > - switch (subcode) > - { > - case PLUS_EXPR: > - wt = wi::add (w[i & 1], w[2 + (i & 2) / 2]); > - break; > - case MINUS_EXPR: > - wt = wi::sub (w[i & 1], w[2 + (i & 2) / 2]); > - break; > - case MULT_EXPR: > - wt = wi::mul (w[i & 1], w[2 + (i & 2) / 2]); > - break; > - default: > - gcc_unreachable (); > - } > - if (i == 0) > - { > - wmin = wt; > - wmax = wt; > - } > - else > - { > - wmin = wi::smin (wmin, wt); > - wmax = wi::smax (wmax, wt); > - } > - } > - /* The result of op0 CODE op1 is known to be in range > - [wmin, wmax]. */ > - widest_int wtmin = wi::to_widest (vrp_val_min (type)); > - widest_int wtmax = wi::to_widest (vrp_val_max (type)); > - /* If all values in [wmin, wmax] are smaller than > - [wtmin, wtmax] or all are larger than [wtmin, wtmax], > - the arithmetic operation will always overflow. */ > - if (wmax < wtmin || wmin > wtmax) > - return true; > - return false; > - } > - return true; > -} > - > -/* Try to derive a nonnegative or nonzero range out of STMT relying > - primarily on generic routines in fold in conjunction with range data. > - Store the result in *VR */ > - > -void > -vr_values::extract_range_basic (value_range *vr, gimple *stmt) > -{ > - bool sop; > - tree type = gimple_expr_type (stmt); > - > - if (is_gimple_call (stmt)) > - { > - tree arg; > - int mini, maxi, zerov = 0, prec; > - enum tree_code subcode = ERROR_MARK; > - combined_fn cfn = gimple_call_combined_fn (stmt); > - scalar_int_mode mode; > - > - switch (cfn) > - { > - case CFN_BUILT_IN_CONSTANT_P: > - /* If the call is __builtin_constant_p and the argument is a > - function parameter resolve it to false. This avoids bogus > - array bound warnings. > - ??? We could do this as early as inlining is finished. */ > - arg = gimple_call_arg (stmt, 0); > - if (TREE_CODE (arg) == SSA_NAME > - && SSA_NAME_IS_DEFAULT_DEF (arg) > - && TREE_CODE (SSA_NAME_VAR (arg)) == PARM_DECL > - && cfun->after_inlining) > - { > - set_value_range_to_null (vr, type); > - return; > - } > - break; > - /* Both __builtin_ffs* and __builtin_popcount return > - [0, prec]. */ > - CASE_CFN_FFS: > - CASE_CFN_POPCOUNT: > - arg = gimple_call_arg (stmt, 0); > - prec = TYPE_PRECISION (TREE_TYPE (arg)); > - mini = 0; > - maxi = prec; > - if (TREE_CODE (arg) == SSA_NAME) > - { > - value_range *vr0 = get_value_range (arg); > - /* If arg is non-zero, then ffs or popcount > - are non-zero. */ > - if ((vr0->type == VR_RANGE > - && range_includes_zero_p (vr0->min, vr0->max) == 0) > - || (vr0->type == VR_ANTI_RANGE > - && range_includes_zero_p (vr0->min, vr0->max) == 1)) > - mini = 1; > - /* If some high bits are known to be zero, > - we can decrease the maximum. */ > - if (vr0->type == VR_RANGE > - && TREE_CODE (vr0->max) == INTEGER_CST > - && !operand_less_p (vr0->min, > - build_zero_cst (TREE_TYPE (vr0->min)))) > - maxi = tree_floor_log2 (vr0->max) + 1; > - } > - goto bitop_builtin; > - /* __builtin_parity* returns [0, 1]. */ > - CASE_CFN_PARITY: > - mini = 0; > - maxi = 1; > - goto bitop_builtin; > - /* __builtin_c[lt]z* return [0, prec-1], except for > - when the argument is 0, but that is undefined behavior. > - On many targets where the CLZ RTL or optab value is defined > - for 0 the value is prec, so include that in the range > - by default. */ > - CASE_CFN_CLZ: > - arg = gimple_call_arg (stmt, 0); > - prec = TYPE_PRECISION (TREE_TYPE (arg)); > - mini = 0; > - maxi = prec; > - mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg)); > - if (optab_handler (clz_optab, mode) != CODE_FOR_nothing > - && CLZ_DEFINED_VALUE_AT_ZERO (mode, zerov) > - /* Handle only the single common value. */ > - && zerov != prec) > - /* Magic value to give up, unless vr0 proves > - arg is non-zero. */ > - mini = -2; > - if (TREE_CODE (arg) == SSA_NAME) > - { > - value_range *vr0 = get_value_range (arg); > - /* From clz of VR_RANGE minimum we can compute > - result maximum. */ > - if (vr0->type == VR_RANGE > - && TREE_CODE (vr0->min) == INTEGER_CST) > - { > - maxi = prec - 1 - tree_floor_log2 (vr0->min); > - if (maxi != prec) > - mini = 0; > - } > - else if (vr0->type == VR_ANTI_RANGE > - && integer_zerop (vr0->min)) > - { > - maxi = prec - 1; > - mini = 0; > - } > - if (mini == -2) > - break; > - /* From clz of VR_RANGE maximum we can compute > - result minimum. */ > - if (vr0->type == VR_RANGE > - && TREE_CODE (vr0->max) == INTEGER_CST) > - { > - mini = prec - 1 - tree_floor_log2 (vr0->max); > - if (mini == prec) > - break; > - } > - } > - if (mini == -2) > - break; > - goto bitop_builtin; > - /* __builtin_ctz* return [0, prec-1], except for > - when the argument is 0, but that is undefined behavior. > - If there is a ctz optab for this mode and > - CTZ_DEFINED_VALUE_AT_ZERO, include that in the range, > - otherwise just assume 0 won't be seen. */ > - CASE_CFN_CTZ: > - arg = gimple_call_arg (stmt, 0); > - prec = TYPE_PRECISION (TREE_TYPE (arg)); > - mini = 0; > - maxi = prec - 1; > - mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (arg)); > - if (optab_handler (ctz_optab, mode) != CODE_FOR_nothing > - && CTZ_DEFINED_VALUE_AT_ZERO (mode, zerov)) > - { > - /* Handle only the two common values. */ > - if (zerov == -1) > - mini = -1; > - else if (zerov == prec) > - maxi = prec; > - else > - /* Magic value to give up, unless vr0 proves > - arg is non-zero. */ > - mini = -2; > - } > - if (TREE_CODE (arg) == SSA_NAME) > - { > - value_range *vr0 = get_value_range (arg); > - /* If arg is non-zero, then use [0, prec - 1]. */ > - if ((vr0->type == VR_RANGE > - && integer_nonzerop (vr0->min)) > - || (vr0->type == VR_ANTI_RANGE > - && integer_zerop (vr0->min))) > - { > - mini = 0; > - maxi = prec - 1; > - } > - /* If some high bits are known to be zero, > - we can decrease the result maximum. */ > - if (vr0->type == VR_RANGE > - && TREE_CODE (vr0->max) == INTEGER_CST) > - { > - maxi = tree_floor_log2 (vr0->max); > - /* For vr0 [0, 0] give up. */ > - if (maxi == -1) > - break; > - } > - } > - if (mini == -2) > - break; > - goto bitop_builtin; > - /* __builtin_clrsb* returns [0, prec-1]. */ > - CASE_CFN_CLRSB: > - arg = gimple_call_arg (stmt, 0); > - prec = TYPE_PRECISION (TREE_TYPE (arg)); > - mini = 0; > - maxi = prec - 1; > - goto bitop_builtin; > - bitop_builtin: > - set_value_range (vr, VR_RANGE, build_int_cst (type, mini), > - build_int_cst (type, maxi), NULL); > - return; > - case CFN_UBSAN_CHECK_ADD: > - subcode = PLUS_EXPR; > - break; > - case CFN_UBSAN_CHECK_SUB: > - subcode = MINUS_EXPR; > - break; > - case CFN_UBSAN_CHECK_MUL: > - subcode = MULT_EXPR; > - break; > - case CFN_GOACC_DIM_SIZE: > - case CFN_GOACC_DIM_POS: > - /* Optimizing these two internal functions helps the loop > - optimizer eliminate outer comparisons. Size is [1,N] > - and pos is [0,N-1]. */ > - { > - bool is_pos = cfn == CFN_GOACC_DIM_POS; > - int axis = oacc_get_ifn_dim_arg (stmt); > - int size = oacc_get_fn_dim_size (current_function_decl, axis); > - > - if (!size) > - /* If it's dynamic, the backend might know a hardware > - limitation. */ > - size = targetm.goacc.dim_limit (axis); > - > - tree type = TREE_TYPE (gimple_call_lhs (stmt)); > - set_value_range (vr, VR_RANGE, > - build_int_cst (type, is_pos ? 0 : 1), > - size ? build_int_cst (type, size - is_pos) > - : vrp_val_max (type), NULL); > - } > - return; > - case CFN_BUILT_IN_STRLEN: > - if (tree lhs = gimple_call_lhs (stmt)) > - if (ptrdiff_type_node > - && (TYPE_PRECISION (ptrdiff_type_node) > - == TYPE_PRECISION (TREE_TYPE (lhs)))) > - { > - tree type = TREE_TYPE (lhs); > - tree max = vrp_val_max (ptrdiff_type_node); > - wide_int wmax = wi::to_wide (max, TYPE_PRECISION (TREE_TYPE > (max))); > - tree range_min = build_zero_cst (type); > - tree range_max = wide_int_to_tree (type, wmax - 1); > - set_value_range (vr, VR_RANGE, range_min, range_max, NULL); > - return; > - } > - break; > - default: > - break; > - } > - if (subcode != ERROR_MARK) > - { > - bool saved_flag_wrapv = flag_wrapv; > - /* Pretend the arithmetics is wrapping. If there is > - any overflow, we'll complain, but will actually do > - wrapping operation. */ > - flag_wrapv = 1; > - extract_range_from_binary_expr (vr, subcode, type, > - gimple_call_arg (stmt, 0), > - gimple_call_arg (stmt, 1)); > - flag_wrapv = saved_flag_wrapv; > - > - /* If for both arguments vrp_valueize returned non-NULL, > - this should have been already folded and if not, it > - wasn't folded because of overflow. Avoid removing the > - UBSAN_CHECK_* calls in that case. */ > - if (vr->type == VR_RANGE > - && (vr->min == vr->max > - || operand_equal_p (vr->min, vr->max, 0))) > - set_value_range_to_varying (vr); > - return; > - } > - } > - /* Handle extraction of the two results (result of arithmetics and > - a flag whether arithmetics overflowed) from {ADD,SUB,MUL}_OVERFLOW > - internal function. Similarly from ATOMIC_COMPARE_EXCHANGE. */ > - else if (is_gimple_assign (stmt) > - && (gimple_assign_rhs_code (stmt) == REALPART_EXPR > - || gimple_assign_rhs_code (stmt) == IMAGPART_EXPR) > - && INTEGRAL_TYPE_P (type)) > - { > - enum tree_code code = gimple_assign_rhs_code (stmt); > - tree op = gimple_assign_rhs1 (stmt); > - if (TREE_CODE (op) == code && TREE_CODE (TREE_OPERAND (op, 0)) == > SSA_NAME) > - { > - gimple *g = SSA_NAME_DEF_STMT (TREE_OPERAND (op, 0)); > - if (is_gimple_call (g) && gimple_call_internal_p (g)) > - { > - enum tree_code subcode = ERROR_MARK; > - switch (gimple_call_internal_fn (g)) > - { > - case IFN_ADD_OVERFLOW: > - subcode = PLUS_EXPR; > - break; > - case IFN_SUB_OVERFLOW: > - subcode = MINUS_EXPR; > - break; > - case IFN_MUL_OVERFLOW: > - subcode = MULT_EXPR; > - break; > - case IFN_ATOMIC_COMPARE_EXCHANGE: > - if (code == IMAGPART_EXPR) > - { > - /* This is the boolean return value whether compare and > - exchange changed anything or not. */ > - set_value_range (vr, VR_RANGE, build_int_cst (type, 0), > - build_int_cst (type, 1), NULL); > - return; > - } > - break; > - default: > - break; > - } > - if (subcode != ERROR_MARK) > - { > - tree op0 = gimple_call_arg (g, 0); > - tree op1 = gimple_call_arg (g, 1); > - if (code == IMAGPART_EXPR) > - { > - bool ovf = false; > - if (check_for_binary_op_overflow (subcode, type, > - op0, op1, &ovf)) > - set_value_range_to_value (vr, > - build_int_cst (type, ovf), > - NULL); > - else if (TYPE_PRECISION (type) == 1 > - && !TYPE_UNSIGNED (type)) > - set_value_range_to_varying (vr); > - else > - set_value_range (vr, VR_RANGE, build_int_cst (type, > 0), > - build_int_cst (type, 1), NULL); > - } > - else if (types_compatible_p (type, TREE_TYPE (op0)) > - && types_compatible_p (type, TREE_TYPE (op1))) > - { > - bool saved_flag_wrapv = flag_wrapv; > - /* Pretend the arithmetics is wrapping. If there is > - any overflow, IMAGPART_EXPR will be set. */ > - flag_wrapv = 1; > - extract_range_from_binary_expr (vr, subcode, type, > - op0, op1); > - flag_wrapv = saved_flag_wrapv; > - } > - else > - { > - value_range vr0 = VR_INITIALIZER; > - value_range vr1 = VR_INITIALIZER; > - bool saved_flag_wrapv = flag_wrapv; > - /* Pretend the arithmetics is wrapping. If there is > - any overflow, IMAGPART_EXPR will be set. */ > - flag_wrapv = 1; > - extract_range_from_unary_expr (&vr0, NOP_EXPR, > - type, op0); > - extract_range_from_unary_expr (&vr1, NOP_EXPR, > - type, op1); > - extract_range_from_binary_expr_1 (vr, subcode, type, > - &vr0, &vr1); > - flag_wrapv = saved_flag_wrapv; > - } > - return; > - } > - } > - } > - } > - if (INTEGRAL_TYPE_P (type) > - && gimple_stmt_nonnegative_warnv_p (stmt, &sop)) > - set_value_range_to_nonnegative (vr, type); > - else if (vrp_stmt_computes_nonzero (stmt)) > - set_value_range_to_nonnull (vr, type); > - else > - set_value_range_to_varying (vr); > -} > - > - > -/* Try to compute a useful range out of assignment STMT and store it > - in *VR. */ > - > -void > -vr_values::extract_range_from_assignment (value_range *vr, gassign *stmt) > -{ > - enum tree_code code = gimple_assign_rhs_code (stmt); > - > - if (code == ASSERT_EXPR) > - extract_range_from_assert (vr, gimple_assign_rhs1 (stmt)); > - else if (code == SSA_NAME) > - extract_range_from_ssa_name (vr, gimple_assign_rhs1 (stmt)); > - else if (TREE_CODE_CLASS (code) == tcc_binary) > - extract_range_from_binary_expr (vr, gimple_assign_rhs_code (stmt), > - gimple_expr_type (stmt), > - gimple_assign_rhs1 (stmt), > - gimple_assign_rhs2 (stmt)); > - else if (TREE_CODE_CLASS (code) == tcc_unary) > - extract_range_from_unary_expr (vr, gimple_assign_rhs_code (stmt), > - gimple_expr_type (stmt), > - gimple_assign_rhs1 (stmt)); > - else if (code == COND_EXPR) > - extract_range_from_cond_expr (vr, stmt); > - else if (TREE_CODE_CLASS (code) == tcc_comparison) > - extract_range_from_comparison (vr, gimple_assign_rhs_code (stmt), > - gimple_expr_type (stmt), > - gimple_assign_rhs1 (stmt), > - gimple_assign_rhs2 (stmt)); > - else if (get_gimple_rhs_class (code) == GIMPLE_SINGLE_RHS > - && is_gimple_min_invariant (gimple_assign_rhs1 (stmt))) > - set_value_range_to_value (vr, gimple_assign_rhs1 (stmt), NULL); > - else > - set_value_range_to_varying (vr); > - > - if (vr->type == VR_VARYING) > - extract_range_basic (vr, stmt); > -} > - > -/* Given a range VR, a LOOP and a variable VAR, determine whether it > - would be profitable to adjust VR using scalar evolution information > - for VAR. If so, update VR with the new limits. */ > - > -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; > - > - /* TODO. Don't adjust anti-ranges. An anti-range may provide > - better opportunities than a regular range, but I'm not sure. */ > - if (vr->type == VR_ANTI_RANGE) > - return; > - > - chrec = instantiate_parameters (loop, analyze_scalar_evolution (loop, > var)); > - > - /* Like in PR19590, scev can return a constant function. */ > - if (is_gimple_min_invariant (chrec)) > - { > - set_value_range_to_value (vr, chrec, vr->equiv); > - return; > - } > - > - if (TREE_CODE (chrec) != POLYNOMIAL_CHREC) > - return; > - > - init = initial_condition_in_loop_num (chrec, loop->num); > - tem = op_with_constant_singleton_value_range (init); > - if (tem) > - init = tem; > - step = evolution_part_in_loop_num (chrec, loop->num); > - tem = op_with_constant_singleton_value_range (step); > - if (tem) > - step = tem; > - > - /* If STEP is symbolic, we can't know whether INIT will be the > - minimum or maximum value in the range. Also, unless INIT is > - a simple expression, compare_values and possibly other functions > - in tree-vrp won't be able to handle it. */ > - if (step == NULL_TREE > - || !is_gimple_min_invariant (step) > - || !valid_value_p (init)) > - return; > - > - dir = scev_direction (chrec); > - if (/* Do not adjust ranges if we do not know whether the iv increases > - or decreases, ... */ > - dir == EV_DIR_UNKNOWN > - /* ... or if it may wrap. */ > - || scev_probably_wraps_p (NULL_TREE, init, step, stmt, > - get_chrec_loop (chrec), true)) > - return; > - > - type = TREE_TYPE (var); > - if (POINTER_TYPE_P (type) || !TYPE_MIN_VALUE (type)) > - tmin = lower_bound_in_type (type, type); > - else > - tmin = TYPE_MIN_VALUE (type); > - if (POINTER_TYPE_P (type) || !TYPE_MAX_VALUE (type)) > - tmax = upper_bound_in_type (type, type); > - else > - tmax = TYPE_MAX_VALUE (type); > - > - /* Try to use estimated number of iterations for the loop to constrain the > - final value in the evolution. */ > - if (TREE_CODE (step) == INTEGER_CST > - && is_gimple_val (init) > - && (TREE_CODE (init) != SSA_NAME > - || get_value_range (init)->type == VR_RANGE)) > - { > - widest_int nit; > - > - /* We are only entering here for loop header PHI nodes, so using > - the number of latch executions is the correct thing to use. */ > - if (max_loop_iterations (loop, &nit)) > - { > - value_range maxvr = VR_INITIALIZER; > - signop sgn = TYPE_SIGN (TREE_TYPE (step)); > - bool overflow; > - > - widest_int wtmp = wi::mul (wi::to_widest (step), nit, sgn, > - &overflow); > - /* If the multiplication overflowed we can't do a meaningful > - adjustment. Likewise if the result doesn't fit in the type > - of the induction variable. For a signed type we have to > - check whether the result has the expected signedness which > - is that of the step as number of iterations is unsigned. */ > - if (!overflow > - && wi::fits_to_tree_p (wtmp, TREE_TYPE (init)) > - && (sgn == UNSIGNED > - || wi::gts_p (wtmp, 0) == wi::gts_p (wi::to_wide (step), > 0))) > - { > - tem = wide_int_to_tree (TREE_TYPE (init), wtmp); > - extract_range_from_binary_expr (&maxvr, PLUS_EXPR, > - TREE_TYPE (init), init, tem); > - /* Likewise if the addition did. */ > - if (maxvr.type == VR_RANGE) > - { > - value_range initvr = VR_INITIALIZER; > - > - if (TREE_CODE (init) == SSA_NAME) > - initvr = *(get_value_range (init)); > - else if (is_gimple_min_invariant (init)) > - set_value_range_to_value (&initvr, init, NULL); > - else > - return; > - > - /* Check if init + nit * step overflows. Though we checked > - scev {init, step}_loop doesn't wrap, it is not enough > - because the loop may exit immediately. Overflow could > - happen in the plus expression in this case. */ > - if ((dir == EV_DIR_DECREASES > - && compare_values (maxvr.min, initvr.min) != -1) > - || (dir == EV_DIR_GROWS > - && compare_values (maxvr.max, initvr.max) != 1)) > - return; > - > - tmin = maxvr.min; > - tmax = maxvr.max; > - } > - } > - } > - } > - > - if (vr->type == VR_VARYING || vr->type == VR_UNDEFINED) > - { > - min = tmin; > - max = tmax; > - > - /* For VARYING or UNDEFINED ranges, just about anything we get > - from scalar evolutions should be better. */ > - > - if (dir == EV_DIR_DECREASES) > - max = init; > - else > - min = init; > - } > - else if (vr->type == VR_RANGE) > - { > - min = vr->min; > - max = vr->max; > - > - if (dir == EV_DIR_DECREASES) > - { > - /* INIT is the maximum value. If INIT is lower than VR->MAX > - but no smaller than VR->MIN, set VR->MAX to INIT. */ > - if (compare_values (init, max) == -1) > - max = init; > - > - /* According to the loop information, the variable does not > - overflow. */ > - if (compare_values (min, tmin) == -1) > - min = tmin; > - > - } > - else > - { > - /* If INIT is bigger than VR->MIN, set VR->MIN to INIT. */ > - if (compare_values (init, min) == 1) > - min = init; > - > - if (compare_values (tmax, max) == -1) > - max = tmax; > - } > - } > - else > - return; > - > - /* If we just created an invalid range with the minimum > - greater than the maximum, we fail conservatively. > - This should happen only in unreachable > - parts of code, or for invalid programs. */ > - if (compare_values (min, max) == 1) > - return; > - > - /* Even for valid range info, sometimes overflow flag will leak in. > - As GIMPLE IL should have no constants with TREE_OVERFLOW set, we > - drop them. */ > - if (TREE_OVERFLOW_P (min)) > - min = drop_tree_overflow (min); > - if (TREE_OVERFLOW_P (max)) > - max = drop_tree_overflow (max); > - > - set_value_range (vr, VR_RANGE, min, max, vr->equiv); > -} > - > - > -/* Given two numeric value ranges VR0, VR1 and a comparison code COMP: > - > - - Return BOOLEAN_TRUE_NODE if VR0 COMP VR1 always returns true for > - all the values in the ranges. > - > - - Return BOOLEAN_FALSE_NODE if the comparison always returns false. > - > - - Return NULL_TREE if it is not always possible to determine the > - value of the comparison. > - > - Also set *STRICT_OVERFLOW_P to indicate whether comparision evaluation > - assumed signed overflow is undefined. */ > - > - > -static tree > -compare_ranges (enum tree_code comp, value_range *vr0, value_range *vr1, > - bool *strict_overflow_p) > -{ > - /* VARYING or UNDEFINED ranges cannot be compared. */ > - if (vr0->type == VR_VARYING > - || vr0->type == VR_UNDEFINED > - || vr1->type == VR_VARYING > - || vr1->type == VR_UNDEFINED) > - return NULL_TREE; > - > - /* Anti-ranges need to be handled separately. */ > - if (vr0->type == VR_ANTI_RANGE || vr1->type == VR_ANTI_RANGE) > - { > - /* If both are anti-ranges, then we cannot compute any > - comparison. */ > - if (vr0->type == VR_ANTI_RANGE && vr1->type == VR_ANTI_RANGE) > - return NULL_TREE; > - > - /* These comparisons are never statically computable. */ > - if (comp == GT_EXPR > - || comp == GE_EXPR > - || comp == LT_EXPR > - || comp == LE_EXPR) > - return NULL_TREE; > - > - /* Equality can be computed only between a range and an > - anti-range. ~[VAL1, VAL2] == [VAL1, VAL2] is always false. */ > - if (vr0->type == VR_RANGE) > - { > - /* To simplify processing, make VR0 the anti-range. */ > - value_range *tmp = vr0; > - vr0 = vr1; > - vr1 = tmp; > - } > - > - gcc_assert (comp == NE_EXPR || comp == EQ_EXPR); > - > - if (compare_values_warnv (vr0->min, vr1->min, strict_overflow_p) == 0 > - && compare_values_warnv (vr0->max, vr1->max, strict_overflow_p) == > 0) > - return (comp == NE_EXPR) ? boolean_true_node : boolean_false_node; > - > - return NULL_TREE; > - } > - > - /* Simplify processing. If COMP is GT_EXPR or GE_EXPR, switch the > - operands around and change the comparison code. */ > - if (comp == GT_EXPR || comp == GE_EXPR) > - { > - comp = (comp == GT_EXPR) ? LT_EXPR : LE_EXPR; > - std::swap (vr0, vr1); > - } > - > - if (comp == EQ_EXPR) > - { > - /* Equality may only be computed if both ranges represent > - exactly one value. */ > - if (compare_values_warnv (vr0->min, vr0->max, strict_overflow_p) == 0 > - && compare_values_warnv (vr1->min, vr1->max, strict_overflow_p) == > 0) > - { > - int cmp_min = compare_values_warnv (vr0->min, vr1->min, > - strict_overflow_p); > - int cmp_max = compare_values_warnv (vr0->max, vr1->max, > - strict_overflow_p); > - if (cmp_min == 0 && cmp_max == 0) > - return boolean_true_node; > - else if (cmp_min != -2 && cmp_max != -2) > - return boolean_false_node; > - } > - /* If [V0_MIN, V1_MAX] < [V1_MIN, V1_MAX] then V0 != V1. */ > - else if (compare_values_warnv (vr0->min, vr1->max, > - strict_overflow_p) == 1 > - || compare_values_warnv (vr1->min, vr0->max, > - strict_overflow_p) == 1) > - return boolean_false_node; > - > - return NULL_TREE; > - } > - else if (comp == NE_EXPR) > - { > - int cmp1, cmp2; > - > - /* If VR0 is completely to the left or completely to the right > - of VR1, they are always different. Notice that we need to > - make sure that both comparisons yield similar results to > - avoid comparing values that cannot be compared at > - compile-time. */ > - cmp1 = compare_values_warnv (vr0->max, vr1->min, strict_overflow_p); > - cmp2 = compare_values_warnv (vr0->min, vr1->max, strict_overflow_p); > - if ((cmp1 == -1 && cmp2 == -1) || (cmp1 == 1 && cmp2 == 1)) > - return boolean_true_node; > - > - /* If VR0 and VR1 represent a single value and are identical, > - return false. */ > - else if (compare_values_warnv (vr0->min, vr0->max, > - strict_overflow_p) == 0 > - && compare_values_warnv (vr1->min, vr1->max, > - strict_overflow_p) == 0 > - && compare_values_warnv (vr0->min, vr1->min, > - strict_overflow_p) == 0 > - && compare_values_warnv (vr0->max, vr1->max, > - strict_overflow_p) == 0) > - return boolean_false_node; > - > - /* Otherwise, they may or may not be different. */ > - else > - return NULL_TREE; > - } > - else if (comp == LT_EXPR || comp == LE_EXPR) > - { > - int tst; > - > - /* If VR0 is to the left of VR1, return true. */ > - tst = compare_values_warnv (vr0->max, vr1->min, strict_overflow_p); > - if ((comp == LT_EXPR && tst == -1) > - || (comp == LE_EXPR && (tst == -1 || tst == 0))) > - return boolean_true_node; > - > - /* If VR0 is to the right of VR1, return false. */ > - tst = compare_values_warnv (vr0->min, vr1->max, strict_overflow_p); > - if ((comp == LT_EXPR && (tst == 0 || tst == 1)) > - || (comp == LE_EXPR && tst == 1)) > - return boolean_false_node; > - > - /* Otherwise, we don't know. */ > - return NULL_TREE; > - } > - > - gcc_unreachable (); > -} > - > - > -/* Given a value range VR, a value VAL and a comparison code COMP, return > - BOOLEAN_TRUE_NODE if VR COMP VAL always returns true for all the > - values in VR. Return BOOLEAN_FALSE_NODE if the comparison > - always returns false. Return NULL_TREE if it is not always > - possible to determine the value of the comparison. Also set > - *STRICT_OVERFLOW_P to indicate whether comparision evaluation > - assumed signed overflow is undefined. */ > - > -static tree > -compare_range_with_value (enum tree_code comp, value_range *vr, tree val, > - bool *strict_overflow_p) > -{ > - if (vr->type == VR_VARYING || vr->type == VR_UNDEFINED) > - return NULL_TREE; > - > - /* Anti-ranges need to be handled separately. */ > - if (vr->type == VR_ANTI_RANGE) > - { > - /* For anti-ranges, the only predicates that we can compute at > - compile time are equality and inequality. */ > - if (comp == GT_EXPR > - || comp == GE_EXPR > - || comp == LT_EXPR > - || comp == LE_EXPR) > - return NULL_TREE; > - > - /* ~[VAL_1, VAL_2] OP VAL is known if VAL_1 <= VAL <= VAL_2. */ > - if (value_inside_range (val, vr->min, vr->max) == 1) > - return (comp == NE_EXPR) ? boolean_true_node : boolean_false_node; > - > - return NULL_TREE; > - } > - > - if (comp == EQ_EXPR) > - { > - /* EQ_EXPR may only be computed if VR represents exactly > - one value. */ > - if (compare_values_warnv (vr->min, vr->max, strict_overflow_p) == 0) > - { > - int cmp = compare_values_warnv (vr->min, val, strict_overflow_p); > - if (cmp == 0) > - return boolean_true_node; > - else if (cmp == -1 || cmp == 1 || cmp == 2) > - return boolean_false_node; > - } > - else if (compare_values_warnv (val, vr->min, strict_overflow_p) == -1 > - || compare_values_warnv (vr->max, val, strict_overflow_p) == > -1) > - return boolean_false_node; > - > - return NULL_TREE; > - } > - else if (comp == NE_EXPR) > - { > - /* If VAL is not inside VR, then they are always different. */ > - if (compare_values_warnv (vr->max, val, strict_overflow_p) == -1 > - || compare_values_warnv (vr->min, val, strict_overflow_p) == 1) > - return boolean_true_node; > - > - /* If VR represents exactly one value equal to VAL, then return > - false. */ > - if (compare_values_warnv (vr->min, vr->max, strict_overflow_p) == 0 > - && compare_values_warnv (vr->min, val, strict_overflow_p) == 0) > - return boolean_false_node; > - > - /* Otherwise, they may or may not be different. */ > - return NULL_TREE; > - } > - else if (comp == LT_EXPR || comp == LE_EXPR) > - { > - int tst; > - > - /* If VR is to the left of VAL, return true. */ > - tst = compare_values_warnv (vr->max, val, strict_overflow_p); > - if ((comp == LT_EXPR && tst == -1) > - || (comp == LE_EXPR && (tst == -1 || tst == 0))) > - return boolean_true_node; > - > - /* If VR is to the right of VAL, return false. */ > - tst = compare_values_warnv (vr->min, val, strict_overflow_p); > - if ((comp == LT_EXPR && (tst == 0 || tst == 1)) > - || (comp == LE_EXPR && tst == 1)) > - return boolean_false_node; > - > - /* Otherwise, we don't know. */ > - return NULL_TREE; > - } > - else if (comp == GT_EXPR || comp == GE_EXPR) > - { > - int tst; > - > - /* If VR is to the right of VAL, return true. */ > - tst = compare_values_warnv (vr->min, val, strict_overflow_p); > - if ((comp == GT_EXPR && tst == 1) > - || (comp == GE_EXPR && (tst == 0 || tst == 1))) > - return boolean_true_node; > - > - /* If VR is to the left of VAL, return false. */ > - tst = compare_values_warnv (vr->max, val, strict_overflow_p); > - if ((comp == GT_EXPR && (tst == -1 || tst == 0)) > - || (comp == GE_EXPR && tst == -1)) > - return boolean_false_node; > - > - /* Otherwise, we don't know. */ > - return NULL_TREE; > - } > - > - gcc_unreachable (); > -} > - > - > /* Debugging dumps. */ > > void dump_value_range (FILE *, const value_range *); > @@ -4437,27 +2601,6 @@ debug_value_range (value_range *vr) > } > > > -/* Dump value ranges of all SSA_NAMEs to FILE. */ > - > -void > -vr_values::dump_all_value_ranges (FILE *file) > -{ > - size_t i; > - > - for (i = 0; i < num_vr_values; i++) > - { > - if (vr_value[i]) > - { > - print_generic_expr (file, ssa_name (i)); > - fprintf (file, ": "); > - dump_value_range (file, vr_value[i]); > - fprintf (file, "\n"); > - } > - } > - > - fprintf (file, "\n"); > -} > - > /* Given a COND_EXPR COND of the form 'V OP W', and an SSA name V, > create a new SSA name N and return the assertion assignment > 'N = ASSERT_EXPR <V, V OP W>'. */ > @@ -4940,7 +3083,7 @@ overflow_comparison_p_1 (enum tree_code code, tree op0, > tree op1, > {ADD,SUB}_OVERFLOW sequences later in the optimizer pipeline. But > the alternate range representation is often useful within VRP. */ > > -static bool > +bool > overflow_comparison_p (tree_code code, tree name, tree val, > bool use_equiv_p, tree *new_cst) > { > @@ -6617,7 +4760,6 @@ class vrp_prop : public ssa_propagation_engine > 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 > and "struct" hacks. If VRP can determine that the > array subscript is a constant, check if it is outside valid > @@ -7099,17 +5241,6 @@ stmt_interesting_for_vrp (gimple *stmt) > return false; > } > > -/* Initialize VRP lattice. */ > - > -vr_values::vr_values () : vrp_value_range_pool ("Tree VRP value ranges") > -{ > - values_propagated = false; > - num_vr_values = num_ssa_names; > - vr_value = XCNEWVEC (value_range *, num_vr_values); > - vr_phi_edge_counts = XCNEWVEC (int, num_ssa_names); > - bitmap_obstack_initialize (&vrp_equiv_obstack); > -} > - > /* Initialization required by ssa_propagate engine. */ > > void > @@ -7154,603 +5285,6 @@ vrp_prop::vrp_initialize () > } > } > > -/* A hack. */ > -static class vr_values *x_vr_values; > - > -/* Return the singleton value-range for NAME or NAME. */ > - > -static inline tree > -vrp_valueize (tree name) > -{ > - if (TREE_CODE (name) == SSA_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)) > - && vrp_operand_equal_p (vr->min, vr->max)) > - return vr->min; > - } > - return name; > -} > - > -/* Return the singleton value-range for NAME if that is a constant > - but signal to not follow SSA edges. */ > - > -static inline tree > -vrp_valueize_1 (tree name) > -{ > - if (TREE_CODE (name) == SSA_NAME) > - { > - /* If the definition may be simulated again we cannot follow > - this SSA edge as the SSA propagator does not necessarily > - re-visit the use. */ > - gimple *def_stmt = SSA_NAME_DEF_STMT (name); > - if (!gimple_nop_p (def_stmt) > - && prop_simulate_again_p (def_stmt)) > - return NULL_TREE; > - value_range *vr = x_vr_values->get_value_range (name); > - if (range_int_cst_singleton_p (vr)) > - return vr->min; > - } > - return name; > -} > - > -/* Visit assignment STMT. If it produces an interesting range, record > - the range in VR and set LHS to OUTPUT_P. */ > - > -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); > - lhs = gimple_get_lhs (stmt); > - *output_p = NULL_TREE; > - > - /* We only keep track of ranges in integral and pointer types. */ > - if (TREE_CODE (lhs) == SSA_NAME > - && ((INTEGRAL_TYPE_P (TREE_TYPE (lhs)) > - /* It is valid to have NULL MIN/MAX values on a type. See > - build_range_type. */ > - && TYPE_MIN_VALUE (TREE_TYPE (lhs)) > - && TYPE_MAX_VALUE (TREE_TYPE (lhs))) > - || POINTER_TYPE_P (TREE_TYPE (lhs)))) > - { > - *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 > - && (SSA_NAME_IS_DEFAULT_DEF (tem) > - || ! prop_simulate_again_p (SSA_NAME_DEF_STMT (tem)))) > - { > - extract_range_from_ssa_name (vr, tem); > - return; > - } > - else if (is_gimple_min_invariant (tem)) > - { > - set_value_range_to_value (vr, tem, NULL); > - return; > - } > - } > - /* Then dispatch to value-range extracting functions. */ > - if (code == GIMPLE_CALL) > - extract_range_basic (vr, stmt); > - else > - extract_range_from_assignment (vr, as_a <gassign *> (stmt)); > - } > -} > - > -/* Helper that gets the value range of the SSA_NAME with version I > - or a symbolic range containing the SSA_NAME only if the value range > - is varying or undefined. */ > - > -value_range > -vr_values::get_vr_for_comparison (int i) > -{ > - value_range vr = *get_value_range (ssa_name (i)); > - > - /* If name N_i does not have a valid range, use N_i as its own > - range. This allows us to compare against names that may > - have N_i in their ranges. */ > - if (vr.type == VR_VARYING || vr.type == VR_UNDEFINED) > - { > - vr.type = VR_RANGE; > - vr.min = ssa_name (i); > - vr.max = ssa_name (i); > - } > - > - return vr; > -} > - > -/* Compare all the value ranges for names equivalent to VAR with VAL > - using comparison code COMP. Return the same value returned by > - compare_range_with_value, including the setting of > - *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) > -{ > - bitmap_iterator bi; > - unsigned i; > - bitmap e; > - tree retval, t; > - int used_strict_overflow; > - bool sop; > - value_range equiv_vr; > - > - /* Get the set of equivalences for VAR. */ > - e = get_value_range (var)->equiv; > - > - /* Start at -1. Set it to 0 if we do a comparison without relying > - on overflow, or 1 if all comparisons rely on overflow. */ > - used_strict_overflow = -1; > - > - /* Compare vars' value range with val. */ > - equiv_vr = get_vr_for_comparison (SSA_NAME_VERSION (var)); > - sop = false; > - retval = compare_range_with_value (comp, &equiv_vr, val, &sop); > - if (retval) > - used_strict_overflow = sop ? 1 : 0; > - > - /* If the equiv set is empty we have done all work we need to do. */ > - if (e == NULL) > - { > - if (retval > - && used_strict_overflow > 0) > - *strict_overflow_p = true; > - return retval; > - } > - > - EXECUTE_IF_SET_IN_BITMAP (e, 0, i, bi) > - { > - tree name = ssa_name (i); > - if (! name) > - continue; > - > - if (! use_equiv_p > - && ! SSA_NAME_IS_DEFAULT_DEF (name) > - && prop_simulate_again_p (SSA_NAME_DEF_STMT (name))) > - continue; > - > - equiv_vr = get_vr_for_comparison (i); > - sop = false; > - t = compare_range_with_value (comp, &equiv_vr, val, &sop); > - if (t) > - { > - /* If we get different answers from different members > - of the equivalence set this check must be in a dead > - code region. Folding it to a trap representation > - would be correct here. For now just return don't-know. */ > - if (retval != NULL > - && t != retval) > - { > - retval = NULL_TREE; > - break; > - } > - retval = t; > - > - if (!sop) > - used_strict_overflow = 0; > - else if (used_strict_overflow < 0) > - used_strict_overflow = 1; > - } > - } > - > - if (retval > - && used_strict_overflow > 0) > - *strict_overflow_p = true; > - > - return retval; > -} > - > - > -/* Given a comparison code COMP and names N1 and N2, compare all the > - ranges equivalent to N1 against all the ranges equivalent to N2 > - to determine the value of N1 COMP N2. Return the same value > - returned by compare_ranges. Set *STRICT_OVERFLOW_P to indicate > - whether we relied on undefined signed overflow in the comparison. */ > - > - > -tree > -vr_values::compare_names (enum tree_code comp, tree n1, tree n2, > - bool *strict_overflow_p) > -{ > - tree t, retval; > - bitmap e1, e2; > - bitmap_iterator bi1, bi2; > - unsigned i1, i2; > - int used_strict_overflow; > - static bitmap_obstack *s_obstack = NULL; > - static bitmap s_e1 = NULL, s_e2 = NULL; > - > - /* Compare the ranges of every name equivalent to N1 against the > - ranges of every name equivalent to N2. */ > - e1 = get_value_range (n1)->equiv; > - e2 = get_value_range (n2)->equiv; > - > - /* Use the fake bitmaps if e1 or e2 are not available. */ > - if (s_obstack == NULL) > - { > - s_obstack = XNEW (bitmap_obstack); > - bitmap_obstack_initialize (s_obstack); > - s_e1 = BITMAP_ALLOC (s_obstack); > - s_e2 = BITMAP_ALLOC (s_obstack); > - } > - if (e1 == NULL) > - e1 = s_e1; > - if (e2 == NULL) > - e2 = s_e2; > - > - /* Add N1 and N2 to their own set of equivalences to avoid > - duplicating the body of the loop just to check N1 and N2 > - ranges. */ > - bitmap_set_bit (e1, SSA_NAME_VERSION (n1)); > - bitmap_set_bit (e2, SSA_NAME_VERSION (n2)); > - > - /* If the equivalence sets have a common intersection, then the two > - names can be compared without checking their ranges. */ > - if (bitmap_intersect_p (e1, e2)) > - { > - bitmap_clear_bit (e1, SSA_NAME_VERSION (n1)); > - bitmap_clear_bit (e2, SSA_NAME_VERSION (n2)); > - > - return (comp == EQ_EXPR || comp == GE_EXPR || comp == LE_EXPR) > - ? boolean_true_node > - : boolean_false_node; > - } > - > - /* Start at -1. Set it to 0 if we do a comparison without relying > - on overflow, or 1 if all comparisons rely on overflow. */ > - used_strict_overflow = -1; > - > - /* Otherwise, compare all the equivalent ranges. First, add N1 and > - N2 to their own set of equivalences to avoid duplicating the body > - of the loop just to check N1 and N2 ranges. */ > - EXECUTE_IF_SET_IN_BITMAP (e1, 0, i1, bi1) > - { > - if (! ssa_name (i1)) > - continue; > - > - value_range vr1 = get_vr_for_comparison (i1); > - > - t = retval = NULL_TREE; > - EXECUTE_IF_SET_IN_BITMAP (e2, 0, i2, bi2) > - { > - if (! ssa_name (i2)) > - continue; > - > - bool sop = false; > - > - value_range vr2 = get_vr_for_comparison (i2); > - > - t = compare_ranges (comp, &vr1, &vr2, &sop); > - if (t) > - { > - /* If we get different answers from different members > - of the equivalence set this check must be in a dead > - code region. Folding it to a trap representation > - would be correct here. For now just return don't-know. */ > - if (retval != NULL > - && t != retval) > - { > - bitmap_clear_bit (e1, SSA_NAME_VERSION (n1)); > - bitmap_clear_bit (e2, SSA_NAME_VERSION (n2)); > - return NULL_TREE; > - } > - retval = t; > - > - if (!sop) > - used_strict_overflow = 0; > - else if (used_strict_overflow < 0) > - used_strict_overflow = 1; > - } > - } > - > - if (retval) > - { > - bitmap_clear_bit (e1, SSA_NAME_VERSION (n1)); > - bitmap_clear_bit (e2, SSA_NAME_VERSION (n2)); > - if (used_strict_overflow > 0) > - *strict_overflow_p = true; > - return retval; > - } > - } > - > - /* None of the equivalent ranges are useful in computing this > - comparison. */ > - bitmap_clear_bit (e1, SSA_NAME_VERSION (n1)); > - bitmap_clear_bit (e2, SSA_NAME_VERSION (n2)); > - return NULL_TREE; > -} > - > -/* Helper function for vrp_evaluate_conditional_warnv & other > - optimizers. */ > - > -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; > - > - vr0 = (TREE_CODE (op0) == SSA_NAME) ? get_value_range (op0) : NULL; > - vr1 = (TREE_CODE (op1) == SSA_NAME) ? get_value_range (op1) : NULL; > - > - tree res = NULL_TREE; > - if (vr0 && vr1) > - res = compare_ranges (code, vr0, vr1, strict_overflow_p); > - if (!res && vr0) > - res = compare_range_with_value (code, vr0, op1, strict_overflow_p); > - if (!res && vr1) > - res = (compare_range_with_value > - (swap_tree_comparison (code), vr1, op0, strict_overflow_p)); > - return res; > -} > - > -/* 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) > -{ > - tree ret; > - if (only_ranges) > - *only_ranges = true; > - > - /* We only deal with integral and pointer types. */ > - if (!INTEGRAL_TYPE_P (TREE_TYPE (op0)) > - && !POINTER_TYPE_P (TREE_TYPE (op0))) > - return NULL_TREE; > - > - /* If OP0 CODE OP1 is an overflow comparison, if it can be expressed > - as a simple equality test, then prefer that over its current form > - for evaluation. > - > - An overflow test which collapses to an equality test can always be > - expressed as a comparison of one argument against zero. Overflow > - occurs when the chosen argument is zero and does not occur if the > - chosen argument is not zero. */ > - tree x; > - if (overflow_comparison_p (code, op0, op1, use_equiv_p, &x)) > - { > - wide_int max = wi::max_value (TYPE_PRECISION (TREE_TYPE (op0)), > UNSIGNED); > - /* B = A - 1; if (A < B) -> B = A - 1; if (A == 0) > - B = A - 1; if (A > B) -> B = A - 1; if (A != 0) > - B = A + 1; if (B < A) -> B = A + 1; if (B == 0) > - B = A + 1; if (B > A) -> B = A + 1; if (B != 0) */ > - if (integer_zerop (x)) > - { > - op1 = x; > - code = (code == LT_EXPR || code == LE_EXPR) ? EQ_EXPR : NE_EXPR; > - } > - /* B = A + 1; if (A > B) -> B = A + 1; if (B == 0) > - B = A + 1; if (A < B) -> B = A + 1; if (B != 0) > - B = A - 1; if (B > A) -> B = A - 1; if (A == 0) > - B = A - 1; if (B < A) -> B = A - 1; if (A != 0) */ > - else if (wi::to_wide (x) == max - 1) > - { > - op0 = op1; > - op1 = wide_int_to_tree (TREE_TYPE (op0), 0); > - code = (code == GT_EXPR || code == GE_EXPR) ? EQ_EXPR : NE_EXPR; > - } > - } > - > - if ((ret = vrp_evaluate_conditional_warnv_with_ops_using_ranges > - (code, op0, op1, strict_overflow_p))) > - return ret; > - if (only_ranges) > - *only_ranges = false; > - /* Do not use compare_names during propagation, it's quadratic. */ > - if (TREE_CODE (op0) == SSA_NAME && TREE_CODE (op1) == SSA_NAME > - && use_equiv_p) > - return compare_names (code, op0, op1, strict_overflow_p); > - else if (TREE_CODE (op0) == SSA_NAME) > - return compare_name_with_value (code, op0, op1, > - strict_overflow_p, use_equiv_p); > - else if (TREE_CODE (op1) == SSA_NAME) > - return compare_name_with_value (swap_tree_comparison (code), op1, op0, > - strict_overflow_p, use_equiv_p); > - return NULL_TREE; > -} > - > -/* Given (CODE OP0 OP1) within STMT, try to simplify it based on value range > - information. Return NULL if the conditional can not be evaluated. > - The ranges of all the names equivalent with the operands in COND > - will be used when trying to compute the value. If the result is > - based on undefined signed overflow, issue a warning if > - appropriate. */ > - > -tree > -vr_values::vrp_evaluate_conditional (tree_code code, tree op0, > - tree op1, gimple *stmt) > -{ > - bool sop; > - tree ret; > - bool only_ranges; > - > - /* Some passes and foldings leak constants with overflow flag set > - into the IL. Avoid doing wrong things with these and bail out. */ > - if ((TREE_CODE (op0) == INTEGER_CST > - && TREE_OVERFLOW (op0)) > - || (TREE_CODE (op1) == INTEGER_CST > - && TREE_OVERFLOW (op1))) > - return NULL_TREE; > - > - sop = false; > - ret = vrp_evaluate_conditional_warnv_with_ops (code, op0, op1, true, &sop, > - &only_ranges); > - > - if (ret && sop) > - { > - enum warn_strict_overflow_code wc; > - const char* warnmsg; > - > - if (is_gimple_min_invariant (ret)) > - { > - wc = WARN_STRICT_OVERFLOW_CONDITIONAL; > - warnmsg = G_("assuming signed overflow does not occur when " > - "simplifying conditional to constant"); > - } > - else > - { > - wc = WARN_STRICT_OVERFLOW_COMPARISON; > - warnmsg = G_("assuming signed overflow does not occur when " > - "simplifying conditional"); > - } > - > - if (issue_strict_overflow_warning (wc)) > - { > - location_t location; > - > - if (!gimple_has_location (stmt)) > - location = input_location; > - else > - location = gimple_location (stmt); > - warning_at (location, OPT_Wstrict_overflow, "%s", warnmsg); > - } > - } > - > - if (warn_type_limits > - && ret && only_ranges > - && TREE_CODE_CLASS (code) == tcc_comparison > - && TREE_CODE (op0) == SSA_NAME) > - { > - /* If the comparison is being folded and the operand on the LHS > - is being compared against a constant value that is outside of > - the natural range of OP0's type, then the predicate will > - always fold regardless of the value of OP0. If -Wtype-limits > - was specified, emit a warning. */ > - tree type = TREE_TYPE (op0); > - value_range *vr0 = get_value_range (op0); > - > - if (vr0->type == VR_RANGE > - && INTEGRAL_TYPE_P (type) > - && vrp_val_is_min (vr0->min) > - && vrp_val_is_max (vr0->max) > - && is_gimple_min_invariant (op1)) > - { > - location_t location; > - > - if (!gimple_has_location (stmt)) > - location = input_location; > - else > - location = gimple_location (stmt); > - > - warning_at (location, OPT_Wtype_limits, > - integer_zerop (ret) > - ? G_("comparison always false " > - "due to limited range of data type") > - : G_("comparison always true " > - "due to limited range of data type")); > - } > - } > - > - return ret; > -} > - > - > -/* Visit conditional statement STMT. If we can determine which edge > - will be taken out of STMT's basic block, record it in > - *TAKEN_EDGE_P. Otherwise, set *TAKEN_EDGE_P to NULL. */ > - > -void > -vr_values::vrp_visit_cond_stmt (gcond *stmt, edge *taken_edge_p) > -{ > - tree val; > - > - *taken_edge_p = NULL; > - > - if (dump_file && (dump_flags & TDF_DETAILS)) > - { > - tree use; > - ssa_op_iter i; > - > - fprintf (dump_file, "\nVisiting conditional with predicate: "); > - print_gimple_stmt (dump_file, stmt, 0); > - fprintf (dump_file, "\nWith known ranges\n"); > - > - FOR_EACH_SSA_TREE_OPERAND (use, stmt, i, SSA_OP_USE) > - { > - fprintf (dump_file, "\t"); > - print_generic_expr (dump_file, use); > - fprintf (dump_file, ": "); > - dump_value_range (dump_file, vr_value[SSA_NAME_VERSION (use)]); > - } > - > - fprintf (dump_file, "\n"); > - } > - > - /* Compute the value of the predicate COND by checking the known > - ranges of each of its operands. > - > - Note that we cannot evaluate all the equivalent ranges here > - because those ranges may not yet be final and with the current > - propagation strategy, we cannot determine when the value ranges > - of the names in the equivalence set have changed. > - > - For instance, given the following code fragment > - > - i_5 = PHI <8, i_13> > - ... > - i_14 = ASSERT_EXPR <i_5, i_5 != 0> > - if (i_14 == 1) > - ... > - > - Assume that on the first visit to i_14, i_5 has the temporary > - range [8, 8] because the second argument to the PHI function is > - not yet executable. We derive the range ~[0, 0] for i_14 and the > - equivalence set { i_5 }. So, when we visit 'if (i_14 == 1)' for > - the first time, since i_14 is equivalent to the range [8, 8], we > - determine that the predicate is always false. > - > - On the next round of propagation, i_13 is determined to be > - VARYING, which causes i_5 to drop down to VARYING. So, another > - visit to i_14 is scheduled. In this second visit, we compute the > - exact same range and equivalence set for i_14, namely ~[0, 0] and > - { i_5 }. But we did not have the previous range for i_5 > - registered, so vrp_visit_assignment thinks that the range for > - i_14 has not changed. Therefore, the predicate 'if (i_14 == 1)' > - is not visited again, which stops propagation from visiting > - statements in the THEN clause of that if(). > - > - To properly fix this we would need to keep the previous range > - value for the names in the equivalence set. This way we would've > - discovered that from one visit to the other i_5 changed from > - range [8, 8] to VR_VARYING. > - > - However, fixing this apparent limitation may not be worth the > - additional checking. Testing on several code bases (GCC, DLV, > - MICO, TRAMP3D and SPEC2000) showed that doing this results in > - 4 more predicates folded in SPEC. */ > - > - bool sop; > - val = vrp_evaluate_conditional_warnv_with_ops (gimple_cond_code (stmt), > - gimple_cond_lhs (stmt), > - gimple_cond_rhs (stmt), > - false, &sop, NULL); > - if (val) > - *taken_edge_p = find_taken_edge (gimple_bb (stmt), val); > - > - if (dump_file && (dump_flags & TDF_DETAILS)) > - { > - fprintf (dump_file, "\nPredicate evaluates to: "); > - if (val == NULL_TREE) > - fprintf (dump_file, "DON'T KNOW\n"); > - else > - print_generic_stmt (dump_file, val); > - } > -} > - > /* Searches the case label vector VEC for the index *IDX of the CASE_LABEL > that includes the value VAL. The search is restricted to the range > [START_IDX, n - 1] where n is the size of VEC. > @@ -7764,7 +5298,7 @@ vr_values::vrp_visit_cond_stmt (gcond *stmt, edge > *taken_edge_p) > If VAL is larger than any CASE_LABEL, n is placed on IDX and false is > returned. */ > > -static bool > +bool > find_case_label_index (gswitch *stmt, size_t start_idx, tree val, size_t > *idx) > { > size_t n = gimple_switch_num_labels (stmt); > @@ -7814,7 +5348,7 @@ find_case_label_index (gswitch *stmt, size_t start_idx, > tree val, size_t *idx) > then MAX_IDX < MIN_IDX. > Returns true if the default label is not needed. */ > > -static bool > +bool > find_case_label_range (gswitch *stmt, tree min, tree max, size_t *min_idx, > size_t *max_idx) > { > @@ -7865,201 +5399,6 @@ find_case_label_range (gswitch *stmt, tree min, tree > max, size_t *min_idx, > } > } > > -/* Searches the case label vector VEC for the ranges of CASE_LABELs that are > - used in range VR. The indices are placed in MIN_IDX1, MAX_IDX, MIN_IDX2 > and > - MAX_IDX2. If the ranges of CASE_LABELs are empty then MAX_IDX1 < > MIN_IDX1. > - Returns true if the default label is not needed. */ > - > -static bool > -find_case_label_ranges (gswitch *stmt, value_range *vr, size_t *min_idx1, > - size_t *max_idx1, size_t *min_idx2, > - size_t *max_idx2) > -{ > - size_t i, j, k, l; > - unsigned int n = gimple_switch_num_labels (stmt); > - bool take_default; > - tree case_low, case_high; > - tree min = vr->min, max = vr->max; > - > - gcc_checking_assert (vr->type == VR_RANGE || vr->type == VR_ANTI_RANGE); > - > - take_default = !find_case_label_range (stmt, min, max, &i, &j); > - > - /* Set second range to emtpy. */ > - *min_idx2 = 1; > - *max_idx2 = 0; > - > - if (vr->type == VR_RANGE) > - { > - *min_idx1 = i; > - *max_idx1 = j; > - return !take_default; > - } > - > - /* Set first range to all case labels. */ > - *min_idx1 = 1; > - *max_idx1 = n - 1; > - > - if (i > j) > - return false; > - > - /* Make sure all the values of case labels [i , j] are contained in > - range [MIN, MAX]. */ > - case_low = CASE_LOW (gimple_switch_label (stmt, i)); > - case_high = CASE_HIGH (gimple_switch_label (stmt, j)); > - if (tree_int_cst_compare (case_low, min) < 0) > - i += 1; > - if (case_high != NULL_TREE > - && tree_int_cst_compare (max, case_high) < 0) > - j -= 1; > - > - if (i > j) > - return false; > - > - /* If the range spans case labels [i, j], the corresponding anti-range > spans > - the labels [1, i - 1] and [j + 1, n - 1]. */ > - k = j + 1; > - l = n - 1; > - if (k > l) > - { > - k = 1; > - l = 0; > - } > - > - j = i - 1; > - i = 1; > - if (i > j) > - { > - i = k; > - j = l; > - k = 1; > - l = 0; > - } > - > - *min_idx1 = i; > - *max_idx1 = j; > - *min_idx2 = k; > - *max_idx2 = l; > - return false; > -} > - > -/* Visit switch statement STMT. If we can determine which edge > - will be taken out of STMT's basic block, record it in > - *TAKEN_EDGE_P. Otherwise, *TAKEN_EDGE_P set to NULL. */ > - > -void > -vr_values::vrp_visit_switch_stmt (gswitch *stmt, edge *taken_edge_p) > -{ > - tree op, val; > - value_range *vr; > - size_t i = 0, j = 0, k, l; > - bool take_default; > - > - *taken_edge_p = NULL; > - op = gimple_switch_index (stmt); > - if (TREE_CODE (op) != SSA_NAME) > - return; > - > - vr = get_value_range (op); > - if (dump_file && (dump_flags & TDF_DETAILS)) > - { > - fprintf (dump_file, "\nVisiting switch expression with operand "); > - print_generic_expr (dump_file, op); > - fprintf (dump_file, " with known range "); > - dump_value_range (dump_file, vr); > - fprintf (dump_file, "\n"); > - } > - > - if ((vr->type != VR_RANGE > - && vr->type != VR_ANTI_RANGE) > - || symbolic_range_p (vr)) > - return; > - > - /* Find the single edge that is taken from the switch expression. */ > - take_default = !find_case_label_ranges (stmt, vr, &i, &j, &k, &l); > - > - /* Check if the range spans no CASE_LABEL. If so, we only reach the default > - label */ > - if (j < i) > - { > - gcc_assert (take_default); > - val = gimple_switch_default_label (stmt); > - } > - else > - { > - /* Check if labels with index i to j and maybe the default label > - are all reaching the same label. */ > - > - val = gimple_switch_label (stmt, i); > - if (take_default > - && CASE_LABEL (gimple_switch_default_label (stmt)) > - != CASE_LABEL (val)) > - { > - if (dump_file && (dump_flags & TDF_DETAILS)) > - fprintf (dump_file, " not a single destination for this " > - "range\n"); > - return; > - } > - for (++i; i <= j; ++i) > - { > - if (CASE_LABEL (gimple_switch_label (stmt, i)) != CASE_LABEL (val)) > - { > - if (dump_file && (dump_flags & TDF_DETAILS)) > - fprintf (dump_file, " not a single destination for this " > - "range\n"); > - return; > - } > - } > - for (; k <= l; ++k) > - { > - if (CASE_LABEL (gimple_switch_label (stmt, k)) != CASE_LABEL (val)) > - { > - if (dump_file && (dump_flags & TDF_DETAILS)) > - fprintf (dump_file, " not a single destination for this " > - "range\n"); > - return; > - } > - } > - } > - > - *taken_edge_p = find_edge (gimple_bb (stmt), > - label_to_block (CASE_LABEL (val))); > - > - if (dump_file && (dump_flags & TDF_DETAILS)) > - { > - fprintf (dump_file, " will take edge to "); > - print_generic_stmt (dump_file, CASE_LABEL (val)); > - } > -} > - > - > -/* Evaluate statement STMT. If the statement produces a useful range, > - set VR and corepsponding OUTPUT_P. > - > - If STMT is a conditional branch and we can determine its truth > - value, the taken edge is recorded in *TAKEN_EDGE_P. */ > - > -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)) > - { > - fprintf (dump_file, "\nVisiting statement:\n"); > - print_gimple_stmt (dump_file, stmt, 0, dump_flags); > - } > - > - if (!stmt_interesting_for_vrp (stmt)) > - gcc_assert (stmt_ends_bb_p (stmt)); > - else if (is_gimple_assign (stmt) || is_gimple_call (stmt)) > - vrp_visit_assignment_or_call (stmt, output_p, vr); > - else if (gimple_code (stmt) == GIMPLE_COND) > - vrp_visit_cond_stmt (as_a <gcond *> (stmt), taken_edge_p); > - else if (gimple_code (stmt) == GIMPLE_SWITCH) > - vrp_visit_switch_stmt (as_a <gswitch *> (stmt), taken_edge_p); > -} > - > /* Evaluate statement STMT. If the statement produces a useful range, > return SSA_PROP_INTERESTING and record the SSA name with the > interesting range into *OUTPUT_P. > @@ -8943,222 +6282,6 @@ vrp_meet (value_range *vr0, const value_range *vr1) > } > > > -/* Visit all arguments for PHI node PHI that flow through executable > - edges. If a valid value range can be derived from all the incoming > - value ranges, set a new range in VR_RESULT. */ > - > -void > -vr_values::extract_range_from_phi_node (gphi *phi, value_range *vr_result) > -{ > - size_t i; > - tree lhs = PHI_RESULT (phi); > - value_range *lhs_vr = get_value_range (lhs); > - bool first = true; > - int edges, old_edges; > - struct loop *l; > - > - if (dump_file && (dump_flags & TDF_DETAILS)) > - { > - fprintf (dump_file, "\nVisiting PHI node: "); > - print_gimple_stmt (dump_file, phi, 0, dump_flags); > - } > - > - bool may_simulate_backedge_again = false; > - edges = 0; > - for (i = 0; i < gimple_phi_num_args (phi); i++) > - { > - edge e = gimple_phi_arg_edge (phi, i); > - > - if (dump_file && (dump_flags & TDF_DETAILS)) > - { > - fprintf (dump_file, > - " Argument #%d (%d -> %d %sexecutable)\n", > - (int) i, e->src->index, e->dest->index, > - (e->flags & EDGE_EXECUTABLE) ? "" : "not "); > - } > - > - if (e->flags & EDGE_EXECUTABLE) > - { > - tree arg = PHI_ARG_DEF (phi, i); > - value_range vr_arg; > - > - ++edges; > - > - if (TREE_CODE (arg) == SSA_NAME) > - { > - /* See if we are eventually going to change one of the args. */ > - gimple *def_stmt = SSA_NAME_DEF_STMT (arg); > - if (! gimple_nop_p (def_stmt) > - && prop_simulate_again_p (def_stmt) > - && e->flags & EDGE_DFS_BACK) > - may_simulate_backedge_again = true; > - > - vr_arg = *(get_value_range (arg)); > - /* Do not allow equivalences or symbolic ranges to leak in from > - backedges. That creates invalid equivalencies. > - See PR53465 and PR54767. */ > - if (e->flags & EDGE_DFS_BACK) > - { > - > ... > > [Message clipped]