[llvm] r290952 - [ADT] Enhance the PriorityWorklist to support bulk insertion.
Chandler Carruth via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 4 03:13:12 PST 2017
Author: chandlerc
Date: Wed Jan 4 05:13:11 2017
New Revision: 290952
URL: http://llvm.org/viewvc/llvm-project?rev=290952&view=rev
Log:
[ADT] Enhance the PriorityWorklist to support bulk insertion.
This is both convenient and more efficient as we can skip any
intermediate reallocation of the vector.
This usage pattern came up in a subsequent patch on the pass manager,
but it seems generically useful so I factored it out and added unittests
here.
Modified:
llvm/trunk/include/llvm/ADT/PriorityWorklist.h
llvm/trunk/unittests/ADT/PriorityWorklistTest.cpp
Modified: llvm/trunk/include/llvm/ADT/PriorityWorklist.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/PriorityWorklist.h?rev=290952&r1=290951&r2=290952&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ADT/PriorityWorklist.h (original)
+++ llvm/trunk/include/llvm/ADT/PriorityWorklist.h Wed Jan 4 05:13:11 2017
@@ -18,6 +18,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Sequence.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Compiler.h"
#include <algorithm>
@@ -107,6 +108,35 @@ public:
return false;
}
+ /// Insert a sequence of new elements into the PriorityWorklist.
+ template <typename SequenceT>
+ typename std::enable_if<!std::is_convertible<SequenceT, T>::value>::type
+ insert(SequenceT &&Input) {
+ // First pull the input sequence into the vector as a bulk append
+ // operation.
+ ptrdiff_t StartIndex = V.size();
+ V.insert(V.end(), std::begin(Input), std::end(Input));
+ // Now walk backwards fixing up the index map and deleting any duplicates.
+ for (auto i : reverse(seq<ptrdiff_t>(StartIndex, V.size()))) {
+ auto InsertResult = M.insert({V[i], i});
+ if (InsertResult.second)
+ continue;
+
+ // If the existing index is before this insert's start, nuke that one and
+ // move it up.
+ ptrdiff_t &Index = InsertResult.first->second;
+ if (Index < StartIndex) {
+ V[Index] = T();
+ Index = i;
+ continue;
+ }
+
+ // Otherwise the existing one comes first so just clear out the value in
+ // this slot.
+ V[i] = T();
+ }
+ }
+
/// Remove the last element of the PriorityWorklist.
void pop_back() {
assert(!empty() && "Cannot remove an element when empty!");
@@ -169,6 +199,11 @@ public:
return true;
}
+ /// Reverse the items in the PriorityWorklist.
+ ///
+ /// This does an in-place reversal. Other kinds of reverse aren't easy to
+ /// support in the face of the worklist semantics.
+
/// Completely clear the PriorityWorklist
void clear() {
M.clear();
Modified: llvm/trunk/unittests/ADT/PriorityWorklistTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/PriorityWorklistTest.cpp?rev=290952&r1=290951&r2=290952&view=diff
==============================================================================
--- llvm/trunk/unittests/ADT/PriorityWorklistTest.cpp (original)
+++ llvm/trunk/unittests/ADT/PriorityWorklistTest.cpp Wed Jan 4 05:13:11 2017
@@ -13,6 +13,8 @@
#include "llvm/ADT/PriorityWorklist.h"
#include "gtest/gtest.h"
+#include <list>
+#include <vector>
namespace {
@@ -72,6 +74,43 @@ TYPED_TEST(PriorityWorklistTest, Basic)
EXPECT_TRUE(W.empty());
}
+TYPED_TEST(PriorityWorklistTest, InsertSequence) {
+ TypeParam W;
+ ASSERT_TRUE(W.insert(2));
+ ASSERT_TRUE(W.insert(4));
+ ASSERT_TRUE(W.insert(7));
+ // Insert a sequence that has internal duplicates and a duplicate among
+ // existing entries.
+ W.insert(std::vector<int>({42, 13, 42, 7, 8}));
+ EXPECT_EQ(8, W.pop_back_val());
+ EXPECT_EQ(7, W.pop_back_val());
+ EXPECT_EQ(42, W.pop_back_val());
+ EXPECT_EQ(13, W.pop_back_val());
+ EXPECT_EQ(4, W.pop_back_val());
+ EXPECT_EQ(2, W.pop_back_val());
+ ASSERT_TRUE(W.empty());
+
+ // Simpler tests with various other input types.
+ ASSERT_TRUE(W.insert(2));
+ ASSERT_TRUE(W.insert(7));
+ // Use a non-random-access container.
+ W.insert(std::list<int>({7, 5}));
+ EXPECT_EQ(5, W.pop_back_val());
+ EXPECT_EQ(7, W.pop_back_val());
+ EXPECT_EQ(2, W.pop_back_val());
+ ASSERT_TRUE(W.empty());
+
+ ASSERT_TRUE(W.insert(2));
+ ASSERT_TRUE(W.insert(7));
+ // Use a raw array.
+ int A[] = {7, 5};
+ W.insert(A);
+ EXPECT_EQ(5, W.pop_back_val());
+ EXPECT_EQ(7, W.pop_back_val());
+ EXPECT_EQ(2, W.pop_back_val());
+ ASSERT_TRUE(W.empty());
+}
+
TYPED_TEST(PriorityWorklistTest, EraseIf) {
TypeParam W;
W.insert(23);
More information about the llvm-commits
mailing list