We have SmallDenseMap now that has more correct and predictable
semantics, even though it is a more narrow abstraction.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@158644 91177308-0d34-0410-b5e6-96231b3b80d8
SmallDenseMap::swap.
First, make it parse cleanly. Yay for uninstantiated methods.
Second, make the inline-buckets case work correctly. This is way
trickier than it should be due to the uninitialized values in empty and
tombstone buckets.
Finally fix a few typos that caused construction/destruction mismatches
in the counting unittest.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@158641 91177308-0d34-0410-b5e6-96231b3b80d8
destruction and fix a bug in SmallDenseMap they caught.
This is kind of a poor-man's version of the testing that just adds the
addresses to a set on construction and removes them on destruction. We
check that double construction and double destruction don't occur.
Amusingly enough, this is enough to catch a lot of SmallDenseMap issues
because we spend a lot of time with fixed stable addresses in the inline
buffer.
The SmallDenseMap bug fix included makes grow() not double-destroy in
some cases. It also fixes a FIXME there, the code was pretty crappy. We
now don't have any wasted initialization, but we do move the entries in
inline bucket array an extra time. It's probably a better tradeoff, and
is much easier to get correct.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@158639 91177308-0d34-0410-b5e6-96231b3b80d8
implementation.
This type includes an inline bucket array which is used initially. Once
it is exceeded, an array of 64 buckets is allocated on the heap. The
bucket count grows from there as needed. Some highlights of this
implementation:
- The inline buffer is very carefully aligned, and so supports types
with alignment constraints.
- It works hard to avoid aliasing issues.
- Supports types with non-trivial constructors, destructors, copy
constructions, etc. It works reasonably hard to minimize copies and
unnecessary initialization. The most common initialization is to set
keys to the empty key, and so that should be fast if at all possible.
This class has a performance / space trade-off. It tries to optimize for
relatively small maps, and so packs the inline bucket array densely into
the object. It will be marginally slower than a normal DenseMap in a few
use patterns, so it isn't appropriate everywhere.
The unit tests for DenseMap have been generalized a bit to support
running over different map implementations in addition to different
key/value types. They've then been automatically extended to cover the
new container through the magic of GoogleTest's typed tests.
All of this is still a bit rough though. I'm going to be cleaning up
some aspects of the implementation, documenting things better, and
adding tests which include non-trivial types. As soon as I'm comfortable
with the correctness, I plan to switch existing users of SmallMap over
to this class as it is already more correct w.r.t. construction and
destruction of objects iin the map.
Thanks to Benjamin Kramer for all the reviews of this and the lead-up
patches. That said, more review on this would really be appreciated. As
I've noted a few times, I'm quite surprised how hard it is to get the
semantics for a hashtable-based map container with a small buffer
optimization correct. =]
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@158638 91177308-0d34-0410-b5e6-96231b3b80d8
rather than the base class. Add a pile of boilerplate to indirect around
this.
This is pretty ugly, but it allows the super class to change the
representation of these values, which will be key for doing
a SmallDenseMap.
Suggestions on better method structuring / naming are welcome, but keep
in mind that SmallDenseMap won't have an 'unsigned' member to expose
a reference to... =/
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@158586 91177308-0d34-0410-b5e6-96231b3b80d8
and a derived class that provides the allocation and growth strategy.
This is the first (and biggest) step toward building a SmallDenseMap
that actually behaves exactly the same as DenseMap, and supports all the
same types and interface points with the same semantics.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@158585 91177308-0d34-0410-b5e6-96231b3b80d8
The only missing part is insert(), which uses a pair of parameters and I haven't
figured out how to convert it to rvalue references. It's now possible to use a
DenseMap with std::unique_ptr values :)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@157539 91177308-0d34-0410-b5e6-96231b3b80d8
Otherwise just looking up a value in the map requires creating a VH, adding it to the use lists and destroying it again.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@157124 91177308-0d34-0410-b5e6-96231b3b80d8
Returning a temporary BitVector is very expensive. If you must, create
the temporary explicitly: Use BitVector(A).flip() instead of ~A.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@156768 91177308-0d34-0410-b5e6-96231b3b80d8
These operators were crazy slow, calling malloc to return a temporary
result. At the same time, they look very innocent when used in code.
If you need temporary BitVectors to compute your thing, create them
explicitly, and use the inplace logical operators. This makes the high
cost explicit in the code.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@156767 91177308-0d34-0410-b5e6-96231b3b80d8
This new function provides a way to get the iOS version number from ios triples.
Part of rdar://11409204
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@156483 91177308-0d34-0410-b5e6-96231b3b80d8
The new target machines are:
nvptx (old ptx32) => 32-bit PTX
nvptx64 (old ptx64) => 64-bit PTX
The sources are based on the internal NVIDIA NVPTX back-end, and
contain more functionality than the current PTX back-end currently
provides.
NV_CONTRIB
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@156196 91177308-0d34-0410-b5e6-96231b3b80d8
but using a FoldingSet underneath and with a largely compatible
interface to that of FoldingSet. This can be used anywhere a FoldingSet
would be natural, but iteration order is significant. The initial
intended use case is in Clang's template specialization lists to
preserve instantiation order iteration.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@156131 91177308-0d34-0410-b5e6-96231b3b80d8
Note that support for rvalue references does not imply support
for the full set of move-related STL operations.
I've preserved support for an odd little thing in insert() where
we're trying to support inserting a new element from an existing
one. If we actually want to support that, there's a lot more we
need to do: insert can call either grow or push_back, neither of
which is safe against this particular use pattern.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@155979 91177308-0d34-0410-b5e6-96231b3b80d8
- FlatArrayMap. Very simple map container that uses flat array inside.
- MultiImplMap. Map container interface, that has two modes, one for small amount of elements and one for big amount.
- SmallMap. SmallMap is DenseMap compatible MultiImplMap. It uses FlatArrayMap for small mode, and DenseMap for big mode.
Also added unittests for new classes and update for ProgrammersManual.
For more details about new classes see ProgrammersManual and comments in sourcecode.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@155557 91177308-0d34-0410-b5e6-96231b3b80d8
This nicely handles the most common case of virtual register sets, but
also handles anticipated cases where we will map pointers to IDs.
The goal is not to develop a completely generic SparseSet
template. Instead we want to handle the expected uses within llvm
without any template antics in the client code. I'm adding a bit of
template nastiness here, and some assumption about expected usage in
order to make the client code very clean.
The expected common uses cases I'm designing for:
- integer keys that need to be reindexed, and may map to additional
data
- densely numbered objects where we want pointer keys because no
number->object map exists.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@155227 91177308-0d34-0410-b5e6-96231b3b80d8
DenseMap's hash function uses slightly more entropy and reduces hash collisions
significantly. I also experimented with Hashing.h, but it didn't gave a lot of
improvement while being much more expensive to compute.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@154996 91177308-0d34-0410-b5e6-96231b3b80d8
optimizers could do this for us, but expecting partial SROA of classes
with template methods through cloning is probably expecting too much
heroics. With this change, the begin/end pointer pairs which indicate
the status of each loop iteration are actually passed directly into each
layer of the combine_data calls, and the inliner has a chance to see
when most of the combine_data function could be deleted by inlining.
Similarly for 'length'.
We have to be careful to limit the places where in/out reference
parameters are used as those will also defeat the inliner / optimizers
from properly propagating constants.
With this change, LLVM is able to fully inline and unroll the hash
computation of small sets of values, such as two or three pointers.
These now decompose into essentially straight-line code with no loops or
function calls.
There is still one code quality problem to be solved with the hashing --
LLVM is failing to nuke the alloca. It removes all loads from the
alloca, leaving only lifetime intrinsics and dead(!!) stores to the
alloca. =/ Very unfortunate.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@154264 91177308-0d34-0410-b5e6-96231b3b80d8
ImmutAVLTree uses random unsigned values as keys into a DenseMap,
which could possibly happen to be the same value as the Tombstone or
Entry keys in the DenseMap.
Test case is hard to come up with. We randomly get failures on the
internal static analyzer bot, which most likely hits this issue
(hard to be 100% sure without the full stack).
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@153148 91177308-0d34-0410-b5e6-96231b3b80d8
Commit r152704 exposed a latent MSVC limitation (aka bug).
Both ilist and and iplist contains the same function:
template<class InIt> void insert(iterator where, InIt first, InIt last) {
for (; first != last; ++first) insert(where, *first);
}
Also ilist inherits from iplist and ilist contains a "using iplist<NodeTy>::insert".
MSVC doesn't know which one to pick and complain with an error.
I think it is safe to delete ilist::insert since it is redundant anyway.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@152746 91177308-0d34-0410-b5e6-96231b3b80d8
caused several clients to select the slow variation. =[ This is extra
annoying because we don't have any realistic way of testing this -- by
design, these two functions *must* compute the same value.
Found while inspecting the output of some benchmarks I'm working on.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@152369 91177308-0d34-0410-b5e6-96231b3b80d8
buildbots. Original commit message:
[ADT] Change the trivial FoldingSetNodeID::Add* methods to be inline, reapplied
with a fix for the longstanding over-read of 32-bit pointer values.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@152304 91177308-0d34-0410-b5e6-96231b3b80d8
Deleting them because they aren't used. =D
Yell if you need these, I'm happy to instead replace them with nice uses
of the new infrastructure.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@152219 91177308-0d34-0410-b5e6-96231b3b80d8
integral and enumeration types. This is accomplished with a bit of
template type trait magic. Thanks to Richard Smith for the core idea
here to detect viable types by detecting the set of types which can be
default constructed in a template parameter.
This is used (in conjunction with a system for detecting nullptr_t
should it exist) to provide an is_integral_or_enum type trait that
doesn't need a whitelist or direct compiler support.
With this, the hashing is extended to the more general facility. This
will be used in a subsequent commit to hashing more things, but I wanted
to make sure the type trait magic went through the build bots separately
in case other compilers don't like this formulation.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@152217 91177308-0d34-0410-b5e6-96231b3b80d8
This currently assumes that both sets have the same SmallSize to keep the implementation simple,
a limitation that can be lifted if someone cares.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@152143 91177308-0d34-0410-b5e6-96231b3b80d8
complains about the truncation of a 64-bit constant to a 32-bit value
when size_t is 32-bits wide, but *only with static_cast*!!! The exact
signal that should *silence* such a warning, and in fact does silence it
with both GCC and Clang.
Anyways, this was causing grief for all the MSVC builds, so pointless
change made. Thanks to Nikola on IRC for confirming that this works.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@152021 91177308-0d34-0410-b5e6-96231b3b80d8
new hash_value infrastructure, and replace their implementations using
hash_combine. This removes a complete copy of Jenkin's lookup3 hash
function (which is both significantly slower and lower quality than the
one implemented in hash_combine) along with a somewhat scary xor-only
hash function.
Now that APInt and APFloat can be passed directly to hash_combine,
simplify the rest of the LLVMContextImpl hashing to use the new
infrastructure.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@152004 91177308-0d34-0410-b5e6-96231b3b80d8
The optimizer should handle this eventually, but currently LVI isn't really designed for this kind of stuff.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@151918 91177308-0d34-0410-b5e6-96231b3b80d8
folks who know something about PPC tell me that the byte swap is crazy
fast and without this the bit mixture would actually be different. It
might not be worse, but I've not measured it and so I'd rather not trust
it. This way, the algorithm is identical on both endianness hosts. I'll
look into any performance issues etc stemming from this.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@151892 91177308-0d34-0410-b5e6-96231b3b80d8
just ensure that the number of bytes in the pair is the sum of the bytes
in each side of the pair. As long as thats true, there are no extra
bytes that might be padding.
Also add a few tests that previously would have slipped through the
checking. The more accurate checking mechanism catches these and ensures
they are handled conservatively correctly.
Thanks to Duncan for prodding me to do this right and more simply.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@151891 91177308-0d34-0410-b5e6-96231b3b80d8
hashable data. This matters when we have pair<T*, U*> as a key, which is
quite common in DenseMap, etc. To that end, we need to detect when this
is safe. The requirements on a generic std::pair<T, U> are:
1) Both T and U must satisfy the existing is_hashable_data trait. Note
that this includes the requirement that T and U have no internal
padding bits or other bits not contributing directly to equality.
2) The alignment constraints of std::pair<T, U> do not require padding
between consecutive objects.
3) The alignment constraints of U and the size of T do not conspire to
require padding between the first and second elements.
Grow two somewhat magical traits to detect this by forming a pod
structure and inspecting offset artifacts on it. Hopefully this won't
cause any compilers to panic.
Added and adjusted tests now that pairs, even nested pairs, are treated
as just sequences of data.
Thanks to Jeffrey Yasskin for helping me sort through this and reviewing
the somewhat subtle traits.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@151883 91177308-0d34-0410-b5e6-96231b3b80d8
an open question of whether we can do better than this by treating pairs
as boring data containers and directly hashing the two subobjects. This
at least makes the API reasonable.
In order to make this change, I reorganized the header a bit. I lifted
the declarations of the hash_value functions up to the top of the header
with their doxygen comments as these are intended for users to interact
with. They shouldn't have to wade through implementation details. I then
defined them at the very end so that they could be defined in terms of
hash_combine or any other hashing infrastructure.
Added various pair-hashing unittests.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@151882 91177308-0d34-0410-b5e6-96231b3b80d8
the hash_code. I'm not sure what I was thinking here, the use cases for
special values are in the *keys*, not in the hashes of those keys.
We can always resurrect this if needed, or clients can accomplish the
same goal themselves. This makes the general case somewhat faster (~5
cycles faster on my machine) and smaller with less branching.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@151865 91177308-0d34-0410-b5e6-96231b3b80d8
of the proposed standard hashing interfaces (N3333), and to use
a modified and tuned version of the CityHash algorithm.
Some of the highlights of this change:
-- Significantly higher quality hashing algorithm with very well
distributed results, and extremely few collisions. Should be close to
a checksum for up to 64-bit keys. Very little clustering or clumping of
hash codes, to better distribute load on probed hash tables.
-- Built-in support for reserved values.
-- Simplified API that composes cleanly with other C++ idioms and APIs.
-- Better scaling performance as keys grow. This is the fastest
algorithm I've found and measured for moderately sized keys (such as
show up in some of the uniquing and folding use cases)
-- Support for enabling per-execution seeds to prevent table ordering
or other artifacts of hashing algorithms to impact the output of
LLVM. The seeding would make each run different and highlight these
problems during bootstrap.
This implementation was tested extensively using the SMHasher test
suite, and pased with flying colors, doing better than the original
CityHash algorithm even.
I've included a unittest, although it is somewhat minimal at the moment.
I've also added (or refactored into the proper location) type traits
necessary to implement this, and converted users of GeneralHash over.
My only immediate concerns with this implementation is the performance
of hashing small keys. I've already started working to improve this, and
will continue to do so. Currently, the only algorithms faster produce
lower quality results, but it is likely there is a better compromise
than the current one.
Many thanks to Jeffrey Yasskin who did most of the work on the N3333
paper, pair-programmed some of this code, and reviewed much of it. Many
thanks also go to Geoff Pike Pike and Jyrki Alakuijala, the original
authors of CityHash on which this is heavily based, and Austin Appleby
who created MurmurHash and the SMHasher test suite.
Also thanks to Nadav, Tobias, Howard, Jay, Nick, Ahmed, and Duncan for
all of the review comments! If there are further comments or concerns,
please let me know and I'll jump on 'em.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@151822 91177308-0d34-0410-b5e6-96231b3b80d8
it with memcpy. This also fixes a problem on big-endian hosts, where
addUnaligned would return different results depending on the alignment
of the data.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@151247 91177308-0d34-0410-b5e6-96231b3b80d8
Added array subscript to SparseSet for convenience.
Slight reorg to make it easier to manage the def/use sets.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@151228 91177308-0d34-0410-b5e6-96231b3b80d8
chip in r139383, and the PSP components of the triple are really
annoying to parse. Let's leave this chapter behind. There is no reason
to expect LLVM to see a PSP-related triple these days, and so no
reasonable motivation to support them.
It might be reasonable to prune a few of the older MIPS triple forms in
general, but as those at least cause no burden on parsing (they aren't
both a chip and an OS!), I'm happy to leave them in for now.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@151156 91177308-0d34-0410-b5e6-96231b3b80d8
For objects that can be identified by small unsigned keys, SparseSet
provides constant time clear() and fast deterministic iteration. Insert,
erase, and find operations are typically faster than hash tables.
SparseSet is useful for keeping information about physical registers,
virtual registers, or numbered basic blocks.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@151110 91177308-0d34-0410-b5e6-96231b3b80d8
They're private static methods but we can just make them static
functions in the implementation. It makes the implementations a touch
more wordy, but takes another chunk out of the header file.
Also, take the opportunity to switch the names to the new coding
conventions.
No functionality changed here.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@151047 91177308-0d34-0410-b5e6-96231b3b80d8