-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve register allocation (part 1) #40
Commits on Nov 28, 2023
-
Configuration menu - View commit details
-
Copy full SHA for 1426248 - Browse repository at this point
Copy the full SHA 1426248View commit details -
RISC-V: prefer volatile registers for leaf methods
...over preserved registers. This saves us the need to save / reload (preserved) registers in prologue / epilogue.
Configuration menu - View commit details
-
Copy full SHA for 8311627 - Browse repository at this point
Copy the full SHA 8311627View commit details -
Consider
TRLeave
s return value register as "read" virtual registerThis commit fixes a bug where return value (virtual) register of an `TRLeave` pseudo-instruction was not considered as "read" by that instruction, which in turn could have caused RA to allocate the same physical register to different virtual register and thus cause invalid value to be returned. This commit fixes this problem (which, interestingly, did not manifest)
Configuration menu - View commit details
-
Copy full SHA for 73c8081 - Browse repository at this point
Copy the full SHA 73c8081View commit details -
Rename
#virtualRegistersModifiedBy...
to `#virtualRegistersAssigned……By...` as the word 'assigned' is more commonly used in literature.
Configuration menu - View commit details
-
Copy full SHA for e0e102e - Browse repository at this point
Copy the full SHA e0e102eView commit details -
Introduce new default register allocator - reverse linear scan allocator
This commit introduces a new (default) register allocator class: `TRReverseLinearScanRegisterAllocator`. It is similar to linear scan allocator used previously except it progresses "backwards", that is from last instruction to first, from last register use towards its assignment. The advantage of this is that one can insert spills / reloads into an instruction stream without changing indexes of instructions not yet "processed". However, support for spills / reloads is not yet implemented.
Configuration menu - View commit details
-
Copy full SHA for f4e62df - Browse repository at this point
Copy the full SHA f4e62dfView commit details -
Remove support for (unused) per-virtual-register constraints
This commit removes original support for constraints on virtual register allocation. Not only they were not used but also they could not represent fact that some instructions kill registers instruction is not using - for example a call kills (trashes) all volatile registers. Subsequent commit will introduce per-instruction specified register dependencies just like in grown-up Testarossa.
Configuration menu - View commit details
-
Copy full SHA for 9b7c248 - Browse repository at this point
Copy the full SHA 9b7c248View commit details -
Rename
TRLinearScanRegisterAllocator >> #expireOldRanges:
to `#expi……reOldIntervals:` ...to use the names from original paper [1]. [1]: MASSIMILIANO POLETTO, VIVEK SARKAR: Linear Scan Register Allocation
Configuration menu - View commit details
-
Copy full SHA for ca3a88b - Browse repository at this point
Copy the full SHA ca3a88bView commit details -
Introduce
TRRegisterDependencies
to express register constraints......by instructions that require certain values to be in specific registers. Most common example are calls where (some) parameters are passed in specific registers an return value is passed on specific register(s). Moreover, register dependencies may be used to express situation where an instruction trashes some registers - for example call to a function trashes all volatile registers. Also, some architectures have other constraints, for example on x86, `mul` places result to `eax` / `rax`. Again, this can be (should be) expressed register dependencies as well. This commit only adds the necessary classes and infrastructure but does not use it. This is left for later commits.
Configuration menu - View commit details
-
Copy full SHA for 60e547d - Browse repository at this point
Copy the full SHA 60e547dView commit details -
Add (virtual) register to
TRRegisterLiveRange
This commit adds new instvar - `register` - to `TRRegisterLiveRange` making use of associations in linear scan allocators unnecessary. This feels as a cleaner solution.
Configuration menu - View commit details
-
Copy full SHA for f5c8f2a - Browse repository at this point
Copy the full SHA f5c8f2aView commit details -
Delegate
?return
evaluation to linkage...just like `?call` is delegated. As before, (new) `TRLinkage >> #generateReturn:` is supposed to generate a leave instruction (see `TRLeave`), *NOT* complete epilogue. This is in preparation for using register dependencies to coerce virtual registers to specific physical registers.
Configuration menu - View commit details
-
Copy full SHA for 8061a46 - Browse repository at this point
Copy the full SHA 8061a46View commit details -
Add
TRCodeGenerator >> #cursor:
(and#cursor
)...for setting (and reading) current instruction generation cursor. Useful for injecting register moves / spills and reloads after RA. See `AcDSLAssembler >> #cursor:` (and `#cursor`)
Configuration menu - View commit details
-
Copy full SHA for 2796102 - Browse repository at this point
Copy the full SHA 2796102View commit details -
Add
TRCodeGenerator >> #registerCopyFrom:to:
...to move register contents from one register to another. Useful (for example) for injecting register moves after RA to satisfy register dependencies.
Configuration menu - View commit details
-
Copy full SHA for 2e3a542 - Browse repository at this point
Copy the full SHA 2e3a542View commit details -
Configuration menu - View commit details
-
Copy full SHA for 81f89e4 - Browse repository at this point
Copy the full SHA 81f89e4View commit details -
RISC-V: use register dependencies to express register constraints
This commit uses `TRRegisterDependencies` to express constraints on registers upon function call and return such that arguments are passed in specific registers as well as return value is returned through a register.
Configuration menu - View commit details
-
Copy full SHA for ae54ae1 - Browse repository at this point
Copy the full SHA ae54ae1View commit details -
Configuration menu - View commit details
-
Copy full SHA for 5de102e - Browse repository at this point
Copy the full SHA 5de102eView commit details -
POWER: use register dependencies to express register constraints
This commit uses `TRRegisterDependencies` to express constraints on registers upon function call and return such that arguments are passed in specific registers as well as return value is returned through a register.
Configuration menu - View commit details
-
Copy full SHA for 7c918d0 - Browse repository at this point
Copy the full SHA 7c918d0View commit details -
Treat pre-dependent virtual registers of an instruction as "read"
This commit treats any dependent virtual register in instructions' register pre-dependencies as "read" by that instruction. This makes sure the register is live at that point.
Configuration menu - View commit details
-
Copy full SHA for d43edf9 - Browse repository at this point
Copy the full SHA d43edf9View commit details -
Treat post-dependent virtual registers of an instruction as "assigned"
Similar to previous commit, this commit treats any dependent virtual register in instructions' register post-dependencies as "assigned" by that instruction. This makes sure the register is live at that point.
Configuration menu - View commit details
-
Copy full SHA for d5d185d - Browse repository at this point
Copy the full SHA d5d185dView commit details -
Let the register allocator to handle (virtual) register dependencies
Previously, satisfying (virtual) register dependencies was hard-coded in linkage, i.e., linkage generated code to move values to appropriate parameter registers before the call and move return value from return register to desired (virtual) register. This solution has two problems: * It works only for parameter / return values of a call, not for any instruction. This is especially problem for x86 which is famous for having peculiar restrictions on what registers can be used with what instructions. * Moreover, it effectively prohibits register allocator to allocate values directly into parameter registers or read value directly from return register and thus, increases register pressure. This commit addreses these two problem by moving the responsibility for satisfying register dependencies to to register allocator. As of now, it does not do anything smart w.r.t. allocation but simply inserts register moves. This will be improved later.
Configuration menu - View commit details
-
Copy full SHA for 1de66be - Browse repository at this point
Copy the full SHA 1de66beView commit details -
Simplify linear scan allocators
This commit simplifies implementation of both (forward) linear scan allocator and reverse linear scan allocator so they no longer use odd interval start points and and even end points (see that `i * 2` and `(i * 2) + 1` when collecting live intervals. Obviously the same effect can be achieved by carefully implementing interval expiration (which is what this commit does).
Configuration menu - View commit details
-
Copy full SHA for 1e78238 - Browse repository at this point
Copy the full SHA 1e78238View commit details -
Refactor reverse linear scan allocator (part i)
This commit refactors reverse linear scan allocator so that it processes one instruction at time, allocating registers and ensuring dependencies are met. This is a preparation for more clever allocation that handles spills and reloads as well.
Configuration menu - View commit details
-
Copy full SHA for 35c00a4 - Browse repository at this point
Copy the full SHA 35c00a4View commit details -
Refactor reverse linear scan allocator (part ii)
This commit further refactors reverse linear scan allocator to facilitate further improvements.
Configuration menu - View commit details
-
Copy full SHA for 62335c2 - Browse repository at this point
Copy the full SHA 62335c2View commit details -
Configuration menu - View commit details
-
Copy full SHA for 73e3c0b - Browse repository at this point
Copy the full SHA 73e3c0bView commit details -
Add new compilation option:
stressRA
This commit adds new boolean option - `stressRA`. When set to `true` it reduces the set of registers available for allocation drastically to stress-test register allocator.
Configuration menu - View commit details
-
Copy full SHA for 4481da3 - Browse repository at this point
Copy the full SHA 4481da3View commit details -
RISC-V: always prefer volatile registers when stress-testing the regi…
…ster allocator ...as it forces allocator to spill / reload live volatile register on each call.
Configuration menu - View commit details
-
Copy full SHA for 1d75e60 - Browse repository at this point
Copy the full SHA 1d75e60View commit details -
When fixing up registers, build fixup map manually
This commit creates register fixup map manually rather than depending on fact that virtual register converts to concrete bitvector when real register is allocated. This is not only easier to understand but also makes it easier debug RA because inserted spills / reloads / moves refer to virtual registers so it is clear which (virtual) register is spilled.
Configuration menu - View commit details
-
Copy full SHA for a8ebd65 - Browse repository at this point
Copy the full SHA a8ebd65View commit details -
RLSRA: spill / reload trashed live registers
This commit add support for spilling / reloading trashed registers that contain live values. Mostly, this is the case of volatile (and argument) registers being (potentially) thrashed by calls. This is only supported by reverse linear scan allocator. Implementation note: for now, spill slot is allocated as unnamed automatic on a stack for each (spilled) interval. For actually spilling, it used `TRCodeGenerator >> registerStore:to:` and `#registerLoad:from:`. This may not work in all cases with all linkages - some linkages may prescribe where to spill registers (PPC64 ELF v2 ABI?, Microsoft x64?).
Configuration menu - View commit details
-
Copy full SHA for 192d92d - Browse repository at this point
Copy the full SHA 192d92dView commit details -
Remove (old) linear scan and (even older) naive constraint solving re…
…gister allocators This commit removes `TRLinearScanRegisterAllocator` and `TRNaiveConstraintSolvingRegisterAllocator` register allocators. The main reason is that commit "Let the register allocator to handle (virtual) register dependencies" moves the responsibility to move values to argument registers and from return register(s) to register allocator based on register dependencies. Neither `TRLinearScanRegisterAllocator` and `TRNaiveConstraintSolvingRegisterAllocator` can be easily updated to work with this change, so this commit removes them.
Configuration menu - View commit details
-
Copy full SHA for 9825aad - Browse repository at this point
Copy the full SHA 9825aadView commit details