Most of the time, register coloring is almost trivial: just pick
available registers for the values defined by the current instruction.
However, some instructions have register operand constraints, and it may
be necessary to move live registers around to satisfy the constraints.
Sometimes the instruction's own operands can interfere with each other
in a way that you can't just pick a register assignment for each output
in order.
This is complicated enough that it is worthwhile to represent as a
constraint satisfaction problem in a separate solver module. The
representation is chosen to be very fast in the common case where the
constraints are trivial to solve.
The current implementation is still incomplete, but as functional as the
code it's replacing. Missing features:
- Handle tied operand constraints.
- Handle ABI constraints on calls and return instructions.
- Execute a constraint solution by emitting regmove instructions.
- Handling register diversions before leaving the EBB.
This is a bare-bones outline of the SSA coloring pass. Many features are
missing, including:
- Handling instruction operand constraints beyond simple register
classes.
- Handling ABI requirements for function arguments and return values.
- Generating shuffle code for EBB arguments.
An SSA value is usually biased towards a specific register class or a
stack slot, depending on the constraints of the instructions using it.
Represent this bias as an Affinity enum, and implement a merging
algorithm for updating an affinity to satisfy a new constraint.
Affinities will be computed as part of the liveness analysis. This is
not implemented yet.
This set of available register units also manages register aliasing in
an efficient way.
Detect if the units in a register straddles mask words. The algorithm
for allocating multi-unit registers expect the whole register to be
inside a single mask word. We could handle this if necessary, but so far
no ISAs need it.
We will track live ranges separately for each SSA value, rather than per
virtual register like LLVM does.
This is the basis for a register allocator, so place it in a new
regalloc module.