[Mips] R3000A scheduling model, constant address folding and delay slot filling (PS2-184) #7

Merged
techwritescode merged 3 commits from r3000a-delay-slot into r5900-ee 2026-10-13 17:52:39 +00:00

Three independent, CPU-gated changes that shrink IOP code (PS2-183, PS2-184). Each commit builds on the previous one and has its own lit test.

Commit Gate Effect
Add an R3000A scheduling model IsR3000A (new, set only by -mcpu=r3000a) In-order single-issue model with a two-cycle load latency, and the machine scheduler for the R3000A. Independent loads are issued back to back instead of load, nop, use
Fold constant absolute addresses into load and store offsets const-addr-fold, implied by r3000a and r5900, switchable with -mattr Memory-mapped register access becomes lui + lw off($r) instead of lui + ori + lw 0($r)
Fill R3000A delay slots from the successor block delay-slot-succ-fill, implied by r3000a only Turns on the existing successor-block search (off by default, disable-mips-df-succbb-search). The option still overrides it either way

The delay-slot commit also keeps an instruction with a %hi relocation from moving across blocks. Without that the search hoisted lui %hi(sym) into a predecessor's slot, away from its %lo, and iopfixup --irx1 rejected the module with R_MIPS_LO16 without R_MIPS_HI16.

Other CPUs are unchanged unless they request a feature. New tests: r3000a-sched.ll, r3000a-const-addr.ll, r3000a-delay-slot.ll, r3000a-delay-slot-hi16.ll.

Results (-Os, RiptOPL's 313 IOP objects against GCC 15.2): unfilled branch delay slots 8,122 -> 5,563 (GCC 5,598). The 46 IRX files total 765,254 -> 755,046 bytes (GCC 650,850). On 11 sdk-core IOP modules .text is 3.9% smaller (69,196 -> 66,480). Load-delay nops are still 6,900 against GCC's 3,761 and are not addressed here.

Tested

  • Mips CodeGen and MC lit suites: 1,514 passed, 23 expected failures, 0 failed.
  • sdk-core regression tests (8) and GCC against LLVM diff runs (15) in PCSX2 with the new compiler.
  • On hardware (Deckard): an IOP register-access test (constant addresses against explicit loads), iop-module, the sdsq/sdhd/reboot modules, audsrv, cxx-exceptions and cxx-threads. fp-compare, kernels and libm give the same hashes as before.
  • RiptOPL builds completely with the new compiler (892 steps, 46 IRX).
  • Not tested: RiptOPL itself on hardware, rmreset on hardware.

🤖 Generated with Claude Code

Three independent, CPU-gated changes that shrink IOP code (PS2-183, PS2-184). Each commit builds on the previous one and has its own lit test. | Commit | Gate | Effect | |---|---|---| | Add an R3000A scheduling model | `IsR3000A` (new, set only by `-mcpu=r3000a`) | In-order single-issue model with a two-cycle load latency, and the machine scheduler for the R3000A. Independent loads are issued back to back instead of load, nop, use | | Fold constant absolute addresses into load and store offsets | `const-addr-fold`, implied by `r3000a` and `r5900`, switchable with `-mattr` | Memory-mapped register access becomes `lui` + `lw off($r)` instead of `lui` + `ori` + `lw 0($r)` | | Fill R3000A delay slots from the successor block | `delay-slot-succ-fill`, implied by `r3000a` only | Turns on the existing successor-block search (off by default, `disable-mips-df-succbb-search`). The option still overrides it either way | The delay-slot commit also keeps an instruction with a `%hi` relocation from moving across blocks. Without that the search hoisted `lui %hi(sym)` into a predecessor's slot, away from its `%lo`, and `iopfixup --irx1` rejected the module with `R_MIPS_LO16 without R_MIPS_HI16`. Other CPUs are unchanged unless they request a feature. New tests: `r3000a-sched.ll`, `r3000a-const-addr.ll`, `r3000a-delay-slot.ll`, `r3000a-delay-slot-hi16.ll`. **Results** (-Os, RiptOPL's 313 IOP objects against GCC 15.2): unfilled branch delay slots 8,122 -> 5,563 (GCC 5,598). The 46 IRX files total 765,254 -> 755,046 bytes (GCC 650,850). On 11 sdk-core IOP modules `.text` is 3.9% smaller (69,196 -> 66,480). Load-delay nops are still 6,900 against GCC's 3,761 and are not addressed here. **Tested** - Mips CodeGen and MC lit suites: 1,514 passed, 23 expected failures, 0 failed. - sdk-core regression tests (8) and GCC against LLVM diff runs (15) in PCSX2 with the new compiler. - On hardware (Deckard): an IOP register-access test (constant addresses against explicit loads), iop-module, the sdsq/sdhd/reboot modules, audsrv, cxx-exceptions and cxx-threads. fp-compare, kernels and libm give the same hashes as before. - RiptOPL builds completely with the new compiler (892 steps, 46 IRX). - Not tested: RiptOPL itself on hardware, `rmreset` on hardware. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
The PS2 IOP's R3000A had no scheduling model and the machine scheduler only
ran for the R5900, so a load was always followed by the instruction that used
it and the load delay pass had to insert a nop. Give the CPU an in-order
single-issue model with a two-cycle load latency, a CPU identity feature of its
own (IsR3000A) and enable the machine scheduler for it.
Memory-mapped register access in PS2 driver code loaded the address with
lui + ori and used a zero offset. Add a const-addr-fold subtarget feature,
implied by r3000a and r5900, that splits a constant 32-bit address into a lui
of the rounded upper half and a signed 16-bit offset, as GCC does. Other
targets are unchanged unless they request the feature.
[Mips] Fill R3000A delay slots from the successor block
Some checks failed
action.yml / [Mips] Fill R3000A delay slots from the successor block (push) Failing after 0s
release-binaries-all.yml / [Mips] Fill R3000A delay slots from the successor block (push) Failing after 0s
release-binaries.yml / [Mips] Fill R3000A delay slots from the successor block (push) Failing after 0s
release-documentation.yml / [Mips] Fill R3000A delay slots from the successor block (push) Failing after 0s
release-sources.yml / [Mips] Fill R3000A delay slots from the successor block (push) Failing after 0s
Check for private emails used in PRs / validate_email (pull_request) Has been skipped
action.yml / [Mips] Fill R3000A delay slots from the successor block (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] Fill R3000A delay slots from the successor block (pull_request) Failing after 0s
release-binaries.yml / [Mips] Fill R3000A delay slots from the successor block (pull_request) Failing after 0s
release-documentation.yml / [Mips] Fill R3000A delay slots from the successor block (pull_request) Failing after 0s
release-sources.yml / [Mips] Fill R3000A delay slots from the successor block (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
e0c309590c
MIPS I has no branch-likely instructions, and the delay slot filler only
searched backwards, so 38 to 74 percent of conditional branch slots in IOP
code were nops. Add a delay-slot-succ-fill subtarget feature, implied by
r3000a, that turns on the existing successor block search. The
disable-mips-df-succbb-search option still overrides it either way.

An instruction holding a %hi relocation is never moved across blocks:
IRX1 relocations pair each HI16 with the LO16 that follows it.
techwritescode deleted branch r3000a-delay-slot 2026-10-13 17:52:42 +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!7
No description provided.