[llvm] r327219 - [ADT] Shuffle containers before sorting to uncover non-deterministic behavior
Mandeep Singh Grang via llvm-commits
llvm-commits at lists.llvm.org
Sat Mar 10 10:59:14 PST 2018
Author: mgrang
Date: Sat Mar 10 10:59:14 2018
New Revision: 327219
URL: http://llvm.org/viewvc/llvm-project?rev=327219&view=rev
Log:
[ADT] Shuffle containers before sorting to uncover non-deterministic behavior
Summary:
std::sort and array_pod_sort both use non-stable sorting algorithms.
This means that the relative order of elements with the same key is
undefined. This patch is an attempt to uncover such scenarios by
randomly shuffling all containers before sorting, if EXPENSIVE_CHECKS
is enabled.
Here's the bugzilla for this: https://bugs.llvm.org/show_bug.cgi?id=35135
Reviewers: dblaikie, dexonsmith, chandlerc, efriedma, RKSimon
Reviewed By: RKSimon
Subscribers: fhahn, davide, RKSimon, vsk, mgorny, llvm-commits
Differential Revision: https://reviews.llvm.org/D39245
Modified:
llvm/trunk/include/llvm/ADT/STLExtras.h
Modified: llvm/trunk/include/llvm/ADT/STLExtras.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/STLExtras.h?rev=327219&r1=327218&r2=327219&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ADT/STLExtras.h (original)
+++ llvm/trunk/include/llvm/ADT/STLExtras.h Sat Mar 10 10:59:14 2018
@@ -36,6 +36,10 @@
#include <type_traits>
#include <utility>
+#ifdef EXPENSIVE_CHECKS
+#include <random> // for std::mt19937
+#endif
+
namespace llvm {
// Only used by compiler if both template types are the same. Useful when
@@ -762,6 +766,10 @@ inline void array_pod_sort(IteratorTy St
// behavior with an empty sequence.
auto NElts = End - Start;
if (NElts <= 1) return;
+#ifdef EXPENSIVE_CHECKS
+ std::mt19937 Generator(std::random_device{}());
+ std::shuffle(Start, End, Generator);
+#endif
qsort(&*Start, NElts, sizeof(*Start), get_array_pod_sort_comparator(*Start));
}
@@ -775,10 +783,34 @@ inline void array_pod_sort(
// behavior with an empty sequence.
auto NElts = End - Start;
if (NElts <= 1) return;
+#ifdef EXPENSIVE_CHECKS
+ std::mt19937 Generator(std::random_device{}());
+ std::shuffle(Start, End, Generator);
+#endif
qsort(&*Start, NElts, sizeof(*Start),
reinterpret_cast<int (*)(const void *, const void *)>(Compare));
}
+// Provide wrappers to std::sort which shuffle the elements before sorting
+// to help uncover non-deterministic behavior (PR35135).
+template <typename IteratorTy>
+inline void sort(IteratorTy Start, IteratorTy End) {
+#ifdef EXPENSIVE_CHECKS
+ std::mt19937 Generator(std::random_device{}());
+ std::shuffle(Start, End, Generator);
+#endif
+ std::sort(Start, End);
+}
+
+template <typename IteratorTy, typename Compare>
+inline void sort(IteratorTy Start, IteratorTy End, Compare Comp) {
+#ifdef EXPENSIVE_CHECKS
+ std::mt19937 Generator(std::random_device{}());
+ std::shuffle(Start, End, Generator);
+#endif
+ std::sort(Start, End, Comp);
+}
+
//===----------------------------------------------------------------------===//
// Extra additions to <algorithm>
//===----------------------------------------------------------------------===//
More information about the llvm-commits
mailing list