Skip to content

Commit 9624c30

Browse files
committed
Generate MIR pass names for profiling on the fly and pass the body DefId as argument
1 parent f742d88 commit 9624c30

File tree

2 files changed

+47
-4
lines changed

2 files changed

+47
-4
lines changed

compiler/rustc_middle/src/mir/mod.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use rustc_target::abi::{FieldIdx, Size, VariantIdx};
2525

2626
use polonius_engine::Atom;
2727
pub use rustc_ast::Mutability;
28+
use rustc_data_structures::fx::FxHashMap;
2829
use rustc_data_structures::fx::FxHashSet;
2930
use rustc_data_structures::graph::dominators::Dominators;
3031
use rustc_index::{Idx, IndexSlice, IndexVec};
@@ -35,6 +36,8 @@ use rustc_span::{Span, DUMMY_SP};
3536
use either::Either;
3637

3738
use std::borrow::Cow;
39+
use std::cell::RefCell;
40+
use std::collections::hash_map::Entry;
3841
use std::fmt::{self, Debug, Display, Formatter, Write};
3942
use std::ops::{Index, IndexMut};
4043
use std::{iter, mem};
@@ -97,6 +100,36 @@ impl<'tcx> HasLocalDecls<'tcx> for Body<'tcx> {
97100
}
98101
}
99102

103+
thread_local! {
104+
static PASS_NAMES: RefCell<FxHashMap<&'static str, &'static str>> = {
105+
RefCell::new(FxHashMap::default())
106+
};
107+
}
108+
109+
/// Converts a MIR pass name into a snake case form to match the profiling naming style.
110+
fn to_profiler_name(type_name: &'static str) -> &'static str {
111+
PASS_NAMES.with(|names| match names.borrow_mut().entry(type_name) {
112+
Entry::Occupied(e) => *e.get(),
113+
Entry::Vacant(e) => {
114+
let snake_case: String = type_name
115+
.chars()
116+
.flat_map(|c| {
117+
if c.is_ascii_uppercase() {
118+
vec!['_', c.to_ascii_lowercase()]
119+
} else if c == '-' {
120+
vec!['_']
121+
} else {
122+
vec![c]
123+
}
124+
})
125+
.collect();
126+
let result = &*String::leak(format!("mir_pass{}", snake_case));
127+
e.insert(result);
128+
result
129+
}
130+
})
131+
}
132+
100133
/// A streamlined trait that you can implement to create a pass; the
101134
/// pass will be named after the type, and it will consist of a main
102135
/// loop that goes over each available MIR and applies `run_pass`.
@@ -106,6 +139,10 @@ pub trait MirPass<'tcx> {
106139
if let Some((_, tail)) = name.rsplit_once(':') { tail } else { name }
107140
}
108141

142+
fn profiler_name(&self) -> &'static str {
143+
to_profiler_name(self.name())
144+
}
145+
109146
/// Returns `true` if this pass is enabled with the current combination of compiler flags.
110147
fn is_enabled(&self, _sess: &Session) -> bool {
111148
true

compiler/rustc_mir_transform/src/pass_manager.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ fn run_passes_inner<'tcx>(
9494
let overridden_passes = &tcx.sess.opts.unstable_opts.mir_enable_passes;
9595
trace!(?overridden_passes);
9696

97+
let prof_arg = tcx.sess.prof.enabled().then(|| format!("{:?}", body.source.def_id()));
98+
9799
if !body.should_skip() {
98100
for pass in passes {
99101
let name = pass.name();
@@ -121,10 +123,14 @@ fn run_passes_inner<'tcx>(
121123
validate_body(tcx, body, format!("before pass {name}"));
122124
}
123125

124-
tcx.sess
125-
.prof
126-
.generic_activity_with_arg("mir_pass", name)
127-
.run(|| pass.run_pass(tcx, body));
126+
if let Some(prof_arg) = &prof_arg {
127+
tcx.sess
128+
.prof
129+
.generic_activity_with_arg(pass.profiler_name(), &**prof_arg)
130+
.run(|| pass.run_pass(tcx, body));
131+
} else {
132+
pass.run_pass(tcx, body);
133+
}
128134

129135
if dump_enabled {
130136
dump_mir_for_pass(tcx, body, &name, true);

0 commit comments

Comments
 (0)