diff --git a/llvm/include/llvm/ADT/GenericCycleImpl.h b/llvm/include/llvm/ADT/GenericCycleImpl.h --- a/llvm/include/llvm/ADT/GenericCycleImpl.h +++ b/llvm/include/llvm/ADT/GenericCycleImpl.h @@ -177,8 +177,7 @@ CurrentContainer.pop_back(); Child->ParentCycle = NewParent; - NewParent->Blocks.insert(NewParent->Blocks.end(), Child->block_begin(), - Child->block_end()); + NewParent->Blocks.insert(Child->block_begin(), Child->block_end()); for (auto &It : BlockMapTopLevel) if (It.second == Child) @@ -266,7 +265,7 @@ } else { Info.BlockMap.try_emplace(Block, NewCycle.get()); assert(!is_contained(NewCycle->Blocks, Block)); - NewCycle->Blocks.push_back(Block); + NewCycle->Blocks.insert(Block); ProcessPredecessors(Block); Info.BlockMapTopLevel.try_emplace(Block, NewCycle.get()); } diff --git a/llvm/include/llvm/ADT/GenericCycleInfo.h b/llvm/include/llvm/ADT/GenericCycleInfo.h --- a/llvm/include/llvm/ADT/GenericCycleInfo.h +++ b/llvm/include/llvm/ADT/GenericCycleInfo.h @@ -28,16 +28,12 @@ #ifndef LLVM_ADT_GENERICCYCLEINFO_H #define LLVM_ADT_GENERICCYCLEINFO_H -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/GenericSSAContext.h" #include "llvm/ADT/GraphTraits.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/iterator.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/Printable.h" #include "llvm/Support/raw_ostream.h" -#include namespace llvm { @@ -67,7 +63,9 @@ /// Basic blocks that are contained in the cycle, including entry blocks, /// and including blocks that are part of a child cycle. - std::vector Blocks; + using BlockSetVectorT = SetVector, + SmallPtrSet>; + BlockSetVectorT Blocks; /// Depth of the cycle in the tree. The root "cycle" is at depth 0. /// @@ -85,7 +83,7 @@ } void appendEntry(BlockT *Block) { Entries.push_back(Block); } - void appendBlock(BlockT *Block) { Blocks.push_back(Block); } + void appendBlock(BlockT *Block) { Blocks.insert(Block); } GenericCycle(const GenericCycle &) = delete; GenericCycle &operator=(const GenericCycle &) = delete; @@ -110,9 +108,7 @@ } /// \brief Return whether \p Block is contained in the cycle. - bool contains(const BlockT *Block) const { - return is_contained(Blocks, Block); - } + bool contains(const BlockT *Block) const { return Blocks.contains(Block); } /// \brief Returns true iff this cycle contains \p C. /// @@ -171,7 +167,7 @@ /// Iteration over blocks in the cycle (including entry blocks). //@{ - using const_block_iterator = typename std::vector::const_iterator; + using const_block_iterator = typename BlockSetVectorT::const_iterator; const_block_iterator block_begin() const { return const_block_iterator{Blocks.begin()}; diff --git a/llvm/include/llvm/ADT/SetVector.h b/llvm/include/llvm/ADT/SetVector.h --- a/llvm/include/llvm/ADT/SetVector.h +++ b/llvm/include/llvm/ADT/SetVector.h @@ -35,14 +35,23 @@ /// This adapter class provides a way to keep a set of things that also has the /// property of a deterministic iteration order. The order of iteration is the /// order of insertion. +/// +/// The key and value types are derived from the Set and Vector types +/// respectively. This allows the vector-type operations and set-type operations +/// to have different types. In particular, this is useful when storing pointers +/// as "Foo *" values but looking them up as "const Foo *" keys. +/// +/// No constraint is placed on the key and value types, although it is assumed +/// that value_type can be converted into key_type for insertion. Users must be +/// aware of any loss of information in this conversion. template , typename Set = DenseSet> class SetVector { public: - using value_type = T; - using key_type = T; - using reference = T&; - using const_reference = const T&; + using value_type = typename Vector::value_type; + using key_type = typename Set::key_type; + using reference = value_type &; + using const_reference = const value_type &; using set_type = Set; using vector_type = Vector; using iterator = typename vector_type::const_iterator; @@ -60,7 +69,7 @@ insert(Start, End); } - ArrayRef getArrayRef() const { return vector_; } + ArrayRef getArrayRef() const { return vector_; } /// Clear the SetVector and return the underlying vector. Vector takeVector() { @@ -119,13 +128,13 @@ } /// Return the first element of the SetVector. - const T &front() const { + const value_type &front() const { assert(!empty() && "Cannot call front() on empty SetVector!"); return vector_.front(); } /// Return the last element of the SetVector. - const T &back() const { + const value_type &back() const { assert(!empty() && "Cannot call back() on empty SetVector!"); return vector_.back(); } @@ -222,8 +231,8 @@ vector_.pop_back(); } - [[nodiscard]] T pop_back_val() { - T Ret = back(); + [[nodiscard]] value_type pop_back_val() { + value_type Ret = back(); pop_back(); return Ret; } diff --git a/llvm/include/llvm/ADT/SmallSet.h b/llvm/include/llvm/ADT/SmallSet.h --- a/llvm/include/llvm/ADT/SmallSet.h +++ b/llvm/include/llvm/ADT/SmallSet.h @@ -149,7 +149,9 @@ static_assert(N <= 32, "N should be small"); public: + using key_type = T; using size_type = size_t; + using value_type = T; using const_iterator = SmallSetIterator; SmallSet() = default; diff --git a/llvm/unittests/ADT/SetVectorTest.cpp b/llvm/unittests/ADT/SetVectorTest.cpp --- a/llvm/unittests/ADT/SetVectorTest.cpp +++ b/llvm/unittests/ADT/SetVectorTest.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallPtrSet.h" #include "gtest/gtest.h" using namespace llvm; @@ -48,3 +49,40 @@ S.remove(2); EXPECT_FALSE(S.contains(2)); } + +TEST(SetVector, ConstPtrKeyTest) { + SetVector, SmallPtrSet> S, T; + int i, j, k, m, n; + + S.insert(&i); + S.insert(&j); + S.insert(&k); + + EXPECT_TRUE(S.contains(&i)); + EXPECT_TRUE(S.contains(&j)); + EXPECT_TRUE(S.contains(&k)); + + EXPECT_TRUE(S.contains((const int *)&i)); + EXPECT_TRUE(S.contains((const int *)&j)); + EXPECT_TRUE(S.contains((const int *)&k)); + + EXPECT_TRUE(S.contains(S[0])); + EXPECT_TRUE(S.contains(S[1])); + EXPECT_TRUE(S.contains(S[2])); + + S.remove(&k); + EXPECT_FALSE(S.contains(&k)); + EXPECT_FALSE(S.contains((const int *)&k)); + + T.insert(&j); + T.insert(&m); + T.insert(&n); + + EXPECT_TRUE(S.set_union(T)); + EXPECT_TRUE(S.contains(&m)); + EXPECT_TRUE(S.contains((const int *)&m)); + + S.set_subtract(T); + EXPECT_FALSE(S.contains(&j)); + EXPECT_FALSE(S.contains((const int *)&j)); +}