use build::*;
use builder::{Builder, noname};
use callee::{Callee, CallArgs, ArgExprs, ArgVals};
-use partitioning;
+use partitioning::{self, PartitioningStrategy};
use cleanup::{self, CleanupMethods, DropHint};
use closure;
use common::{Block, C_bool, C_bytes_in_context, C_i32, C_int, C_uint, C_integral};
collector::collect_crate_translation_items(&ccx, collection_mode)
});
+ let strategy = if ccx.sess().opts.debugging_opts.incremental.is_some() {
+ PartitioningStrategy::PerModule
+ } else {
+ PartitioningStrategy::FixedUnitCount(ccx.sess().opts.cg.codegen_units)
+ };
+
let codegen_units = time(time_passes, "codegen unit partitioning", || {
- partitioning::partition(ccx.tcx(), items.iter().cloned(), &inlining_map)
+ partitioning::partition(ccx.tcx(),
+ items.iter().cloned(),
+ strategy,
+ &inlining_map)
});
if ccx.sess().opts.debugging_opts.print_trans_items.is_some() {
pub items: FnvHashMap<TransItem<'tcx>, llvm::Linkage>,
}
+pub enum PartitioningStrategy {
+ PerModule,
+ FixedUnitCount(usize)
+}
+
// Anything we can't find a proper codegen unit for goes into this.
const FALLBACK_CODEGEN_UNIT: &'static str = "__rustc_fallback_codegen_unit";
pub fn partition<'tcx, I>(tcx: &TyCtxt<'tcx>,
trans_items: I,
+ strategy: PartitioningStrategy,
inlining_map: &InliningMap<'tcx>)
-> Vec<CodegenUnit<'tcx>>
where I: Iterator<Item = TransItem<'tcx>>
// In the first step, we place all regular translation items into their
// respective 'home' codegen unit. Regular translation items are all
// functions and statics defined in the local crate.
- let initial_partitioning = place_root_translation_items(tcx, trans_items);
+ let mut initial_partitioning = place_root_translation_items(tcx, trans_items);
+
+ if let PartitioningStrategy::FixedUnitCount(count) = strategy {
+ merge_codegen_units(&mut initial_partitioning, count, &tcx.crate_name[..]);
+ }
// In the next step, we use the inlining map to determine which addtional
// translation items have to go into each codegen unit. These additional
}
}
+fn merge_codegen_units<'tcx>(initial_partitioning: &mut InitialPartitioning<'tcx>,
+ target_cgu_count: usize,
+ crate_name: &str) {
+ if target_cgu_count >= initial_partitioning.codegen_units.len() {
+ return;
+ }
+
+ assert!(target_cgu_count >= 1);
+ let codegen_units = &mut initial_partitioning.codegen_units;
+
+ // Merge the two smallest codegen units until the target size is reached
+ while codegen_units.len() > target_cgu_count {
+ // Sort small cgus to the back
+ codegen_units.as_mut_slice().sort_by_key(|cgu| -(cgu.items.len() as i64));
+ let smallest = codegen_units.pop().unwrap();
+ let second_smallest = codegen_units.last_mut().unwrap();
+
+ for (k, v) in smallest.items.into_iter() {
+ second_smallest.items.insert(k, v);
+ }
+ }
+
+ for (index, cgu) in codegen_units.iter_mut().enumerate() {
+ cgu.name = token::intern_and_get_ident(&format!("{}.{}", crate_name, index)[..]);
+ }
+}
+
fn place_inlined_translation_items<'tcx>(initial_partitioning: InitialPartitioning<'tcx>,
inlining_map: &InliningMap<'tcx>)
-> Vec<CodegenUnit<'tcx>> {