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 112985595 : vrange_internal_alloc () { }
40 112985583 : 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 112701004 : vrange_obstack_alloc ()
51 112701004 : {
52 112701004 : obstack_init (&m_obstack);
53 112701004 : }
54 112700992 : virtual ~vrange_obstack_alloc () final override
55 112700992 : {
56 112700992 : obstack_free (&m_obstack, NULL);
57 112700992 : }
58 395213272 : virtual void *alloc (size_t size) final override
59 : {
60 395213272 : 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 284591 : vrange_ggc_alloc () { }
71 284591 : virtual ~vrange_ggc_alloc () final override { }
72 18093583 : virtual void *alloc (size_t size) final override
73 : {
74 18093583 : 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 112985595 : vrange_allocator::vrange_allocator (bool gc)
83 : {
84 112985595 : if (gc)
85 284591 : m_alloc = new vrange_ggc_alloc;
86 : else
87 112701004 : m_alloc = new vrange_obstack_alloc;
88 112985595 : }
89 :
90 112985583 : vrange_allocator::~vrange_allocator ()
91 : {
92 112985583 : delete m_alloc;
93 112985583 : }
94 :
95 : void *
96 56787068 : vrange_allocator::alloc (size_t size)
97 : {
98 56787068 : 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 299742848 : vrange_allocator::clone (const vrange &r)
112 : {
113 299742848 : return vrange_storage::alloc (*m_alloc, r);
114 : }
115 :
116 : vrange_storage *
117 28431593 : vrange_allocator::clone_varying (tree type)
118 : {
119 28431593 : if (irange::supports_p (type))
120 18197436 : return irange_storage::alloc (*m_alloc, int_range <1> (type));
121 10234157 : if (prange::supports_p (type))
122 9778184 : return prange_storage::alloc (*m_alloc, prange (type));
123 455973 : if (frange::supports_p (type))
124 455973 : return frange_storage::alloc (*m_alloc, frange (type));
125 : return NULL;
126 : }
127 :
128 : vrange_storage *
129 28345346 : vrange_allocator::clone_undefined (tree type)
130 : {
131 28345346 : if (irange::supports_p (type))
132 18116541 : return irange_storage::alloc (*m_alloc, int_range<1> ());
133 10228805 : if (prange::supports_p (type))
134 9776996 : return prange_storage::alloc (*m_alloc, prange ());
135 451809 : if (frange::supports_p (type))
136 451809 : 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 299742848 : vrange_storage::alloc (vrange_internal_alloc &allocator, const vrange &r)
145 : {
146 299742848 : if (is_a <irange> (r))
147 212774502 : return irange_storage::alloc (allocator, as_a <irange> (r));
148 86968346 : if (is_a <prange> (r))
149 75489006 : return prange_storage::alloc (allocator, as_a <prange> (r));
150 11479340 : if (is_a <frange> (r))
151 11479340 : return frange_storage::alloc (allocator, as_a <frange> (r));
152 : return NULL;
153 : }
154 :
155 : // Set storage to R.
156 :
157 : void
158 27527341 : vrange_storage::set_vrange (const vrange &r)
159 : {
160 27527341 : if (is_a <irange> (r))
161 : {
162 23227655 : irange_storage *s = static_cast <irange_storage *> (this);
163 23227655 : gcc_checking_assert (s->fits_p (as_a <irange> (r)));
164 23227655 : s->set_irange (as_a <irange> (r));
165 : }
166 4299686 : else if (is_a <prange> (r))
167 : {
168 3621602 : prange_storage *s = static_cast <prange_storage *> (this);
169 3621602 : gcc_checking_assert (s->fits_p (as_a <prange> (r)));
170 3621602 : s->set_prange (as_a <prange> (r));
171 : }
172 678084 : else if (is_a <frange> (r))
173 : {
174 678084 : frange_storage *s = static_cast <frange_storage *> (this);
175 678084 : gcc_checking_assert (s->fits_p (as_a <frange> (r)));
176 678084 : 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 27527341 : 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 27527251 : && !is_a <frange> (r)
187 54376508 : && !r.undefined_p ())
188 : {
189 26730971 : value_range tmp (r);
190 26730971 : get_vrange (tmp, r.type ());
191 26730971 : gcc_checking_assert (tmp == r);
192 26730971 : }
193 27527341 : }
194 :
195 : // Restore R from storage.
196 :
197 : void
198 1718843482 : vrange_storage::get_vrange (vrange &r, tree type) const
199 : {
200 1718843482 : if (is_a <irange> (r))
201 : {
202 1323277474 : const irange_storage *s = static_cast <const irange_storage *> (this);
203 1323277474 : s->get_irange (as_a <irange> (r), type);
204 : }
205 395566008 : else if (is_a <prange> (r))
206 : {
207 349276628 : const prange_storage *s = static_cast <const prange_storage *> (this);
208 349276628 : s->get_prange (as_a <prange> (r), type);
209 : }
210 46289380 : else if (is_a <frange> (r))
211 : {
212 46289380 : const frange_storage *s = static_cast <const frange_storage *> (this);
213 46289380 : s->get_frange (as_a <frange> (r), type);
214 : }
215 : else
216 0 : gcc_unreachable ();
217 1718843482 : }
218 :
219 : // Return TRUE if storage can fit R.
220 :
221 : bool
222 32221613 : vrange_storage::fits_p (const vrange &r) const
223 : {
224 32221613 : if (is_a <irange> (r))
225 : {
226 28117093 : const irange_storage *s = static_cast <const irange_storage *> (this);
227 28117093 : return s->fits_p (as_a <irange> (r));
228 : }
229 4104520 : if (is_a <prange> (r))
230 : {
231 3426855 : const prange_storage *s = static_cast <const prange_storage *> (this);
232 3426855 : return s->fits_p (as_a <prange> (r));
233 : }
234 677665 : if (is_a <frange> (r))
235 : {
236 677665 : const frange_storage *s = static_cast <const frange_storage *> (this);
237 677665 : 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 9609957 : vrange_storage::equal_p (const vrange &r) const
249 : {
250 9609957 : if (is_a <irange> (r))
251 : {
252 4546844 : const irange_storage *s = static_cast <const irange_storage *> (this);
253 4546844 : return s->equal_p (as_a <irange> (r));
254 : }
255 5063113 : if (is_a <prange> (r))
256 : {
257 5044000 : const prange_storage *s = static_cast <const prange_storage *> (this);
258 5044000 : return s->equal_p (as_a <prange> (r));
259 : }
260 19113 : if (is_a <frange> (r))
261 : {
262 19113 : const frange_storage *s = static_cast <const frange_storage *> (this);
263 19113 : 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 1057555291 : irange_storage::write_lengths_address ()
274 : {
275 1057555291 : return (unsigned short *)&m_val[(m_num_ranges * 2 + 2)
276 1057555291 : * WIDE_INT_MAX_HWIS (m_precision)];
277 : }
278 :
279 : const unsigned short *
280 917516384 : irange_storage::lengths_address () const
281 : {
282 917516384 : 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 249088479 : irange_storage::alloc (vrange_internal_alloc &allocator, const irange &r)
289 : {
290 249088479 : size_t size = irange_storage::size (r);
291 249088479 : irange_storage *p = static_cast <irange_storage *> (allocator.alloc (size));
292 249088479 : new (p) irange_storage (r);
293 249088479 : return p;
294 : }
295 :
296 : // Initialize the storage with R.
297 :
298 249088479 : irange_storage::irange_storage (const irange &r)
299 249088479 : : m_max_ranges (r.num_pairs ())
300 : {
301 249088479 : m_num_ranges = m_max_ranges;
302 249088479 : set_irange (r);
303 249088479 : }
304 :
305 : static inline void
306 675086512 : write_wide_int (HOST_WIDE_INT *&val, unsigned short *&len, const wide_int &w)
307 : {
308 675086512 : *len = w.get_len ();
309 1351232193 : for (unsigned i = 0; i < *len; ++i)
310 676145681 : *val++ = w.elt (i);
311 675086512 : ++len;
312 675086512 : }
313 :
314 : // Store R into the current storage.
315 :
316 : void
317 272316134 : irange_storage::set_irange (const irange &r)
318 : {
319 272316134 : gcc_checking_assert (fits_p (r));
320 :
321 272316134 : if (r.undefined_p ())
322 : {
323 18493748 : m_kind = VR_UNDEFINED;
324 132277227 : return;
325 : }
326 253822386 : if (r.varying_p ())
327 : {
328 113783479 : m_kind = VR_VARYING;
329 113783479 : return;
330 : }
331 :
332 140038907 : m_precision = TYPE_PRECISION (r.type ());
333 140038907 : m_num_ranges = r.num_pairs ();
334 140038907 : m_kind = VR_RANGE;
335 :
336 140038907 : HOST_WIDE_INT *val = &m_val[0];
337 140038907 : unsigned short *len = write_lengths_address ();
338 :
339 337543256 : for (unsigned i = 0; i < r.num_pairs (); ++i)
340 : {
341 197504349 : write_wide_int (val, len, r.lower_bound (i));
342 197506518 : 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 140038907 : irange_bitmask bm = r.m_bitmask;
347 140038907 : write_wide_int (val, len, bm.value ());
348 140038907 : write_wide_int (val, len, bm.mask ());
349 140038907 : }
350 :
351 : static inline void
352 4429781336 : read_wide_int (wide_int &w,
353 : const HOST_WIDE_INT *val, unsigned short len, unsigned prec)
354 : {
355 4429781336 : trailing_wide_int_storage stow (prec, &len,
356 1103684966 : const_cast <HOST_WIDE_INT *> (val));
357 3326096370 : w = trailing_wide_int (stow);
358 : }
359 :
360 : // Restore a range of TYPE from storage into R.
361 :
362 : void
363 1327409013 : irange_storage::get_irange (irange &r, tree type) const
364 : {
365 1327409013 : if (m_kind == VR_UNDEFINED)
366 : {
367 10495256 : r.set_undefined ();
368 420387885 : return;
369 : }
370 1316913757 : if (m_kind == VR_VARYING)
371 : {
372 399397373 : r.set_varying (type);
373 399397373 : return;
374 : }
375 :
376 917516384 : gcc_checking_assert (TYPE_PRECISION (type) == m_precision);
377 917516384 : const HOST_WIDE_INT *val = &m_val[0];
378 917516384 : const unsigned short *len = lengths_address ();
379 :
380 : // Handle the common case where R can fit the new range.
381 917516384 : if (r.m_max_ranges >= m_num_ranges)
382 : {
383 885366496 : r.m_kind = VR_RANGE;
384 885366496 : r.m_num_ranges = m_num_ranges;
385 885366496 : r.m_type = type;
386 3107777900 : for (unsigned i = 0; i < m_num_ranges * 2; ++i)
387 : {
388 2222411404 : read_wide_int (r.m_base[i], val, *len, m_precision);
389 2222411404 : val += *len++;
390 : }
391 : }
392 : // Otherwise build the range piecewise.
393 : else
394 : {
395 32149888 : r.set_undefined ();
396 218318470 : for (unsigned i = 0; i < m_num_ranges; ++i)
397 : {
398 186168582 : wide_int lb, ub;
399 186168582 : read_wide_int (lb, val, *len, m_precision);
400 186168582 : val += *len++;
401 186168582 : read_wide_int (ub, val, *len, m_precision);
402 186168582 : val += *len++;
403 186168582 : int_range<1> tmp (type, lb, ub);
404 186168582 : r.union_ (tmp);
405 186168582 : }
406 : }
407 :
408 917516384 : wide_int bits_value, bits_mask;
409 917516384 : read_wide_int (bits_value, val, *len, m_precision);
410 917516384 : val += *len++;
411 917516384 : read_wide_int (bits_mask, val, *len, m_precision);
412 917516384 : r.m_bitmask = irange_bitmask (bits_value, bits_mask);
413 917516384 : if (r.m_kind == VR_VARYING)
414 0 : r.m_kind = VR_RANGE;
415 :
416 917516384 : if (flag_checking)
417 917512670 : r.verify_range ();
418 917522911 : }
419 :
420 : bool
421 4546844 : irange_storage::equal_p (const irange &r) const
422 : {
423 4546844 : if (m_kind == VR_UNDEFINED || r.undefined_p ())
424 0 : return m_kind == r.m_kind;
425 4546844 : if (m_kind == VR_VARYING || r.varying_p ())
426 415305 : 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 4131539 : int_range_max tmp;
431 4131539 : get_irange (tmp, r.type ());
432 4131539 : return tmp == r;
433 4131539 : }
434 :
435 : // Return the size in bytes to allocate storage that can hold R.
436 :
437 : size_t
438 249088479 : irange_storage::size (const irange &r)
439 : {
440 249088479 : if (r.undefined_p ())
441 : return sizeof (irange_storage);
442 :
443 230706659 : unsigned prec = TYPE_PRECISION (r.type ());
444 230706659 : unsigned n = r.num_pairs () * 2 + 2;
445 230706659 : unsigned hwi_size = ((n * WIDE_INT_MAX_HWIS (prec) - 1)
446 : * sizeof (HOST_WIDE_INT));
447 230706659 : unsigned len_size = n * sizeof (unsigned short);
448 230706659 : return sizeof (irange_storage) + hwi_size + len_size;
449 : }
450 :
451 : // Return TRUE if R fits in the current storage.
452 :
453 : bool
454 323660882 : irange_storage::fits_p (const irange &r) const
455 : {
456 323660882 : 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 12387122 : frange_storage::alloc (vrange_internal_alloc &allocator, const frange &r)
512 : {
513 12387122 : size_t size = sizeof (frange_storage);
514 12387122 : frange_storage *p = static_cast <frange_storage *> (allocator.alloc (size));
515 12387122 : new (p) frange_storage (r);
516 12387122 : return p;
517 : }
518 :
519 : void
520 13065206 : frange_storage::set_frange (const frange &r)
521 : {
522 13065206 : gcc_checking_assert (fits_p (r));
523 :
524 13065206 : m_kind = r.m_kind;
525 13065206 : m_min = r.m_min;
526 13065206 : m_max = r.m_max;
527 13065206 : m_pos_nan = r.m_pos_nan;
528 13065206 : m_neg_nan = r.m_neg_nan;
529 13065206 : }
530 :
531 : void
532 46308493 : frange_storage::get_frange (frange &r, tree type) const
533 : {
534 46308493 : gcc_checking_assert (r.supports_type_p (type));
535 :
536 : // Handle explicit NANs.
537 46308493 : if (m_kind == VR_NAN)
538 : {
539 104771 : if (HONOR_NANS (type))
540 : {
541 104771 : if (m_pos_nan && m_neg_nan)
542 99281 : r.set_nan (type);
543 : else
544 5490 : r.set_nan (type, m_neg_nan);
545 : }
546 : else
547 0 : r.set_undefined ();
548 104771 : return;
549 : }
550 46203722 : if (m_kind == VR_UNDEFINED)
551 : {
552 66417 : r.set_undefined ();
553 66417 : 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 46137305 : 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 46137305 : if (HONOR_NANS (type) && (m_pos_nan ^ m_neg_nan) == 1)
567 1287514 : r.update_nan (m_neg_nan);
568 44849791 : else if (!m_pos_nan && !m_neg_nan)
569 12268306 : r.clear_nan ();
570 : }
571 :
572 : bool
573 19113 : frange_storage::equal_p (const frange &r) const
574 : {
575 19113 : if (r.undefined_p ())
576 0 : return m_kind == VR_UNDEFINED;
577 :
578 19113 : frange tmp;
579 19113 : get_frange (tmp, r.type ());
580 19113 : return tmp == r;
581 19113 : }
582 :
583 : bool
584 14420955 : frange_storage::fits_p (const frange &) const
585 : {
586 14420955 : return true;
587 : }
588 :
589 : //============================================================================
590 : // prange_storage implementation
591 : //============================================================================
592 :
593 : prange_storage *
594 95044186 : prange_storage::alloc (vrange_internal_alloc &allocator, const prange &r)
595 : {
596 95044186 : size_t size = sizeof (prange_storage);
597 95044186 : if (!r.undefined_p ())
598 : {
599 85233707 : unsigned prec = TYPE_PRECISION (r.type ());
600 85233707 : size += trailing_wide_ints<NINTS>::extra_size (prec);
601 : }
602 95044186 : prange_storage *p = static_cast <prange_storage *> (allocator.alloc (size));
603 95044186 : new (p) prange_storage (r);
604 95044186 : return p;
605 : }
606 :
607 : // Initialize the storage with R.
608 :
609 95044186 : prange_storage::prange_storage (const prange &r)
610 : {
611 : // It is the caller's responsibility to allocate enough space such
612 : // that the precision fits.
613 95044186 : if (r.undefined_p ())
614 : // Undefined ranges do not require any extra space for trailing
615 : // wide ints.
616 9810479 : m_trailing_ints.set_precision (0);
617 : else
618 85233707 : m_trailing_ints.set_precision (TYPE_PRECISION (r.type ()));
619 :
620 95044186 : set_prange (r);
621 95044186 : }
622 :
623 : void
624 98665788 : prange_storage::set_prange (const prange &r)
625 : {
626 98665788 : if (r.undefined_p ())
627 9816764 : m_kind = VR_UNDEFINED;
628 88849024 : else if (r.varying_p ())
629 47865313 : m_kind = VR_VARYING;
630 : else
631 : {
632 40983711 : m_kind = VR_RANGE;
633 40983711 : set_low (r.lower_bound ());
634 40983711 : set_high (r.upper_bound ());
635 40983711 : irange_bitmask bm = r.m_bitmask;
636 40983711 : set_value (bm.value ());
637 40983711 : set_mask (bm.mask ());
638 40983711 : }
639 98665788 : }
640 :
641 : void
642 354320628 : prange_storage::get_prange (prange &r, tree type) const
643 : {
644 354320628 : gcc_checking_assert (r.supports_type_p (type));
645 :
646 354320628 : if (m_kind == VR_UNDEFINED)
647 1003413 : r.set_undefined ();
648 353317215 : else if (m_kind == VR_VARYING)
649 198991264 : r.set_varying (type);
650 : else
651 : {
652 154325951 : gcc_checking_assert (m_kind == VR_RANGE);
653 154325951 : gcc_checking_assert (TYPE_PRECISION (type) == m_trailing_ints.get_precision ());
654 154325951 : r.m_kind = VR_RANGE;
655 154325951 : r.m_type = type;
656 154325951 : r.m_min = get_low ();
657 154325951 : r.m_max = get_high ();
658 154325951 : r.m_bitmask = irange_bitmask (get_value (), get_mask ());
659 154325951 : if (flag_checking)
660 154325813 : r.verify_range ();
661 : }
662 354320628 : }
663 :
664 : bool
665 5044000 : prange_storage::equal_p (const prange &r) const
666 : {
667 5044000 : if (r.undefined_p ())
668 0 : return m_kind == VR_UNDEFINED;
669 :
670 5044000 : prange tmp;
671 5044000 : get_prange (tmp, r.type ());
672 5044000 : return tmp == r;
673 5044000 : }
674 :
675 : bool
676 7048457 : prange_storage::fits_p (const prange &r) const
677 : {
678 : // Undefined ranges always fit, because they don't store anything in
679 : // the trailing wide ints.
680 7048457 : if (r.undefined_p ())
681 : return true;
682 :
683 7035887 : return TYPE_PRECISION (r.type ()) <= m_trailing_ints.get_precision ();
684 : }
685 :
686 :
687 : static vrange_allocator ggc_vrange_allocator (true);
688 :
689 0 : vrange_storage *ggc_alloc_vrange_storage (tree type)
690 : {
691 0 : return ggc_vrange_allocator.clone_varying (type);
692 : }
693 :
694 18093583 : vrange_storage *ggc_alloc_vrange_storage (const vrange &r)
695 : {
696 18093583 : return ggc_vrange_allocator.clone (r);
697 : }
|