(root)/
gcc-13.2.0/
gcc/
value-range-storage.h
       1  /* Support routines for vrange storage.
       2     Copyright (C) 2022-2023 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  #ifndef GCC_VALUE_RANGE_STORAGE_H
      22  #define GCC_VALUE_RANGE_STORAGE_H
      23  
      24  // This class is used to allocate the minimum amount of storage needed
      25  // for a given range.  Storage is automatically freed at destruction
      26  // of the class.
      27  
      28  class vrange_allocator
      29  {
      30  public:
      31    vrange_allocator () { }
      32    virtual ~vrange_allocator () { }
      33    // Allocate a range of TYPE.
      34    vrange *alloc_vrange (tree type);
      35    // Allocate a memory block of BYTES.
      36    virtual void *alloc (unsigned bytes) = 0;
      37    virtual void free (void *p) = 0;
      38    // Return a clone of SRC.
      39    template <typename T> T *clone (const T &src);
      40  private:
      41    irange *alloc_irange (unsigned pairs);
      42    frange *alloc_frange ();
      43    void operator= (const vrange_allocator &) = delete;
      44  };
      45  
      46  // This class is used to allocate chunks of memory that can store
      47  // ranges as memory efficiently as possible.  It is meant to be used
      48  // when long term storage of a range is needed.  The class can be used
      49  // with any vrange_allocator (i.e. alloca or GC).
      50  
      51  class vrange_storage
      52  {
      53  public:
      54    vrange_storage (vrange_allocator *alloc) : m_alloc (alloc) { }
      55    void *alloc_slot (const vrange &r);
      56    void free (void *slot) { m_alloc->free (slot); }
      57    void get_vrange (const void *slot, vrange &r, tree type);
      58    void set_vrange (void *slot, const vrange &r);
      59    static bool fits_p (const void *slot, const vrange &r);
      60  private:
      61    DISABLE_COPY_AND_ASSIGN (vrange_storage);
      62    vrange_allocator *m_alloc;
      63  };
      64  
      65  // A chunk of memory pointing to an irange storage.
      66  
      67  class GTY ((variable_size)) irange_storage_slot
      68  {
      69  public:
      70    static irange_storage_slot *alloc_slot (vrange_allocator &, const irange &r);
      71    void set_irange (const irange &r);
      72    void get_irange (irange &r, tree type) const;
      73    wide_int get_nonzero_bits () const { return m_ints[0]; }
      74    bool fits_p (const irange &r) const;
      75    static size_t size (const irange &r);
      76    void dump () const;
      77  private:
      78    DISABLE_COPY_AND_ASSIGN (irange_storage_slot);
      79    friend void gt_ggc_mx_irange_storage_slot (void *);
      80    friend void gt_pch_p_19irange_storage_slot (void *, void *,
      81  					      gt_pointer_operator, void *);
      82    friend void gt_pch_nx_irange_storage_slot (void *);
      83  
      84    // This is the maximum number of wide_int's allowed in the trailing
      85    // ints structure, without going over 16 bytes (128 bits) in the
      86    // control word that precedes the HOST_WIDE_INTs in
      87    // trailing_wide_ints::m_val[].
      88    static const unsigned MAX_INTS = 12;
      89  
      90    // Maximum number of range pairs we can handle, considering the
      91    // nonzero bits take one wide_int.
      92    static const unsigned MAX_PAIRS = (MAX_INTS - 1) / 2;
      93  
      94    // Constructor is private to disallow stack initialization.  Use
      95    // alloc_slot() to create objects.
      96    irange_storage_slot (const irange &r);
      97  
      98    static unsigned num_wide_ints_needed (const irange &r);
      99  
     100    trailing_wide_ints<MAX_INTS> m_ints;
     101  };
     102  
     103  // A chunk of memory to store an frange to long term memory.
     104  
     105  class GTY (()) frange_storage_slot
     106  {
     107   public:
     108    static frange_storage_slot *alloc_slot (vrange_allocator &, const frange &r);
     109    void set_frange (const frange &r);
     110    void get_frange (frange &r, tree type) const;
     111    bool fits_p (const frange &) const;
     112   private:
     113    frange_storage_slot (const frange &r) { set_frange (r); }
     114    DISABLE_COPY_AND_ASSIGN (frange_storage_slot);
     115  
     116    enum value_range_kind m_kind;
     117    REAL_VALUE_TYPE m_min;
     118    REAL_VALUE_TYPE m_max;
     119    bool m_pos_nan;
     120    bool m_neg_nan;
     121  };
     122  
     123  class obstack_vrange_allocator final: public vrange_allocator
     124  {
     125  public:
     126    obstack_vrange_allocator ()
     127    {
     128      obstack_init (&m_obstack);
     129    }
     130    virtual ~obstack_vrange_allocator () final override
     131    {
     132      obstack_free (&m_obstack, NULL);
     133    }
     134    virtual void *alloc (unsigned bytes) final override
     135    {
     136      return obstack_alloc (&m_obstack, bytes);
     137    }
     138    virtual void free (void *) final override { }
     139  private:
     140    obstack m_obstack;
     141  };
     142  
     143  class ggc_vrange_allocator final: public vrange_allocator
     144  {
     145  public:
     146    ggc_vrange_allocator () { }
     147    virtual ~ggc_vrange_allocator () final override { }
     148    virtual void *alloc (unsigned bytes) final override
     149    {
     150      return ggc_internal_alloc (bytes);
     151    }
     152    virtual void free (void *p) final override
     153    {
     154      return ggc_free (p);
     155    }
     156  };
     157  
     158  // Return a new range to hold ranges of TYPE.  The newly allocated
     159  // range is initialized to VR_UNDEFINED.
     160  
     161  inline vrange *
     162  vrange_allocator::alloc_vrange (tree type)
     163  {
     164    if (irange::supports_p (type))
     165      return alloc_irange (2);
     166    if (frange::supports_p (type))
     167      return alloc_frange ();
     168    return NULL;
     169    gcc_unreachable ();
     170  }
     171  
     172  // Return a new range with NUM_PAIRS.
     173  
     174  inline irange *
     175  vrange_allocator::alloc_irange (unsigned num_pairs)
     176  {
     177    // Never allocate 0 pairs.
     178    // Don't allocate 1 either, or we get legacy value_range's.
     179    if (num_pairs < 2)
     180      num_pairs = 2;
     181  
     182    size_t nbytes = sizeof (tree) * 2 * num_pairs;
     183  
     184    // Allocate the irange and required memory for the vector.
     185    void *r = alloc (sizeof (irange));
     186    tree *mem = static_cast <tree *> (alloc (nbytes));
     187    return new (r) irange (mem, num_pairs);
     188  }
     189  
     190  inline frange *
     191  vrange_allocator::alloc_frange ()
     192  {
     193    void *r = alloc (sizeof (frange));
     194    return new (r) frange ();
     195  }
     196  
     197  // Return a clone of an irange.
     198  
     199  template <>
     200  inline irange *
     201  vrange_allocator::clone <irange> (const irange &src)
     202  {
     203    irange *r = alloc_irange (src.num_pairs ());
     204    *r = src;
     205    return r;
     206  }
     207  
     208  // Return a clone of an frange.
     209  
     210  template <>
     211  inline frange *
     212  vrange_allocator::clone <frange> (const frange &src)
     213  {
     214    frange *r = alloc_frange ();
     215    *r = src;
     216    return r;
     217  }
     218  
     219  // Return a clone of a vrange.
     220  
     221  template <>
     222  inline vrange *
     223  vrange_allocator::clone <vrange> (const vrange &src)
     224  {
     225    if (is_a <irange> (src))
     226      return clone <irange> (as_a <irange> (src));
     227    if (is_a <frange> (src))
     228      return clone <frange> (as_a <frange> (src));
     229    return NULL;
     230    gcc_unreachable ();
     231  }
     232  
     233  #endif // GCC_VALUE_RANGE_STORAGE_H