LCOV - code coverage report
Current view: top level - gcc - value-range-storage.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 87.6 % 402 352
Test Date: 2026-05-11 19:44:49 Functions: 83.0 % 47 39
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Support routines for vrange storage.
       2              :    Copyright (C) 2022-2026 Free Software Foundation, Inc.
       3              :    Contributed by Aldy Hernandez <aldyh@redhat.com>.
       4              : 
       5              : This file is part of GCC.
       6              : 
       7              : GCC is free software; you can redistribute it and/or modify
       8              : it under the terms of the GNU General Public License as published by
       9              : the Free Software Foundation; either version 3, or (at your option)
      10              : any later version.
      11              : 
      12              : GCC is distributed in the hope that it will be useful,
      13              : but WITHOUT ANY WARRANTY; without even the implied warranty of
      14              : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15              : GNU General Public License for more details.
      16              : 
      17              : You should have received a copy of the GNU General Public License
      18              : along with GCC; see the file COPYING3.  If not see
      19              : <http://www.gnu.org/licenses/>.  */
      20              : 
      21              : #include "config.h"
      22              : #include "system.h"
      23              : #include "coretypes.h"
      24              : #include "backend.h"
      25              : #include "tree.h"
      26              : #include "gimple.h"
      27              : #include "ssa.h"
      28              : #include "tree-pretty-print.h"
      29              : #include "fold-const.h"
      30              : #include "gimple-range.h"
      31              : #include "value-range-storage.h"
      32              : 
      33              : // Generic memory allocator to share one interface between GC and
      34              : // obstack allocators.
      35              : 
      36              : class vrange_internal_alloc
      37              : {
      38              : public:
      39    111376055 :   vrange_internal_alloc () { }
      40    111376043 :   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    111089139 :   vrange_obstack_alloc ()
      51    111089139 :   {
      52    111089139 :     obstack_init (&m_obstack);
      53    111089139 :   }
      54    111089127 :   virtual ~vrange_obstack_alloc () final override
      55    111089127 :   {
      56    111089127 :     obstack_free (&m_obstack, NULL);
      57    111089127 :   }
      58    379147250 :   virtual void *alloc (size_t size) final override
      59              :   {
      60    379147250 :     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       286916 :   vrange_ggc_alloc () { }
      71       286916 :   virtual ~vrange_ggc_alloc () final override { }
      72     17824140 :   virtual void *alloc (size_t size) final override
      73              :   {
      74     17824140 :     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    111376055 : vrange_allocator::vrange_allocator (bool gc)
      83              : {
      84    111376055 :   if (gc)
      85       286916 :     m_alloc = new vrange_ggc_alloc;
      86              :   else
      87    111089139 :     m_alloc = new vrange_obstack_alloc;
      88    111376055 : }
      89              : 
      90    111376043 : vrange_allocator::~vrange_allocator ()
      91              : {
      92    111376043 :   delete m_alloc;
      93    111376043 : }
      94              : 
      95              : void *
      96     54959460 : vrange_allocator::alloc (size_t size)
      97              : {
      98     54959460 :   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    287062613 : vrange_allocator::clone (const vrange &r)
     112              : {
     113    287062613 :   return vrange_storage::alloc (*m_alloc, r);
     114              : }
     115              : 
     116              : vrange_storage *
     117     27516934 : vrange_allocator::clone_varying (tree type)
     118              : {
     119     27516934 :   if (irange::supports_p (type))
     120     17553883 :     return irange_storage::alloc (*m_alloc, int_range <1> (type));
     121      9963051 :   if (prange::supports_p (type))
     122      9507593 :     return prange_storage::alloc (*m_alloc, prange (type));
     123       455458 :   if (frange::supports_p (type))
     124       455458 :     return frange_storage::alloc (*m_alloc, frange (type));
     125              :   return NULL;
     126              : }
     127              : 
     128              : vrange_storage *
     129     27432383 : vrange_allocator::clone_undefined (tree type)
     130              : {
     131     27432383 :   if (irange::supports_p (type))
     132     17474684 :     return irange_storage::alloc (*m_alloc, int_range<1> ());
     133      9957699 :   if (prange::supports_p (type))
     134      9506405 :     return prange_storage::alloc (*m_alloc, prange ());
     135       451294 :   if (frange::supports_p (type))
     136       451294 :     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    287062613 : vrange_storage::alloc (vrange_internal_alloc &allocator, const vrange &r)
     145              : {
     146    287062613 :   if (is_a <irange> (r))
     147    202408725 :     return irange_storage::alloc (allocator, as_a <irange> (r));
     148     84653888 :   if (is_a <prange> (r))
     149     73398631 :     return prange_storage::alloc (allocator, as_a <prange> (r));
     150     11255257 :   if (is_a <frange> (r))
     151     11255257 :     return frange_storage::alloc (allocator, as_a <frange> (r));
     152              :   return NULL;
     153              : }
     154              : 
     155              : // Set storage to R.
     156              : 
     157              : void
     158     24891329 : vrange_storage::set_vrange (const vrange &r)
     159              : {
     160     24891329 :   if (is_a <irange> (r))
     161              :     {
     162     21157218 :       irange_storage *s = static_cast <irange_storage *> (this);
     163     21157218 :       gcc_checking_assert (s->fits_p (as_a <irange> (r)));
     164     21157218 :       s->set_irange (as_a <irange> (r));
     165              :     }
     166      3734111 :   else if (is_a <prange> (r))
     167              :     {
     168      3115758 :       prange_storage *s = static_cast <prange_storage *> (this);
     169      3115758 :       gcc_checking_assert (s->fits_p (as_a <prange> (r)));
     170      3115758 :       s->set_prange (as_a <prange> (r));
     171              :     }
     172       618353 :   else if (is_a <frange> (r))
     173              :     {
     174       618353 :       frange_storage *s = static_cast <frange_storage *> (this);
     175       618353 :       gcc_checking_assert (s->fits_p (as_a <frange> (r)));
     176       618353 :       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     24891329 :   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     24891256 :       && !is_a <frange> (r)
     187     49164232 :       && !r.undefined_p ())
     188              :     {
     189     24154886 :       value_range tmp (r);
     190     24154886 :       get_vrange (tmp, r.type ());
     191     24154886 :       gcc_checking_assert (tmp == r);
     192     24154886 :     }
     193     24891329 : }
     194              : 
     195              : // Restore R from storage.
     196              : 
     197              : void
     198   1674734334 : vrange_storage::get_vrange (vrange &r, tree type) const
     199              : {
     200   1674734334 :   if (is_a <irange> (r))
     201              :     {
     202   1291161720 :       const irange_storage *s = static_cast <const irange_storage *> (this);
     203   1291161720 :       s->get_irange (as_a <irange> (r), type);
     204              :     }
     205    383572614 :   else if (is_a <prange> (r))
     206              :     {
     207    337979880 :       const prange_storage *s = static_cast <const prange_storage *> (this);
     208    337979880 :       s->get_prange (as_a <prange> (r), type);
     209              :     }
     210     45592734 :   else if (is_a <frange> (r))
     211              :     {
     212     45592734 :       const frange_storage *s = static_cast <const frange_storage *> (this);
     213     45592734 :       s->get_frange (as_a <frange> (r), type);
     214              :     }
     215              :   else
     216            0 :     gcc_unreachable ();
     217   1674734334 : }
     218              : 
     219              : // Return TRUE if storage can fit R.
     220              : 
     221              : bool
     222     28897841 : vrange_storage::fits_p (const vrange &r) const
     223              : {
     224     28897841 :   if (is_a <irange> (r))
     225              :     {
     226     25174485 :       const irange_storage *s = static_cast <const irange_storage *> (this);
     227     25174485 :       return s->fits_p (as_a <irange> (r));
     228              :     }
     229      3723356 :   if (is_a <prange> (r))
     230              :     {
     231      3105422 :       const prange_storage *s = static_cast <const prange_storage *> (this);
     232      3105422 :       return s->fits_p (as_a <prange> (r));
     233              :     }
     234       617934 :   if (is_a <frange> (r))
     235              :     {
     236       617934 :       const frange_storage *s = static_cast <const frange_storage *> (this);
     237       617934 :       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      9630754 : vrange_storage::equal_p (const vrange &r) const
     249              : {
     250      9630754 :   if (is_a <irange> (r))
     251              :     {
     252      4580012 :       const irange_storage *s = static_cast <const irange_storage *> (this);
     253      4580012 :       return s->equal_p (as_a <irange> (r));
     254              :     }
     255      5050742 :   if (is_a <prange> (r))
     256              :     {
     257      5031584 :       const prange_storage *s = static_cast <const prange_storage *> (this);
     258      5031584 :       return s->equal_p (as_a <prange> (r));
     259              :     }
     260        19158 :   if (is_a <frange> (r))
     261              :     {
     262        19158 :       const frange_storage *s = static_cast <const frange_storage *> (this);
     263        19158 :       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   1033948827 : irange_storage::write_lengths_address ()
     274              : {
     275   1033948827 :   return (unsigned short *)&m_val[(m_num_ranges * 2 + 2)
     276   1033948827 :                                   * WIDE_INT_MAX_HWIS (m_precision)];
     277              : }
     278              : 
     279              : const unsigned short *
     280    901254218 : irange_storage::lengths_address () const
     281              : {
     282    901254218 :   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    237437292 : irange_storage::alloc (vrange_internal_alloc &allocator, const irange &r)
     289              : {
     290    237437292 :   size_t size = irange_storage::size (r);
     291    237437292 :   irange_storage *p = static_cast <irange_storage *> (allocator.alloc (size));
     292    237437292 :   new (p) irange_storage (r);
     293    237437292 :   return p;
     294              : }
     295              : 
     296              : // Initialize the storage with R.
     297              : 
     298    237437292 : irange_storage::irange_storage (const irange &r)
     299    237437292 :   : m_max_ranges (r.num_pairs ())
     300              : {
     301    237437292 :   m_num_ranges = m_max_ranges;
     302    237437292 :   set_irange (r);
     303    237437292 : }
     304              : 
     305              : static inline void
     306    636551030 : write_wide_int (HOST_WIDE_INT *&val, unsigned short *&len, const wide_int &w)
     307              : {
     308    636551030 :   *len = w.get_len ();
     309   1273965809 :   for (unsigned i = 0; i < *len; ++i)
     310    637414779 :     *val++ = w.elt (i);
     311    636551030 :   ++len;
     312    636551030 : }
     313              : 
     314              : // Store R into the current storage.
     315              : 
     316              : void
     317    258594510 : irange_storage::set_irange (const irange &r)
     318              : {
     319    258594510 :   gcc_checking_assert (fits_p (r));
     320              : 
     321    258594510 :   if (r.undefined_p ())
     322              :     {
     323     17850977 :       m_kind = VR_UNDEFINED;
     324    125899901 :       return;
     325              :     }
     326    240743533 :   if (r.varying_p ())
     327              :     {
     328    108048924 :       m_kind = VR_VARYING;
     329    108048924 :       return;
     330              :     }
     331              : 
     332    132694609 :   m_precision = TYPE_PRECISION (r.type ());
     333    132694609 :   m_num_ranges = r.num_pairs ();
     334    132694609 :   m_kind = VR_RANGE;
     335              : 
     336    132694609 :   HOST_WIDE_INT *val = &m_val[0];
     337    132694609 :   unsigned short *len = write_lengths_address ();
     338              : 
     339    318275515 :   for (unsigned i = 0; i < r.num_pairs (); ++i)
     340              :     {
     341    185580906 :       write_wide_int (val, len, r.lower_bound (i));
     342    185583321 :       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    132694609 :   irange_bitmask bm = r.m_bitmask;
     347    132694609 :   write_wide_int (val, len, bm.value ());
     348    132694609 :   write_wide_int (val, len, bm.mask ());
     349    132694609 : }
     350              : 
     351              : static inline void
     352   4344527804 : read_wide_int (wide_int &w,
     353              :                const HOST_WIDE_INT *val, unsigned short len, unsigned prec)
     354              : {
     355   4344527804 :   trailing_wide_int_storage stow (prec, &len,
     356   1082721284 :                                   const_cast <HOST_WIDE_INT *> (val));
     357   3261806520 :   w = trailing_wide_int (stow);
     358              : }
     359              : 
     360              : // Restore a range of TYPE from storage into R.
     361              : 
     362              : void
     363   1295328765 : irange_storage::get_irange (irange &r, tree type) const
     364              : {
     365   1295328765 :   if (m_kind == VR_UNDEFINED)
     366              :     {
     367     10390254 :       r.set_undefined ();
     368    404464801 :       return;
     369              :     }
     370   1284938511 :   if (m_kind == VR_VARYING)
     371              :     {
     372    383684293 :       r.set_varying (type);
     373    383684293 :       return;
     374              :     }
     375              : 
     376    901254218 :   gcc_checking_assert (TYPE_PRECISION (type) == m_precision);
     377    901254218 :   const HOST_WIDE_INT *val = &m_val[0];
     378    901254218 :   const unsigned short *len = lengths_address ();
     379              : 
     380              :   // Handle the common case where R can fit the new range.
     381    901254218 :   if (r.m_max_ranges >= m_num_ranges)
     382              :     {
     383    870046980 :       r.m_kind = VR_RANGE;
     384    870046980 :       r.m_num_ranges = m_num_ranges;
     385    870046980 :       r.m_type = type;
     386   3049132216 :       for (unsigned i = 0; i < m_num_ranges * 2; ++i)
     387              :         {
     388   2179085236 :           read_wide_int (r.m_base[i], val, *len, m_precision);
     389   2179085236 :           val += *len++;
     390              :         }
     391              :     }
     392              :   // Otherwise build the range piecewise.
     393              :   else
     394              :     {
     395     31207238 :       r.set_undefined ();
     396    212674304 :       for (unsigned i = 0; i < m_num_ranges; ++i)
     397              :         {
     398    181467066 :           wide_int lb, ub;
     399    181467066 :           read_wide_int (lb, val, *len, m_precision);
     400    181467066 :           val += *len++;
     401    181467066 :           read_wide_int (ub, val, *len, m_precision);
     402    181467066 :           val += *len++;
     403    181467066 :           int_range<1> tmp (type, lb, ub);
     404    181467066 :           r.union_ (tmp);
     405    181467066 :         }
     406              :     }
     407              : 
     408    901254218 :   wide_int bits_value, bits_mask;
     409    901254218 :   read_wide_int (bits_value, val, *len, m_precision);
     410    901254218 :   val += *len++;
     411    901254218 :   read_wide_int (bits_mask, val, *len, m_precision);
     412    901254218 :   r.m_bitmask = irange_bitmask (bits_value, bits_mask);
     413    901254218 :   if (r.m_kind == VR_VARYING)
     414            0 :     r.m_kind = VR_RANGE;
     415              : 
     416    901254218 :   if (flag_checking)
     417    901250685 :     r.verify_range ();
     418    901261232 : }
     419              : 
     420              : bool
     421      4580012 : irange_storage::equal_p (const irange &r) const
     422              : {
     423      4580012 :   if (m_kind == VR_UNDEFINED || r.undefined_p ())
     424            0 :     return m_kind == r.m_kind;
     425      4580012 :   if (m_kind == VR_VARYING || r.varying_p ())
     426       412967 :     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      4167045 :   int_range_max tmp;
     431      4167045 :   get_irange (tmp, r.type ());
     432      4167045 :   return tmp == r;
     433      4167045 : }
     434              : 
     435              : // Return the size in bytes to allocate storage that can hold R.
     436              : 
     437              : size_t
     438    237437292 : irange_storage::size (const irange &r)
     439              : {
     440    237437292 :   if (r.undefined_p ())
     441              :     return sizeof (irange_storage);
     442              : 
     443    219698573 :   unsigned prec = TYPE_PRECISION (r.type ());
     444    219698573 :   unsigned n = r.num_pairs () * 2 + 2;
     445    219698573 :   unsigned hwi_size = ((n * WIDE_INT_MAX_HWIS (prec) - 1)
     446              :                        * sizeof (HOST_WIDE_INT));
     447    219698573 :   unsigned len_size = n * sizeof (unsigned short);
     448    219698573 :   return sizeof (irange_storage) + hwi_size + len_size;
     449              : }
     450              : 
     451              : // Return TRUE if R fits in the current storage.
     452              : 
     453              : bool
     454    304926213 : irange_storage::fits_p (const irange &r) const
     455              : {
     456    304926213 :   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     12162009 : frange_storage::alloc (vrange_internal_alloc &allocator, const frange &r)
     512              : {
     513     12162009 :   size_t size = sizeof (frange_storage);
     514     12162009 :   frange_storage *p = static_cast <frange_storage *> (allocator.alloc (size));
     515     12162009 :   new (p) frange_storage (r);
     516     12162009 :   return p;
     517              : }
     518              : 
     519              : void
     520     12780362 : frange_storage::set_frange (const frange &r)
     521              : {
     522     12780362 :   gcc_checking_assert (fits_p (r));
     523              : 
     524     12780362 :   m_kind = r.m_kind;
     525     12780362 :   m_min = r.m_min;
     526     12780362 :   m_max = r.m_max;
     527     12780362 :   m_pos_nan = r.m_pos_nan;
     528     12780362 :   m_neg_nan = r.m_neg_nan;
     529     12780362 : }
     530              : 
     531              : void
     532     45611892 : frange_storage::get_frange (frange &r, tree type) const
     533              : {
     534     45611892 :   gcc_checking_assert (r.supports_type_p (type));
     535              : 
     536              :   // Handle explicit NANs.
     537     45611892 :   if (m_kind == VR_NAN)
     538              :     {
     539       105682 :       if (HONOR_NANS (type))
     540              :         {
     541       105682 :           if (m_pos_nan && m_neg_nan)
     542       100146 :             r.set_nan (type);
     543              :           else
     544         5536 :             r.set_nan (type, m_neg_nan);
     545              :         }
     546              :       else
     547            0 :         r.set_undefined ();
     548       105682 :       return;
     549              :     }
     550     45506210 :   if (m_kind == VR_UNDEFINED)
     551              :     {
     552        67529 :       r.set_undefined ();
     553        67529 :       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     45438681 :   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     45438681 :   if (HONOR_NANS (type) && (m_pos_nan ^ m_neg_nan) == 1)
     567      1251886 :     r.update_nan (m_neg_nan);
     568     44186795 :   else if (!m_pos_nan && !m_neg_nan)
     569     11837105 :     r.clear_nan ();
     570              : }
     571              : 
     572              : bool
     573        19158 : frange_storage::equal_p (const frange &r) const
     574              : {
     575        19158 :   if (r.undefined_p ())
     576            0 :     return m_kind == VR_UNDEFINED;
     577              : 
     578        19158 :   frange tmp;
     579        19158 :   get_frange (tmp, r.type ());
     580        19158 :   return tmp == r;
     581        19158 : }
     582              : 
     583              : bool
     584     14016649 : frange_storage::fits_p (const frange &) const
     585              : {
     586     14016649 :   return true;
     587              : }
     588              : 
     589              : //============================================================================
     590              : // prange_storage implementation
     591              : //============================================================================
     592              : 
     593              : prange_storage *
     594     92412629 : prange_storage::alloc (vrange_internal_alloc &allocator, const prange &r)
     595              : {
     596     92412629 :   prange_format format (r);
     597     92412629 :   size_t size = sizeof (prange_storage) + format.extra_size;
     598     92412629 :   prange_storage *p = static_cast <prange_storage *> (allocator.alloc (size));
     599     92412629 :   new (p) prange_storage (r);
     600     92412629 :   return p;
     601              : }
     602              : 
     603              : // Initialize the storage with R.
     604              : 
     605     92412629 : prange_storage::prange_storage (const prange &r)
     606              : {
     607     92412629 :   prange_format format (r);
     608     92412629 :   m_trailing_ints.set_precision (format.precision, format.num_words);
     609     92412629 :   set_prange (r);
     610     92412629 : }
     611              : 
     612              : // FIll the format structure for range R.
     613              : 
     614    286563273 : prange_storage::prange_format::prange_format (const prange &r)
     615              : {
     616    286563273 :   kind = PR_UNDEFINED;
     617    286563273 :   has_bitmask = 0;
     618    286563273 :   extra_size = 0;
     619    286563273 :   precision = 0;
     620    286563273 :   num_words = 0;
     621              : 
     622    286563273 :   if (r.undefined_p ())
     623              :     return;
     624              : 
     625    257937668 :   if (r.varying_p ())
     626              :     {
     627    139308705 :       kind = PR_VARYING;
     628    139308705 :       return;
     629              :     }
     630              : 
     631    118628963 :   if (r.zero_p ())
     632              :     {
     633       710132 :       kind = PR_ZERO;
     634       710132 :       return;
     635              :     }
     636              : 
     637    117918831 :   if (r.nonzero_p ())
     638    115412168 :     kind = PR_NONZERO;
     639              :   else
     640              :     {
     641      2506663 :       prange tmp (r.type ());
     642      5013326 :       if (r.lower_bound () == tmp.lower_bound ()
     643      3588717 :           && r.upper_bound () == tmp.upper_bound ())
     644        65541 :         kind = PR_FULL;
     645              :       else
     646              :         {
     647              :           // PR_OTHER requires words of storage for the end points.
     648      2441122 :           kind = PR_OTHER;
     649      2441122 :           num_words += 2;
     650              :         }
     651      2506663 :     }
     652    117918831 :   precision = TYPE_PRECISION (r.type ());
     653    117918831 :   has_bitmask = !r.get_bitmask ().unknown_p ();
     654              : 
     655              :   // Bitmasks require 2 words of storage.
     656    117918831 :   if (has_bitmask)
     657      1439745 :     num_words += 2;
     658              : 
     659    117918831 :   if (num_words != 0)
     660      3457829 :     extra_size = trailing_wide_ints<NINTS>::extra_size (precision, num_words);
     661              : 
     662              :   // PR_FULL must have a bitmask, or it should be PR_VARYING.
     663    117918831 :   gcc_checking_assert (kind != PR_FULL || has_bitmask);
     664              : }
     665              : 
     666              : void
     667     95528387 : prange_storage::set_prange (const prange &r)
     668              : {
     669     95528387 :   prange_format format (r);
     670     95528387 :   m_kind = format.kind;
     671     95528387 :   m_has_bitmask = format.has_bitmask;
     672     95528387 :   unsigned index = 0;
     673              : 
     674     95528387 :   switch (m_kind)
     675              :     {
     676     56219910 :       case PR_UNDEFINED:
     677     56219910 :       case PR_VARYING:
     678     56219910 :       case PR_ZERO:
     679     56219910 :         return;
     680              :       case PR_NONZERO:
     681              :       case PR_FULL:
     682              :         break;
     683       755435 :       case PR_OTHER:
     684       755435 :         set_word (index++, r.lower_bound (), r.type ());
     685       755435 :         set_word (index++, r.upper_bound (), r.type ());
     686       755435 :         break;
     687            0 :       default:
     688            0 :         gcc_unreachable ();
     689              :     }
     690              : 
     691     39308477 :   if (m_has_bitmask)
     692              :     {
     693       488189 :       irange_bitmask bm = r.m_bitmask;
     694       488189 :       set_word (index++, r.m_bitmask.value (), r.type ());
     695       488189 :       set_word (index++, r.m_bitmask.mask (), r.type ());
     696       488189 :     }
     697     39308477 :    gcc_checking_assert (index == format.num_words);
     698              : }
     699              : 
     700              : void
     701    343011464 : prange_storage::get_prange (prange &r, tree type) const
     702              : {
     703    343011464 :   gcc_checking_assert (r.supports_type_p (type));
     704    343011464 :   unsigned index = 0;
     705    343011464 :   switch (m_kind)
     706              :     {
     707       963384 :       case PR_UNDEFINED:
     708       963384 :         r.set_undefined ();
     709       963384 :         return;
     710              : 
     711    193196797 :       case PR_VARYING:
     712    193196797 :         r.set_varying (type);
     713    193196797 :         return;
     714              : 
     715      1458709 :       case PR_ZERO:
     716      1458709 :         r.set_zero (type);
     717      1458709 :         return;
     718              : 
     719    144569487 :       case PR_NONZERO:
     720    144569487 :         r.set_nonzero (type);
     721    144569487 :         break;
     722              : 
     723       235960 :       case PR_FULL:
     724       235960 :         {
     725       235960 :           r.m_kind = VR_RANGE;
     726       235960 :           r.m_type = type;
     727       235960 :           prange tmp (type);
     728       235960 :           r.m_min = tmp.lower_bound ();
     729       235960 :           r.m_max = tmp.upper_bound ();
     730       235960 :           break;
     731       235960 :         }
     732              : 
     733      2587127 :       case PR_OTHER:
     734      2587127 :         {
     735      2587127 :           gcc_checking_assert (m_kind == PR_OTHER);
     736      2587127 :           r.m_kind = VR_RANGE;
     737      2587127 :           r.m_type = type;
     738      2587127 :           r.m_min = get_word (index++, type);
     739      2587127 :           r.m_max = get_word (index++, type);
     740      2587127 :           break;
     741              :         }
     742            0 :       default:
     743            0 :         gcc_unreachable ();
     744              :     }
     745              : 
     746    147392574 :   if (m_has_bitmask)
     747              :     {
     748     10876361 :       wide_int value = get_word (index++, type);
     749     10876361 :       wide_int mask = get_word (index++, type);
     750     10876361 :       r.m_bitmask = irange_bitmask (value, mask);
     751     10876361 :     }
     752              :   else
     753    136516213 :     r.m_bitmask.set_unknown (TYPE_PRECISION (type));
     754              : 
     755    147392574 :   if (flag_checking)
     756    147392436 :     r.verify_range ();
     757              : }
     758              : 
     759              : bool
     760      5031584 : prange_storage::equal_p (const prange &r) const
     761              : {
     762      5031584 :   if (r.undefined_p ())
     763            0 :     return m_kind == PR_UNDEFINED;
     764              : 
     765      5031584 :   prange tmp;
     766      5031584 :   get_prange (tmp, r.type ());
     767      5031584 :   return tmp == r;
     768      5031584 : }
     769              : 
     770              : bool
     771      6221180 : prange_storage::fits_p (const prange &r) const
     772              : {
     773              :   // Undefined ranges always fit, because they don't store anything in
     774              :   // the trailing wide ints.
     775      6221180 :   if (r.undefined_p ())
     776              :     return true;
     777              : 
     778      6209628 :   prange_format f (r);
     779      6209628 :   unsigned prec = m_trailing_ints.get_precision ();
     780      6209628 :   unsigned num = m_trailing_ints.num_elements ();
     781      6209628 :   size_t curr = num ? trailing_wide_ints<NINTS>::extra_size (prec, num) : 0;
     782      6209628 :   return f.extra_size <= curr;
     783              : }
     784              : 
     785              : 
     786              : static vrange_allocator ggc_vrange_allocator (true);
     787              : 
     788            0 : vrange_storage *ggc_alloc_vrange_storage (tree type)
     789              : {
     790            0 :   return ggc_vrange_allocator.clone_varying (type);
     791              : }
     792              : 
     793     17824140 : vrange_storage *ggc_alloc_vrange_storage (const vrange &r)
     794              : {
     795     17824140 :   return ggc_vrange_allocator.clone (r);
     796              : }
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.