@@ -132,19 +132,29 @@ pub struct CodegenUnit<'tcx> {
132
132
pub items : FnvHashMap < TransItem < ' tcx > , llvm:: Linkage > ,
133
133
}
134
134
135
+ pub enum PartitioningStrategy {
136
+ PerModule ,
137
+ FixedUnitCount ( usize )
138
+ }
139
+
135
140
// Anything we can't find a proper codegen unit for goes into this.
136
141
const FALLBACK_CODEGEN_UNIT : & ' static str = "__rustc_fallback_codegen_unit" ;
137
142
138
143
pub fn partition < ' tcx , I > ( tcx : & TyCtxt < ' tcx > ,
139
144
trans_items : I ,
145
+ strategy : PartitioningStrategy ,
140
146
inlining_map : & InliningMap < ' tcx > )
141
147
-> Vec < CodegenUnit < ' tcx > >
142
148
where I : Iterator < Item = TransItem < ' tcx > >
143
149
{
144
150
// In the first step, we place all regular translation items into their
145
151
// respective 'home' codegen unit. Regular translation items are all
146
152
// functions and statics defined in the local crate.
147
- let initial_partitioning = place_root_translation_items ( tcx, trans_items) ;
153
+ let mut initial_partitioning = place_root_translation_items ( tcx, trans_items) ;
154
+
155
+ if let PartitioningStrategy :: FixedUnitCount ( count) = strategy {
156
+ merge_codegen_units ( & mut initial_partitioning, count, & tcx. crate_name [ ..] ) ;
157
+ }
148
158
149
159
// In the next step, we use the inlining map to determine which addtional
150
160
// translation items have to go into each codegen unit. These additional
@@ -217,6 +227,33 @@ fn place_root_translation_items<'tcx, I>(tcx: &TyCtxt<'tcx>,
217
227
}
218
228
}
219
229
230
+ fn merge_codegen_units < ' tcx > ( initial_partitioning : & mut InitialPartitioning < ' tcx > ,
231
+ target_cgu_count : usize ,
232
+ crate_name : & str ) {
233
+ if target_cgu_count >= initial_partitioning. codegen_units . len ( ) {
234
+ return ;
235
+ }
236
+
237
+ assert ! ( target_cgu_count >= 1 ) ;
238
+ let codegen_units = & mut initial_partitioning. codegen_units ;
239
+
240
+ // Merge the two smallest codegen units until the target size is reached
241
+ while codegen_units. len ( ) > target_cgu_count {
242
+ // Sort small cgus to the back
243
+ codegen_units. as_mut_slice ( ) . sort_by_key ( |cgu| -( cgu. items . len ( ) as i64 ) ) ;
244
+ let smallest = codegen_units. pop ( ) . unwrap ( ) ;
245
+ let second_smallest = codegen_units. last_mut ( ) . unwrap ( ) ;
246
+
247
+ for ( k, v) in smallest. items . into_iter ( ) {
248
+ second_smallest. items . insert ( k, v) ;
249
+ }
250
+ }
251
+
252
+ for ( index, cgu) in codegen_units. iter_mut ( ) . enumerate ( ) {
253
+ cgu. name = token:: intern_and_get_ident ( & format ! ( "{}.{}" , crate_name, index) [ ..] ) ;
254
+ }
255
+ }
256
+
220
257
fn place_inlined_translation_items < ' tcx > ( initial_partitioning : InitialPartitioning < ' tcx > ,
221
258
inlining_map : & InliningMap < ' tcx > )
222
259
-> Vec < CodegenUnit < ' tcx > > {
0 commit comments