Branch data Line data Source code
1 : : /* Support routines for vrange storage.
2 : : Copyright (C) 2022-2024 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 : 97686011 : vrange_internal_alloc () { }
40 : 97686002 : 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 : 97413825 : vrange_obstack_alloc ()
51 : 97413825 : {
52 : 97413825 : obstack_init (&m_obstack);
53 : 97413825 : }
54 : 97413816 : virtual ~vrange_obstack_alloc () final override
55 : 97413816 : {
56 : 97413816 : obstack_free (&m_obstack, NULL);
57 : 97413816 : }
58 : 328766105 : virtual void *alloc (size_t size) final override
59 : : {
60 : 328766105 : 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 : 272186 : vrange_ggc_alloc () { }
71 : 272186 : virtual ~vrange_ggc_alloc () final override { }
72 : 15304245 : virtual void *alloc (size_t size) final override
73 : : {
74 : 15304245 : 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 : 97686011 : vrange_allocator::vrange_allocator (bool gc)
83 : : {
84 : 97686011 : if (gc)
85 : 272186 : m_alloc = new vrange_ggc_alloc;
86 : : else
87 : 97413825 : m_alloc = new vrange_obstack_alloc;
88 : 97686011 : }
89 : :
90 : 97686002 : vrange_allocator::~vrange_allocator ()
91 : : {
92 : 97686002 : delete m_alloc;
93 : 97686002 : }
94 : :
95 : : void *
96 : 46129767 : vrange_allocator::alloc (size_t size)
97 : : {
98 : 46129767 : 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 : 251810816 : vrange_allocator::clone (const vrange &r)
112 : : {
113 : 251810816 : return vrange_storage::alloc (*m_alloc, r);
114 : : }
115 : :
116 : : vrange_storage *
117 : 23067876 : vrange_allocator::clone_varying (tree type)
118 : : {
119 : 23067876 : if (irange::supports_p (type))
120 : 14233876 : return irange_storage::alloc (*m_alloc, int_range <1> (type));
121 : 8834000 : if (prange::supports_p (type))
122 : 8446148 : return prange_storage::alloc (*m_alloc, prange (type));
123 : 387852 : if (frange::supports_p (type))
124 : 387852 : return frange_storage::alloc (*m_alloc, frange (type));
125 : : return NULL;
126 : : }
127 : :
128 : : vrange_storage *
129 : 23061891 : vrange_allocator::clone_undefined (tree type)
130 : : {
131 : 23061891 : if (irange::supports_p (type))
132 : 14229207 : return irange_storage::alloc (*m_alloc, int_range<1> ());
133 : 8832684 : if (prange::supports_p (type))
134 : 8445811 : return prange_storage::alloc (*m_alloc, prange ());
135 : 386873 : if (frange::supports_p (type))
136 : 386873 : 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 : 251810816 : vrange_storage::alloc (vrange_internal_alloc &allocator, const vrange &r)
145 : : {
146 : 251810816 : if (is_a <irange> (r))
147 : 170920777 : return irange_storage::alloc (allocator, as_a <irange> (r));
148 : 80890039 : if (is_a <prange> (r))
149 : 70825025 : return prange_storage::alloc (allocator, as_a <prange> (r));
150 : 10065014 : if (is_a <frange> (r))
151 : 10065014 : return frange_storage::alloc (allocator, as_a <frange> (r));
152 : : return NULL;
153 : : }
154 : :
155 : : // Set storage to R.
156 : :
157 : : void
158 : 19417359 : vrange_storage::set_vrange (const vrange &r)
159 : : {
160 : 19417359 : if (is_a <irange> (r))
161 : : {
162 : 16372366 : irange_storage *s = static_cast <irange_storage *> (this);
163 : 16372366 : gcc_checking_assert (s->fits_p (as_a <irange> (r)));
164 : 16372366 : s->set_irange (as_a <irange> (r));
165 : : }
166 : 3044993 : else if (is_a <prange> (r))
167 : : {
168 : 2624135 : prange_storage *s = static_cast <prange_storage *> (this);
169 : 2624135 : gcc_checking_assert (s->fits_p (as_a <prange> (r)));
170 : 2624135 : s->set_prange (as_a <prange> (r));
171 : : }
172 : 420858 : else if (is_a <frange> (r))
173 : : {
174 : 420858 : frange_storage *s = static_cast <frange_storage *> (this);
175 : 420858 : gcc_checking_assert (s->fits_p (as_a <frange> (r)));
176 : 420858 : 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 : 19417359 : 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 : 19417275 : && !is_a <frange> (r)
187 : 38413776 : && !r.undefined_p ())
188 : : {
189 : 18902910 : value_range tmp (r);
190 : 18902910 : get_vrange (tmp, r.type ());
191 : 18902910 : gcc_checking_assert (tmp == r);
192 : 18902910 : }
193 : 19417359 : }
194 : :
195 : : // Restore R from storage.
196 : :
197 : : void
198 : 1325179272 : vrange_storage::get_vrange (vrange &r, tree type) const
199 : : {
200 : 1325179272 : if (is_a <irange> (r))
201 : : {
202 : 1003181616 : const irange_storage *s = static_cast <const irange_storage *> (this);
203 : 1003181616 : s->get_irange (as_a <irange> (r), type);
204 : : }
205 : 321997656 : else if (is_a <prange> (r))
206 : : {
207 : 282497138 : const prange_storage *s = static_cast <const prange_storage *> (this);
208 : 282497138 : s->get_prange (as_a <prange> (r), type);
209 : : }
210 : 39500518 : else if (is_a <frange> (r))
211 : : {
212 : 39500518 : const frange_storage *s = static_cast <const frange_storage *> (this);
213 : 39500518 : s->get_frange (as_a <frange> (r), type);
214 : : }
215 : : else
216 : 0 : gcc_unreachable ();
217 : 1325179272 : }
218 : :
219 : : // Return TRUE if storage can fit R.
220 : :
221 : : bool
222 : 22877706 : vrange_storage::fits_p (const vrange &r) const
223 : : {
224 : 22877706 : if (is_a <irange> (r))
225 : : {
226 : 20024410 : const irange_storage *s = static_cast <const irange_storage *> (this);
227 : 20024410 : return s->fits_p (as_a <irange> (r));
228 : : }
229 : 2853296 : if (is_a <prange> (r))
230 : : {
231 : 2432438 : const prange_storage *s = static_cast <const prange_storage *> (this);
232 : 2432438 : return s->fits_p (as_a <prange> (r));
233 : : }
234 : 420858 : if (is_a <frange> (r))
235 : : {
236 : 420858 : const frange_storage *s = static_cast <const frange_storage *> (this);
237 : 420858 : 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 : 7168538 : vrange_storage::equal_p (const vrange &r) const
249 : : {
250 : 7168538 : if (is_a <irange> (r))
251 : : {
252 : 3543843 : const irange_storage *s = static_cast <const irange_storage *> (this);
253 : 3543843 : return s->equal_p (as_a <irange> (r));
254 : : }
255 : 3624695 : if (is_a <prange> (r))
256 : : {
257 : 3613779 : const prange_storage *s = static_cast <const prange_storage *> (this);
258 : 3613779 : return s->equal_p (as_a <prange> (r));
259 : : }
260 : 10916 : if (is_a <frange> (r))
261 : : {
262 : 10916 : const frange_storage *s = static_cast <const frange_storage *> (this);
263 : 10916 : 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 : 762080665 : irange_storage::write_lengths_address ()
274 : : {
275 : 762080665 : return (unsigned short *)&m_val[(m_num_ranges * 2 + 2)
276 : 762080665 : * WIDE_INT_MAX_HWIS (m_precision)];
277 : : }
278 : :
279 : : const unsigned short *
280 : 657667034 : irange_storage::lengths_address () const
281 : : {
282 : 657667034 : 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 : 199383860 : irange_storage::alloc (vrange_internal_alloc &allocator, const irange &r)
289 : : {
290 : 199383860 : size_t size = irange_storage::size (r);
291 : 199383860 : irange_storage *p = static_cast <irange_storage *> (allocator.alloc (size));
292 : 199383860 : new (p) irange_storage (r);
293 : 199383860 : return p;
294 : : }
295 : :
296 : : // Initialize the storage with R.
297 : :
298 : 199383860 : irange_storage::irange_storage (const irange &r)
299 : 199383860 : : m_max_ranges (r.num_pairs ())
300 : : {
301 : 199383860 : m_num_ranges = m_max_ranges;
302 : 199383860 : set_irange (r);
303 : 199383860 : }
304 : :
305 : : static inline void
306 : 478192388 : write_wide_int (HOST_WIDE_INT *&val, unsigned short *&len, const wide_int &w)
307 : : {
308 : 478192388 : *len = w.get_len ();
309 : 957287956 : for (unsigned i = 0; i < *len; ++i)
310 : 479095568 : *val++ = w.elt (i);
311 : 478192388 : ++len;
312 : 478192388 : }
313 : :
314 : : // Store R into the current storage.
315 : :
316 : : void
317 : 215756226 : irange_storage::set_irange (const irange &r)
318 : : {
319 : 215756226 : gcc_checking_assert (fits_p (r));
320 : :
321 : 215756226 : if (r.undefined_p ())
322 : : {
323 : 14528364 : m_kind = VR_UNDEFINED;
324 : 111342595 : return;
325 : : }
326 : 201227862 : if (r.varying_p ())
327 : : {
328 : 96814231 : m_kind = VR_VARYING;
329 : 96814231 : return;
330 : : }
331 : :
332 : 104413631 : m_precision = TYPE_PRECISION (r.type ());
333 : 104413631 : m_num_ranges = r.num_pairs ();
334 : 104413631 : m_kind = VR_RANGE;
335 : :
336 : 104413631 : HOST_WIDE_INT *val = &m_val[0];
337 : 104413631 : unsigned short *len = write_lengths_address ();
338 : :
339 : 239096194 : for (unsigned i = 0; i < r.num_pairs (); ++i)
340 : : {
341 : 134682563 : write_wide_int (val, len, r.lower_bound (i));
342 : 134684499 : 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 : 104413631 : irange_bitmask bm = r.m_bitmask;
347 : 104413631 : write_wide_int (val, len, bm.value ());
348 : 104413631 : write_wide_int (val, len, bm.mask ());
349 : 104413631 : }
350 : :
351 : : static inline void
352 : 3003201470 : read_wide_int (wide_int &w,
353 : : const HOST_WIDE_INT *val, unsigned short len, unsigned prec)
354 : : {
355 : 3003201470 : trailing_wide_int_storage stow (prec, &len,
356 : 737395970 : const_cast <HOST_WIDE_INT *> (val));
357 : 2265805500 : w = trailing_wide_int (stow);
358 : : }
359 : :
360 : : // Restore a range of TYPE from storage into R.
361 : :
362 : : void
363 : 1006450203 : irange_storage::get_irange (irange &r, tree type) const
364 : : {
365 : 1006450203 : if (m_kind == VR_UNDEFINED)
366 : : {
367 : 1453332 : r.set_undefined ();
368 : 350236501 : return;
369 : : }
370 : 1004996871 : if (m_kind == VR_VARYING)
371 : : {
372 : 347329837 : r.set_varying (type);
373 : 347329837 : return;
374 : : }
375 : :
376 : 657667034 : gcc_checking_assert (TYPE_PRECISION (type) == m_precision);
377 : 657667034 : const HOST_WIDE_INT *val = &m_val[0];
378 : 657667034 : const unsigned short *len = lengths_address ();
379 : :
380 : : // Handle the common case where R can fit the new range.
381 : 657667034 : if (r.m_max_ranges >= m_num_ranges)
382 : : {
383 : 643128212 : r.m_kind = VR_RANGE;
384 : 643128212 : r.m_num_ranges = m_num_ranges;
385 : 643128212 : r.m_type = type;
386 : 2171537742 : for (unsigned i = 0; i < m_num_ranges * 2; ++i)
387 : : {
388 : 1528409530 : read_wide_int (r.m_base[i], val, *len, m_precision);
389 : 1528409530 : val += *len++;
390 : : }
391 : : }
392 : : // Otherwise build the range piecewise.
393 : : else
394 : : {
395 : 14538822 : r.set_undefined ();
396 : 94267758 : for (unsigned i = 0; i < m_num_ranges; ++i)
397 : : {
398 : 79728936 : wide_int lb, ub;
399 : 79728936 : read_wide_int (lb, val, *len, m_precision);
400 : 79728936 : val += *len++;
401 : 79728936 : read_wide_int (ub, val, *len, m_precision);
402 : 79728936 : val += *len++;
403 : 79728936 : int_range<1> tmp (type, lb, ub);
404 : 79728936 : r.union_ (tmp);
405 : 79728936 : }
406 : : }
407 : :
408 : 657667034 : wide_int bits_value, bits_mask;
409 : 657667034 : read_wide_int (bits_value, val, *len, m_precision);
410 : 657667034 : val += *len++;
411 : 657667034 : read_wide_int (bits_mask, val, *len, m_precision);
412 : 657667034 : r.m_bitmask = irange_bitmask (bits_value, bits_mask);
413 : 657667034 : if (r.m_kind == VR_VARYING)
414 : 0 : r.m_kind = VR_RANGE;
415 : :
416 : 657667034 : if (flag_checking)
417 : 657663985 : r.verify_range ();
418 : 657672325 : }
419 : :
420 : : bool
421 : 3543843 : irange_storage::equal_p (const irange &r) const
422 : : {
423 : 3543843 : if (m_kind == VR_UNDEFINED || r.undefined_p ())
424 : 0 : return m_kind == r.m_kind;
425 : 3543843 : if (m_kind == VR_VARYING || r.varying_p ())
426 : 275256 : 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 : 3268587 : int_range_max tmp;
431 : 3268587 : get_irange (tmp, r.type ());
432 : 3268587 : return tmp == r;
433 : 3268587 : }
434 : :
435 : : // Return the size in bytes to allocate storage that can hold R.
436 : :
437 : : size_t
438 : 199383860 : irange_storage::size (const irange &r)
439 : : {
440 : 199383860 : if (r.undefined_p ())
441 : : return sizeof (irange_storage);
442 : :
443 : 184944168 : unsigned prec = TYPE_PRECISION (r.type ());
444 : 184944168 : unsigned n = r.num_pairs () * 2 + 2;
445 : 184944168 : unsigned hwi_size = ((n * WIDE_INT_MAX_HWIS (prec) - 1)
446 : : * sizeof (HOST_WIDE_INT));
447 : 184944168 : unsigned len_size = n * sizeof (unsigned short);
448 : 184944168 : return sizeof (irange_storage) + hwi_size + len_size;
449 : : }
450 : :
451 : : // Return TRUE if R fits in the current storage.
452 : :
453 : : bool
454 : 252153002 : irange_storage::fits_p (const irange &r) const
455 : : {
456 : 252153002 : 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 : 10839739 : frange_storage::alloc (vrange_internal_alloc &allocator, const frange &r)
512 : : {
513 : 10839739 : size_t size = sizeof (frange_storage);
514 : 10839739 : frange_storage *p = static_cast <frange_storage *> (allocator.alloc (size));
515 : 10839739 : new (p) frange_storage (r);
516 : 10839739 : return p;
517 : : }
518 : :
519 : : void
520 : 11260597 : frange_storage::set_frange (const frange &r)
521 : : {
522 : 11260597 : gcc_checking_assert (fits_p (r));
523 : :
524 : 11260597 : m_kind = r.m_kind;
525 : 11260597 : m_min = r.m_min;
526 : 11260597 : m_max = r.m_max;
527 : 11260597 : m_pos_nan = r.m_pos_nan;
528 : 11260597 : m_neg_nan = r.m_neg_nan;
529 : 11260597 : }
530 : :
531 : : void
532 : 39511434 : frange_storage::get_frange (frange &r, tree type) const
533 : : {
534 : 39511434 : gcc_checking_assert (r.supports_type_p (type));
535 : :
536 : : // Handle explicit NANs.
537 : 39511434 : if (m_kind == VR_NAN)
538 : : {
539 : 89425 : if (HONOR_NANS (type))
540 : : {
541 : 89425 : if (m_pos_nan && m_neg_nan)
542 : 85853 : r.set_nan (type);
543 : : else
544 : 3572 : r.set_nan (type, m_neg_nan);
545 : : }
546 : : else
547 : 0 : r.set_undefined ();
548 : 89425 : return;
549 : : }
550 : 39422009 : if (m_kind == VR_UNDEFINED)
551 : : {
552 : 57363 : r.set_undefined ();
553 : 57363 : 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 : 39364646 : 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 : 39364646 : if (HONOR_NANS (type) && (m_pos_nan ^ m_neg_nan) == 1)
567 : 1166114 : r.update_nan (m_neg_nan);
568 : 38198532 : else if (!m_pos_nan && !m_neg_nan)
569 : 4657966 : r.clear_nan ();
570 : : }
571 : :
572 : : bool
573 : 10916 : frange_storage::equal_p (const frange &r) const
574 : : {
575 : 10916 : if (r.undefined_p ())
576 : 0 : return m_kind == VR_UNDEFINED;
577 : :
578 : 10916 : frange tmp;
579 : 10916 : get_frange (tmp, r.type ());
580 : 10916 : return tmp == r;
581 : 10916 : }
582 : :
583 : : bool
584 : 12102313 : frange_storage::fits_p (const frange &) const
585 : : {
586 : 12102313 : return true;
587 : : }
588 : :
589 : : //============================================================================
590 : : // prange_storage implementation
591 : : //============================================================================
592 : :
593 : : prange_storage *
594 : 87716984 : prange_storage::alloc (vrange_internal_alloc &allocator, const prange &r)
595 : : {
596 : 87716984 : size_t size = sizeof (prange_storage);
597 : 87716984 : if (!r.undefined_p ())
598 : : {
599 : 79241544 : unsigned prec = TYPE_PRECISION (r.type ());
600 : 79241544 : size += trailing_wide_ints<NINTS>::extra_size (prec);
601 : : }
602 : 87716984 : prange_storage *p = static_cast <prange_storage *> (allocator.alloc (size));
603 : 87716984 : new (p) prange_storage (r);
604 : 87716984 : return p;
605 : : }
606 : :
607 : : // Initialize the storage with R.
608 : :
609 : 87716984 : 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 : 87716984 : if (r.undefined_p ())
614 : : // Undefined ranges do not require any extra space for trailing
615 : : // wide ints.
616 : 8475440 : m_trailing_ints.set_precision (0);
617 : : else
618 : 79241544 : m_trailing_ints.set_precision (TYPE_PRECISION (r.type ()));
619 : :
620 : 87716984 : set_prange (r);
621 : 87716984 : }
622 : :
623 : : void
624 : 90341119 : prange_storage::set_prange (const prange &r)
625 : : {
626 : 90341119 : if (r.undefined_p ())
627 : 8480292 : m_kind = VR_UNDEFINED;
628 : 81860827 : else if (r.varying_p ())
629 : 41023492 : m_kind = VR_VARYING;
630 : : else
631 : : {
632 : 40837335 : m_kind = VR_RANGE;
633 : 40837335 : set_low (r.lower_bound ());
634 : 40837335 : set_high (r.upper_bound ());
635 : 40837335 : irange_bitmask bm = r.m_bitmask;
636 : 40837335 : set_value (bm.value ());
637 : 40837335 : set_mask (bm.mask ());
638 : 40837335 : }
639 : 90341119 : }
640 : :
641 : : void
642 : 286110917 : prange_storage::get_prange (prange &r, tree type) const
643 : : {
644 : 286110917 : gcc_checking_assert (r.supports_type_p (type));
645 : :
646 : 286110917 : if (m_kind == VR_UNDEFINED)
647 : 194672 : r.set_undefined ();
648 : 285916245 : else if (m_kind == VR_VARYING)
649 : 162955326 : r.set_varying (type);
650 : : else
651 : : {
652 : 122960919 : gcc_checking_assert (m_kind == VR_RANGE);
653 : 122960919 : gcc_checking_assert (TYPE_PRECISION (type) == m_trailing_ints.get_precision ());
654 : 122960919 : r.m_kind = VR_RANGE;
655 : 122960919 : r.m_type = type;
656 : 122960919 : r.m_min = get_low ();
657 : 122960919 : r.m_max = get_high ();
658 : 122960919 : r.m_bitmask = irange_bitmask (get_value (), get_mask ());
659 : 122960919 : if (flag_checking)
660 : 122960814 : r.verify_range ();
661 : : }
662 : 286110917 : }
663 : :
664 : : bool
665 : 3613779 : prange_storage::equal_p (const prange &r) const
666 : : {
667 : 3613779 : if (r.undefined_p ())
668 : 0 : return m_kind == VR_UNDEFINED;
669 : :
670 : 3613779 : prange tmp;
671 : 3613779 : get_prange (tmp, r.type ());
672 : 3613779 : return tmp == r;
673 : 3613779 : }
674 : :
675 : : bool
676 : 5056573 : 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 : 5056573 : if (r.undefined_p ())
681 : : return true;
682 : :
683 : 5046869 : 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 : 15304245 : vrange_storage *ggc_alloc_vrange_storage (const vrange &r)
695 : : {
696 : 15304245 : return ggc_vrange_allocator.clone (r);
697 : : }
|