Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rustc: Allow target-specific default cgus #45032

Merged
merged 1 commit into from
Oct 13, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 3 additions & 45 deletions src/librustc/session/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ top_level_options!(
actually_rustdoc: bool [TRACKED],

// Number of object files/codegen units to produce on the backend
codegen_units: usize [UNTRACKED],
cli_forced_codegen_units: Option<usize> [UNTRACKED],
}
);

Expand Down Expand Up @@ -505,7 +505,7 @@ pub fn basic_options() -> Options {
unstable_features: UnstableFeatures::Disallow,
debug_assertions: true,
actually_rustdoc: false,
codegen_units: 1,
cli_forced_codegen_units: None,
}
}

Expand Down Expand Up @@ -1711,48 +1711,6 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)

let incremental = debugging_opts.incremental.as_ref().map(|m| PathBuf::from(m));

let codegen_units = codegen_units.unwrap_or_else(|| {
match opt_level {
// If we're compiling at `-O0` then default to 16 codegen units.
// The number here shouldn't matter too too much as debug mode
// builds don't rely on performance at all, meaning that lost
// opportunities for inlining through multiple codegen units is
// a non-issue.
//
// Note that the high number here doesn't mean that we'll be
// spawning a large number of threads in parallel. The backend
// of rustc contains global rate limiting through the
// `jobserver` crate so we'll never overload the system with too
// much work, but rather we'll only be optimizing when we're
// otherwise cooperating with other instances of rustc.
//
// Rather the high number here means that we should be able to
// keep a lot of idle cpus busy. By ensuring that no codegen
// unit takes *too* long to build we'll be guaranteed that all
// cpus will finish pretty closely to one another and we should
// make relatively optimal use of system resources
//
// Another note worth mentioning here, however, is that this number
// isn't *too* high. When codegen units are increased that means we
// currently have to codegen `#[inline]` functions into each codegen
// unit, which means the more codegen units we're using the more we
// may be generating. In other words, increasing codegen units may
// increase the overall work the compiler does. If we don't have
// enough cores to make up for this loss then increasing the number
// of codegen units could become an overall loss!
//
// As a result we choose a hopefully conservative value 16, which
// should be more than the number of cpus of most hardware compiling
// Rust but also not too much for 2-4 core machines to have too much
// loss of compile time.
OptLevel::No => 16,

// All other optimization levels default use one codegen unit,
// the historical default in Rust for a Long Time.
_ => 1,
}
});

(Options {
crate_types,
optimize: opt_level,
Expand All @@ -1777,7 +1735,7 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
unstable_features: UnstableFeatures::from_environment(),
debug_assertions,
actually_rustdoc: false,
codegen_units,
cli_forced_codegen_units: codegen_units,
},
cfg)
}
Expand Down
37 changes: 37 additions & 0 deletions src/librustc/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,43 @@ impl Session {
}
ret
}

/// Returns the number of codegen units that should be used for this
/// compilation
pub fn codegen_units(&self) -> usize {
if let Some(n) = self.opts.cli_forced_codegen_units {
return n
}
if let Some(n) = self.target.target.options.default_codegen_units {
return n as usize
}

match self.opts.optimize {
// If we're compiling at `-O0` then default to 16 codegen units.
// The number here shouldn't matter too too much as debug mode
// builds don't rely on performance at all, meaning that lost
// opportunities for inlining through multiple codegen units is
// a non-issue.
//
// Note that the high number here doesn't mean that we'll be
// spawning a large number of threads in parallel. The backend
// of rustc contains global rate limiting through the
// `jobserver` crate so we'll never overload the system with too
// much work, but rather we'll only be optimizing when we're
// otherwise cooperating with other instances of rustc.
//
// Rather the high number here means that we should be able to
// keep a lot of idle cpus busy. By ensuring that no codegen
// unit takes *too* long to build we'll be guaranteed that all
// cpus will finish pretty closely to one another and we should
// make relatively optimal use of system resources
config::OptLevel::No => 16,

// All other optimization levels default use one codegen unit,
// the historical default in Rust for a Long Time.
_ => 1,
}
}
}

pub fn build_session(sopts: config::Options,
Expand Down
6 changes: 6 additions & 0 deletions src/librustc_back/target/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,9 @@ pub struct TargetOptions {

/// The minimum alignment for global symbols.
pub min_global_align: Option<u64>,

/// Default number of codegen units to use in debug mode
pub default_codegen_units: Option<u64>,
}

impl Default for TargetOptions {
Expand Down Expand Up @@ -492,6 +495,7 @@ impl Default for TargetOptions {
crt_static_respected: false,
stack_probes: false,
min_global_align: None,
default_codegen_units: None,
}
}
}
Expand Down Expand Up @@ -732,6 +736,7 @@ impl Target {
key!(crt_static_respected, bool);
key!(stack_probes, bool);
key!(min_global_align, Option<u64>);
key!(default_codegen_units, Option<u64>);

if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) {
for name in array.iter().filter_map(|abi| abi.as_string()) {
Expand Down Expand Up @@ -924,6 +929,7 @@ impl ToJson for Target {
target_option_val!(crt_static_respected);
target_option_val!(stack_probes);
target_option_val!(min_global_align);
target_option_val!(default_codegen_units);

if default.abi_blacklist != self.options.abi_blacklist {
d.insert("abi-blacklist".to_string(), self.options.abi_blacklist.iter()
Expand Down
5 changes: 5 additions & 0 deletions src/librustc_back/target/msp430_none_elf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ pub fn target() -> TargetResult {
// code because of the extra costs it involves.
relocation_model: "static".to_string(),

// Right now we invoke an external assembler and this isn't
// compatible with multiple codegen units, and plus we probably
// don't want to invoke that many gcc instances.
default_codegen_units: Some(1),

.. Default::default( )
}
})
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_trans/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ fn link_rlib<'a>(sess: &'a Session,
// of when we do and don't keep .#module-name#.bc files around.
let user_wants_numbered_bitcode =
sess.opts.output_types.contains_key(&OutputType::Bitcode) &&
sess.opts.codegen_units > 1;
sess.codegen_units() > 1;
if !sess.opts.cg.save_temps && !user_wants_numbered_bitcode {
remove(sess, &bc_filename);
}
Expand Down
6 changes: 3 additions & 3 deletions src/librustc_trans/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1037,10 +1037,10 @@ fn produce_final_output_artifacts(sess: &Session,
let needs_crate_object = crate_output.outputs.contains_key(&OutputType::Exe);

let keep_numbered_bitcode = needs_crate_bitcode ||
(user_wants_bitcode && sess.opts.codegen_units > 1);
(user_wants_bitcode && sess.codegen_units() > 1);

let keep_numbered_objects = needs_crate_object ||
(user_wants_objects && sess.opts.codegen_units > 1);
(user_wants_objects && sess.codegen_units() > 1);

for module in compiled_modules.modules.iter() {
let module_name = Some(&module.name[..]);
Expand Down Expand Up @@ -2052,7 +2052,7 @@ impl OngoingCrateTranslation {

// FIXME: time_llvm_passes support - does this use a global context or
// something?
if sess.opts.codegen_units == 1 && sess.time_llvm_passes() {
if sess.codegen_units() == 1 && sess.time_llvm_passes() {
unsafe { llvm::LLVMRustPrintPassTimings(); }
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc_trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1218,7 +1218,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>(
let strategy = if tcx.sess.opts.debugging_opts.incremental.is_some() {
PartitioningStrategy::PerModule
} else {
PartitioningStrategy::FixedUnitCount(tcx.sess.opts.codegen_units)
PartitioningStrategy::FixedUnitCount(tcx.sess.codegen_units())
};

let codegen_units = time(time_passes, "codegen unit partitioning", || {
Expand Down