[libcxx-commits] [libcxx] [libc++] Optimize `to_chars` for bases 2, 8 and 16 (PR #223222)

David Bayer via libcxx-commits libcxx-commits at lists.llvm.org
Sun Sep 13 02:42:36 PDT 2026


================
@@ -126,21 +131,32 @@ struct _LIBCPP_HIDDEN __integral<2> {
     int __n         = __width(__value);
     if (__n > __cap)
       return {__last, errc::value_too_large};
-
     __last                   = __first + __n;
     char* __p                = __last;
-    const unsigned __divisor = 16;
-    while (__value > __divisor) {
-      unsigned __c = __value % __divisor;
+
+    constexpr auto __ncs_per_word   = 8u;
+    constexpr auto __divisor        = 1u << __ncs_per_word;
+    constexpr auto __dep_mask       = uint64_t{0x0101'0101'0101'0101};
+    constexpr auto __c0_offset_mask = uint64_t{0x3030'3030'3030'3030};
+    while (__value >= __divisor) {
+      const auto __digits = __builtin_elementwise_pdep(static_cast<uint64_t>(__value), __dep_mask);
+      auto __cs            = __digits | __c0_offset_mask;
+#ifdef _LIBCPP_LITTLE_ENDIAN
+      __cs = __builtin_bswap64(__cs);
+#endif
       __value /= __divisor;
-      __p -= 4;
-      std::copy_n(&__base_2_lut[4 * __c], 4, __p);
+      __p -= __ncs_per_word;
+      const auto __chars = __builtin_bit_cast(__chars_storage<__ncs_per_word>, __cs);
+      __builtin_memcpy(__p, __chars.__data, __ncs_per_word);
----------------
davebayer wrote:

The idea is to take bottom `__ncs_per_word` bits
```
0b0101'1010'0110'0110 -> 0b0110'0110
```
distribute each bit to start of a byte within a register
```
0b0110'0110 -> 0x0001'0100'0001;0100
```
add `0x30` (`'0'` character offset) to every byte
```
0x0001'0100'0001;0100 + 0x3030'3030'3030'3030 -> 0x3031'3130'3031'3130
```
byteswap on little endian platforms
```
0x3031'3130'3031'3130 -> 0x3031'3130'3031'3130
```
and copy the result to memory

https://github.com/llvm/llvm-project/pull/223222


More information about the libcxx-commits mailing list