Skip to content

Commit decf8a0

Browse files
committed
Build a new incr comp session dir from scratch every time
Rather than copying the old incr comp dir and then modifying it. This saves a copy/hardlink for files that are modified. And it removes the need for accurate work product tracking to avoid accumulating cruft, which is non-trivial. We don't accurately track the pre-LTO bitcode files for ThinLTO for example.
1 parent 87212ce commit decf8a0

15 files changed

Lines changed: 158 additions & 205 deletions

File tree

compiler/rustc_codegen_cranelift/src/driver/aot.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,6 @@ fn emit_module(
140140
bytecode: None,
141141
assembly: None,
142142
llvm_ir: None,
143-
links_from_incr_cache: Vec::new(),
144143
})
145144
}
146145

compiler/rustc_codegen_llvm/src/back/lto.rs

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -463,23 +463,33 @@ fn thin_lto(
463463

464464
info!("thin LTO data created");
465465

466-
let (key_map_path, prev_key_map, curr_key_map) = if let Some(ref incr_comp_session_dir) =
467-
cgcx.incr_comp_session_dir
466+
let new_key_map_path = cgcx
467+
.new_incr_comp_session_dir
468+
.as_ref()
469+
.map(|dir| dir.join(THIN_LTO_KEYS_INCR_COMP_FILE_NAME));
470+
471+
let (prev_key_map, curr_key_map) = if let Some(ref old_incr_comp_session_dir) =
472+
cgcx.old_incr_comp_session_dir
468473
{
469-
let path = incr_comp_session_dir.join(THIN_LTO_KEYS_INCR_COMP_FILE_NAME);
474+
let old_path = old_incr_comp_session_dir.join(THIN_LTO_KEYS_INCR_COMP_FILE_NAME);
475+
470476
// If the previous file was deleted, or we get an IO error
471477
// reading the file, then we'll just use `None` as the
472478
// prev_key_map, which will force the code to be recompiled.
473-
let prev =
474-
if path.exists() { ThinLTOKeysMap::load_from_file(&path).ok() } else { None };
479+
let prev = if old_path.exists() {
480+
ThinLTOKeysMap::load_from_file(&old_path).ok()
481+
} else {
482+
None
483+
};
475484
let curr = ThinLTOKeysMap::from_thin_lto_modules(&data, &thin_modules, &module_names);
476-
(Some(path), prev, curr)
485+
486+
(prev, curr)
477487
} else {
478488
// If we don't compile incrementally, we don't need to load the
479489
// import data from LLVM.
480490
assert!(green_modules.is_empty());
481491
let curr = ThinLTOKeysMap::default();
482-
(None, None, curr)
492+
(None, curr)
483493
};
484494
info!("thin LTO cache key map loaded");
485495
info!("prev_key_map: {:#?}", prev_key_map);
@@ -500,15 +510,15 @@ fn thin_lto(
500510
if let (Some(prev_key_map), true) =
501511
(prev_key_map.as_ref(), green_modules.contains_key(module_name))
502512
{
503-
assert!(cgcx.incr_comp_session_dir.is_some());
513+
assert!(cgcx.old_incr_comp_session_dir.is_some());
514+
assert!(cgcx.new_incr_comp_session_dir.is_some());
504515

505516
// If a module exists in both the current and the previous session,
506517
// and has the same LTO cache key in both sessions, then we can re-use it
507518
if prev_key_map.keys.get(module_name) == curr_key_map.keys.get(module_name) {
508519
let work_product = green_modules[module_name].clone();
509520
copy_jobs.push(work_product);
510521
info!(" - {}: re-used", module_name);
511-
assert!(cgcx.incr_comp_session_dir.is_some());
512522
continue;
513523
}
514524
}
@@ -518,8 +528,8 @@ fn thin_lto(
518528
}
519529

520530
// Save the current ThinLTO import information for the next compilation
521-
// session, overwriting the previous serialized data (if any).
522-
if let Some(path) = key_map_path
531+
// session.
532+
if let Some(path) = new_key_map_path
523533
&& let Err(err) = curr_key_map.save_to_file(&path)
524534
{
525535
write::llvm_err(dcx, LlvmError::WriteThinLtoKey { err });

compiler/rustc_codegen_ssa/src/back/write.rs

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ use rustc_errors::{
1616
};
1717
use rustc_fs_util::link_or_copy;
1818
use rustc_hir::find_attr;
19-
use rustc_incremental::{copy_cgu_workproduct_to_incr_comp_cache_dir, in_incr_comp_dir_sess};
19+
use rustc_incremental::{
20+
copy_cgu_workproduct_to_incr_comp_cache_dir, in_incr_comp_dir_sess, in_old_incr_comp_dir_sess,
21+
};
2022
use rustc_macros::{Decodable, Encodable};
2123
use rustc_metadata::fs::copy_to_stdout;
2224
use rustc_middle::bug;
@@ -354,9 +356,12 @@ pub struct CodegenContext {
354356
/// Directory into which should the LLVM optimization remarks be written.
355357
/// If `None`, they will be written to stderr.
356358
pub remark_dir: Option<PathBuf>,
359+
/// The previous incremental compilation session directory, or None if we
360+
/// are not compiling incrementally or there is no previous session.
361+
pub old_incr_comp_session_dir: Option<PathBuf>,
357362
/// The incremental compilation session directory, or None if we are not
358363
/// compiling incrementally
359-
pub incr_comp_session_dir: Option<PathBuf>,
364+
pub new_incr_comp_session_dir: Option<PathBuf>,
360365
/// `Some(limit)` if the codegen should be run in parallel.
361366
///
362367
/// Depends on [`WriteBackendMethods::supports_parallel()`] and `--jobs-backend`.
@@ -503,7 +508,6 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir(
503508
incr_comp_session.unwrap(),
504509
&module.name,
505510
files.as_slice(),
506-
&module.links_from_incr_cache,
507511
);
508512
work_products.insert(id, product);
509513
}
@@ -845,7 +849,7 @@ fn execute_optimize_work_item<B: WriteBackendMethods>(
845849
// save our module to disk first.
846850
let bitcode = if cgcx.module_config.emit_pre_lto_bc {
847851
let filename = pre_lto_bitcode_filename(&module.name);
848-
cgcx.incr_comp_session_dir.as_ref().map(|path| path.join(&filename))
852+
cgcx.new_incr_comp_session_dir.as_ref().map(|path| path.join(&filename))
849853
} else {
850854
None
851855
};
@@ -892,11 +896,9 @@ fn execute_copy_from_cache_work_item(
892896
let dcx = DiagCtxt::new(Box::new(shared_emitter));
893897
let dcx = dcx.handle();
894898

895-
let incr_comp_session_dir = cgcx.incr_comp_session_dir.as_ref().unwrap();
896-
897-
let mut links_from_incr_cache = Vec::new();
899+
let incr_comp_session_dir = cgcx.old_incr_comp_session_dir.as_ref().unwrap();
898900

899-
let mut load_from_incr_comp_dir = |output_path: PathBuf, saved_path: &str| {
901+
let load_from_incr_comp_dir = |output_path: PathBuf, saved_path: &str| {
900902
let source_file_in_incr_comp_dir = incr_comp_session_dir.join(saved_path);
901903
debug!(
902904
"copying preexisting module `{}` from {:?} to {}",
@@ -905,10 +907,7 @@ fn execute_copy_from_cache_work_item(
905907
output_path.display()
906908
);
907909
match link_or_copy(&source_file_in_incr_comp_dir, &output_path) {
908-
Ok(_) => {
909-
links_from_incr_cache.push(source_file_in_incr_comp_dir);
910-
Some(output_path)
911-
}
910+
Ok(_) => Some(output_path),
912911
Err(error) => {
913912
dcx.emit_err(diagnostics::CopyPathBuf {
914913
source_file: source_file_in_incr_comp_dir,
@@ -931,7 +930,7 @@ fn execute_copy_from_cache_work_item(
931930
load_from_incr_comp_dir(dwarf_obj_out, saved_dwarf_object_file)
932931
});
933932

934-
let mut load_from_incr_cache = |perform, output_type: OutputType| {
933+
let load_from_incr_cache = |perform, output_type: OutputType| {
935934
if perform {
936935
let saved_file = module.source.saved_files.get(output_type.extension())?;
937936
let output_path = cgcx.output_filenames.temp_path_for_cgu(output_type, &module.name);
@@ -959,7 +958,6 @@ fn execute_copy_from_cache_work_item(
959958
}
960959

961960
CompiledModule {
962-
links_from_incr_cache,
963961
kind: ModuleKind::Regular,
964962
name: module.name,
965963
object,
@@ -1301,10 +1299,14 @@ fn start_executing_work<B: WriteBackendMethods>(
13011299
time_trace: sess.opts.unstable_opts.llvm_time_trace,
13021300
remark: sess.opts.cg.remark.clone(),
13031301
remark_dir,
1304-
incr_comp_session_dir: tcx
1302+
old_incr_comp_session_dir: tcx
1303+
.incr_comp_session
1304+
.as_ref()
1305+
.and_then(|incr_comp_session| incr_comp_session.old_session_directory.clone()),
1306+
new_incr_comp_session_dir: tcx
13051307
.incr_comp_session
13061308
.as_ref()
1307-
.map(|incr_comp_session| incr_comp_session.session_directory.clone()),
1309+
.map(|incr_comp_session| incr_comp_session.new_session_directory.clone()),
13081310
output_filenames: Arc::clone(tcx.output_filenames(())),
13091311
module_config: regular_config,
13101312
opt_level,
@@ -2278,7 +2280,22 @@ pub(crate) fn submit_pre_lto_module_to_llvm<B: WriteBackendMethods>(
22782280
module: CachedModuleCodegen,
22792281
) {
22802282
let filename = pre_lto_bitcode_filename(&module.name);
2283+
let old_bitcode_path =
2284+
in_old_incr_comp_dir_sess(tcx.incr_comp_session.unwrap(), &filename).unwrap();
22812285
let bitcode_path = in_incr_comp_dir_sess(tcx.incr_comp_session.unwrap(), &filename);
2286+
2287+
match link_or_copy(&old_bitcode_path, &bitcode_path) {
2288+
Ok(_) => {}
2289+
Err(error) => {
2290+
tcx.sess.dcx().emit_err(diagnostics::CopyPathBuf {
2291+
source_file: old_bitcode_path,
2292+
output_path: bitcode_path,
2293+
error,
2294+
});
2295+
return;
2296+
}
2297+
}
2298+
22822299
// Schedule the module to be loaded
22832300
drop(
22842301
coordinator

compiler/rustc_codegen_ssa/src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,6 @@ impl<M> ModuleCodegen<M> {
115115
bytecode,
116116
assembly,
117117
llvm_ir,
118-
links_from_incr_cache: Vec::new(),
119118
}
120119
}
121120
}
@@ -130,7 +129,6 @@ pub struct CompiledModule {
130129
pub bytecode: Option<PathBuf>,
131130
pub assembly: Option<PathBuf>, // --emit=asm
132131
pub llvm_ir: Option<PathBuf>, // --emit=llvm-ir, llvm-bc is in bytecode
133-
pub links_from_incr_cache: Vec<PathBuf>,
134132
}
135133

136134
impl CompiledModule {

compiler/rustc_incremental/src/diagnostics.rs

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -169,21 +169,6 @@ pub(crate) struct DeleteLock<'a> {
169169
pub err: std::io::Error,
170170
}
171171

172-
#[derive(Diagnostic)]
173-
#[diag(
174-
"hard linking files in the incremental compilation cache failed. copying files instead. consider moving the cache directory to a file system which supports hard linking in session dir `{$path}`"
175-
)]
176-
pub(crate) struct HardLinkFailed<'a> {
177-
pub path: &'a Path,
178-
}
179-
180-
#[derive(Diagnostic)]
181-
#[diag("failed to delete partly initialized session dir `{$path}`: {$err}")]
182-
pub(crate) struct DeletePartial<'a> {
183-
pub path: &'a Path,
184-
pub err: std::io::Error,
185-
}
186-
187172
#[derive(Diagnostic)]
188173
#[diag("did not finalize incremental compilation session directory `{$path}`: {$err}")]
189174
#[help("the next build will not be able to reuse work from this compilation")]

compiler/rustc_incremental/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ mod persist;
1111

1212
pub use persist::{
1313
copy_cgu_workproduct_to_incr_comp_cache_dir, finalize_session_directory, in_incr_comp_dir_sess,
14-
load_query_result_cache, save_work_product_index, setup_dep_graph,
14+
in_old_incr_comp_dir_sess, load_query_result_cache, save_work_product_index, setup_dep_graph,
1515
};
1616
use rustc_middle::util::Providers;
1717

0 commit comments

Comments
 (0)