@@ -132,19 +132,29 @@ pub struct CodegenUnit<'tcx> {
132132 pub items : FnvHashMap < TransItem < ' tcx > , llvm:: Linkage > ,
133133}
134134
135+ pub enum PartitioningStrategy {
136+ PerModule ,
137+ FixedUnitCount ( usize )
138+ }
139+
135140// Anything we can't find a proper codegen unit for goes into this.
136141const FALLBACK_CODEGEN_UNIT : & ' static str = "__rustc_fallback_codegen_unit" ;
137142
138143pub fn partition < ' tcx , I > ( tcx : & TyCtxt < ' tcx > ,
139144 trans_items : I ,
145+ strategy : PartitioningStrategy ,
140146 inlining_map : & InliningMap < ' tcx > )
141147 -> Vec < CodegenUnit < ' tcx > >
142148 where I : Iterator < Item = TransItem < ' tcx > >
143149{
144150 // In the first step, we place all regular translation items into their
145151 // respective 'home' codegen unit. Regular translation items are all
146152 // 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+ }
148158
149159 // In the next step, we use the inlining map to determine which addtional
150160 // 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>,
217227 }
218228}
219229
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+
220257fn place_inlined_translation_items < ' tcx > ( initial_partitioning : InitialPartitioning < ' tcx > ,
221258 inlining_map : & InliningMap < ' tcx > )
222259 -> Vec < CodegenUnit < ' tcx > > {
0 commit comments