]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/value-range.h
d: Import dmd b8384668f, druntime e6caaab9, phobos 5ab9ad256 (v2.098.0-beta.1)
[thirdparty/gcc.git] / gcc / value-range.h
1 /* Support routines for value ranges.
2 Copyright (C) 2019-2021 Free Software Foundation, Inc.
3 Contributed by Aldy Hernandez <aldyh@redhat.com> and
4 Andrew Macleod <amacleod@redhat.com>.
5
6 This file is part of GCC.
7
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)
11 any later version.
12
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.
17
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/>. */
21
22 #ifndef GCC_VALUE_RANGE_H
23 #define GCC_VALUE_RANGE_H
24
25 // Types of value ranges.
26 enum value_range_kind
27 {
28 /* Empty range. */
29 VR_UNDEFINED,
30 /* Range spans the entire domain. */
31 VR_VARYING,
32 /* Range is [MIN, MAX]. */
33 VR_RANGE,
34 /* Range is ~[MIN, MAX]. */
35 VR_ANTI_RANGE,
36 /* Range is a nice guy. */
37 VR_LAST
38 };
39
40 // Range of values that can be associated with an SSA_NAME.
41 //
42 // This is the base class without any storage.
43
44 class GTY((user)) irange
45 {
46 friend class irange_allocator;
47 public:
48 // In-place setters.
49 void set (tree, tree, value_range_kind = VR_RANGE);
50 void set_nonzero (tree);
51 void set_zero (tree);
52 void set_varying (tree type);
53 void set_undefined ();
54
55 // Range types.
56 static bool supports_type_p (tree);
57 tree type () const;
58
59 // Iteration over sub-ranges.
60 unsigned num_pairs () const;
61 wide_int lower_bound (unsigned = 0) const;
62 wide_int upper_bound (unsigned) const;
63 wide_int upper_bound () const;
64
65 // Predicates.
66 bool zero_p () const;
67 bool nonzero_p () const;
68 bool undefined_p () const;
69 bool varying_p () const;
70 bool singleton_p (tree *result = NULL) const;
71 bool contains_p (tree) const;
72
73 // In-place operators.
74 void union_ (const irange &);
75 void intersect (const irange &);
76 void intersect (const wide_int& lb, const wide_int& ub);
77 void invert ();
78
79 // Operator overloads.
80 irange& operator= (const irange &);
81 bool operator== (const irange &) const;
82 bool operator!= (const irange &r) const { return !(*this == r); }
83
84 // Misc methods.
85 bool fits_p (const irange &r) { return m_max_ranges >= r.num_pairs (); }
86 void dump (FILE * = stderr) const;
87 void debug () const;
88
89 // Deprecated legacy public methods.
90 enum value_range_kind kind () const; // DEPRECATED
91 tree min () const; // DEPRECATED
92 tree max () const; // DEPRECATED
93 bool symbolic_p () const; // DEPRECATED
94 bool constant_p () const; // DEPRECATED
95 void normalize_symbolics (); // DEPRECATED
96 void normalize_addresses (); // DEPRECATED
97 bool may_contain_p (tree) const; // DEPRECATED
98 void set (tree); // DEPRECATED
99 bool equal_p (const irange &) const; // DEPRECATED
100 void union_ (const class irange *); // DEPRECATED
101 void intersect (const irange *); // DEPRECATED
102
103 protected:
104 irange (tree *, unsigned);
105 // potential promotion to public?
106 tree tree_lower_bound (unsigned = 0) const;
107 tree tree_upper_bound (unsigned) const;
108 tree tree_upper_bound () const;
109
110 // In-place operators.
111 void irange_union (const irange &);
112 void irange_intersect (const irange &);
113 void irange_set (tree, tree);
114 void irange_set_anti_range (tree, tree);
115
116 void normalize_kind ();
117
118 bool legacy_mode_p () const;
119 bool legacy_equal_p (const irange &) const;
120 void legacy_union (irange *, const irange *);
121 void legacy_intersect (irange *, const irange *);
122 void verify_range ();
123 wide_int legacy_lower_bound (unsigned = 0) const;
124 wide_int legacy_upper_bound (unsigned) const;
125 int value_inside_range (tree) const;
126 bool maybe_anti_range () const;
127 void copy_to_legacy (const irange &);
128 void copy_legacy_to_multi_range (const irange &);
129
130 private:
131 friend void gt_ggc_mx (irange *);
132 friend void gt_pch_nx (irange *);
133 friend void gt_pch_nx (irange *, gt_pointer_operator, void *);
134
135 void irange_set_1bit_anti_range (tree, tree);
136 bool varying_compatible_p () const;
137
138 unsigned char m_num_ranges;
139 unsigned char m_max_ranges;
140 ENUM_BITFIELD(value_range_kind) m_kind : 8;
141 tree *m_base;
142 };
143
144 // Here we describe an irange with N pairs of ranges. The storage for
145 // the pairs is embedded in the class as an array.
146
147 template<unsigned N>
148 class GTY((user)) int_range : public irange
149 {
150 public:
151 int_range ();
152 int_range (tree, tree, value_range_kind = VR_RANGE);
153 int_range (tree type, const wide_int &, const wide_int &,
154 value_range_kind = VR_RANGE);
155 int_range (tree type);
156 int_range (const int_range &);
157 int_range (const irange &);
158 int_range& operator= (const int_range &);
159 private:
160 template <unsigned X> friend void gt_ggc_mx (int_range<X> *);
161 template <unsigned X> friend void gt_pch_nx (int_range<X> *);
162 template <unsigned X> friend void gt_pch_nx (int_range<X> *,
163 gt_pointer_operator, void *);
164
165 // ?? These stubs are for ipa-prop.c which use a value_range in a
166 // hash_traits. hash-traits.h defines an extern of gt_ggc_mx (T &)
167 // instead of picking up the gt_ggc_mx (T *) version.
168 friend void gt_ggc_mx (int_range<1> *&);
169 friend void gt_pch_nx (int_range<1> *&);
170
171 tree m_ranges[N*2];
172 };
173
174 // This is a special int_range<1> with only one pair, plus
175 // VR_ANTI_RANGE magic to describe slightly more than can be described
176 // in one pair. It is described in the code as a "legacy range" (as
177 // opposed to multi-ranges which have multiple sub-ranges). It is
178 // provided for backward compatibility with code that has not been
179 // converted to multi-range irange's.
180 //
181 // There are copy operators to seamlessly copy to/fro multi-ranges.
182 typedef int_range<1> value_range;
183
184 // This is an "infinite" precision irange for use in temporary
185 // calculations.
186 typedef int_range<255> int_range_max;
187
188 // Returns true for an old-school value_range as described above.
189 inline bool
190 irange::legacy_mode_p () const
191 {
192 return m_max_ranges == 1;
193 }
194
195 extern bool range_has_numeric_bounds_p (const irange *);
196 extern bool ranges_from_anti_range (const value_range *,
197 value_range *, value_range *);
198 extern void dump_value_range (FILE *, const irange *);
199 extern bool vrp_val_is_min (const_tree);
200 extern bool vrp_val_is_max (const_tree);
201 extern bool vrp_operand_equal_p (const_tree, const_tree);
202
203 inline value_range_kind
204 irange::kind () const
205 {
206 return m_kind;
207 }
208
209 // Number of sub-ranges in a range.
210
211 inline unsigned
212 irange::num_pairs () const
213 {
214 if (m_kind == VR_ANTI_RANGE)
215 return constant_p () ? 2 : 1;
216 else
217 return m_num_ranges;
218 }
219
220 inline tree
221 irange::type () const
222 {
223 gcc_checking_assert (m_num_ranges > 0);
224 return TREE_TYPE (m_base[0]);
225 }
226
227 // Return the lower bound of a sub-range expressed as a tree. PAIR is
228 // the sub-range in question.
229
230 inline tree
231 irange::tree_lower_bound (unsigned pair) const
232 {
233 return m_base[pair * 2];
234 }
235
236 // Return the upper bound of a sub-range expressed as a tree. PAIR is
237 // the sub-range in question.
238
239 inline tree
240 irange::tree_upper_bound (unsigned pair) const
241 {
242 return m_base[pair * 2 + 1];
243 }
244
245 // Return the highest bound of a range expressed as a tree.
246
247 inline tree
248 irange::tree_upper_bound () const
249 {
250 gcc_checking_assert (m_num_ranges);
251 return tree_upper_bound (m_num_ranges - 1);
252 }
253
254 inline tree
255 irange::min () const
256 {
257 return tree_lower_bound (0);
258 }
259
260 inline tree
261 irange::max () const
262 {
263 if (m_num_ranges)
264 return tree_upper_bound ();
265 else
266 return NULL;
267 }
268
269 inline bool
270 irange::varying_compatible_p () const
271 {
272 if (m_num_ranges != 1)
273 return false;
274
275 tree l = m_base[0];
276 tree u = m_base[1];
277 tree t = TREE_TYPE (l);
278
279 if (m_kind == VR_VARYING && t == error_mark_node)
280 return true;
281
282 unsigned prec = TYPE_PRECISION (t);
283 signop sign = TYPE_SIGN (t);
284 if (INTEGRAL_TYPE_P (t))
285 return (wi::to_wide (l) == wi::min_value (prec, sign)
286 && wi::to_wide (u) == wi::max_value (prec, sign));
287 if (POINTER_TYPE_P (t))
288 return (wi::to_wide (l) == 0
289 && wi::to_wide (u) == wi::max_value (prec, sign));
290 return true;
291 }
292
293 inline bool
294 irange::varying_p () const
295 {
296 return m_kind == VR_VARYING;
297 }
298
299 inline bool
300 irange::undefined_p () const
301 {
302 return m_kind == VR_UNDEFINED;
303 }
304
305 inline bool
306 irange::zero_p () const
307 {
308 return (m_kind == VR_RANGE && m_num_ranges == 1
309 && integer_zerop (tree_lower_bound (0))
310 && integer_zerop (tree_upper_bound (0)));
311 }
312
313 inline bool
314 irange::nonzero_p () const
315 {
316 if (undefined_p ())
317 return false;
318
319 tree zero = build_zero_cst (type ());
320 return *this == int_range<1> (zero, zero, VR_ANTI_RANGE);
321 }
322
323 inline bool
324 irange::supports_type_p (tree type)
325 {
326 if (type && (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)))
327 return type;
328 return false;
329 }
330
331 inline bool
332 range_includes_zero_p (const irange *vr)
333 {
334 if (vr->undefined_p ())
335 return false;
336
337 if (vr->varying_p ())
338 return true;
339
340 return vr->may_contain_p (build_zero_cst (vr->type ()));
341 }
342
343 inline void
344 gt_ggc_mx (irange *x)
345 {
346 for (unsigned i = 0; i < x->m_num_ranges; ++i)
347 {
348 gt_ggc_mx (x->m_base[i * 2]);
349 gt_ggc_mx (x->m_base[i * 2 + 1]);
350 }
351 }
352
353 inline void
354 gt_pch_nx (irange *x)
355 {
356 for (unsigned i = 0; i < x->m_num_ranges; ++i)
357 {
358 gt_pch_nx (x->m_base[i * 2]);
359 gt_pch_nx (x->m_base[i * 2 + 1]);
360 }
361 }
362
363 inline void
364 gt_pch_nx (irange *x, gt_pointer_operator op, void *cookie)
365 {
366 for (unsigned i = 0; i < x->m_num_ranges; ++i)
367 {
368 op (&x->m_base[i * 2], cookie);
369 op (&x->m_base[i * 2 + 1], cookie);
370 }
371 }
372
373 template<unsigned N>
374 inline void
375 gt_ggc_mx (int_range<N> *x)
376 {
377 gt_ggc_mx ((irange *) x);
378 }
379
380 template<unsigned N>
381 inline void
382 gt_pch_nx (int_range<N> *x)
383 {
384 gt_pch_nx ((irange *) x);
385 }
386
387 template<unsigned N>
388 inline void
389 gt_pch_nx (int_range<N> *x, gt_pointer_operator op, void *cookie)
390 {
391 gt_pch_nx ((irange *) x, op, cookie);
392 }
393
394 // Constructors for irange
395
396 inline
397 irange::irange (tree *base, unsigned nranges)
398 {
399 m_base = base;
400 m_num_ranges = 0;
401 m_max_ranges = nranges;
402 m_kind = VR_UNDEFINED;
403 }
404
405 // Constructors for int_range<>.
406
407 template<unsigned N>
408 inline
409 int_range<N>::int_range ()
410 : irange (m_ranges, N)
411 {
412 }
413
414 template<unsigned N>
415 int_range<N>::int_range (const int_range &other)
416 : irange (m_ranges, N)
417 {
418 irange::operator= (other);
419 }
420
421 template<unsigned N>
422 int_range<N>::int_range (tree min, tree max, value_range_kind kind)
423 : irange (m_ranges, N)
424 {
425 irange::set (min, max, kind);
426 }
427
428 template<unsigned N>
429 int_range<N>::int_range (tree type)
430 : irange (m_ranges, N)
431 {
432 set_varying (type);
433 }
434
435 template<unsigned N>
436 int_range<N>::int_range (tree type, const wide_int &wmin, const wide_int &wmax,
437 value_range_kind kind)
438 : irange (m_ranges, N)
439 {
440 tree min = wide_int_to_tree (type, wmin);
441 tree max = wide_int_to_tree (type, wmax);
442 set (min, max, kind);
443 }
444
445 template<unsigned N>
446 int_range<N>::int_range (const irange &other)
447 : irange (m_ranges, N)
448 {
449 irange::operator= (other);
450 }
451
452 template<unsigned N>
453 int_range<N>&
454 int_range<N>::operator= (const int_range &src)
455 {
456 irange::operator= (src);
457 return *this;
458 }
459
460 inline void
461 irange::set (tree val)
462 {
463 set (val, val);
464 }
465
466 inline void
467 irange::set_undefined ()
468 {
469 m_kind = VR_UNDEFINED;
470 m_num_ranges = 0;
471 }
472
473 inline void
474 irange::set_varying (tree type)
475 {
476 m_kind = VR_VARYING;
477 m_num_ranges = 1;
478
479 if (INTEGRAL_TYPE_P (type))
480 {
481 // Strict enum's require varying to be not TYPE_MIN/MAX, but rather
482 // min_value and max_value.
483 wide_int min = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
484 wide_int max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
485 if (wi::eq_p (max, wi::to_wide (TYPE_MAX_VALUE (type)))
486 && wi::eq_p (min, wi::to_wide (TYPE_MIN_VALUE (type))))
487 {
488 m_base[0] = TYPE_MIN_VALUE (type);
489 m_base[1] = TYPE_MAX_VALUE (type);
490 }
491 else
492 {
493 m_base[0] = wide_int_to_tree (type, min);
494 m_base[1] = wide_int_to_tree (type, max);
495 }
496 }
497 else if (POINTER_TYPE_P (type))
498 {
499 m_base[0] = build_int_cst (type, 0);
500 m_base[1] = build_int_cst (type, -1);
501 }
502 else
503 m_base[0] = m_base[1] = error_mark_node;
504 }
505
506 inline bool
507 irange::operator== (const irange &r) const
508 {
509 return equal_p (r);
510 }
511
512 // Return the lower bound of a sub-range. PAIR is the sub-range in
513 // question.
514
515 inline wide_int
516 irange::lower_bound (unsigned pair) const
517 {
518 if (legacy_mode_p ())
519 return legacy_lower_bound (pair);
520 gcc_checking_assert (m_num_ranges > 0);
521 gcc_checking_assert (pair + 1 <= num_pairs ());
522 return wi::to_wide (tree_lower_bound (pair));
523 }
524
525 // Return the upper bound of a sub-range. PAIR is the sub-range in
526 // question.
527
528 inline wide_int
529 irange::upper_bound (unsigned pair) const
530 {
531 if (legacy_mode_p ())
532 return legacy_upper_bound (pair);
533 gcc_checking_assert (m_num_ranges > 0);
534 gcc_checking_assert (pair + 1 <= num_pairs ());
535 return wi::to_wide (tree_upper_bound (pair));
536 }
537
538 // Return the highest bound of a range.
539
540 inline wide_int
541 irange::upper_bound () const
542 {
543 unsigned pairs = num_pairs ();
544 gcc_checking_assert (pairs > 0);
545 return upper_bound (pairs - 1);
546 }
547
548 inline void
549 irange::union_ (const irange &r)
550 {
551 dump_flags_t m_flags = dump_flags;
552 dump_flags &= ~TDF_DETAILS;
553 irange::union_ (&r);
554 dump_flags = m_flags;
555 }
556
557 inline void
558 irange::intersect (const irange &r)
559 {
560 dump_flags_t m_flags = dump_flags;
561 dump_flags &= ~TDF_DETAILS;
562 irange::intersect (&r);
563 dump_flags = m_flags;
564 }
565
566 // Set value range VR to a nonzero range of type TYPE.
567
568 inline void
569 irange::set_nonzero (tree type)
570 {
571 tree zero = build_int_cst (type, 0);
572 if (legacy_mode_p ())
573 set (zero, zero, VR_ANTI_RANGE);
574 else
575 irange_set_anti_range (zero, zero);
576 }
577
578 // Set value range VR to a ZERO range of type TYPE.
579
580 inline void
581 irange::set_zero (tree type)
582 {
583 tree z = build_int_cst (type, 0);
584 if (legacy_mode_p ())
585 set (z);
586 else
587 irange_set (z, z);
588 }
589
590 // Normalize a range to VARYING or UNDEFINED if possible.
591
592 inline void
593 irange::normalize_kind ()
594 {
595 if (m_num_ranges == 0)
596 m_kind = VR_UNDEFINED;
597 else if (varying_compatible_p ())
598 {
599 if (m_kind == VR_RANGE)
600 m_kind = VR_VARYING;
601 else if (m_kind == VR_ANTI_RANGE)
602 set_undefined ();
603 else
604 gcc_unreachable ();
605 }
606 }
607
608 // Return the maximum value for TYPE.
609
610 inline tree
611 vrp_val_max (const_tree type)
612 {
613 if (INTEGRAL_TYPE_P (type))
614 return TYPE_MAX_VALUE (type);
615 if (POINTER_TYPE_P (type))
616 {
617 wide_int max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
618 return wide_int_to_tree (const_cast<tree> (type), max);
619 }
620 return NULL_TREE;
621 }
622
623 // Return the minimum value for TYPE.
624
625 inline tree
626 vrp_val_min (const_tree type)
627 {
628 if (INTEGRAL_TYPE_P (type))
629 return TYPE_MIN_VALUE (type);
630 if (POINTER_TYPE_P (type))
631 return build_zero_cst (const_cast<tree> (type));
632 return NULL_TREE;
633 }
634
635 // This is the irange storage class. It is used to allocate the
636 // minimum amount of storage needed for a given irange. Storage is
637 // automatically freed at destruction of the storage class.
638 //
639 // It is meant for long term storage, as opposed to int_range_max
640 // which is meant for intermediate temporary results on the stack.
641 //
642 // The newly allocated irange is initialized to the empty set
643 // (undefined_p() is true).
644
645 class irange_allocator
646 {
647 public:
648 irange_allocator ();
649 ~irange_allocator ();
650 // Return a new range with NUM_PAIRS.
651 irange *allocate (unsigned num_pairs);
652 // Return a copy of SRC with the minimum amount of sub-ranges needed
653 // to represent it.
654 irange *allocate (const irange &src);
655 void *get_memory (unsigned num_bytes);
656 private:
657 DISABLE_COPY_AND_ASSIGN (irange_allocator);
658 struct obstack m_obstack;
659 };
660
661 inline
662 irange_allocator::irange_allocator ()
663 {
664 obstack_init (&m_obstack);
665 }
666
667 inline
668 irange_allocator::~irange_allocator ()
669 {
670 obstack_free (&m_obstack, NULL);
671 }
672
673 // Provide a hunk of memory from the obstack.
674 inline void *
675 irange_allocator::get_memory (unsigned num_bytes)
676 {
677 void *r = obstack_alloc (&m_obstack, num_bytes);
678 return r;
679 }
680
681 // Return a new range with NUM_PAIRS.
682
683 inline irange *
684 irange_allocator::allocate (unsigned num_pairs)
685 {
686 // Never allocate 0 pairs.
687 // Don't allocate 1 either, or we get legacy value_range's.
688 if (num_pairs < 2)
689 num_pairs = 2;
690
691 size_t nbytes = sizeof (tree) * 2 * num_pairs;
692
693 // Allocate the irange and required memory for the vector.
694 void *r = obstack_alloc (&m_obstack, sizeof (irange));
695 tree *mem = (tree *) obstack_alloc (&m_obstack, nbytes);
696 return new (r) irange (mem, num_pairs);
697 }
698
699 inline irange *
700 irange_allocator::allocate (const irange &src)
701 {
702 irange *r = allocate (src.num_pairs ());
703 *r = src;
704 return r;
705 }
706
707 #endif // GCC_VALUE_RANGE_H