Repository navigation
Let a register local of several longs give its registers back - #521
j-modernc-org wants to merge 3 commits into
Conversation
A local held in registers that is larger than a long -- a struct, or a 64
bit value -- is a base register with a subregister for each further long,
and RenameSubregs keeps those in consecutive registers. ReuseLocalRegisters
leaves subregisters alone, so such a local keeps all its registers to the
end of the function. A function passing many struct values to calls, each
a compound literal or a temporary of its own, runs out of registers ("fit
480 failed"), or past the limit crashes.
SplitLocalStructs runs before a function's first optimization and splits
each such local into one local per long, unless something needs the longs
together: the register's address taken for an indexed access (an
IMM_COG_LABEL of its name), inline assembly, or an instruction after a
SETQ. The optimizer then reuses those registers as it does any other
local's.
Test/stest322.c passes a struct literal to four calls: the literals took 12
registers and take none, their values moved straight into the argument
registers. 15 asm test outputs change: 9 only drop registers reserved for
locals the optimizer had already removed, 6 have shorter code (in two of
them functions become identical and are merged).
|
Subregister is the Chesterton's Fence of flexpsin. |
GetLea of a subregister names that long's address as OffsetName does, base_01, and SplitLocalStructs compared an address with the base register's name only. No frontend was found to reach this with a local held in registers, since a local whose address is taken goes to the stack; but where one did, the split would leave the label naming a register the long is no longer in. An address of the base register or of any of its longs now keeps the local whole. No test output changes.
|
Point taken, and that is why this pass stays away from them instead of
Your comment sent me back to look for more, and there was one I had missed: If you know of anything else that relies on the longs being consecutive, I Thank you. |
|
If I were to make an additional suggestion, instead of having a big comment at some random position in the file and a bunch of uncommented code below, the comments should be next to the code it actually applies to. |
|
(and given aformentioned subregister cursedness, this should be |
Subregisters are used in ways that are easy to miss, so the pass now runs only where OPT_EXPERIMENTAL is set (-O2, -Oexperimental). At the default -O1 the output is master's. The comments now sit next to the code they describe. The asm tests are compiled with all optimizations, so their expected output does not change.
|
Thank you, all three are done in 01c3f51:
The asm tests are compiled with all optimizations, so their expected output |
A local held in registers that is larger than a long (a struct, or a 64 bit
value) is a base register with a subregister for each further long, and
RenameSubregs keeps its longs in consecutive registers. ReuseLocalRegisters
does not touch subregisters, so such a local holds all its registers until
the end of the function. A function that passes many struct values to calls,
each a compound literal or a temporary of its own, runs out of cog registers
("fit 480 failed") or, past the local register limit, crashes.
This adds SplitLocalStructs, run before a function's first OptimizeIRLocal
when experimental optimizations are enabled (-O2, -Oexperimental).
It splits each such local into one local per long, unless something needs
the longs together: the register's address taken for an indexed access (an
IMM_COG_LABEL of its name), inline assembly, or an instruction after a SETQ.
The optimizer then reuses those registers as it does any other local's.
Test/stest322.c is a new asm test: four calls passing a struct literal. The
literals took 12 registers and now take none; their values are moved
straight into the argument registers. 15 existing asm test outputs change,
and I read each diff: 9 only drop registers reserved for locals the
optimizer had already removed, 6 have shorter code, and in two of those
(stest278, stest315) functions become identical and are merged.
Testing:
pass as on master.
output of a compiler that emits C for flexcc, and its reproducers),
compiled with -2 at b5993a8 with Fix two miscompiles of values of two to four longs passed and returned in registers #519's two commits and our other
patches applied, with and without this change: 1165 build differently,
44 that did not fit before now build, and on a P2-EDGE every one prints
what it printed before (the ones that did not build before print what
gcc's build prints).