[Mips] Restore the return address first in the R3000A epilogue (PS2-184) #8

Merged
techwritescode merged 1 commit from r3000a-load-delay-fill into r5900-ee 2026-10-13 19:19:25 +00:00

MIPS I has no load interlock, so a load directly before its use needs a nop. The return reads $ra, and restoring it last put a nop before the jump in nearly every non-leaf function (1,501 of the 6,337 load-delay nops in RiptOPL's IOP code, against 194 for GCC).

A new ra-restore-first subtarget feature, implied by r3000a only, restores $ra first in the epilogue so the other restores fill its delay. It is implemented as a restoreCalleeSavedRegisters override in MipsSEFrameLowering; other CPUs keep the default order unless they ask for the feature. Test: CodeGen/Mips/r3000a-epilogue.ll (first on r3000a and with +ra-restore-first, last on mips1 and with -ra-restore-first).

Results (-Os, RiptOPL's 313 IOP objects): load-delay nops 6,900 -> 5,907 (GCC 3,761); the 46 IRX files total 755,046 -> 750,950 bytes (GCC 650,850, so +16.0% -> +15.4%). The effect is smaller than the epilogue count suggests because many functions already had another instruction between the restore and the jump.

Tested

  • Mips CodeGen and MC lit suites: 1,515 passed, 23 expected failures, 0 failed.
  • sdk-core regression tests (8) and GCC against LLVM diff runs (15) in PCSX2 with the new compiler.
  • RiptOPL builds completely (892 steps, 46 IRX).
  • On hardware (Deckard): IOP register-access test, iop-module, the sdsq/sdhd/reboot modules and audsrv all pass.
  • Not tested: RiptOPL itself on hardware.

Remaining load-delay nops (5,907 against GCC's 3,761) are mostly a load directly followed by its use inside one block; a pass that moves an earlier independent instruction into the slot removed only about 22 nops on the sdk-core modules, so it is not included.

🤖 Generated with Claude Code

MIPS I has no load interlock, so a load directly before its use needs a nop. The return reads `$ra`, and restoring it last put a nop before the jump in nearly every non-leaf function (1,501 of the 6,337 load-delay nops in RiptOPL's IOP code, against 194 for GCC). A new `ra-restore-first` subtarget feature, implied by `r3000a` only, restores `$ra` first in the epilogue so the other restores fill its delay. It is implemented as a `restoreCalleeSavedRegisters` override in `MipsSEFrameLowering`; other CPUs keep the default order unless they ask for the feature. Test: `CodeGen/Mips/r3000a-epilogue.ll` (first on `r3000a` and with `+ra-restore-first`, last on `mips1` and with `-ra-restore-first`). **Results** (-Os, RiptOPL's 313 IOP objects): load-delay nops 6,900 -> 5,907 (GCC 3,761); the 46 IRX files total 755,046 -> 750,950 bytes (GCC 650,850, so +16.0% -> +15.4%). The effect is smaller than the epilogue count suggests because many functions already had another instruction between the restore and the jump. **Tested** - Mips CodeGen and MC lit suites: 1,515 passed, 23 expected failures, 0 failed. - sdk-core regression tests (8) and GCC against LLVM diff runs (15) in PCSX2 with the new compiler. - RiptOPL builds completely (892 steps, 46 IRX). - On hardware (Deckard): IOP register-access test, iop-module, the sdsq/sdhd/reboot modules and audsrv all pass. - Not tested: RiptOPL itself on hardware. Remaining load-delay nops (5,907 against GCC's 3,761) are mostly a load directly followed by its use inside one block; a pass that moves an earlier independent instruction into the slot removed only about 22 nops on the sdk-core modules, so it is not included. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
[Mips] Restore the return address first in the R3000A epilogue
Some checks failed
Check for private emails used in PRs / validate_email (pull_request) Has been skipped
action.yml / [Mips] Restore the return address first in the R3000A epilogue (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] Restore the return address first in the R3000A epilogue (pull_request) Failing after 0s
release-binaries.yml / [Mips] Restore the return address first in the R3000A epilogue (pull_request) Failing after 0s
action.yml / [Mips] Restore the return address first in the R3000A epilogue (push) Failing after 0s
release-binaries-all.yml / [Mips] Restore the return address first in the R3000A epilogue (push) Failing after 0s
release-binaries.yml / [Mips] Restore the return address first in the R3000A epilogue (push) Failing after 0s
release-documentation.yml / [Mips] Restore the return address first in the R3000A epilogue (push) Failing after 0s
release-sources.yml / [Mips] Restore the return address first in the R3000A epilogue (push) Failing after 0s
release-documentation.yml / [Mips] Restore the return address first in the R3000A epilogue (pull_request) Failing after 0s
release-sources.yml / [Mips] Restore the return address first in the R3000A epilogue (pull_request) 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
2b74f6a346
MIPS I has no load interlock, so a load directly before its use needs a nop.
The return reads $ra, and restoring it last put a nop before the jump in
nearly every non-leaf function. Add an ra-restore-first subtarget feature,
implied by r3000a, that restores $ra first so the other restores fill the
delay.
techwritescode deleted branch r3000a-load-delay-fill 2026-10-13 19:19:27 +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!8
No description provided.