diff --git a/llvm/include/llvm/IR/ValueHandle.h b/llvm/include/llvm/IR/ValueHandle.h --- a/llvm/include/llvm/IR/ValueHandle.h +++ b/llvm/include/llvm/IR/ValueHandle.h @@ -307,30 +307,10 @@ ValueTy &operator*() const { return *getValPtr(); } }; -// Specialize DenseMapInfo to allow AssertingVH to participate in DenseMap. +// Treat AssertingVH like T* inside maps. This also allows using find_as() +// to look up a value without constructing a value handle. template -struct DenseMapInfo> { - static inline AssertingVH getEmptyKey() { - AssertingVH Res; - Res.setRawValPtr(DenseMapInfo::getEmptyKey()); - return Res; - } - - static inline AssertingVH getTombstoneKey() { - AssertingVH Res; - Res.setRawValPtr(DenseMapInfo::getTombstoneKey()); - return Res; - } - - static unsigned getHashValue(const AssertingVH &Val) { - return DenseMapInfo::getHashValue(Val.getRawValPtr()); - } - - static bool isEqual(const AssertingVH &LHS, const AssertingVH &RHS) { - return DenseMapInfo::isEqual(LHS.getRawValPtr(), - RHS.getRawValPtr()); - } -}; +struct DenseMapInfo> : DenseMapInfo {}; /// Value handle that tracks a Value across RAUW. /// @@ -562,6 +542,17 @@ return DenseMapInfo::isEqual(LHS.getRawValPtr(), RHS.getRawValPtr()); } + + // Allow lookup by T* via find_as(), without constructing a temporary + // value handle. + + static unsigned getHashValue(const T *Val) { + return DenseMapInfo::getHashValue(Val); + } + + static bool isEqual(const T *LHS, const PoisoningVH &RHS) { + return DenseMapInfo::isEqual(LHS, RHS.getRawValPtr()); + } }; } // end namespace llvm diff --git a/llvm/unittests/IR/ValueHandleTest.cpp b/llvm/unittests/IR/ValueHandleTest.cpp --- a/llvm/unittests/IR/ValueHandleTest.cpp +++ b/llvm/unittests/IR/ValueHandleTest.cpp @@ -491,6 +491,30 @@ EXPECT_TRUE(DenseMapInfo>::isEqual(VH, BitcastV.get())); } +TEST_F(ValueHandle, AssertingVH_DenseMap) { + DenseMap, int> Map; + Map.insert({BitcastV.get(), 1}); + Map.insert({ConstantV, 2}); + // These will create a temporary AssertingVH during lookup. + EXPECT_TRUE(Map.find(BitcastV.get()) != Map.end()); + EXPECT_TRUE(Map.find(ConstantV) != Map.end()); + // These will not create a temporary AssertingVH. + EXPECT_TRUE(Map.find_as(BitcastV.get()) != Map.end()); + EXPECT_TRUE(Map.find_as(ConstantV) != Map.end()); +} + +TEST_F(ValueHandle, PoisoningVH_DenseMap) { + DenseMap, int> Map; + Map.insert({BitcastV.get(), 1}); + Map.insert({ConstantV, 2}); + // These will create a temporary PoisoningVH during lookup. + EXPECT_TRUE(Map.find(BitcastV.get()) != Map.end()); + EXPECT_TRUE(Map.find(ConstantV) != Map.end()); + // These will not create a temporary PoisoningVH. + EXPECT_TRUE(Map.find_as(BitcastV.get()) != Map.end()); + EXPECT_TRUE(Map.find_as(ConstantV) != Map.end()); +} + #ifdef NDEBUG TEST_F(ValueHandle, PoisoningVH_ReducesToPointer) {