heya, just curious. Is profile guided optimization a prerequisite for instrumenting LLVM to get coverage information for rustc code?
I found this comment which seems to say so
I think this is a different kind of instrumentation (although it records similar data)
although that comment looks like it does something that actually builds on PGO instrumentation (instead of GCOV)
Hi @mw ,
Have there been any discussion about making rustc insert the PGO instrumentation that @bossmc mention in the above comment?
there are two ways of adding this kind of instrumentation to LLVM IR:
Both use the same LLVM intrinsics but the first one relies on the compiler front-end (e.g. clang or rustc) to insert them, while the second one lets LLVM automatically insert them during the optimization passes.
Right now, rustc only supports the IR-level approach and (afaik) there are no immediate plans to support the front-end approach.
I don't know the details about this code coverage technique but from taking a quick look at the documentation, it only talks about front-end based instrumentation. not sure if it would also work with IR-level instrumentation.
the project this working group is about is focused on make PGO work though, code coverage would have to be a separate effort
Thanks, I understand. Would the working group be interested in looking into the feasibility in adding Front-end based instrumentation?
since I am currently the only member of this working "group" and I'll be going on parental leave next month, I don't think it's likely that this will happen. I personally would also like to avoid adding front-end based instrumentation if possible (it's another feature that needs to be maintained).
I would suggest trying to find out if IR-level instrumentation would also work here.
the corresponding clang commandline option is
(while FE-based instrumentation is enabled in clang via
Hi, I've been taking a look at getting a prototype going for the front-end based approach, but don't quite know my way around the
librustc_codegen_* architecture. Could anyone direct me towards where I could start emitting additional IR for e.g. a
The goal is to emit the LLVM intrinsics mentioned by @mw above, just a single counter for function entry as a starter. My current idea is to add something like
librustc_codegen_ssa and implement in
librustc_codegen_llvm. Then I can start injecting profiling intrinsics from existing functions like
codegen_statement in the SSA crate. Is that reasonable?
I did look at using the existing IR-level approach for this, but don't see any way to reconcile the counters inserted into the IR by LLVM with the counters referenced in the coverage mapping.
It's probably best if you re-post this message in the regular #t-compiler stream for better visibility.
I kind of expected to be around here: https://github.com/rust-lang/rust/blob/master/src/librustc_codegen_llvm/declare.rs#L133
but that only declares fns with the intention to define it
Maybe in the
You could add it to the
"start" block of a function, or maybe earlier
@gnzlbg ah, thanks. I think
codegen_mir(...) has the bulk of what I'm looking for. This should get me started on emitting the intrinsics.
I think @eddyb or @bjorn3 are familiar with that code, so it might make sense to ping them if you have questions
The birds eye is that
librustc_codegen_ssa is the "API" for generating code for a backend from MIR
and that the different backends (e.g.
librustc_codegen_clif, etc.) implement that API
You might get away touching only the LLVM backend (e.g. for the
"start" label, also insert some code coverage code)
but I can't tell you whether that's a good idea
Thanks, great info. I think I'll start with adding something like a new
librustc_codegen_ssa that I can implement for the LLVM backend. That'll let me insert counters generically from the "API" crate and the LLVM backend can look at these counters and associate it with coverage maps. I can start stripping it back later if it living in
librustc_codegen_ssa turns out to be a bad idea.
@Gary Tierney hey! so I did a bit of research last year about this for a contract that never happened, and I think I might remember a few things
my suggestions is not adding another trait but just methods to BuilderMethods or w/e
specifically for inserting runtime calls, at least
Hi @eddyb :)
Yep, that seems reasonable. I don't quite get the delineation between the various traits at the moment, I'd just found
DebugInfoBuilderMethods and started copying from that ;).
My intention at the moment is to have an API for inserting runtime calls in
BuilderMethods, et al. and leave it up to the LLVM backend to map source spans to profiling counters when it begins emitting a function or compiling a module.
FooBuilderMethods is a bit of an anti-pattern, and debuginfo is kinda special, so I'd avoid mimicking it
Noted, I'll just add some simple functions to
BuilderMethods for now.. Getting the backend agnostic code to start emitting the calls doesn't
seem too difficult.
I'll report any progress on https://github.com/rust-lang/rust/issues/34701.