[Mips] Permit tail calls on the R3000A (PS2-184) #10

Merged
techwritescode merged 1 commit from r3000a-tail-calls into r3000a-shared-global-base 2026-10-13 19:16:44 +00:00

Stacked on #9 (which is stacked on #8); the diff against r5900-ee includes their commits until those merge.

GCC turns a call in tail position into a jump (jr $25 / j callee) when the callee's arguments fit in the caller's incoming argument area. LLVM's MIPS backend disables tail calls by default (mips-tail-calls, because of $gp handling in position independent code), so a wrapper that forwards its arguments keeps them in callee-saved registers across a normal call, needing a frame plus a save and restore for each.

A new tail-calls subtarget feature, implied by r3000a only, turns tail calls on. For a CPU with the feature and no SVR4 abicalls the callee no longer has to be DSO-local, since there is no $gp to restore. Other CPUs are unchanged (the existing tailcall.ll test passes unmodified); the mips-tail-calls option still overrides the feature either way. Test: CodeGen/Mips/r3000a-tail-calls.ll.

Results (-Os/-Oz): sdk-core IOP modules at -Oz 57,808 -> 56,836 bytes (-1.7%, +9.5% -> +7.6% over GCC). RiptOPL IOP modules at -Oz: the 46 IRX files 684,894 -> 681,166 (-0.5%), now +4.7% over GCC's 650,850. Each forwarding wrapper loses its frame and its register saves.

Tested

  • Mips CodeGen and MC lit suites: 1,517 passed, 23 expected failures, 0 failed.
  • sdk-core regression tests (9, including a new IOP tail-call test) and diff runs (15) in PCSX2 with the new compiler.
  • The new test covers forwarding with 0 to 6 arguments, reordered and rotated stack arguments, growing and shrinking argument lists, calls through function pointers, and a tail call after another call.
  • RiptOPL builds completely (892 steps) and all 46 IRX pass iopfixup --irx1.
  • On hardware (Deckard): the tail-call test, iop-mmio, the sdsq/sdhd/reboot modules at -Os and -Oz, and audsrv.
  • Not tested: RiptOPL itself on hardware.

🤖 Generated with Claude Code

Stacked on #9 (which is stacked on #8); the diff against `r5900-ee` includes their commits until those merge. GCC turns a call in tail position into a jump (`jr $25` / `j callee`) when the callee's arguments fit in the caller's incoming argument area. LLVM's MIPS backend disables tail calls by default (`mips-tail-calls`, because of $gp handling in position independent code), so a wrapper that forwards its arguments keeps them in callee-saved registers across a normal call, needing a frame plus a save and restore for each. A new `tail-calls` subtarget feature, implied by `r3000a` only, turns tail calls on. For a CPU with the feature and no SVR4 abicalls the callee no longer has to be DSO-local, since there is no $gp to restore. Other CPUs are unchanged (the existing `tailcall.ll` test passes unmodified); the `mips-tail-calls` option still overrides the feature either way. Test: `CodeGen/Mips/r3000a-tail-calls.ll`. **Results** (-Os/-Oz): sdk-core IOP modules at -Oz 57,808 -> 56,836 bytes (-1.7%, +9.5% -> +7.6% over GCC). RiptOPL IOP modules at -Oz: the 46 IRX files 684,894 -> 681,166 (-0.5%), now +4.7% over GCC's 650,850. Each forwarding wrapper loses its frame and its register saves. **Tested** - Mips CodeGen and MC lit suites: 1,517 passed, 23 expected failures, 0 failed. - sdk-core regression tests (9, including a new IOP tail-call test) and diff runs (15) in PCSX2 with the new compiler. - The new test covers forwarding with 0 to 6 arguments, reordered and rotated stack arguments, growing and shrinking argument lists, calls through function pointers, and a tail call after another call. - RiptOPL builds completely (892 steps) and all 46 IRX pass `iopfixup --irx1`. - On hardware (Deckard): the tail-call test, iop-mmio, the sdsq/sdhd/reboot modules at -Os and -Oz, and audsrv. - Not tested: RiptOPL itself on hardware. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
[Mips] Permit tail calls on the R3000A
Some checks failed
Check for private emails used in PRs / validate_email (pull_request) Has been skipped
action.yml / [Mips] Permit tail calls on the R3000A (pull_request) Failing after 0s
Check LLVM ABI annotations / Check LLVM_ABI annotations with ids (pull_request) Has been skipped
CI Checks / Build and Test Linux (pull_request) Has been skipped
CI Checks / Build and Test Windows (pull_request) Has been skipped
CI Checks / Compute macOS Projects (pull_request) Has been skipped
CI Checks / Build and Test macOS arm64 (pull_request) Has been skipped
release-binaries-all.yml / [Mips] Permit tail calls on the R3000A (pull_request) Failing after 0s
release-binaries.yml / [Mips] Permit tail calls on the R3000A (pull_request) Failing after 0s
release-documentation.yml / [Mips] Permit tail calls on the R3000A (pull_request) Failing after 0s
release-sources.yml / [Mips] Permit tail calls on the R3000A (pull_request) Failing after 0s
action.yml / [Mips] Permit tail calls on the R3000A (push) Failing after 0s
release-binaries-all.yml / [Mips] Permit tail calls on the R3000A (push) Failing after 0s
release-binaries.yml / [Mips] Permit tail calls on the R3000A (push) Failing after 0s
release-documentation.yml / [Mips] Permit tail calls on the R3000A (push) Failing after 0s
release-sources.yml / [Mips] Permit tail calls on the R3000A (push) Failing after 0s
Add buildbot information to first PRs from new contributors / buildbot_comment (pull_request_target) Has been skipped
Labelling new pull requests / greeter (pull_request_target) Has been cancelled
Labelling new pull requests / automate-prs-labels (pull_request_target) Has been cancelled
267389ace7
Tail calls are off by default in the MIPS backend because of $gp handling in
position independent code. Add a tail-calls subtarget feature, implied by
r3000a, that turns them on, and drop the requirement for a local callee when
the code has no SVR4 abicalls: without $gp there is nothing to restore. A caller
that ends in a call then needs neither a frame nor callee-saved registers to
hold its arguments across it. The mips-tail-calls option still overrides the
feature.
techwritescode merged commit 267389ace7 into r3000a-shared-global-base 2026-10-13 19:16:44 +00:00
techwritescode deleted branch r3000a-tail-calls 2026-10-13 19:16:46 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
ps2/llvm!10
No description provided.