Using a custom optimisation pass pipeline


Currently we use the same set of optimisation passes that clang does. This is fine for the most part, since our semantics and codegen are similar enough for the set of passes to be reasonably good.

However, Rust isn’t C/C++, and some things don’t match up perfectly. Looking at LLVM’s Frontend Performance Guide, a few of those points seem to apply to Rust. Two notable points are:

If you language uses range checks, consider using the IRCE pass. It is not currently part of the standard pass order and For languages with numerous rarely executed guard conditions (e.g. null checks, type checks, range checks) consider adding an extra execution or two of LoopUnswith and LICM to your pass order. The standard pass order, which is tuned for C and C++ applications, may not be sufficient to remove all dischargeable checks from loops

For looking at the IRCE pass it is targeted at eliminating checks about the range of a value. This would include bounds checks for indexing. Similarly, the second point also applies to bounds checks, but may also help eliminate unecessary null checks and similar.

I think that continuing to use the basic C/C+±tuned pipeline is only going to hinder the effectiveness of the optimizer. I propose then that we use our own pipeline that can be tuned to be better for Rust code, though still based on the Clang base pipeline.


One thing I’ve been worried about in the past is that if we go the route of our own full optimization pipeline then it’s something that we need to maintain and update as LLVM is updated. Things like this tend to get a lot of attention for a short period of time and then we upgrade LLVM two or three times and realize the ordering is all wrong for the newest LLVM version (and then we don’t remember how to order them again).

It’d be awesome if we could use the existing pipeline but just tweak it in various ways (e.g. insert passes in the middle or remove some we don’t need). I’d also want to be super confident that our choice of passes is better than the LLVM devs chose for C++ before we bank too hard on it because I have a feeling it’s quite easy to go wrong in terms of orderings.


As I said on IRC, I’m in favor of this, not only because of better codegen but also because we should be able to move the extra pass we have out of the LLVM fork, build it out-of-tree and thus get to use it even if building against a system LLVM.

That said, I’m also with @alexcrichton about being super confident that we actually end up with a better pipeline and keeping up with upstream changes.


The best way to combat regressions is automation. Finding a good pass order is tricky and requires thought, but it can be automated to some degree. Given a good enough set of benchmarks, it’s essentially a discrete optimization problem. This can be scripted. There is prior art for this. It may not find the best pass order, but it can find a good one with essentially no human intervention except for interpreting the results. Any significant change to the generated IR and any LLVM update could be accompanied by letting the script search for a good pass order over night. If the best pass order found is worse than the previous custom order, or the current Clang order, one can keep the old one or revert to the Clang one.

There are two big problems with that though:

  1. Finding a good utility function. In particular, weighting the individual benchmarks fairly and balancing compile time against performance for -O and -C opt-level=1 (assuming we want to generate custom pass orders for all of those).
  2. Having representative benchmarks. The #[test] tests are almost entirely micro benchmarks AFAIK, which may impact how representative they are.

Both problems are fixable with enough one-time effort.


@rkruppe While it’s a tantalizing idea to search for the best optimization pipeline, when I’ve floated this to @sunfish (an LLVM dev) he advised against it, since using our own optimization ordering will be very untested and we’ll be exposing ourselves to bugs nobody else sees.


FWIW, there’s an issue for activating IRCE.


There is now an issue for custom pass itself.