mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 10:42:39 +01:00
[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. llvm-svn: 290952
This commit is contained in:
parent
53828bbf87
commit
5c979966df
@ -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();
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user