| /* Support routines for value ranges. |
| Copyright (C) 2019-2020 Free Software Foundation, Inc. |
| |
| This file is part of GCC. |
| |
| GCC is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 3, or (at your option) |
| any later version. |
| |
| GCC is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GCC; see the file COPYING3. If not see |
| <http://www.gnu.org/licenses/>. */ |
| |
| #ifndef GCC_VALUE_RANGE_H |
| #define GCC_VALUE_RANGE_H |
| |
| /* Types of value ranges. */ |
| enum value_range_kind |
| { |
| /* Empty range. */ |
| VR_UNDEFINED, |
| /* Range spans the entire domain. */ |
| VR_VARYING, |
| /* Range is [MIN, MAX]. */ |
| VR_RANGE, |
| /* Range is ~[MIN, MAX]. */ |
| VR_ANTI_RANGE, |
| /* Range is a nice guy. */ |
| VR_LAST |
| }; |
| |
| // Range of values that can be associated with an SSA_NAME. |
| |
| class GTY((for_user)) value_range |
| { |
| public: |
| value_range (); |
| value_range (tree, tree, value_range_kind = VR_RANGE); |
| value_range (tree type, const wide_int &, const wide_int &, |
| value_range_kind = VR_RANGE); |
| value_range (tree type); |
| |
| void set (tree, tree, value_range_kind = VR_RANGE); |
| void set (tree); |
| void set_nonzero (tree); |
| void set_zero (tree); |
| |
| enum value_range_kind kind () const; |
| tree min () const; |
| tree max () const; |
| |
| /* Types of value ranges. */ |
| bool symbolic_p () const; |
| bool constant_p () const; |
| bool undefined_p () const; |
| bool varying_p () const; |
| void set_varying (tree type); |
| void set_undefined (); |
| |
| void union_ (const value_range *); |
| void intersect (const value_range *); |
| void union_ (const value_range &); |
| void intersect (const value_range &); |
| |
| bool operator== (const value_range &) const; |
| bool operator!= (const value_range &) const /* = delete */; |
| bool equal_p (const value_range &) const; |
| |
| /* Misc methods. */ |
| tree type () const; |
| bool may_contain_p (tree) const; |
| bool zero_p () const; |
| bool nonzero_p () const; |
| bool singleton_p (tree *result = NULL) const; |
| void dump (FILE *) const; |
| void dump () const; |
| |
| static bool supports_type_p (tree); |
| void normalize_symbolics (); |
| void normalize_addresses (); |
| |
| static const unsigned int m_max_pairs = 2; |
| bool contains_p (tree) const; |
| unsigned num_pairs () const; |
| wide_int lower_bound (unsigned = 0) const; |
| wide_int upper_bound (unsigned) const; |
| wide_int upper_bound () const; |
| void invert (); |
| |
| protected: |
| void check (); |
| static value_range union_helper (const value_range *, const value_range *); |
| static value_range intersect_helper (const value_range *, |
| const value_range *); |
| |
| friend void gt_ggc_mx_value_range (void *); |
| friend void gt_pch_p_11value_range (void *, void *, |
| gt_pointer_operator, void *); |
| friend void gt_pch_nx_value_range (void *); |
| friend void gt_ggc_mx (value_range &); |
| friend void gt_ggc_mx (value_range *&); |
| friend void gt_pch_nx (value_range &); |
| friend void gt_pch_nx (value_range *, gt_pointer_operator, void *); |
| |
| enum value_range_kind m_kind; |
| tree m_min; |
| tree m_max; |
| |
| private: |
| int value_inside_range (tree) const; |
| }; |
| |
| extern bool range_has_numeric_bounds_p (const value_range *); |
| extern bool ranges_from_anti_range (const value_range *, |
| value_range *, value_range *); |
| extern void dump_value_range (FILE *, const value_range *); |
| extern bool vrp_val_is_min (const_tree); |
| extern bool vrp_val_is_max (const_tree); |
| extern tree vrp_val_min (const_tree); |
| extern tree vrp_val_max (const_tree); |
| extern bool vrp_operand_equal_p (const_tree, const_tree); |
| |
| inline |
| value_range::value_range () |
| { |
| m_kind = VR_UNDEFINED; |
| m_min = m_max = NULL; |
| } |
| |
| inline value_range_kind |
| value_range::kind () const |
| { |
| return m_kind; |
| } |
| |
| inline tree |
| value_range::type () const |
| { |
| return TREE_TYPE (min ()); |
| } |
| |
| inline tree |
| value_range::min () const |
| { |
| return m_min; |
| } |
| |
| inline tree |
| value_range::max () const |
| { |
| return m_max; |
| } |
| |
| inline bool |
| value_range::varying_p () const |
| { |
| return m_kind == VR_VARYING; |
| } |
| |
| inline bool |
| value_range::undefined_p () const |
| { |
| return m_kind == VR_UNDEFINED; |
| } |
| |
| inline bool |
| value_range::zero_p () const |
| { |
| return (m_kind == VR_RANGE |
| && integer_zerop (m_min) |
| && integer_zerop (m_max)); |
| } |
| |
| inline bool |
| value_range::nonzero_p () const |
| { |
| if (m_kind == VR_ANTI_RANGE |
| && !TYPE_UNSIGNED (type ()) |
| && integer_zerop (m_min) |
| && integer_zerop (m_max)) |
| return true; |
| |
| return (m_kind == VR_RANGE |
| && TYPE_UNSIGNED (type ()) |
| && integer_onep (m_min) |
| && vrp_val_is_max (m_max)); |
| } |
| |
| inline bool |
| value_range::supports_type_p (tree type) |
| { |
| if (type && (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))) |
| return type; |
| return false; |
| } |
| |
| inline bool |
| range_includes_zero_p (const value_range *vr) |
| { |
| if (vr->undefined_p ()) |
| return false; |
| |
| if (vr->varying_p ()) |
| return true; |
| |
| return vr->may_contain_p (build_zero_cst (vr->type ())); |
| } |
| |
| #endif // GCC_VALUE_RANGE_H |