[llvm-commits] [llvm] r152090 - /llvm/trunk/include/llvm/ADT/UsuallyTinyPtrVector.h
Argyrios Kyrtzidis
akyrtzi at gmail.com
Mon Mar 5 18:08:48 PST 2012
Author: akirtzidis
Date: Mon Mar 5 20:08:48 2012
New Revision: 152090
URL: http://llvm.org/viewvc/llvm-project?rev=152090&view=rev
Log:
Add include/llvm/ADT/UsuallyTinyPtrVector.h which is a vector that
optimizes the case where there is only one element.
Added:
llvm/trunk/include/llvm/ADT/UsuallyTinyPtrVector.h
Added: llvm/trunk/include/llvm/ADT/UsuallyTinyPtrVector.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/UsuallyTinyPtrVector.h?rev=152090&view=auto
==============================================================================
--- llvm/trunk/include/llvm/ADT/UsuallyTinyPtrVector.h (added)
+++ llvm/trunk/include/llvm/ADT/UsuallyTinyPtrVector.h Mon Mar 5 20:08:48 2012
@@ -0,0 +1,137 @@
+//===-- UsuallyTinyPtrVector.h - Pointer vector class -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the UsuallyTinyPtrVector class, which is a vector that
+// optimizes the case where there is only one element.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_USUALLY_TINY_PTR_VECTOR_H
+#define LLVM_ADT_USUALLY_TINY_PTR_VECTOR_H
+
+#include <vector>
+
+namespace llvm {
+
+/// \brief A vector class template that is optimized for storing a single
+/// pointer element.
+template<typename T>
+class UsuallyTinyPtrVector {
+ /// \brief Storage for the vector.
+ ///
+ /// When the low bit is zero, this is a T *. When the
+ /// low bit is one, this is a std::vector<T *> *.
+ mutable uintptr_t Storage;
+
+ typedef std::vector<T*> vector_type;
+
+public:
+ UsuallyTinyPtrVector() : Storage(0) { }
+ explicit UsuallyTinyPtrVector(T *Element)
+ : Storage(reinterpret_cast<uintptr_t>(Element)) { }
+
+ bool empty() const { return !Storage; }
+
+ typedef const T **iterator;
+ iterator begin() const;
+ iterator end() const;
+ size_t size() const;
+
+ void push_back(T *Method);
+ iterator erase(const iterator ElementPos);
+ void Destroy();
+};
+
+template<typename T>
+typename UsuallyTinyPtrVector<T>::iterator
+UsuallyTinyPtrVector<T>::begin() const {
+ if ((Storage & 0x01) == 0)
+ return reinterpret_cast<iterator>(&Storage);
+
+ vector_type *Vec = reinterpret_cast<vector_type *>(Storage & ~0x01);
+ return &Vec->front();
+}
+
+template<typename T>
+typename UsuallyTinyPtrVector<T>::iterator
+UsuallyTinyPtrVector<T>::end() const {
+ if ((Storage & 0x01) == 0) {
+ if (Storage == 0)
+ return reinterpret_cast<iterator>(&Storage);
+
+ return reinterpret_cast<iterator>(&Storage) + 1;
+ }
+
+ vector_type *Vec = reinterpret_cast<vector_type *>(Storage & ~0x01);
+ return &Vec->front() + Vec->size();
+}
+
+template<typename T>
+size_t UsuallyTinyPtrVector<T>::size() const {
+ if ((Storage & 0x01) == 0)
+ return (Storage == 0) ? 0 : 1;
+
+ vector_type *Vec = reinterpret_cast<vector_type *>(Storage & ~0x01);
+ return Vec->size();
+}
+
+template<typename T>
+void UsuallyTinyPtrVector<T>::push_back(T *Element) {
+ if (Storage == 0) {
+ // 0 -> 1 element.
+ Storage = reinterpret_cast<uintptr_t>(Element);
+ return;
+ }
+
+ vector_type *Vec;
+ if ((Storage & 0x01) == 0) {
+ // 1 -> 2 elements. Allocate a new vector and push the element into that
+ // vector.
+ Vec = new vector_type;
+ Vec->push_back(reinterpret_cast<T *>(Storage));
+ Storage = reinterpret_cast<uintptr_t>(Vec) | 0x01;
+ } else
+ Vec = reinterpret_cast<vector_type *>(Storage & ~0x01);
+
+ // Add the new element to the vector.
+ Vec->push_back(Element);
+}
+
+template<typename T>
+typename UsuallyTinyPtrVector<T>::iterator
+UsuallyTinyPtrVector<T>::erase(
+ const typename UsuallyTinyPtrVector<T>::iterator ElementPos) {
+ // only one item
+ if ((Storage & 0x01) == 0) {
+ // if the element is found remove it
+ if (ElementPos == reinterpret_cast<T **>(&Storage))
+ Storage = 0;
+ } else {
+ // multiple items in a vector; just do the erase, there is no
+ // benefit to collapsing back to a pointer
+ vector_type *Vec = reinterpret_cast<vector_type *>(Storage & ~0x01);
+ unsigned index = ElementPos -
+ const_cast<typename UsuallyTinyPtrVector<T>::iterator>(&Vec->front());
+ if (index < Vec->size())
+ return const_cast<typename UsuallyTinyPtrVector<T>::iterator>(
+ &*(Vec->erase(Vec->begin() + index)));
+ }
+ return end();
+}
+
+template<typename T>
+void UsuallyTinyPtrVector<T>::Destroy() {
+ if (Storage & 0x01)
+ delete reinterpret_cast<vector_type *>(Storage & ~0x01);
+
+ Storage = 0;
+}
+
+}
+#endif
More information about the llvm-commits
mailing list