This is an archive of the discontinued LLVM Phabricator instance.

Add a CachedHash structure
ClosedPublic

Authored by rafael on Apr 12 2016, 7:22 PM.

Details

Summary

A DenseMap doesn't store the hashes, so it needs to recompute them when the table is resized.

In some applications the hashing cost is noticeable. That is the case for example in lld for symbol names (StringRef).

This patch adds a templated structure that can wraps any value that can go in a DenseMap and caches the hash.

Diff Detail

Event Timeline

rafael updated this revision to Diff 53511.Apr 12 2016, 7:22 PM
rafael retitled this revision from to Add a CachedHash structure.
rafael updated this object.
rafael added reviewers: ruiu, sanjoy, dblaikie.
rafael added a subscriber: llvm-commits.
sanjoy edited edge metadata.Apr 13 2016, 11:13 PM

This lgtm, but I'd be more comfortable if @dblaikie took a peek to see if there are any C++ gotchas here.

rafael updated this revision to Diff 54422.Apr 20 2016, 2:37 PM
rafael edited edge metadata.

Add assert and tests.

dblaikie accepted this revision.Apr 20 2016, 2:47 PM
dblaikie edited edge metadata.

Looks good apart from some optional feedback - thanks!

include/llvm/ADT/DenseMapInfo.h
34–35

I think you can remove both of these constructors if you're going to use braced init anyway?

(though I guess maybe you need the first because you want implicit conversion from T -> CachedHash)

Also, any desire to make this do the right thing for movable types? I'd probably at least add the "Val(std::move(Val))" in the ctors (whichever ones you keep, if any). That still won't be great for expensive-to-move things, but they're less of a priority & hopefully we just fix them.

unittests/ADT/DenseMapTest.cpp
512

Could just write this as ++*X.Counter if you like. Up to you.

This revision is now accepted and ready to land.Apr 20 2016, 2:47 PM

Comment at: include/llvm/ADT/DenseMapInfo.h:34-35
@@ +33,4 @@
+template <typename T> struct CachedHash {
+ CachedHash(T Val) : Val(Val) { Hash = DenseMapInfo<T>::getHashValue(Val); }
+ CachedHash(T Val, unsigned Hash) : Val(Val), Hash(Hash) {}

+ T Val;

I think you can remove both of these constructors if you're going to use braced init anyway?

(though I guess maybe you need the first because you want implicit conversion from T -> CachedHash)

Correct. And once you have the first you need the second.

Also, any desire to make this do the right thing for movable types? I'd probably at least add the "Val(std::move(Val))" in the ctors (whichever ones you keep, if any). That still won't be great for expensive-to-move things, but they're less of a priority & hopefully we just fix them.

Done.

Comment at: unittests/ADT/DenseMapTest.cpp:512
@@ +511,3 @@
+ static unsigned getHashValue(const CachedHashTest &X) {
+ (*X.Counter)++;

+ return X.Val;

Could just write this as ++*X.Counter if you like. Up to you.

Done.

Cheers,
Rafael

Eugene.Zelenko added a subscriber: Eugene.Zelenko.

Committed in r266981.