]> git.proxmox.com Git - rustc.git/blame - src/doc/rustc-dev-guide/src/mir/optimizations.md
Merge tag 'debian/1.52.1+dfsg1-1_exp2' into proxmox/buster
[rustc.git] / src / doc / rustc-dev-guide / src / mir / optimizations.md
CommitLineData
a1dfa0c6 1# MIR optimizations
60c5eb7d
XL
2
3MIR optimizations are optimizations run on the [MIR][mir] to produce better MIR
4before codegen. This is important for two reasons: first, it makes the final
5generated executable code better, and second, it means that LLVM has less work
6to do, so compilation is faster. Note that since MIR is generic (not
7[monomorphized][monomorph] yet), these optimizations are particularly
8effective; we can optimize the generic version, so all of the monomorphizations
9are cheaper!
10
74b04a01 11[mir]: https://rustc-dev-guide.rust-lang.org/mir/index.html
ba9703b0 12[monomorph]: https://rustc-dev-guide.rust-lang.org/appendix/glossary.html#mono
60c5eb7d
XL
13
14MIR optimizations run after borrow checking. We run a series of optimization
15passes over the MIR to improve it. Some passes are required to run on all code,
16some passes don't actually do optimizations but only check stuff, and some
17passes are only turned on in `release` mode.
18
19The [`optimized_mir`][optmir] [query] is called to produce the optimized MIR
20for a given [`DefId`][defid]. This query makes sure that the borrow checker has
ba9703b0 21run and that some validation has occurred. Then, it [steals][steal] the MIR,
60c5eb7d
XL
22optimizes it, and returns the improved MIR.
23
24[optmir]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/fn.optimized_mir.html
74b04a01 25[query]: https://rustc-dev-guide.rust-lang.org/query.html
ba9703b0 26[defid]: https://rustc-dev-guide.rust-lang.org/appendix/glossary.html#def-id
74b04a01 27[steal]: https://rustc-dev-guide.rust-lang.org/mir/passes.html?highlight=steal#stealing
60c5eb7d
XL
28
29## Defining optimization passes
30
31The list of passes run and the order in which they are run is defined by the
32[`run_optimization_passes`][rop] function. It contains an array of passes to
33run. Each pass in the array is a struct that implements the [`MirPass`] trait.
34The array is an array of `&dyn MirPass` trait objects. Typically, a pass is
35implemented in its own submodule of the [`rustc_mir::transform`][trans] module.
36
37[rop]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/fn.run_optimization_passes.html
38[`MirPass`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/trait.MirPass.html
6a06907d 39[trans]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/index.html
60c5eb7d
XL
40
41Some examples of passes are:
42- `CleanupNonCodegenStatements`: remove some of the info that is only needed for
43 analyses, rather than codegen.
44- `ConstProp`: Does [constant propagation][constprop]
45
46You can see the ["Implementors" section of the `MirPass` rustdocs][impl] for more examples.
47
48[impl]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/trait.MirPass.html#implementors
49[constprop]: https://en.wikipedia.org/wiki/Constant_folding#Constant_propagation
6a06907d
XL
50
51## MIR optimization levels
52
53MIR optimizations can come in various levels of readiness. Experimental
54optimizations may cause miscompilations, or slow down compile times.
55These passes are still included in nightly builds to gather feedback and make it easier to modify
56the pass. To enable working with slow or otherwise experimental optimization passes,
57you can specify the `-Z mir-opt-level` debug flag. You can find the
58definitions of the levels in the [compiler MCP]. If you are developing a MIR pass and
59want to query whether your optimization pass should run, you can check the
60current level using `tcx.sess.opts.debugging_opts.mir_opt_level`.
61
62[compiler MCP]: https://github.com/rust-lang/compiler-team/issues/319
63
64## Optimization fuel
65
66Optimization fuel is a compiler option (`-Z fuel=<crate>=<value>`) that allows for fine grained
67control over which optimizations can be applied during compilation: each optimization reduces
68fuel by 1, and when fuel reaches 0 no more optimizations are applied. The primary use of fuel
69is debugging optimizations that may be incorrect or misapplied. By changing the fuel
70value, you can bisect a compilation session down to the exact incorrect optimization
71(this behaves like a kind of binary search through the optimizations).
72
73MIR optimizations respect fuel, and in general each pass should check fuel by calling
74[`tcx.consider_optimizing`][consideroptimizing] and skipping the optimization if fuel
75is empty. There are a few considerations:
76
771. If the pass is considered "guaranteed" (for example, it should always be run because it is
78needed for correctness), then fuel should not be used. An example of this is `PromoteTemps`.
792. In some cases, an initial pass is performed to gather candidates, which are then iterated to
80perform optimizations. In these situations, we should allow for the initial gathering pass
81and then check fuel as close to the mutation as possible. This allows for the best
82debugging experience, because we can determine where in the list of candidates an optimization
83may have been misapplied. Examples of this are `InstCombine` and `ConstantPropagation`.
84
85[consideroptimizing]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.consider_optimizing