@@ -136,15 +136,21 @@ where
136
136
{
137
137
let _prof_timer = tcx. prof . generic_activity ( "cgu_partitioning" ) ;
138
138
139
+ let mut estimator = SizeEstimator :: new ( ) ;
140
+
139
141
// In the first step, we place all regular monomorphizations into their
140
142
// respective 'home' codegen unit. Regular monomorphizations are all
141
143
// functions and statics defined in the local crate.
142
144
let initial_partitioning = {
143
145
let _prof_timer = tcx. prof . generic_activity ( "cgu_partitioning_place_roots" ) ;
144
- place_root_mono_items ( tcx, mono_items)
146
+ place_root_mono_items ( tcx, mono_items, & mut estimator )
145
147
} ;
146
148
147
- debug_dump ( tcx, "INITIAL PARTITIONING:" , initial_partitioning. codegen_units . iter ( ) ) ;
149
+ debug_dump (
150
+ tcx,
151
+ "INITIAL PARTITIONING:" ,
152
+ initial_partitioning. codegen_units . iter ( ) ,
153
+ & mut estimator) ;
148
154
149
155
// In the next step, we use the inlining map to determine which additional
150
156
// monomorphizations have to go into each codegen unit. These additional
@@ -153,19 +159,17 @@ where
153
159
let mut post_inlining = {
154
160
let _prof_timer =
155
161
tcx. prof . generic_activity ( "cgu_partitioning_place_inline_items" ) ;
156
- place_inlined_mono_items ( initial_partitioning, inlining_map)
162
+ place_inlined_mono_items ( tcx , initial_partitioning, inlining_map, & mut estimator )
157
163
} ;
158
164
159
- post_inlining. codegen_units . iter_mut ( ) . for_each ( |cgu| cgu. estimate_size ( tcx) ) ;
160
-
161
- debug_dump ( tcx, "POST INLINING:" , post_inlining. codegen_units . iter ( ) ) ;
165
+ debug_dump ( tcx, "POST INLINING:" , post_inlining. codegen_units . iter ( ) , & mut estimator) ;
162
166
163
167
// If the partitioning should produce a fixed count of codegen units, merge
164
168
// until that count is reached.
165
169
if let PartitioningStrategy :: FixedUnitCount ( count) = strategy {
166
170
let _prof_timer = tcx. prof . generic_activity ( "cgu_partitioning_merge_cgus" ) ;
167
- merge_codegen_units ( tcx, & mut post_inlining, count) ;
168
- debug_dump ( tcx, "POST MERGING:" , post_inlining. codegen_units . iter ( ) ) ;
171
+ merge_codegen_units ( tcx, & mut post_inlining, count, & mut estimator ) ;
172
+ debug_dump ( tcx, "POST MERGING:" , post_inlining. codegen_units . iter ( ) , & mut estimator ) ;
169
173
}
170
174
171
175
// Next we try to make as many symbols "internal" as possible, so LLVM has
@@ -189,6 +193,27 @@ where
189
193
result
190
194
}
191
195
196
+ struct SizeEstimator < ' tcx > {
197
+ cache : FxHashMap < MonoItem < ' tcx > , usize > ,
198
+ }
199
+ impl < ' tcx > SizeEstimator < ' tcx > {
200
+ pub fn new ( ) -> SizeEstimator < ' tcx > {
201
+ SizeEstimator { cache : Default :: default ( ) }
202
+ }
203
+ pub fn size_estimate ( & mut self , tcx : TyCtxt < ' tcx > , mono_item : MonoItem < ' tcx > ) -> usize {
204
+ * self . cache . entry ( mono_item) . or_insert_with ( || match mono_item {
205
+ MonoItem :: Fn ( instance) => {
206
+ // Estimate the size of a function based on how many statements
207
+ // it contains.
208
+ tcx. instance_def_size_estimate ( instance. def )
209
+ }
210
+ // Conservatively estimate the size of a static declaration
211
+ // or assembly to be 1.
212
+ MonoItem :: Static ( _) | MonoItem :: GlobalAsm ( _) => 1 ,
213
+ } )
214
+ }
215
+ }
216
+
192
217
struct PreInliningPartitioning < ' tcx > {
193
218
codegen_units : Vec < CodegenUnit < ' tcx > > ,
194
219
roots : FxHashSet < MonoItem < ' tcx > > ,
@@ -209,7 +234,11 @@ struct PostInliningPartitioning<'tcx> {
209
234
internalization_candidates : FxHashSet < MonoItem < ' tcx > > ,
210
235
}
211
236
212
- fn place_root_mono_items < ' tcx , I > ( tcx : TyCtxt < ' tcx > , mono_items : I ) -> PreInliningPartitioning < ' tcx >
237
+ fn place_root_mono_items < ' tcx , I > (
238
+ tcx : TyCtxt < ' tcx > ,
239
+ mono_items : I ,
240
+ estimator : & mut SizeEstimator < ' tcx > ,
241
+ ) -> PreInliningPartitioning < ' tcx >
213
242
where
214
243
I : Iterator < Item = MonoItem < ' tcx > > ,
215
244
{
@@ -260,8 +289,8 @@ where
260
289
if visibility == Visibility :: Hidden && can_be_internalized {
261
290
internalization_candidates. insert ( mono_item) ;
262
291
}
263
-
264
- codegen_unit. items_mut ( ) . insert ( mono_item, ( linkage, visibility) ) ;
292
+ let item_size = estimator . size_estimate ( tcx , mono_item ) ;
293
+ codegen_unit. add_item ( mono_item, ( linkage, visibility) , item_size ) ;
265
294
roots. insert ( mono_item) ;
266
295
}
267
296
@@ -475,6 +504,7 @@ fn merge_codegen_units<'tcx>(
475
504
tcx : TyCtxt < ' tcx > ,
476
505
partitioning : & mut PostInliningPartitioning < ' tcx > ,
477
506
target_cgu_count : usize ,
507
+ estimator : & mut SizeEstimator < ' tcx > ,
478
508
) {
479
509
assert ! ( target_cgu_count >= 1 ) ;
480
510
let codegen_units = & mut partitioning. codegen_units ;
@@ -497,10 +527,10 @@ fn merge_codegen_units<'tcx>(
497
527
let mut smallest = codegen_units. pop ( ) . unwrap ( ) ;
498
528
let second_smallest = codegen_units. last_mut ( ) . unwrap ( ) ;
499
529
500
- for ( k, v) in smallest. items_mut ( ) . drain ( ) {
501
- second_smallest. items_mut ( ) . insert ( k, v) ;
530
+ for ( mono_item, v) in smallest. items_mut ( ) . drain ( ) {
531
+ let item_size = estimator. size_estimate ( tcx, mono_item) ;
532
+ second_smallest. add_item ( mono_item, v, item_size) ;
502
533
}
503
- second_smallest. estimate_size ( tcx) ;
504
534
debug ! ( "CodegenUnit {} merged in to CodegenUnit {}" ,
505
535
smallest. name( ) ,
506
536
second_smallest. name( ) ) ;
@@ -512,9 +542,11 @@ fn merge_codegen_units<'tcx>(
512
542
}
513
543
}
514
544
515
- fn place_inlined_mono_items < ' tcx > ( initial_partitioning : PreInliningPartitioning < ' tcx > ,
516
- inlining_map : & InliningMap < ' tcx > )
517
- -> PostInliningPartitioning < ' tcx > {
545
+ fn place_inlined_mono_items < ' tcx > ( tcx : TyCtxt < ' tcx > ,
546
+ initial_partitioning : PreInliningPartitioning < ' tcx > ,
547
+ inlining_map : & InliningMap < ' tcx > ,
548
+ estimator : & mut SizeEstimator < ' tcx > ,
549
+ ) -> PostInliningPartitioning < ' tcx > {
518
550
let mut new_partitioning = Vec :: new ( ) ;
519
551
520
552
let PreInliningPartitioning {
@@ -536,18 +568,20 @@ fn place_inlined_mono_items<'tcx>(initial_partitioning: PreInliningPartitioning<
536
568
for mono_item in reachable {
537
569
if let Some ( linkage) = old_codegen_unit. items ( ) . get ( & mono_item) {
538
570
// This is a root, just copy it over.
539
- new_codegen_unit. items_mut ( ) . insert ( mono_item, * linkage) ;
571
+ let item_size = estimator. size_estimate ( tcx, mono_item) ;
572
+ new_codegen_unit. add_item ( mono_item, * linkage, item_size) ;
540
573
} else {
541
574
if roots. contains ( & mono_item) {
542
575
bug ! ( "GloballyShared mono-item inlined into other CGU: \
543
576
{:?}", mono_item) ;
544
577
}
545
578
546
579
// This is a CGU-private copy.
547
- new_codegen_unit. items_mut ( ) . insert (
580
+ let item_size = estimator. size_estimate ( tcx, mono_item) ;
581
+ new_codegen_unit. add_item (
548
582
mono_item,
549
583
( Linkage :: Internal , Visibility :: Default ) ,
550
- ) ;
584
+ item_size ) ;
551
585
}
552
586
}
553
587
@@ -768,7 +802,10 @@ fn numbered_codegen_unit_name(
768
802
name_builder. build_cgu_name_no_mangle ( LOCAL_CRATE , & [ "cgu" ] , Some ( index) )
769
803
}
770
804
771
- fn debug_dump < ' a , ' tcx , I > ( tcx : TyCtxt < ' tcx > , label : & str , cgus : I )
805
+ fn debug_dump < ' a , ' tcx , I > ( tcx : TyCtxt < ' tcx > ,
806
+ label : & str ,
807
+ cgus : I ,
808
+ estimator : & mut SizeEstimator < ' tcx > )
772
809
where
773
810
I : Iterator < Item = & ' a CodegenUnit < ' tcx > > ,
774
811
' tcx : ' a ,
@@ -788,7 +825,7 @@ where
788
825
mono_item. to_string( tcx, true ) ,
789
826
linkage,
790
827
symbol_hash,
791
- mono_item . size_estimate( tcx) ) ;
828
+ estimator . size_estimate( tcx, * mono_item ) ) ;
792
829
}
793
830
794
831
debug ! ( "" ) ;
0 commit comments