aboutsummaryrefslogtreecommitdiff
path: root/gcc/value-range.h
AgeCommit message (Collapse)AuthorFilesLines
2023-09-26Reduce the initial size of int_range_max.Andrew MacLeod1-29/+67
This patch adds the ability to resize ranges as needed, defaulting to no resizing. int_range_max now defaults to 3 sub-ranges (instead of 255) and grows to 255 when the range being calculated does not fit. PR tree-optimization/110315 * value-range-storage.h (vrange_allocator::alloc_irange): Adjust new params. * value-range.cc (irange::operator=): Resize range. (irange::irange_union): Same. (irange::irange_intersect): Same. (irange::invert): Same. * value-range.h (irange::maybe_resize): New. (~int_range): New. (int_range_max): Default to 3 sub-ranges and resize as needed. (int_range::int_range): Adjust for resizing. (int_range::operator=): Same.
2023-03-28range-op-float: Only flush_denormals_to_zero for +-*/ [PR109154]Jakub Jelinek1-1/+1
As discussed in the PR, flushing denormals to zero on every frange::set might be harmful for e.g. x < 0.0 comparisons, because we then on both sides use ranges that include zero [-Inf, -0.0] on the true side, and [-0.0, +Inf] NAN on the false side, rather than [-Inf, nextafter (-0.0, -Inf)] on the true side. The following patch does it only in range_operator_float::fold_range which is right now used for +-*/ (both normal and reverse ops of those). Though, I don't see any difference on the testcase in the PR, but not sure what I should be looking at and the reduced testcase there has undefined behavior. 2023-03-28 Jakub Jelinek <jakub@redhat.com> PR tree-optimization/109154 * value-range.h (frange::flush_denormals_to_zero): Make it public rather than private. * value-range.cc (frange::set): Don't call flush_denormals_to_zero here. * range-op-float.cc (range_operator_float::fold_range): Call flush_denormals_to_zero.
2023-03-23ranger: Ranger meets aspellJakub Jelinek1-4/+4
I've noticed a comment typo in tree-vrp.cc and decided to quickly skim aspell -c on the ranger sources (with quick I on everything that looked ok or roughly ok). But not being a native English speaker, I could get stuff wrong. 2023-03-23 Jakub Jelinek <jakub@redhat.com> * value-range.cc (irange::irange_union, irange::intersect): Fix comment spelling bugs. * gimple-range-trace.cc (range_tracer::do_header): Likewise. * gimple-range-trace.h: Likewise. * gimple-range-edge.cc: Likewise. (gimple_outgoing_range_stmt_p, gimple_outgoing_range::switch_edge_range, gimple_outgoing_range::edge_range_p): Likewise. * gimple-range.cc (gimple_ranger::prefill_stmt_dependencies, gimple_ranger::fold_stmt, gimple_ranger::register_transitive_infer, assume_query::assume_query, assume_query::calculate_phi): Likewise. * gimple-range-edge.h: Likewise. * value-range.h (Value_Range::set, Value_Range::lower_bound, Value_Range::upper_bound, frange::set_undefined): Likewise. * gimple-range-gori.h (range_def_chain::depend, gori_map::m_outgoing, gori_compute): Likewise. * gimple-range-fold.h (fold_using_range): Likewise. * gimple-range-path.cc (path_range_query::compute_ranges_in_phis): Likewise. * gimple-range-gori.cc (range_def_chain::in_chain_p, range_def_chain::dump, gori_map::calculate_gori, gori_compute::compute_operand_range_switch, gori_compute::logical_combine, gori_compute::refine_using_relation, gori_compute::compute_operand1_range, gori_compute::may_recompute_p): Likewise. * gimple-range.h: Likewise. (enable_ranger): Likewise. * range-op.h (empty_range_varying): Likewise. * value-query.h (value_query): Likewise. * gimple-range-cache.cc (block_range_cache::set_bb_range, block_range_cache::dump, ssa_global_cache::clear_global_range, temporal_cache::temporal_value, temporal_cache::current_p, ranger_cache::range_of_def, ranger_cache::propagate_updated_value, ranger_cache::range_from_dom, ranger_cache::register_inferred_value): Likewise. * gimple-range-fold.cc (fur_edge::get_phi_operand, fur_stmt::get_operand, gimple_range_adjustment, fold_using_range::range_of_phi, fold_using_range::relation_fold_and_or): Likewise. * value-range-storage.h (irange_storage_slot::MAX_INTS): Likewise. * value-query.cc (range_query::value_of_expr, range_query::value_on_edge, range_query::query_relation): Likewise. * tree-vrp.cc (remove_unreachable::remove_and_update_globals, intersect_range_with_nonzero_bits): Likewise. * gimple-range-infer.cc (gimple_infer_range::check_assume_func, exit_range): Likewise. * value-relation.h: Likewise. (equiv_oracle, relation_trio::relation_trio, value_relation, value_relation::value_relation, pe_min): Likewise. * range-op-float.cc (range_operator_float::rv_fold, frange_arithmetic, foperator_unordered_equal::op1_range, foperator_div::rv_fold): Likewise. * gimple-range-op.cc (cfn_clz::fold_range): Likewise. * value-relation.cc (equiv_oracle::query_relation, equiv_oracle::register_equiv, equiv_oracle::add_equiv_to_block, value_relation::apply_transitive, relation_chain_head::find_relation, dom_oracle::query_relation, dom_oracle::find_relation_block, dom_oracle::find_relation_dom, path_oracle::register_equiv): Likewise. * range-op.cc (range_operator::wi_fold_in_parts_equiv, create_possibly_reversed_range, adjust_op1_for_overflow, operator_mult::wi_fold, operator_exact_divide::op1_range, operator_cast::lhs_op1_relation, operator_cast::fold_pair, operator_cast::fold_range, operator_abs::wi_fold, range_op_cast_tests, range_op_lshift_tests): Likewise.
2023-03-22frange: Implement nan_state class [PR109008]Aldy Hernandez1-0/+62
This patch implements a nan_state class, that allows us to query or pass around the NANness of an frange. We can store +NAN, -NAN, +-NAN, or not-a-NAN with it. I tried to touch as little as possible, leaving other cleanups to the next release. For example, we should replace the m_*_nan fields in frange with nan_state, and provide relevant accessors to nan_state (isnan, etc). PR tree-optimization/109008 gcc/ChangeLog: * value-range.cc (frange::set): Add nan_state argument. * value-range.h (class nan_state): New. (frange::get_nan_state): New.
2023-01-15[PR107608] [range-ops] Avoid folding into INF when flag_trapping_math.Aldy Hernandez1-0/+1
As discussed in the PR, for trapping math, do not fold overflowing operations into +-INF as doing so could elide a trap. There is a minor adjustment to known_isinf() where it was mistakenly returning true for an [infinity U NAN], whereas it should only return true when the range is exclusively +INF or -INF. This is benign, as there were no users of known_isinf up to now. Tested on x86-64 Linux. I also ran the glibc testsuite (git sources) on x86-64 and this patch fixes: -FAIL: math/test-double-lgamma -FAIL: math/test-double-log1p -FAIL: math/test-float-lgamma -FAIL: math/test-float-log1p -FAIL: math/test-float128-catan -FAIL: math/test-float128-catanh -FAIL: math/test-float128-lgamma -FAIL: math/test-float128-log -FAIL: math/test-float128-log1p -FAIL: math/test-float128-y0 -FAIL: math/test-float128-y1 -FAIL: math/test-float32-lgamma -FAIL: math/test-float32-log1p -FAIL: math/test-float32x-lgamma -FAIL: math/test-float32x-log1p -FAIL: math/test-float64-lgamma -FAIL: math/test-float64-log1p -FAIL: math/test-float64x-lgamma -FAIL: math/test-ldouble-lgamma PR tree-optimization/107608 gcc/ChangeLog: * range-op-float.cc (range_operator_float::fold_range): Avoid folding into INF when flag_trapping_math. * value-range.h (frange::known_isinf): Return false for possible NANs.
2023-01-02Update copyright years.Jakub Jelinek1-1/+1
2022-10-26Convert flag_finite_math_only uses in frange to HONOR_*.Aldy Hernandez1-6/+6
As mentioned earlier, we should be using HONOR_* on types rather than flag_finite_math_only. gcc/ChangeLog: * value-range.cc (frange::set): Use HONOR_*. (frange::verify_range): Same. * value-range.h (frange_val_min): Same. (frange_val_max): Same.
2022-10-20Do not set NAN flags for VARYING ranges when !HONOR_NANS.Aldy Hernandez1-2/+10
Since NANs can't appear in ranges for !HONOR_NANS, there's no reason to set them in a VARYING range. gcc/ChangeLog: * value-range.h (frange::set_varying): Do not set NAN flags for !HONOR_NANS. * value-range.cc (frange::normalize_kind): Adjust for no NAN when !HONOR_NANS. (frange::verify_range): Same. * range-op-float.cc (maybe_isnan): Remove flag_finite_math_only check.
2022-10-12Add method to query the sign of a NAN.Aldy Hernandez1-0/+17
In writing some range-op entries I noticed we don't have a way to query the sign of the NAN in a range, unless the range only contains NAN, in which case you can just use frange::signbit_p. This patch adds a method that returns TRUE if there exists the possiblity of a NAN and we know its sign. gcc/ChangeLog: * value-range.h (frange::nan_signbit_p): New.
2022-10-12Disable tree to bool conversion in frange::update_nan.Aldy Hernandez1-0/+1
We have a set_nan(type) method which can be confused with update_nan(bool) because of the silent conversion of pointers to bool. Currently, if you call update_nan(tree), you'll set the possibility of NAN with a sign of true if tree is non-null. This is prone to error and this patch disallows this behavior. gcc/ChangeLog: * value-range.cc (frange::set_nonnegative): Pass bool to update_nan. * value-range.h: Disallow conversion to bool in update_nan().
2022-10-12Add an frange(type) constructor analogous to the irange version.Aldy Hernandez1-0/+8
gcc/ChangeLog: * value-range.h (frange::frange): Add constructor taking type.
2022-10-10Add frange::maybe_isnan (bool sign).Aldy Hernandez1-0/+13
It is useful to know if there's the possiblity of a NAN with a given sign. This is to complement maybe_isnan(void) which returns TRUE for a NAN of any sign. A follow-up patch implementing ABS will make use of this. gcc/ChangeLog: * value-range.h (frange::maybe_isnan): New.
2022-10-07Convert nonzero mask back to tree.Aldy Hernandez1-8/+11
Having nonzero masks always set had a performance penalty of 10% in VRP, so mask==NULL is a shortcut to all bits set. gcc/ChangeLog: * value-range.cc (irange::irange_set): Convert nonzero mask to tree. (irange::irange_set_anti_range): Same. (irange::set): Same. (irange::verify_range): Same. (irange::contains_p): Same. (irange::invert): Same. (irange::set_range_from_nonzero_bits): Same. (irange::set_nonzero_bits): Same. (mask_to_wi): Same. (irange::intersect_nonzero_bits): Same. (irange::union_nonzero_bits): Same. * value-range.h (irange::varying_compatible_p): Same. (gt_ggc_mx): Same. (gt_pch_nx): Same. (irange::set_undefined): Same. (irange::set_varying): Same.
2022-10-06Setting explicit NANs sets UNDEFINED for -ffinite-math-only.Aldy Hernandez1-22/+38
We recently agreed that setting a range of NAN should instead set UNDEFINED for -ffinite-math-only. This patch makes that change to frange::set_nan() directly. Also, calling frange::update_nan() will now be a nop for !HONOR_NANS. Doing this in the setters simplifies everywhere we set NANs, as it keeps us from introducing NANs by mistake. gcc/ChangeLog: * value-range.cc (frange::set): Call set_nan unconditionally. (range_tests_nan): Adjust tests. (range_tests_signed_zeros): Same. (range_tests_floats): Same. * value-range.h (frange::update_nan): Guard with HONOR_NANS. (frange::set_nan): Set undefined if !HONOR_NANS.
2022-10-04Convert nonzero mask in irange to wide_int.Aldy Hernandez1-14/+11
The reason the nonzero mask was kept in a tree was basically inertia, as everything in irange is a tree. However, there's no need to keep it in a tree, as the conversions to and from wide ints are very annoying. That, plus special casing NULL masks to be -1 is prone to error. I have not only rewritten all the uses to assume a wide int, but have corrected a few places where we weren't propagating the masks, or rather pessimizing them to -1. This will become more important in upcoming patches where we make better use of the masks. Performance testing shows a trivial improvement in VRP, as things like irange::contains_p() are tied to a tree. Ughh, can't wait for trees in iranges to go away. gcc/ChangeLog: * value-range-storage.cc (irange_storage_slot::set_irange): Remove special case. * value-range.cc (irange::irange_set): Adjust for nonzero mask being a wide int. (irange::irange_set_anti_range): Same. (irange::set): Same. (irange::verify_range): Same. (irange::legacy_equal_p): Same. (irange::operator==): Same. (irange::contains_p): Same. (irange::legacy_intersect): Same. (irange::legacy_union): Same. (irange::irange_single_pair_union): Call union_nonzero_bits. (irange::irange_union): Same. (irange::irange_intersect): Call intersect_nonzero_bits. (irange::intersect): Adjust for nonzero mask being a wide int. (irange::invert): Same. (irange::set_nonzero_bits): Same. (irange::get_nonzero_bits_from_range): New. (irange::set_range_from_nonzero_bits): New. (irange::get_nonzero_bits): Adjust for nonzero mask being a wide int. (irange::intersect_nonzero_bits): Same. (irange::union_nonzero_bits): Same. (range_tests_nonzero_bits): Remove test. * value-range.h (irange::varying_compatible_p): Adjust for nonzero mask being a wide int. (gt_ggc_mx): Same. (gt_pch_nx): Same. (irange::set_undefined): Same. (irange::set_varying): Same. (irange::normalize_kind): Same.
2022-09-27Add an irange setter for wide_ints.Aldy Hernandez1-0/+9
Just the same way as we have real_value setters for franges, we should have a wide_int version for irange. This matches the irange constructor for wide_ints, and paves the way for the eventual conversion of irange to wide ints. gcc/ChangeLog: * value-range.h (irange::set): New version taking wide_int_ref.
2022-09-23frange: drop endpoints to min/max representable numbers for -ffinite-math-only.Aldy Hernandez1-12/+63
Similarly to how we drop NANs to UNDEFINED when -ffinite-math-only, I think we can drop the numbers outside of the min/max representable numbers to the representable number. This means the endpoings to VR_VARYING for -ffinite-math-only can now be the min/max representable, instead of -INF and +INF. Saturating in the setter means that the upcoming implementation for binary operators no longer have to worry about doing the right thing for -ffinite-math-only. If the range goes outside the limits, it'll get chopped down. Tested on x86-64 Linux. gcc/ChangeLog: * range-op-float.cc (build_le): Use vrp_val_*. (build_lt): Same. (build_ge): Same. (build_gt): Same. * value-range.cc (frange::set): Chop ranges outside of the representable numbers for -ffinite-math-only. (frange::normalize_kind): Use vrp_val*. (frange::verify_range): Same. (frange::set_nonnegative): Same. (range_tests_floats): Remove tests that depend on -INF and +INF. * value-range.h (real_max_representable): Add prototype. (real_min_representable): Same. (vrp_val_max): Set max representable number for -ffinite-math-only. (vrp_val_min): Same but for min. (frange::set_varying): Use vrp_val*.
2022-09-21Clear unused flags in frange for undefined ranges.Aldy Hernandez1-0/+4
gcc/ChangeLog: * value-range.cc (frange::combine_zeros): Call set_undefined. (frange::intersect_nans): Same. (frange::intersect): Same. (frange::verify_range): Undefined ranges do not have a type. * value-range.h (frange::set_undefined): Clear NAN flags and type.
2022-09-20frange::maybe_isnan() should return FALSE for undefined ranges.Aldy Hernandez1-0/+2
Undefined ranges have undefined NAN bits. We can't depend on them, as they may contain garbage. This patch returns false from maybe_isnan() for undefined ranges (the empty set). gcc/ChangeLog: * value-range.h (frange::maybe_isnan): Return false for undefined ranges.
2022-09-20frange::set_nonnegative should not contain -NAN.Aldy Hernandez1-0/+14
A specifically nonnegative range should not contain -NAN, otherwise signbit_p() would return false, because we'd be unsure of the sign. PR 68097/tree-optimization gcc/ChangeLog: * value-range.cc (frange::set_nonnegative): Set +NAN. (range_tests_signed_zeros): New test. * value-range.h (frange::update_nan): New overload to set NAN sign.
2022-09-20frange: flush denormals to zeroAldy Hernandez1-0/+1
For some architectures (or for -funsafe-math-optimizations) we may flush denormals to zero, in which case we need to be careful to extend the ranges to the appropriate zero. This patch does exactly that. For a range of [x, -DENORMAL] we flush to [x, -0.0] and for [+DENORMAL, x] we flush to [+0.0, x]. gcc/ChangeLog: * value-range.cc (frange::flush_denormals_to_zero): New. (frange::set): Call flush_denormals_to_zero. * value-range.h (class frange): Add flush_denormals_to_zero.
2022-09-18Rewrite NAN and sign handling in frangeAldy Hernandez1-130/+101
The attatched patch rewrites the NAN and sign handling, dropping both tristates in favor of a pair of boolean flags for NANs, and nothing at all for signs. The signs are tracked in the range itself, so now it's possible to describe things like [-0.0, +0.0] +NAN, [+0, +0], [-5, +0], [+0, 3] -NAN, etc. Here is an example of the various ranges and how they are displayed: [frange] float VARYING NAN ;; Varying includes NAN [frange] UNDEFINED ;; Empty set as always [frange] float [] +-NAN ;; Unknown sign NAN [frange] float [] -NAN ;; -NAN [frange] float [] +NAN ;; +NAN [frange] float [-0.0, 0.0] ;; All zeros. [frange] float [-0.0, -0.0] +-NAN ;; -0 or NAN. [frange] float [-5.0e+0, -1.0e+0] +NAN ;; [-5, -1] or +NAN [frange] float [-5.0e+0, -0.0] +-NAN ;; [-5, -0] or NAN [frange] float [-5.0e+0, -0.0] ;; [-5, -0] [frange] float [5.0e+0, 1.0e+1] ;; [5, 10] Notice the NAN signs are decoupled from the range, so we can represent a negative range with a positive NAN. For this range, frange::signbit_p() would return false, as only when the signs of the NANs and range agree can we be certain. There is no longer any pessimization of ranges for intersects involving NANs. Also, union and intersect work with signed zeros: // [-0, x] U [+0, x] => [-0, x] // [ x, -0] U [ x, +0] => [ x, +0] // [-0, x] ^ [+0, x] => [+0, x] // [ x, -0] ^ [ x, +0] => [ x, -0] The special casing for signed zeros in the singleton code is gone in favor of just making sure the signs in the range agree, that is [-0, -0] for example. I have removed the idea that a known NAN is a "range", so a NAN is no longer in the endpoints itself. Requesting the bound of a known NAN is a hard fail. For that matter, we don't store the actual NAN in the range. The only information we have are the set of boolean flags. This way we make sure nothing seeps into the frange. This also means it's explicit that we don't track anything but the sign in NANs. We can revisit this if we desire to track signalling or whatever concoction y'all can imagine. Regstrapped with mpfr tests on x86-64 and ppc64le Linux. Selftests were also run with -ffinite-math-only on x86-64. At Jakub's suggestion, I built lapack with associated tests. They pass on x86-64 and ppc64le Linux with no regressions from mainline. As a sanity check, I also ran them for -ffinite-math-only on x86 which (as expected) returned: NaN arithmetic did not perform per the ieee spec Otherwise, all tests pass for -ffinite-math-only. gcc/ChangeLog: * range-op-float.cc (frange_add_zeros): Replace set_signbit with union of zero. * value-query.cc (range_query::get_tree_range): Remove set_signbit use. * value-range-pretty-print.cc (vrange_printer::print_frange_prop): Remove. (vrange_printer::print_frange_nan): New. * value-range-pretty-print.h (print_frange_prop): Remove. (print_frange_nan): New. * value-range-storage.cc (frange_storage_slot::set_frange): Set kind and NAN fields. (frange_storage_slot::get_frange): Restore kind and NAN fields. * value-range-storage.h (class frange_storage_slot): Add kind and NAN fields. * value-range.cc (frange::update_nan): Remove. (frange::set_signbit): Remove. (frange::set): Adjust for NAN fields. (frange::normalize_kind): Remove m_props. (frange::combine_zeros): New. (frange::union_nans): New. (frange::union_): Handle new NAN fields. (frange::intersect_nans): New. (frange::intersect): Handle new NAN fields. (frange::operator=): Same. (frange::operator==): Same. (frange::contains_p): Same. (frange::singleton_p): Remove special case for signed zeros. (frange::verify_range): Adjust for new NAN fields. (frange::set_zero): Handle signed zeros. (frange::set_nonnegative): Same. (range_tests_nan): Adjust tests. (range_tests_signed_zeros): Same. (range_tests_signbit): Same. (range_tests_floats): Same. * value-range.h (class fp_prop): Remove. (FP_PROP_ACCESSOR): Remove. (class frange_props): Remove (frange::lower_bound): NANs don't have endpoints. (frange::upper_bound): Same. (frange_props::operator==): Remove. (frange_props::union_): Remove. (frange_props::intersect): Remove. (frange::update_nan): New. (frange::clear_nan): New. (frange::undefined_p): New. (frange::set_nan): New. (frange::known_finite): Adjust for new NAN representation. (frange::maybe_isnan): Same. (frange::known_isnan): Same. (frange::signbit_p): Same. * gimple-range-fold.cc (range_of_builtin_int_call): Rename known_signbit_p into signbit_p.
2022-09-14Use frange::set_nan() from the generic frange::set().Aldy Hernandez1-1/+8
This patch cleans up the frange::set() code by passing all things NAN to frange::set_nan(). No functional changes. Regstrapped on x86-64 Linux, plus I ran selftests for -ffinite-math-only. gcc/ChangeLog: * value-range.cc (frange::set): Use set_nan. * value-range.h (frange::set_nan): Inline code originally in set().
2022-09-14Provide cleaner set_nan(), clear_nan(), and update_nan() methods.Aldy Hernandez1-5/+6
set_* has a very specific meaning for irange's and friends. Methods prefixed with set_* are setters clobbering the existing range. As such, the current set_nan() method is confusing in that it's not actually setting a range to a NAN, but twiddling the NAN flags for an existing frange. This patch replaces set_nan() with an update_nan() to set the flag, and clear_nan() to clear it. This makes the code clearer, and though the confusing tristate is still there, it will be removed in upcoming patches. Also, there is now an actual set_nan() method to set the range to a NAN. This replaces two out of class functions doing the same thing. In future patches I will also add the ability to create a NAN with a specific sign, but doing so now would be confusing because we're not tracking NAN signs. We should also submit set_signbit to the same fate, but it's about to get removed. No functional changes. Regstrapped on x86-64 Linux, plus I ran selftests for -ffinite-math-only. gcc/ChangeLog: * range-op-float.cc (frange_set_nan): Remove. (build_lt): Use set_nan, update_nan, clear_nan. (build_gt): Same. (foperator_equal::op1_range): Same. (foperator_not_equal::op1_range): Same. (foperator_lt::op1_range): Same. (foperator_lt::op2_range): Same. (foperator_le::op1_range): Same. (foperator_le::op2_range): Same. (foperator_gt::op1_range): Same. (foperator_gt::op2_range): Same. (foperator_ge::op1_range): Same. (foperator_ge::op2_range): Same. (foperator_unordered::op1_range): Same. (foperator_ordered::op1_range): Same. * value-query.cc (range_query::get_tree_range): Same. * value-range.cc (frange::set_nan): Same. (frange::update_nan): Same. (frange::union_): Same. (frange::intersect): Same. (range_tests_nan): Same. (range_tests_signed_zeros): Same. (range_tests_signbit): Same. (range_tests_floats): Same. * value-range.h (class frange): Add update_nan and clear_nan. (frange::set_nan): New.
2022-09-14Minor fixes to frange.Aldy Hernandez1-2/+1
Following are a series of cleanups to the frange code in preparation for a much more invasive patch rewriting the NAN and sign tracking bits. Please be patient, as I'm trying to break everything up into small chunks instead of dropping a mondo patch removing the NAN and sign tristate handling. No functional changes. Regstrapped on x86-64 Linux, plus I ran selftests for -ffinite-math-only. gcc/ChangeLog: * value-query.cc (range_query::get_tree_range): Remove check for overflow. * value-range-pretty-print.cc (vrange_printer::visit): Move read of type until after undefined_p is checked. * value-range.cc (frange::set): Remove asserts for REAL_CST. (frange::contains_p): Tidy up. (range_tests_nan): Add comment. * value-range.h (frange::type): Check for undefined_p. (frange::set_undefined): Remove set of endpoints.
2022-09-08Implement known/maybe fpclassify like API for frange.Aldy Hernandez1-2/+76
gcc/ChangeLog: * gimple-range-fold.cc (fold_using_range::range_of_builtin_int_call): Use fpclassify like API. * range-op-float.cc (finite_operand_p): Same. (finite_operands_p): Same. (foperator_lt::fold_range): Same. (foperator_le::fold_range): Same. (foperator_gt::fold_range): Same. (foperator_ge::fold_range): Same. (foperator_unordered::fold_range): Same. (foperator_unordered::op1_range): Same. (foperator_ordered::fold_range): Same. * value-range.cc (frange::set_nan): Same. (frange::set_signbit): Same. (frange::union_): Same. (frange::intersect): Same. (frange::operator==): Same. (frange::singleton_p): Same. (frange::verify_range): Same. (range_tests_nan): Same. (range_tests_floats): Same. * value-range.h(frange::known_finite): New. (frange::maybe_inf): New. (frange::known_inf): New. (frange::maybe_nan): New. (frange::known_nan): New. (frange::known_signbit): New.
2022-09-05Disable decimal floating point in frange.Aldy Hernandez1-1/+4
As Jakub mentioned in the PR, because many numbers have multiple possible representations, we can't reliably return true for singleton_p. For that matter, we may not be capable of modeling them just yet. Disabling them until someone with DFP knowledge can opine or extend frange. PR middle-end/106831 gcc/ChangeLog: * value-range.h (frange::supports_p): Disable decimal floats. * range-op-float.cc (frange_drop_inf): Remove DECIMAL_FLOAT_MODE_P check. (frange_drop_ninf): Same.
2022-09-01Convert ranger uses of real_inf to dconst[n]inf.Aldy Hernandez1-12/+4
gcc/ChangeLog: * range-op-float.cc (build_le): Convert to dconst*inf. (build_ge): Same. * value-range.cc (frange::set_signbit): Same. (frange::normalize_kind): Same. (range_tests_floats): Same. * value-range.h (vrp_val_max): Same. (vrp_val_min): Same. (frange::set_varying): Same.
2022-09-01Add signbit property to frange to better model signed zeros.Aldy Hernandez1-0/+4
As discussed here: https://gcc.gnu.org/pipermail/gcc-patches/2022-August/600656.html This adds an frange property to keep track of the sign bit. We keep it updated at all times, but we don't use it make any decisions when !HONOR_SIGNED_ZEROS. With this property we can now query the range for the appropriate sign with frange::get_signbit (). Possible values are yes, no, and unknown. gcc/ChangeLog: * range-op-float.cc (foperator_equal::op1_range): Do not copy sign bit. (foperator_not_equal::op1_range): Same. * value-query.cc (range_query::get_tree_range): Set sign bit. * value-range-pretty-print.cc (vrange_printer::visit): Dump sign bit. * value-range.cc (frange::set_signbit): New. (frange::set): Adjust for sign bit. (frange::normalize_kind): Same. (frange::union_): Remove useless comment. (frange::intersect): Same. (frange::contains_p): Adjust for sign bit. (frange::singleton_p): Same. (frange::verify_range): Same. (range_tests_signbit): New tests. (range_tests_floats): Call range_tests_signbit. * value-range.h (class frange_props): Add signbit (class frange): Same.
2022-08-31fix clang warnings (-Winconsistent-missing-override)Martin Liska1-4/+4
gcc/ChangeLog: * value-range.h: Add more override keywords.
2022-08-31fix -Winconsistent-missing-override clang warningMartin Liska1-1/+1
Fixes: gcc/value-range.h:357:16: warning: 'set_nonnegative' overrides a member function but is not marked 'override' [-Winconsistent-missing-override] gcc/ChangeLog: * value-range.h: Add override.
2022-08-30Force a [NAN, NAN] range when the definite NAN property is set.Aldy Hernandez1-12/+14
Setting the definite NAN property should also force a [NAN, NAN] range, otherwise we'd have two ways of representing a NAN: with the endpoints or with the property. In the ranger world we avoid at all costs having more than one representation for a range. In doing this, I removed the FRANGE_PROP_ACCESSOR macro, since it looks like setting a property may have repercurssions in the range itself, so it's best for the client to definte its own setter. gcc/ChangeLog: * value-range-storage.cc (frange_storage_slot::get_frange): Use frange_nan. * value-range.cc (frange::set_nan): New. (frange_nan): Move to header file. (range_tests_nan): Adjust frange_nan callers to pass type. New test. * value-range.h (FRANGE_PROP_ACCESSOR): Remove. (frange_nan): New.
2022-08-30Add support for floating point endpoints to frange.Aldy Hernandez1-10/+78
The current implementation of frange is just a type with some bits to represent NAN and INF. We can do better and represent endpoints to ultimately solve longstanding PRs such as PR24021. This patch adds these endpoints. In follow-up patches I will add support for a bare bones PLUS_EXPR range-op-float entry to solve the PR. I have chosen to use REAL_VALUE_TYPEs for the endpoints, since that's what we use underneath the trees. This will be somewhat analogous to our eventual use of wide-ints in the irange. No sense going through added levels of indirection if we can avoid it. That, plus real.* already has a nice API for dealing with floats. With this patch, ranges will be closed float point intervals, which make the implementation simpler, since we don't have to keep track of open/closed intervals. This is conservative enough for use in the ranger world, as we'd rather err on the side of more elements in a range, than less. For example, even though we cannot precisely represent the open interval (3.0, 5.0) with this approach, it is perfectably reasonable to represent it as [3.0, 5.0] since the closed interval is a super set of the open one. In the VRP/ranger world, it is always better to err on the side of more information in a range, than not. After all, when we don't know anything about a range, we just use VARYING which is a fancy term for a range spanning the entire domain. Since REAL_VALUE_TYPEs have properly defined infinity and NAN semantics, all the math can be made to work: [-INF, 3.0] !NAN => Numbers <= 3.0 (NAN cannot happen) [3.0, 3.0] => 3.0 or NAN. [3.0, +INF] => Numbers >= 3.0 (NAN is possible) [-INF, +INF] => VARYING (NAN is possible) [-INF, +INF] !NAN => Entire domain. NAN cannot happen. Also, since REAL_VALUE_TYPEs can represent the minimum and maximum representable values of a TYPE_MODE, we can disambiguate between them and negative and positive infinity (see get_max_float in real.cc). This also makes the math all work. For example, suppose we know nothing about x and y (VARYING). On the TRUE side of x > y, we can deduce that: (a) x cannot be NAN (b) y cannot be NAN (c) y cannot be +INF. (c) means that we can drop the upper bound of "y" from +INF to the maximum representable value for its type. Having endpoints with different representation for infinity and the maximum representable values, means we can drop the +-INF properties we currently have in the frange. gcc/ChangeLog: * range-op-float.cc (frange_set_nan): New. (frange_drop_inf): New. (frange_drop_ninf): New. (foperator_equal::op1_range): Adjust for endpoints. (foperator_lt::op1_range): Same. (foperator_lt::op2_range): Same. (foperator_gt::op1_range): Same. (foperator_gt::op2_range): Same. (foperator_unordered::op1_range): Same. * value-query.cc (range_query::get_tree_range): Same. * value-range-pretty-print.cc (vrange_printer::visit): Same. * value-range-storage.cc (frange_storage_slot::get_frange): Same. * value-range.cc (frange::set): Same. (frange::normalize_kind): Same. (frange::union_): Same. (frange::intersect): Same. (frange::operator=): Same. (early_nan_resolve): New. (frange::contains_p): New. (frange::singleton_p): New. (frange::set_nonzero): New. (frange::nonzero_p): New. (frange::set_zero): New. (frange::zero_p): New. (frange::set_nonnegative): New. (frange_float): New. (frange_nan): New. (range_tests_nan): New. (range_tests_signed_zeros): New. (range_tests_floats): New. (range_tests): New. * value-range.h (frange::lower_bound): New. (frange::upper_bound): New. (vrp_val_min): Use real_inf with a sign instead of negating inf. (frange::frange): New. (frange::set_varying): Adjust for endpoints. (real_max_representable): New. (real_min_representable): New.
2022-08-16VR: add more virtual dtorsMartin Liska1-0/+1
Add 2 virtual destructors in order to address: gcc/alloc-pool.h:522:5: warning: destructor called on non-final 'value_range_equiv' that has virtual functions but non-virtual destructor [-Wdelete-non-abstract-non-virtual-dtor] gcc/ggc.h:166:3: warning: destructor called on non-final 'int_range<1>' that has virtual functions but non-virtual destructor [-Wdelete-non-abstract-non-virtual-dtor] gcc/ChangeLog: * value-range-equiv.h (class value_range_equiv): Add virtual destructor. * value-range.h: Likewise.
2022-08-05Inline unsupported_range constructor.Aldy Hernandez1-1/+9
An unsupported_range temporary is instantiated in every Value_Range for completeness sake and should be mostly a NOP. However, it's showing up in the callgrind stats, because it's not inline. This fixes the oversight. PR tree-optimization/106514 gcc/ChangeLog: * value-range.cc (unsupported_range::unsupported_range): Move... * value-range.h (unsupported_range::unsupported_range): ...here. (unsupported_range::set_undefined): New.
2022-08-02Implement basic range operators to enable floating point VRP.Aldy Hernandez1-2/+1
Without further ado, here is the implementation for floating point range operators, plus the switch to enable all ranger clients to handle floats. These are bare bone implementations good enough for relation operators to work, while keeping the NAN bits up to date in the frange. There is also minimal support for keeping track of +-INF when it is obvious. Tested on x86-64 Linux. gcc/ChangeLog: * range-op-float.cc (finite_operands_p): New. (frelop_early_resolve): New. (default_frelop_fold_range): New. (class foperator_equal): New. (class foperator_not_equal): New. (class foperator_lt): New. (class foperator_le): New. (class foperator_gt): New. (class foperator_ge): New. (class foperator_unordered): New. (class foperator_ordered): New. (class foperator_relop_unknown): New. (floating_op_table::floating_op_table): Add above classes to floating op table. * value-range.h (frange::supports_p): Enable. gcc/testsuite/ChangeLog: * g++.dg/opt/pr94589-2.C: XFAIL. * gcc.dg/tree-ssa/vrp-float-1.c: New test. * gcc.dg/tree-ssa/vrp-float-11.c: New test. * gcc.dg/tree-ssa/vrp-float-3.c: New test. * gcc.dg/tree-ssa/vrp-float-4.c: New test. * gcc.dg/tree-ssa/vrp-float-6.c: New test. * gcc.dg/tree-ssa/vrp-float-7.c: New test. * gcc.dg/tree-ssa/vrp-float-8.c: New test.
2022-08-01Cleanups to frange.Aldy Hernandez1-30/+40
These are some assorted cleanups to the frange class to make it easier to drop in an implementation with FP endpoints: * frange::set() had some asserts limiting the type of arguments passed. There's no reason why we can't handle all the variants. Worse comes to worse, we can always return a VARYING which is conservative and correct. * frange::normalize_kind() now returns a boolean that can be used in union and intersection to indicate that the range changed. * Implement vrp_val_max and vrp_val_min for floats. Also, move them earlier in the header file so frange can use them. Tested on x86-64 Linux. gcc/ChangeLog: * value-range.cc (tree_compare): New. (frange::set): Make more general. (frange::normalize_kind): Cleanup and return bool. (frange::union_): Use normalize_kind return value. (frange::intersect): Same. (frange::verify_range): Remove unnecessary else. * value-range.h (vrp_val_max): Move before frange class. (vrp_val_min): Same. (frange::frange): Remove set to m_type.
2022-08-01const_tree conversion of vrange::supports_*Aldy Hernandez1-8/+8
Make all vrange::supports_*_p methods const_tree as they can end up being called from functions that are const_tree. Tested on x86-64 Linux. gcc/ChangeLog: * value-range.cc (vrange::supports_type_p): Use const_tree. (irange::supports_type_p): Same. (frange::supports_type_p): Same. * value-range.h (Value_Range::supports_type_p): Same. (irange::supports_p): Same.
2022-07-25frange class to represent floating point rangesAldy Hernandez1-1/+193
This implements a basic frange class to represent floating point ranges. Although it is meant to be a base for further development, it is enough to handle relations and propagate NAN and other properties. For ranger clients to become floating point aware, we still need the range-op entries, which I will submit later this week. Since those entries require specialized FP knowledge, I will ask for a review from the FP experts before committing. Once range-op entries come live, all ranger clients that have been converted to the type agnostic vrange API will become FP aware: evrp, DOM, the threaders, loop-ch, etc. (Still missing is loop unswitching, as a lot of the int_range* temporaries should be Value_Range. I don't have enough cycles to convert loop unswitching, but could gladly give guidance. It should be straightforward for those familiar with the code ;-)). Samples things we handle: * We can set the FP properties (!NAN, !INF, etc) at assignment from constants (and propagate them throughout the CFG): float z = 0.0; if (__builtin_isnan (z)) link_error (); * The relation oracle works in tandem with the FP ranges: if (x > y) ; else if (!__builtin_isnan (x) && !__builtin_isnan (y)) { // If x and y are not NAN, the x <= y relationship holds, and the // following conditional can be folded away. if (x <= y) bar (); } * We know the true side of all ordered conditionals (except !=) implies !NAN: if (x > y) { if (__builtin_isnan (x) || __builtin_isnan (y)) link_error (); } Range-ops also works correctly with -ffinite-math-only, and avoids checking for NANs, etc. I believe this is enough to get a fully fleshed out floating point support for evrp and friends, but doing so is beyond my limited FP knowledge. For example, frange could be enhanced to track constant endpoints, and we could track other FP properties aside from NAN. Further discussion is gladly welcome. Tested on x86-64 Linux. gcc/ChangeLog: * value-range-pretty-print.cc (vrange_printer::visit): New. (vrange_printer::print_frange_prop): New. * value-range-pretty-print.h (class vrange_printer): Add visit and print_frange_prop. * value-range-storage.h (vrange_allocator::alloc_vrange): Handle frange. (vrange_allocator::alloc_frange): New. * value-range.cc (vrange::operator=): Handle frange. (vrange::operator==): Same. (frange::accept): New. (frange::set): New. (frange::normalize_kind): New. (frange::union_): New. (frange::intersect): New. (frange::operator=): New. (frange::operator==): New. (frange::supports_type_p): New. (frange::verify_range): New. * value-range.h (enum value_range_discriminator): Handle frange. (class fp_prop): New. (FP_PROP_ACCESSOR): New. (class frange_props): New. (FRANGE_PROP_ACCESSOR): New. (class frange): New. (Value_Range::init): Handle frange. (Value_Range::operator=): Same. (Value_Range::supports_type_p): Same. (frange_props::operator==): New. (frange_props::union_): New. (frange_props::intersect): New (frange::frange): New. (frange::type): New. (frange::set_varying): New. (frange::set_undefined): New.
2022-07-15Convert vrange dumping facilities to pretty_printer.Aldy Hernandez1-6/+2
We need to dump global ranges from the gimple pretty printer code, but all the vrange dumping facilities work with FILE handles. This patch converts all the dumping methods to work with pretty printers, and provides a wrapper so the FILE * methods continue to work for debugging. I also cleaned up the code a bit. Tested on x86-64 Linux. gcc/ChangeLog: * Makefile.in (OBJS): Add value-range-pretty-print.o. * pretty-print.h (pp_vrange): New. * value-range.cc (vrange::dump): Call pp version. (unsupported_range::dump): Move to its own file. (dump_bound_with_infinite_markers): Same. (irange::dump): Same. (irange::dump_bitmasks): Same. (vrange::debug): Remove. * value-range.h: Remove virtual designation for dump methods. Remove dump_bitmasks method. * value-range-pretty-print.cc: New file. * value-range-pretty-print.h: New file.
2022-07-15Implement visitor pattern for vrange.Aldy Hernandez1-0/+11
We frequently do operations on the various (upcoming) range types. The cascading if/switch statements of is_a<> are getting annoying and repetitive. The classic visitor pattern provides a clean way to implement classes handling various range types without the need for endless conditionals. It also helps us keep polluting the vrange API with functionality that should frankly live elsewhere. In a follow-up patch I will add pretty printing facilities for vrange and unify them with the dumping code. This is a prime candidate for the pattern, as the code isn't performance sensitive. Other instances (?? the dispatch code in range-ops ??) may still benefit from the hand coded conditionals, since they elide vtables in favor of the discriminator bit in vrange. Tested on x86-64 Linux. gcc/ChangeLog: * value-range.cc (irange::accept): New. (unsupported_range::accept): New. * value-range.h (class vrange_visitor): New. (class vrange): Add accept method. (class unsupported_range): Same. (class Value_Range): Same.
2022-07-10Cleanups to irange::nonzero bit code.Aldy Hernandez1-2/+3
In discussions with Andrew we realized varying_p() was returning true for a range of the entire domain with a non-empty nonzero mask. This is confusing as varying_p() should only return true when absolutely no information is available. A nonzero mask that has any cleared bits is extra information and must return false for varying_p(). This patch fixes this oversight. Now a range of the entire domain with nonzero bits, is internally set to VR_RANGE (with the appropriate end points set). VR_VARYING ranges must have a null nonzero mask. Also, the union and intersect code were not quite right in the presence of nonzero masks. Sometimes we would drop masks to -1 unnecessarily. I was trying to be too smart in avoiding extra work when the mask was NULL, but there's also an implicit mask in the range that must be taken into account. For example, [0,0] may have no nonzero bits set explicitly, but the mask is really 0x0. This will all be simpler when we drop trees, because the nonzero bits will always be set, even if -1. Finally, I've added unit tests to the nonzero mask code. This should help us maintain sanity going forward. There should be no visible changes, as the main consumer of this code is the SSA_NAME_RANGE_INFO patchset which has yet to be committed. Tested on x86-64 Linux. gcc/ChangeLog: * value-range.cc (irange::operator=): Call verify_range. (irange::irange_set): Normalize kind after everything else has been set. (irange::irange_set_anti_range): Same. (irange::set): Same. (irange::verify_range): Disallow nonzero masks for VARYING. (irange::irange_union): Call verify_range. Handle nonzero masks better. (irange::irange_intersect): Same. (irange::set_nonzero_bits): Calculate mask if either range has an explicit mask. (irange::intersect_nonzero_bits): Same. (irange::union_nonzero_bits): Same. (range_tests_nonzero_bits): New. (range_tests): Call range_tests_nonzero_bits. * value-range.h (class irange): Remove set_nonzero_bits method with trees. (irange::varying_compatible_p): Set nonzero mask.
2022-07-04Integrate nonzero bits with irange.Aldy Hernandez1-1/+19
The nonzero bits and integer ranges compliment each other quite well, and it only makes sense to make the mask a first class citizen in the irange. We do a half assed job of keeping ranges and nonzero bits somewhat in sync in SSA_NAME_RANGE_INFO, and the goal has always been to integrate them properly. This patch does that, in preparation for streaming out full-resolution iranges between passes (think SSA_NAME_RANGE_INFO). Having nonzero bits in the irange allows us to get better results from things like irange::contains_p() and keeping them in the irange allows us to propagate the bits throughout with the ranger. This patch provides the bare infrastructure, without any optimizations to range-ops, etc. Those will come as follow-ups. A few notes: Legacy SSA_NAME_RANGE_INFO updates the nonzero bits every time a range is set. Here instead, we don't update the nonzero bits on a new range, but calculate it on the fly when irange::get_nonzero_bits() is called. The goal is to only store nonzero bits that provide meaningful information that can't be gleaned from the range itself. But you can always call get_nonzero_bits() and get the full information. Nonzero bits are not supported in legacy mode. The mask may be set as a consequence of propagation or reading global ranges, but no one from legacy land should be querying irange::get_nonzero_bits. There is an assert enforcing this. However, legacy/global set_nonzero_bits() continue to work as before. There is no change to legacy behavior. There is virtually no performance change with this patch, as there are no consumers. The next patch I post will be the SSA_NAME_RANGE_INFO conversion to the new world, in which I will discuss performance proper. Hint: I'll be chewing up the time budget we gained with the vrange conversion. Tested and benchmarked on x86-64 Linux. gcc/ChangeLog: * value-range-storage.cc (irange_storage_slot::set_irange): Set nonzero bits in irange. (irange_storage_slot::get_irange): Get nonzero bits from irange. * value-range.cc (irange::operator=): Set nonzero bits. (irange::irange_set): Same. (irange::irange_set_anti_range): Same. (irange::set): Same. (irange::verify_range): Same. (irange::legacy_equal_p): Check nonzero bits. (irange::equal_p): Same. (irange::contains_p): Handle nonzero bits. (irange::irange_union): Same. (irange::irange_intersect): Same. (irange::dump): Same. (irange::set_nonzero_bits): New. (irange::get_nonzero_bits): New. (irange::intersect_nonzero_bits): New. (irange::union_nonzero_bits): New. (irange::dump_bitmasks): New. * value-range.h (class irange): Add m_nonzero_mask. (gt_ggc_mx): Handle nonzero bits. (gt_pch_nx): Same. (irange::set_undefined): Set nonzero bits. (irange::set_varying): Same. (irange::normalize_kind): Call set_undefined.
2022-07-04Remove some deprecated irange methods.Aldy Hernandez1-15/+1
Tested on x86-64 Linux. gcc/ChangeLog: * ipa-cp.cc (ipcp_vr_lattice::meet_with_1): Use operator!=. * ipa-prop.cc (struct ipa_vr_ggc_hash_traits): Same. * tree-ssa-loop-unswitch.cc (struct unswitch_predicate): Use set with two arguments. (find_unswitching_predicates_for_bb): Same. * tree-vrp.cc (range_fold_unary_symbolics_p): Same. * value-range-equiv.cc (value_range_equiv::equal_p): Use operator==. * value-range.cc (irange::equal_p): Rename to... (irange::operator==): ...this. * value-range.h (irange::set): Remove. (irange::operator==): Remove. (irange::set_zero): Use set with two arguments. * vr-values.cc (vr_values::extract_range_from_binary_expr): Same. (vr_values::extract_range_from_unary_expr): Same. (check_for_binary_op_overflow): Same. (bounds_of_var_in_loop): Same.
2022-07-03Move range allocator code to value-range-storage.*Aldy Hernandez1-109/+0
Now that vrange_storage is in its own file, I think it's prudent to move all the vrange allocator code there since it's all related. The users of value-range.h do not need to know the implementation details of the storage facilities. Tested and benchmarked on x86-64 Linux. gcc/ChangeLog: * gimple-range-cache.cc: Include value-range-storage.h. * gimple-range-cache.h (class block_range_cache): Add "class" to m_range_allocator. * gimple-range-edge.cc (gimple_outgoing_range::gimple_outgoing_range): Allocate allocator. (gimple_outgoing_range::~gimple_outgoing_range): Free allocator. (gimple_outgoing_range::calc_switch_ranges): Dereference allocator. * gimple-range-edge.h: Add "class" to m_range_allocator. * gimple-range-infer.cc (infer_range_manager::infer_range_manager): Allocate allocator. (infer_range_manager::~infer_range_manager): Free allocator. (infer_range_manager::get_nonzero): Dereference allocator. (infer_range_manager::add_range): Same. * gimple-range-infer.h (class vrange_allocator): Add "class" to m_range_allocator. * value-range-storage.h (class vrange_allocator): Move from value-range.h. (class obstack_vrange_allocator): Same. (class ggc_vrange_allocator): Same. (vrange_allocator::alloc_vrange): Same. (vrange_allocator::alloc_irange): Same. * value-range.h (class vrange_allocator): Move to value-range-storage.h. (class obstack_vrange_allocator): Same. (class ggc_vrange_allocator): Same.
2022-06-30Implement ggc_vrange_allocator.Aldy Hernandez1-21/+36
This patch makes the vrange_allocator an abstract class, and uses it to implement the obstack allocator as well as a new GC allocator. The GC bits will be used to implement the vrange storage class for global ranges, which will be contributed in the next week or so. Tested and benchmarked on x86-64 Linux. gcc/ChangeLog: * gimple-range-cache.cc (block_range_cache::block_range_cache): Rename vrange_allocator to obstack_vrange_allocator. (ssa_global_cache::ssa_global_cache): Same. * gimple-range-edge.h (class gimple_outgoing_range): Same. * gimple-range-infer.h (class infer_range_manager): Same. * value-range.h (class vrange_allocator): Make abstract. (class obstack_vrange_allocator): Inherit from vrange_allocator. (class ggc_vrange_allocator): New.
2022-06-03Misc range temporary fixes.Aldy Hernandez1-1/+7
This fixes a couples places that were using int_range_max, but needed a generic temporary. Found while merging the frange work. Also, copying between range temporaries is actually useful :). Tested on x86-64 Linux. gcc/ChangeLog: * gimple-range-cache.cc (ranger_cache::range_from_dom): Use Value_Range. * gimple-range.cc (gimple_ranger::register_inferred_ranges): Same. * value-range.h (Value_Range::Value_Range): Implement copy constructor for Value_Range.
2022-06-03Remove unneeded vrange_traits.Aldy Hernandez1-21/+7
The traits struct is no longer needed. Tested on x86-64 Linux. gcc/ChangeLog: * value-range.h (struct vrange_traits): Remove. (is_a): Rewrite without vrange_traits. (as_a): Same.
2022-06-03Flesh out unsupported_range.Aldy Hernandez1-29/+15
It's cleaner to have the unsupported_range fully fleshed out, instead of trapping on every operation. It can also serve as the basis for the default vrange methods that frange and prange will inherit. This patch implements most methods, including union and intersect, to handle an UNDEFINED and a VARYING range. Since this can serve as the basis for other classes, I have moved everything into the vrange class, making the unsupported_range trivial. Note that vrange is still an abstract class, as I have purposely left the dump() method abstract. Also, I have made the unsupported range in the temporary class (Value_Range) a method field, instead of a static member. This way the temporary can set UNDEFINED and VARYING as needed. Tested on x86-64 Linux. gcc/ChangeLog: * value-range.cc (vrange::contains_p): Implement. (vrange::type): Return void. (vrange::supports_type_p): Implement. (irange::fits_p): Same. (vrange::set_undefined): Same. (irange::set_nonnegative): Same. (vrange::set_varying): Same. (vrange::union_): Same. (unsupported_range::set): Move to vrange. (unsupported_range::type): Move to vrange. (vrange::intersect): Implement for varying and undefined. (vrange::zero_p): Implement. (unsupported_range::supports_type_p): Move to vrange. (vrange::nonzero_p): Implement. (unsupported_range::set_undefined): Move to vrange. (unsupported_range::set_varying): Same. (unsupported_range::dump): Same. (unsupported_range::union_): Same. Implement for varying and undefined. (unsupported_range::intersect): Move to vrange. (unsupported_range::zero_p): Same. (unsupported_range::nonzero_p): Same. (unsupported_range::set_nonzero): Same. (unsupported_range::set_zero): Same. (unsupported_range::set_nonnegative): Same. (unsupported_range::fits_p): Same. * value-range.h (class vrange): Remove abstract markers for most methods. (class unsupported_range): Remove most methods as they will now be inherited from vrange.
2022-06-03Implement vrange::supports_type_p.Aldy Hernandez1-12/+33
[I have conservatively assumed that both the loop-ch and loop-unswitch passes, which also use the ranger, only support integers and pointers. If the goal is to handle other types as well, irange::supports_p() should be Value_Range::supports_type_p(), and any uses of int_range_max should be converted to Value_Range. I can help in the conversion if you'd like.] As discussed, this patch disambiguates the use of supports_type_p throughout, as what ranger supports is a totally different question than what a given range variant (irange, frange, etc) supports. Unfortunately we need both a static method and a virtual method, and they can't be named the same. The uses are documented in the vrange class: +// To query what types ranger and the entire ecosystem can support, +// use Value_Range::supports_type_p(tree type). This is a static +// method available independently of any vrange object. +// +// To query what a given vrange variant can support, use: +// irange::supports_p () +// frange::supports_p () +// etc +// +// To query what a range object can support, use: +// void foo (vrange &v, irange &i, frange &f) +// { +// if (v.supports_type_p (type)) ... +// if (i.supports_type_p (type)) ... +// if (f.supports_type_p (type)) ... +// } The value_range_equiv::supports_p() method can be use to determine what legacy VRP supports, as irange::supports_p() will no longer be applicable in the evrp analyzer code base once irange and prange are split. Tested on x86-64 Linux. gcc/ChangeLog: * gimple-range-edge.cc (gimple_outgoing_range_stmt_p): Adjust for an object level supports_type_p for irange and a static Value_Range::supports_type_p. * gimple-range-fold.cc (fold_using_range::range_of_range_op): Same. (fold_using_range::range_of_address): Same. (fold_using_range::range_of_builtin_call): Same. * gimple-range-fold.h (gimple_range_type): Same. (gimple_range_ssa_p): Same. * gimple-range-path.cc (path_range_query::internal_range_of_expr): Same. (path_range_query::range_of_stmt): Same. (path_range_query::add_to_imports): Same. * gimple-range.cc (gimple_ranger::range_on_edge): Same. (gimple_ranger::export_global_ranges): Same. * gimple-ssa-evrp-analyze.cc (evrp_range_analyzer::record_ranges_from_phis): Same. * range-op.cc (range_operator::wi_fold): Same. (range_operator::fold_range): Same. * tree-ssa-loop-ch.cc (entry_loop_condition_is_static): Same. * tree-ssa-loop-unswitch.cc (struct unswitch_predicate): Same. (evaluate_control_stmt_using_entry_checks): Same. * tree-ssa-threadedge.cc (hybrid_jt_simplifier::compute_ranges_from_state): Same. * tree-vrp.cc (supported_types_p): Same. * value-query.cc (range_query::value_of_expr): Same. (range_query::value_on_edge): Same. (range_query::value_of_stmt): Same. (range_query::get_tree_range): Same. (get_range_global): Same. (global_range_query::range_of_expr): Same. * value-range-equiv.h (class value_range_equiv): Same. * value-range.cc (irange::supports_type_p): Same. (unsupported_range::supports_type_p): Same. * value-range.h (enum value_range_discriminator): Same. (Value_Range::init): Same. (Value_Range::supports_type_p): Same. (irange::supports_type_p): Same. (irange::supports_p): Same. (vrange::supports_type_p): Same. (vrange_allocator::alloc_vrange): Same.