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 "gimplify.h"
28 : #include "ssa.h"
29 : #include "tree-pretty-print.h"
30 : #include "fold-const.h"
31 : #include "gimple-range.h"
32 : #include "value-range-storage.h"
33 :
34 : // Generic memory allocator to share one interface between GC and
35 : // obstack allocators.
36 :
37 : class vrange_internal_alloc
38 : {
39 : public:
40 113127002 : vrange_internal_alloc () { }
41 113126993 : virtual ~vrange_internal_alloc () { }
42 : virtual void *alloc (size_t size) = 0;
43 : virtual void free (void *) = 0;
44 : private:
45 : DISABLE_COPY_AND_ASSIGN (vrange_internal_alloc);
46 : };
47 :
48 : class vrange_obstack_alloc final: public vrange_internal_alloc
49 : {
50 : public:
51 112835801 : vrange_obstack_alloc ()
52 112835801 : {
53 112835801 : obstack_init (&m_obstack);
54 112835801 : }
55 112835792 : virtual ~vrange_obstack_alloc () final override
56 112835792 : {
57 112835792 : obstack_free (&m_obstack, NULL);
58 112835792 : }
59 393326117 : virtual void *alloc (size_t size) final override
60 : {
61 393326117 : return obstack_alloc (&m_obstack, size);
62 : }
63 0 : virtual void free (void *) final override { }
64 : private:
65 : obstack m_obstack;
66 : };
67 :
68 : class vrange_ggc_alloc final: public vrange_internal_alloc
69 : {
70 : public:
71 291201 : vrange_ggc_alloc () { }
72 291201 : virtual ~vrange_ggc_alloc () final override { }
73 20425376 : virtual void *alloc (size_t size) final override
74 : {
75 20425376 : return ggc_internal_alloc (size);
76 : }
77 0 : virtual void free (void *p) final override
78 : {
79 0 : return ggc_free (p);
80 : }
81 : };
82 :
83 113127002 : vrange_allocator::vrange_allocator (bool gc)
84 : {
85 113127002 : if (gc)
86 291201 : m_alloc = new vrange_ggc_alloc;
87 : else
88 112835801 : m_alloc = new vrange_obstack_alloc;
89 113127002 : }
90 :
91 113126993 : vrange_allocator::~vrange_allocator ()
92 : {
93 113126993 : delete m_alloc;
94 113126993 : }
95 :
96 : void *
97 57343621 : vrange_allocator::alloc (size_t size)
98 : {
99 57343621 : return m_alloc->alloc (size);
100 : }
101 :
102 : void
103 0 : vrange_allocator::free (void *p)
104 : {
105 0 : m_alloc->free (p);
106 0 : }
107 :
108 : // Allocate a new vrange_storage object initialized to R and return
109 : // it.
110 :
111 : vrange_storage *
112 299074622 : vrange_allocator::clone (const vrange &r, bool shared_p)
113 : {
114 299074622 : return vrange_storage::alloc (*m_alloc, r, shared_p);
115 : }
116 :
117 : vrange_storage *
118 28716392 : vrange_allocator::clone_varying (tree type)
119 : {
120 28716392 : if (irange::supports_p (type))
121 18300791 : return irange_storage::alloc (*m_alloc, int_range <1> (type));
122 10415601 : if (prange::supports_p (type))
123 9945631 : return prange_storage::alloc (*m_alloc, prange (type));
124 469970 : if (frange::supports_p (type))
125 469970 : return frange_storage::alloc (*m_alloc, frange (type));
126 : return NULL;
127 : }
128 :
129 : vrange_storage *
130 28616858 : vrange_allocator::clone_undefined (tree type)
131 : {
132 28616858 : if (irange::supports_p (type))
133 18206925 : return irange_storage::alloc (*m_alloc, int_range<1> ());
134 10409933 : if (prange::supports_p (type))
135 9944116 : return prange_storage::alloc (*m_alloc, prange ());
136 465817 : if (frange::supports_p (type))
137 465817 : return frange_storage::alloc (*m_alloc, frange ());
138 : return NULL;
139 : }
140 :
141 : // Allocate a new vrange_storage object initialized to R and return
142 : // it. Return NULL if R is unsupported.
143 :
144 : vrange_storage *
145 299074622 : vrange_storage::alloc (vrange_internal_alloc &allocator, const vrange &r,
146 : bool shared_p)
147 : {
148 299074622 : if (is_a <irange> (r))
149 208955637 : return irange_storage::alloc (allocator, as_a <irange> (r));
150 90118985 : if (is_a <prange> (r))
151 78681930 : return prange_storage::alloc (allocator, as_a <prange> (r), shared_p);
152 11437055 : if (is_a <frange> (r))
153 11437055 : return frange_storage::alloc (allocator, as_a <frange> (r));
154 : return NULL;
155 : }
156 :
157 : // Set storage to R.
158 :
159 : void
160 25249146 : vrange_storage::set_vrange (const vrange &r)
161 : {
162 25249146 : if (is_a <irange> (r))
163 : {
164 21417866 : irange_storage *s = static_cast <irange_storage *> (this);
165 21417866 : gcc_checking_assert (s->fits_p (as_a <irange> (r)));
166 21417866 : s->set_irange (as_a <irange> (r));
167 : }
168 3831280 : else if (is_a <prange> (r))
169 : {
170 3206456 : prange_storage *s = static_cast <prange_storage *> (this);
171 3206456 : gcc_checking_assert (s->fits_p (as_a <prange> (r)));
172 3206456 : s->set_prange (as_a <prange> (r));
173 : }
174 624824 : else if (is_a <frange> (r))
175 : {
176 624824 : frange_storage *s = static_cast <frange_storage *> (this);
177 624824 : gcc_checking_assert (s->fits_p (as_a <frange> (r)));
178 624824 : s->set_frange (as_a <frange> (r));
179 : }
180 : else
181 0 : gcc_unreachable ();
182 :
183 : // Verify that reading back from the cache didn't drop bits.
184 25249146 : if (flag_checking
185 : // FIXME: Avoid checking frange, as it currently pessimizes some ranges:
186 : //
187 : // gfortran.dg/pr49472.f90 pessimizes [0.0, 1.0] into [-0.0, 1.0].
188 25249078 : && !is_a <frange> (r)
189 49873400 : && !r.undefined_p ())
190 : {
191 24502920 : value_range tmp (r);
192 24502920 : get_vrange (tmp, r.type ());
193 24502920 : gcc_checking_assert (tmp == r);
194 24502920 : }
195 25249146 : }
196 :
197 : // Restore R from storage.
198 :
199 : void
200 1735853506 : vrange_storage::get_vrange (vrange &r, tree type) const
201 : {
202 1735853506 : if (is_a <irange> (r))
203 : {
204 1327031674 : const irange_storage *s = static_cast <const irange_storage *> (this);
205 1327031674 : s->get_irange (as_a <irange> (r), type);
206 : }
207 408821832 : else if (is_a <prange> (r))
208 : {
209 364372984 : const prange_storage *s = static_cast <const prange_storage *> (this);
210 364372984 : s->get_prange (as_a <prange> (r), type);
211 : }
212 44448848 : else if (is_a <frange> (r))
213 : {
214 44448848 : const frange_storage *s = static_cast <const frange_storage *> (this);
215 44448848 : s->get_frange (as_a <frange> (r), type);
216 : }
217 : else
218 0 : gcc_unreachable ();
219 1735853506 : }
220 :
221 : // Return TRUE if storage can fit R.
222 :
223 : bool
224 29278064 : vrange_storage::fits_p (const vrange &r) const
225 : {
226 29278064 : if (is_a <irange> (r))
227 : {
228 25453699 : const irange_storage *s = static_cast <const irange_storage *> (this);
229 25453699 : return s->fits_p (as_a <irange> (r));
230 : }
231 3824365 : if (is_a <prange> (r))
232 : {
233 3199960 : const prange_storage *s = static_cast <const prange_storage *> (this);
234 3199960 : return s->fits_p (as_a <prange> (r));
235 : }
236 624405 : if (is_a <frange> (r))
237 : {
238 624405 : const frange_storage *s = static_cast <const frange_storage *> (this);
239 624405 : return s->fits_p (as_a <frange> (r));
240 : }
241 0 : gcc_unreachable ();
242 : return false;
243 : }
244 :
245 : // Return TRUE if the range in storage is equal to R. It is the
246 : // caller's responsibility to verify that the type of the range in
247 : // storage matches that of R.
248 :
249 : bool
250 18366651 : vrange_storage::equal_p (const vrange &r) const
251 : {
252 18366651 : if (is_a <irange> (r))
253 : {
254 3765652 : const irange_storage *s = static_cast <const irange_storage *> (this);
255 3765652 : return s->equal_p (as_a <irange> (r));
256 : }
257 14600999 : if (is_a <prange> (r))
258 : {
259 14581639 : const prange_storage *s = static_cast <const prange_storage *> (this);
260 14581639 : return s->equal_p (as_a <prange> (r));
261 : }
262 19360 : if (is_a <frange> (r))
263 : {
264 19360 : const frange_storage *s = static_cast <const frange_storage *> (this);
265 19360 : return s->equal_p (as_a <frange> (r));
266 : }
267 0 : gcc_unreachable ();
268 : }
269 :
270 : //============================================================================
271 : // irange_storage implementation
272 : //============================================================================
273 :
274 : unsigned short *
275 1062361679 : irange_storage::write_lengths_address ()
276 : {
277 1062361679 : return (unsigned short *)&m_val[(m_num_ranges * 2 + 2)
278 1062361679 : * WIDE_INT_MAX_HWIS (m_precision)];
279 : }
280 :
281 : const unsigned short *
282 925477617 : irange_storage::lengths_address () const
283 : {
284 925477617 : return const_cast <irange_storage *> (this)->write_lengths_address ();
285 : }
286 :
287 : // Allocate a new irange_storage object initialized to R.
288 :
289 : irange_storage *
290 245463353 : irange_storage::alloc (vrange_internal_alloc &allocator, const irange &r)
291 : {
292 245463353 : size_t size = irange_storage::size (r);
293 245463353 : irange_storage *p = static_cast <irange_storage *> (allocator.alloc (size));
294 245463353 : new (p) irange_storage (r);
295 245463353 : return p;
296 : }
297 :
298 : // Initialize the storage with R.
299 :
300 245463353 : irange_storage::irange_storage (const irange &r)
301 245463353 : : vrange_storage (VR_IRANGE), m_max_ranges (r.num_pairs ())
302 : {
303 245463353 : m_num_ranges = m_max_ranges;
304 245463353 : set_irange (r);
305 245463353 : }
306 :
307 : static inline void
308 655048442 : write_wide_int (HOST_WIDE_INT *&val, unsigned short *&len, const wide_int &w)
309 : {
310 655048442 : *len = w.get_len ();
311 1310968497 : for (unsigned i = 0; i < *len; ++i)
312 655920055 : *val++ = w.elt (i);
313 655048442 : ++len;
314 655048442 : }
315 :
316 : // Store R into the current storage.
317 :
318 : void
319 266881219 : irange_storage::set_irange (const irange &r)
320 : {
321 266881219 : gcc_checking_assert (fits_p (r));
322 :
323 266881219 : if (r.undefined_p ())
324 : {
325 18597501 : m_kind = VR_UNDEFINED;
326 129997157 : return;
327 : }
328 248283718 : if (r.varying_p ())
329 : {
330 111399656 : m_kind = VR_VARYING;
331 111399656 : return;
332 : }
333 :
334 136884062 : m_precision = TYPE_PRECISION (r.type ());
335 136884062 : m_num_ranges = r.num_pairs ();
336 136884062 : m_kind = VR_RANGE;
337 :
338 136884062 : HOST_WIDE_INT *val = &m_val[0];
339 136884062 : unsigned short *len = write_lengths_address ();
340 :
341 327524221 : for (unsigned i = 0; i < r.num_pairs (); ++i)
342 : {
343 190640159 : write_wide_int (val, len, r.lower_bound (i));
344 190642582 : write_wide_int (val, len, r.upper_bound (i));
345 : }
346 :
347 : // TODO: We could avoid streaming out the value if the mask is -1.
348 136884062 : irange_bitmask bm = r.m_bitmask;
349 136884062 : write_wide_int (val, len, bm.value ());
350 136884062 : write_wide_int (val, len, bm.mask ());
351 136884062 : }
352 :
353 : static inline void
354 4483961370 : read_wide_int (wide_int &w,
355 : const HOST_WIDE_INT *val, unsigned short len, unsigned prec)
356 : {
357 4483961370 : trailing_wide_int_storage stow (prec, &len,
358 1116545328 : const_cast <HOST_WIDE_INT *> (val));
359 3367416042 : w = trailing_wide_int (stow);
360 : }
361 :
362 : // Restore a range of TYPE from storage into R.
363 :
364 : void
365 1330353637 : irange_storage::get_irange (irange &r, tree type) const
366 : {
367 1330353637 : if (m_kind == VR_UNDEFINED)
368 : {
369 9842455 : r.set_undefined ();
370 414718475 : return;
371 : }
372 1320511182 : if (m_kind == VR_VARYING)
373 : {
374 395033565 : r.set_varying (type);
375 395033565 : return;
376 : }
377 :
378 925477617 : gcc_checking_assert (TYPE_PRECISION (type) == m_precision);
379 925477617 : const HOST_WIDE_INT *val = &m_val[0];
380 925477617 : const unsigned short *len = lengths_address ();
381 :
382 : // Handle the common case where R can fit the new range.
383 925477617 : if (r.m_max_ranges >= m_num_ranges)
384 : {
385 892688528 : r.m_kind = VR_RANGE;
386 892688528 : r.m_num_ranges = m_num_ranges;
387 892688528 : r.m_type = type;
388 3143559242 : for (unsigned i = 0; i < m_num_ranges * 2; ++i)
389 : {
390 2250870714 : read_wide_int (r.m_base[i], val, *len, m_precision);
391 2250870714 : val += *len++;
392 : }
393 : }
394 : // Otherwise build the range piecewise.
395 : else
396 : {
397 32789089 : r.set_undefined ();
398 223856800 : for (unsigned i = 0; i < m_num_ranges; ++i)
399 : {
400 191067711 : wide_int lb, ub;
401 191067711 : read_wide_int (lb, val, *len, m_precision);
402 191067711 : val += *len++;
403 191067711 : read_wide_int (ub, val, *len, m_precision);
404 191067711 : val += *len++;
405 191067711 : int_range<1> tmp (type, lb, ub);
406 191067711 : r.union_ (tmp);
407 191067711 : }
408 : }
409 :
410 925477617 : wide_int bits_value, bits_mask;
411 925477617 : read_wide_int (bits_value, val, *len, m_precision);
412 925477617 : val += *len++;
413 925477617 : read_wide_int (bits_mask, val, *len, m_precision);
414 925477617 : r.m_bitmask = irange_bitmask (bits_value, bits_mask);
415 925477617 : if (r.m_kind == VR_VARYING)
416 0 : r.m_kind = VR_RANGE;
417 :
418 925477617 : if (flag_checking)
419 925474211 : r.verify_range ();
420 925484548 : }
421 :
422 : bool
423 3765652 : irange_storage::equal_p (const irange &r) const
424 : {
425 3765652 : if (m_kind == VR_UNDEFINED || r.undefined_p ())
426 0 : return m_kind == r.m_kind;
427 3765652 : if (m_kind == VR_VARYING || r.varying_p ())
428 443689 : return m_kind == r.m_kind;
429 :
430 : // ?? We could make this faster by doing the comparison in place,
431 : // without going through get_irange.
432 3321963 : int_range_max tmp;
433 3321963 : get_irange (tmp, r.type ());
434 3321963 : return tmp == r;
435 3321963 : }
436 :
437 : // Return the size in bytes to allocate storage that can hold R.
438 :
439 : size_t
440 245463353 : irange_storage::size (const irange &r)
441 : {
442 245463353 : if (r.undefined_p ())
443 : return sizeof (irange_storage);
444 :
445 226981441 : unsigned prec = TYPE_PRECISION (r.type ());
446 226981441 : unsigned n = r.num_pairs () * 2 + 2;
447 226981441 : unsigned hwi_size = ((n * WIDE_INT_MAX_HWIS (prec) - 1)
448 : * sizeof (HOST_WIDE_INT));
449 226981441 : unsigned len_size = n * sizeof (unsigned short);
450 226981441 : return sizeof (irange_storage) + hwi_size + len_size;
451 : }
452 :
453 : // Return TRUE if R fits in the current storage.
454 :
455 : bool
456 313752784 : irange_storage::fits_p (const irange &r) const
457 : {
458 313752784 : return m_max_ranges >= r.num_pairs ();
459 : }
460 :
461 : void
462 0 : irange_storage::dump () const
463 : {
464 0 : fprintf (stderr, "irange_storage (prec=%d, ranges=%d):\n",
465 0 : m_precision, m_num_ranges);
466 :
467 0 : if (m_num_ranges == 0)
468 : return;
469 :
470 0 : const HOST_WIDE_INT *val = &m_val[0];
471 0 : const unsigned short *len = lengths_address ();
472 0 : int i, j;
473 :
474 0 : fprintf (stderr, " lengths = [ ");
475 0 : for (i = 0; i < m_num_ranges * 2 + 2; ++i)
476 0 : fprintf (stderr, "%d ", len[i]);
477 0 : fprintf (stderr, "]\n");
478 :
479 0 : for (i = 0; i < m_num_ranges; ++i)
480 : {
481 0 : for (j = 0; j < *len; ++j)
482 0 : fprintf (stderr, " [PAIR %d] LB " HOST_WIDE_INT_PRINT_DEC "\n", i,
483 0 : *val++);
484 0 : ++len;
485 0 : for (j = 0; j < *len; ++j)
486 0 : fprintf (stderr, " [PAIR %d] UB " HOST_WIDE_INT_PRINT_DEC "\n", i,
487 0 : *val++);
488 0 : ++len;
489 : }
490 :
491 : // Dump value/mask pair.
492 0 : for (j = 0; j < *len; ++j)
493 0 : fprintf (stderr, " [VALUE] " HOST_WIDE_INT_PRINT_DEC "\n", *val++);
494 0 : ++len;
495 0 : for (j = 0; j < *len; ++j)
496 0 : fprintf (stderr, " [MASK] " HOST_WIDE_INT_PRINT_DEC "\n", *val++);
497 : }
498 :
499 : DEBUG_FUNCTION void
500 0 : debug (const irange_storage &storage)
501 : {
502 0 : storage.dump ();
503 0 : fprintf (stderr, "\n");
504 0 : }
505 :
506 : //============================================================================
507 : // frange_storage implementation
508 : //============================================================================
509 :
510 : // Allocate a new frange_storage object initialized to R.
511 :
512 : frange_storage *
513 12372842 : frange_storage::alloc (vrange_internal_alloc &allocator, const frange &r)
514 : {
515 12372842 : size_t size = sizeof (frange_storage);
516 12372842 : frange_storage *p = static_cast <frange_storage *> (allocator.alloc (size));
517 12372842 : new (p) frange_storage (r);
518 12372842 : return p;
519 : }
520 :
521 : void
522 12997666 : frange_storage::set_frange (const frange &r)
523 : {
524 12997666 : gcc_checking_assert (fits_p (r));
525 :
526 12997666 : m_kind = r.m_kind;
527 12997666 : m_min = r.m_min;
528 12997666 : m_max = r.m_max;
529 12997666 : m_pos_nan = r.m_pos_nan;
530 12997666 : m_neg_nan = r.m_neg_nan;
531 12997666 : }
532 :
533 : void
534 44468208 : frange_storage::get_frange (frange &r, tree type) const
535 : {
536 44468208 : gcc_checking_assert (r.supports_type_p (type));
537 :
538 : // Handle explicit NANs.
539 44468208 : if (m_kind == VR_NAN)
540 : {
541 106595 : if (HONOR_NANS (type))
542 : {
543 106595 : if (m_pos_nan && m_neg_nan)
544 101051 : r.set_nan (type);
545 : else
546 5544 : r.set_nan (type, m_neg_nan);
547 : }
548 : else
549 0 : r.set_undefined ();
550 106595 : return;
551 : }
552 44361613 : if (m_kind == VR_UNDEFINED)
553 : {
554 55085 : r.set_undefined ();
555 55085 : return;
556 : }
557 :
558 : // We use the constructor to create the new range instead of writing
559 : // out the bits into the frange directly, because the global range
560 : // being read may be being inlined into a function with different
561 : // restrictions as when it was originally written. We want to make
562 : // sure the resulting range is canonicalized correctly for the new
563 : // consumer.
564 44306528 : r = frange (type, m_min, m_max, m_kind);
565 :
566 : // The constructor will set the NAN bits for HONOR_NANS, but we must
567 : // make sure to set the NAN sign if known.
568 44306528 : if (HONOR_NANS (type) && (m_pos_nan ^ m_neg_nan) == 1)
569 1327764 : r.update_nan (m_neg_nan);
570 42978764 : else if (!m_pos_nan && !m_neg_nan)
571 11757572 : r.clear_nan ();
572 : }
573 :
574 : bool
575 19360 : frange_storage::equal_p (const frange &r) const
576 : {
577 19360 : if (r.undefined_p ())
578 0 : return m_kind == VR_UNDEFINED;
579 :
580 19360 : frange tmp;
581 19360 : get_frange (tmp, r.type ());
582 19360 : return tmp == r;
583 19360 : }
584 :
585 : bool
586 14246895 : frange_storage::fits_p (const frange &) const
587 : {
588 14246895 : return true;
589 : }
590 :
591 : //============================================================================
592 : // prange_storage implementation
593 : //============================================================================
594 :
595 : prange_storage *
596 98571677 : prange_storage::alloc (vrange_internal_alloc &allocator, const prange &r,
597 : bool shared_p)
598 : {
599 98571677 : unsigned num_words;
600 98571677 : prange_format (r, num_words);
601 98571677 : size_t extra_size = 0;
602 98571677 : if (num_words)
603 : {
604 2268844 : unsigned short precision = TYPE_PRECISION (r.type ());
605 2268844 : extra_size = trailing_wide_ints<PRANGE_STORAGE_NINTS>
606 2268844 : ::extra_size (precision, num_words);
607 : }
608 :
609 98571677 : size_t size = sizeof (prange_storage) + extra_size;
610 98571677 : prange_storage *p = static_cast <prange_storage *> (allocator.alloc (size));
611 98571677 : new (p) prange_storage (r);
612 98571677 : if (p->m_pt && !shared_p)
613 2017023 : p->m_pt = unshare_expr_without_location (p->m_pt);
614 :
615 98571677 : return p;
616 : }
617 :
618 : // Initialize the storage with R.
619 :
620 98571677 : prange_storage::prange_storage (const prange &r) : vrange_storage (VR_PRANGE)
621 : {
622 98571677 : unsigned num_words;
623 98571677 : enum prange_kind kind = prange_format (r, num_words);
624 98571677 : unsigned short prec = (kind == PR_UNDEFINED) ? 0 : TYPE_PRECISION (r.type ());
625 98571677 : m_trailing_ints.set_precision (prec, num_words);
626 98571677 : set_prange (r);
627 98571677 : }
628 :
629 : // Return the prange_kind for range R, and the number of words of storage
630 : // it requires in NUM_WORDS.
631 :
632 : enum prange_kind
633 305316389 : prange_storage::prange_format (const prange &r, unsigned &num_words)
634 : {
635 305316389 : num_words = 0;
636 305316389 : if (r.undefined_p ())
637 : return PR_UNDEFINED;
638 :
639 275358713 : if (r.varying_p ())
640 : return PR_VARYING;
641 :
642 129814904 : if (r.zero_p ())
643 : return PR_ZERO;
644 :
645 129090266 : enum prange_kind kind = PR_NONZERO;
646 :
647 129090266 : if (!r.nonzero_p ())
648 : {
649 2764166 : prange tmp (r.type ());
650 5528332 : if (r.lower_bound () == tmp.lower_bound ()
651 4025690 : && r.upper_bound () == tmp.upper_bound ())
652 : kind = PR_FULL;
653 : else
654 : {
655 : // PR_OTHER requires words of storage for the end points.
656 2549409 : kind = PR_OTHER;
657 2549409 : num_words += 2;
658 : }
659 2764166 : }
660 :
661 : // Bitmasks require 2 words of storage.
662 129090266 : if (!r.get_bitmask ().unknown_p ())
663 5207122 : num_words += 2;
664 :
665 : // PR_FULL must have a bitmask or points to, or it should be PR_VARYING.
666 129305023 : gcc_checking_assert (kind != PR_FULL || !r.get_bitmask ().unknown_p ()
667 : || r.m_pt != NULL_TREE);
668 129090266 : return kind;
669 : }
670 :
671 : void
672 101778133 : prange_storage::set_prange (const prange &r)
673 : {
674 101778133 : unsigned num_words;
675 101778133 : m_kind = prange_format (r, num_words);
676 101778133 : m_has_bitmask = !r.get_bitmask ().unknown_p ();
677 101778133 : m_pt = r.m_pt;
678 101778133 : m_points_to_p = r.m_points_to_p;
679 :
680 101778133 : unsigned index = 0;
681 :
682 101778133 : switch (m_kind)
683 : {
684 58747125 : case PR_UNDEFINED:
685 58747125 : case PR_VARYING:
686 58747125 : case PR_ZERO:
687 58747125 : return;
688 : case PR_NONZERO:
689 : case PR_FULL:
690 : break;
691 790256 : case PR_OTHER:
692 790256 : set_word (index++, r.lower_bound (), r.type ());
693 790256 : set_word (index++, r.upper_bound (), r.type ());
694 790256 : break;
695 0 : default:
696 0 : gcc_unreachable ();
697 : }
698 :
699 43031008 : if (m_has_bitmask)
700 : {
701 1743776 : irange_bitmask bm = r.m_bitmask;
702 1743776 : set_word (index++, r.m_bitmask.value (), r.type ());
703 1743776 : set_word (index++, r.m_bitmask.mask (), r.type ());
704 1743776 : }
705 43031008 : gcc_checking_assert (index == num_words);
706 : }
707 :
708 : void
709 364372984 : prange_storage::get_prange (prange &r, tree type) const
710 : {
711 364372984 : gcc_checking_assert (r.supports_type_p (type));
712 364372984 : unsigned index = 0;
713 364372984 : switch (m_kind)
714 : {
715 995437 : case PR_UNDEFINED:
716 995437 : r.set_undefined ();
717 995437 : return;
718 :
719 202526449 : case PR_VARYING:
720 202526449 : r.set_varying (type);
721 202526449 : return;
722 :
723 682646 : case PR_ZERO:
724 682646 : r.set_zero (type);
725 682646 : return;
726 :
727 156846557 : case PR_NONZERO:
728 156846557 : r.set_nonzero (type);
729 156846557 : break;
730 :
731 515780 : case PR_FULL:
732 515780 : {
733 515780 : r.m_kind = VR_RANGE;
734 515780 : r.m_type = type;
735 515780 : prange tmp (type);
736 515780 : r.m_min = tmp.lower_bound ();
737 515780 : r.m_max = tmp.upper_bound ();
738 515780 : break;
739 515780 : }
740 :
741 2806115 : case PR_OTHER:
742 2806115 : {
743 2806115 : gcc_checking_assert (m_kind == PR_OTHER);
744 2806115 : r.m_kind = VR_RANGE;
745 2806115 : r.m_type = type;
746 2806115 : r.m_min = get_word (index++, type);
747 2806115 : r.m_max = get_word (index++, type);
748 2806115 : break;
749 : }
750 0 : default:
751 0 : gcc_unreachable ();
752 : }
753 :
754 160168452 : if (m_has_bitmask)
755 : {
756 17243830 : wide_int value = get_word (index++, type);
757 17243830 : wide_int mask = get_word (index++, type);
758 17243830 : r.m_bitmask = irange_bitmask (value, mask);
759 17243830 : }
760 : else
761 142924622 : r.m_bitmask.set_unknown (TYPE_PRECISION (type));
762 :
763 160168452 : r.m_points_to_p = m_points_to_p;
764 160168452 : r.m_pt = m_pt;
765 :
766 160168452 : if (flag_checking)
767 160168317 : r.verify_range ();
768 : }
769 :
770 : bool
771 14581639 : prange_storage::equal_p (const prange &r) const
772 : {
773 14581639 : if (r.undefined_p ())
774 0 : return m_kind == PR_UNDEFINED;
775 :
776 14581639 : unsigned index = 0;
777 14581639 : switch (m_kind)
778 : {
779 5748 : case PR_VARYING:
780 5748 : return r.varying_p ();
781 :
782 85351 : case PR_ZERO:
783 85351 : return r.zero_p ();
784 :
785 14153891 : case PR_NONZERO:
786 14153891 : if (!r.nonzero_p ())
787 : return false;
788 : break;
789 :
790 290858 : case PR_FULL:
791 290858 : if (r.m_min != wi::zero (TYPE_PRECISION (r.m_type))
792 584088 : || r.m_max != wi::max_value (TYPE_PRECISION (r.m_type),
793 146615 : TYPE_SIGN (r.m_type)))
794 : return false;
795 : break;
796 :
797 45791 : case PR_OTHER:
798 91582 : if (r.m_min != get_word (index++, r.m_type)
799 74310 : || r.m_max != get_word (index++, r.m_type))
800 : return false;
801 : break;
802 :
803 0 : default:
804 0 : gcc_unreachable ();
805 : }
806 :
807 13932236 : if (m_has_bitmask)
808 : {
809 8207393 : wide_int value = get_word (index++, r.m_type);
810 8207393 : wide_int mask = get_word (index++, r.m_type);
811 8207393 : if (r.m_bitmask != irange_bitmask (value, mask))
812 3972646 : return false;
813 8207393 : }
814 : else
815 5724843 : if (!r.m_bitmask.unknown_p ())
816 : return false;
817 :
818 8373037 : if (m_pt != r.m_pt)
819 : return false;
820 1495744 : if (m_points_to_p != r.m_points_to_p)
821 : return false;
822 :
823 : return true;
824 : }
825 :
826 : bool
827 6406416 : prange_storage::fits_p (const prange &r) const
828 : {
829 : // Undefined ranges always fit, because they don't store anything in
830 : // the trailing wide ints.
831 6406416 : if (r.undefined_p ())
832 : return true;
833 :
834 6394902 : unsigned num_words;
835 6394902 : prange_format (r, num_words);
836 6394902 : return num_words <= m_trailing_ints.num_elements ();
837 : }
838 :
839 :
840 : static vrange_allocator ggc_vrange_allocator (true);
841 :
842 0 : vrange_storage *ggc_alloc_vrange_storage (tree type)
843 : {
844 0 : return ggc_vrange_allocator.clone_varying (type);
845 : }
846 :
847 20425376 : vrange_storage *ggc_alloc_vrange_storage (const vrange &r, bool shared_p)
848 : {
849 20425376 : return ggc_vrange_allocator.clone (r, shared_p);
850 : }
|