Line data Source code
1 : /* Support routines for vrange storage.
2 : Copyright (C) 2022-2026 Free Software Foundation, Inc.
3 : Contributed by Aldy Hernandez <aldyh@redhat.com>.
4 :
5 : This file is part of GCC.
6 :
7 : GCC is free software; you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3, or (at your option)
10 : any later version.
11 :
12 : GCC is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with GCC; see the file COPYING3. If not see
19 : <http://www.gnu.org/licenses/>. */
20 :
21 : #include "config.h"
22 : #include "system.h"
23 : #include "coretypes.h"
24 : #include "backend.h"
25 : #include "tree.h"
26 : #include "gimple.h"
27 : #include "ssa.h"
28 : #include "tree-pretty-print.h"
29 : #include "fold-const.h"
30 : #include "gimple-range.h"
31 : #include "value-range-storage.h"
32 :
33 : // Generic memory allocator to share one interface between GC and
34 : // obstack allocators.
35 :
36 : class vrange_internal_alloc
37 : {
38 : public:
39 111376055 : vrange_internal_alloc () { }
40 111376043 : virtual ~vrange_internal_alloc () { }
41 : virtual void *alloc (size_t size) = 0;
42 : virtual void free (void *) = 0;
43 : private:
44 : DISABLE_COPY_AND_ASSIGN (vrange_internal_alloc);
45 : };
46 :
47 : class vrange_obstack_alloc final: public vrange_internal_alloc
48 : {
49 : public:
50 111089139 : vrange_obstack_alloc ()
51 111089139 : {
52 111089139 : obstack_init (&m_obstack);
53 111089139 : }
54 111089127 : virtual ~vrange_obstack_alloc () final override
55 111089127 : {
56 111089127 : obstack_free (&m_obstack, NULL);
57 111089127 : }
58 379147250 : virtual void *alloc (size_t size) final override
59 : {
60 379147250 : return obstack_alloc (&m_obstack, size);
61 : }
62 0 : virtual void free (void *) final override { }
63 : private:
64 : obstack m_obstack;
65 : };
66 :
67 : class vrange_ggc_alloc final: public vrange_internal_alloc
68 : {
69 : public:
70 286916 : vrange_ggc_alloc () { }
71 286916 : virtual ~vrange_ggc_alloc () final override { }
72 17824140 : virtual void *alloc (size_t size) final override
73 : {
74 17824140 : return ggc_internal_alloc (size);
75 : }
76 0 : virtual void free (void *p) final override
77 : {
78 0 : return ggc_free (p);
79 : }
80 : };
81 :
82 111376055 : vrange_allocator::vrange_allocator (bool gc)
83 : {
84 111376055 : if (gc)
85 286916 : m_alloc = new vrange_ggc_alloc;
86 : else
87 111089139 : m_alloc = new vrange_obstack_alloc;
88 111376055 : }
89 :
90 111376043 : vrange_allocator::~vrange_allocator ()
91 : {
92 111376043 : delete m_alloc;
93 111376043 : }
94 :
95 : void *
96 54959460 : vrange_allocator::alloc (size_t size)
97 : {
98 54959460 : return m_alloc->alloc (size);
99 : }
100 :
101 : void
102 0 : vrange_allocator::free (void *p)
103 : {
104 0 : m_alloc->free (p);
105 0 : }
106 :
107 : // Allocate a new vrange_storage object initialized to R and return
108 : // it.
109 :
110 : vrange_storage *
111 287062613 : vrange_allocator::clone (const vrange &r)
112 : {
113 287062613 : return vrange_storage::alloc (*m_alloc, r);
114 : }
115 :
116 : vrange_storage *
117 27516934 : vrange_allocator::clone_varying (tree type)
118 : {
119 27516934 : if (irange::supports_p (type))
120 17553883 : return irange_storage::alloc (*m_alloc, int_range <1> (type));
121 9963051 : if (prange::supports_p (type))
122 9507593 : return prange_storage::alloc (*m_alloc, prange (type));
123 455458 : if (frange::supports_p (type))
124 455458 : return frange_storage::alloc (*m_alloc, frange (type));
125 : return NULL;
126 : }
127 :
128 : vrange_storage *
129 27432383 : vrange_allocator::clone_undefined (tree type)
130 : {
131 27432383 : if (irange::supports_p (type))
132 17474684 : return irange_storage::alloc (*m_alloc, int_range<1> ());
133 9957699 : if (prange::supports_p (type))
134 9506405 : return prange_storage::alloc (*m_alloc, prange ());
135 451294 : if (frange::supports_p (type))
136 451294 : return frange_storage::alloc (*m_alloc, frange ());
137 : return NULL;
138 : }
139 :
140 : // Allocate a new vrange_storage object initialized to R and return
141 : // it. Return NULL if R is unsupported.
142 :
143 : vrange_storage *
144 287062613 : vrange_storage::alloc (vrange_internal_alloc &allocator, const vrange &r)
145 : {
146 287062613 : if (is_a <irange> (r))
147 202408725 : return irange_storage::alloc (allocator, as_a <irange> (r));
148 84653888 : if (is_a <prange> (r))
149 73398631 : return prange_storage::alloc (allocator, as_a <prange> (r));
150 11255257 : if (is_a <frange> (r))
151 11255257 : return frange_storage::alloc (allocator, as_a <frange> (r));
152 : return NULL;
153 : }
154 :
155 : // Set storage to R.
156 :
157 : void
158 24891329 : vrange_storage::set_vrange (const vrange &r)
159 : {
160 24891329 : if (is_a <irange> (r))
161 : {
162 21157218 : irange_storage *s = static_cast <irange_storage *> (this);
163 21157218 : gcc_checking_assert (s->fits_p (as_a <irange> (r)));
164 21157218 : s->set_irange (as_a <irange> (r));
165 : }
166 3734111 : else if (is_a <prange> (r))
167 : {
168 3115758 : prange_storage *s = static_cast <prange_storage *> (this);
169 3115758 : gcc_checking_assert (s->fits_p (as_a <prange> (r)));
170 3115758 : s->set_prange (as_a <prange> (r));
171 : }
172 618353 : else if (is_a <frange> (r))
173 : {
174 618353 : frange_storage *s = static_cast <frange_storage *> (this);
175 618353 : gcc_checking_assert (s->fits_p (as_a <frange> (r)));
176 618353 : s->set_frange (as_a <frange> (r));
177 : }
178 : else
179 0 : gcc_unreachable ();
180 :
181 : // Verify that reading back from the cache didn't drop bits.
182 24891329 : if (flag_checking
183 : // FIXME: Avoid checking frange, as it currently pessimizes some ranges:
184 : //
185 : // gfortran.dg/pr49472.f90 pessimizes [0.0, 1.0] into [-0.0, 1.0].
186 24891256 : && !is_a <frange> (r)
187 49164232 : && !r.undefined_p ())
188 : {
189 24154886 : value_range tmp (r);
190 24154886 : get_vrange (tmp, r.type ());
191 24154886 : gcc_checking_assert (tmp == r);
192 24154886 : }
193 24891329 : }
194 :
195 : // Restore R from storage.
196 :
197 : void
198 1674734334 : vrange_storage::get_vrange (vrange &r, tree type) const
199 : {
200 1674734334 : if (is_a <irange> (r))
201 : {
202 1291161720 : const irange_storage *s = static_cast <const irange_storage *> (this);
203 1291161720 : s->get_irange (as_a <irange> (r), type);
204 : }
205 383572614 : else if (is_a <prange> (r))
206 : {
207 337979880 : const prange_storage *s = static_cast <const prange_storage *> (this);
208 337979880 : s->get_prange (as_a <prange> (r), type);
209 : }
210 45592734 : else if (is_a <frange> (r))
211 : {
212 45592734 : const frange_storage *s = static_cast <const frange_storage *> (this);
213 45592734 : s->get_frange (as_a <frange> (r), type);
214 : }
215 : else
216 0 : gcc_unreachable ();
217 1674734334 : }
218 :
219 : // Return TRUE if storage can fit R.
220 :
221 : bool
222 28897841 : vrange_storage::fits_p (const vrange &r) const
223 : {
224 28897841 : if (is_a <irange> (r))
225 : {
226 25174485 : const irange_storage *s = static_cast <const irange_storage *> (this);
227 25174485 : return s->fits_p (as_a <irange> (r));
228 : }
229 3723356 : if (is_a <prange> (r))
230 : {
231 3105422 : const prange_storage *s = static_cast <const prange_storage *> (this);
232 3105422 : return s->fits_p (as_a <prange> (r));
233 : }
234 617934 : if (is_a <frange> (r))
235 : {
236 617934 : const frange_storage *s = static_cast <const frange_storage *> (this);
237 617934 : return s->fits_p (as_a <frange> (r));
238 : }
239 0 : gcc_unreachable ();
240 : return false;
241 : }
242 :
243 : // Return TRUE if the range in storage is equal to R. It is the
244 : // caller's responsibility to verify that the type of the range in
245 : // storage matches that of R.
246 :
247 : bool
248 9630754 : vrange_storage::equal_p (const vrange &r) const
249 : {
250 9630754 : if (is_a <irange> (r))
251 : {
252 4580012 : const irange_storage *s = static_cast <const irange_storage *> (this);
253 4580012 : return s->equal_p (as_a <irange> (r));
254 : }
255 5050742 : if (is_a <prange> (r))
256 : {
257 5031584 : const prange_storage *s = static_cast <const prange_storage *> (this);
258 5031584 : return s->equal_p (as_a <prange> (r));
259 : }
260 19158 : if (is_a <frange> (r))
261 : {
262 19158 : const frange_storage *s = static_cast <const frange_storage *> (this);
263 19158 : return s->equal_p (as_a <frange> (r));
264 : }
265 0 : gcc_unreachable ();
266 : }
267 :
268 : //============================================================================
269 : // irange_storage implementation
270 : //============================================================================
271 :
272 : unsigned short *
273 1033948827 : irange_storage::write_lengths_address ()
274 : {
275 1033948827 : return (unsigned short *)&m_val[(m_num_ranges * 2 + 2)
276 1033948827 : * WIDE_INT_MAX_HWIS (m_precision)];
277 : }
278 :
279 : const unsigned short *
280 901254218 : irange_storage::lengths_address () const
281 : {
282 901254218 : return const_cast <irange_storage *> (this)->write_lengths_address ();
283 : }
284 :
285 : // Allocate a new irange_storage object initialized to R.
286 :
287 : irange_storage *
288 237437292 : irange_storage::alloc (vrange_internal_alloc &allocator, const irange &r)
289 : {
290 237437292 : size_t size = irange_storage::size (r);
291 237437292 : irange_storage *p = static_cast <irange_storage *> (allocator.alloc (size));
292 237437292 : new (p) irange_storage (r);
293 237437292 : return p;
294 : }
295 :
296 : // Initialize the storage with R.
297 :
298 237437292 : irange_storage::irange_storage (const irange &r)
299 237437292 : : m_max_ranges (r.num_pairs ())
300 : {
301 237437292 : m_num_ranges = m_max_ranges;
302 237437292 : set_irange (r);
303 237437292 : }
304 :
305 : static inline void
306 636551030 : write_wide_int (HOST_WIDE_INT *&val, unsigned short *&len, const wide_int &w)
307 : {
308 636551030 : *len = w.get_len ();
309 1273965809 : for (unsigned i = 0; i < *len; ++i)
310 637414779 : *val++ = w.elt (i);
311 636551030 : ++len;
312 636551030 : }
313 :
314 : // Store R into the current storage.
315 :
316 : void
317 258594510 : irange_storage::set_irange (const irange &r)
318 : {
319 258594510 : gcc_checking_assert (fits_p (r));
320 :
321 258594510 : if (r.undefined_p ())
322 : {
323 17850977 : m_kind = VR_UNDEFINED;
324 125899901 : return;
325 : }
326 240743533 : if (r.varying_p ())
327 : {
328 108048924 : m_kind = VR_VARYING;
329 108048924 : return;
330 : }
331 :
332 132694609 : m_precision = TYPE_PRECISION (r.type ());
333 132694609 : m_num_ranges = r.num_pairs ();
334 132694609 : m_kind = VR_RANGE;
335 :
336 132694609 : HOST_WIDE_INT *val = &m_val[0];
337 132694609 : unsigned short *len = write_lengths_address ();
338 :
339 318275515 : for (unsigned i = 0; i < r.num_pairs (); ++i)
340 : {
341 185580906 : write_wide_int (val, len, r.lower_bound (i));
342 185583321 : write_wide_int (val, len, r.upper_bound (i));
343 : }
344 :
345 : // TODO: We could avoid streaming out the value if the mask is -1.
346 132694609 : irange_bitmask bm = r.m_bitmask;
347 132694609 : write_wide_int (val, len, bm.value ());
348 132694609 : write_wide_int (val, len, bm.mask ());
349 132694609 : }
350 :
351 : static inline void
352 4344527804 : read_wide_int (wide_int &w,
353 : const HOST_WIDE_INT *val, unsigned short len, unsigned prec)
354 : {
355 4344527804 : trailing_wide_int_storage stow (prec, &len,
356 1082721284 : const_cast <HOST_WIDE_INT *> (val));
357 3261806520 : w = trailing_wide_int (stow);
358 : }
359 :
360 : // Restore a range of TYPE from storage into R.
361 :
362 : void
363 1295328765 : irange_storage::get_irange (irange &r, tree type) const
364 : {
365 1295328765 : if (m_kind == VR_UNDEFINED)
366 : {
367 10390254 : r.set_undefined ();
368 404464801 : return;
369 : }
370 1284938511 : if (m_kind == VR_VARYING)
371 : {
372 383684293 : r.set_varying (type);
373 383684293 : return;
374 : }
375 :
376 901254218 : gcc_checking_assert (TYPE_PRECISION (type) == m_precision);
377 901254218 : const HOST_WIDE_INT *val = &m_val[0];
378 901254218 : const unsigned short *len = lengths_address ();
379 :
380 : // Handle the common case where R can fit the new range.
381 901254218 : if (r.m_max_ranges >= m_num_ranges)
382 : {
383 870046980 : r.m_kind = VR_RANGE;
384 870046980 : r.m_num_ranges = m_num_ranges;
385 870046980 : r.m_type = type;
386 3049132216 : for (unsigned i = 0; i < m_num_ranges * 2; ++i)
387 : {
388 2179085236 : read_wide_int (r.m_base[i], val, *len, m_precision);
389 2179085236 : val += *len++;
390 : }
391 : }
392 : // Otherwise build the range piecewise.
393 : else
394 : {
395 31207238 : r.set_undefined ();
396 212674304 : for (unsigned i = 0; i < m_num_ranges; ++i)
397 : {
398 181467066 : wide_int lb, ub;
399 181467066 : read_wide_int (lb, val, *len, m_precision);
400 181467066 : val += *len++;
401 181467066 : read_wide_int (ub, val, *len, m_precision);
402 181467066 : val += *len++;
403 181467066 : int_range<1> tmp (type, lb, ub);
404 181467066 : r.union_ (tmp);
405 181467066 : }
406 : }
407 :
408 901254218 : wide_int bits_value, bits_mask;
409 901254218 : read_wide_int (bits_value, val, *len, m_precision);
410 901254218 : val += *len++;
411 901254218 : read_wide_int (bits_mask, val, *len, m_precision);
412 901254218 : r.m_bitmask = irange_bitmask (bits_value, bits_mask);
413 901254218 : if (r.m_kind == VR_VARYING)
414 0 : r.m_kind = VR_RANGE;
415 :
416 901254218 : if (flag_checking)
417 901250685 : r.verify_range ();
418 901261232 : }
419 :
420 : bool
421 4580012 : irange_storage::equal_p (const irange &r) const
422 : {
423 4580012 : if (m_kind == VR_UNDEFINED || r.undefined_p ())
424 0 : return m_kind == r.m_kind;
425 4580012 : if (m_kind == VR_VARYING || r.varying_p ())
426 412967 : return m_kind == r.m_kind;
427 :
428 : // ?? We could make this faster by doing the comparison in place,
429 : // without going through get_irange.
430 4167045 : int_range_max tmp;
431 4167045 : get_irange (tmp, r.type ());
432 4167045 : return tmp == r;
433 4167045 : }
434 :
435 : // Return the size in bytes to allocate storage that can hold R.
436 :
437 : size_t
438 237437292 : irange_storage::size (const irange &r)
439 : {
440 237437292 : if (r.undefined_p ())
441 : return sizeof (irange_storage);
442 :
443 219698573 : unsigned prec = TYPE_PRECISION (r.type ());
444 219698573 : unsigned n = r.num_pairs () * 2 + 2;
445 219698573 : unsigned hwi_size = ((n * WIDE_INT_MAX_HWIS (prec) - 1)
446 : * sizeof (HOST_WIDE_INT));
447 219698573 : unsigned len_size = n * sizeof (unsigned short);
448 219698573 : return sizeof (irange_storage) + hwi_size + len_size;
449 : }
450 :
451 : // Return TRUE if R fits in the current storage.
452 :
453 : bool
454 304926213 : irange_storage::fits_p (const irange &r) const
455 : {
456 304926213 : return m_max_ranges >= r.num_pairs ();
457 : }
458 :
459 : void
460 0 : irange_storage::dump () const
461 : {
462 0 : fprintf (stderr, "irange_storage (prec=%d, ranges=%d):\n",
463 0 : m_precision, m_num_ranges);
464 :
465 0 : if (m_num_ranges == 0)
466 : return;
467 :
468 0 : const HOST_WIDE_INT *val = &m_val[0];
469 0 : const unsigned short *len = lengths_address ();
470 0 : int i, j;
471 :
472 0 : fprintf (stderr, " lengths = [ ");
473 0 : for (i = 0; i < m_num_ranges * 2 + 2; ++i)
474 0 : fprintf (stderr, "%d ", len[i]);
475 0 : fprintf (stderr, "]\n");
476 :
477 0 : for (i = 0; i < m_num_ranges; ++i)
478 : {
479 0 : for (j = 0; j < *len; ++j)
480 0 : fprintf (stderr, " [PAIR %d] LB " HOST_WIDE_INT_PRINT_DEC "\n", i,
481 0 : *val++);
482 0 : ++len;
483 0 : for (j = 0; j < *len; ++j)
484 0 : fprintf (stderr, " [PAIR %d] UB " HOST_WIDE_INT_PRINT_DEC "\n", i,
485 0 : *val++);
486 0 : ++len;
487 : }
488 :
489 : // Dump value/mask pair.
490 0 : for (j = 0; j < *len; ++j)
491 0 : fprintf (stderr, " [VALUE] " HOST_WIDE_INT_PRINT_DEC "\n", *val++);
492 0 : ++len;
493 0 : for (j = 0; j < *len; ++j)
494 0 : fprintf (stderr, " [MASK] " HOST_WIDE_INT_PRINT_DEC "\n", *val++);
495 : }
496 :
497 : DEBUG_FUNCTION void
498 0 : debug (const irange_storage &storage)
499 : {
500 0 : storage.dump ();
501 0 : fprintf (stderr, "\n");
502 0 : }
503 :
504 : //============================================================================
505 : // frange_storage implementation
506 : //============================================================================
507 :
508 : // Allocate a new frange_storage object initialized to R.
509 :
510 : frange_storage *
511 12162009 : frange_storage::alloc (vrange_internal_alloc &allocator, const frange &r)
512 : {
513 12162009 : size_t size = sizeof (frange_storage);
514 12162009 : frange_storage *p = static_cast <frange_storage *> (allocator.alloc (size));
515 12162009 : new (p) frange_storage (r);
516 12162009 : return p;
517 : }
518 :
519 : void
520 12780362 : frange_storage::set_frange (const frange &r)
521 : {
522 12780362 : gcc_checking_assert (fits_p (r));
523 :
524 12780362 : m_kind = r.m_kind;
525 12780362 : m_min = r.m_min;
526 12780362 : m_max = r.m_max;
527 12780362 : m_pos_nan = r.m_pos_nan;
528 12780362 : m_neg_nan = r.m_neg_nan;
529 12780362 : }
530 :
531 : void
532 45611892 : frange_storage::get_frange (frange &r, tree type) const
533 : {
534 45611892 : gcc_checking_assert (r.supports_type_p (type));
535 :
536 : // Handle explicit NANs.
537 45611892 : if (m_kind == VR_NAN)
538 : {
539 105682 : if (HONOR_NANS (type))
540 : {
541 105682 : if (m_pos_nan && m_neg_nan)
542 100146 : r.set_nan (type);
543 : else
544 5536 : r.set_nan (type, m_neg_nan);
545 : }
546 : else
547 0 : r.set_undefined ();
548 105682 : return;
549 : }
550 45506210 : if (m_kind == VR_UNDEFINED)
551 : {
552 67529 : r.set_undefined ();
553 67529 : return;
554 : }
555 :
556 : // We use the constructor to create the new range instead of writing
557 : // out the bits into the frange directly, because the global range
558 : // being read may be being inlined into a function with different
559 : // restrictions as when it was originally written. We want to make
560 : // sure the resulting range is canonicalized correctly for the new
561 : // consumer.
562 45438681 : r = frange (type, m_min, m_max, m_kind);
563 :
564 : // The constructor will set the NAN bits for HONOR_NANS, but we must
565 : // make sure to set the NAN sign if known.
566 45438681 : if (HONOR_NANS (type) && (m_pos_nan ^ m_neg_nan) == 1)
567 1251886 : r.update_nan (m_neg_nan);
568 44186795 : else if (!m_pos_nan && !m_neg_nan)
569 11837105 : r.clear_nan ();
570 : }
571 :
572 : bool
573 19158 : frange_storage::equal_p (const frange &r) const
574 : {
575 19158 : if (r.undefined_p ())
576 0 : return m_kind == VR_UNDEFINED;
577 :
578 19158 : frange tmp;
579 19158 : get_frange (tmp, r.type ());
580 19158 : return tmp == r;
581 19158 : }
582 :
583 : bool
584 14016649 : frange_storage::fits_p (const frange &) const
585 : {
586 14016649 : return true;
587 : }
588 :
589 : //============================================================================
590 : // prange_storage implementation
591 : //============================================================================
592 :
593 : prange_storage *
594 92412629 : prange_storage::alloc (vrange_internal_alloc &allocator, const prange &r)
595 : {
596 92412629 : prange_format format (r);
597 92412629 : size_t size = sizeof (prange_storage) + format.extra_size;
598 92412629 : prange_storage *p = static_cast <prange_storage *> (allocator.alloc (size));
599 92412629 : new (p) prange_storage (r);
600 92412629 : return p;
601 : }
602 :
603 : // Initialize the storage with R.
604 :
605 92412629 : prange_storage::prange_storage (const prange &r)
606 : {
607 92412629 : prange_format format (r);
608 92412629 : m_trailing_ints.set_precision (format.precision, format.num_words);
609 92412629 : set_prange (r);
610 92412629 : }
611 :
612 : // FIll the format structure for range R.
613 :
614 286563273 : prange_storage::prange_format::prange_format (const prange &r)
615 : {
616 286563273 : kind = PR_UNDEFINED;
617 286563273 : has_bitmask = 0;
618 286563273 : extra_size = 0;
619 286563273 : precision = 0;
620 286563273 : num_words = 0;
621 :
622 286563273 : if (r.undefined_p ())
623 : return;
624 :
625 257937668 : if (r.varying_p ())
626 : {
627 139308705 : kind = PR_VARYING;
628 139308705 : return;
629 : }
630 :
631 118628963 : if (r.zero_p ())
632 : {
633 710132 : kind = PR_ZERO;
634 710132 : return;
635 : }
636 :
637 117918831 : if (r.nonzero_p ())
638 115412168 : kind = PR_NONZERO;
639 : else
640 : {
641 2506663 : prange tmp (r.type ());
642 5013326 : if (r.lower_bound () == tmp.lower_bound ()
643 3588717 : && r.upper_bound () == tmp.upper_bound ())
644 65541 : kind = PR_FULL;
645 : else
646 : {
647 : // PR_OTHER requires words of storage for the end points.
648 2441122 : kind = PR_OTHER;
649 2441122 : num_words += 2;
650 : }
651 2506663 : }
652 117918831 : precision = TYPE_PRECISION (r.type ());
653 117918831 : has_bitmask = !r.get_bitmask ().unknown_p ();
654 :
655 : // Bitmasks require 2 words of storage.
656 117918831 : if (has_bitmask)
657 1439745 : num_words += 2;
658 :
659 117918831 : if (num_words != 0)
660 3457829 : extra_size = trailing_wide_ints<NINTS>::extra_size (precision, num_words);
661 :
662 : // PR_FULL must have a bitmask, or it should be PR_VARYING.
663 117918831 : gcc_checking_assert (kind != PR_FULL || has_bitmask);
664 : }
665 :
666 : void
667 95528387 : prange_storage::set_prange (const prange &r)
668 : {
669 95528387 : prange_format format (r);
670 95528387 : m_kind = format.kind;
671 95528387 : m_has_bitmask = format.has_bitmask;
672 95528387 : unsigned index = 0;
673 :
674 95528387 : switch (m_kind)
675 : {
676 56219910 : case PR_UNDEFINED:
677 56219910 : case PR_VARYING:
678 56219910 : case PR_ZERO:
679 56219910 : return;
680 : case PR_NONZERO:
681 : case PR_FULL:
682 : break;
683 755435 : case PR_OTHER:
684 755435 : set_word (index++, r.lower_bound (), r.type ());
685 755435 : set_word (index++, r.upper_bound (), r.type ());
686 755435 : break;
687 0 : default:
688 0 : gcc_unreachable ();
689 : }
690 :
691 39308477 : if (m_has_bitmask)
692 : {
693 488189 : irange_bitmask bm = r.m_bitmask;
694 488189 : set_word (index++, r.m_bitmask.value (), r.type ());
695 488189 : set_word (index++, r.m_bitmask.mask (), r.type ());
696 488189 : }
697 39308477 : gcc_checking_assert (index == format.num_words);
698 : }
699 :
700 : void
701 343011464 : prange_storage::get_prange (prange &r, tree type) const
702 : {
703 343011464 : gcc_checking_assert (r.supports_type_p (type));
704 343011464 : unsigned index = 0;
705 343011464 : switch (m_kind)
706 : {
707 963384 : case PR_UNDEFINED:
708 963384 : r.set_undefined ();
709 963384 : return;
710 :
711 193196797 : case PR_VARYING:
712 193196797 : r.set_varying (type);
713 193196797 : return;
714 :
715 1458709 : case PR_ZERO:
716 1458709 : r.set_zero (type);
717 1458709 : return;
718 :
719 144569487 : case PR_NONZERO:
720 144569487 : r.set_nonzero (type);
721 144569487 : break;
722 :
723 235960 : case PR_FULL:
724 235960 : {
725 235960 : r.m_kind = VR_RANGE;
726 235960 : r.m_type = type;
727 235960 : prange tmp (type);
728 235960 : r.m_min = tmp.lower_bound ();
729 235960 : r.m_max = tmp.upper_bound ();
730 235960 : break;
731 235960 : }
732 :
733 2587127 : case PR_OTHER:
734 2587127 : {
735 2587127 : gcc_checking_assert (m_kind == PR_OTHER);
736 2587127 : r.m_kind = VR_RANGE;
737 2587127 : r.m_type = type;
738 2587127 : r.m_min = get_word (index++, type);
739 2587127 : r.m_max = get_word (index++, type);
740 2587127 : break;
741 : }
742 0 : default:
743 0 : gcc_unreachable ();
744 : }
745 :
746 147392574 : if (m_has_bitmask)
747 : {
748 10876361 : wide_int value = get_word (index++, type);
749 10876361 : wide_int mask = get_word (index++, type);
750 10876361 : r.m_bitmask = irange_bitmask (value, mask);
751 10876361 : }
752 : else
753 136516213 : r.m_bitmask.set_unknown (TYPE_PRECISION (type));
754 :
755 147392574 : if (flag_checking)
756 147392436 : r.verify_range ();
757 : }
758 :
759 : bool
760 5031584 : prange_storage::equal_p (const prange &r) const
761 : {
762 5031584 : if (r.undefined_p ())
763 0 : return m_kind == PR_UNDEFINED;
764 :
765 5031584 : prange tmp;
766 5031584 : get_prange (tmp, r.type ());
767 5031584 : return tmp == r;
768 5031584 : }
769 :
770 : bool
771 6221180 : prange_storage::fits_p (const prange &r) const
772 : {
773 : // Undefined ranges always fit, because they don't store anything in
774 : // the trailing wide ints.
775 6221180 : if (r.undefined_p ())
776 : return true;
777 :
778 6209628 : prange_format f (r);
779 6209628 : unsigned prec = m_trailing_ints.get_precision ();
780 6209628 : unsigned num = m_trailing_ints.num_elements ();
781 6209628 : size_t curr = num ? trailing_wide_ints<NINTS>::extra_size (prec, num) : 0;
782 6209628 : return f.extra_size <= curr;
783 : }
784 :
785 :
786 : static vrange_allocator ggc_vrange_allocator (true);
787 :
788 0 : vrange_storage *ggc_alloc_vrange_storage (tree type)
789 : {
790 0 : return ggc_vrange_allocator.clone_varying (type);
791 : }
792 :
793 17824140 : vrange_storage *ggc_alloc_vrange_storage (const vrange &r)
794 : {
795 17824140 : return ggc_vrange_allocator.clone (r);
796 : }
|