[llvm-dev] Status of the function merging pass?
JF Bastien via llvm-dev
llvm-dev at lists.llvm.org
Thu Jan 31 16:54:13 PST 2019
> On Jan 31, 2019, at 4:40 PM, Aditya K via llvm-dev <llvm-dev at lists.llvm.org> wrote:
> Hi Nikita,
> Glad to hear that Rust code can benefit a lot from this.
> I have put patches to enable merge-similar functions with thinLTO.
> https://reviews.llvm.org/D52896 etc.
> This is more powerful than existing merge-functions pass and all we need to do is port these patches to trunk llvm. I'd be happy to help with this effort.
I still don’t understand why we should ditch mergefuncs instead of incrementally improving it. I’d like to understand what’s actually changing incrementally, and first fix the fundamental flaw mergefuncs has (as I discuss below).
To answer Vedant’s question: I think the fundamental problem with mergefuncs is that it needs to understand IR perfectly, for equality comparison, hashing, and “fuzzy” matching. Any solution that’s on-by-default should address this issue: when we change IR we cannot allow mergefuncs to suddenly be wrong in a subtle way. For example, when we added cmpxchg “failure” order, mergefuncs needed to know about it, otherwise it could merge functions which differed only in failure ordering and suddenly generate code that was *wrong* in an incredibly hard to diagnose manner.
Once that’s addressed, I think mergefuncs can be improved in a few ways.
First it can be run early to remove exact duplicates. This will speed up build times. I had an intern, Jason, work on mergefuncs a few years ago and he measured speedups when compiling Chrome just though an early run.
Then mergefuncs should be improved to do fuzzy matching, where it determines that functions are similar enough that they can be variants of each other with an extra argument passed in to specialize each “flavor”. Jason had posted a patch for this back then as well, and it yielded some gains on Chrome’s binary size. He hadn’t explored the full breadth of specializations (do you just find differences in constants, or branch around entire code blocks, etc). There’s extra science to perform around different optimization levels.
The fuzzy matching should only be run later, and some science should be put in determining how it interacts with inlining.
Vedant, I’m happy to chat in person next time we’re in the same building :-)
> From: Nikita Popov <nikita.ppv at gmail.com>
> Sent: Thursday, January 31, 2019 3:46 PM
> To: Vedant Kumar
> Cc: llvm-dev; Reid Kleckner; Aditya K; whitequark at whitequark.org; Teresa Johnson; Duncan P. N. Exon Smith; Jessica Paquette
> Subject: Re: Status of the function merging pass?
> On Thu, Jan 31, 2019 at 8:52 PM Vedant Kumar <vsk at apple.com <mailto:vsk at apple.com>> wrote:
> I'm interested in finding ways to reduce code size. LLVM's MergeFunctions pass seems like a promising option, and I'm curious about its status in tree.
> Enabling MergeFunctions gives a 1% code size reduction across the entire iOS shared cache (a collection of a few hundred system-critical DSO's). The numbers are even more compelling for Swift code. In fact, the swift compiler enables MergeFunctions by default when optimizing, along with an even more aggressive merging pass which handles equivalence-modulo-constant-uses (https://github.com/apple/swift/blob/master/lib/LLVMPasses/LLVMMergeFunctions.cpp <https://github.com/apple/swift/blob/master/lib/LLVMPasses/LLVMMergeFunctions.cpp>).
> Is anyone actively working on enabling MergeFunctions in LLVM's default pipelines? Is there a roadmap for doing so?
> ISTM that preventing miscompiles when merging functions is a serious, unsolved problem. I.e., it's hard for the MergeFunctions pass to be *really sure* that two functions are a) really identical and b) safe to merge.
> Is there a systematic solution at the IR-level, given that the semantics of IR are subject to change? Is extensive testing the only solution? Or is this intractable, and the only safe approach is to perform merging post-regalloc (or, at some late point when equivalence is easier to determine)?
> In Rust we've been running with MergeFunctions enabled by default for a while now, and have recently also enabled the use of aliases instead of thunks. Apart from some initial bugs we didn't encounter any significant issues (one minor issue with NVPTX not supporting aliases and having CC restrictions).
> As Rust tends to be quite heavy on monomorphization, MergeFuncs can give significant binary size reductions. I don't have any comprehensive numbers, but from checking this on a pet project just now, it reduces final artifact size by 13% and I've seen some similar numbers in the ~10% range quoted before.
> So, at least for Rust's use case this pass seems to be both quite robust and useful :)
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the llvm-dev