1 /* Support routines for value ranges.
2 Copyright (C) 2019-2022 Free Software Foundation, Inc.
3 Contributed by Aldy Hernandez <aldyh@redhat.com> and
4 Andrew Macleod <amacleod@redhat.com>.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
22 #ifndef GCC_VALUE_RANGE_H
23 #define GCC_VALUE_RANGE_H
27 // Types of value ranges.
32 /* Range spans the entire domain. */
34 /* Range is [MIN, MAX]. */
36 /* Range is ~[MIN, MAX]. */
38 /* Range is a nice guy. */
42 // Discriminator between different vrange types.
44 enum value_range_discriminator
46 // Range holds an integer or pointer.
48 // Floating point range.
50 // Range holds an unsupported type.
54 // Abstract class for ranges of any of the supported types.
56 // To query what types ranger and the entire ecosystem can support,
57 // use Value_Range::supports_type_p(tree type). This is a static
58 // method available independently of any vrange object.
60 // To query what a given vrange variant can support, use:
61 // irange::supports_p ()
62 // frange::supports_p ()
65 // To query what a range object can support, use:
66 // void foo (vrange &v, irange &i, frange &f)
68 // if (v.supports_type_p (type)) ...
69 // if (i.supports_type_p (type)) ...
70 // if (f.supports_type_p (type)) ...
75 template <typename T
> friend bool is_a (vrange
&);
76 friend class Value_Range
;
78 virtual void accept (const class vrange_visitor
&v
) const = 0;
79 virtual void set (tree
, tree
, value_range_kind
= VR_RANGE
);
80 virtual tree
type () const;
81 virtual bool supports_type_p (const_tree type
) const;
82 virtual void set_varying (tree type
);
83 virtual void set_undefined ();
84 virtual bool union_ (const vrange
&);
85 virtual bool intersect (const vrange
&);
86 virtual bool singleton_p (tree
*result
= NULL
) const;
87 virtual bool contains_p (tree cst
) const;
88 virtual bool zero_p () const;
89 virtual bool nonzero_p () const;
90 virtual void set_nonzero (tree type
);
91 virtual void set_zero (tree type
);
92 virtual void set_nonnegative (tree type
);
93 virtual bool fits_p (const vrange
&r
) const;
95 bool varying_p () const;
96 bool undefined_p () const;
97 vrange
& operator= (const vrange
&);
98 bool operator== (const vrange
&) const;
99 bool operator!= (const vrange
&r
) const { return !(*this == r
); }
100 void dump (FILE *) const;
102 enum value_range_kind
kind () const; // DEPRECATED
105 ENUM_BITFIELD(value_range_kind
) m_kind
: 8;
106 ENUM_BITFIELD(value_range_discriminator
) m_discriminator
: 4;
109 // An integer range without any storage.
111 class GTY((user
)) irange
: public vrange
113 friend class vrange_allocator
;
114 friend class irange_storage_slot
; // For legacy_mode_p checks.
117 virtual void set (tree
, tree
, value_range_kind
= VR_RANGE
) override
;
118 virtual void set_nonzero (tree type
) override
;
119 virtual void set_zero (tree type
) override
;
120 virtual void set_nonnegative (tree type
) override
;
121 virtual void set_varying (tree type
) override
;
122 virtual void set_undefined () override
;
125 static bool supports_p (const_tree type
);
126 virtual bool supports_type_p (const_tree type
) const override
;
127 virtual tree
type () const override
;
129 // Iteration over sub-ranges.
130 unsigned num_pairs () const;
131 wide_int
lower_bound (unsigned = 0) const;
132 wide_int
upper_bound (unsigned) const;
133 wide_int
upper_bound () const;
136 virtual bool zero_p () const override
;
137 virtual bool nonzero_p () const override
;
138 virtual bool singleton_p (tree
*result
= NULL
) const override
;
139 virtual bool contains_p (tree cst
) const override
;
141 // In-place operators.
142 virtual bool union_ (const vrange
&) override
;
143 virtual bool intersect (const vrange
&) override
;
146 // Operator overloads.
147 irange
& operator= (const irange
&);
148 bool operator== (const irange
&) const;
149 bool operator!= (const irange
&r
) const { return !(*this == r
); }
152 virtual bool fits_p (const vrange
&r
) const override
;
153 virtual void accept (const vrange_visitor
&v
) const override
;
156 wide_int
get_nonzero_bits () const;
157 void set_nonzero_bits (const wide_int_ref
&bits
);
159 // Deprecated legacy public methods.
160 tree
min () const; // DEPRECATED
161 tree
max () const; // DEPRECATED
162 bool symbolic_p () const; // DEPRECATED
163 bool constant_p () const; // DEPRECATED
164 void normalize_symbolics (); // DEPRECATED
165 void normalize_addresses (); // DEPRECATED
166 bool may_contain_p (tree
) const; // DEPRECATED
167 bool legacy_verbose_union_ (const class irange
*); // DEPRECATED
168 bool legacy_verbose_intersect (const irange
*); // DEPRECATED
171 irange (tree
*, unsigned);
172 // potential promotion to public?
173 tree
tree_lower_bound (unsigned = 0) const;
174 tree
tree_upper_bound (unsigned) const;
175 tree
tree_upper_bound () const;
177 // In-place operators.
178 bool irange_union (const irange
&);
179 bool irange_intersect (const irange
&);
180 void irange_set (tree
, tree
);
181 void irange_set_anti_range (tree
, tree
);
182 bool irange_contains_p (const irange
&) const;
183 bool irange_single_pair_union (const irange
&r
);
185 void normalize_kind ();
187 bool legacy_mode_p () const;
188 bool legacy_equal_p (const irange
&) const;
189 void legacy_union (irange
*, const irange
*);
190 void legacy_intersect (irange
*, const irange
*);
191 void verify_range ();
192 wide_int
legacy_lower_bound (unsigned = 0) const;
193 wide_int
legacy_upper_bound (unsigned) const;
194 int value_inside_range (tree
) const;
195 bool maybe_anti_range () const;
196 void copy_to_legacy (const irange
&);
197 void copy_legacy_to_multi_range (const irange
&);
200 friend void gt_ggc_mx (irange
*);
201 friend void gt_pch_nx (irange
*);
202 friend void gt_pch_nx (irange
*, gt_pointer_operator
, void *);
204 void irange_set_1bit_anti_range (tree
, tree
);
205 bool varying_compatible_p () const;
206 void set_nonzero_bits (tree mask
);
207 bool intersect_nonzero_bits (const irange
&r
);
208 bool union_nonzero_bits (const irange
&r
);
210 bool intersect (const wide_int
& lb
, const wide_int
& ub
);
211 unsigned char m_num_ranges
;
212 unsigned char m_max_ranges
;
217 // Here we describe an irange with N pairs of ranges. The storage for
218 // the pairs is embedded in the class as an array.
221 class GTY((user
)) int_range
: public irange
225 int_range (tree
, tree
, value_range_kind
= VR_RANGE
);
226 int_range (tree type
, const wide_int
&, const wide_int
&,
227 value_range_kind
= VR_RANGE
);
228 int_range (tree type
);
229 int_range (const int_range
&);
230 int_range (const irange
&);
231 virtual ~int_range () = default;
232 int_range
& operator= (const int_range
&);
234 template <unsigned X
> friend void gt_ggc_mx (int_range
<X
> *);
235 template <unsigned X
> friend void gt_pch_nx (int_range
<X
> *);
236 template <unsigned X
> friend void gt_pch_nx (int_range
<X
> *,
237 gt_pointer_operator
, void *);
239 // ?? These stubs are for ipa-prop.cc which use a value_range in a
240 // hash_traits. hash-traits.h defines an extern of gt_ggc_mx (T &)
241 // instead of picking up the gt_ggc_mx (T *) version.
242 friend void gt_ggc_mx (int_range
<1> *&);
243 friend void gt_pch_nx (int_range
<1> *&);
248 // Unsupported temporaries may be created by ranger before it's known
249 // they're unsupported, or by vr_values::get_value_range.
251 class unsupported_range
: public vrange
256 m_discriminator
= VR_UNKNOWN
;
259 virtual void set_undefined () final override
261 m_kind
= VR_UNDEFINED
;
263 virtual void accept (const vrange_visitor
&v
) const override
;
266 // Floating point property to represent possible values of a NAN, INF, etc.
272 UNDEFINED
= 0x0, // Prop is impossible.
273 YES
= 0x1, // Prop is definitely set.
274 NO
= 0x2, // Prop is definitely not set.
275 VARYING
= (YES
| NO
) // Prop may hold.
277 fp_prop (kind f
) : m_kind (f
) { }
278 bool varying_p () const { return m_kind
== VARYING
; }
279 bool undefined_p () const { return m_kind
== UNDEFINED
; }
280 bool yes_p () const { return m_kind
== YES
; }
281 bool no_p () const { return m_kind
== NO
; }
283 unsigned char m_kind
: 2;
286 // Accessors for individual FP properties.
288 #define FP_PROP_ACCESSOR(NAME) \
289 void NAME##_set_varying () { u.bits.NAME = fp_prop::VARYING; } \
290 void NAME##_set_yes () { u.bits.NAME = fp_prop::YES; } \
291 void NAME##_set_no () { u.bits.NAME = fp_prop::NO; } \
292 bool NAME##_varying_p () const { return u.bits.NAME == fp_prop::VARYING; } \
293 bool NAME##_undefined_p () const { return u.bits.NAME == fp_prop::UNDEFINED; } \
294 bool NAME##_yes_p () const { return u.bits.NAME == fp_prop::YES; } \
295 bool NAME##_no_p () const { return u.bits.NAME == fp_prop::NO; } \
296 fp_prop get_##NAME () const \
297 { return fp_prop ((fp_prop::kind) u.bits.NAME); } \
298 void set_##NAME (fp_prop::kind f) { u.bits.NAME = f; }
300 // Aggregate of all the FP properties in an frange packed into one
301 // structure to save space. Using explicit fp_prop's in the frange,
302 // would take one byte per property because of padding. Instead, we
303 // can save all properties into one byte.
308 frange_props () { set_varying (); }
309 void set_varying () { u
.bytes
= 0xff; }
310 void set_undefined () { u
.bytes
= 0; }
311 bool varying_p () { return u
.bytes
== 0xff; }
312 bool undefined_p () { return u
.bytes
== 0; }
313 bool union_ (const frange_props
&other
);
314 bool intersect (const frange_props
&other
);
315 bool operator== (const frange_props
&other
) const;
316 FP_PROP_ACCESSOR(nan
)
317 FP_PROP_ACCESSOR(inf
)
318 FP_PROP_ACCESSOR(ninf
)
322 unsigned char nan
: 2;
323 unsigned char inf
: 2;
324 unsigned char ninf
: 2;
330 // Accessors for getting/setting all FP properties at once.
332 #define FRANGE_PROP_ACCESSOR(NAME) \
333 fp_prop get_##NAME () const { return m_props.get_##NAME (); } \
334 void set_##NAME (fp_prop::kind f) \
336 m_props.set_##NAME (f); \
340 // A floating point range.
342 class frange
: public vrange
344 friend class frange_storage_slot
;
347 frange (const frange
&);
348 static bool supports_p (const_tree type
)
350 return SCALAR_FLOAT_TYPE_P (type
);
352 virtual tree
type () const override
;
353 virtual void set (tree
, tree
, value_range_kind
= VR_RANGE
) override
;
354 virtual void set_varying (tree type
) override
;
355 virtual void set_undefined () override
;
356 virtual bool union_ (const vrange
&) override
;
357 virtual bool intersect (const vrange
&) override
;
358 virtual bool supports_type_p (const_tree type
) const override
;
359 virtual void accept (const vrange_visitor
&v
) const override
;
360 frange
& operator= (const frange
&);
361 bool operator== (const frange
&) const;
362 bool operator!= (const frange
&r
) const { return !(*this == r
); }
364 // Each fp_prop can be accessed with get_PROP() and set_PROP().
365 FRANGE_PROP_ACCESSOR(nan
)
366 FRANGE_PROP_ACCESSOR(inf
)
367 FRANGE_PROP_ACCESSOR(ninf
)
369 void verify_range ();
370 bool normalize_kind ();
372 frange_props m_props
;
376 // is_a<> and as_a<> implementation for vrange.
378 // Anything we haven't specialized is a hard fail.
379 template <typename T
>
387 template <typename T
>
389 is_a (const vrange
&v
)
391 // Reuse is_a <vrange> to implement the const version.
392 const T
&derived
= static_cast<const T
&> (v
);
393 return is_a
<T
> (const_cast<T
&> (derived
));
396 template <typename T
>
400 gcc_checking_assert (is_a
<T
> (v
));
401 return static_cast <T
&> (v
);
404 template <typename T
>
406 as_a (const vrange
&v
)
408 gcc_checking_assert (is_a
<T
> (v
));
409 return static_cast <const T
&> (v
);
412 // Specializations for the different range types.
416 is_a
<irange
> (vrange
&v
)
418 return v
.m_discriminator
== VR_IRANGE
;
423 is_a
<frange
> (vrange
&v
)
425 return v
.m_discriminator
== VR_FRANGE
;
431 virtual void visit (const irange
&) const { }
432 virtual void visit (const frange
&) const { }
433 virtual void visit (const unsupported_range
&) const { }
436 // This is a special int_range<1> with only one pair, plus
437 // VR_ANTI_RANGE magic to describe slightly more than can be described
438 // in one pair. It is described in the code as a "legacy range" (as
439 // opposed to multi-ranges which have multiple sub-ranges). It is
440 // provided for backward compatibility with code that has not been
441 // converted to multi-range irange's.
443 // There are copy operators to seamlessly copy to/fro multi-ranges.
444 typedef int_range
<1> value_range
;
446 // This is an "infinite" precision irange for use in temporary
448 typedef int_range
<255> int_range_max
;
450 // This is an "infinite" precision range object for use in temporary
451 // calculations for any of the handled types. The object can be
452 // transparently used as a vrange.
458 Value_Range (const vrange
&r
);
459 Value_Range (tree type
);
460 Value_Range (const Value_Range
&);
461 void set_type (tree type
);
462 vrange
& operator= (const vrange
&);
463 bool operator== (const Value_Range
&r
) const;
464 bool operator!= (const Value_Range
&r
) const;
466 operator const vrange
&() const;
467 void dump (FILE *) const;
468 static bool supports_type_p (const_tree type
);
470 // Convenience methods for vrange compatability.
471 void set (tree min
, tree max
, value_range_kind kind
= VR_RANGE
)
472 { return m_vrange
->set (min
, max
, kind
); }
473 tree
type () { return m_vrange
->type (); }
474 enum value_range_kind
kind () { return m_vrange
->kind (); }
475 bool varying_p () const { return m_vrange
->varying_p (); }
476 bool undefined_p () const { return m_vrange
->undefined_p (); }
477 void set_varying (tree type
) { m_vrange
->set_varying (type
); }
478 void set_undefined () { m_vrange
->set_undefined (); }
479 bool union_ (const vrange
&r
) { return m_vrange
->union_ (r
); }
480 bool intersect (const vrange
&r
) { return m_vrange
->intersect (r
); }
481 bool singleton_p (tree
*result
= NULL
) const
482 { return m_vrange
->singleton_p (result
); }
483 bool zero_p () const { return m_vrange
->zero_p (); }
484 wide_int
lower_bound () const; // For irange/prange compatability.
485 wide_int
upper_bound () const; // For irange/prange compatability.
486 void accept (const vrange_visitor
&v
) const { m_vrange
->accept (v
); }
488 void init (tree type
);
489 unsupported_range m_unsupported
;
491 int_range_max m_irange
;
496 Value_Range::Value_Range ()
498 m_vrange
= &m_unsupported
;
501 // Copy constructor from a vrange.
504 Value_Range::Value_Range (const vrange
&r
)
509 // Copy constructor from a TYPE. The range of the temporary is set to
513 Value_Range::Value_Range (tree type
)
519 Value_Range::Value_Range (const Value_Range
&r
)
521 m_vrange
= r
.m_vrange
;
524 // Initialize object so it is possible to store temporaries of TYPE
528 Value_Range::init (tree type
)
530 gcc_checking_assert (TYPE_P (type
));
532 if (irange::supports_p (type
))
533 m_vrange
= &m_irange
;
534 else if (frange::supports_p (type
))
535 m_vrange
= &m_frange
;
537 m_vrange
= &m_unsupported
;
540 // Set the temporary to allow storing temporaries of TYPE. The range
541 // of the temporary is set to UNDEFINED.
544 Value_Range::set_type (tree type
)
547 m_vrange
->set_undefined ();
550 // Assignment operator for temporaries. Copying incompatible types is
554 Value_Range::operator= (const vrange
&r
)
556 if (is_a
<irange
> (r
))
558 m_irange
= as_a
<irange
> (r
);
559 m_vrange
= &m_irange
;
561 else if (is_a
<frange
> (r
))
563 m_frange
= as_a
<frange
> (r
);
564 m_vrange
= &m_frange
;
573 Value_Range::operator== (const Value_Range
&r
) const
575 return *m_vrange
== *r
.m_vrange
;
579 Value_Range::operator!= (const Value_Range
&r
) const
581 return *m_vrange
!= *r
.m_vrange
;
585 Value_Range::operator vrange
&()
591 Value_Range::operator const vrange
&() const
596 // Return TRUE if TYPE is supported by the vrange infrastructure.
599 Value_Range::supports_type_p (const_tree type
)
601 return irange::supports_p (type
) || frange::supports_p (type
);
604 // Returns true for an old-school value_range as described above.
606 irange::legacy_mode_p () const
608 return m_max_ranges
== 1;
611 extern bool range_has_numeric_bounds_p (const irange
*);
612 extern bool ranges_from_anti_range (const value_range
*,
613 value_range
*, value_range
*);
614 extern void dump_value_range (FILE *, const vrange
*);
615 extern bool vrp_val_is_min (const_tree
);
616 extern bool vrp_val_is_max (const_tree
);
617 extern bool vrp_operand_equal_p (const_tree
, const_tree
);
619 inline value_range_kind
620 vrange::kind () const
625 // Number of sub-ranges in a range.
628 irange::num_pairs () const
630 if (m_kind
== VR_ANTI_RANGE
)
631 return constant_p () ? 2 : 1;
637 irange::type () const
639 gcc_checking_assert (m_num_ranges
> 0);
640 return TREE_TYPE (m_base
[0]);
643 // Return the lower bound of a sub-range expressed as a tree. PAIR is
644 // the sub-range in question.
647 irange::tree_lower_bound (unsigned pair
) const
649 return m_base
[pair
* 2];
652 // Return the upper bound of a sub-range expressed as a tree. PAIR is
653 // the sub-range in question.
656 irange::tree_upper_bound (unsigned pair
) const
658 return m_base
[pair
* 2 + 1];
661 // Return the highest bound of a range expressed as a tree.
664 irange::tree_upper_bound () const
666 gcc_checking_assert (m_num_ranges
);
667 return tree_upper_bound (m_num_ranges
- 1);
673 return tree_lower_bound (0);
680 return tree_upper_bound ();
686 irange::varying_compatible_p () const
688 if (m_num_ranges
!= 1)
693 tree t
= TREE_TYPE (l
);
695 if (m_kind
== VR_VARYING
&& t
== error_mark_node
)
698 unsigned prec
= TYPE_PRECISION (t
);
699 signop sign
= TYPE_SIGN (t
);
700 if (INTEGRAL_TYPE_P (t
))
701 return (wi::to_wide (l
) == wi::min_value (prec
, sign
)
702 && wi::to_wide (u
) == wi::max_value (prec
, sign
)
704 if (POINTER_TYPE_P (t
))
705 return (wi::to_wide (l
) == 0
706 && wi::to_wide (u
) == wi::max_value (prec
, sign
));
711 vrange::varying_p () const
713 return m_kind
== VR_VARYING
;
717 vrange::undefined_p () const
719 return m_kind
== VR_UNDEFINED
;
723 irange::zero_p () const
725 return (m_kind
== VR_RANGE
&& m_num_ranges
== 1
726 && integer_zerop (tree_lower_bound (0))
727 && integer_zerop (tree_upper_bound (0)));
731 irange::nonzero_p () const
736 tree zero
= build_zero_cst (type ());
737 return *this == int_range
<1> (zero
, zero
, VR_ANTI_RANGE
);
741 irange::supports_p (const_tree type
)
743 return INTEGRAL_TYPE_P (type
) || POINTER_TYPE_P (type
);
747 range_includes_zero_p (const irange
*vr
)
749 if (vr
->undefined_p ())
752 if (vr
->varying_p ())
755 return vr
->may_contain_p (build_zero_cst (vr
->type ()));
759 gt_ggc_mx (irange
*x
)
761 for (unsigned i
= 0; i
< x
->m_num_ranges
; ++i
)
763 gt_ggc_mx (x
->m_base
[i
* 2]);
764 gt_ggc_mx (x
->m_base
[i
* 2 + 1]);
766 if (x
->m_nonzero_mask
)
767 gt_ggc_mx (x
->m_nonzero_mask
);
771 gt_pch_nx (irange
*x
)
773 for (unsigned i
= 0; i
< x
->m_num_ranges
; ++i
)
775 gt_pch_nx (x
->m_base
[i
* 2]);
776 gt_pch_nx (x
->m_base
[i
* 2 + 1]);
778 if (x
->m_nonzero_mask
)
779 gt_pch_nx (x
->m_nonzero_mask
);
783 gt_pch_nx (irange
*x
, gt_pointer_operator op
, void *cookie
)
785 for (unsigned i
= 0; i
< x
->m_num_ranges
; ++i
)
787 op (&x
->m_base
[i
* 2], NULL
, cookie
);
788 op (&x
->m_base
[i
* 2 + 1], NULL
, cookie
);
790 if (x
->m_nonzero_mask
)
791 op (&x
->m_nonzero_mask
, NULL
, cookie
);
796 gt_ggc_mx (int_range
<N
> *x
)
798 gt_ggc_mx ((irange
*) x
);
803 gt_pch_nx (int_range
<N
> *x
)
805 gt_pch_nx ((irange
*) x
);
810 gt_pch_nx (int_range
<N
> *x
, gt_pointer_operator op
, void *cookie
)
812 gt_pch_nx ((irange
*) x
, op
, cookie
);
815 // Constructors for irange
818 irange::irange (tree
*base
, unsigned nranges
)
820 m_discriminator
= VR_IRANGE
;
822 m_max_ranges
= nranges
;
826 // Constructors for int_range<>.
830 int_range
<N
>::int_range ()
831 : irange (m_ranges
, N
)
836 int_range
<N
>::int_range (const int_range
&other
)
837 : irange (m_ranges
, N
)
839 irange::operator= (other
);
843 int_range
<N
>::int_range (tree min
, tree max
, value_range_kind kind
)
844 : irange (m_ranges
, N
)
846 irange::set (min
, max
, kind
);
850 int_range
<N
>::int_range (tree type
)
851 : irange (m_ranges
, N
)
857 int_range
<N
>::int_range (tree type
, const wide_int
&wmin
, const wide_int
&wmax
,
858 value_range_kind kind
)
859 : irange (m_ranges
, N
)
861 tree min
= wide_int_to_tree (type
, wmin
);
862 tree max
= wide_int_to_tree (type
, wmax
);
863 set (min
, max
, kind
);
867 int_range
<N
>::int_range (const irange
&other
)
868 : irange (m_ranges
, N
)
870 irange::operator= (other
);
875 int_range
<N
>::operator= (const int_range
&src
)
877 irange::operator= (src
);
882 irange::set_undefined ()
884 m_kind
= VR_UNDEFINED
;
886 m_nonzero_mask
= NULL
;
890 irange::set_varying (tree type
)
894 m_nonzero_mask
= NULL
;
896 if (INTEGRAL_TYPE_P (type
))
898 // Strict enum's require varying to be not TYPE_MIN/MAX, but rather
899 // min_value and max_value.
900 wide_int min
= wi::min_value (TYPE_PRECISION (type
), TYPE_SIGN (type
));
901 wide_int max
= wi::max_value (TYPE_PRECISION (type
), TYPE_SIGN (type
));
902 if (wi::eq_p (max
, wi::to_wide (TYPE_MAX_VALUE (type
)))
903 && wi::eq_p (min
, wi::to_wide (TYPE_MIN_VALUE (type
))))
905 m_base
[0] = TYPE_MIN_VALUE (type
);
906 m_base
[1] = TYPE_MAX_VALUE (type
);
910 m_base
[0] = wide_int_to_tree (type
, min
);
911 m_base
[1] = wide_int_to_tree (type
, max
);
914 else if (POINTER_TYPE_P (type
))
916 m_base
[0] = build_int_cst (type
, 0);
917 m_base
[1] = build_int_cst (type
, -1);
920 m_base
[0] = m_base
[1] = error_mark_node
;
923 // Return the lower bound of a sub-range. PAIR is the sub-range in
927 irange::lower_bound (unsigned pair
) const
929 if (legacy_mode_p ())
930 return legacy_lower_bound (pair
);
931 gcc_checking_assert (m_num_ranges
> 0);
932 gcc_checking_assert (pair
+ 1 <= num_pairs ());
933 return wi::to_wide (tree_lower_bound (pair
));
936 // Return the upper bound of a sub-range. PAIR is the sub-range in
940 irange::upper_bound (unsigned pair
) const
942 if (legacy_mode_p ())
943 return legacy_upper_bound (pair
);
944 gcc_checking_assert (m_num_ranges
> 0);
945 gcc_checking_assert (pair
+ 1 <= num_pairs ());
946 return wi::to_wide (tree_upper_bound (pair
));
949 // Return the highest bound of a range.
952 irange::upper_bound () const
954 unsigned pairs
= num_pairs ();
955 gcc_checking_assert (pairs
> 0);
956 return upper_bound (pairs
- 1);
960 irange::union_ (const vrange
&r
)
962 dump_flags_t m_flags
= dump_flags
;
963 dump_flags
&= ~TDF_DETAILS
;
964 bool ret
= irange::legacy_verbose_union_ (&as_a
<irange
> (r
));
965 dump_flags
= m_flags
;
970 irange::intersect (const vrange
&r
)
972 dump_flags_t m_flags
= dump_flags
;
973 dump_flags
&= ~TDF_DETAILS
;
974 bool ret
= irange::legacy_verbose_intersect (&as_a
<irange
> (r
));
975 dump_flags
= m_flags
;
979 // Set value range VR to a nonzero range of type TYPE.
982 irange::set_nonzero (tree type
)
984 tree zero
= build_int_cst (type
, 0);
985 if (legacy_mode_p ())
986 set (zero
, zero
, VR_ANTI_RANGE
);
988 irange_set_anti_range (zero
, zero
);
991 // Set value range VR to a ZERO range of type TYPE.
994 irange::set_zero (tree type
)
996 tree z
= build_int_cst (type
, 0);
997 if (legacy_mode_p ())
1003 // Normalize a range to VARYING or UNDEFINED if possible.
1006 irange::normalize_kind ()
1008 if (m_num_ranges
== 0)
1010 else if (varying_compatible_p ())
1012 if (m_kind
== VR_RANGE
)
1013 m_kind
= VR_VARYING
;
1014 else if (m_kind
== VR_ANTI_RANGE
)
1021 // Return the maximum value for TYPE.
1024 vrp_val_max (const_tree type
)
1026 if (INTEGRAL_TYPE_P (type
))
1027 return TYPE_MAX_VALUE (type
);
1028 if (POINTER_TYPE_P (type
))
1030 wide_int max
= wi::max_value (TYPE_PRECISION (type
), TYPE_SIGN (type
));
1031 return wide_int_to_tree (const_cast<tree
> (type
), max
);
1033 if (frange::supports_p (type
))
1035 REAL_VALUE_TYPE real
;
1037 return build_real (const_cast <tree
> (type
), real
);
1042 // Return the minimum value for TYPE.
1045 vrp_val_min (const_tree type
)
1047 if (INTEGRAL_TYPE_P (type
))
1048 return TYPE_MIN_VALUE (type
);
1049 if (POINTER_TYPE_P (type
))
1050 return build_zero_cst (const_cast<tree
> (type
));
1051 if (frange::supports_p (type
))
1053 REAL_VALUE_TYPE real
, real_ninf
;
1055 real_ninf
= real_value_negate (&real
);
1056 return build_real (const_cast <tree
> (type
), real_ninf
);
1061 // Supporting methods for frange.
1064 frange_props::operator== (const frange_props
&other
) const
1066 return u
.bytes
== other
.u
.bytes
;
1070 frange_props::union_ (const frange_props
&other
)
1072 unsigned char saved
= u
.bytes
;
1073 u
.bytes
|= other
.u
.bytes
;
1074 return u
.bytes
!= saved
;
1078 frange_props::intersect (const frange_props
&other
)
1080 unsigned char saved
= u
.bytes
;
1081 u
.bytes
&= other
.u
.bytes
;
1082 return u
.bytes
!= saved
;
1088 m_discriminator
= VR_FRANGE
;
1093 frange::frange (const frange
&src
)
1095 m_discriminator
= VR_FRANGE
;
1100 frange::type () const
1106 frange::set_varying (tree type
)
1108 m_kind
= VR_VARYING
;
1110 m_props
.set_varying ();
1114 frange::set_undefined ()
1116 m_kind
= VR_UNDEFINED
;
1118 m_props
.set_undefined ();
1121 #endif // GCC_VALUE_RANGE_H