<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Wed, Aug 6, 2014 at 11:20 AM, Duncan P. N. Exon Smith <span dir="ltr"><<a href="mailto:dexonsmith@apple.com" target="_blank">dexonsmith@apple.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class=""><br>
> On 2014-Aug-05, at 17:47, Sean Silva <<a href="mailto:chisophugis@gmail.com">chisophugis@gmail.com</a>> wrote:<br>
><br>
>> On Mon, Aug 4, 2014 at 4:36 PM, Duncan P. N. Exon Smith <<a href="mailto:dexonsmith@apple.com">dexonsmith@apple.com</a>> wrote:<br>
>><br>
</div><div class="">>> The difference between these three versions is pretty noisy, but the<br>
>> `std::vector<>` version looks slightly slower.  I think it can be left<br>
>> as-is in the tree, but let me know if you think differently and/or want<br>
>> data from a bigger bitcode file.<br>
><br>
> This difference is definitely in the noise. Seems like optimizing this code path is pointless. Just leave it with whichever one is simplest (std::vector?).<br>
<br>
</div>Agreed.  r214979.<br>
<div class=""><br>
>> Calculating the use-lists takes extra memory -- but none of these data<br>
>> structures has much effect on how much.<br>
><br>
> Do you have stats about the size distributions of use lists? E.g. a histogram? (might want to use a log scale)<br>
> Also comparing said distributions across many different bitcode modules of different sorts of code (e.g. chromium, firefox, clang, various cases in the test-suite, etc.).<br>
<br>
</div>No, I didn't collect those, although it would be interesting to know.<br>
<br>
Without having looked deeply, my impression is that most of the expense<br>
is in *calculating* the use-list order</blockquote><div><br></div><div>Let's wait for some data to back this up before doing anything.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
 -- i.e., in the<br>
`DenseMap<Value *, unsigned>` that saves the relative order that values<br>
will be read in the `BitcodeReader`.  This is calculated and used to<br>
generate the use-list order shuffles, and has *every* `Value` accounted<br>
for that will get read by the `BitcodeReader` -- even those that are<br>
already "sorted" (including those with 0 or 1 uses).<br>
<br>
Using this global map was supposed to be a first step, just for the<br>
prototype -- I'd planned to reuse the similar `ValueEnumerator`<br>
tables as much as possible, and predict use-list orders on-the-fly with<br>
a rather more complicated scheme.  However, the memory overhead is small<br>
enough that I'm no longer motivated to add the complexity, or to look<br>
into other designs (like a sorted std::vector).<br>
<br>
I was anticipating needing to optimize the `UseListOrder` data structure<br>
once I'd dealt with the global map.<br>
<br>
Given that it doesn't seem to require optimization, I'm not particularly<br>
motivated to collect these stats right now.  I could file a PR to look<br>
into it later if you think it's worthwhile though -- that seems like a<br>
useful output of `verify-uselistorder`, for example.<br>
<div class=""><br>
>> File-size of the input bitcode for same (in the same order):<br>
>><br>
>>     7.2M nopreserve.bc<br>
>>     7.6M preserve.bc<br>
>>     8.3M shuffled.bc<br>
><br>
> Why does shuffling increase the filesize? Is there some "default" order that is cheaper to store? How does the choice of permutation affect the amount stored?<br>
<br>
</div>The use-lists aren't stored directly -- some users can't be referenced,<br>
so there isn't a practical way to do that.<br>
<br>
Instead, we predict the order the use-lists will be after reading, and<br>
store how to reorder them. </blockquote><div><br></div><div>That seems really fragile. However, I doubt there's  a better way to do it.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
 If the use list is already sorted in the<br>
predicted order, there's no need to store an ordering at all.<br></blockquote><div><br></div><div>That makes sense.</div><div><br></div><div>-- Sean Silva</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<br>
Shuffling makes it so that most of the use-lists will *not* be in the<br>
predicted order, causing most of the use-list-orders to be written out<br>
(1/2 of those size 2, 5/6 of those size 3, etc.).<br>
<br>
A given use-list is either stored or it isn't -- I didn't optimize<br>
based on the "distance" from sorted.  I had planned some storage<br>
optimizations based on the known-limited domain, but it turns out the<br>
bitcode format stores record contents in VBR so I skipped them.<br>
</blockquote></div><br></div></div>