incr.ThinLTO: Do some cleanup and add some logging.
This commit is contained in:
parent
d5545751f9
commit
21d05f64aa
2 changed files with 57 additions and 62 deletions
|
@ -29,7 +29,7 @@ use {ModuleCodegen, ModuleLlvm, ModuleKind};
|
||||||
use libc;
|
use libc;
|
||||||
|
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString};
|
||||||
use std::fs::File;
|
use std::fs::{self, File};
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -423,16 +423,10 @@ fn thin_lto(cgcx: &CodegenContext,
|
||||||
// because only then it will contain the ThinLTO module summary.
|
// because only then it will contain the ThinLTO module summary.
|
||||||
if let Some(ref incr_comp_session_dir) = cgcx.incr_comp_session_dir {
|
if let Some(ref incr_comp_session_dir) = cgcx.incr_comp_session_dir {
|
||||||
if cgcx.config(module.kind).emit_pre_thin_lto_bc {
|
if cgcx.config(module.kind).emit_pre_thin_lto_bc {
|
||||||
use std::io::Write;
|
|
||||||
|
|
||||||
let path = incr_comp_session_dir
|
let path = incr_comp_session_dir
|
||||||
.join(pre_lto_bitcode_filename(&module.name));
|
.join(pre_lto_bitcode_filename(&module.name));
|
||||||
let mut file = File::create(&path).unwrap_or_else(|e| {
|
|
||||||
panic!("Failed to create pre-lto-bitcode file `{}`: {}",
|
fs::write(&path, buffer.data()).unwrap_or_else(|e| {
|
||||||
path.display(),
|
|
||||||
e);
|
|
||||||
});
|
|
||||||
file.write_all(buffer.data()).unwrap_or_else(|e| {
|
|
||||||
panic!("Error writing pre-lto-bitcode file `{}`: {}",
|
panic!("Error writing pre-lto-bitcode file `{}`: {}",
|
||||||
path.display(),
|
path.display(),
|
||||||
e);
|
e);
|
||||||
|
@ -499,12 +493,22 @@ fn thin_lto(cgcx: &CodegenContext,
|
||||||
write::llvm_err(&diag_handler, "failed to prepare thin LTO context".to_string())
|
write::llvm_err(&diag_handler, "failed to prepare thin LTO context".to_string())
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let import_map = ThinLTOImports::from_thin_lto_data(data);
|
|
||||||
|
|
||||||
let data = ThinData(data);
|
|
||||||
info!("thin LTO data created");
|
info!("thin LTO data created");
|
||||||
timeline.record("data");
|
timeline.record("data");
|
||||||
|
|
||||||
|
let import_map = if cgcx.incr_comp_session_dir.is_some() {
|
||||||
|
ThinLTOImports::from_thin_lto_data(data)
|
||||||
|
} else {
|
||||||
|
// If we don't compile incrementally, we don't need to load the
|
||||||
|
// import data from LLVM.
|
||||||
|
assert!(green_modules.is_empty());
|
||||||
|
ThinLTOImports::new()
|
||||||
|
};
|
||||||
|
info!("thin LTO import map loaded");
|
||||||
|
timeline.record("import-map-loaded");
|
||||||
|
|
||||||
|
let data = ThinData(data);
|
||||||
|
|
||||||
// Throw our data in an `Arc` as we'll be sharing it across threads. We
|
// Throw our data in an `Arc` as we'll be sharing it across threads. We
|
||||||
// also put all memory referenced by the C++ data (buffers, ids, etc)
|
// also put all memory referenced by the C++ data (buffers, ids, etc)
|
||||||
// into the arc as well. After this we'll create a thin module
|
// into the arc as well. After this we'll create a thin module
|
||||||
|
@ -519,25 +523,27 @@ fn thin_lto(cgcx: &CodegenContext,
|
||||||
let mut copy_jobs = vec![];
|
let mut copy_jobs = vec![];
|
||||||
let mut opt_jobs = vec![];
|
let mut opt_jobs = vec![];
|
||||||
|
|
||||||
|
info!("checking which modules can be-reused and which have to be re-optimized.");
|
||||||
for (module_index, module_name) in shared.module_names.iter().enumerate() {
|
for (module_index, module_name) in shared.module_names.iter().enumerate() {
|
||||||
let module_name = module_name_to_str(module_name);
|
let module_name = module_name_to_str(module_name);
|
||||||
|
|
||||||
|
// If the module hasn't changed and none of the modules it imports
|
||||||
|
// from has changed, we can re-use the post-ThinLTO version of the
|
||||||
|
// module.
|
||||||
if green_modules.contains_key(module_name) {
|
if green_modules.contains_key(module_name) {
|
||||||
let mut imports_all_green = true;
|
let imports_all_green = import_map.modules_imported_by(module_name)
|
||||||
for imported_module in import_map.modules_imported_by(module_name) {
|
.iter()
|
||||||
if !green_modules.contains_key(imported_module) {
|
.all(|imported_module| green_modules.contains_key(imported_module));
|
||||||
imports_all_green = false;
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if imports_all_green {
|
if imports_all_green {
|
||||||
let work_product = green_modules[module_name].clone();
|
let work_product = green_modules[module_name].clone();
|
||||||
copy_jobs.push(work_product);
|
copy_jobs.push(work_product);
|
||||||
|
info!(" - {}: re-used", module_name);
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info!(" - {}: re-compiled", module_name);
|
||||||
opt_jobs.push(LtoModuleCodegen::Thin(ThinModule {
|
opt_jobs.push(LtoModuleCodegen::Thin(ThinModule {
|
||||||
shared: shared.clone(),
|
shared: shared.clone(),
|
||||||
idx: module_index,
|
idx: module_index,
|
||||||
|
@ -872,7 +878,13 @@ pub struct ThinLTOImports {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ThinLTOImports {
|
impl ThinLTOImports {
|
||||||
pub fn modules_imported_by(&self, llvm_module_name: &str) -> &[String] {
|
fn new() -> ThinLTOImports {
|
||||||
|
ThinLTOImports {
|
||||||
|
imports: FxHashMap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn modules_imported_by(&self, llvm_module_name: &str) -> &[String] {
|
||||||
self.imports.get(llvm_module_name).map(|v| &v[..]).unwrap_or(&[])
|
self.imports.get(llvm_module_name).map(|v| &v[..]).unwrap_or(&[])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -915,4 +927,4 @@ fn module_name_to_str(c_str: &CStr) -> &str {
|
||||||
e)
|
e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1311,36 +1311,31 @@ fn execute_work_item(cgcx: &CodegenContext,
|
||||||
timeline: &mut Timeline)
|
timeline: &mut Timeline)
|
||||||
-> Result<WorkItemResult, FatalError>
|
-> Result<WorkItemResult, FatalError>
|
||||||
{
|
{
|
||||||
|
let module_config = cgcx.config(work_item.module_kind());
|
||||||
|
|
||||||
match work_item {
|
match work_item {
|
||||||
work_item @ WorkItem::Optimize(_) => {
|
WorkItem::Optimize(module) => {
|
||||||
execute_optimize_work_item(cgcx, work_item, timeline)
|
execute_optimize_work_item(cgcx, module, module_config, timeline)
|
||||||
}
|
}
|
||||||
work_item @ WorkItem::CopyPostLtoArtifacts(_) => {
|
WorkItem::CopyPostLtoArtifacts(module) => {
|
||||||
execute_copy_from_cache_work_item(cgcx, work_item, timeline)
|
execute_copy_from_cache_work_item(cgcx, module, module_config, timeline)
|
||||||
}
|
}
|
||||||
work_item @ WorkItem::LTO(_) => {
|
WorkItem::LTO(module) => {
|
||||||
execute_lto_work_item(cgcx, work_item, timeline)
|
execute_lto_work_item(cgcx, module, module_config, timeline)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_optimize_work_item(cgcx: &CodegenContext,
|
fn execute_optimize_work_item(cgcx: &CodegenContext,
|
||||||
work_item: WorkItem,
|
module: ModuleCodegen,
|
||||||
|
module_config: &ModuleConfig,
|
||||||
timeline: &mut Timeline)
|
timeline: &mut Timeline)
|
||||||
-> Result<WorkItemResult, FatalError>
|
-> Result<WorkItemResult, FatalError>
|
||||||
{
|
{
|
||||||
let config = cgcx.config(work_item.module_kind());
|
|
||||||
|
|
||||||
let module = if let WorkItem::Optimize(module) = work_item {
|
|
||||||
module
|
|
||||||
} else {
|
|
||||||
bug!("execute_optimize_work_item() called with non-WorkItem::Optimize");
|
|
||||||
};
|
|
||||||
|
|
||||||
let diag_handler = cgcx.create_diag_handler();
|
let diag_handler = cgcx.create_diag_handler();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
optimize(cgcx, &diag_handler, &module, config, timeline)?;
|
optimize(cgcx, &diag_handler, &module, module_config, timeline)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let linker_does_lto = cgcx.opts.debugging_opts.cross_lang_lto.enabled();
|
let linker_does_lto = cgcx.opts.debugging_opts.cross_lang_lto.enabled();
|
||||||
|
@ -1394,25 +1389,18 @@ fn execute_optimize_work_item(cgcx: &CodegenContext,
|
||||||
Ok(WorkItemResult::NeedsLTO(module))
|
Ok(WorkItemResult::NeedsLTO(module))
|
||||||
} else {
|
} else {
|
||||||
let module = unsafe {
|
let module = unsafe {
|
||||||
codegen(cgcx, &diag_handler, module, config, timeline)?
|
codegen(cgcx, &diag_handler, module, module_config, timeline)?
|
||||||
};
|
};
|
||||||
Ok(WorkItemResult::Compiled(module))
|
Ok(WorkItemResult::Compiled(module))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_copy_from_cache_work_item(cgcx: &CodegenContext,
|
fn execute_copy_from_cache_work_item(cgcx: &CodegenContext,
|
||||||
work_item: WorkItem,
|
module: CachedModuleCodegen,
|
||||||
|
module_config: &ModuleConfig,
|
||||||
_: &mut Timeline)
|
_: &mut Timeline)
|
||||||
-> Result<WorkItemResult, FatalError>
|
-> Result<WorkItemResult, FatalError>
|
||||||
{
|
{
|
||||||
let config = cgcx.config(work_item.module_kind());
|
|
||||||
|
|
||||||
let module = if let WorkItem::CopyPostLtoArtifacts(module) = work_item {
|
|
||||||
module
|
|
||||||
} else {
|
|
||||||
bug!("execute_copy_from_cache_work_item() called with wrong WorkItem kind.")
|
|
||||||
};
|
|
||||||
|
|
||||||
let incr_comp_session_dir = cgcx.incr_comp_session_dir
|
let incr_comp_session_dir = cgcx.incr_comp_session_dir
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -1459,9 +1447,9 @@ fn execute_copy_from_cache_work_item(cgcx: &CodegenContext,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(object.is_some(), config.emit_obj);
|
assert_eq!(object.is_some(), module_config.emit_obj);
|
||||||
assert_eq!(bytecode.is_some(), config.emit_bc);
|
assert_eq!(bytecode.is_some(), module_config.emit_bc);
|
||||||
assert_eq!(bytecode_compressed.is_some(), config.emit_bc_compressed);
|
assert_eq!(bytecode_compressed.is_some(), module_config.emit_bc_compressed);
|
||||||
|
|
||||||
Ok(WorkItemResult::Compiled(CompiledModule {
|
Ok(WorkItemResult::Compiled(CompiledModule {
|
||||||
name: module.name,
|
name: module.name,
|
||||||
|
@ -1473,22 +1461,17 @@ fn execute_copy_from_cache_work_item(cgcx: &CodegenContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_lto_work_item(cgcx: &CodegenContext,
|
fn execute_lto_work_item(cgcx: &CodegenContext,
|
||||||
work_item: WorkItem,
|
mut module: lto::LtoModuleCodegen,
|
||||||
|
module_config: &ModuleConfig,
|
||||||
timeline: &mut Timeline)
|
timeline: &mut Timeline)
|
||||||
-> Result<WorkItemResult, FatalError>
|
-> Result<WorkItemResult, FatalError>
|
||||||
{
|
{
|
||||||
let config = cgcx.config(work_item.module_kind());
|
let diag_handler = cgcx.create_diag_handler();
|
||||||
|
|
||||||
if let WorkItem::LTO(mut lto) = work_item {
|
unsafe {
|
||||||
let diag_handler = cgcx.create_diag_handler();
|
let module = module.optimize(cgcx, timeline)?;
|
||||||
|
let module = codegen(cgcx, &diag_handler, module, module_config, timeline)?;
|
||||||
unsafe {
|
Ok(WorkItemResult::Compiled(module))
|
||||||
let module = lto.optimize(cgcx, timeline)?;
|
|
||||||
let module = codegen(cgcx, &diag_handler, module, config, timeline)?;
|
|
||||||
Ok(WorkItemResult::Compiled(module))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
bug!("execute_lto_work_item() called with wrong WorkItem kind.")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue