From 1c3423f7740fa89bb9e7a6b145f2312bcfcaf95c Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Sat, 28 Mar 2020 18:47:26 +0100 Subject: [PATCH] [ADT] Automatically forward llvm::sort to array_pod_sort if safe This is safe if the iterator type is a pointer and the comparator is stateless. The enable_if pattern I'm adding here only uses array_pod_sort for the default comparator (std::less). Using array_pod_sort has a potential performance impact, but I didn't notice anything when testing clang. Sorting doesn't seem to be on the hot path anywhere in LLVM. Shrinks Release+Asserts clang by 73k. --- include/llvm/ADT/STLExtras.h | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/include/llvm/ADT/STLExtras.h b/include/llvm/ADT/STLExtras.h index e5620bedb0c..a6619adc44b 100644 --- a/include/llvm/ADT/STLExtras.h +++ b/include/llvm/ADT/STLExtras.h @@ -1105,9 +1105,20 @@ inline void array_pod_sort( reinterpret_cast(Compare)); } +namespace detail { +template +// We can use qsort if the iterator type is a pointer and the underlying value +// is trivially copyable. +using sort_trivially_copyable = conjunction< + std::is_pointer, + is_trivially_copyable::value_type>>; +} // namespace detail + // Provide wrappers to std::sort which shuffle the elements before sorting // to help uncover non-deterministic behavior (PR35135). -template +template ::value, + int> = 0> inline void sort(IteratorTy Start, IteratorTy End) { #ifdef EXPENSIVE_CHECKS detail::presortShuffle(Start, End); @@ -1115,6 +1126,15 @@ inline void sort(IteratorTy Start, IteratorTy End) { std::sort(Start, End); } +// Forward trivially copyable types to array_pod_sort. This avoids a large +// amount of code bloat for a minor performance hit. +template ::value, + int> = 0> +inline void sort(IteratorTy Start, IteratorTy End) { + array_pod_sort(Start, End); +} + template inline void sort(Container &&C) { llvm::sort(adl_begin(C), adl_end(C)); }