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

Replace TimeLine LLVM profiling with the self profiler #58488

Merged
merged 1 commit into from
Mar 14, 2019
Merged
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
1 change: 0 additions & 1 deletion src/librustc/lib.rs
Original file line number Diff line number Diff line change
@@ -136,7 +136,6 @@ pub mod util {
pub mod common;
pub mod ppaux;
pub mod nodemap;
pub mod time_graph;
pub mod profiling;
pub mod bug;
}
31 changes: 23 additions & 8 deletions src/librustc/util/profiling.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::borrow::Cow;
use std::fs;
use std::io::{BufWriter, Write};
use std::mem;
@@ -20,12 +21,12 @@ pub enum ProfileCategory {
Other,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum ProfilerEvent {
QueryStart { query_name: &'static str, category: ProfileCategory, time: u64 },
QueryEnd { query_name: &'static str, category: ProfileCategory, time: u64 },
GenericActivityStart { category: ProfileCategory, time: u64 },
GenericActivityEnd { category: ProfileCategory, time: u64 },
GenericActivityStart { category: ProfileCategory, label: Cow<'static, str>, time: u64 },
GenericActivityEnd { category: ProfileCategory, label: Cow<'static, str>, time: u64 },
IncrementalLoadResultStart { query_name: &'static str, time: u64 },
IncrementalLoadResultEnd { query_name: &'static str, time: u64 },
QueryCacheHit { query_name: &'static str, category: ProfileCategory, time: u64 },
@@ -75,17 +76,27 @@ impl SelfProfiler {
}

#[inline]
pub fn start_activity(&mut self, category: ProfileCategory) {
pub fn start_activity(
&mut self,
category: ProfileCategory,
label: impl Into<Cow<'static, str>>,
) {
self.record(ProfilerEvent::GenericActivityStart {
category,
label: label.into(),
time: self.get_time_from_start(),
})
}

#[inline]
pub fn end_activity(&mut self, category: ProfileCategory) {
pub fn end_activity(
&mut self,
category: ProfileCategory,
label: impl Into<Cow<'static, str>>,
) {
self.record(ProfilerEvent::GenericActivityEnd {
category,
label: label.into(),
time: self.get_time_from_start(),
})
}
@@ -273,11 +284,12 @@ impl SelfProfiler {
nanos,
thread_id,
).unwrap(),
GenericActivityStart { category, time: _ } =>
GenericActivityStart { category, label, time: _ } =>
write!(file,
"{{
\"GenericActivityStart\": {{\
\"category\": \"{:?}\",\
\"label\": \"{}\",\
\"time\": {{\
\"secs\": {},\
\"nanos\": {}\
@@ -286,15 +298,17 @@ impl SelfProfiler {
}}\
}}",
category,
label,
secs,
nanos,
thread_id,
).unwrap(),
GenericActivityEnd { category, time: _ } =>
GenericActivityEnd { category, label, time: _ } =>
write!(file,
"{{\
\"GenericActivityEnd\": {{\
\"category\": \"{:?}\",\
\"label\": \"{}\",\
\"time\": {{\
\"secs\": {},\
\"nanos\": {}\
@@ -303,6 +317,7 @@ impl SelfProfiler {
}}\
}}",
category,
label,
secs,
nanos,
thread_id,
@@ -418,7 +433,7 @@ impl SelfProfiler {
secs,
nanos,
thread_id,
).unwrap()
).unwrap(),
}
}
}
268 changes: 0 additions & 268 deletions src/librustc/util/time_graph.rs

This file was deleted.

44 changes: 14 additions & 30 deletions src/librustc_codegen_llvm/back/lto.rs
Original file line number Diff line number Diff line change
@@ -3,7 +3,6 @@ use crate::back::write::{self, DiagnosticHandlers, with_llvm_pmb, save_temp_bitc
to_llvm_opt_settings};
use crate::llvm::archive_ro::ArchiveRO;
use crate::llvm::{self, True, False};
use crate::time_graph::Timeline;
use crate::{ModuleLlvm, LlvmCodegenBackend};
use rustc_codegen_ssa::back::symbol_export;
use rustc_codegen_ssa::back::write::{ModuleConfig, CodegenContext, FatLTOInput};
@@ -16,6 +15,7 @@ use rustc::hir::def_id::LOCAL_CRATE;
use rustc::middle::exported_symbols::SymbolExportLevel;
use rustc::session::config::{self, Lto};
use rustc::util::common::time_ext;
use rustc::util::profiling::ProfileCategory;
use rustc_data_structures::fx::FxHashMap;
use rustc_codegen_ssa::{ModuleCodegen, ModuleKind};

@@ -37,7 +37,6 @@ pub fn crate_type_allows_lto(crate_type: config::CrateType) -> bool {
}

fn prepare_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
timeline: &mut Timeline,
diag_handler: &Handler)
-> Result<(Vec<CString>, Vec<(SerializedModule<ModuleBuffer>, CString)>), FatalError>
{
@@ -68,7 +67,8 @@ fn prepare_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
.iter()
.filter_map(symbol_filter)
.collect::<Vec<CString>>();
timeline.record("whitelist");
let _timer = cgcx.profile_activity(ProfileCategory::Codegen,
"generate_symbol_white_list_for_thinlto");
info!("{} symbols to preserve in this crate", symbol_white_list.len());

// If we're performing LTO for the entire crate graph, then for each of our
@@ -97,6 +97,8 @@ fn prepare_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
}

for &(cnum, ref path) in cgcx.each_linked_rlib_for_lto.iter() {
let _timer = cgcx.profile_activity(ProfileCategory::Codegen,
format!("load: {}", path.display()));
let exported_symbols = cgcx.exported_symbols
.as_ref().expect("needs exported symbols for LTO");
symbol_white_list.extend(
@@ -121,7 +123,6 @@ fn prepare_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
let bc = SerializedModule::FromRlib(bc);
upstream_modules.push((bc, CString::new(id).unwrap()));
}
timeline.record(&format!("load: {}", path.display()));
}
}

@@ -132,12 +133,11 @@ fn prepare_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
/// for further optimization.
pub(crate) fn run_fat(cgcx: &CodegenContext<LlvmCodegenBackend>,
modules: Vec<FatLTOInput<LlvmCodegenBackend>>,
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
timeline: &mut Timeline)
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>)
-> Result<LtoModuleCodegen<LlvmCodegenBackend>, FatalError>
{
let diag_handler = cgcx.create_diag_handler();
let (symbol_white_list, upstream_modules) = prepare_lto(cgcx, timeline, &diag_handler)?;
let (symbol_white_list, upstream_modules) = prepare_lto(cgcx, &diag_handler)?;
let symbol_white_list = symbol_white_list.iter()
.map(|c| c.as_ptr())
.collect::<Vec<_>>();
@@ -148,7 +148,6 @@ pub(crate) fn run_fat(cgcx: &CodegenContext<LlvmCodegenBackend>,
cached_modules,
upstream_modules,
&symbol_white_list,
timeline,
)
}

@@ -157,12 +156,11 @@ pub(crate) fn run_fat(cgcx: &CodegenContext<LlvmCodegenBackend>,
/// can simply be copied over from the incr. comp. cache.
pub(crate) fn run_thin(cgcx: &CodegenContext<LlvmCodegenBackend>,
modules: Vec<(String, ThinBuffer)>,
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
timeline: &mut Timeline)
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>)
-> Result<(Vec<LtoModuleCodegen<LlvmCodegenBackend>>, Vec<WorkProduct>), FatalError>
{
let diag_handler = cgcx.create_diag_handler();
let (symbol_white_list, upstream_modules) = prepare_lto(cgcx, timeline, &diag_handler)?;
let (symbol_white_list, upstream_modules) = prepare_lto(cgcx, &diag_handler)?;
let symbol_white_list = symbol_white_list.iter()
.map(|c| c.as_ptr())
.collect::<Vec<_>>();
@@ -175,8 +173,7 @@ pub(crate) fn run_thin(cgcx: &CodegenContext<LlvmCodegenBackend>,
modules,
upstream_modules,
cached_modules,
&symbol_white_list,
timeline)
&symbol_white_list)
}

pub(crate) fn prepare_thin(
@@ -192,8 +189,7 @@ fn fat_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
mut modules: Vec<FatLTOInput<LlvmCodegenBackend>>,
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
mut serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
symbol_white_list: &[*const libc::c_char],
timeline: &mut Timeline)
symbol_white_list: &[*const libc::c_char])
-> Result<LtoModuleCodegen<LlvmCodegenBackend>, FatalError>
{
info!("going for a fat lto");
@@ -303,7 +299,6 @@ fn fat_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
write::llvm_err(&diag_handler, &msg)
})
})?;
timeline.record(&format!("link {:?}", name));
serialized_bitcode.push(bc_decoded);
}
drop(linker);
@@ -325,7 +320,6 @@ fn fat_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
}
save_temp_bitcode(&cgcx, &module, "lto.after-nounwind");
}
timeline.record("passes");
}

Ok(LtoModuleCodegen::Fat {
@@ -395,8 +389,7 @@ fn thin_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
modules: Vec<(String, ThinBuffer)>,
serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
symbol_white_list: &[*const libc::c_char],
timeline: &mut Timeline)
symbol_white_list: &[*const libc::c_char])
-> Result<(Vec<LtoModuleCodegen<LlvmCodegenBackend>>, Vec<WorkProduct>), FatalError>
{
unsafe {
@@ -422,7 +415,6 @@ fn thin_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
});
thin_buffers.push(buffer);
module_names.push(cname);
timeline.record(&name);
}

// FIXME: All upstream crates are deserialized internally in the
@@ -475,7 +467,6 @@ fn thin_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
})?;

info!("thin LTO data created");
timeline.record("data");

let import_map = if cgcx.incr_comp_session_dir.is_some() {
ThinLTOImports::from_thin_lto_data(data)
@@ -486,7 +477,6 @@ fn thin_lto(cgcx: &CodegenContext<LlvmCodegenBackend>,
ThinLTOImports::default()
};
info!("thin LTO import map loaded");
timeline.record("import-map-loaded");

let data = ThinData(data);

@@ -691,7 +681,6 @@ impl Drop for ThinBuffer {
pub unsafe fn optimize_thin_module(
thin_module: &mut ThinModule<LlvmCodegenBackend>,
cgcx: &CodegenContext<LlvmCodegenBackend>,
timeline: &mut Timeline
) -> Result<ModuleCodegen<ModuleLlvm>, FatalError> {
let diag_handler = cgcx.create_diag_handler();
let tm = (cgcx.tm_factory.0)().map_err(|e| {
@@ -738,9 +727,10 @@ pub unsafe fn optimize_thin_module(
// Like with "fat" LTO, get some better optimizations if landing pads
// are disabled by removing all landing pads.
if cgcx.no_landing_pads {
let _timer = cgcx.profile_activity(ProfileCategory::Codegen,
"LLVM_remove_landing_pads");
llvm::LLVMRustMarkAllFunctionsNounwind(llmod);
save_temp_bitcode(&cgcx, &module, "thin-lto-after-nounwind");
timeline.record("nounwind");
}

// Up next comes the per-module local analyses that we do for Thin LTO.
@@ -756,25 +746,21 @@ pub unsafe fn optimize_thin_module(
return Err(write::llvm_err(&diag_handler, msg))
}
save_temp_bitcode(cgcx, &module, "thin-lto-after-rename");
timeline.record("rename");
if !llvm::LLVMRustPrepareThinLTOResolveWeak(thin_module.shared.data.0, llmod) {
let msg = "failed to prepare thin LTO module";
return Err(write::llvm_err(&diag_handler, msg))
}
save_temp_bitcode(cgcx, &module, "thin-lto-after-resolve");
timeline.record("resolve");
if !llvm::LLVMRustPrepareThinLTOInternalize(thin_module.shared.data.0, llmod) {
let msg = "failed to prepare thin LTO module";
return Err(write::llvm_err(&diag_handler, msg))
}
save_temp_bitcode(cgcx, &module, "thin-lto-after-internalize");
timeline.record("internalize");
if !llvm::LLVMRustPrepareThinLTOImport(thin_module.shared.data.0, llmod) {
let msg = "failed to prepare thin LTO module";
return Err(write::llvm_err(&diag_handler, msg))
}
save_temp_bitcode(cgcx, &module, "thin-lto-after-import");
timeline.record("import");

// Ok now this is a bit unfortunate. This is also something you won't
// find upstream in LLVM's ThinLTO passes! This is a hack for now to
@@ -807,7 +793,6 @@ pub unsafe fn optimize_thin_module(
// fixed in LLVM.
llvm::LLVMRustThinLTOPatchDICompileUnit(llmod, cu1);
save_temp_bitcode(cgcx, &module, "thin-lto-after-patch");
timeline.record("patch");

// Alright now that we've done everything related to the ThinLTO
// analysis it's time to run some optimizations! Here we use the same
@@ -818,7 +803,6 @@ pub unsafe fn optimize_thin_module(
let config = cgcx.config(module.kind);
run_pass_manager(cgcx, &module, config, true);
save_temp_bitcode(cgcx, &module, "thin-lto-after-pm");
timeline.record("thin-done");
}
Ok(module)
}
58 changes: 31 additions & 27 deletions src/librustc_codegen_llvm/back/write.rs
Original file line number Diff line number Diff line change
@@ -3,7 +3,6 @@ use crate::back::bytecode::{self, RLIB_BYTECODE_EXTENSION};
use crate::back::lto::ThinBuffer;
use crate::base;
use crate::consts;
use crate::time_graph::Timeline;
use crate::llvm::{self, DiagnosticInfo, PassManager, SMDiagnostic};
use crate::llvm_util;
use crate::ModuleLlvm;
@@ -19,6 +18,7 @@ use rustc::session::Session;
use rustc::ty::TyCtxt;
use rustc_codegen_ssa::{ModuleCodegen, CompiledModule};
use rustc::util::common::time_ext;
use rustc::util::profiling::ProfileCategory;
use rustc_fs_util::{path_to_c_string, link_or_copy};
use rustc_data_structures::small_c_str::SmallCStr;
use errors::{Handler, FatalError};
@@ -305,8 +305,7 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void
pub(crate) unsafe fn optimize(cgcx: &CodegenContext<LlvmCodegenBackend>,
diag_handler: &Handler,
module: &ModuleCodegen<ModuleLlvm>,
config: &ModuleConfig,
timeline: &mut Timeline)
config: &ModuleConfig)
-> Result<(), FatalError>
{
let llmod = module.module_llvm.llmod();
@@ -415,19 +414,24 @@ pub(crate) unsafe fn optimize(cgcx: &CodegenContext<LlvmCodegenBackend>,
diag_handler.abort_if_errors();

// Finally, run the actual optimization passes
time_ext(config.time_passes,
None,
&format!("llvm function passes [{}]", module_name.unwrap()),
|| {
llvm::LLVMRustRunFunctionPassManager(fpm, llmod)
});
timeline.record("fpm");
time_ext(config.time_passes,
None,
&format!("llvm module passes [{}]", module_name.unwrap()),
|| {
llvm::LLVMRunPassManager(mpm, llmod)
});
{
let _timer = cgcx.profile_activity(ProfileCategory::Codegen, "LLVM_function_passes");
time_ext(config.time_passes,
None,
&format!("llvm function passes [{}]", module_name.unwrap()),
|| {
llvm::LLVMRustRunFunctionPassManager(fpm, llmod)
});
}
{
let _timer = cgcx.profile_activity(ProfileCategory::Codegen, "LLVM_module_passes");
time_ext(config.time_passes,
None,
&format!("llvm module passes [{}]", module_name.unwrap()),
|| {
llvm::LLVMRunPassManager(mpm, llmod)
});
}

// Deallocate managers that we're now done with
llvm::LLVMDisposePassManager(fpm);
@@ -439,11 +443,10 @@ pub(crate) unsafe fn optimize(cgcx: &CodegenContext<LlvmCodegenBackend>,
pub(crate) unsafe fn codegen(cgcx: &CodegenContext<LlvmCodegenBackend>,
diag_handler: &Handler,
module: ModuleCodegen<ModuleLlvm>,
config: &ModuleConfig,
timeline: &mut Timeline)
config: &ModuleConfig)
-> Result<CompiledModule, FatalError>
{
timeline.record("codegen");
let _timer = cgcx.profile_activity(ProfileCategory::Codegen, "codegen");
{
let llmod = module.module_llvm.llmod();
let llcx = &*module.module_llvm.llcx;
@@ -494,29 +497,30 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext<LlvmCodegenBackend>,


if write_bc || config.emit_bc_compressed || config.embed_bitcode {
let _timer = cgcx.profile_activity(ProfileCategory::Codegen, "LLVM_make_bitcode");
let thin = ThinBuffer::new(llmod);
let data = thin.data();
timeline.record("make-bc");

if write_bc {
let _timer = cgcx.profile_activity(ProfileCategory::Codegen, "LLVM_emit_bitcode");
if let Err(e) = fs::write(&bc_out, data) {
diag_handler.err(&format!("failed to write bytecode: {}", e));
}
timeline.record("write-bc");
}

if config.embed_bitcode {
let _timer = cgcx.profile_activity(ProfileCategory::Codegen, "LLVM_embed_bitcode");
embed_bitcode(cgcx, llcx, llmod, Some(data));
timeline.record("embed-bc");
}

if config.emit_bc_compressed {
let _timer = cgcx.profile_activity(ProfileCategory::Codegen,
"LLVM_compress_bitcode");
let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION);
let data = bytecode::encode(&module.name, data);
if let Err(e) = fs::write(&dst, data) {
diag_handler.err(&format!("failed to write bytecode: {}", e));
}
timeline.record("compress-bc");
}
} else if config.embed_bitcode_marker {
embed_bitcode(cgcx, llcx, llmod, None);
@@ -525,6 +529,7 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext<LlvmCodegenBackend>,
time_ext(config.time_passes, None, &format!("codegen passes [{}]", module_name.unwrap()),
|| -> Result<(), FatalError> {
if config.emit_ir {
let _timer = cgcx.profile_activity(ProfileCategory::Codegen, "LLVM_emit_ir");
let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name);
let out = path_to_c_string(&out);

@@ -563,10 +568,10 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext<LlvmCodegenBackend>,
llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr(), demangle_callback);
llvm::LLVMDisposePassManager(cpm);
});
timeline.record("ir");
}

if config.emit_asm || asm_to_obj {
let _timer = cgcx.profile_activity(ProfileCategory::Codegen, "LLVM_emit_asm");
let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);

// We can't use the same module for asm and binary output, because that triggers
@@ -581,19 +586,18 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext<LlvmCodegenBackend>,
write_output_file(diag_handler, tm, cpm, llmod, &path,
llvm::FileType::AssemblyFile)
})?;
timeline.record("asm");
}

if write_obj {
let _timer = cgcx.profile_activity(ProfileCategory::Codegen, "LLVM_emit_obj");
with_codegen(tm, llmod, config.no_builtins, |cpm| {
write_output_file(diag_handler, tm, cpm, llmod, &obj_out,
llvm::FileType::ObjectFile)
})?;
timeline.record("obj");
} else if asm_to_obj {
let _timer = cgcx.profile_activity(ProfileCategory::Codegen, "LLVM_asm_to_obj");
let assembly = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
run_assembler(cgcx, diag_handler, &assembly, &obj_out);
timeline.record("asm_to_obj");

if !config.emit_asm && !cgcx.save_temps {
drop(fs::remove_file(&assembly));
21 changes: 7 additions & 14 deletions src/librustc_codegen_llvm/lib.rs
Original file line number Diff line number Diff line change
@@ -53,7 +53,6 @@ use rustc_codegen_ssa::back::lto::{SerializedModule, LtoModuleCodegen, ThinModul
use rustc_codegen_ssa::CompiledModule;
use errors::{FatalError, Handler};
use rustc::dep_graph::WorkProduct;
use rustc::util::time_graph::Timeline;
use syntax_pos::symbol::InternedString;
use rustc::mir::mono::Stats;
pub use llvm_util::target_features;
@@ -66,7 +65,6 @@ use rustc::middle::cstore::{EncodedMetadata, MetadataLoader};
use rustc::session::Session;
use rustc::session::config::{OutputFilenames, OutputType, PrintRequest, OptLevel};
use rustc::ty::{self, TyCtxt};
use rustc::util::time_graph;
use rustc::util::profiling::ProfileCategory;
use rustc::util::common::ErrorReported;
use rustc_mir::monomorphize;
@@ -167,42 +165,37 @@ impl WriteBackendMethods for LlvmCodegenBackend {
cgcx: &CodegenContext<Self>,
modules: Vec<FatLTOInput<Self>>,
cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
timeline: &mut Timeline
) -> Result<LtoModuleCodegen<Self>, FatalError> {
back::lto::run_fat(cgcx, modules, cached_modules, timeline)
back::lto::run_fat(cgcx, modules, cached_modules)
}
fn run_thin_lto(
cgcx: &CodegenContext<Self>,
modules: Vec<(String, Self::ThinBuffer)>,
cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
timeline: &mut Timeline
) -> Result<(Vec<LtoModuleCodegen<Self>>, Vec<WorkProduct>), FatalError> {
back::lto::run_thin(cgcx, modules, cached_modules, timeline)
back::lto::run_thin(cgcx, modules, cached_modules)
}
unsafe fn optimize(
cgcx: &CodegenContext<Self>,
diag_handler: &Handler,
module: &ModuleCodegen<Self::Module>,
config: &ModuleConfig,
timeline: &mut Timeline
) -> Result<(), FatalError> {
back::write::optimize(cgcx, diag_handler, module, config, timeline)
back::write::optimize(cgcx, diag_handler, module, config)
}
unsafe fn optimize_thin(
cgcx: &CodegenContext<Self>,
thin: &mut ThinModule<Self>,
timeline: &mut Timeline
) -> Result<ModuleCodegen<Self::Module>, FatalError> {
back::lto::optimize_thin_module(thin, cgcx, timeline)
back::lto::optimize_thin_module(thin, cgcx)
}
unsafe fn codegen(
cgcx: &CodegenContext<Self>,
diag_handler: &Handler,
module: ModuleCodegen<Self::Module>,
config: &ModuleConfig,
timeline: &mut Timeline
) -> Result<CompiledModule, FatalError> {
back::write::codegen(cgcx, diag_handler, module, config, timeline)
back::write::codegen(cgcx, diag_handler, module, config)
}
fn prepare_thin(
module: ModuleCodegen<Self::Module>
@@ -336,12 +329,12 @@ impl CodegenBackend for LlvmCodegenBackend {

// Run the linker on any artifacts that resulted from the LLVM run.
// This should produce either a finished executable or library.
sess.profiler(|p| p.start_activity(ProfileCategory::Linking));
sess.profiler(|p| p.start_activity(ProfileCategory::Linking, "link_crate"));
time(sess, "linking", || {
back::link::link_binary(sess, &codegen_results,
outputs, &codegen_results.crate_name.as_str());
});
sess.profiler(|p| p.end_activity(ProfileCategory::Linking));
sess.profiler(|p| p.end_activity(ProfileCategory::Linking, "link_crate"));

// Now that we won't touch anything in the incremental compilation directory
// any more, we can finalize it (which involves renaming it)
5 changes: 1 addition & 4 deletions src/librustc_codegen_ssa/back/lto.rs
Original file line number Diff line number Diff line change
@@ -2,7 +2,6 @@ use super::write::CodegenContext;
use crate::traits::*;
use crate::ModuleCodegen;

use rustc::util::time_graph::Timeline;
use rustc_errors::FatalError;

use std::sync::Arc;
@@ -67,19 +66,17 @@ impl<B: WriteBackendMethods> LtoModuleCodegen<B> {
pub unsafe fn optimize(
&mut self,
cgcx: &CodegenContext<B>,
timeline: &mut Timeline
) -> Result<ModuleCodegen<B::Module>, FatalError> {
match *self {
LtoModuleCodegen::Fat { ref mut module, .. } => {
let module = module.take().unwrap();
{
let config = cgcx.config(module.kind);
B::run_lto_pass_manager(cgcx, &module, config, false);
timeline.record("fat-done");
}
Ok(module)
}
LtoModuleCodegen::Thin(ref mut thin) => B::optimize_thin(cgcx, thin, timeline),
LtoModuleCodegen::Thin(ref mut thin) => B::optimize_thin(cgcx, thin),
}
}

113 changes: 65 additions & 48 deletions src/librustc_codegen_ssa/back/write.rs
Original file line number Diff line number Diff line change
@@ -15,11 +15,10 @@ use rustc::middle::cstore::EncodedMetadata;
use rustc::session::config::{self, OutputFilenames, OutputType, Passes, Sanitizer, Lto};
use rustc::session::Session;
use rustc::util::nodemap::FxHashMap;
use rustc::util::time_graph::{self, TimeGraph, Timeline};
use rustc::hir::def_id::{CrateNum, LOCAL_CRATE};
use rustc::ty::TyCtxt;
use rustc::util::common::{time_depth, set_time_depth, print_time_passes_entry};
use rustc::util::profiling::SelfProfiler;
use rustc::util::profiling::{ProfileCategory, SelfProfiler};
use rustc_fs_util::link_or_copy;
use rustc_data_structures::svh::Svh;
use rustc_errors::{Handler, Level, DiagnosticBuilder, FatalError, DiagnosticId};
@@ -33,6 +32,7 @@ use jobserver::{Client, Acquired};
use parking_lot::Mutex as PlMutex;

use std::any::Any;
use std::borrow::Cow;
use std::fs;
use std::io;
use std::mem;
@@ -197,6 +197,40 @@ impl<B: WriteBackendMethods> Clone for TargetMachineFactory<B> {
}
}

pub struct ProfileGenericActivityTimer {
profiler: Option<Arc<PlMutex<SelfProfiler>>>,
category: ProfileCategory,
label: Cow<'static, str>,
}

impl ProfileGenericActivityTimer {
pub fn start(
profiler: Option<Arc<PlMutex<SelfProfiler>>>,
category: ProfileCategory,
label: Cow<'static, str>,
) -> ProfileGenericActivityTimer {
if let Some(profiler) = &profiler {
let mut p = profiler.lock();
p.start_activity(category, label.clone());
}

ProfileGenericActivityTimer {
profiler,
category,
label,
}
}
}

impl Drop for ProfileGenericActivityTimer {
fn drop(&mut self) {
if let Some(profiler) = &self.profiler {
let mut p = profiler.lock();
p.end_activity(self.category, self.label.clone());
}
}
}

/// Additional resources used by optimize_and_codegen (not module specific)
#[derive(Clone)]
pub struct CodegenContext<B: WriteBackendMethods> {
@@ -238,9 +272,6 @@ pub struct CodegenContext<B: WriteBackendMethods> {
pub cgu_reuse_tracker: CguReuseTracker,
// Channel back to the main control thread to send messages to
pub coordinator_send: Sender<Box<dyn Any + Send>>,
// A reference to the TimeGraph so we can register timings. None means that
// measuring is disabled.
pub time_graph: Option<TimeGraph>,
// The assembler command if no_integrated_as option is enabled, None otherwise
pub assembler_cmd: Option<Arc<AssemblerCommand>>
}
@@ -277,6 +308,14 @@ impl<B: WriteBackendMethods> CodegenContext<B> {
self.profiler_active(f)
}
}

pub fn profile_activity(
&self,
category: ProfileCategory,
label: impl Into<Cow<'static, str>>,
) -> ProfileGenericActivityTimer {
ProfileGenericActivityTimer::start(self.profiler.clone(), category, label.into())
}
}

fn generate_lto_work<B: ExtraBackendMethods>(
@@ -285,37 +324,36 @@ fn generate_lto_work<B: ExtraBackendMethods>(
needs_thin_lto: Vec<(String, B::ThinBuffer)>,
import_only_modules: Vec<(SerializedModule<B::ModuleBuffer>, WorkProduct)>
) -> Vec<(WorkItem<B>, u64)> {
let mut timeline = cgcx.time_graph.as_ref().map(|tg| {
tg.start(CODEGEN_WORKER_TIMELINE,
CODEGEN_WORK_PACKAGE_KIND,
"generate lto")
}).unwrap_or(Timeline::noop());
cgcx.profile(|p| p.start_activity(ProfileCategory::Linking, "codegen_run_lto"));

let (lto_modules, copy_jobs) = if !needs_fat_lto.is_empty() {
assert!(needs_thin_lto.is_empty());
let lto_module = B::run_fat_lto(
cgcx,
needs_fat_lto,
import_only_modules,
&mut timeline,
)
.unwrap_or_else(|e| e.raise());
(vec![lto_module], vec![])
} else {
assert!(needs_fat_lto.is_empty());
B::run_thin_lto(cgcx, needs_thin_lto, import_only_modules, &mut timeline)
B::run_thin_lto(cgcx, needs_thin_lto, import_only_modules)
.unwrap_or_else(|e| e.raise())
};

lto_modules.into_iter().map(|module| {
let result = lto_modules.into_iter().map(|module| {
let cost = module.cost();
(WorkItem::LTO(module), cost)
}).chain(copy_jobs.into_iter().map(|wp| {
(WorkItem::CopyPostLtoArtifacts(CachedModuleCodegen {
name: wp.cgu_name.clone(),
source: wp,
}), 0)
})).collect()
})).collect();

cgcx.profile(|p| p.end_activity(ProfileCategory::Linking, "codegen_run_lto"));

result
}

pub struct CompiledModules {
@@ -345,7 +383,6 @@ fn need_pre_lto_bitcode_for_incr_comp(sess: &Session) -> bool {
pub fn start_async_codegen<B: ExtraBackendMethods>(
backend: B,
tcx: TyCtxt<'_, '_, '_>,
time_graph: Option<TimeGraph>,
metadata: EncodedMetadata,
coordinator_receive: Receiver<Box<dyn Any + Send>>,
total_cgus: usize
@@ -469,7 +506,6 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
coordinator_receive,
total_cgus,
sess.jobserver.clone(),
time_graph.clone(),
Arc::new(modules_config),
Arc::new(metadata_config),
Arc::new(allocator_config));
@@ -483,7 +519,6 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
linker_info,
crate_info,

time_graph,
coordinator_send: tcx.tx_to_llvm_workers.lock().clone(),
codegen_worker_receive,
shared_emitter_main,
@@ -728,19 +763,18 @@ pub enum FatLTOInput<B: WriteBackendMethods> {
fn execute_work_item<B: ExtraBackendMethods>(
cgcx: &CodegenContext<B>,
work_item: WorkItem<B>,
timeline: &mut Timeline
) -> Result<WorkItemResult<B>, FatalError> {
let module_config = cgcx.config(work_item.module_kind());

match work_item {
WorkItem::Optimize(module) => {
execute_optimize_work_item(cgcx, module, module_config, timeline)
execute_optimize_work_item(cgcx, module, module_config)
}
WorkItem::CopyPostLtoArtifacts(module) => {
execute_copy_from_cache_work_item(cgcx, module, module_config, timeline)
execute_copy_from_cache_work_item(cgcx, module, module_config)
}
WorkItem::LTO(module) => {
execute_lto_work_item(cgcx, module, module_config, timeline)
execute_lto_work_item(cgcx, module, module_config)
}
}
}
@@ -756,12 +790,11 @@ fn execute_optimize_work_item<B: ExtraBackendMethods>(
cgcx: &CodegenContext<B>,
module: ModuleCodegen<B::Module>,
module_config: &ModuleConfig,
timeline: &mut Timeline
) -> Result<WorkItemResult<B>, FatalError> {
let diag_handler = cgcx.create_diag_handler();

unsafe {
B::optimize(cgcx, &diag_handler, &module, module_config, timeline)?;
B::optimize(cgcx, &diag_handler, &module, module_config)?;
}

// After we've done the initial round of optimizations we need to
@@ -818,7 +851,7 @@ fn execute_optimize_work_item<B: ExtraBackendMethods>(
Ok(match lto_type {
ComputedLtoType::No => {
let module = unsafe {
B::codegen(cgcx, &diag_handler, module, module_config, timeline)?
B::codegen(cgcx, &diag_handler, module, module_config)?
};
WorkItemResult::Compiled(module)
}
@@ -854,7 +887,6 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
cgcx: &CodegenContext<B>,
module: CachedModuleCodegen,
module_config: &ModuleConfig,
_: &mut Timeline
) -> Result<WorkItemResult<B>, FatalError> {
let incr_comp_session_dir = cgcx.incr_comp_session_dir
.as_ref()
@@ -916,13 +948,12 @@ fn execute_lto_work_item<B: ExtraBackendMethods>(
cgcx: &CodegenContext<B>,
mut module: lto::LtoModuleCodegen<B>,
module_config: &ModuleConfig,
timeline: &mut Timeline
) -> Result<WorkItemResult<B>, FatalError> {
let diag_handler = cgcx.create_diag_handler();

unsafe {
let module = module.optimize(cgcx, timeline)?;
let module = B::codegen(cgcx, &diag_handler, module, module_config, timeline)?;
let module = module.optimize(cgcx)?;
let module = B::codegen(cgcx, &diag_handler, module, module_config)?;
Ok(WorkItemResult::Compiled(module))
}
}
@@ -977,7 +1008,6 @@ fn start_executing_work<B: ExtraBackendMethods>(
coordinator_receive: Receiver<Box<dyn Any + Send>>,
total_cgus: usize,
jobserver: Client,
time_graph: Option<TimeGraph>,
modules_config: Arc<ModuleConfig>,
metadata_config: Arc<ModuleConfig>,
allocator_config: Arc<ModuleConfig>
@@ -1065,7 +1095,6 @@ fn start_executing_work<B: ExtraBackendMethods>(
cgu_reuse_tracker: sess.cgu_reuse_tracker.clone(),
coordinator_send,
diag_emitter: shared_emitter.clone(),
time_graph,
output_filenames: tcx.output_filenames(LOCAL_CRATE),
regular_module_config: modules_config,
metadata_module_config: metadata_config,
@@ -1570,12 +1599,6 @@ fn start_executing_work<B: ExtraBackendMethods>(
}

pub const CODEGEN_WORKER_ID: usize = ::std::usize::MAX;
pub const CODEGEN_WORKER_TIMELINE: time_graph::TimelineId =
time_graph::TimelineId(CODEGEN_WORKER_ID);
pub const CODEGEN_WORK_PACKAGE_KIND: time_graph::WorkPackageKind =
time_graph::WorkPackageKind(&["#DE9597", "#FED1D3", "#FDC5C7", "#B46668", "#88494B"]);
const LLVM_WORK_PACKAGE_KIND: time_graph::WorkPackageKind =
time_graph::WorkPackageKind(&["#7DB67A", "#C6EEC4", "#ACDAAA", "#579354", "#3E6F3C"]);

fn spawn_work<B: ExtraBackendMethods>(
cgcx: CodegenContext<B>,
@@ -1625,13 +1648,12 @@ fn spawn_work<B: ExtraBackendMethods>(
// as a diagnostic was already sent off to the main thread - just
// surface that there was an error in this worker.
bomb.result = {
let timeline = cgcx.time_graph.as_ref().map(|tg| {
tg.start(time_graph::TimelineId(cgcx.worker),
LLVM_WORK_PACKAGE_KIND,
&work.name())
});
let mut timeline = timeline.unwrap_or(Timeline::noop());
execute_work_item(&cgcx, work, &mut timeline).ok()
let label = work.name();
cgcx.profile(|p| p.start_activity(ProfileCategory::Codegen, label.clone()));
let result = execute_work_item(&cgcx, work).ok();
cgcx.profile(|p| p.end_activity(ProfileCategory::Codegen, label));

result
};
});
}
@@ -1785,7 +1807,6 @@ pub struct OngoingCodegen<B: ExtraBackendMethods> {
pub windows_subsystem: Option<String>,
pub linker_info: LinkerInfo,
pub crate_info: CrateInfo,
pub time_graph: Option<TimeGraph>,
pub coordinator_send: Sender<Box<dyn Any + Send>>,
pub codegen_worker_receive: Receiver<Message<B>>,
pub shared_emitter_main: SharedEmitterMain,
@@ -1814,10 +1835,6 @@ impl<B: ExtraBackendMethods> OngoingCodegen<B> {

sess.abort_if_errors();

if let Some(time_graph) = self.time_graph {
time_graph.dump(&format!("{}-timings", self.crate_name));
}

let work_products =
copy_all_cgu_workproducts_to_incr_comp_cache_dir(sess,
&compiled_modules);
27 changes: 6 additions & 21 deletions src/librustc_codegen_ssa/base.rs
Original file line number Diff line number Diff line change
@@ -29,7 +29,6 @@ use rustc::util::profiling::ProfileCategory;
use rustc::session::config::{self, EntryFnType, Lto};
use rustc::session::Session;
use rustc_mir::monomorphize::item::DefPathBasedNames;
use rustc::util::time_graph;
use rustc_mir::monomorphize::Instance;
use rustc_mir::monomorphize::partitioning::{CodegenUnit, CodegenUnitExt};
use rustc::util::nodemap::FxHashMap;
@@ -528,11 +527,6 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
}

pub const CODEGEN_WORKER_ID: usize = ::std::usize::MAX;
pub const CODEGEN_WORKER_TIMELINE: time_graph::TimelineId =
time_graph::TimelineId(CODEGEN_WORKER_ID);
pub const CODEGEN_WORK_PACKAGE_KIND: time_graph::WorkPackageKind =
time_graph::WorkPackageKind(&["#DE9597", "#FED1D3", "#FDC5C7", "#B46668", "#88494B"]);


pub fn codegen_crate<B: ExtraBackendMethods>(
backend: B,
@@ -545,7 +539,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx);

// Codegen the metadata.
tcx.sess.profiler(|p| p.start_activity(ProfileCategory::Codegen));
tcx.sess.profiler(|p| p.start_activity(ProfileCategory::Codegen, "codegen crate metadata"));

let metadata_cgu_name = cgu_name_builder.build_cgu_name(LOCAL_CRATE,
&["crate"],
@@ -555,27 +549,20 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
let metadata = time(tcx.sess, "write metadata", || {
backend.write_metadata(tcx, &mut metadata_llvm_module)
});
tcx.sess.profiler(|p| p.end_activity(ProfileCategory::Codegen));
tcx.sess.profiler(|p| p.end_activity(ProfileCategory::Codegen, "codegen crate metadata"));

let metadata_module = ModuleCodegen {
name: metadata_cgu_name,
module_llvm: metadata_llvm_module,
kind: ModuleKind::Metadata,
};

let time_graph = if tcx.sess.opts.debugging_opts.codegen_time_graph {
Some(time_graph::TimeGraph::new())
} else {
None
};

// Skip crate items and just output metadata in -Z no-codegen mode.
if tcx.sess.opts.debugging_opts.no_codegen ||
!tcx.sess.opts.output_types.should_codegen() {
let ongoing_codegen = start_async_codegen(
backend,
tcx,
time_graph,
metadata,
rx,
1);
@@ -609,7 +596,6 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
let ongoing_codegen = start_async_codegen(
backend.clone(),
tcx,
time_graph.clone(),
metadata,
rx,
codegen_units.len());
@@ -676,15 +662,14 @@ pub fn codegen_crate<B: ExtraBackendMethods>(

match cgu_reuse {
CguReuse::No => {
let _timing_guard = time_graph.as_ref().map(|time_graph| {
time_graph.start(CODEGEN_WORKER_TIMELINE,
CODEGEN_WORK_PACKAGE_KIND,
&format!("codegen {}", cgu.name()))
});
tcx.sess.profiler(|p| p.start_activity(ProfileCategory::Codegen,
format!("codegen {}", cgu.name())));
let start_time = Instant::now();
let stats = backend.compile_codegen_unit(tcx, *cgu.name());
all_stats.extend(stats);
total_codegen_time += start_time.elapsed();
tcx.sess.profiler(|p| p.end_activity(ProfileCategory::Codegen,
format!("codegen {}", cgu.name())));
false
}
CguReuse::PreLto => {
6 changes: 0 additions & 6 deletions src/librustc_codegen_ssa/traits/write.rs
Original file line number Diff line number Diff line change
@@ -3,7 +3,6 @@ use crate::back::write::{CodegenContext, ModuleConfig, FatLTOInput};
use crate::{CompiledModule, ModuleCodegen};

use rustc::dep_graph::WorkProduct;
use rustc::util::time_graph::Timeline;
use rustc_errors::{FatalError, Handler};

pub trait WriteBackendMethods: 'static + Sized + Clone {
@@ -20,7 +19,6 @@ pub trait WriteBackendMethods: 'static + Sized + Clone {
cgcx: &CodegenContext<Self>,
modules: Vec<FatLTOInput<Self>>,
cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
timeline: &mut Timeline,
) -> Result<LtoModuleCodegen<Self>, FatalError>;
/// Performs thin LTO by performing necessary global analysis and returning two
/// lists, one of the modules that need optimization and another for modules that
@@ -29,27 +27,23 @@ pub trait WriteBackendMethods: 'static + Sized + Clone {
cgcx: &CodegenContext<Self>,
modules: Vec<(String, Self::ThinBuffer)>,
cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
timeline: &mut Timeline,
) -> Result<(Vec<LtoModuleCodegen<Self>>, Vec<WorkProduct>), FatalError>;
fn print_pass_timings(&self);
unsafe fn optimize(
cgcx: &CodegenContext<Self>,
diag_handler: &Handler,
module: &ModuleCodegen<Self::Module>,
config: &ModuleConfig,
timeline: &mut Timeline,
) -> Result<(), FatalError>;
unsafe fn optimize_thin(
cgcx: &CodegenContext<Self>,
thin: &mut ThinModule<Self>,
timeline: &mut Timeline,
) -> Result<ModuleCodegen<Self::Module>, FatalError>;
unsafe fn codegen(
cgcx: &CodegenContext<Self>,
diag_handler: &Handler,
module: ModuleCodegen<Self::Module>,
config: &ModuleConfig,
timeline: &mut Timeline,
) -> Result<CompiledModule, FatalError>;
fn prepare_thin(
module: ModuleCodegen<Self::Module>
12 changes: 6 additions & 6 deletions src/librustc_interface/passes.rs
Original file line number Diff line number Diff line change
@@ -67,15 +67,15 @@ pub fn parse<'a>(sess: &'a Session, input: &Input) -> PResult<'a, ast::Crate> {
.set_continue_after_error(sess.opts.debugging_opts.continue_parse_after_error);
hygiene::set_default_edition(sess.edition());

sess.profiler(|p| p.start_activity(ProfileCategory::Parsing));
sess.profiler(|p| p.start_activity(ProfileCategory::Parsing, "parsing"));
let krate = time(sess, "parsing", || match *input {
Input::File(ref file) => parse::parse_crate_from_file(file, &sess.parse_sess),
Input::Str {
ref input,
ref name,
} => parse::parse_crate_from_source_str(name.clone(), input.clone(), &sess.parse_sess),
})?;
sess.profiler(|p| p.end_activity(ProfileCategory::Parsing));
sess.profiler(|p| p.end_activity(ProfileCategory::Parsing, "parsing"));

sess.diagnostic().set_continue_after_error(true);

@@ -374,7 +374,7 @@ fn configure_and_expand_inner<'a>(
syntax_ext::register_builtins(&mut resolver, plugin_info.syntax_exts);

// Expand all macros
sess.profiler(|p| p.start_activity(ProfileCategory::Expansion));
sess.profiler(|p| p.start_activity(ProfileCategory::Expansion, "macro expansion"));
krate = time(sess, "expansion", || {
// Windows dlls do not have rpaths, so they don't know how to find their
// dependencies. It's up to us to tell the system where to find all the
@@ -449,7 +449,7 @@ fn configure_and_expand_inner<'a>(
}
krate
});
sess.profiler(|p| p.end_activity(ProfileCategory::Expansion));
sess.profiler(|p| p.end_activity(ProfileCategory::Expansion, "macro expansion"));

time(sess, "maybe building test harness", || {
syntax::test::modify_for_testing(
@@ -1018,9 +1018,9 @@ pub fn start_codegen<'tcx>(
::rustc::middle::dependency_format::calculate(tcx)
});

tcx.sess.profiler(|p| p.start_activity(ProfileCategory::Codegen));
tcx.sess.profiler(|p| p.start_activity(ProfileCategory::Codegen, "codegen crate"));
let codegen = time(tcx.sess, "codegen", move || codegen_backend.codegen_crate(tcx, rx));
tcx.sess.profiler(|p| p.end_activity(ProfileCategory::Codegen));
tcx.sess.profiler(|p| p.end_activity(ProfileCategory::Codegen, "codegen crate"));

if log_enabled!(::log::Level::Info) {
println!("Post-codegen");
4 changes: 2 additions & 2 deletions src/librustc_typeck/lib.rs
Original file line number Diff line number Diff line change
@@ -317,7 +317,7 @@ pub fn provide(providers: &mut Providers<'_>) {
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
-> Result<(), ErrorReported>
{
tcx.sess.profiler(|p| p.start_activity(ProfileCategory::TypeChecking));
tcx.sess.profiler(|p| p.start_activity(ProfileCategory::TypeChecking, "type-check crate"));

// this ensures that later parts of type checking can assume that items
// have valid types and not error
@@ -368,7 +368,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
check_unused::check_crate(tcx);
check_for_entry_fn(tcx);

tcx.sess.profiler(|p| p.end_activity(ProfileCategory::TypeChecking));
tcx.sess.profiler(|p| p.end_activity(ProfileCategory::TypeChecking, "type-check crate"));

if tcx.sess.err_count() == 0 {
Ok(())