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

rustc_llvm: Add a -Z print-llvm-stats option to expose LLVM statistics. #104000

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
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
4 changes: 4 additions & 0 deletions compiler/rustc_codegen_gcc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,10 @@ impl WriteBackendMethods for GccCodegenBackend {
unimplemented!();
}

fn print_statistics(&self) {
unimplemented!()
}

unsafe fn optimize(_cgcx: &CodegenContext<Self>, _diag_handler: &Handler, module: &ModuleCodegen<Self::Module>, config: &ModuleConfig) -> Result<(), FatalError> {
module.module_llvm.context.set_optimization_level(to_gcc_opt_level(config.opt_level));
Ok(())
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_codegen_llvm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,11 @@ impl WriteBackendMethods for LlvmCodegenBackend {
llvm::LLVMRustPrintPassTimings();
}
}
fn print_statistics(&self) {
unsafe {
llvm::LLVMRustPrintStatistics();
}
}
fn run_link(
cgcx: &CodegenContext<Self>,
diag_handler: &Handler,
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_codegen_llvm/src/llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1826,6 +1826,9 @@ extern "C" {
/// Print the pass timings since static dtors aren't picking them up.
pub fn LLVMRustPrintPassTimings();

/// Print the statistics since static dtors aren't picking them up.
pub fn LLVMRustPrintStatistics();

pub fn LLVMStructCreateNamed(C: &Context, Name: *const c_char) -> &Type;

pub fn LLVMStructSetBody<'a>(
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_codegen_llvm/src/llvm_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ unsafe fn configure_llvm(sess: &Session) {
// Use non-zero `import-instr-limit` multiplier for cold callsites.
add("-import-cold-multiplier=0.1", false);

if sess.print_llvm_stats() {
add("-stats", false);
}

for arg in sess_args {
add(&(*arg), true);
}
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_codegen_ssa/src/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1897,6 +1897,10 @@ impl<B: ExtraBackendMethods> OngoingCodegen<B> {
self.backend.print_pass_timings()
}

if sess.print_llvm_stats() {
self.backend.print_statistics()
}

(
CodegenResults {
metadata: self.metadata,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_ssa/src/traits/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ pub trait WriteBackendMethods: 'static + Sized + Clone {
cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
) -> Result<(Vec<LtoModuleCodegen<Self>>, Vec<WorkProduct>), FatalError>;
fn print_pass_timings(&self);
fn print_statistics(&self);
unsafe fn optimize(
cgcx: &CodegenContext<Self>,
diag_handler: &Handler,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_interface/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,7 @@ fn test_unstable_options_tracking_hash() {
// `pre_link_arg` is omitted because it just forwards to `pre_link_args`.
untracked!(pre_link_args, vec![String::from("abc"), String::from("def")]);
untracked!(print_llvm_passes, true);
untracked!(print_llvm_stats, true);
untracked!(print_mono_items, Some(String::from("abc")));
untracked!(print_type_sizes, true);
untracked!(proc_macro_backtrace, true);
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "LLVMWrapper.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DiagnosticHandler.h"
#include "llvm/IR/DiagnosticInfo.h"
Expand Down Expand Up @@ -113,6 +114,11 @@ extern "C" void LLVMRustPrintPassTimings() {
TimerGroup::printAll(OS);
}

extern "C" void LLVMRustPrintStatistics() {
raw_fd_ostream OS(2, false); // stderr.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn’t it be better to return a string from this function and leave it up to rustc to actually print? Sure it’ll allocate the stats into a memory buffer, but that seems like a negligible cost.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same is true for LLVMRustPrintPassTimings I guess, but that's preexisting.

What would be the benefit? Better reusability?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, one thing I’m thinking of is that just dumping stuff onto stderr is not a great experience with output formats like JSON. It just seems that leaving outputting to rustc is just gonna leave less room for things to go very wrong in general. While I’m not anticipating this getting fixed anytime soon, but having this just output a string seems like a meaningful intermediate step.

But also, looking at that magic number makes my eyeballs really itchy, even despite the comment :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nagisa I'm not opposed to doing it that way (allocating into a string). Do you want me to change LLVMRustPrintPassTimings too?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would be quite awesome!

llvm::PrintStatistics(OS);
}

extern "C" LLVMValueRef LLVMRustGetNamedValue(LLVMModuleRef M, const char *Name,
size_t NameLen) {
return wrap(unwrap(M)->getNamedValue(StringRef(Name, NameLen)));
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_session/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1465,6 +1465,9 @@ options! {
#[rustc_lint_opt_deny_field_access("use `Session::print_llvm_passes` instead of this field")]
print_llvm_passes: bool = (false, parse_bool, [UNTRACKED],
"print the LLVM optimization passes being run (default: no)"),
#[rustc_lint_opt_deny_field_access("use `Session::print_llvm_stats` instead of this field")]
print_llvm_stats: bool = (false, parse_bool, [UNTRACKED],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe call it print_codegen_stats since it's forwarded to all ssa codegen backends

"print LLVM statistics (default: no)"),
print_mono_items: Option<String> = (None, parse_opt_string, [UNTRACKED],
"print the result of the monomorphization collection pass"),
print_type_sizes: bool = (false, parse_bool, [UNTRACKED],
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_session/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -959,6 +959,10 @@ impl Session {
self.opts.unstable_opts.instrument_mcount
}

pub fn print_llvm_stats(&self) -> bool {
self.opts.unstable_opts.print_llvm_stats
}

pub fn time_passes(&self) -> bool {
self.opts.unstable_opts.time_passes
}
Expand Down