@@ -61,33 +61,73 @@ units](../appendix/glossary.md#codegen-unit).
61
61
## Polymorphization
62
62
63
63
As mentioned above, monomorphization produces fast code, but it comes at the
64
- cost of compile time and binary size. [ MIR
65
- optimizations] ( ../mir/optimizations.md ) can help a bit with this. Another
66
- optimization currently under development is called _ polymorphization_ .
67
-
68
- The general idea is that often we can share some code between monomorphized
69
- copies of code. More precisely, if a MIR block is not dependent on a type
70
- parameter, it may not need to be monomorphized into many copies. Consider the
71
- following example:
64
+ cost of compile time and binary size. [ MIR optimizations] [ miropt ] can help a
65
+ bit with this.
66
+
67
+ In addition to MIR optimizations, rustc attempts to determine when fewer
68
+ copies of functions are necessary and avoid making those copies - known
69
+ as "polymorphization". When a function-like item is found during
70
+ monomorphization collection, the
71
+ [ ` rustc_mir::monomorphize::polymorphize::unused_generic_params ` ] [ polymorph ]
72
+ query is invoked, which traverses the MIR of the item to determine on which
73
+ generic parameters the item might not need duplicated.
74
+
75
+ Currently, polymorphization only looks for unused generic parameters. These
76
+ are relatively rare in functions, but closures inherit the generic
77
+ parameters of their parent function and it is common for closures to not
78
+ use those inherited parameters. Without polymorphization, a copy of these
79
+ closures would be created for each copy of the parent function. By
80
+ creating fewer copies, less LLVM IR is generated and needs processed.
81
+
82
+ ` unused_generic_params ` returns a ` FiniteBitSet<u64> ` where a bit is set if
83
+ the generic parameter of the corresponding index is unused. Any parameters
84
+ after the first sixty-four are considered used.
85
+
86
+ The results of polymorphization analysis are used in the
87
+ [ ` Instance::polymorphize ` ] [ inst_polymorph ] function to replace the
88
+ [ ` Instance ` ] [ inst ] 's substitutions for the unused generic parameters with their
89
+ identity substitutions.
90
+
91
+ Consider the example below:
72
92
73
93
``` rust
74
- pub fn f () {
75
- g :: <bool >();
76
- g :: <usize >();
94
+ fn foo <A , B >() {
95
+ let x : Option <B > = None ;
77
96
}
78
97
79
- fn g <T >() -> usize {
80
- let n = 1 ;
81
- let closure = || n ;
82
- closure ()
98
+ fn main () {
99
+ foo :: <u16 , u32 >();
100
+ foo :: <u64 , u32 >();
83
101
}
84
102
```
85
103
86
- In this case, we would currently collect `[ f, g::<bool >, g::<usize >,
87
- g::<bool >::{{closure}}, g::<usize >::{{closure}}] `, but notice that the two
88
- closures would be identical -- they don't depend on the type parameter ` T ` of
89
- function ` g ` . So we only need to emit one copy of the closure.
104
+ During monomorphization collection, ` foo ` will be collected with the
105
+ substitutions ` [u16, u32] ` and ` [u64, u32] ` (from its invocations in ` main ` ).
106
+ ` foo ` has the identity substitutions ` [A, B] ` (or
107
+ ` [ty::Param(0), ty::Param(1)] ` ).
108
+
109
+ Polymorphization will identify ` A ` as being unused and it will be replaced in
110
+ the substitutions with the identity parameter before being added to the set
111
+ of collected items - thereby reducing the copies from two (` [u16, u32] ` and
112
+ ` [u64, u32] ` ) to one (` [A, u32] ` ).
113
+
114
+ ` unused_generic_params ` will also invoked during code generation when the
115
+ symbol name for ` foo ` is being computed for use in the callsites of ` foo `
116
+ (which have the regular substitutions present, otherwise there would be a
117
+ symbol mismatch between the caller and the function).
118
+
119
+ As a result of polymorphization, items collected during monomorphization
120
+ cannot be assumed to be monomorphic.
121
+
122
+ It is intended that polymorphization be extended to more advanced cases,
123
+ such as where only the size/alignment of a generic parameter are required.
90
124
91
- For more information, see [ this thread on github] [ polymorph ] .
125
+ More details on polymorphization are available in the
126
+ [ master's thesis] [ thesis ] associated with polymorphization's initial
127
+ implementation.
92
128
93
- [ polymorph ] : https://github.com/rust-lang/rust/issues/46477
129
+ [ miropt ] : ../mir/optimizations.md
130
+ [ polymorph ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/monomorphize/polymorphize/fn.unused_generic_params.html
131
+ [ inst ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/instance/struct.Instance.html
132
+ [ inst_polymorph ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/instance/struct.Instance.html#method.polymorphize
133
+ [ thesis ] : https://davidtw.co/media/masters_dissertation.pdf
0 commit comments