@@ -110,7 +110,7 @@ use rustc::mir::mono::{Linkage, Visibility};
110
110
use rustc:: ty:: { self , TyCtxt , InstanceDef } ;
111
111
use rustc:: ty:: item_path:: characteristic_def_id_of_type;
112
112
use rustc:: util:: nodemap:: { FxHashMap , FxHashSet } ;
113
- use std:: collections:: hash_map:: { HashMap , Entry } ;
113
+ use std:: collections:: hash_map:: Entry ;
114
114
use syntax:: ast:: NodeId ;
115
115
use syntax:: symbol:: { Symbol , InternedString } ;
116
116
use rustc:: mir:: mono:: MonoItem ;
@@ -225,12 +225,14 @@ pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
225
225
let mut initial_partitioning = place_root_translation_items ( tcx,
226
226
trans_items) ;
227
227
228
+ initial_partitioning. codegen_units . iter_mut ( ) . for_each ( |cgu| cgu. estimate_size ( & tcx) ) ;
229
+
228
230
debug_dump ( tcx, "INITIAL PARTITIONING:" , initial_partitioning. codegen_units . iter ( ) ) ;
229
231
230
232
// If the partitioning should produce a fixed count of codegen units, merge
231
233
// until that count is reached.
232
234
if let PartitioningStrategy :: FixedUnitCount ( count) = strategy {
233
- merge_codegen_units ( tcx , & mut initial_partitioning, count, & tcx. crate_name . as_str ( ) ) ;
235
+ merge_codegen_units ( & mut initial_partitioning, count, & tcx. crate_name . as_str ( ) ) ;
234
236
235
237
debug_dump ( tcx, "POST MERGING:" , initial_partitioning. codegen_units . iter ( ) ) ;
236
238
}
@@ -242,6 +244,8 @@ pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
242
244
let mut post_inlining = place_inlined_translation_items ( initial_partitioning,
243
245
inlining_map) ;
244
246
247
+ post_inlining. codegen_units . iter_mut ( ) . for_each ( |cgu| cgu. estimate_size ( & tcx) ) ;
248
+
245
249
debug_dump ( tcx, "POST INLINING:" , post_inlining. codegen_units . iter ( ) ) ;
246
250
247
251
// Next we try to make as many symbols "internal" as possible, so LLVM has
@@ -405,8 +409,7 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
405
409
}
406
410
}
407
411
408
- fn merge_codegen_units < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
409
- initial_partitioning : & mut PreInliningPartitioning < ' tcx > ,
412
+ fn merge_codegen_units < ' tcx > ( initial_partitioning : & mut PreInliningPartitioning < ' tcx > ,
410
413
target_cgu_count : usize ,
411
414
crate_name : & str ) {
412
415
assert ! ( target_cgu_count >= 1 ) ;
@@ -423,51 +426,16 @@ fn merge_codegen_units<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
423
426
// the stable sort below will keep everything nice and deterministic.
424
427
codegen_units. sort_by_key ( |cgu| cgu. name ( ) . clone ( ) ) ;
425
428
426
- // Estimate the size of a codegen unit as (approximately) the number of MIR
427
- // statements it corresponds to.
428
- fn codegen_unit_size_estimate < ' a , ' tcx > ( cgu : & CodegenUnit < ' tcx > ,
429
- mono_item_sizes : & HashMap < MonoItem , usize > )
430
- -> usize {
431
- cgu. items ( ) . keys ( ) . map ( |mi| mono_item_sizes. get ( mi) . unwrap ( ) ) . sum ( )
432
- }
433
-
434
- fn mono_item_size_estimate < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
435
- item : & MonoItem < ' tcx > )
436
- -> usize {
437
- match item {
438
- MonoItem :: Fn ( instance) => {
439
- // Estimate the size of a function based on how many statements
440
- // it contains.
441
- let mir = tcx. instance_mir ( instance. def ) ;
442
- mir. basic_blocks ( ) . iter ( ) . map ( |bb| bb. statements . len ( ) ) . sum ( )
443
- } ,
444
- // Conservatively estimate the size of a static declaration
445
- // or assembly to be 1.
446
- MonoItem :: Static ( _) | MonoItem :: GlobalAsm ( _) => 1 ,
447
- }
448
- }
449
-
450
- // Since `sort_by_key` currently recomputes the keys for each comparison,
451
- // we can save unnecessary recomputations by storing size estimates for
452
- // each `MonoItem`. Storing estimates for `CodegenUnit` might be preferable,
453
- // but its structure makes it awkward to use as a key and additionally their
454
- // sizes change as the merging occurs, requiring the map to be updated.
455
- let mut sizes: HashMap < MonoItem , usize > = HashMap :: new ( ) ;
456
- for mis in codegen_units. iter ( ) . map ( |cgu| cgu. items ( ) . keys ( ) ) {
457
- mis. for_each ( |mi| {
458
- sizes. entry ( * mi) . or_insert_with ( || mono_item_size_estimate ( tcx, mi) ) ;
459
- } ) ;
460
- }
461
-
462
429
// Merge the two smallest codegen units until the target size is reached.
463
430
// Note that "size" is estimated here rather inaccurately as the number of
464
431
// translation items in a given unit. This could be improved on.
465
432
while codegen_units. len ( ) > target_cgu_count {
466
433
// Sort small cgus to the back
467
- codegen_units. sort_by_key ( |cgu| usize:: MAX - codegen_unit_size_estimate ( cgu, & sizes ) ) ;
434
+ codegen_units. sort_by_key ( |cgu| usize:: MAX - cgu. size_estimate ( ) ) ;
468
435
let mut smallest = codegen_units. pop ( ) . unwrap ( ) ;
469
436
let second_smallest = codegen_units. last_mut ( ) . unwrap ( ) ;
470
437
438
+ second_smallest. modify_size_estimate ( smallest. size_estimate ( ) ) ;
471
439
for ( k, v) in smallest. items_mut ( ) . drain ( ) {
472
440
second_smallest. items_mut ( ) . insert ( k, v) ;
473
441
}
0 commit comments