[llvm] r214135 - IR: Optimize size of use-list order shuffle vectors
Sean Silva
chisophugis at gmail.com
Tue Jul 29 10:19:28 PDT 2014
First, I agree with Chandler about not worrying unless this is in the
profile.
However, if this really does need to be optimized....
Crazy idea: would it be possible to store just a single int's worth of RNG
seed for each use list?
A less crazy idea: a vector of indices is an extremely memory-inefficient
way to store permutations. For example, there are 12! permutations of 12
elements, and 12! is less than 2^32. Similarly, there are 20! permutations
of 20 elements and 20! < 2^64. Therefore your "small" case could
theoretically be just a single `unsigned` from a storage perspective.
A slightly memory-suboptimal but simple and cpu-friendly way to store the
permutations in an integer would be to bit-pack the indices, using just as
many bits for the indices as necessary. For example, suppose you were just
allowed a single uint64. You could use the following arrangement to store
permutations of up to 15 elements:
Low 4 bits: number of elements (the "size")
Each 4 bits after that: an index. Since we use 4 bits to store it, size()
is at most 15, thus each index fits in 4 bits. 4 * 15 = 60, so that is just
enough room for up to 15 elements.
(there is actually room for quite a bit of out-of-band data; if size() <
15, then you have entire unused indices at the top and so you have 4*(15 -
size()) bits available)
-- Sean Silva
On Mon, Jul 28, 2014 at 4:41 PM, Duncan P. N. Exon Smith <
dexonsmith at apple.com> wrote:
> Author: dexonsmith
> Date: Mon Jul 28 17:41:50 2014
> New Revision: 214135
>
> URL: http://llvm.org/viewvc/llvm-project?rev=214135&view=rev
> Log:
> IR: Optimize size of use-list order shuffle vectors
>
> Since we're storing lots of these, save two-pointers per vector with a
> custom type rather than using the relatively heavy `SmallVector`.
>
> Part of PR5680.
>
> Modified:
> llvm/trunk/include/llvm/IR/UseListOrder.h
> llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp
>
> Modified: llvm/trunk/include/llvm/IR/UseListOrder.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/UseListOrder.h?rev=214135&r1=214134&r2=214135&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/IR/UseListOrder.h (original)
> +++ llvm/trunk/include/llvm/IR/UseListOrder.h Mon Jul 28 17:41:50 2014
> @@ -25,11 +25,58 @@ class Module;
> class Function;
> class Value;
>
> +/// \brief Structure to hold a use-list shuffle vector.
> +///
> +/// Stores most use-lists locally, but large use-lists use an extra heap
> entry.
> +/// Costs two fewer pointers than the equivalent \a SmallVector.
> +class UseListShuffleVector {
> + unsigned Size;
> + union {
> + unsigned *Ptr;
> + unsigned Array[6];
> + } Storage;
> +
> + bool isSmall() const { return Size <= 6; }
> + unsigned *data() { return isSmall() ? Storage.Array : Storage.Ptr; }
> + const unsigned *data() const {
> + return isSmall() ? Storage.Array : Storage.Ptr;
> + }
> +
> +public:
> + UseListShuffleVector() : Size(0) {}
> + UseListShuffleVector(UseListShuffleVector &&X) {
> + std::memcpy(this, &X, sizeof(UseListShuffleVector));
> + X.Size = 0;
> + }
> + explicit UseListShuffleVector(size_t Size) : Size(Size) {
> + if (!isSmall())
> + Storage.Ptr = new unsigned[Size];
> + }
> + ~UseListShuffleVector() {
> + if (!isSmall())
> + delete Storage.Ptr;
> + }
> +
> + typedef unsigned *iterator;
> + typedef const unsigned *const_iterator;
> +
> + size_t size() const { return Size; }
> + iterator begin() { return data(); }
> + iterator end() { return begin() + size(); }
> + const_iterator begin() const { return data(); }
> + const_iterator end() const { return begin() + size(); }
> + unsigned &operator[](size_t I) { return data()[I]; }
> + unsigned operator[](size_t I) const { return data()[I]; }
> +};
> +
> /// \brief Structure to hold a use-list order.
> struct UseListOrder {
> - const Function *F;
> const Value *V;
> - SmallVector<unsigned, 8> Shuffle;
> + const Function *F;
> + UseListShuffleVector Shuffle;
> +
> + UseListOrder(const Value *V, const Function *F, size_t ShuffleSize)
> + : V(V), F(F), Shuffle(ShuffleSize) {}
> };
>
> typedef std::vector<UseListOrder> UseListOrderStack;
>
> Modified: llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp?rev=214135&r1=214134&r2=214135&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp (original)
> +++ llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp Mon Jul 28 17:41:50
> 2014
> @@ -133,12 +133,11 @@ static void predictValueUseListOrderImpl
> return;
>
> // Store the shuffle.
> - UseListOrder O;
> - O.V = V;
> - O.F = F;
> - for (auto &I : List)
> - O.Shuffle.push_back(I.second);
> - Stack.push_back(O);
> + UseListOrder O(V, F, List.size());
> + assert(List.size() == O.Shuffle.size() && "Wrong size");
> + for (size_t I = 0, E = List.size(); I != E; ++I)
> + O.Shuffle[I] = List[I].second;
> + Stack.emplace_back(std::move(O));
> }
>
> static void predictValueUseListOrder(const Value *V, const Function *F,
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140729/fd24c108/attachment.html>
More information about the llvm-commits
mailing list