ZJIT: Skip eliminate_empty_inline_frames if no inlining (#18871)

Resolves https://github.com/Shopify/ruby/issues/1035

If nothing has been inlined skip the eliminate empty inline optimisation pass. We can only do this if no inlining has occurred on any pass. In subsequent passes it's possible for no inlining to occur, but redundant code to be removed, resulting in empty inline frames. By definition of the loop, if `iteration > 0` then inlining has occurred. This is covered by [test_eliminate_empty_inline_frames_with_dead_snapshot](1c391ebaeb/zjit/src/hir/opt_tests.rs (L2238)).

It cuts ~4ms off the compile time:

    build❯ for i in $(seq 0 5); do WARMUP_ITRS=0 MIN_BENCH_ITRS=2 MIN_BENCH_TIME=0 ./ruby --zjit --zjit-stats ruby-bench/benchmarks/lobsters/benchmark.rb 2>&1 | grep eliminate_empty_inline; done
    compile_hir_eliminate_empty_inline_frames_time:                      8ms
    compile_hir_eliminate_empty_inline_frames_time:                      9ms
    compile_hir_eliminate_empty_inline_frames_time:                      9ms
    compile_hir_eliminate_empty_inline_frames_time:                      9ms
    compile_hir_eliminate_empty_inline_frames_time:                      9ms
    compile_hir_eliminate_empty_inline_frames_time:                      9ms

vs master:

    build❯ for i in $(seq 0 5); do WARMUP_ITRS=0 MIN_BENCH_ITRS=2 MIN_BENCH_TIME=0 ./ruby --zjit --zjit-stats ruby-bench/benchmarks/lobsters/benchmark.rb 2>&1 | grep eliminate_empty_inline; done
    compile_hir_eliminate_empty_inline_frames_time:                    13ms
    compile_hir_eliminate_empty_inline_frames_time:                    14ms
    compile_hir_eliminate_empty_inline_frames_time:                    14ms
    compile_hir_eliminate_empty_inline_frames_time:                    13ms
    compile_hir_eliminate_empty_inline_frames_time:                    13ms
    compile_hir_eliminate_empty_inline_frames_time:                    14ms

To measure the change this PR also adds compile_hir_eliminate_empty_inline_frames_time_ns to the statistics displayed.
This commit is contained in:
Steven Webb 2026-10-20 04:22:49 +08:00 committed by GitHub
parent 2720e66e48
commit 7ec1f13c07
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
Notes: git 2026-10-19 20:23:33 +00:00
Merged-By: tekknolagi <donotemailthisaddress@bernsteinbear.com>
2 changed files with 6 additions and 1 deletions

View File

@ -185,6 +185,7 @@ class << RubyVM::ZJIT
:compile_hir_clean_cfg_time_ns,
:compile_hir_remove_redundant_patch_points_time_ns,
:compile_hir_remove_duplicate_check_interrupts_time_ns,
:compile_hir_eliminate_empty_inline_frames_time_ns,
:compile_hir_eliminate_dead_code_time_ns,
:compile_lir_time_ns,
:profile_time_ns,

View File

@ -7711,6 +7711,7 @@ impl Function {
// on inlining passes. If we reach the max, we run the loop one more time with inlining
// disabled in order to optimize the results of the last inlining operation.
let inline_max_iterations = get_option!(inline_max_iterations);
let mut has_ever_inlined = false;
for iteration in 0..=inline_max_iterations {
// Function is assumed to have types inferred already
run_pass!(type_specialize);
@ -7729,7 +7730,10 @@ impl Function {
run_pass!(clean_cfg);
run_pass!(remove_redundant_patch_points);
run_pass!(remove_duplicate_check_interrupts);
run_pass!(eliminate_empty_inline_frames);
has_ever_inlined |= did_inline;
if has_ever_inlined {
run_pass!(eliminate_empty_inline_frames);
}
run_pass!(eliminate_dead_code);
if !did_inline {