69 Commits

Author SHA1 Message Date
Christopher Di Bella
4d6913e14f
[libcxx] Rename __split_buffer alias template to _SplitBuffer (#180284)
`-Wchanges-meaning` is a GCC warning that catches shadowing in more
contexts. While a bit annoying here, it's a helpful warning. As such, we
need to rename the `__split_buffer` alias template in `std::vector` so
that we don't trip it up.
2026-02-06 23:22:32 +00:00
Christopher Di Bella
f735aa061b
[libc++] Tighten __add_alignment_assumption return type (#180090)
`__add_alignment_assumption` unilaterally returned a `pointer`, even
when passed a `const_pointer`. This was surfaced by some (but not all)
CI jobs when rebasing `std::vector` to have a layout type.
2026-02-06 08:26:37 -05:00
Louis Dionne
a3ebe650d3
[libc++][NFC] Clang-format <vector> and remove unused __self alias (#177021)
These changes were extracted out of the size-based vector patch.

Co-authored-by: Christopher Di Bella <cjdb@google.com>
2026-01-23 09:17:20 -05:00
Nikolas Klauser
b6bfb199cc
[libc++] Fix {deque,vector}::append_range assuming too much about the types (#162438)
Currently, `deque` and `vector`'s `append_range` is implemented in terms
of `insert_range`. The problem with that is that `insert_range` has more
preconditions, resulting in us rejecting valid code.

This also significantly improves performance for `deque` in some cases.
2026-01-09 12:06:43 +01:00
Eduardo Tachotte
e227125e6d
[libc++][NFC] Fix typo in comment (#173741)
Found a typo while reading the `vector` implementation, this PR simply
fixes it.
2025-12-29 01:09:59 +08:00
Nikolas Klauser
b97b1f2f49
[libc++] Optimize vector<bool>::resize() (#172853)
This both simplifies the implementation and improves the performance,
since the compiler is better able to see through what's going on.

```
Benchmark                                                                              old             new    Difference    % Difference
--------------------------------------------------------------------------  --------------  --------------  ------------  --------------
vector<bool>(const_vector<bool>&)                                                    11.99           12.26          0.27           2.25%
vector<bool>(size_type,_const_value_type&)                                            9.24            9.29          0.05           0.54%
vector<bool>(vector<bool>&&,_const_allocator_type&)_(different_allocators)           14.26           14.35          0.09           0.65%
vector<bool>(vector<bool>&&,_const_allocator_type&)_(equal_allocators)                2.67            2.67         -0.01          -0.29%
vector<bool>::reserve()                                                               9.30            9.29         -0.01          -0.12%
vector<bool>::resize()                                                               15.14           13.43         -1.71         -11.28%
Geomean                                                                               9.17            9.03         -0.14          -1.48%
2025-12-20 10:52:48 +01:00
Louis Dionne
2c1decb7f7
[libc++] Don't instantiate __split_buffer with an allocator reference (#171651)
Allocators should be extremely cheap, if not free, to copy. Furthermore,
we have requirements on allocator types that copies must compare equal,
and that move and copy must be the same.

Hence, taking an allocator by reference should not provide benefits
beyond making a copy of it. However, taking the allocator by reference
leads to complexity in __split_buffer, which can be removed if we stop
using that pattern.
2025-12-11 09:31:22 +01:00
Nikolas Klauser
c567e28a9d
[libc++] Optimize vector<bool>::reserve (#170137)
Apple M4:
```
Benchmark                                                                      old        new    Difference    % Difference
--------------------------------------------------------------------------  ------  ----------  ------------  --------------
vector<bool>(const_vector<bool>&)                                            12.73       12.87          0.14           1.07%
vector<bool>(size_type,_const_value_type&)                                    9.39        9.41          0.02           0.22%
vector<bool>(vector<bool>&&,_const_allocator_type&)_(different_allocators)   16.87       15.22         -1.65          -9.80%
vector<bool>(vector<bool>&&,_const_allocator_type&)_(equal_allocators)        2.68        2.73          0.05           1.90%
vector<bool>::reserve()                                                      11.81        9.43         -2.38         -20.14%
Geomean                                                                       9.14        8.62         -0.53          -5.76%
```
2025-12-10 10:18:59 +01:00
Nikolas Klauser
634f6e9ff3
[libc++] Merge the implementations of ranges::copy_n and std::copy_n and fix vector::insert to assign (#157444)
This reduces the amount of code we have to maintain a bit.

This also simplifies `vector` by using the internal API instead of
`#if`s to switch based on language dialect.
2025-11-27 15:50:50 +01:00
Louis Dionne
17ce48f2b6
[libc++] Remove __is_replaceable emulation (#167355)
The Trivial Relocation feature has been removed from the C++26 working
draft. Based on discussions in Kona, it is unlikely that the
"replaceable" type concept will come back in the C++29 time frame.

Since we don't have a use for the type trait in the library at the
moment, remove the code associated to it. If we end up needing something
like it in the future, we can always add it back.
2025-11-11 07:53:56 -05:00
Nikolas Klauser
0d97f43974
[libc++] Inline vector::__append into resize (#162086)
These functions are only used in a single place, so there is not much
reason to keep them around.
2025-11-10 20:02:54 +01:00
Nikolas Klauser
446d950524
[libc++] Use std::__{scope,exception}_guard throughout the code base (#161322)
This simplifies the code quite a bit and seems to improve code size
slightly in some cases.
2025-10-09 09:32:40 +02:00
Nikolas Klauser
a798a10434
[libc++] Optimize vector<bool>(const vector<bool>&) (#161672)
```
Benchmark                   Baseline    Candidate    Difference    % Difference
------------------------  ----------  -----------  ------------  --------------
BM_vector_bool_copy_ctor       56.93        10.93        -46.00          -80.80
BM_vector_bool_size_ctor        7.99         8.01          0.02            0.22
```
2025-10-07 15:07:12 +02:00
Nikolas Klauser
70b7874ab2
[libc++] Make the naming of the iterator_traits aliases consistent (#161661)
This renames all the `iterator_traits` alises to be
`__iterator_<type-name>`. e.g `iterator_traits<T>::value_type` will be
`__iterator_value_type<T>`.
2025-10-07 14:42:11 +02:00
Nikolas Klauser
96a7c9b985
[libc++] Simplify vector<bool> fill constructors (#160521)
#119632 introduced a code size and performance regression. This was
verified by running the included benchmark against trunk and trunk with
#119632 reverted. Instead of actually reverting that patch, we can
inline `__construct_at_end` into the few places it's used instead,
simplifying the implementation further (by not handling special cases we
never actually encounter).

```
Benchmark                   Baseline    Candidate    Difference    % Difference
------------------------  ----------  -----------  ------------  --------------
BM_vector_bool_size_ctor       29.91         8.56        -21.35          -71.37
```
2025-09-25 19:48:14 +02:00
Nikolas Klauser
8cb03a05ff
[libc++][NFC] Refactor __is_allocator to be a variable template (#159584) 2025-09-24 10:41:29 +02:00
Nikolas Klauser
ebcf1bf2ec
[libc++] Remove a few unused includes from <string> and <vector> (#160087) 2025-09-23 09:37:24 +02:00
Nikolas Klauser
76a11c769d
Reapply "[libc++] Mark __{emplace,push}_back_slow_path as noinline (#94379)" (#158606)
This reverts commit 7f2e9b17098f42c85ef469b029bb84ef4eea189c.

The LLDB failures have been resolved in trunk.
2025-09-17 11:10:06 +02:00
Aiden Grossman
7f2e9b1709 Revert "[libc++] Mark __{emplace,push}_back_slow_path as noinline (#94379)"
This reverts commit 1bafd020c7c80be476f211bc239ce43424f7e0ce.

This breaks the LLDB data formatters which means these failures show up
on every premerge run. Reverting for now until fixing the LLDB
formatters can be coordinated with a relanding.
2025-09-12 21:24:15 +00:00
Christopher Di Bella
e8f61801c6
[libcxx] adds size-based __split_buffer representation to unstable ABI (#139632)
**tl;dr** We can significantly improve the runtime performance of
`std::vector` by changing its representation from three pointers to one
pointer and two integers. This document explains the details of this
change, along with the justifications for making it. See the [RFC] for
more information.

`vector` depends on `__split_buffer` for inserting elements. Changing
`__split_buffer` to match `vector`'s representation simplifies the
model, as it eliminates the need to convert between two different
representations of a contiguous buffer in the same configuration of
libc++.

[RFC]: https://discourse.llvm.org/t/adding-a-size-based-vector-to-libc-s-unstable-abi/86306

---------

Co-authored-by: Jorge Gorbe Moya <jgorbe@google.com>
2025-09-12 06:33:10 -07:00
Nikolas Klauser
1bafd020c7
[libc++] Mark __{emplace,push}_back_slow_path as noinline (#94379)
These are almost certainly intended to not be inlined. This
significantly reduces code size when `push_back` and `emplace_back` are
used heavily.

Fixes #94360
2025-09-12 11:05:14 +02:00
Nikolas Klauser
34d4f0c136
[libc++][NFC] Use llvm.org/PR to link to bug reports (#156288)
We've built up quite a few links directly to github within the code
base. We should instead use `llvm.org/PR<issue-number>` to link to bugs,
since that is resilient to the bug tracker changing in the future. This
is especially relevant for tests linking to bugs, since they will
probably be there for decades to come. A nice side effect is that these
links are significantly shorter than the GH links, making them much less
of an eyesore.

This patch also replaces a few links that linked to the old bugzilla
instance on llvm.org.
2025-09-04 09:20:02 +02:00
Nikolas Klauser
9f00ab411a
[libc++] Add [[nodiscard]] to the vector accessor functions (#150615) 2025-07-29 10:30:37 +02:00
Hui
692c5cdb56
[libc++] Do not call reserve in flat containers if underlying container is user defined (#140379)
This is brought up in the LWG reflector. We currently call `reserve` if
the underlying container has one. But the spec does not specify what
`reserve` should do for Sequence Container. So in theory if the
underlying container is user defined type and it can have a function
called `reserve` which does something completely different.

The fix is to just call `reserve` for STL containers if it has one
2025-06-07 08:47:46 +01:00
A. Jiang
e9ce752769
[libc++] Remove the constexpr hash<vector<bool>> extension (#132617)
libc++ makes the `hash<vector<bool, A>>::operator()` `constexpr` since
C++20, which is a conforming extension, but it was unintended.

This patch removes the extension, with an escape hatch macro for it, and
the escape hatch will be removed in the future. Test cases for
`constexpr` along with the assumption of hash values are moved to the
`libcxx/test/libcxx/` subdirectory.

---------

Co-authored-by: Louis Dionne <ldionne.2@gmail.com>
2025-05-14 07:20:27 +08:00
Nikolas Klauser
df78e288c3
[libc++] Use __is_address_in_range in vector (#139032)
This avoids a branch in `vector`s code on whether we're constant
evaluating, which improves our coverage of constant-evaluated code.
2025-05-09 21:45:32 +02:00
Louis Dionne
45d493b680
[libc++] Add the __is_replaceable type trait (#132408)
That type trait represents whether move-assigning an object is
equivalent to destroying it and then move-constructing a new one from
the same argument. This will be useful in a few places where we may want
to destroy + construct instead of doing an assignment, in particular
when implementing some container operations in terms of relocation.

This is effectively adding a library emulation of P2786R12's
is_replaceable trait, similarly to what we do for trivial relocation.
Eventually, we can replace this library emulation by the real
compiler-backed trait.

This is building towards #129328.
2025-05-08 16:35:00 -04:00
Nikolas Klauser
f25f9e480b
[libc++][NFC] Remove a bunch of redundant ASan existence checks (#128504)
There are currently lots of `_LIBCPP_HAS_ASAN` and
`__libcpp_is_constant_evaluated()` checks which aren't needed, since it
is centrally checked inside `__debug_utils/sanitizers.h`.
2025-05-06 22:16:58 +02:00
Nikolas Klauser
8c3aa3e81c
[libc++][NFC] Replace typedefs with using declarations in <vector> (#134083)
This brings the code base a bit closer to using `using` declarations
everywhere.
2025-05-03 08:39:48 +02:00
Nikolas Klauser
af9c04fa68
[libc++] Remove _LIBCPP_TEMPLATE_VIS (#134885)
The need for `_LIBCPP_TEMPLATE_VIS` has been removed in #133233.
2025-04-09 23:47:57 +02:00
Peng Liu
e6c2fdc90f
[libc++] Fix ambiguous call to std::max in vector<bool> (#119801)
Closes #121713.
2025-04-02 11:14:14 -04:00
Louis Dionne
fc5b4d4a9d
[libc++] Rename __construct_one_at_end to __emplace_back_assume_capacity (#132276)
This makes it clear that the end of the vector is updated when calling
the function.
2025-03-25 14:27:54 -04:00
Nikolas Klauser
a8e168e0c1
[libc++][NFC] Replace structs with variable templates in <__memory/allocator_traits.h> (#129237)
Variable templates are a bit easier on the compiler and improve the
readability of the code.
2025-03-25 15:58:24 +01:00
Peng Liu
c5195ae2d0
[libc++] Fix {std, ranges}::equal for vector<bool> with small storage types (#130394)
The current implementation of `{std, ranges}::equal` fails to correctly
compare `vector<bool>`s when the underlying storage type is smaller than
`int` (e.g., `unsigned char`, `unsigned short`, `uint8_t` and
`uint16_t`). See [demo](https://godbolt.org/z/j4s87s6b3)). The problem
arises due to integral promotions on the intermediate bitwise
operations, leading to incorrect final equality comparison results. This
patch fixes the issue by ensuring that `{std, ranges}::equal` operate
properly for both aligned and unaligned bits.
 
Fixes #126369.
2025-03-19 11:51:21 -04:00
Louis Dionne
351bcd9fe2 [libc++][NFC] Add a comment that an include is a workaround 2025-03-18 11:03:42 -04:00
Peng Liu
4baf1c03fa
[libc++] Optimize ranges::rotate for vector<bool>::iterator (#121168)
This PR optimizes the performance of `std::ranges::rotate` for
`vector<bool>::iterator`. The optimization yields a performance
improvement of up to 2096x.

Closes #64038.
2025-03-13 14:07:23 -04:00
A. Jiang
5bf1f03d1f
[libc++] Fix assignment in insertion into vector (#116001)
Changes:
- Avoid direct assignment in iterator-pair `insert` overload and
`insert_range`, except when the assignment is move assignment.
2025-03-04 09:06:49 +08:00
Peng Liu
7717a549e9
[libc++] Optimize ranges::equal for vector<bool>::iterator (#121084)
This PR optimizes the performance of `std::ranges::equal` for
`vector<bool>::iterator`, addressing a subtask outlined in issue #64038.
The optimizations yield performance improvements of up to 188x for
aligned equality comparison and 82x for unaligned equality
comparison. Moreover, comprehensive tests covering up to 4 storage words
(256 bytes) with odd and even bit sizes are provided, which validate the
proposed optimizations in this patch.
2025-02-26 12:18:25 -05:00
Louis Dionne
5e26fb1699
[libc++] Qualify calls to nullary functions like __throw_foo (#122465)
This is technically not necessary in most cases to prevent issues with ADL,
but let's be consistent. This allows us to remove the libcpp-qualify-declval
clang-tidy check, which is now enforced by the robust-against-adl clang-tidy check.
2025-02-21 07:59:46 -05:00
Takuto Ikuta
672e3858a4
[libcxx] Add a missing include for __bit_iterator (#127015)
This is to fix compile error with explicit Clang modules like
```
../../third_party/libc++/src/include/__vector/vector_bool.h:85:11: error: default argument of '__bit_iterator' must be imported from module 'std.bit_reference_fwd' before it is required
   85 |   typedef __bit_iterator<vector, false> pointer;
      |           ^
../../third_party/libc++/src/include/__fwd/bit_reference.h:23:68: note: default argument declared here is not reachable
   23 | template <class _Cp, bool _IsConst, typename _Cp::__storage_type = 0>
      |                                                                    ^
```
2025-02-13 08:54:43 +01:00
Nikolas Klauser
1117568dad
[libc++][NFC] Remove __default_allocator_type aliases (#126066)
These aliases are never used, so we can ditch them.
2025-02-06 19:28:12 +01:00
Peng Liu
efa287dd8a
[libc++] Slightly simplify max_size and add new tests for vector (#119990)
This PR slightly simplifies the implementation of `vector<bool>::max_size`
and adds extensive tests for the `max_size()` function for both `vector<bool>`
and `vector<T>`. The main purposes of the new tests include:

- Verify correctness of `max_size()` under various `size_type` and
  `difference_type` definitions: check that `max_size()` works properly
  with allocators that have custom `size_type` and `difference_type`. This
  is particularly useful for `vector<bool>`, as different `size_type` lead
  to different `__storage_type` of different word lengths, resulting in
  varying `max_size()` values for `vector<bool>`. Additionally, different
  `difference_type` also sets different upper limit of `max_size()` for
  both `vector<bool>` and `std::vector`. These tests were previously
  missing.

- Eliminate incorrect implementations: Special tests are added to identify and
  reject incorrect implementations of `vector<bool>::max_size` that unconditionally
  return `std::min<size_type>(size-max, __internal_cap_to_external(allocator-max-size))`.
  This can cause overflow in the `__internal_cap_to_external()` call and lead
  to incorrect results. The new tests ensure that such incorrect
  implementations are identified.
2025-02-05 22:38:32 -05:00
Louis Dionne
ccb08b9dab
[libc++] Also provide an alignment assumption for vector in C++03 mode (#124839)
There's no reason not to, and it's easy enough to do using enable_if. As
a drive-by change, also add a missing _LIBCPP_NO_CFI attribute on
__add_alignment_assumption.
2025-02-05 08:57:22 -05:00
Peng Liu
edc3dc6abd
[libc++] Optimize ranges::copy_backward for vector<bool>::iterator (#121026)
As a follow-up to #121013 (which focused on `std::ranges::copy`), this
PR optimizes the performance of `std::ranges::copy_backward` for
`vector<bool>::iterator`, addressing a subtask outlined in issue #64038.
The optimizations yield performance improvements of up to 2000x for
aligned copies and 60x for unaligned copies.
2025-01-30 14:55:05 -05:00
Peng Liu
67752f6191
[libc++] Simplify vector<bool>::__construct_at_end (#119632)
This patch simplifies the implementation of `__construct_at_end` in
`vector<bool>`, which currently contains duplicate initialization logic
across its two overloads.
2025-01-29 11:46:57 -05:00
A. Jiang
733a98db4a
[libc++] Fix input-only range handling for vector (#116157)
Changes:
- Carve out sized but input-only ranges for C++23.
- Call `std::move` for related functions when the iterator is possibly input-only.

Fixes #115727
2025-01-21 16:30:42 -05:00
Peng Liu
2d317d903a
[libc++] Fix no-op shrink_to_fit for vector<bool> (#120495)
This PR addresses an issue where the `shrink_to_fit` function in
`vector<bool>` is effectively a no-op, meaning it will never shrink the
capacity.

Fixes #122502
2025-01-21 16:28:58 -05:00
Dominic Chen
9b853f63be
[libc++] Fix vector sanitization annotations on destruction (#121031)
In https://reviews.llvm.org/D136765 / https://reviews.llvm.org/D144155,
the asan annotations for `std::vector` were modified to unpoison freed
backing memory on destruction, instead of leaving it poisoned. However,
calling `__clear()` instead of `clear()` skips informing the asan runtime
of this decrease in the accessible container size, which breaks the
invariant that the value of `old_mid` should match the value of `new_mid`
from the previous call to `__sanitizer_annotate_contiguous_container`, which
can trip the sanity checks for the partial poison between [d1, d2) and the
container redzone between [d2, c), if enabled. To fix this, ensure that
`clear()` is called instead, as is already done by `__vdeallocate()`.
Also remove `__clear()`, since it is no longer called.
2025-01-20 08:57:52 -05:00
Florian Hahn
eac23a5b97
[libc++] Add assumption for align of begin and end pointers of vector. (#108961)
Missing information about begin and end pointers of std::vector can lead
to missed optimizations in LLVM.

This patch adds alignment assumptions at the point where the begin and
end pointers are loaded. If the pointers would not have the same
alignment, end might never get hit when incrementing begin.

See https://github.com/llvm/llvm-project/issues/101372 for a discussion
of missed range check optimizations in hardened mode.

Once https://github.com/llvm/llvm-project/pull/108958 lands, the created
`llvm.assume` calls for the alignment should be folded into the `load`
instructions, resulting in no extra instructions after InstCombine.

Co-authored-by: Louis Dionne <ldionne.2@gmail.com>
2025-01-16 10:57:01 -05:00
Peng Liu
0298e58c7d
[libc++] Optimize input_iterator-pair insert for std::vector (#113768)
As a follow-up to #113852, this PR optimizes the performance of the
`insert(const_iterator pos, InputIt first, InputIt last)` function for
`input_iterator`-pair inputs in `std::vector` for cases where
reallocation occurs during insertion. Additionally, this optimization
enhances exception safety by replacing the traditional `try-catch`
mechanism with a modern exception guard for the `insert` function.

The optimization targets cases where insertion trigger reallocation. In
scenarios without reallocation, the implementation remains unchanged.

Previous implementation
-----------------------
The previous implementation of `insert` is inefficient in reallocation
scenarios because it performs the following steps separately:
- `reserve()`: This leads to the first round of relocating old
elements to new memory;
- `rotate()`: This leads to the second round of reorganizing the
existing elements;
- Move-forward: Moves the elements after the insertion position to
their final positions.
- Insert: performs the actual insertion.

This approach results in a lot of redundant operations, requiring the
elements to undergo three rounds of relocations/reorganizations to be
placed in their final positions.

Proposed implementation
-----------------------
The proposed implementation jointly optimize the above 4 steps in the
previous implementation such that each element is placed in its final
position in just one round of relocation. Specifically, this
optimization reduces the total cost from 2 relocations + 1 std::rotate
call to just 1 relocation, without needing to call `std::rotate`,
thereby significantly improving overall performance.
2025-01-14 11:40:29 -05:00