[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