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 111214140 : vrange_internal_alloc () { }
41 111214125 : 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 110916482 : vrange_obstack_alloc ()
52 110916482 : {
53 110916482 : obstack_init (&m_obstack);
54 110916482 : }
55 110916467 : virtual ~vrange_obstack_alloc () final override
56 110916467 : {
57 110916467 : obstack_free (&m_obstack, NULL);
58 110916467 : }
59 381803171 : virtual void *alloc (size_t size) final override
60 : {
61 381803171 : 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 297658 : vrange_ggc_alloc () { }
72 297658 : virtual ~vrange_ggc_alloc () final override { }
73 19644436 : virtual void *alloc (size_t size) final override
74 : {
75 19644436 : 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 111214140 : vrange_allocator::vrange_allocator (bool gc)
84 : {
85 111214140 : if (gc)
86 297658 : m_alloc = new vrange_ggc_alloc;
87 : else
88 110916482 : m_alloc = new vrange_obstack_alloc;
89 111214140 : }
90 :
91 111214125 : vrange_allocator::~vrange_allocator ()
92 : {
93 111214125 : delete m_alloc;
94 111214125 : }
95 :
96 : void *
97 55835991 : vrange_allocator::alloc (size_t size)
98 : {
99 55835991 : 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 289785908 : vrange_allocator::clone (const vrange &r, bool shared_p)
113 : {
114 289785908 : return vrange_storage::alloc (*m_alloc, r, shared_p);
115 : }
116 :
117 : vrange_storage *
118 27956038 : vrange_allocator::clone_varying (tree type)
119 : {
120 27956038 : if (irange::supports_p (type))
121 17970100 : return irange_storage::alloc (*m_alloc, int_range <1> (type));
122 9985938 : if (prange::supports_p (type))
123 9529049 : return prange_storage::alloc (*m_alloc, prange (type));
124 456889 : if (frange::supports_p (type))
125 456889 : return frange_storage::alloc (*m_alloc, frange (type));
126 : return NULL;
127 : }
128 :
129 : vrange_storage *
130 27869670 : vrange_allocator::clone_undefined (tree type)
131 : {
132 27869670 : if (irange::supports_p (type))
133 17889084 : return irange_storage::alloc (*m_alloc, int_range<1> ());
134 9980586 : if (prange::supports_p (type))
135 9527861 : return prange_storage::alloc (*m_alloc, prange ());
136 452725 : if (frange::supports_p (type))
137 452725 : 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 289785908 : vrange_storage::alloc (vrange_internal_alloc &allocator, const vrange &r,
146 : bool shared_p)
147 : {
148 289785908 : if (is_a <irange> (r))
149 203403748 : return irange_storage::alloc (allocator, as_a <irange> (r));
150 86382160 : if (is_a <prange> (r))
151 75096876 : return prange_storage::alloc (allocator, as_a <prange> (r), shared_p);
152 11285284 : if (is_a <frange> (r))
153 11285284 : return frange_storage::alloc (allocator, as_a <frange> (r));
154 : return NULL;
155 : }
156 :
157 : // Set storage to R.
158 :
159 : void
160 24677161 : vrange_storage::set_vrange (const vrange &r)
161 : {
162 24677161 : if (is_a <irange> (r))
163 : {
164 20990473 : irange_storage *s = static_cast <irange_storage *> (this);
165 20990473 : gcc_checking_assert (s->fits_p (as_a <irange> (r)));
166 20990473 : s->set_irange (as_a <irange> (r));
167 : }
168 3686688 : else if (is_a <prange> (r))
169 : {
170 3068272 : prange_storage *s = static_cast <prange_storage *> (this);
171 3068272 : gcc_checking_assert (s->fits_p (as_a <prange> (r)));
172 3068272 : s->set_prange (as_a <prange> (r));
173 : }
174 618416 : else if (is_a <frange> (r))
175 : {
176 618416 : frange_storage *s = static_cast <frange_storage *> (this);
177 618416 : gcc_checking_assert (s->fits_p (as_a <frange> (r)));
178 618416 : 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 24677161 : 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 24677088 : && !is_a <frange> (r)
189 48735833 : && !r.undefined_p ())
190 : {
191 23945743 : value_range tmp (r);
192 23945743 : get_vrange (tmp, r.type ());
193 23945743 : gcc_checking_assert (tmp == r);
194 23945743 : }
195 24677161 : }
196 :
197 : // Restore R from storage.
198 :
199 : void
200 1717945176 : vrange_storage::get_vrange (vrange &r, tree type) const
201 : {
202 1717945176 : if (is_a <irange> (r))
203 : {
204 1318922073 : const irange_storage *s = static_cast <const irange_storage *> (this);
205 1318922073 : s->get_irange (as_a <irange> (r), type);
206 : }
207 399023103 : else if (is_a <prange> (r))
208 : {
209 353392237 : const prange_storage *s = static_cast <const prange_storage *> (this);
210 353392237 : s->get_prange (as_a <prange> (r), type);
211 : }
212 45630866 : else if (is_a <frange> (r))
213 : {
214 45630866 : const frange_storage *s = static_cast <const frange_storage *> (this);
215 45630866 : s->get_frange (as_a <frange> (r), type);
216 : }
217 : else
218 0 : gcc_unreachable ();
219 1717945176 : }
220 :
221 : // Return TRUE if storage can fit R.
222 :
223 : bool
224 28686972 : vrange_storage::fits_p (const vrange &r) const
225 : {
226 28686972 : if (is_a <irange> (r))
227 : {
228 25008875 : const irange_storage *s = static_cast <const irange_storage *> (this);
229 25008875 : return s->fits_p (as_a <irange> (r));
230 : }
231 3678097 : if (is_a <prange> (r))
232 : {
233 3060100 : const prange_storage *s = static_cast <const prange_storage *> (this);
234 3060100 : return s->fits_p (as_a <prange> (r));
235 : }
236 617997 : if (is_a <frange> (r))
237 : {
238 617997 : const frange_storage *s = static_cast <const frange_storage *> (this);
239 617997 : 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 17318474 : vrange_storage::equal_p (const vrange &r) const
251 : {
252 17318474 : if (is_a <irange> (r))
253 : {
254 3632991 : const irange_storage *s = static_cast <const irange_storage *> (this);
255 3632991 : return s->equal_p (as_a <irange> (r));
256 : }
257 13685483 : if (is_a <prange> (r))
258 : {
259 13666433 : const prange_storage *s = static_cast <const prange_storage *> (this);
260 13666433 : return s->equal_p (as_a <prange> (r));
261 : }
262 19050 : if (is_a <frange> (r))
263 : {
264 19050 : const frange_storage *s = static_cast <const frange_storage *> (this);
265 19050 : 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 1049726560 : irange_storage::write_lengths_address ()
276 : {
277 1049726560 : return (unsigned short *)&m_val[(m_num_ranges * 2 + 2)
278 1049726560 : * WIDE_INT_MAX_HWIS (m_precision)];
279 : }
280 :
281 : const unsigned short *
282 916435799 : irange_storage::lengths_address () const
283 : {
284 916435799 : 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 239262932 : irange_storage::alloc (vrange_internal_alloc &allocator, const irange &r)
291 : {
292 239262932 : size_t size = irange_storage::size (r);
293 239262932 : irange_storage *p = static_cast <irange_storage *> (allocator.alloc (size));
294 239262932 : new (p) irange_storage (r);
295 239262932 : return p;
296 : }
297 :
298 : // Initialize the storage with R.
299 :
300 239262932 : irange_storage::irange_storage (const irange &r)
301 239262932 : : vrange_storage (VR_IRANGE), m_max_ranges (r.num_pairs ())
302 : {
303 239262932 : m_num_ranges = m_max_ranges;
304 239262932 : set_irange (r);
305 239262932 : }
306 :
307 : static inline void
308 639257126 : write_wide_int (HOST_WIDE_INT *&val, unsigned short *&len, const wide_int &w)
309 : {
310 639257126 : *len = w.get_len ();
311 1279375610 : for (unsigned i = 0; i < *len; ++i)
312 640118484 : *val++ = w.elt (i);
313 639257126 : ++len;
314 639257126 : }
315 :
316 : // Store R into the current storage.
317 :
318 : void
319 260253405 : irange_storage::set_irange (const irange &r)
320 : {
321 260253405 : gcc_checking_assert (fits_p (r));
322 :
323 260253405 : if (r.undefined_p ())
324 : {
325 18262904 : m_kind = VR_UNDEFINED;
326 126962644 : return;
327 : }
328 241990501 : if (r.varying_p ())
329 : {
330 108699740 : m_kind = VR_VARYING;
331 108699740 : return;
332 : }
333 :
334 133290761 : m_precision = TYPE_PRECISION (r.type ());
335 133290761 : m_num_ranges = r.num_pairs ();
336 133290761 : m_kind = VR_RANGE;
337 :
338 133290761 : HOST_WIDE_INT *val = &m_val[0];
339 133290761 : unsigned short *len = write_lengths_address ();
340 :
341 319628563 : for (unsigned i = 0; i < r.num_pairs (); ++i)
342 : {
343 186337802 : write_wide_int (val, len, r.lower_bound (i));
344 186340225 : 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 133290761 : irange_bitmask bm = r.m_bitmask;
349 133290761 : write_wide_int (val, len, bm.value ());
350 133290761 : write_wide_int (val, len, bm.mask ());
351 133290761 : }
352 :
353 : static inline void
354 4444945440 : read_wide_int (wide_int &w,
355 : const HOST_WIDE_INT *val, unsigned short len, unsigned prec)
356 : {
357 4444945440 : trailing_wide_int_storage stow (prec, &len,
358 1105698078 : const_cast <HOST_WIDE_INT *> (val));
359 3339247362 : w = trailing_wide_int (stow);
360 : }
361 :
362 : // Restore a range of TYPE from storage into R.
363 :
364 : void
365 1322138955 : irange_storage::get_irange (irange &r, tree type) const
366 : {
367 1322138955 : if (m_kind == VR_UNDEFINED)
368 : {
369 9954977 : r.set_undefined ();
370 415658133 : return;
371 : }
372 1312183978 : if (m_kind == VR_VARYING)
373 : {
374 395748179 : r.set_varying (type);
375 395748179 : return;
376 : }
377 :
378 916435799 : gcc_checking_assert (TYPE_PRECISION (type) == m_precision);
379 916435799 : const HOST_WIDE_INT *val = &m_val[0];
380 916435799 : const unsigned short *len = lengths_address ();
381 :
382 : // Handle the common case where R can fit the new range.
383 916435799 : if (r.m_max_ranges >= m_num_ranges)
384 : {
385 883940202 : r.m_kind = VR_RANGE;
386 883940202 : r.m_num_ranges = m_num_ranges;
387 883940202 : r.m_type = type;
388 3117489486 : for (unsigned i = 0; i < m_num_ranges * 2; ++i)
389 : {
390 2233549284 : read_wide_int (r.m_base[i], val, *len, m_precision);
391 2233549284 : val += *len++;
392 : }
393 : }
394 : // Otherwise build the range piecewise.
395 : else
396 : {
397 32495597 : r.set_undefined ();
398 221757876 : for (unsigned i = 0; i < m_num_ranges; ++i)
399 : {
400 189262279 : wide_int lb, ub;
401 189262279 : read_wide_int (lb, val, *len, m_precision);
402 189262279 : val += *len++;
403 189262279 : read_wide_int (ub, val, *len, m_precision);
404 189262279 : val += *len++;
405 189262279 : int_range<1> tmp (type, lb, ub);
406 189262279 : r.union_ (tmp);
407 189262279 : }
408 : }
409 :
410 916435799 : wide_int bits_value, bits_mask;
411 916435799 : read_wide_int (bits_value, val, *len, m_precision);
412 916435799 : val += *len++;
413 916435799 : read_wide_int (bits_mask, val, *len, m_precision);
414 916435799 : r.m_bitmask = irange_bitmask (bits_value, bits_mask);
415 916435799 : if (r.m_kind == VR_VARYING)
416 0 : r.m_kind = VR_RANGE;
417 :
418 916435799 : if (flag_checking)
419 916432314 : r.verify_range ();
420 916442836 : }
421 :
422 : bool
423 3632991 : irange_storage::equal_p (const irange &r) const
424 : {
425 3632991 : if (m_kind == VR_UNDEFINED || r.undefined_p ())
426 0 : return m_kind == r.m_kind;
427 3632991 : if (m_kind == VR_VARYING || r.varying_p ())
428 416109 : 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 3216882 : int_range_max tmp;
433 3216882 : get_irange (tmp, r.type ());
434 3216882 : return tmp == r;
435 3216882 : }
436 :
437 : // Return the size in bytes to allocate storage that can hold R.
438 :
439 : size_t
440 239262932 : irange_storage::size (const irange &r)
441 : {
442 239262932 : if (r.undefined_p ())
443 : return sizeof (irange_storage);
444 :
445 221107366 : unsigned prec = TYPE_PRECISION (r.type ());
446 221107366 : unsigned n = r.num_pairs () * 2 + 2;
447 221107366 : unsigned hwi_size = ((n * WIDE_INT_MAX_HWIS (prec) - 1)
448 : * sizeof (HOST_WIDE_INT));
449 221107366 : unsigned len_size = n * sizeof (unsigned short);
450 221107366 : return sizeof (irange_storage) + hwi_size + len_size;
451 : }
452 :
453 : // Return TRUE if R fits in the current storage.
454 :
455 : bool
456 306252753 : irange_storage::fits_p (const irange &r) const
457 : {
458 306252753 : 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 12194898 : frange_storage::alloc (vrange_internal_alloc &allocator, const frange &r)
514 : {
515 12194898 : size_t size = sizeof (frange_storage);
516 12194898 : frange_storage *p = static_cast <frange_storage *> (allocator.alloc (size));
517 12194898 : new (p) frange_storage (r);
518 12194898 : return p;
519 : }
520 :
521 : void
522 12813314 : frange_storage::set_frange (const frange &r)
523 : {
524 12813314 : gcc_checking_assert (fits_p (r));
525 :
526 12813314 : m_kind = r.m_kind;
527 12813314 : m_min = r.m_min;
528 12813314 : m_max = r.m_max;
529 12813314 : m_pos_nan = r.m_pos_nan;
530 12813314 : m_neg_nan = r.m_neg_nan;
531 12813314 : }
532 :
533 : void
534 45649916 : frange_storage::get_frange (frange &r, tree type) const
535 : {
536 45649916 : gcc_checking_assert (r.supports_type_p (type));
537 :
538 : // Handle explicit NANs.
539 45649916 : if (m_kind == VR_NAN)
540 : {
541 105217 : if (HONOR_NANS (type))
542 : {
543 105217 : if (m_pos_nan && m_neg_nan)
544 99671 : r.set_nan (type);
545 : else
546 5546 : r.set_nan (type, m_neg_nan);
547 : }
548 : else
549 0 : r.set_undefined ();
550 105217 : return;
551 : }
552 45544699 : if (m_kind == VR_UNDEFINED)
553 : {
554 54704 : r.set_undefined ();
555 54704 : 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 45489995 : 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 45489995 : if (HONOR_NANS (type) && (m_pos_nan ^ m_neg_nan) == 1)
569 1259116 : r.update_nan (m_neg_nan);
570 44230879 : else if (!m_pos_nan && !m_neg_nan)
571 11817657 : r.clear_nan ();
572 : }
573 :
574 : bool
575 19050 : frange_storage::equal_p (const frange &r) const
576 : {
577 19050 : if (r.undefined_p ())
578 0 : return m_kind == VR_UNDEFINED;
579 :
580 19050 : frange tmp;
581 19050 : get_frange (tmp, r.type ());
582 19050 : return tmp == r;
583 19050 : }
584 :
585 : bool
586 14049727 : frange_storage::fits_p (const frange &) const
587 : {
588 14049727 : return true;
589 : }
590 :
591 : //============================================================================
592 : // prange_storage implementation
593 : //============================================================================
594 :
595 : prange_storage *
596 94153786 : prange_storage::alloc (vrange_internal_alloc &allocator, const prange &r,
597 : bool shared_p)
598 : {
599 94153786 : unsigned num_words;
600 94153786 : prange_format (r, num_words);
601 94153786 : size_t extra_size = 0;
602 94153786 : if (num_words)
603 : {
604 2174694 : unsigned short precision = TYPE_PRECISION (r.type ());
605 2174694 : extra_size = trailing_wide_ints<PRANGE_STORAGE_NINTS>
606 2174694 : ::extra_size (precision, num_words);
607 : }
608 :
609 94153786 : size_t size = sizeof (prange_storage) + extra_size;
610 94153786 : prange_storage *p = static_cast <prange_storage *> (allocator.alloc (size));
611 94153786 : new (p) prange_storage (r);
612 94153786 : if (p->m_pt && !shared_p)
613 1907163 : p->m_pt = unshare_expr_without_location (p->m_pt);
614 :
615 94153786 : return p;
616 : }
617 :
618 : // Initialize the storage with R.
619 :
620 94153786 : prange_storage::prange_storage (const prange &r) : vrange_storage (VR_PRANGE)
621 : {
622 94153786 : unsigned num_words;
623 94153786 : enum prange_kind kind = prange_format (r, num_words);
624 94153786 : unsigned short prec = (kind == PR_UNDEFINED) ? 0 : TYPE_PRECISION (r.type ());
625 94153786 : m_trailing_ints.set_precision (prec, num_words);
626 94153786 : set_prange (r);
627 94153786 : }
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 291646786 : prange_storage::prange_format (const prange &r, unsigned &num_words)
634 : {
635 291646786 : num_words = 0;
636 291646786 : if (r.undefined_p ())
637 : return PR_UNDEFINED;
638 :
639 262956057 : if (r.varying_p ())
640 : return PR_VARYING;
641 :
642 123283017 : if (r.zero_p ())
643 : return PR_ZERO;
644 :
645 122583375 : enum prange_kind kind = PR_NONZERO;
646 :
647 122583375 : if (!r.nonzero_p ())
648 : {
649 2729549 : prange tmp (r.type ());
650 5459098 : if (r.lower_bound () == tmp.lower_bound ()
651 3969150 : && 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 2515058 : kind = PR_OTHER;
657 2515058 : num_words += 2;
658 : }
659 2729549 : }
660 :
661 : // Bitmasks require 2 words of storage.
662 122583375 : if (!r.get_bitmask ().unknown_p ())
663 4952787 : num_words += 2;
664 :
665 : // PR_FULL must have a bitmask or points to, or it should be PR_VARYING.
666 122797866 : gcc_checking_assert (kind != PR_FULL || !r.get_bitmask ().unknown_p ()
667 : || r.m_pt != NULL_TREE);
668 122583375 : return kind;
669 : }
670 :
671 : void
672 97222058 : prange_storage::set_prange (const prange &r)
673 : {
674 97222058 : unsigned num_words;
675 97222058 : m_kind = prange_format (r, num_words);
676 97222058 : m_has_bitmask = !r.get_bitmask ().unknown_p ();
677 97222058 : m_pt = r.m_pt;
678 97222058 : m_points_to_p = r.m_points_to_p;
679 :
680 97222058 : unsigned index = 0;
681 :
682 97222058 : switch (m_kind)
683 : {
684 56359453 : case PR_UNDEFINED:
685 56359453 : case PR_VARYING:
686 56359453 : case PR_ZERO:
687 56359453 : return;
688 : case PR_NONZERO:
689 : case PR_FULL:
690 : break;
691 779382 : case PR_OTHER:
692 779382 : set_word (index++, r.lower_bound (), r.type ());
693 779382 : set_word (index++, r.upper_bound (), r.type ());
694 779382 : break;
695 0 : default:
696 0 : gcc_unreachable ();
697 : }
698 :
699 40862605 : if (m_has_bitmask)
700 : {
701 1659088 : irange_bitmask bm = r.m_bitmask;
702 1659088 : set_word (index++, r.m_bitmask.value (), r.type ());
703 1659088 : set_word (index++, r.m_bitmask.mask (), r.type ());
704 1659088 : }
705 40862605 : gcc_checking_assert (index == num_words);
706 : }
707 :
708 : void
709 353392237 : prange_storage::get_prange (prange &r, tree type) const
710 : {
711 353392237 : gcc_checking_assert (r.supports_type_p (type));
712 353392237 : unsigned index = 0;
713 353392237 : switch (m_kind)
714 : {
715 924059 : case PR_UNDEFINED:
716 924059 : r.set_undefined ();
717 924059 : return;
718 :
719 197420505 : case PR_VARYING:
720 197420505 : r.set_varying (type);
721 197420505 : return;
722 :
723 657506 : case PR_ZERO:
724 657506 : r.set_zero (type);
725 657506 : return;
726 :
727 150990102 : case PR_NONZERO:
728 150990102 : r.set_nonzero (type);
729 150990102 : break;
730 :
731 523111 : case PR_FULL:
732 523111 : {
733 523111 : r.m_kind = VR_RANGE;
734 523111 : r.m_type = type;
735 523111 : prange tmp (type);
736 523111 : r.m_min = tmp.lower_bound ();
737 523111 : r.m_max = tmp.upper_bound ();
738 523111 : break;
739 523111 : }
740 :
741 2876954 : case PR_OTHER:
742 2876954 : {
743 2876954 : gcc_checking_assert (m_kind == PR_OTHER);
744 2876954 : r.m_kind = VR_RANGE;
745 2876954 : r.m_type = type;
746 2876954 : r.m_min = get_word (index++, type);
747 2876954 : r.m_max = get_word (index++, type);
748 2876954 : break;
749 : }
750 0 : default:
751 0 : gcc_unreachable ();
752 : }
753 :
754 154390167 : if (m_has_bitmask)
755 : {
756 16169948 : wide_int value = get_word (index++, type);
757 16169948 : wide_int mask = get_word (index++, type);
758 16169948 : r.m_bitmask = irange_bitmask (value, mask);
759 16169948 : }
760 : else
761 138220219 : r.m_bitmask.set_unknown (TYPE_PRECISION (type));
762 :
763 154390167 : r.m_points_to_p = m_points_to_p;
764 154390167 : r.m_pt = m_pt;
765 :
766 154390167 : if (flag_checking)
767 154390032 : r.verify_range ();
768 : }
769 :
770 : bool
771 13666433 : prange_storage::equal_p (const prange &r) const
772 : {
773 13666433 : if (r.undefined_p ())
774 0 : return m_kind == PR_UNDEFINED;
775 :
776 13666433 : unsigned index = 0;
777 13666433 : switch (m_kind)
778 : {
779 5465 : case PR_VARYING:
780 5465 : return r.varying_p ();
781 :
782 83377 : case PR_ZERO:
783 83377 : return r.zero_p ();
784 :
785 13240242 : case PR_NONZERO:
786 13240242 : if (!r.nonzero_p ())
787 : return false;
788 : break;
789 :
790 294078 : case PR_FULL:
791 294078 : if (r.m_min != wi::zero (TYPE_PRECISION (r.m_type))
792 587460 : || r.m_max != wi::max_value (TYPE_PRECISION (r.m_type),
793 146691 : TYPE_SIGN (r.m_type)))
794 : return false;
795 : break;
796 :
797 43271 : case PR_OTHER:
798 86542 : if (r.m_min != get_word (index++, r.m_type)
799 68466 : || 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 13018973 : if (m_has_bitmask)
808 : {
809 7598455 : wide_int value = get_word (index++, r.m_type);
810 7598455 : wide_int mask = get_word (index++, r.m_type);
811 7598455 : if (r.m_bitmask != irange_bitmask (value, mask))
812 3619928 : return false;
813 7598455 : }
814 : else
815 5420518 : if (!r.m_bitmask.unknown_p ())
816 : return false;
817 :
818 7936422 : if (m_pt != r.m_pt)
819 : return false;
820 1406306 : if (m_points_to_p != r.m_points_to_p)
821 : return false;
822 :
823 : return true;
824 : }
825 :
826 : bool
827 6128372 : 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 6128372 : if (r.undefined_p ())
832 : return true;
833 :
834 6117156 : unsigned num_words;
835 6117156 : prange_format (r, num_words);
836 6117156 : 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 19644436 : vrange_storage *ggc_alloc_vrange_storage (const vrange &r, bool shared_p)
848 : {
849 19644436 : return ggc_vrange_allocator.clone (r, shared_p);
850 : }
|