[llvm-branch-commits] [llvm] [docs] Migrate 22 popular LLVM docs to MyST (PR #201244)
Reid Kleckner via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Jun 22 15:51:26 PDT 2026
================
@@ -1581,439 +1460,413 @@ memory use, constant factors, and cache behaviors of access by intelligently
picking a member of the category. Note that constant factors and cache behavior
can be a big deal. If you have a vector that usually only contains a few
elements (but could contain many), for example, it's much better to use
-:ref:`SmallVector <dss_smallvector>` than :ref:`vector <dss_vector>`. Doing so
+{ref}`SmallVector <dss_smallvector>` than {ref}`vector <dss_vector>`. Doing so
avoids (relatively) expensive malloc/free calls, which dwarf the cost of adding
the elements to the container.
-.. _ds_sequential:
+(ds_sequential)=
-Sequential Containers (std::vector, std::list, etc)
----------------------------------------------------
+### Sequential Containers (std::vector, std::list, etc)
There are a variety of sequential containers available for you, based on your
needs. Pick the first in this section that will do what you want.
-.. _dss_arrayref:
+(dss_arrayref)=
-llvm/ADT/ArrayRef.h
-^^^^^^^^^^^^^^^^^^^
+#### llvm/ADT/ArrayRef.h
-The ``llvm::ArrayRef`` class is the preferred class to use in an interface that
+The `llvm::ArrayRef` class is the preferred class to use in an interface that
accepts a sequential list of elements in memory and just reads from them. By
-taking an ``ArrayRef``, the API can be passed a fixed size array, an
-``std::vector``, an ``llvm::SmallVector`` and anything else that is contiguous
+taking an `ArrayRef`, the API can be passed a fixed size array, an
+`std::vector`, an `llvm::SmallVector` and anything else that is contiguous
in memory.
-.. _dss_fixedarrays:
+(dss_fixedarrays)=
-Fixed Size Arrays
-^^^^^^^^^^^^^^^^^
+#### Fixed Size Arrays
Fixed size arrays are very simple and very fast. They are good if you know
exactly how many elements you have, or you have a (low) upper bound on how many
you have.
-.. _dss_heaparrays:
+(dss_heaparrays)=
-Heap Allocated Arrays
-^^^^^^^^^^^^^^^^^^^^^
+#### Heap Allocated Arrays
-Heap allocated arrays (``new[]`` + ``delete[]``) are also simple. They are good
+Heap allocated arrays (`new[]` + `delete[]`) are also simple. They are good
if the number of elements is variable, if you know how many elements you will
need before the array is allocated, and if the array is usually large (if not,
-consider a :ref:`SmallVector <dss_smallvector>`). The cost of a heap allocated
+consider a {ref}`SmallVector <dss_smallvector>`). The cost of a heap allocated
array is the cost of the new/delete (aka malloc/free). Also note that if you
are allocating an array of a type with a constructor, the constructor and
destructors will be run for every element in the array (re-sizable vectors only
construct those elements actually used).
-.. _dss_tinyptrvector:
+(dss_tinyptrvector)=
-llvm/ADT/TinyPtrVector.h
-^^^^^^^^^^^^^^^^^^^^^^^^
+#### llvm/ADT/TinyPtrVector.h
-``TinyPtrVector<Type>`` is a highly specialized collection class that is
+`TinyPtrVector<Type>` is a highly specialized collection class that is
optimized to avoid allocation in the case when a vector has zero or one
elements. It has two major restrictions: 1) it can only hold values of pointer
type, and 2) it cannot hold a null pointer.
Since this container is highly specialized, it is rarely used.
-.. _dss_smallvector:
+(dss_smallvector)=
-llvm/ADT/SmallVector.h
-^^^^^^^^^^^^^^^^^^^^^^
+#### llvm/ADT/SmallVector.h
-``SmallVector<Type, N>`` is a simple class that looks and smells just like
-``vector<Type>``: it supports efficient iteration, lays out elements in memory
+`SmallVector<Type, N>` is a simple class that looks and smells just like
+`vector<Type>`: it supports efficient iteration, lays out elements in memory
order (so you can do pointer arithmetic between elements), supports efficient
-``push_back``/``pop_back`` operations, supports efficient random access to its elements,
+`push_back`/`pop_back` operations, supports efficient random access to its elements,
etc.
-The main advantage of ``SmallVector`` is that it allocates space for some number of
-elements (N) **in the object itself**. Because of this, if the ``SmallVector`` is
+The main advantage of `SmallVector` is that it allocates space for some number of
+elements (N) **in the object itself**. Because of this, if the `SmallVector` is
dynamically smaller than N, no malloc is performed. This can be a big win in
cases where the malloc/free call is far more expensive than the code that
fiddles around with the elements.
This is good for vectors that are "usually small" (e.g., the number of
predecessors/successors of a block is usually less than 8). On the other hand,
-this makes the size of the ``SmallVector`` itself large, so you don't want to
+this makes the size of the `SmallVector` itself large, so you don't want to
allocate lots of them (doing so will waste a lot of space). As such,
SmallVectors are most useful when on the stack.
In the absence of a well-motivated choice for the number of
-inlined elements ``N``, it is recommended to use ``SmallVector<T>`` (that is,
-omitting the ``N``). This will choose a default number of
+inlined elements `N`, it is recommended to use `SmallVector<T>` (that is,
+omitting the `N`). This will choose a default number of
inlined elements reasonable for allocation on the stack (for example, trying
-to keep ``sizeof(SmallVector<T>)`` around 64 bytes).
+to keep `sizeof(SmallVector<T>)` around 64 bytes).
-``SmallVector`` also provides a nice portable and efficient replacement for
-``alloca``.
+`SmallVector` also provides a nice portable and efficient replacement for
+`alloca`.
-``SmallVector`` has grown a few other minor advantages over ``std::vector``, causing
-``SmallVector<Type, 0>`` to be preferred over ``std::vector<Type>``.
+`SmallVector` has grown a few other minor advantages over `std::vector`, causing
+`SmallVector<Type, 0>` to be preferred over `std::vector<Type>`.
-#. ``std::vector`` is exception-safe, and some implementations have pessimizations
- that copy elements when ``SmallVector`` would move them.
+1. `std::vector` is exception-safe, and some implementations have pessimizations
+ that copy elements when `SmallVector` would move them.
-#. ``SmallVector`` understands ``std::is_trivially_copyable<Type>`` and uses realloc aggressively.
+1. `SmallVector` understands `std::is_trivially_copyable<Type>` and uses realloc aggressively.
-#. Many LLVM APIs take a ``SmallVectorImpl`` as an out parameter (see the note
+1. Many LLVM APIs take a `SmallVectorImpl` as an out parameter (see the note
below).
-#. ``SmallVector`` with N equal to 0 is smaller than ``std::vector`` on 64-bit
- platforms, since it uses ``unsigned`` (instead of ``void*``) for its size
+1. `SmallVector` with N equal to 0 is smaller than `std::vector` on 64-bit
+ platforms, since it uses `unsigned` (instead of `void*`) for its size
and capacity.
-.. note::
-
- Prefer to use ``ArrayRef<T>`` or ``SmallVectorImpl<T>`` as a parameter type.
-
- It's rarely appropriate to use ``SmallVector<T, N>`` as a parameter type.
- If an API only reads from the vector, it should use :ref:`ArrayRef
- <dss_arrayref>`. Even if an API updates the vector the "small size" is
- unlikely to be relevant; such an API should use the ``SmallVectorImpl<T>``
- class, which is the "vector header" (and methods) without the elements
- allocated after it. Note that ``SmallVector<T, N>`` inherits from
- ``SmallVectorImpl<T>`` so the conversion is implicit and costs nothing. E.g.
-
- .. code-block:: c++
-
- // DISCOURAGED: Clients cannot pass e.g., raw arrays.
- hardcodedContiguousStorage(const SmallVectorImpl<Foo> &In);
- // ENCOURAGED: Clients can pass any contiguous storage of Foo.
- allowsAnyContiguousStorage(ArrayRef<Foo> In);
-
- void someFunc1() {
- Foo Vec[] = { /* ... */ };
- hardcodedContiguousStorage(Vec); // Error.
- allowsAnyContiguousStorage(Vec); // Works.
- }
-
- // DISCOURAGED: Clients cannot pass e.g., SmallVector<Foo, 8>.
- hardcodedSmallSize(SmallVector<Foo, 2> &Out);
- // ENCOURAGED: Clients can pass any SmallVector<Foo, N>.
- allowsAnySmallSize(SmallVectorImpl<Foo> &Out);
-
- void someFunc2() {
- SmallVector<Foo, 8> Vec;
- hardcodedSmallSize(Vec); // Error.
- allowsAnySmallSize(Vec); // Works.
- }
-
- Even though it has "``Impl``" in the name, SmallVectorImpl is widely used
- and is no longer "private to the implementation". A name like
- ``SmallVectorHeader`` might be more appropriate.
-
-.. _dss_pagedvector:
-
-llvm/ADT/PagedVector.h
-^^^^^^^^^^^^^^^^^^^^^^
-
-``PagedVector<Type, PageSize>`` is a random access container that allocates
-``PageSize`` elements of type ``Type`` when the first element of a page is
-accessed via the ``operator[]``. This is useful for cases where the number of
+````{note}
+Prefer to use `ArrayRef<T>` or `SmallVectorImpl<T>` as a parameter type.
+
+It's rarely appropriate to use `SmallVector<T, N>` as a parameter type.
+If an API only reads from the vector, it should use {ref}`ArrayRef <dss_arrayref>`. Even if an API updates the vector the "small size" is
+unlikely to be relevant; such an API should use the `SmallVectorImpl<T>`
+class, which is the "vector header" (and methods) without the elements
+allocated after it. Note that `SmallVector<T, N>` inherits from
+`SmallVectorImpl<T>` so the conversion is implicit and costs nothing. E.g.
+
+```cpp
+// DISCOURAGED: Clients cannot pass e.g., raw arrays.
+hardcodedContiguousStorage(const SmallVectorImpl<Foo> &In);
+// ENCOURAGED: Clients can pass any contiguous storage of Foo.
+allowsAnyContiguousStorage(ArrayRef<Foo> In);
+
+void someFunc1() {
+ Foo Vec[] = { /* ... */ };
+ hardcodedContiguousStorage(Vec); // Error.
+ allowsAnyContiguousStorage(Vec); // Works.
+}
+
+// DISCOURAGED: Clients cannot pass e.g., SmallVector<Foo, 8>.
+hardcodedSmallSize(SmallVector<Foo, 2> &Out);
+// ENCOURAGED: Clients can pass any SmallVector<Foo, N>.
+allowsAnySmallSize(SmallVectorImpl<Foo> &Out);
+
+void someFunc2() {
+ SmallVector<Foo, 8> Vec;
+ hardcodedSmallSize(Vec); // Error.
+ allowsAnySmallSize(Vec); // Works.
+}
+```
+Even though it has "`Impl`" in the name, SmallVectorImpl is widely used
+and is no longer "private to the implementation". A name like
+`SmallVectorHeader` might be more appropriate.
+````
+(dss_pagedvector)=
+
+#### llvm/ADT/PagedVector.h
+
+`PagedVector<Type, PageSize>` is a random access container that allocates
+`PageSize` elements of type `Type` when the first element of a page is
+accessed via the `operator[]`. This is useful for cases where the number of
elements is known in advance; their actual initialization is expensive; and
they are sparsely used. This utility uses page-granular lazy initialization
when the element is accessed. When the number of used pages is small
significant memory savings can be achieved.
-The main advantage is that a ``PagedVector`` allows to delay the actual
+The main advantage is that a `PagedVector` allows to delay the actual
allocation of the page until it's needed, at the extra cost of one pointer per
page and one extra indirection when accessing elements with their positional
index.
In order to minimise the memory footprint of this container, it's important to
-balance the ``PageSize`` so that it's not too small (otherwise, the overhead of the
+balance the `PageSize` so that it's not too small (otherwise, the overhead of the
pointer per page might become too high) and not too big (otherwise, the memory
is wasted if the page is not fully used).
Moreover, while retaining the order of the elements based on their insertion
-index, like a vector, iterating over the elements via ``begin()`` and ``end()``
+index, like a vector, iterating over the elements via `begin()` and `end()`
is not provided in the API, due to the fact that accessing the elements in order
would allocate all the iterated pages, defeating memory savings and the purpose
-of the ``PagedVector``.
+of the `PagedVector`.
-Finally, ``materialized_begin()`` and ``materialized_end`` iterators are
+Finally, `materialized_begin()` and `materialized_end` iterators are
provided to access the elements associated to the accessed pages, which could
speed up operations that need to iterate over initialized elements in a
non-ordered manner.
-.. _dss_vector:
+(dss_vector)=
-<vector>
-^^^^^^^^
+#### `<vector>`
-``std::vector<T>`` is well loved and respected. However, ``SmallVector<T, 0>``
-is often a better option due to the advantages listed above. ``std::vector`` is
-still useful when you need to store more than ``UINT32_MAX`` elements or when
+`std::vector<T>` is well loved and respected. However, `SmallVector<T, 0>`
+is often a better option due to the advantages listed above. `std::vector` is
+still useful when you need to store more than `UINT32_MAX` elements or when
interfacing with code that expects vectors :).
-One worthwhile note about ``std::vector``: avoid code like this:
-
-.. code-block:: c++
-
- for ( ... ) {
- std::vector<foo> V;
- // make use of V.
- }
+One worthwhile note about `std::vector`: avoid code like this:
+```cpp
+for ( ... ) {
+ std::vector<foo> V;
+ // make use of V.
+}
+```
Instead, write this as:
-.. code-block:: c++
-
- std::vector<foo> V;
- for ( ... ) {
- // make use of V.
- V.clear();
- }
-
+```cpp
+std::vector<foo> V;
+for ( ... ) {
+ // make use of V.
+ V.clear();
+}
+```
Doing so will save (at least) one heap allocation and free per iteration of the
loop.
-.. _dss_deque:
+(dss_deque)=
-<deque>
-^^^^^^^
+#### `<deque>`
----------------
rnk wrote:
Yeah, I caught this at some point.
https://github.com/llvm/llvm-project/pull/201244
More information about the llvm-branch-commits
mailing list