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 : 98507566 : vrange_internal_alloc () { }
40 : 98507557 : 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 : 98228504 : vrange_obstack_alloc ()
51 : 98228504 : {
52 : 98228504 : obstack_init (&m_obstack);
53 : 98228504 : }
54 : 98228495 : virtual ~vrange_obstack_alloc () final override
55 : 98228495 : {
56 : 98228495 : obstack_free (&m_obstack, NULL);
57 : 98228495 : }
58 : 333153974 : virtual void *alloc (size_t size) final override
59 : : {
60 : 333153974 : 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 : 279062 : vrange_ggc_alloc () { }
71 : 279062 : virtual ~vrange_ggc_alloc () final override { }
72 : 16175987 : virtual void *alloc (size_t size) final override
73 : : {
74 : 16175987 : 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 : 98507566 : vrange_allocator::vrange_allocator (bool gc)
83 : : {
84 : 98507566 : if (gc)
85 : 279062 : m_alloc = new vrange_ggc_alloc;
86 : : else
87 : 98228504 : m_alloc = new vrange_obstack_alloc;
88 : 98507566 : }
89 : :
90 : 98507557 : vrange_allocator::~vrange_allocator ()
91 : : {
92 : 98507557 : delete m_alloc;
93 : 98507557 : }
94 : :
95 : : void *
96 : 48110588 : vrange_allocator::alloc (size_t size)
97 : : {
98 : 48110588 : 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 : 253108785 : vrange_allocator::clone (const vrange &r)
112 : : {
113 : 253108785 : return vrange_storage::alloc (*m_alloc, r);
114 : : }
115 : :
116 : : vrange_storage *
117 : 24060934 : vrange_allocator::clone_varying (tree type)
118 : : {
119 : 24060934 : if (irange::supports_p (type))
120 : 15031190 : return irange_storage::alloc (*m_alloc, int_range <1> (type));
121 : 9029744 : if (prange::supports_p (type))
122 : 8619870 : return prange_storage::alloc (*m_alloc, prange (type));
123 : 409874 : if (frange::supports_p (type))
124 : 409874 : return frange_storage::alloc (*m_alloc, frange (type));
125 : : return NULL;
126 : : }
127 : :
128 : : vrange_storage *
129 : 24049654 : vrange_allocator::clone_undefined (tree type)
130 : : {
131 : 24049654 : if (irange::supports_p (type))
132 : 15023312 : return irange_storage::alloc (*m_alloc, int_range<1> ());
133 : 9026342 : if (prange::supports_p (type))
134 : 8619617 : return prange_storage::alloc (*m_alloc, prange ());
135 : 406725 : if (frange::supports_p (type))
136 : 406725 : 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 : 253108785 : vrange_storage::alloc (vrange_internal_alloc &allocator, const vrange &r)
145 : : {
146 : 253108785 : if (is_a <irange> (r))
147 : 177674044 : return irange_storage::alloc (allocator, as_a <irange> (r));
148 : 75434741 : if (is_a <prange> (r))
149 : 65105677 : return prange_storage::alloc (allocator, as_a <prange> (r));
150 : 10329064 : if (is_a <frange> (r))
151 : 10329064 : return frange_storage::alloc (allocator, as_a <frange> (r));
152 : : return NULL;
153 : : }
154 : :
155 : : // Set storage to R.
156 : :
157 : : void
158 : 20497908 : vrange_storage::set_vrange (const vrange &r)
159 : : {
160 : 20497908 : if (is_a <irange> (r))
161 : : {
162 : 17347513 : irange_storage *s = static_cast <irange_storage *> (this);
163 : 17347513 : gcc_checking_assert (s->fits_p (as_a <irange> (r)));
164 : 17347513 : s->set_irange (as_a <irange> (r));
165 : : }
166 : 3150395 : else if (is_a <prange> (r))
167 : : {
168 : 2700043 : prange_storage *s = static_cast <prange_storage *> (this);
169 : 2700043 : gcc_checking_assert (s->fits_p (as_a <prange> (r)));
170 : 2700043 : s->set_prange (as_a <prange> (r));
171 : : }
172 : 450352 : else if (is_a <frange> (r))
173 : : {
174 : 450352 : frange_storage *s = static_cast <frange_storage *> (this);
175 : 450352 : gcc_checking_assert (s->fits_p (as_a <frange> (r)));
176 : 450352 : 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 : 20497908 : 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 : 20497824 : && !is_a <frange> (r)
187 : 40545380 : && !r.undefined_p ())
188 : : {
189 : 19944348 : value_range tmp (r);
190 : 19944348 : get_vrange (tmp, r.type ());
191 : 19944348 : gcc_checking_assert (tmp == r);
192 : 19944348 : }
193 : 20497908 : }
194 : :
195 : : // Restore R from storage.
196 : :
197 : : void
198 : 1432948216 : vrange_storage::get_vrange (vrange &r, tree type) const
199 : : {
200 : 1432948216 : if (is_a <irange> (r))
201 : : {
202 : 1103286200 : const irange_storage *s = static_cast <const irange_storage *> (this);
203 : 1103286200 : s->get_irange (as_a <irange> (r), type);
204 : : }
205 : 329662016 : else if (is_a <prange> (r))
206 : : {
207 : 289609163 : const prange_storage *s = static_cast <const prange_storage *> (this);
208 : 289609163 : s->get_prange (as_a <prange> (r), type);
209 : : }
210 : 40052853 : else if (is_a <frange> (r))
211 : : {
212 : 40052853 : const frange_storage *s = static_cast <const frange_storage *> (this);
213 : 40052853 : s->get_frange (as_a <frange> (r), type);
214 : : }
215 : : else
216 : 0 : gcc_unreachable ();
217 : 1432948216 : }
218 : :
219 : : // Return TRUE if storage can fit R.
220 : :
221 : : bool
222 : 24027812 : vrange_storage::fits_p (const vrange &r) const
223 : : {
224 : 24027812 : if (is_a <irange> (r))
225 : : {
226 : 21069071 : const irange_storage *s = static_cast <const irange_storage *> (this);
227 : 21069071 : return s->fits_p (as_a <irange> (r));
228 : : }
229 : 2958741 : if (is_a <prange> (r))
230 : : {
231 : 2508389 : const prange_storage *s = static_cast <const prange_storage *> (this);
232 : 2508389 : return s->fits_p (as_a <prange> (r));
233 : : }
234 : 450352 : if (is_a <frange> (r))
235 : : {
236 : 450352 : const frange_storage *s = static_cast <const frange_storage *> (this);
237 : 450352 : 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 : 8376050 : vrange_storage::equal_p (const vrange &r) const
249 : : {
250 : 8376050 : if (is_a <irange> (r))
251 : : {
252 : 3861308 : const irange_storage *s = static_cast <const irange_storage *> (this);
253 : 3861308 : return s->equal_p (as_a <irange> (r));
254 : : }
255 : 4514742 : if (is_a <prange> (r))
256 : : {
257 : 4499979 : const prange_storage *s = static_cast <const prange_storage *> (this);
258 : 4499979 : return s->equal_p (as_a <prange> (r));
259 : : }
260 : 14763 : if (is_a <frange> (r))
261 : : {
262 : 14763 : const frange_storage *s = static_cast <const frange_storage *> (this);
263 : 14763 : 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 : 868783353 : irange_storage::write_lengths_address ()
274 : : {
275 : 868783353 : return (unsigned short *)&m_val[(m_num_ranges * 2 + 2)
276 : 868783353 : * WIDE_INT_MAX_HWIS (m_precision)];
277 : : }
278 : :
279 : : const unsigned short *
280 : 757262238 : irange_storage::lengths_address () const
281 : : {
282 : 757262238 : 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 : 207728546 : irange_storage::alloc (vrange_internal_alloc &allocator, const irange &r)
289 : : {
290 : 207728546 : size_t size = irange_storage::size (r);
291 : 207728546 : irange_storage *p = static_cast <irange_storage *> (allocator.alloc (size));
292 : 207728546 : new (p) irange_storage (r);
293 : 207728546 : return p;
294 : : }
295 : :
296 : : // Initialize the storage with R.
297 : :
298 : 207728546 : irange_storage::irange_storage (const irange &r)
299 : 207728546 : : m_max_ranges (r.num_pairs ())
300 : : {
301 : 207728546 : m_num_ranges = m_max_ranges;
302 : 207728546 : set_irange (r);
303 : 207728546 : }
304 : :
305 : : static inline void
306 : 507554122 : write_wide_int (HOST_WIDE_INT *&val, unsigned short *&len, const wide_int &w)
307 : : {
308 : 507554122 : *len = w.get_len ();
309 : 1016026463 : for (unsigned i = 0; i < *len; ++i)
310 : 508472341 : *val++ = w.elt (i);
311 : 507554122 : ++len;
312 : 507554122 : }
313 : :
314 : : // Store R into the current storage.
315 : :
316 : : void
317 : 225076059 : irange_storage::set_irange (const irange &r)
318 : : {
319 : 225076059 : gcc_checking_assert (fits_p (r));
320 : :
321 : 225076059 : if (r.undefined_p ())
322 : : {
323 : 15349859 : m_kind = VR_UNDEFINED;
324 : 113554944 : return;
325 : : }
326 : 209726200 : if (r.varying_p ())
327 : : {
328 : 98205085 : m_kind = VR_VARYING;
329 : 98205085 : return;
330 : : }
331 : :
332 : 111521115 : m_precision = TYPE_PRECISION (r.type ());
333 : 111521115 : m_num_ranges = r.num_pairs ();
334 : 111521115 : m_kind = VR_RANGE;
335 : :
336 : 111521115 : HOST_WIDE_INT *val = &m_val[0];
337 : 111521115 : unsigned short *len = write_lengths_address ();
338 : :
339 : 253777061 : for (unsigned i = 0; i < r.num_pairs (); ++i)
340 : : {
341 : 142255946 : write_wide_int (val, len, r.lower_bound (i));
342 : 142257887 : 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 : 111521115 : irange_bitmask bm = r.m_bitmask;
347 : 111521115 : write_wide_int (val, len, bm.value ());
348 : 111521115 : write_wide_int (val, len, bm.mask ());
349 : 111521115 : }
350 : :
351 : : static inline void
352 : 3429621716 : read_wide_int (wide_int &w,
353 : : const HOST_WIDE_INT *val, unsigned short len, unsigned prec)
354 : : {
355 : 3429621716 : trailing_wide_int_storage stow (prec, &len,
356 : 840349433 : const_cast <HOST_WIDE_INT *> (val));
357 : 2589272283 : w = trailing_wide_int (stow);
358 : : }
359 : :
360 : : // Restore a range of TYPE from storage into R.
361 : :
362 : : void
363 : 1106864687 : irange_storage::get_irange (irange &r, tree type) const
364 : : {
365 : 1106864687 : if (m_kind == VR_UNDEFINED)
366 : : {
367 : 1490870 : r.set_undefined ();
368 : 351093319 : return;
369 : : }
370 : 1105373817 : if (m_kind == VR_VARYING)
371 : : {
372 : 348111579 : r.set_varying (type);
373 : 348111579 : return;
374 : : }
375 : :
376 : 757262238 : gcc_checking_assert (TYPE_PRECISION (type) == m_precision);
377 : 757262238 : const HOST_WIDE_INT *val = &m_val[0];
378 : 757262238 : const unsigned short *len = lengths_address ();
379 : :
380 : : // Handle the common case where R can fit the new range.
381 : 757262238 : if (r.m_max_ranges >= m_num_ranges)
382 : : {
383 : 742076067 : r.m_kind = VR_RANGE;
384 : 742076067 : r.m_num_ranges = m_num_ranges;
385 : 742076067 : r.m_type = type;
386 : 2490998917 : for (unsigned i = 0; i < m_num_ranges * 2; ++i)
387 : : {
388 : 1748922850 : read_wide_int (r.m_base[i], val, *len, m_precision);
389 : 1748922850 : val += *len++;
390 : : }
391 : : }
392 : : // Otherwise build the range piecewise.
393 : : else
394 : : {
395 : 15186171 : r.set_undefined ();
396 : 98273366 : for (unsigned i = 0; i < m_num_ranges; ++i)
397 : : {
398 : 83087195 : wide_int lb, ub;
399 : 83087195 : read_wide_int (lb, val, *len, m_precision);
400 : 83087195 : val += *len++;
401 : 83087195 : read_wide_int (ub, val, *len, m_precision);
402 : 83087195 : val += *len++;
403 : 83087195 : int_range<1> tmp (type, lb, ub);
404 : 83087195 : r.union_ (tmp);
405 : 83087195 : }
406 : : }
407 : :
408 : 757262238 : wide_int bits_value, bits_mask;
409 : 757262238 : read_wide_int (bits_value, val, *len, m_precision);
410 : 757262238 : val += *len++;
411 : 757262238 : read_wide_int (bits_mask, val, *len, m_precision);
412 : 757262238 : r.m_bitmask = irange_bitmask (bits_value, bits_mask);
413 : 757262238 : if (r.m_kind == VR_VARYING)
414 : 0 : r.m_kind = VR_RANGE;
415 : :
416 : 757262238 : if (flag_checking)
417 : 757258588 : r.verify_range ();
418 : 757267608 : }
419 : :
420 : : bool
421 : 3861308 : irange_storage::equal_p (const irange &r) const
422 : : {
423 : 3861308 : if (m_kind == VR_UNDEFINED || r.undefined_p ())
424 : 0 : return m_kind == r.m_kind;
425 : 3861308 : if (m_kind == VR_VARYING || r.varying_p ())
426 : 282821 : 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 : 3578487 : int_range_max tmp;
431 : 3578487 : get_irange (tmp, r.type ());
432 : 3578487 : return tmp == r;
433 : 3578487 : }
434 : :
435 : : // Return the size in bytes to allocate storage that can hold R.
436 : :
437 : : size_t
438 : 207728546 : irange_storage::size (const irange &r)
439 : : {
440 : 207728546 : if (r.undefined_p ())
441 : : return sizeof (irange_storage);
442 : :
443 : 192476567 : unsigned prec = TYPE_PRECISION (r.type ());
444 : 192476567 : unsigned n = r.num_pairs () * 2 + 2;
445 : 192476567 : unsigned hwi_size = ((n * WIDE_INT_MAX_HWIS (prec) - 1)
446 : : * sizeof (HOST_WIDE_INT));
447 : 192476567 : unsigned len_size = n * sizeof (unsigned short);
448 : 192476567 : return sizeof (irange_storage) + hwi_size + len_size;
449 : : }
450 : :
451 : : // Return TRUE if R fits in the current storage.
452 : :
453 : : bool
454 : 263492643 : irange_storage::fits_p (const irange &r) const
455 : : {
456 : 263492643 : 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 : 11145663 : frange_storage::alloc (vrange_internal_alloc &allocator, const frange &r)
512 : : {
513 : 11145663 : size_t size = sizeof (frange_storage);
514 : 11145663 : frange_storage *p = static_cast <frange_storage *> (allocator.alloc (size));
515 : 11145663 : new (p) frange_storage (r);
516 : 11145663 : return p;
517 : : }
518 : :
519 : : void
520 : 11596015 : frange_storage::set_frange (const frange &r)
521 : : {
522 : 11596015 : gcc_checking_assert (fits_p (r));
523 : :
524 : 11596015 : m_kind = r.m_kind;
525 : 11596015 : m_min = r.m_min;
526 : 11596015 : m_max = r.m_max;
527 : 11596015 : m_pos_nan = r.m_pos_nan;
528 : 11596015 : m_neg_nan = r.m_neg_nan;
529 : 11596015 : }
530 : :
531 : : void
532 : 40067616 : frange_storage::get_frange (frange &r, tree type) const
533 : : {
534 : 40067616 : gcc_checking_assert (r.supports_type_p (type));
535 : :
536 : : // Handle explicit NANs.
537 : 40067616 : if (m_kind == VR_NAN)
538 : : {
539 : 90169 : if (HONOR_NANS (type))
540 : : {
541 : 90169 : if (m_pos_nan && m_neg_nan)
542 : 85655 : r.set_nan (type);
543 : : else
544 : 4514 : r.set_nan (type, m_neg_nan);
545 : : }
546 : : else
547 : 0 : r.set_undefined ();
548 : 90169 : return;
549 : : }
550 : 39977447 : if (m_kind == VR_UNDEFINED)
551 : : {
552 : 57666 : r.set_undefined ();
553 : 57666 : 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 : 39919781 : 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 : 39919781 : if (HONOR_NANS (type) && (m_pos_nan ^ m_neg_nan) == 1)
567 : 1165867 : r.update_nan (m_neg_nan);
568 : 38753914 : else if (!m_pos_nan && !m_neg_nan)
569 : 5066646 : r.clear_nan ();
570 : : }
571 : :
572 : : bool
573 : 14763 : frange_storage::equal_p (const frange &r) const
574 : : {
575 : 14763 : if (r.undefined_p ())
576 : 0 : return m_kind == VR_UNDEFINED;
577 : :
578 : 14763 : frange tmp;
579 : 14763 : get_frange (tmp, r.type ());
580 : 14763 : return tmp == r;
581 : 14763 : }
582 : :
583 : : bool
584 : 12496719 : frange_storage::fits_p (const frange &) const
585 : : {
586 : 12496719 : return true;
587 : : }
588 : :
589 : : //============================================================================
590 : : // prange_storage implementation
591 : : //============================================================================
592 : :
593 : : prange_storage *
594 : 82345164 : prange_storage::alloc (vrange_internal_alloc &allocator, const prange &r)
595 : : {
596 : 82345164 : size_t size = sizeof (prange_storage);
597 : 82345164 : if (!r.undefined_p ())
598 : : {
599 : 73694567 : unsigned prec = TYPE_PRECISION (r.type ());
600 : 73694567 : size += trailing_wide_ints<NINTS>::extra_size (prec);
601 : : }
602 : 82345164 : prange_storage *p = static_cast <prange_storage *> (allocator.alloc (size));
603 : 82345164 : new (p) prange_storage (r);
604 : 82345164 : return p;
605 : : }
606 : :
607 : : // Initialize the storage with R.
608 : :
609 : 82345164 : 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 : 82345164 : if (r.undefined_p ())
614 : : // Undefined ranges do not require any extra space for trailing
615 : : // wide ints.
616 : 8650597 : m_trailing_ints.set_precision (0);
617 : : else
618 : 73694567 : m_trailing_ints.set_precision (TYPE_PRECISION (r.type ()));
619 : :
620 : 82345164 : set_prange (r);
621 : 82345164 : }
622 : :
623 : : void
624 : 85045207 : prange_storage::set_prange (const prange &r)
625 : : {
626 : 85045207 : if (r.undefined_p ())
627 : 8655858 : m_kind = VR_UNDEFINED;
628 : 76389349 : else if (r.varying_p ())
629 : 41713325 : m_kind = VR_VARYING;
630 : : else
631 : : {
632 : 34676024 : m_kind = VR_RANGE;
633 : 34676024 : set_low (r.lower_bound ());
634 : 34676024 : set_high (r.upper_bound ());
635 : 34676024 : irange_bitmask bm = r.m_bitmask;
636 : 34676024 : set_value (bm.value ());
637 : 34676024 : set_mask (bm.mask ());
638 : 34676024 : }
639 : 85045207 : }
640 : :
641 : : void
642 : 294109142 : prange_storage::get_prange (prange &r, tree type) const
643 : : {
644 : 294109142 : gcc_checking_assert (r.supports_type_p (type));
645 : :
646 : 294109142 : if (m_kind == VR_UNDEFINED)
647 : 206421 : r.set_undefined ();
648 : 293902721 : else if (m_kind == VR_VARYING)
649 : 167962502 : r.set_varying (type);
650 : : else
651 : : {
652 : 125940219 : gcc_checking_assert (m_kind == VR_RANGE);
653 : 125940219 : gcc_checking_assert (TYPE_PRECISION (type) == m_trailing_ints.get_precision ());
654 : 125940219 : r.m_kind = VR_RANGE;
655 : 125940219 : r.m_type = type;
656 : 125940219 : r.m_min = get_low ();
657 : 125940219 : r.m_max = get_high ();
658 : 125940219 : r.m_bitmask = irange_bitmask (get_value (), get_mask ());
659 : 125940219 : if (flag_checking)
660 : 125940096 : r.verify_range ();
661 : : }
662 : 294109142 : }
663 : :
664 : : bool
665 : 4499979 : prange_storage::equal_p (const prange &r) const
666 : : {
667 : 4499979 : if (r.undefined_p ())
668 : 0 : return m_kind == VR_UNDEFINED;
669 : :
670 : 4499979 : prange tmp;
671 : 4499979 : get_prange (tmp, r.type ());
672 : 4499979 : return tmp == r;
673 : 4499979 : }
674 : :
675 : : bool
676 : 5208432 : 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 : 5208432 : if (r.undefined_p ())
681 : : return true;
682 : :
683 : 5197910 : 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 : 16175987 : vrange_storage *ggc_alloc_vrange_storage (const vrange &r)
695 : : {
696 : 16175987 : return ggc_vrange_allocator.clone (r);
697 : : }
|