Skip to content

Add -Oinline-pushregs: save and restore registers inline in P2 hub functions - #517

Merged
totalspectrum merged 1 commit into
totalspectrum:masterfrom
j-modernc-org:inline-pushregs
Oct 13, 2026
Merged

totalspectrum merged 1 commit into
totalspectrum:masterfrom
j-modernc-org:inline-pushregs

Conversation

@j-modernc-org

Copy link
Copy Markdown

This is the inline save/restore from item 3 of totalspectrum/flexprop#118, behind an optimization flag as you suggested there.

With -Oinline-pushregs, a P2 function in hub memory that needs a frame saves and restores its registers with setq/wrlong and setq/rdlong inline in its entry and exit code, instead of calling pushregs_ and popregs_ in COG memory. The frame is the same, so __unwind_stack, popregs_, setjmp/longjmp and gosub_ are untouched. Functions placed in COG or LUT memory keep the calls, and P1 is not affected.

The flag is in EXTRA_ASM_OPTS, so -O2 turns it on, and -O1 and -Os generate the same code as before. It can also be turned on by itself (-O1,inline-pushregs) or for one function with __attribute__(opt(inline-pushregs)). doc/general.md has an entry for it.

Cost and benefit are as measured in the flexprop issue: about 32 clocks less per call of such a function, 5 to 9 more longs per function, and +6.3% speed on a PDP-11 emulator. Over the C programs below, binaries grow by 8.9% on average (0.5% to 13.4%).

Checked, with flexspin built from this branch (master 28d434d plus this commit):

  • make test_offline: the same tests pass as on master. The P2 asm expectations are COG code, so none of them is affected.
  • Test/runtests_p2.sh on a P2-EDGE: 27 of 27 pass. They are built with -O2, so every test now uses the inline sequences and none calls pushregs_. The BASIC try/catch and Spin abort tests unwind through these frames.
  • 1416 C programs, our compiler's test corpus and fuzzer output (1326 of them build):
    • With the flag off, every binary is identical to master's: -O1 for all of them, -Os for a quarter of them.
    • With the flag on, every binary is identical to what the unconditional change from the flexprop issue gives on the same master: -O1,inline-pushregs for all of them, -O2 for a quarter of them.
    • On the board, built with -O1,inline-pushregs: all 321 fuzzer programs that build pass their own checks, and 238 test programs print the same as master's builds of them.

…nctions

On the P2, a function in hub memory that needs a frame calls pushregs_
and popregs_ in COG memory to save and restore its registers. Each of
those calls goes into COG memory and back to hub, which reloads the
instruction FIFO.

With -Oinline-pushregs the same setq/wrlong and setq/rdlong sequences
are emitted inline in the function's entry and exit code. They build
the identical frame, so __unwind_stack, popregs_, setjmp/longjmp and
gosub_ are unchanged. Functions placed in COG or LUT memory keep the
calls, and P1 is not affected.

The flag is part of -O2 (EXTRA_ASM_OPTS); -O1 and -Os generate the same
code as before.
@totalspectrum
totalspectrum merged commit 05730c4 into totalspectrum:master Oct 13, 2026
6 checks passed
@totalspectrum

Copy link
Copy Markdown
Owner

Thank you for the pull request!

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.

2 participants