LCOV - code coverage report
Current view: top level - gcc - value-range-storage.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 88.1 % 446 393
Test Date: 2026-10-17 16:30:31 Functions: 84.0 % 50 42
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 "gimplify.h"
      28              : #include "ssa.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     99519457 :   vrange_internal_alloc () { }
      40     99519445 :   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     99226091 :   vrange_obstack_alloc ()
      51     99226091 :   {
      52     99226091 :     obstack_init (&m_obstack);
      53     99226091 :   }
      54     99226079 :   virtual ~vrange_obstack_alloc () final override
      55     99226079 :   {
      56     99226079 :     obstack_free (&m_obstack, NULL);
      57     99226079 :   }
      58    426070394 :   virtual void *alloc (size_t size) final override
      59              :   {
      60    426070394 :     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       293366 :   vrange_ggc_alloc () { }
      71       293366 :   virtual ~vrange_ggc_alloc () final override { }
      72     21439282 :   virtual void *alloc (size_t size) final override
      73              :   {
      74     21439282 :     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     99519457 : vrange_allocator::vrange_allocator (bool gc)
      83              : {
      84     99519457 :   if (gc)
      85       293366 :     m_alloc = new vrange_ggc_alloc;
      86              :   else
      87     99226091 :     m_alloc = new vrange_obstack_alloc;
      88     99519457 : }
      89              : 
      90     99519445 : vrange_allocator::~vrange_allocator ()
      91              : {
      92     99519445 :   delete m_alloc;
      93     99519445 : }
      94              : 
      95              : void *
      96     59616766 : vrange_allocator::alloc (size_t size)
      97              : {
      98     59616766 :   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    328285729 : vrange_allocator::clone (const vrange &r, bool shared_p)
     112              : {
     113    328285729 :   return vrange_storage::alloc (*m_alloc, r, shared_p);
     114              : }
     115              : 
     116              : vrange_storage *
     117     29857920 : vrange_allocator::clone_varying (tree type)
     118              : {
     119     29857920 :   if (irange::supports_p (type))
     120     19643964 :     return irange_storage::alloc (*m_alloc, int_range <1> (type));
     121     10213956 :   if (prange::supports_p (type))
     122      9730645 :     return prange_storage::alloc (*m_alloc, prange (type));
     123       483311 :   if (frange::supports_p (type))
     124       483311 :     return frange_storage::alloc (*m_alloc, frange (type));
     125              :   return NULL;
     126              : }
     127              : 
     128              : vrange_storage *
     129     29749261 : vrange_allocator::clone_undefined (tree type)
     130              : {
     131     29749261 :   if (irange::supports_p (type))
     132     19541106 :     return irange_storage::alloc (*m_alloc, int_range<1> ());
     133     10208155 :   if (prange::supports_p (type))
     134      9729016 :     return prange_storage::alloc (*m_alloc, prange ());
     135       479139 :   if (frange::supports_p (type))
     136       479139 :     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    328285729 : vrange_storage::alloc (vrange_internal_alloc &allocator, const vrange &r,
     145              :                        bool shared_p)
     146              : {
     147    328285729 :   if (is_a <irange> (r))
     148    233049186 :     return irange_storage::alloc (allocator, as_a <irange> (r));
     149     95236543 :   if (is_a <prange> (r))
     150     83193466 :     return prange_storage::alloc (allocator, as_a <prange> (r), shared_p);
     151     12043077 :   if (is_a <frange> (r))
     152     12043077 :     return frange_storage::alloc (allocator, as_a <frange> (r));
     153              :   return NULL;
     154              : }
     155              : 
     156              : // Set storage to R.
     157              : 
     158              : void
     159     28289398 : vrange_storage::set_vrange (const vrange &r)
     160              : {
     161     28289398 :   if (is_a <irange> (r))
     162              :     {
     163     23885540 :       irange_storage *s = static_cast <irange_storage *> (this);
     164     23885540 :       gcc_checking_assert (s->fits_p (as_a <irange> (r)));
     165     23885540 :       s->set_irange (as_a <irange> (r));
     166              :     }
     167      4403858 :   else if (is_a <prange> (r))
     168              :     {
     169      3805313 :       prange_storage *s = static_cast <prange_storage *> (this);
     170      3805313 :       gcc_checking_assert (s->fits_p (as_a <prange> (r)));
     171      3805313 :       s->set_prange (as_a <prange> (r));
     172              :     }
     173       598545 :   else if (is_a <frange> (r))
     174              :     {
     175       598545 :       frange_storage *s = static_cast <frange_storage *> (this);
     176       598545 :       gcc_checking_assert (s->fits_p (as_a <frange> (r)));
     177       598545 :       s->set_frange (as_a <frange> (r));
     178              :     }
     179              :   else
     180            0 :     gcc_unreachable ();
     181              : 
     182              :   // Verify that reading back from the cache didn't drop bits.
     183     28289398 :   if (flag_checking
     184              :       // FIXME: Avoid checking frange, as it currently pessimizes some ranges:
     185              :       //
     186              :       // gfortran.dg/pr49472.f90 pessimizes [0.0, 1.0] into [-0.0, 1.0].
     187     28289330 :       && !is_a <frange> (r)
     188     55980183 :       && !r.undefined_p ())
     189              :     {
     190     27531020 :       value_range tmp (r);
     191     27531020 :       get_vrange (tmp, r.type ());
     192     27531020 :       gcc_checking_assert (tmp == r);
     193     27531020 :     }
     194     28289398 : }
     195              : 
     196              : // Restore R from storage.
     197              : 
     198              : void
     199   1900667016 : vrange_storage::get_vrange (vrange &r, tree type) const
     200              : {
     201   1900667016 :   if (is_a <irange> (r))
     202              :     {
     203   1462722462 :       const irange_storage *s = static_cast <const irange_storage *> (this);
     204   1462722462 :       s->get_irange (as_a <irange> (r), type);
     205              :     }
     206    437944554 :   else if (is_a <prange> (r))
     207              :     {
     208    389676249 :       const prange_storage *s = static_cast <const prange_storage *> (this);
     209    389676249 :       s->get_prange (as_a <prange> (r), type);
     210              :     }
     211     48268305 :   else if (is_a <frange> (r))
     212              :     {
     213     48268305 :       const frange_storage *s = static_cast <const frange_storage *> (this);
     214     48268305 :       s->get_frange (as_a <frange> (r), type);
     215              :     }
     216              :   else
     217            0 :     gcc_unreachable ();
     218   1900667016 : }
     219              : 
     220              : // Return TRUE if storage can fit R.
     221              : 
     222              : bool
     223     32683287 : vrange_storage::fits_p (const vrange &r) const
     224              : {
     225     32683287 :   if (is_a <irange> (r))
     226              :     {
     227     28199164 :       const irange_storage *s = static_cast <const irange_storage *> (this);
     228     28199164 :       return s->fits_p (as_a <irange> (r));
     229              :     }
     230      4484123 :   if (is_a <prange> (r))
     231              :     {
     232      3836969 :       const prange_storage *s = static_cast <const prange_storage *> (this);
     233      3836969 :       return s->fits_p (as_a <prange> (r));
     234              :     }
     235       647154 :   if (is_a <frange> (r))
     236              :     {
     237       647154 :       const frange_storage *s = static_cast <const frange_storage *> (this);
     238       647154 :       return s->fits_p (as_a <frange> (r));
     239              :     }
     240            0 :   gcc_unreachable ();
     241              :   return false;
     242              : }
     243              : 
     244              : // Return TRUE if the range in storage is equal to R.  It is the
     245              : // caller's responsibility to verify that the type of the range in
     246              : // storage matches that of R.
     247              : 
     248              : bool
     249     19183364 : vrange_storage::equal_p (const vrange &r) const
     250              : {
     251     19183364 :   if (is_a <irange> (r))
     252              :     {
     253      3818578 :       const irange_storage *s = static_cast <const irange_storage *> (this);
     254      3818578 :       return s->equal_p (as_a <irange> (r));
     255              :     }
     256     15364786 :   if (is_a <prange> (r))
     257              :     {
     258     15344387 :       const prange_storage *s = static_cast <const prange_storage *> (this);
     259     15344387 :       return s->equal_p (as_a <prange> (r));
     260              :     }
     261        20399 :   if (is_a <frange> (r))
     262              :     {
     263        20399 :       const frange_storage *s = static_cast <const frange_storage *> (this);
     264        20399 :       return s->equal_p (as_a <frange> (r));
     265              :     }
     266            0 :   gcc_unreachable ();
     267              : }
     268              : 
     269              : //============================================================================
     270              : // irange_storage implementation
     271              : //============================================================================
     272              : 
     273              : unsigned short *
     274   1165714010 : irange_storage::write_lengths_address ()
     275              : {
     276   1165714010 :   return (unsigned short *)&m_val[(m_num_ranges * 2 + 2)
     277   1165714010 :                                   * WIDE_INT_MAX_HWIS (m_precision)];
     278              : }
     279              : 
     280              : const unsigned short *
     281   1010454367 : irange_storage::lengths_address () const
     282              : {
     283   1010454367 :   return const_cast <irange_storage *> (this)->write_lengths_address ();
     284              : }
     285              : 
     286              : // Allocate a new irange_storage object initialized to R.
     287              : 
     288              : irange_storage *
     289    272234256 : irange_storage::alloc (vrange_internal_alloc &allocator, const irange &r)
     290              : {
     291    272234256 :   size_t size = irange_storage::size (r);
     292    272234256 :   irange_storage *p = static_cast <irange_storage *> (allocator.alloc (size));
     293    272234256 :   new (p) irange_storage (r);
     294    272234256 :   return p;
     295              : }
     296              : 
     297              : // Initialize the storage with R.
     298              : 
     299    272234256 : irange_storage::irange_storage (const irange &r)
     300    272234256 :   : vrange_storage (VR_IRANGE), m_max_ranges (r.num_pairs ())
     301              : {
     302    272234256 :   m_num_ranges = m_max_ranges;
     303    272234256 :   set_irange (r);
     304    272234256 : }
     305              : 
     306              : static inline void
     307    744606538 : write_wide_int (HOST_WIDE_INT *&val, unsigned short *&len, const wide_int &w)
     308              : {
     309    744606538 :   *len = w.get_len ();
     310   1490569884 :   for (unsigned i = 0; i < *len; ++i)
     311    745963346 :     *val++ = w.elt (i);
     312    744606538 :   ++len;
     313    744606538 : }
     314              : 
     315              : // Store R into the current storage.
     316              : 
     317              : void
     318    296119796 : irange_storage::set_irange (const irange &r)
     319              : {
     320    296119796 :   gcc_checking_assert (fits_p (r));
     321              : 
     322    296119796 :   if (r.undefined_p ())
     323              :     {
     324     19986118 :       m_kind = VR_UNDEFINED;
     325    140860153 :       return;
     326              :     }
     327    276133678 :   if (r.varying_p ())
     328              :     {
     329    120874035 :       m_kind = VR_VARYING;
     330    120874035 :       return;
     331              :     }
     332              : 
     333    155259643 :   m_precision = TYPE_PRECISION (r.type ());
     334    155259643 :   m_num_ranges = r.num_pairs ();
     335    155259643 :   m_kind = VR_RANGE;
     336              : 
     337    155259643 :   HOST_WIDE_INT *val = &m_val[0];
     338    155259643 :   unsigned short *len = write_lengths_address ();
     339              : 
     340    372303269 :   for (unsigned i = 0; i < r.num_pairs (); ++i)
     341              :     {
     342    217043626 :       write_wide_int (val, len, r.lower_bound (i));
     343    217046441 :       write_wide_int (val, len, r.upper_bound (i));
     344              :     }
     345              : 
     346              :   // TODO: We could avoid streaming out the value if the mask is -1.
     347    155259643 :   irange_bitmask bm = r.m_bitmask;
     348    155259643 :   write_wide_int (val, len, bm.value ());
     349    155259643 :   write_wide_int (val, len, bm.mask ());
     350    155259643 : }
     351              : 
     352              : static inline void
     353   4918079088 : read_wide_int (wide_int &w,
     354              :                const HOST_WIDE_INT *val, unsigned short len, unsigned prec)
     355              : {
     356   4918079088 :   trailing_wide_int_storage stow (prec, &len,
     357   1218783758 :                                   const_cast <HOST_WIDE_INT *> (val));
     358   3699295330 :   w = trailing_wide_int (stow);
     359              : }
     360              : 
     361              : // Restore a range of TYPE from storage into R.
     362              : 
     363              : void
     364   1466090583 : irange_storage::get_irange (irange &r, tree type) const
     365              : {
     366   1466090583 :   if (m_kind == VR_UNDEFINED)
     367              :     {
     368     10120850 :       r.set_undefined ();
     369    465757066 :       return;
     370              :     }
     371   1455969733 :   if (m_kind == VR_VARYING)
     372              :     {
     373    445515366 :       r.set_varying (type);
     374    445515366 :       return;
     375              :     }
     376              : 
     377   1010454367 :   gcc_checking_assert (TYPE_PRECISION (type) == m_precision);
     378   1010454367 :   const HOST_WIDE_INT *val = &m_val[0];
     379   1010454367 :   const unsigned short *len = lengths_address ();
     380              : 
     381              :   // Handle the common case where R can fit the new range.
     382   1010454367 :   if (r.m_max_ranges >= m_num_ranges)
     383              :     {
     384    975639806 :       r.m_kind = VR_RANGE;
     385    975639806 :       r.m_num_ranges = m_num_ranges;
     386    975639806 :       r.m_type = type;
     387   3456151378 :       for (unsigned i = 0; i < m_num_ranges * 2; ++i)
     388              :         {
     389   2480511572 :           read_wide_int (r.m_base[i], val, *len, m_precision);
     390   2480511572 :           val += *len++;
     391              :         }
     392              :     }
     393              :   // Otherwise build the range piecewise.
     394              :   else
     395              :     {
     396     34814561 :       r.set_undefined ();
     397    277958513 :       for (unsigned i = 0; i < m_num_ranges; ++i)
     398              :         {
     399    208329391 :           wide_int lb, ub;
     400    208329391 :           read_wide_int (lb, val, *len, m_precision);
     401    208329391 :           val += *len++;
     402    208329391 :           read_wide_int (ub, val, *len, m_precision);
     403    208329391 :           val += *len++;
     404    208329391 :           int_range<1> tmp (type, lb, ub);
     405    208329391 :           r.union_ (tmp);
     406    208920083 :         }
     407              :     }
     408              : 
     409   1010454367 :   wide_int bits_value, bits_mask;
     410   1010454367 :   read_wide_int (bits_value, val, *len, m_precision);
     411   1010454367 :   val += *len++;
     412   1010454367 :   read_wide_int (bits_mask, val, *len, m_precision);
     413   1010454367 :   r.m_bitmask = irange_bitmask (bits_value, bits_mask);
     414   1010454367 :   if (r.m_kind == VR_VARYING)
     415            0 :     r.m_kind = VR_RANGE;
     416              : 
     417   1010454367 :   if (flag_checking)
     418   1010450963 :     r.verify_range ();
     419   1010527602 : }
     420              : 
     421              : bool
     422      3818578 : irange_storage::equal_p (const irange &r) const
     423              : {
     424      3818578 :   if (m_kind == VR_UNDEFINED || r.undefined_p ())
     425            0 :     return m_kind == r.m_kind;
     426      3818578 :   if (m_kind == VR_VARYING || r.varying_p ())
     427       450457 :     return m_kind == r.m_kind;
     428              : 
     429              :   // ?? We could make this faster by doing the comparison in place,
     430              :   // without going through get_irange.
     431      3368121 :   int_range_max tmp;
     432      3368121 :   get_irange (tmp, r.type ());
     433      3368121 :   return tmp == r;
     434      3368121 : }
     435              : 
     436              : // Return the size in bytes to allocate storage that can hold R.
     437              : 
     438              : size_t
     439    272234256 : irange_storage::size (const irange &r)
     440              : {
     441    272234256 :   if (r.undefined_p ())
     442              :     return sizeof (irange_storage);
     443              : 
     444    252399547 :   unsigned prec = TYPE_PRECISION (r.type ());
     445    252399547 :   unsigned n = r.num_pairs () * 2 + 2;
     446    252399547 :   unsigned hwi_size = ((n * WIDE_INT_MAX_HWIS (prec) - 1)
     447              :                        * sizeof (HOST_WIDE_INT));
     448    252399547 :   unsigned len_size = n * sizeof (unsigned short);
     449    252399547 :   return sizeof (irange_storage) + hwi_size + len_size;
     450              : }
     451              : 
     452              : // Return TRUE if R fits in the current storage.
     453              : 
     454              : bool
     455    348204500 : irange_storage::fits_p (const irange &r) const
     456              : {
     457    348204500 :   return m_max_ranges >= r.num_pairs ();
     458              : }
     459              : 
     460              : void
     461            0 : irange_storage::dump () const
     462              : {
     463            0 :   fprintf (stderr, "irange_storage (prec=%d, ranges=%d):\n",
     464            0 :            m_precision, m_num_ranges);
     465              : 
     466            0 :   if (m_num_ranges == 0)
     467              :     return;
     468              : 
     469            0 :   const HOST_WIDE_INT *val = &m_val[0];
     470            0 :   const unsigned short *len = lengths_address ();
     471            0 :   int i, j;
     472              : 
     473            0 :   fprintf (stderr, "  lengths = [ ");
     474            0 :   for (i = 0; i < m_num_ranges * 2 + 2; ++i)
     475            0 :     fprintf (stderr, "%d ", len[i]);
     476            0 :   fprintf (stderr, "]\n");
     477              : 
     478            0 :   for (i = 0; i < m_num_ranges; ++i)
     479              :     {
     480            0 :       for (j = 0; j < *len; ++j)
     481            0 :         fprintf (stderr, "  [PAIR %d] LB " HOST_WIDE_INT_PRINT_DEC "\n", i,
     482            0 :                  *val++);
     483            0 :       ++len;
     484            0 :       for (j = 0; j < *len; ++j)
     485            0 :         fprintf (stderr, "  [PAIR %d] UB " HOST_WIDE_INT_PRINT_DEC "\n", i,
     486            0 :                  *val++);
     487            0 :       ++len;
     488              :     }
     489              : 
     490              :   // Dump value/mask pair.
     491            0 :   for (j = 0; j < *len; ++j)
     492            0 :     fprintf (stderr, "  [VALUE] " HOST_WIDE_INT_PRINT_DEC "\n", *val++);
     493            0 :   ++len;
     494            0 :   for (j = 0; j < *len; ++j)
     495            0 :     fprintf (stderr, "  [MASK] " HOST_WIDE_INT_PRINT_DEC "\n", *val++);
     496              : }
     497              : 
     498              : DEBUG_FUNCTION void
     499            0 : debug (const irange_storage &storage)
     500              : {
     501            0 :   storage.dump ();
     502            0 :   fprintf (stderr, "\n");
     503            0 : }
     504              : 
     505              : //============================================================================
     506              : // frange_storage implementation
     507              : //============================================================================
     508              : 
     509              : // Return the number of bytes to allocate for an frange_storage holding R.
     510              : 
     511              : size_t
     512     13005527 : frange_storage::size (const frange &r)
     513              : {
     514     13005527 :   return sizeof (frange_storage) + (r.num_pairs () - 1) * sizeof (frange_pair);
     515              : }
     516              : 
     517              : // Allocate a new frange_storage object initialized to R.
     518              : 
     519              : frange_storage *
     520     13005527 : frange_storage::alloc (vrange_internal_alloc &allocator, const frange &r)
     521              : {
     522     13005527 :   frange_storage *p
     523     13005527 :     = static_cast <frange_storage *> (allocator.alloc (size (r)));
     524     13005527 :   new (p) frange_storage (r);
     525     13005527 :   return p;
     526              : }
     527              : 
     528     13005527 : frange_storage::frange_storage (const frange &r)
     529     13005527 :   : vrange_storage (VR_FRANGE), m_max_ranges (r.num_pairs ())
     530              : {
     531     13005527 :   set_frange (r);
     532     13005527 : }
     533              : 
     534              : void
     535     13604072 : frange_storage::set_frange (const frange &r)
     536              : {
     537     13604072 :   gcc_checking_assert (fits_p (r));
     538              : 
     539     13604072 :   m_kind = r.m_kind;
     540     13604072 :   m_num_ranges = r.m_num_ranges;
     541     27698728 :   for (unsigned i = 0; i < r.m_num_ranges; ++i)
     542     14094656 :     m_pairs[i] = r.m_pairs[i];
     543     13604072 :   m_pos_nan = r.m_pos_nan;
     544     13604072 :   m_neg_nan = r.m_neg_nan;
     545     13604072 : }
     546              : 
     547              : void
     548     48288704 : frange_storage::get_frange (frange &r, tree type) const
     549              : {
     550     48288704 :   gcc_checking_assert (r.supports_type_p (type));
     551              : 
     552              :   // Handle explicit NANs.
     553     48288704 :   if (m_kind == VR_NAN)
     554              :     {
     555       113687 :       if (HONOR_NANS (type))
     556              :         {
     557       113687 :           if (m_pos_nan && m_neg_nan)
     558       107671 :             r.set_nan (type);
     559              :           else
     560         6016 :             r.set_nan (type, m_neg_nan);
     561              :         }
     562              :       else
     563            0 :         r.set_undefined ();
     564              :       return;
     565              :     }
     566     48175017 :   if (m_kind == VR_UNDEFINED)
     567              :     {
     568        62120 :       r.set_undefined ();
     569        62120 :       return;
     570              :     }
     571     48112897 :   if (m_kind == VR_VARYING)
     572              :     {
     573     33889379 :       r.set_varying (type);
     574     33889379 :       return;
     575              :     }
     576              : 
     577              :   // Rebuild piecewise, like irange_storage::get_irange().
     578     14223518 :   r.set_undefined ();
     579     44299150 :   for (unsigned i = 0; i < m_num_ranges; ++i)
     580              :     {
     581     15852114 :       frange tmp (type, m_pairs[i].min, m_pairs[i].max, m_kind);
     582     15852114 :       r.union_ (tmp);
     583     15852114 :     }
     584              : 
     585              :   // The constructor will set the NAN bits for HONOR_NANS, but we must
     586              :   // make sure to set the NAN sign if known.
     587     14223518 :   if (HONOR_NANS (type) && (m_pos_nan ^ m_neg_nan) == 1)
     588      1367909 :     r.update_nan (m_neg_nan);
     589     12855609 :   else if (!m_pos_nan && !m_neg_nan)
     590     10350898 :     r.clear_nan ();
     591              : }
     592              : 
     593              : bool
     594        20399 : frange_storage::equal_p (const frange &r) const
     595              : {
     596        20399 :   if (r.undefined_p ())
     597            0 :     return m_kind == VR_UNDEFINED;
     598              : 
     599        20399 :   frange tmp;
     600        20399 :   get_frange (tmp, r.type ());
     601        20399 :   return tmp == r;
     602        20399 : }
     603              : 
     604              : bool
     605     14849771 : frange_storage::fits_p (const frange &r) const
     606              : {
     607     14849771 :   return m_max_ranges >= r.num_pairs ();
     608              : }
     609              : 
     610              : //============================================================================
     611              : // prange_storage implementation
     612              : //============================================================================
     613              : 
     614              : prange_storage *
     615    102653127 : prange_storage::alloc (vrange_internal_alloc &allocator, const prange &r,
     616              :                        bool shared_p)
     617              : {
     618    102653127 :   unsigned num_words;
     619    102653127 :   prange_format (r, num_words);
     620    102653127 :   size_t extra_size = 0;
     621    102653127 :   if (num_words)
     622              :     {
     623      2432684 :       unsigned short precision = TYPE_PRECISION (r.type ());
     624      2432684 :       extra_size = trailing_wide_ints<PRANGE_STORAGE_NINTS>
     625      2432684 :                      ::extra_size (precision, num_words);
     626              :     }
     627              : 
     628    102653127 :   size_t size = sizeof (prange_storage) + extra_size;
     629    102653127 :   prange_storage *p = static_cast <prange_storage *> (allocator.alloc (size));
     630    102653127 :   new (p) prange_storage (r);
     631    102653127 :   if (p->m_pt && !shared_p)
     632      2093333 :     p->m_pt = unshare_expr_without_location (p->m_pt);
     633              : 
     634    102653127 :   return p;
     635              : }
     636              : 
     637              : // Initialize the storage with R.
     638              : 
     639    102653127 : prange_storage::prange_storage (const prange &r) : vrange_storage (VR_PRANGE)
     640              : {
     641    102653127 :   unsigned num_words;
     642    102653127 :   enum prange_kind kind = prange_format (r, num_words);
     643    102653127 :   unsigned short prec = (kind == PR_UNDEFINED) ? 0 : TYPE_PRECISION (r.type ());
     644    102653127 :   m_trailing_ints.set_precision (prec, num_words);
     645    102653127 :   set_prange (r);
     646    102653127 : }
     647              : 
     648              : // Return TRUE if R is exactly the nonzero set [1, MAX], which prange_storage
     649              : // encodes compactly as PR_NONZERO.
     650              : //
     651              : // Compare the bounds against a fresh set_nonzero () rather than using
     652              : // prange::operator==, because operator== also compares the bitmask and
     653              : // points-to info, which are stored separately here, so a non-null pointer that
     654              : // also carries e.g. an alignment bitmask still belongs in PR_NONZERO.
     655              : 
     656              : static inline bool
     657    149268226 : nonzero_range_p (const prange &r)
     658              : {
     659    149268226 :   prange nonzero (r.type ());
     660    149268226 :   nonzero.set_nonzero (r.type ());
     661    298536452 :   return (r.lower_bound () == nonzero.lower_bound ()
     662    296089659 :           && r.upper_bound () == nonzero.upper_bound ());
     663    149268226 : }
     664              : 
     665              : // Return the prange_kind for range R, and the number of words of storage
     666              : // it requires in NUM_WORDS.
     667              : 
     668              : enum prange_kind
     669    319390240 : prange_storage::prange_format (const prange &r, unsigned &num_words)
     670              : {
     671    319390240 :   num_words = 0;
     672    319390240 :   if (r.undefined_p ())
     673              :     return PR_UNDEFINED;
     674              : 
     675    290058198 :   if (r.varying_p ())
     676              :     return PR_VARYING;
     677              : 
     678    135451125 :   if (r.zero_p ())
     679              :     return PR_ZERO;
     680              : 
     681    134358437 :   enum prange_kind kind = PR_NONZERO;
     682              : 
     683    134358437 :   if (!nonzero_range_p (r))
     684              :     {
     685      3146528 :       prange tmp (r.type ());
     686      6293056 :       if (r.lower_bound () == tmp.lower_bound ()
     687      4550594 :           && r.upper_bound () == tmp.upper_bound ())
     688              :         kind = PR_FULL;
     689              :       else
     690              :         {
     691              :           // PR_OTHER requires words of storage for the end points.
     692      2928577 :           kind = PR_OTHER;
     693      2928577 :           num_words += 2;
     694              :         }
     695      3146528 :     }
     696              : 
     697              :   // Bitmasks require 2 words of storage.
     698    134358437 :   if (!r.get_bitmask ().unknown_p ())
     699      5403549 :     num_words += 2;
     700              : 
     701              :   // PR_FULL must have a bitmask or points to, or it should be PR_VARYING.
     702    134576388 :   gcc_checking_assert (kind != PR_FULL || !r.get_bitmask ().unknown_p ()
     703              :                        || r.m_pt != NULL_TREE);
     704    134358437 :   return kind;
     705              : }
     706              : 
     707              : void
     708    106458440 : prange_storage::set_prange (const prange &r)
     709              : {
     710    106458440 :   unsigned num_words;
     711    106458440 :   m_kind = prange_format (r, num_words);
     712    106458440 :   m_has_bitmask = false;
     713    106458440 :   m_points_to_p = false;
     714    106458440 :   m_pt = r.m_pt;
     715              : 
     716    106458440 :   unsigned index = 0;
     717              : 
     718    106458440 :   switch (m_kind)
     719              :     {
     720     61684107 :       case PR_UNDEFINED:
     721     61684107 :       case PR_VARYING:
     722     61684107 :       case PR_ZERO:
     723     61684107 :         return;
     724              :       case PR_NONZERO:
     725              :       case PR_FULL:
     726              :         break;
     727       903893 :       case PR_OTHER:
     728       903893 :         set_word (index++, r.lower_bound (), r.type ());
     729       903893 :         set_word (index++, r.upper_bound (), r.type ());
     730       903893 :         break;
     731            0 :       default:
     732            0 :         gcc_unreachable ();
     733              :     }
     734              : 
     735     44774333 :   m_has_bitmask = !r.get_bitmask ().unknown_p ();
     736     44774333 :   m_points_to_p = r.m_points_to_p;
     737              : 
     738     44774333 :   if (m_has_bitmask)
     739              :     {
     740      1807880 :       irange_bitmask bm = r.m_bitmask;
     741      1807880 :       set_word (index++, r.m_bitmask.value (), r.type ());
     742      1807880 :       set_word (index++, r.m_bitmask.mask (), r.type ());
     743      1807880 :     }
     744     44774333 :   gcc_checking_assert (index == num_words);
     745              : }
     746              : 
     747              : void
     748    389676249 : prange_storage::get_prange (prange &r, tree type) const
     749              : {
     750    389676249 :   gcc_checking_assert (r.supports_type_p (type));
     751    389676249 :   unsigned index = 0;
     752    389676249 :   switch (m_kind)
     753              :     {
     754       971806 :       case PR_UNDEFINED:
     755       971806 :         r.set_undefined ();
     756       971806 :         return;
     757              : 
     758    219204324 :       case PR_VARYING:
     759    219204324 :         r.set_varying (type);
     760    219204324 :         return;
     761              : 
     762       641921 :       case PR_ZERO:
     763       641921 :         r.set_zero (type);
     764       641921 :         return;
     765              : 
     766    165145379 :       case PR_NONZERO:
     767    165145379 :         r.set_nonzero (type);
     768    165145379 :         break;
     769              : 
     770       526208 :       case PR_FULL:
     771       526208 :         {
     772       526208 :           r.m_kind = VR_RANGE;
     773       526208 :           r.m_type = type;
     774       526208 :           prange tmp (type);
     775       526208 :           r.m_min = tmp.lower_bound ();
     776       526208 :           r.m_max = tmp.upper_bound ();
     777       526208 :           break;
     778       526208 :         }
     779              : 
     780      3186611 :       case PR_OTHER:
     781      3186611 :         {
     782      3186611 :           gcc_checking_assert (m_kind == PR_OTHER);
     783      3186611 :           r.m_kind = VR_RANGE;
     784      3186611 :           r.m_type = type;
     785      3186611 :           r.m_min = get_word (index++, type);
     786      3186611 :           r.m_max = get_word (index++, type);
     787      3186611 :           break;
     788              :         }
     789            0 :       default:
     790            0 :         gcc_unreachable ();
     791              :     }
     792              : 
     793    168858198 :   if (m_has_bitmask)
     794              :     {
     795     18171683 :       wide_int value = get_word (index++, type);
     796     18171683 :       wide_int mask = get_word (index++, type);
     797     18171683 :       r.m_bitmask = irange_bitmask (value, mask);
     798     18171683 :     }
     799              :   else
     800    150686515 :     r.m_bitmask.set_unknown (TYPE_PRECISION (type));
     801              : 
     802    168858198 :   r.m_points_to_p = m_points_to_p;
     803    168858198 :   r.m_pt = m_pt;
     804              : 
     805    168858198 :   if (flag_checking)
     806    168858072 :     r.verify_range ();
     807              : }
     808              : 
     809              : bool
     810     15344387 : prange_storage::equal_p (const prange &r) const
     811              : {
     812     15344387 :   if (r.undefined_p ())
     813            0 :     return m_kind == PR_UNDEFINED;
     814              : 
     815     15344387 :   unsigned index = 0;
     816     15344387 :   switch (m_kind)
     817              :     {
     818         6494 :       case PR_VARYING:
     819         6494 :         return r.varying_p ();
     820              : 
     821        87002 :       case PR_ZERO:
     822        87002 :         return r.zero_p ();
     823              : 
     824     14909789 :       case PR_NONZERO:
     825     14909789 :         if (!nonzero_range_p (r))
     826              :           return false;
     827              :         break;
     828              : 
     829       297111 :       case PR_FULL:
     830       297111 :         if (r.m_min != wi::zero (TYPE_PRECISION (r.m_type))
     831       595147 :             || r.m_max != wi::max_value (TYPE_PRECISION (r.m_type),
     832       149018 :                                          TYPE_SIGN (r.m_type)))
     833              :           return false;
     834              :         break;
     835              : 
     836        43991 :       case PR_OTHER:
     837        87982 :         if (r.m_min != get_word (index++, r.m_type)
     838        73862 :             || r.m_max != get_word (index++, r.m_type))
     839              :           return false;
     840              :         break;
     841              : 
     842            0 :       default:
     843            0 :         gcc_unreachable ();
     844              :     }
     845              : 
     846     14673328 :   if (m_has_bitmask)
     847              :     {
     848      8755824 :       wide_int value = get_word (index++, r.m_type);
     849      8755824 :       wide_int mask = get_word (index++, r.m_type);
     850      8755824 :       if (r.m_bitmask != irange_bitmask (value, mask))
     851      4267482 :         return false;
     852      8755824 :     }
     853              :   else
     854      5917504 :     if (!r.m_bitmask.unknown_p ())
     855              :       return false;
     856              : 
     857      8769853 :   if (m_pt != r.m_pt)
     858              :     return false;
     859              :   // Storage objects are only equal If they point to the same memory.
     860      1539539 :   if (m_points_to_p != r.m_points_to_p)
     861            0 :     return false;
     862              : 
     863              :   return true;
     864              : }
     865              : 
     866              : bool
     867      7642282 : prange_storage::fits_p (const prange &r) const
     868              : {
     869              :   // Undefined ranges always fit, because they don't store anything in
     870              :   // the trailing wide ints.
     871      7642282 :   if (r.undefined_p ())
     872              :     return true;
     873              : 
     874      7625546 :   unsigned num_words;
     875      7625546 :   prange_format (r, num_words);
     876      7625546 :   return num_words <= m_trailing_ints.num_elements ();
     877              : }
     878              : 
     879              : 
     880              : static vrange_allocator ggc_vrange_allocator (true);
     881              : 
     882            0 : vrange_storage *ggc_alloc_vrange_storage (tree type)
     883              : {
     884            0 :   return ggc_vrange_allocator.clone_varying (type);
     885              : }
     886              : 
     887     21439282 : vrange_storage *ggc_alloc_vrange_storage (const vrange &r, bool shared_p)
     888              : {
     889     21439282 :   return ggc_vrange_allocator.clone (r, shared_p);
     890              : }
        

Generated by: LCOV version 2.5.0-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.