Skip to content

Emit inlinable forms of the FP gate and paired-single helpers - #12

Open
dougchansan wants to merge 2 commits into
ExpansionPak:mainfrom
dougchansan:emit-inline-runtime-helpers
Open

Emit inlinable forms of the FP gate and paired-single helpers#12
dougchansan wants to merge 2 commits into
ExpansionPak:mainfrom
dougchansan:emit-inline-runtime-helpers

Conversation

@dougchansan

Copy link
Copy Markdown
Contributor

Profiling a recompiled Mario Kart: Double Dash on Apple Silicon (sample, race scene) put two runtime helpers near the top of self time inside the dispatch loop:

symbol self samples share
ppc_fp_available 869 ~7.1%
psq_load_value + psq_store_value 1101 ~9.0%

Both are called out of line once per generated instruction site — 121,874 FP sites and 19,642 paired-single sites on this title. ppc_fp_available exists to test one MSR bit that a running game always has set, so the cost was the call rather than the work.

What changed

The emitter now emits ppc_fp_available_inline(), ppc_psq_load_inline() and ppc_psq_store_inline(), so a hosting runtime can provide fast paths. This repo's own runtime gets a real inline gate for the FP case and plain forwarders for paired-single, since it backs the tests rather than a shipping port.

ppc_fp_available() is deliberately still defined — the LLVM backend emits calls to it by name (llvm_runtime_lowering.cpp), so it cannot become header-only.

Measured

With GXRuntime providing the fast paths, alternating A/B with a reversed-order block on an idle host:

change delta ranges
inline FP gate +11.8% do not overlap
inline paired-single +4.0% do not overlap

Both beat their profiled share, because an out-of-line call is also an optimisation barrier: at every generated site the helper arguments (w, gqr_index, indexed, cia) are literals, so inlining lets the compiler fold the LSQE test and the w branch away per site.

Ordering

Requires the hosting runtime to provide the _inline names. Without them a port fails to compile, so this should land after the corresponding RecompCore change (ExpansionPak/RecompCore#9).

codegen_compile asserts generated FP code carries an MSR gate; updated to match the new spelling rather than relaxed.

dougchansan and others added 2 commits August 5, 2026 07:35
Profiling a recompiled Mario Kart: Double Dash on Apple Silicon (`sample`, race
scene) put two runtime helpers near the top of self time inside the dispatch
loop:

    ppc_fp_available                       869 samples   ~7.1%
    psq_load_value + psq_store_value      1101 samples   ~9.0%

Both are called out of line once per generated instruction site -- 121,874 FP
sites and 19,642 paired-single sites on this title. ppc_fp_available exists to
test one MSR bit that a running game always has set, so the cost was the call
rather than the work.

The emitter now emits ppc_fp_available_inline(), ppc_psq_load_inline() and
ppc_psq_store_inline(). A hosting runtime can make those fast paths; this
repo's own runtime gets a real inline gate for the FP case and plain forwarders
for paired-single, since it backs the tests rather than a shipping port.

ppc_fp_available() is deliberately still defined: the LLVM backend emits calls
to it by name (llvm_runtime_lowering.cpp), so it cannot become header-only.

Measured with GXRuntime providing the fast paths, alternating A/B with a
reversed-order block, on an otherwise idle host:

    inline FP gate            +11.8%   ranges do not overlap
    inline paired-single       +4.0%   ranges do not overlap

Both beat their profiled share, because an out-of-line call is also an
optimisation barrier: at every generated site the helper arguments (w,
gqr_index, indexed, cia) are literals, so inlining lets the compiler fold the
LSQE test and the w branch away per site.

Requires the hosting runtime to provide the _inline names. Without them a port
fails to compile, so this needs to land after the corresponding RecompCore
change.

codegen_compile asserts generated FP code carries an MSR gate; updated to match
the new spelling rather than relaxed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant