diff options
author | Aldy Hernandez <aldyh@redhat.com> | 2022-07-31 13:43:36 +0200 |
---|---|---|
committer | Aldy Hernandez <aldyh@redhat.com> | 2022-08-01 08:16:03 +0200 |
commit | 3f05605364f6f17b84842a8a5960d465b4448bae (patch) | |
tree | f74fe9fd71c1f3bf256bd602b38066909f26ba26 /gcc/value-range.cc | |
parent | 7e029e067d81f714419cd196fdd506b06881e0c9 (diff) | |
download | gcc-3f05605364f6f17b84842a8a5960d465b4448bae.zip gcc-3f05605364f6f17b84842a8a5960d465b4448bae.tar.gz gcc-3f05605364f6f17b84842a8a5960d465b4448bae.tar.bz2 |
Cleanups to frange.
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.
Diffstat (limited to 'gcc/value-range.cc')
-rw-r--r-- | gcc/value-range.cc | 102 |
1 files changed, 65 insertions, 37 deletions
diff --git a/gcc/value-range.cc b/gcc/value-range.cc index 7adbf55..dc06f8b 100644 --- a/gcc/value-range.cc +++ b/gcc/value-range.cc @@ -260,66 +260,93 @@ frange::accept (const vrange_visitor &v) const v.visit (*this); } -// Setter for franges. Currently only singletons are supported. +// Helper function to compare floats. Returns TRUE if op1 .CODE. op2 +// is nonzero. + +static inline bool +tree_compare (tree_code code, tree op1, tree op2) +{ + return !integer_zerop (fold_build2 (code, integer_type_node, op1, op2)); +} + +// Setter for franges. void frange::set (tree min, tree max, value_range_kind kind) { - gcc_checking_assert (kind == VR_RANGE); - gcc_checking_assert (operand_equal_p (min, max)); gcc_checking_assert (TREE_CODE (min) == REAL_CST); + gcc_checking_assert (TREE_CODE (max) == REAL_CST); + + if (kind == VR_UNDEFINED) + { + set_undefined (); + return; + } + + // Treat VR_ANTI_RANGE and VR_VARYING as varying. + if (kind != VR_RANGE) + { + set_varying (TREE_TYPE (min)); + return; + } m_kind = kind; m_type = TREE_TYPE (min); - REAL_VALUE_TYPE *const cst = TREE_REAL_CST_PTR (min); - if (real_isnan (cst)) - m_props.nan_set_yes (); - else - m_props.nan_set_no (); - - if (real_isinf (cst)) + // Mark NANness. + if (real_isnan (TREE_REAL_CST_PTR (min)) + || real_isnan (TREE_REAL_CST_PTR (max))) { - if (real_isneg (cst)) - { - m_props.inf_set_no (); - m_props.ninf_set_yes (); - } - else - { - m_props.inf_set_yes (); - m_props.ninf_set_no (); - } + gcc_checking_assert (operand_equal_p (min, max)); + m_props.nan_set_yes (); } else + m_props.nan_set_no (); + + bool is_min = vrp_val_is_min (min); + bool is_max = vrp_val_is_max (max); + + // Mark when the endpoints can't be INF. + if (!is_min) + m_props.ninf_set_no (); + if (!is_max) + m_props.inf_set_no (); + + // Mark when the endpoints are definitely INF. + if (operand_equal_p (min, max)) { - m_props.inf_set_no (); - m_props.ninf_set_no (); + if (is_min) + m_props.ninf_set_yes (); + else if (is_max) + m_props.inf_set_yes (); } + // Check for swapped ranges. + gcc_checking_assert (m_props.nan_yes_p () + || tree_compare (LE_EXPR, min, max)); + if (flag_checking) verify_range (); } -// Normalize range to VARYING or UNDEFINED, or vice versa. +// Normalize range to VARYING or UNDEFINED, or vice versa. Return +// TRUE if anything changed. // // A range with no known properties can be dropped to VARYING. // Similarly, a VARYING with any properties should be dropped to a // VR_RANGE. Normalizing ranges upon changing them ensures there is // only one representation for a given range. -void +bool frange::normalize_kind () { if (m_kind == VR_RANGE) { // No FP properties set means varying. - if (m_props.nan_varying_p () - && m_props.inf_varying_p () - && m_props.ninf_varying_p ()) + if (m_props.varying_p ()) { set_varying (m_type); - return; + return true; } // Undefined is viral. if (m_props.nan_undefined_p () @@ -327,17 +354,19 @@ frange::normalize_kind () || m_props.ninf_undefined_p ()) { set_undefined (); - return; + return true; } } else if (m_kind == VR_VARYING) { // If a VARYING has any FP properties, it's no longer VARYING. - if (!m_props.nan_varying_p () - || !m_props.inf_varying_p () - || !m_props.ninf_varying_p ()) - m_kind = VR_RANGE; + if (!m_props.varying_p ()) + { + m_kind = VR_RANGE; + return true; + } } + return false; } bool @@ -354,7 +383,7 @@ frange::union_ (const vrange &v) } bool ret = m_props.union_ (r.m_props); - normalize_kind (); + ret |= normalize_kind (); if (flag_checking) verify_range (); @@ -380,7 +409,7 @@ frange::intersect (const vrange &v) } bool ret = m_props.intersect (r.m_props); - normalize_kind (); + ret |= normalize_kind (); if (flag_checking) verify_range (); @@ -429,12 +458,11 @@ frange::verify_range () gcc_checking_assert (m_props.undefined_p ()); return; } - else if (varying_p ()) + if (varying_p ()) { gcc_checking_assert (m_props.varying_p ()); return; } - gcc_checking_assert (m_kind == VR_RANGE); gcc_checking_assert (!m_props.varying_p () && !m_props.undefined_p ()); } |