[libcxx-commits] [libcxx] [libc++] Optimize __hash_table copy constructors and assignment (PR #151951)

via libcxx-commits libcxx-commits at lists.llvm.org
Sun Sep 21 17:05:16 PDT 2025


asmok-g wrote:

IDK if it helps, but I tried reducing the issue:
```
namespace std {
template <int __v> struct integral_constant {
  static const int value = __v;
};
void __libcpp_verbose_abort();
template <class>
constexpr bool is_copy_constructible_v =
    integral_constant<__is_constructible(int)>::value;
template <class _Tp> using remove_reference_t = _Tp;
template <int, class _If, class> struct conditional {
  using type = _If;
};
template <class _If, class _Then> struct conditional<false, _If, _Then> {
  using type = _Then;
};
template <bool _Bp, class _IfRes, class _ElseRes>
using conditional_t = conditional<_Bp, _IfRes, _ElseRes>::type;
template <class _Tp> struct __type_identity {
  typedef _Tp type;
};
struct __empty;
template <class...> struct common_type;
template <class> using __common_type_t = common_type<>;
template <class... _Args>
struct common_type : __builtin_common_type<__common_type_t, __type_identity,
                                           __empty, _Args...> {};
template <class... _Tp> using common_type_t = common_type<_Tp...>::type;
template <class _Default, template <class> class>
using __detected_or_t = _Default;
} // namespace std
bool __set_long_cap___trans_tmp_3;
namespace std {
inline namespace __u {
struct basic_string;
template <class... _Args> void construct_at(_Args... __args) {
  basic_string(__args...);
}
template <class... _Args> void __construct_at(_Args... __args) {
  construct_at(__args...);
}
template <class _Tp> using __pointer_member = _Tp;
template <class _Tp, class>
using __pointer = __detected_or_t<_Tp *, __pointer_member>;
template <class _Tp> using __size_type_member = _Tp;
template <class, class _DiffType>
using __size_type = __detected_or_t<_DiffType, __size_type_member>;
template <class, class> struct __allocator_traits_rebind;
template <template <class...> class _Alloc, class _Tp, class... _Args,
          class _Up>
struct __allocator_traits_rebind<_Alloc<_Tp, _Args...>, _Up> {
  using type = _Alloc<_Up>;
};
template <class _Alloc, class _Tp>
using __allocator_traits_rebind_t =
    __allocator_traits_rebind<_Alloc, _Tp>::type;
template <class _Alloc> struct allocator_traits {
  using allocator_type = _Alloc;
  using size_type =
      __size_type<allocator_type, decltype(static_cast<int *>(nullptr) -
                                           static_cast<int *>(nullptr))>;
  template <class _Tp>
  using rebind_alloc = __allocator_traits_rebind_t<allocator_type, _Tp>;
  template <class _Tp, class... _Args>
  static void construct(allocator_type, _Tp, _Args... __args) {
    __construct_at(__args...);
  }
};
template <class _Traits, class _Tp>
using __rebind_alloc = _Traits::template rebind_alloc<_Tp>;
struct __n_destructor;
template <class _Tp> struct unique_ptr {
  using pointer = __pointer<_Tp, int>;
  template <bool> using _GoodRValRefType = __n_destructor;
  template <bool _Dummy = true> unique_ptr(pointer, _GoodRValRefType<_Dummy>);
  pointer operator->();
};
struct __allocation_result {
  char *ptr;
  decltype(sizeof(int)) count;
};
template <class _Alloc>
__allocation_result __allocate_at_least(_Alloc __alloc,
                                        decltype(sizeof(int)) __n) {
  return {__alloc.allocate(__n), __n};
}
template <class _Tp> struct allocator {
  _Tp *allocate(decltype(sizeof(int)));
};
decltype(sizeof(int)) length(char *);
enum { __min_cap = sizeof(char) };
allocator<char> __alloc_;
template <int>
allocator_traits<char>::size_type
__align_it(allocator_traits<char>::size_type __s) {
  return __s & ~1;
}
void __set_ss(allocator_traits<char>::size_type);
struct basic_string {
  basic_string(char *__s) {
    auto __trans_tmp_1 = length(__s);
    bool __trans_tmp_6;
    allocator_traits<char>::size_type __trans_tmp_5, __trans_tmp_4;
    if (__trans_tmp_1 > __trans_tmp_4)
      __throw_length_error();
    __trans_tmp_6 = __trans_tmp_1 < __min_cap;
    if (__trans_tmp_6)
      __set_ss(__trans_tmp_1);
    else {
      allocator_traits<char>::size_type __guess =
          __align_it<1>(__trans_tmp_1 + 1);
      __libcpp_verbose_abort();
      __trans_tmp_5 = __guess;
    }
    auto __allocation = __allocate_at_least(__alloc_, __trans_tmp_5);
    __set_long_cap___trans_tmp_3 = __allocation.count;
    __libcpp_verbose_abort();
  }
  [[__noreturn__]] void __throw_length_error();
};
template <class _Tp> struct shared_ptr {
  _Tp *operator->();
};
template <class _Tp> struct array {
  using iterator = _Tp *;
  iterator begin();
  iterator end();
};
template <class _Tp> using remove_volatile_t = _Tp;
struct __n {
  basic_string __value_;
};
struct __n_destructor {
  __n_destructor(allocator<__n>);
};
template <class... _Args> void __construct_node(_Args... __args) {
  __rebind_alloc<allocator_traits<allocator<char>>, __n> __na;
  unique_ptr<__n> __h(0, __na);
  basic_string __trans_tmp_2(__h->__value_);
  allocator_traits<__rebind_alloc<allocator_traits<allocator<char>>,
                                  __n>>::construct(__na, __trans_tmp_2,
                                                           __args...);
}
struct __t {
  __t(int);
  template <class... _Args>
  void __emplace_hint_multi(basic_string, _Args... __args) {
    __construct_node(__args...);
  }
};
int multiset___comp;
basic_string cend();
struct multiset {
  __t __t_;
  template <class _InputIterator>
  multiset(_InputIterator __f, _InputIterator __l) : __t_(multiset___comp) {
    insert(__f, __l);
  }
  template <class _InputIterator>
  void insert(_InputIterator __f, _InputIterator) {
    for (basic_string __e = cend();;)
      __t_.__emplace_hint_multi(__e, *__f);
  }
};
} // namespace __u
} // namespace std
template <typename F> struct FirstType {
  using type = F;
};
template <typename... V> using FirstTypeT = FirstType<V...>::type;
template <typename...>
using FirstTypeOrNullptrT = FirstTypeT<decltype(nullptr)>;
template <typename T> struct ContainerImpl {
  using StorageType = std::array<T>;
  static constexpr bool kCanCopyValuesV = std::is_copy_constructible_v<T>;
  template <typename DesiredContainer> operator DesiredContainer() {
    DesiredContainer(values_->begin(), values_->end());
  }
  std::conditional_t<kCanCopyValuesV, std::shared_ptr<StorageType>,
                     std::unique_ptr<StorageType>>
      values_;
};
template <typename> constexpr bool kIsCharArrayV = 0;
template <typename T>
using NoCharArrayT = std::conditional_t<kIsCharArrayV<T>, int, T>;
template <typename T>
using DropVolatileReferenceT =
    std::remove_volatile_t<std::remove_reference_t<T>>;
template <typename...>
using CommonTypeOrNullptrT = NoCharArrayT<
    DropVolatileReferenceT<std::common_type_t<FirstTypeOrNullptrT<>>>>;
template <typename...> using ContainerElementTypeT = CommonTypeOrNullptrT<>;
ContainerImpl<ContainerElementTypeT<>> __trans_tmp_8;
std::multiset s0 = __trans_tmp_8;
```
cmd: `clang '-fsanitize=alignment,array-bounds,null,return,enum,returns-nonnull-attribute,vla-bound,unreachable,float-cast-overflow' '-fsanitize-trap=all'   '-ftrivial-auto-var-init=pattern' -O1`. I tried putting that to godbolt, but I got errors.

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


More information about the libcxx-commits mailing list