IR: Optimize size of use-list order shuffle vectors
[oota-llvm.git] / include / llvm / IR / UseListOrder.h
index 4326182c366443d1aa6530f0035d411136ae1801..a0eb0a6ce1b6ddc1084c0b26fbcab3a34ac014a9 100644 (file)
@@ -25,11 +25,58 @@ class Module;
 class Function;
 class Value;
 
+/// \brief Structure to hold a use-list shuffle vector.
+///
+/// Stores most use-lists locally, but large use-lists use an extra heap entry.
+/// Costs two fewer pointers than the equivalent \a SmallVector.
+class UseListShuffleVector {
+  unsigned Size;
+  union {
+    unsigned *Ptr;
+    unsigned Array[6];
+  } Storage;
+
+  bool isSmall() const { return Size <= 6; }
+  unsigned *data() { return isSmall() ? Storage.Array : Storage.Ptr; }
+  const unsigned *data() const {
+    return isSmall() ? Storage.Array : Storage.Ptr;
+  }
+
+public:
+  UseListShuffleVector() : Size(0) {}
+  UseListShuffleVector(UseListShuffleVector &&X) {
+    std::memcpy(this, &X, sizeof(UseListShuffleVector));
+    X.Size = 0;
+  }
+  explicit UseListShuffleVector(size_t Size) : Size(Size) {
+    if (!isSmall())
+      Storage.Ptr = new unsigned[Size];
+  }
+  ~UseListShuffleVector() {
+    if (!isSmall())
+      delete Storage.Ptr;
+  }
+
+  typedef unsigned *iterator;
+  typedef const unsigned *const_iterator;
+
+  size_t size() const { return Size; }
+  iterator begin() { return data(); }
+  iterator end() { return begin() + size(); }
+  const_iterator begin() const { return data(); }
+  const_iterator end() const { return begin() + size(); }
+  unsigned &operator[](size_t I) { return data()[I]; }
+  unsigned operator[](size_t I) const { return data()[I]; }
+};
+
 /// \brief Structure to hold a use-list order.
 struct UseListOrder {
-  const Function *F;
   const Value *V;
-  SmallVector<unsigned, 8> Shuffle;
+  const Function *F;
+  UseListShuffleVector Shuffle;
+
+  UseListOrder(const Value *V, const Function *F, size_t ShuffleSize)
+      : V(V), F(F), Shuffle(ShuffleSize) {}
 };
 
 typedef std::vector<UseListOrder> UseListOrderStack;