Add timers to compiler and linker

This commit is contained in:
khyperia 2020-09-28 14:51:04 +02:00
parent df3da15f0b
commit 8f1d69848f
3 changed files with 34 additions and 3 deletions

View File

@ -118,7 +118,12 @@ fn extract_literal_u32(op: &rspirv::dr::Operand) -> u32 {
}
}
pub fn link(inputs: &mut [&mut rspirv::dr::Module], opts: &Options) -> Result<rspirv::dr::Module> {
pub fn link<T>(
inputs: &mut [&mut rspirv::dr::Module],
opts: &Options,
timer: impl Fn(&'static str) -> T,
) -> Result<rspirv::dr::Module> {
let merge_timer = timer("link_merge");
// shift all the ids
let mut bound = inputs[0].header.as_ref().unwrap().bound - 1;
let version = inputs[0].header.as_ref().unwrap().version();
@ -139,38 +144,56 @@ pub fn link(inputs: &mut [&mut rspirv::dr::Module], opts: &Options) -> Result<rs
}
let mut output = loader.module();
drop(merge_timer);
let find_pairs_timer = timer("link_find_pairs");
// find import / export pairs
let defs = DefAnalyzer::new(&output);
let info = import_export_link::find_import_export_pairs(&output, &defs)?;
// ensure import / export pairs have matching types and defintions
let matching_pairs = info.ensure_matching_import_export_pairs(&defs)?;
drop(find_pairs_timer);
let remove_duplicates_timer = timer("link_remove_duplicates");
// remove duplicates (https://github.com/KhronosGroup/SPIRV-Tools/blob/e7866de4b1dc2a7e8672867caeb0bdca49f458d3/source/opt/remove_duplicates_pass.cpp)
duplicates::remove_duplicate_capablities(&mut output);
duplicates::remove_duplicate_ext_inst_imports(&mut output);
duplicates::remove_duplicate_types(&mut output);
// jb-todo: strip identical OpDecoration / OpDecorationGroups
drop(remove_duplicates_timer);
let import_kill_annotations_and_debug_timer = timer("link_import_kill_annotations_and_debug");
// remove names and decorations of import variables / functions https://github.com/KhronosGroup/SPIRV-Tools/blob/8a0ebd40f86d1f18ad42ea96c6ac53915076c3c7/source/opt/ir_context.cpp#L404
import_export_link::import_kill_annotations_and_debug(&mut output, &info);
drop(import_kill_annotations_and_debug_timer);
let replace_matching_pairs_timer = timer("link_replace_matching_pairs");
// rematch import variables and functions to export variables / functions https://github.com/KhronosGroup/SPIRV-Tools/blob/8a0ebd40f86d1f18ad42ea96c6ac53915076c3c7/source/opt/ir_context.cpp#L255
for pair in matching_pairs {
replace_all_uses_with(&mut output, pair.import.id, pair.export.id);
}
drop(replace_matching_pairs_timer);
let kill_linkage_instructions_timer = timer("link_kill_linkage_instructions");
// remove linkage specific instructions
import_export_link::kill_linkage_instructions(&matching_pairs, &mut output, &opts);
drop(kill_linkage_instructions_timer);
let remove_zombies_timer = timer("link_remove_zombies");
zombies::remove_zombies(&mut output);
drop(remove_zombies_timer);
let block_ordering_pass_timer = timer("link_block_ordering_pass");
for func in &mut output.functions {
simple_passes::block_ordering_pass(func);
}
drop(block_ordering_pass_timer);
let sort_globals_timer = timer("link_sort_globals");
simple_passes::sort_globals(&mut output);
drop(sort_globals_timer);
let compact_ids_timer = timer("link_compact_ids");
let bound = if env::var("NO_COMPACT_IDS").is_ok() {
// It is sometimes useful to not rewrite IDs. For example, if using PRINT_ALL_ZOMBIE, it's useful to be able to
// inspect the module and have the same IDs as the ones that were printed in the zombie pass.
@ -179,6 +202,7 @@ pub fn link(inputs: &mut [&mut rspirv::dr::Module], opts: &Options) -> Result<rs
// compact the ids https://github.com/KhronosGroup/SPIRV-Tools/blob/e02f178a716b0c3c803ce31b9df4088596537872/source/opt/compact_ids_pass.cpp#L43
simple_passes::compact_ids(&mut output)
};
drop(compact_ids_timer);
let mut header = rspirv::dr::ModuleHeader::new(bound);
header.set_version(version.0, version.1);
output.header = Some(header);

View File

@ -270,12 +270,14 @@ impl CodegenBackend for SpirvCodegenBackend {
return Ok(());
}
let timer = sess.prof.generic_activity("link_crate");
link::link(
sess,
&codegen_results,
outputs,
&codegen_results.crate_name.as_str(),
);
drop(timer);
rustc_incremental::finalize_session_directory(sess, codegen_results.crate_hash);
@ -445,6 +447,10 @@ impl ExtraBackendMethods for SpirvCodegenBackend {
tcx: TyCtxt<'_>,
cgu_name: Symbol,
) -> (ModuleCodegen<Self::Module>, u64) {
let _timer = tcx
.prof
.generic_activity_with_arg("codegen_module", cgu_name.to_string());
// TODO: Do dep_graph stuff
let cgu = tcx.codegen_unit(cgu_name);

View File

@ -116,7 +116,7 @@ fn link_exe(
codegen_results,
);
do_link(&objects, &rlibs, out_filename);
do_link(sess, &objects, &rlibs, out_filename);
if env::var("SPIRV_OPT").is_ok() {
do_spirv_opt(out_filename);
@ -279,7 +279,7 @@ pub fn read_metadata(rlib: &Path) -> MetadataRef {
/// This is the actual guts of linking: the rest of the link-related functions are just digging through rustc's
/// shenanigans to collect all the object files we need to link.
fn do_link(objects: &[PathBuf], rlibs: &[PathBuf], out_filename: &Path) {
fn do_link(sess: &Session, objects: &[PathBuf], rlibs: &[PathBuf], out_filename: &Path) {
let mut modules = Vec::new();
// `objects` are the plain obj files we need to link - usually produced by the final crate.
for obj in objects {
@ -323,6 +323,7 @@ fn do_link(objects: &[PathBuf], rlibs: &[PathBuf], out_filename: &Path) {
lib: false,
partial: false,
},
|name| sess.prof.generic_activity(name),
) {
Ok(result) => result,
Err(err) => {