Skip to content

Commit f9ee161

Browse files
authored
Merge pull request #37136 from NHDaly/nhd-emit-per-method-llvm_timings
Add ccalls to enable dumping LLVM_OPT time per method instance.
2 parents ebc63b9 + 1178f57 commit f9ee161

File tree

2 files changed

+78
-0
lines changed

2 files changed

+78
-0
lines changed

src/codegen.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,13 @@ typedef Instruction TerminatorInst;
9595
#include "processor.h"
9696
#include "julia_assert.h"
9797

98+
JL_STREAM *dump_emitted_mi_name_stream = NULL;
99+
extern "C" JL_DLLEXPORT
100+
void jl_dump_emitted_mi_name(void *s)
101+
{
102+
dump_emitted_mi_name_stream = (JL_STREAM*)s;
103+
}
104+
98105
extern "C" {
99106

100107
#include "builtin_proto.h"
@@ -7157,6 +7164,16 @@ jl_compile_result_t jl_emit_code(
71577164
"functions compiled with custom codegen params must not be cached");
71587165
JL_TRY {
71597166
std::tie(m, decls) = emit_function(li, src, jlrettype, params);
7167+
if (dump_emitted_mi_name_stream != NULL) {
7168+
jl_printf(dump_emitted_mi_name_stream, "%s\t", decls.specFunctionObject.c_str());
7169+
// NOTE: We print the Type Tuple without surrounding quotes, because the quotes
7170+
// break CSV parsing if there are any internal quotes in the Type name (e.g. in
7171+
// Symbol("...")). The \t delineator should be enough to ensure whitespace is
7172+
// handled correctly. (And we don't need to worry about any tabs in the printed
7173+
// string, because tabs are printed as "\t" by `show`.)
7174+
jl_static_show(dump_emitted_mi_name_stream, li->specTypes);
7175+
jl_printf(dump_emitted_mi_name_stream, "\n");
7176+
}
71607177
}
71617178
JL_CATCH {
71627179
// Something failed! This is very, very bad.

src/jitlayers.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ void jl_dump_compiles(void *s)
3838
{
3939
dump_compiles_stream = (JL_STREAM*)s;
4040
}
41+
JL_STREAM *dump_llvm_opt_stream = NULL;
42+
extern "C" JL_DLLEXPORT
43+
void jl_dump_llvm_opt(void *s)
44+
{
45+
dump_llvm_opt_stream = (JL_STREAM*)s;
46+
}
4147

4248
static void jl_add_to_ee(std::unique_ptr<Module> m);
4349
static void jl_add_to_ee(std::unique_ptr<Module> &M, StringMap<std::unique_ptr<Module>*> &NewExports);
@@ -523,7 +529,36 @@ static void addPassesForOptLevel(legacy::PassManager &PM, TargetMachine &TM, raw
523529

524530
CompilerResultT JuliaOJIT::CompilerT::operator()(Module &M)
525531
{
532+
uint64_t start_time = 0;
533+
if (dump_llvm_opt_stream != NULL) {
534+
// Print LLVM function statistics _before_ optimization
535+
// Print all the information about this invocation as a YAML object
536+
jl_printf(dump_llvm_opt_stream, "- \n");
537+
// We print the name and some statistics for each function in the module, both
538+
// before optimization and again afterwards.
539+
jl_printf(dump_llvm_opt_stream, " before: \n");
540+
for (auto &F : M.functions()) {
541+
if (F.isDeclaration() || F.getName().startswith("jfptr_")) {
542+
continue;
543+
}
544+
// Count number of Basic Blocks
545+
int bbs = 0;
546+
for (auto &B : F.getBasicBlockList()) {
547+
std::ignore = B;
548+
++bbs;
549+
}
550+
551+
// Each function is printed as a YAML object with several attributes
552+
jl_printf(dump_llvm_opt_stream, " \"%s\":\n", F.getName().str().c_str());
553+
jl_printf(dump_llvm_opt_stream, " instructions: %u\n", F.getInstructionCount());
554+
jl_printf(dump_llvm_opt_stream, " basicblocks: %u\n", bbs);
555+
}
556+
557+
start_time = jl_hrtime();
558+
}
559+
526560
JL_TIMING(LLVM_OPT);
561+
527562
int optlevel;
528563
if (jl_generating_output()) {
529564
optlevel = 0;
@@ -565,6 +600,32 @@ CompilerResultT JuliaOJIT::CompilerT::operator()(Module &M)
565600
"The module's content was printed above. Please file a bug report");
566601
}
567602

603+
uint64_t end_time = 0;
604+
if (dump_llvm_opt_stream != NULL) {
605+
end_time = jl_hrtime();
606+
jl_printf(dump_llvm_opt_stream, " time_ns: %" PRIu64 "\n", end_time - start_time);
607+
jl_printf(dump_llvm_opt_stream, " optlevel: %d\n", optlevel);
608+
609+
// Print LLVM function statistics _after_ optimization
610+
jl_printf(dump_llvm_opt_stream, " after: \n");
611+
for (auto &F : M.functions()) {
612+
if (F.isDeclaration() || F.getName().startswith("jfptr_")) {
613+
continue;
614+
}
615+
616+
// Count number of Basic Blocks
617+
int bbs = 0;
618+
for (auto &B : F.getBasicBlockList()) {
619+
std::ignore = B;
620+
++bbs;
621+
}
622+
623+
jl_printf(dump_llvm_opt_stream, " \"%s\":\n", F.getName().str().c_str());
624+
jl_printf(dump_llvm_opt_stream, " instructions: %u\n", F.getInstructionCount());
625+
jl_printf(dump_llvm_opt_stream, " basicblocks: %u\n", bbs);
626+
}
627+
}
628+
568629
return CompilerResultT(std::move(ObjBuffer));
569630
}
570631

0 commit comments

Comments
 (0)