[llvm] d3b6e1f - [ADT] Automatically forward llvm::sort to array_pod_sort if safe

Benjamin Kramer via llvm-commits llvm-commits at lists.llvm.org
Sat Mar 28 12:43:38 PDT 2020


Author: Benjamin Kramer
Date: 2020-03-28T20:20:14+01:00
New Revision: d3b6e1f1f93e196669645fd04ab597f8df7580d1

URL: https://github.com/llvm/llvm-project/commit/d3b6e1f1f93e196669645fd04ab597f8df7580d1
DIFF: https://github.com/llvm/llvm-project/commit/d3b6e1f1f93e196669645fd04ab597f8df7580d1.diff

LOG: [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.

Added: 
    

Modified: 
    llvm/include/llvm/ADT/STLExtras.h

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h
index e5620bedb0cd..a6619adc44b3 100644
--- a/llvm/include/llvm/ADT/STLExtras.h
+++ b/llvm/include/llvm/ADT/STLExtras.h
@@ -1105,9 +1105,20 @@ inline void array_pod_sort(
         reinterpret_cast<int (*)(const void *, const void *)>(Compare));
 }
 
+namespace detail {
+template <typename T>
+// 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<T>,
+    is_trivially_copyable<typename std::iterator_traits<T>::value_type>>;
+} // namespace detail
+
 // Provide wrappers to std::sort which shuffle the elements before sorting
 // to help uncover non-deterministic behavior (PR35135).
-template <typename IteratorTy>
+template <typename IteratorTy,
+          std::enable_if_t<!detail::sort_trivially_copyable<IteratorTy>::value,
+                           int> = 0>
 inline void sort(IteratorTy Start, IteratorTy End) {
 #ifdef EXPENSIVE_CHECKS
   detail::presortShuffle<IteratorTy>(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 <typename IteratorTy,
+          std::enable_if_t<detail::sort_trivially_copyable<IteratorTy>::value,
+                           int> = 0>
+inline void sort(IteratorTy Start, IteratorTy End) {
+  array_pod_sort(Start, End);
+}
+
 template <typename Container> inline void sort(Container &&C) {
   llvm::sort(adl_begin(C), adl_end(C));
 }


        


More information about the llvm-commits mailing list