irange_allocator class
authorAldy Hernandez <aldyh@redhat.com>
Fri, 11 Sep 2020 08:15:12 +0000 (10:15 +0200)
committerAldy Hernandez <aldyh@redhat.com>
Mon, 28 Sep 2020 22:23:53 +0000 (00:23 +0200)
This is the irange storage class.  It is used to allocate the
minimum amount of storage needed for a given irange.  Storage is
automatically freed at destruction of the storage class.

It is meant for long term storage, as opposed to int_range_max
which is meant for intermediate temporary results on the stack.

The general gist is:

irange_allocator alloc;

// Allocate an irange of 5 sub-ranges.
irange *p = alloc.allocate (5);

// Allocate an irange of 3 sub-ranges.
irange *q = alloc.allocate (3);

// Allocate an irange with as many sub-ranges as are currently
// used in "some_other_range".
irange *r = alloc.allocate (some_other_range);

gcc/ChangeLog:

* value-range.h (class irange): Add irange_allocator friend.
(class irange_allocator): New.

gcc/value-range.h

index 8497791c7b3a0e7a2b4c4e12d186fe71fc078856..c875e713d6524bcf0934e21a9f3c8496b280843b 100644 (file)
@@ -43,6 +43,7 @@ enum value_range_kind
 
 class irange
 {
+  friend class irange_allocator;
 public:
   // In-place setters.
   void set (tree, tree, value_range_kind = VR_RANGE);
@@ -619,4 +620,68 @@ vrp_val_min (const_tree type)
   return NULL_TREE;
 }
 
+// This is the irange storage class.  It is used to allocate the
+// minimum amount of storage needed for a given irange.  Storage is
+// automatically freed at destruction of the storage class.
+//
+// It is meant for long term storage, as opposed to int_range_max
+// which is meant for intermediate temporary results on the stack.
+//
+// The newly allocated irange is initialized to the empty set
+// (undefined_p() is true).
+
+class irange_allocator
+{
+public:
+  irange_allocator ();
+  ~irange_allocator ();
+  // Return a new range with NUM_PAIRS.
+  irange *allocate (unsigned num_pairs);
+  // Return a copy of SRC with the minimum amount of sub-ranges needed
+  // to represent it.
+  irange *allocate (const irange &src);
+private:
+  DISABLE_COPY_AND_ASSIGN (irange_allocator);
+  struct obstack m_obstack;
+};
+
+inline
+irange_allocator::irange_allocator ()
+{
+  obstack_init (&m_obstack);
+}
+
+inline
+irange_allocator::~irange_allocator ()
+{
+  obstack_free (&m_obstack, NULL);
+}
+
+// Return a new range with NUM_PAIRS.
+
+inline irange *
+irange_allocator::allocate (unsigned num_pairs)
+{
+  // Never allocate 0 pairs.
+  // Don't allocate 1 either, or we get legacy value_range's.
+  if (num_pairs < 2)
+    num_pairs = 2;
+
+  struct newir {
+    irange range;
+    tree mem[1];
+  };
+  size_t nbytes = (sizeof (newir) + sizeof (tree) * 2 * (num_pairs - 1));
+  struct newir *r = (newir *) obstack_alloc (&m_obstack, nbytes);
+  return new (r) irange (r->mem, num_pairs);
+}
+
+inline irange *
+irange_allocator::allocate (const irange &src)
+{
+  irange *r = allocate (src.num_pairs ());
+  *r = src;
+  return r;
+}
+
 #endif // GCC_VALUE_RANGE_H