Skip to content

Commit d9dd28d

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 f9679fa commit d9dd28d

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
@@ -15,7 +15,9 @@ use rustc_errors::{
1515
};
1616
use rustc_fs_util::link_or_copy;
1717
use rustc_hir::find_attr;
18-
use rustc_incremental::{copy_cgu_workproduct_to_incr_comp_cache_dir, in_incr_comp_dir_sess};
18+
use rustc_incremental::{
19+
copy_cgu_workproduct_to_incr_comp_cache_dir, in_incr_comp_dir_sess, in_old_incr_comp_dir_sess,
20+
};
1921
use rustc_macros::{Decodable, Encodable};
2022
use rustc_metadata::fs::copy_to_stdout;
2123
use rustc_middle::bug;
@@ -349,9 +351,12 @@ pub struct CodegenContext {
349351
/// Directory into which should the LLVM optimization remarks be written.
350352
/// If `None`, they will be written to stderr.
351353
pub remark_dir: Option<PathBuf>,
354+
/// The previous incremental compilation session directory, or None if we
355+
/// are not compiling incrementally or there is no previous session.
356+
pub old_incr_comp_session_dir: Option<PathBuf>,
352357
/// The incremental compilation session directory, or None if we are not
353358
/// compiling incrementally
354-
pub incr_comp_session_dir: Option<PathBuf>,
359+
pub new_incr_comp_session_dir: Option<PathBuf>,
355360
/// `true` if the codegen should be run in parallel.
356361
///
357362
/// Depends on [`WriteBackendMethods::supports_parallel()`] and `-Zno_parallel_backend`.
@@ -498,7 +503,6 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir(
498503
incr_comp_session.unwrap(),
499504
&module.name,
500505
files.as_slice(),
501-
&module.links_from_incr_cache,
502506
);
503507
work_products.insert(id, product);
504508
}
@@ -840,7 +844,7 @@ fn execute_optimize_work_item<B: WriteBackendMethods>(
840844
// save our module to disk first.
841845
let bitcode = if cgcx.module_config.emit_pre_lto_bc {
842846
let filename = pre_lto_bitcode_filename(&module.name);
843-
cgcx.incr_comp_session_dir.as_ref().map(|path| path.join(&filename))
847+
cgcx.new_incr_comp_session_dir.as_ref().map(|path| path.join(&filename))
844848
} else {
845849
None
846850
};
@@ -887,11 +891,9 @@ fn execute_copy_from_cache_work_item(
887891
let dcx = DiagCtxt::new(Box::new(shared_emitter));
888892
let dcx = dcx.handle();
889893

890-
let incr_comp_session_dir = cgcx.incr_comp_session_dir.as_ref().unwrap();
891-
892-
let mut links_from_incr_cache = Vec::new();
894+
let incr_comp_session_dir = cgcx.old_incr_comp_session_dir.as_ref().unwrap();
893895

894-
let mut load_from_incr_comp_dir = |output_path: PathBuf, saved_path: &str| {
896+
let load_from_incr_comp_dir = |output_path: PathBuf, saved_path: &str| {
895897
let source_file_in_incr_comp_dir = incr_comp_session_dir.join(saved_path);
896898
debug!(
897899
"copying preexisting module `{}` from {:?} to {}",
@@ -900,10 +902,7 @@ fn execute_copy_from_cache_work_item(
900902
output_path.display()
901903
);
902904
match link_or_copy(&source_file_in_incr_comp_dir, &output_path) {
903-
Ok(_) => {
904-
links_from_incr_cache.push(source_file_in_incr_comp_dir);
905-
Some(output_path)
906-
}
905+
Ok(_) => Some(output_path),
907906
Err(error) => {
908907
dcx.emit_err(diagnostics::CopyPathBuf {
909908
source_file: source_file_in_incr_comp_dir,
@@ -926,7 +925,7 @@ fn execute_copy_from_cache_work_item(
926925
load_from_incr_comp_dir(dwarf_obj_out, saved_dwarf_object_file)
927926
});
928927

929-
let mut load_from_incr_cache = |perform, output_type: OutputType| {
928+
let load_from_incr_cache = |perform, output_type: OutputType| {
930929
if perform {
931930
let saved_file = module.source.saved_files.get(output_type.extension())?;
932931
let output_path = cgcx.output_filenames.temp_path_for_cgu(output_type, &module.name);
@@ -954,7 +953,6 @@ fn execute_copy_from_cache_work_item(
954953
}
955954

956955
CompiledModule {
957-
links_from_incr_cache,
958956
kind: ModuleKind::Regular,
959957
name: module.name,
960958
object,
@@ -1288,10 +1286,14 @@ fn start_executing_work<B: WriteBackendMethods>(
12881286
time_trace: sess.opts.unstable_opts.llvm_time_trace,
12891287
remark: sess.opts.cg.remark.clone(),
12901288
remark_dir,
1291-
incr_comp_session_dir: tcx
1289+
old_incr_comp_session_dir: tcx
1290+
.incr_comp_session
1291+
.as_ref()
1292+
.and_then(|incr_comp_session| incr_comp_session.old_session_directory.clone()),
1293+
new_incr_comp_session_dir: tcx
12921294
.incr_comp_session
12931295
.as_ref()
1294-
.map(|incr_comp_session| incr_comp_session.session_directory.clone()),
1296+
.map(|incr_comp_session| incr_comp_session.new_session_directory.clone()),
12951297
output_filenames: Arc::clone(tcx.output_filenames(())),
12961298
module_config: regular_config,
12971299
opt_level,
@@ -2262,7 +2264,22 @@ pub(crate) fn submit_pre_lto_module_to_llvm<B: WriteBackendMethods>(
22622264
module: CachedModuleCodegen,
22632265
) {
22642266
let filename = pre_lto_bitcode_filename(&module.name);
2267+
let old_bitcode_path =
2268+
in_old_incr_comp_dir_sess(tcx.incr_comp_session.unwrap(), &filename).unwrap();
22652269
let bitcode_path = in_incr_comp_dir_sess(tcx.incr_comp_session.unwrap(), &filename);
2270+
2271+
match link_or_copy(&old_bitcode_path, &bitcode_path) {
2272+
Ok(_) => {}
2273+
Err(error) => {
2274+
tcx.sess.dcx().emit_err(diagnostics::CopyPathBuf {
2275+
source_file: old_bitcode_path,
2276+
output_path: bitcode_path,
2277+
error,
2278+
});
2279+
return;
2280+
}
2281+
}
2282+
22662283
// Schedule the module to be loaded
22672284
drop(
22682285
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)