[LLVMdev] MergeFunctions: reduce complexity to O(log(N))

Sean Silva chisophugis at gmail.com
Wed Jan 29 11:52:27 PST 2014


On Tue, Jan 28, 2014 at 2:47 PM, Tobias von Koch
<tobias.von.koch at gmail.com>wrote:

> Hi Stepan,
>
> Sorry for the delay. It's great that you are working on MergeFunctions as
> well and I agree, we should definitely try to combine our efforts to
> improve MergeFunctions.
>
> Just to give you some context, the pass (with the similar function merging
> patch) is already being used in a production setting. From my point of
> view, it would be better if we focus on improving its capability of merging
> functions at this stage rather than on reduction of compilation time.
>
> I'll give a brief overview of how our similar function merging algorithm
> works (you can also watch the presentation from the US LLVM conference to
> hear me explain it using an animation).
>
> 1. Hash all functions into buckets
>
> In each bucket, separately:
>
>  2. Compare functions pair-wise and determine a
>     similarity metric for each pair (%age of equivalent instructions)
>
>  3. Merge identical functions (with similarity = 100%), update call
>     sites for those functions.
>
>  4. If the updates of call sites have touched other functions,
>     go back to step 2 and re-compare *only* those functions to all
>     others in their buckets.
>
>  Finally,
>
>  5. Form groups of similar functions for merging:
>     a) Pick most similar pair (A,B)
>     b) Find all functions C that are also similar to B but are not
>        more similar to some other function D.
>     c) Merge A with B and all the C's.
>     Repeat until there are no more functions to merge.
>
> As you can see, we need to compute a similarity measure for each pair of
> functions in a bucket. If I understand correctly, your patch reduces
> compile-time by avoiding comparisons of functions that cannot be identical.
> That's exactly what you want to do if you only want to merge identical
> functions. However, because we also need to determine whether functions are
> merely *similar*, I can't see how your idea could be applied in that case.
>

Yeah, the existing pass only tries to merge identical functions (identical
in machine code). I'm wondering if the "similar" function merging would be
better as a separate pass (I'm genuinely wondering; I have no clue). I
would wait for Nick's feedback.

-- Sean Silva


>
> Looking at your statistics, I see that you are considering a very large
> number of functions. I don't know which benchmarks you are using, but I
> doubt that many of these are worth merging. For instance, you rarely gain a
> code size benefit from merging functions with just a few instructions. Our
> patch takes care of this using thresholds. It's worth looking at actual
> code size reductions, rather than just numbers of functions merged/
> compilation time spent comparing functions. It turns out that the number of
> functions in each bucket is really quite small once you apply some
> heuristics (and could still be further reduced!).
>
> Given your experience with MergeFunctions, it would be really great if you
> could review our patch and also try it out on your benchmarks.
>
> Tobias
>
>
> On 24/01/2014 19:11, Stepan Dyatkovskiy wrote:
>
>> Hi Tobias.
>>
>> So, what do you think?
>>
>> If it means to much extra-job for your team, may be I can help you
>> somehow? I really would like to.
>>
>> -Stepan
>>
>> Stepan Dyatkovskiy wrote:
>>
>>> Hi Tobias,
>>>
>>>  I can't really see a way to combine our approach with your patch. What
>>>> are your thoughts?
>>>>
>>>
>>> I think it is possible. Even more - we need to combine our efforts, in
>>> order to bring this pass into real live.
>>> I'have read your presentation file, and unfortunately read your patch
>>> only a little.
>>> How exactly you scan functions on 2nd stage? Could you explain the
>>> algorithm in few words, how you compare workflow? Is it possible to
>>> scan binary tree instead of hash table? ...OK.
>>>
>>> That's how I see the modification. Now its important to explain idea,
>>> so consider the simplest case: you need to catch two functions that
>>> are differs with single instruction somewhere.
>>>
>>> 1. Imagine, that IR *module* contents is represented as binary tree:
>>> Each line (trace) from root to terminal node is a function.
>>> Each node - is function's primitive (instruction opcode, for example).
>>> Down - is direction to terminal nodes, up - is direction to the root.
>>>
>>> 2. Now you are standing on some node. And you have two directions
>>> down-left and down-right.
>>>
>>> 3. If you are able to find two equal sub-traces down (at left and at
>>> right), then the only difference lies in this node. Then we catch that
>>> case.
>>>
>>> 4. Even more, if two subtrees at left and at right are equal, than you
>>> catch at once all the cases that are represented by these subtrees.
>>>
>>> I still didn't look at you patch carefully. Sorry.. But I hope that
>>> helps, and I'll try look at it in nearest time and perhaps its not the
>>> best solution I gave in this post.
>>>
>>> -Stepan
>>>
>>> 22.01.2014, 20:53, "Tobias von Koch" <tobias.von.koch at gmail.com>:
>>>
>>>> Hi Stepan,
>>>>
>>>> As you've seen we have recently implemented a significant enhancement to
>>>> the MergeFunctions pass that also allows merging of functions that are
>>>> only similar but not identical
>>>> (http://llvm-reviews.chandlerc.com/D2591).
>>>>
>>>> Our patch also changes the way that functions are compared quite
>>>> significantly. This is necessary because we need to compare all
>>>> functions in a bucket in order to get a similarity measure for each
>>>> pair, so we can then decide which 'groups' of functions to merge.
>>>>
>>>> I can't really see a way to combine our approach with your patch. What
>>>> are your thoughts?
>>>>
>>>> Another way to improve the performance of MergeFunctions might be to
>>>> make the hash function better. I've already added the size of the first
>>>> BB to it, and perhaps there are other factors we could try... if we
>>>> don't have to compare functions in the first place (because they're in
>>>> different buckets) then that's obviously a much bigger win.
>>>>
>>>> Thanks,
>>>> Tobias
>>>>
>>>> On 17/01/2014 20:25, Stepan Dyatkovskiy wrote:
>>>>
>>>>    Hi all,
>>>>>
>>>>>   I propose simple improvement for MergeFunctions pass, that reduced
>>>>> its
>>>>>   complexity from O(N^2) to O(log(N)), where N is number of
>>>>> functions in
>>>>>   module.
>>>>>
>>>>>   The idea, is to replace the result of comparison from "bool" to
>>>>>   "-1,0,1". In another words: define order relation on functions set.
>>>>>   To be sure, that functions could be comparable that way, we have to
>>>>>   prove that order relation is possible on all comparison stage.
>>>>>
>>>>>   The last one is possible, if for each comparison stage we
>>>>> implement has
>>>>>   next properties:
>>>>>   * reflexivity (a <= a, a == a, a >= a),
>>>>>   * antisymmetry (if a <= b and b <= a then a  == b),
>>>>>   * transitivity (a <= b and b <= c, then a <= c)
>>>>>   * asymmetry (if a < b, then a > b or a == b).
>>>>>
>>>>>   Once we have defined order relation we can store all the functions in
>>>>>   binary tree and perform lookup in O(log(N)) time.
>>>>>
>>>>>   This post has two attachments:
>>>>>   1. The patch, that has implementation of this idea.
>>>>>   2. The MergeFunctions pass detailed description, with explanation how
>>>>>   order relation could be possible.
>>>>>
>>>>>   Hope it helps to make things better!
>>>>>
>>>>>   -Stepan.
>>>>>
>>>>>   _______________________________________________
>>>>>   LLVM Developers mailing list
>>>>>   LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
>>>>>   http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>>>>>
>>>>
>>
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140129/77b8206b/attachment.html>


More information about the llvm-dev mailing list