Commit Graph

92 Commits

Author SHA1 Message Date
Jakob Stoklund Olesen
0917cfe7f4 Attach encodings to regmove instructions generated during coloring.
All emitted regmove instructions must be materialized as real move
instructions.
2017-07-12 10:43:42 -07:00
Jakob Stoklund Olesen
69f974ba5d Add an ISA argument to dfg.display_inst().
Include ISA-specific annotations in tracing and error messages.
2017-07-12 10:13:13 -07:00
Jakob Stoklund Olesen
f0abff3611 Handle tied operands that are not killed by their use.
Any tied register uses are interesting enough to be added to the reguses
list if their value is not killed.

A copy needs to be inserted in that case.
2017-07-05 15:48:06 -07:00
Jakob Stoklund Olesen
60efc68931 Only print pressure for toprcs containing registers.
Many ISAs don't need 4 top-level register classes, so don't print them.
2017-07-05 15:48:06 -07:00
Jakob Stoklund Olesen
e7db3f2b3a Add a test with a fixed register constraint.
Make sure we use the diverted register location for tied operands.
2017-07-05 12:08:53 -07:00
Jakob Stoklund Olesen
9108716cb7 Implement fmt::Display for AllocatableSet.
Also add a display() method which accepts a RegInfo reference.
2017-07-05 12:08:53 -07:00
Jakob Stoklund Olesen
0d2d1ea8cf Add support for tied operands.
Include a very basic test using an Intel 'sub' instruction. More to
follow.
2017-06-30 13:36:41 -07:00
Jakob Stoklund Olesen
aa3bf4467e Hook up the handling of tied register constraints.
Tests are forthcoming, we need to implement Intel ABI lowering first.
2017-06-30 08:41:54 -07:00
Jakob Stoklund Olesen
18dc420352 Repair constraint violations during spilling.
The following constraints may need to be resolved during spilling
because the resolution increases register pressure:

- A tied operand whose value is live through the instruction.
- A fixed register constraint for a value used more than once.
- A register use of a spilled value needs to account for the reload
  register.
2017-06-29 16:51:05 -07:00
Jakob Stoklund Olesen
2b999d9bd6 Add an Index<Value> implementation to Liveness.
Use it to access live ranges that are supposed to be there.
2017-06-29 15:13:04 -07:00
Jakob Stoklund Olesen
138d3c75c6 Spill live-ins and EBB arguments if there are too many. 2017-06-29 14:07:19 -07:00
Jakob Stoklund Olesen
ae661631aa Only color EBB arguments that have register affinity.
It is possible to pass a register value as an argument to an EBB that
expects a "None" affinity. In that case, the destination EBB value
should not be colored.
2017-06-29 13:29:43 -07:00
Jakob Stoklund Olesen
d6f73ac4c8 Split spill_from() into spill_candidate() and spill_reg().
We'll need to pick a spill candidate from a set and allow for the search
to fail to find anything.

This also allows slightly better panic messages when we run out of
registers.
2017-06-29 11:11:46 -07:00
Jakob Stoklund Olesen
588ef0ad2f Propagate affinities for EBB arguments.
A priory, an EBB argument value only gets an affinity if it is used
directly by a non-ghost instruction. A use by a branch passing arguments
to an EBB doesn't count.

When an EBB argument value does have an affinity, the values passed by
all the predecessors must also have affinities. This can cause EBB
argument values to get affinities recursively.

- Add a second pass to the liveness computation for propagating EBB
  argument affinities, possibly recursively.
- Verify EBB argument affinities correctly: A value passed to a branch
  must have an affinity only if the corresponding EBB argument value in
  the destination has an affinity.
2017-06-29 10:30:26 -07:00
Jakob Stoklund Olesen
e7a543ea33 Make sure return values are assigned an affinity.
When an EBB argument value is used only as a return value, it still
needs to be given a register affinity. Otherwise it would appear as a
ghost value with no affinity.

Do the same to call arguments.
2017-06-29 09:24:05 -07:00
Jakob Stoklund Olesen
0574dcdeee Don't coalesce incoming stack arguments.
A function parameter in an incoming_arg stack slot should not be
coalesced into any virtual registers. We don't want to force the whole
virtual register to spill to the incoming_arg slot.
2017-06-28 15:37:38 -07:00
Jakob Stoklund Olesen
b2fda76c5f Assign stack slots to incoming function arguments.
Function arguments that don't fit in registers are passed on the stack.

Create "incoming_arg" stack slots representing the stack arguments, and
assign them to the value arguments during spilling.
2017-06-28 15:03:59 -07:00
Jakob Stoklund Olesen
bbdf07a64e Color EBB arguments.
When coloring registers for a branch instruction, also make sure that
the values passed as EBB arguments are in the registers expected by the
EBB.

The first time a branch to an EBB is processed, assign the EBB arguments
to the registers where the branch arguments already reside so no
regmoves are needed.
2017-06-27 16:35:38 -07:00
Jakob Stoklund Olesen
165e80d9bf Process ghost instruction kills during coloring.
Ghost instructions don't generate code, but they can keep registers
alive. The coloring pass needs to process values killed by ghost
instructions so it knows when the registers are freed up.

Also track register pressure changes from ghost kills in the spiller.
2017-06-27 16:35:11 -07:00
Jakob Stoklund Olesen
222ea74830 Spill whole virtual registers at a time.
When the spiller decides to spill a value, bring along all of the values
in its virtual register. This ensures that we won't have problems with
computing register pressure around EBB arguments. They will always be
register-to-register or stack-to-stack with related values using the
same stack slot.

This also means that the reloading pass won't have to deal with spilled
EBB arguments.
2017-06-23 10:43:59 -07:00
Jakob Stoklund Olesen
85b624d13b Add a coalescing pass to the register allocator.
Coalescing means creating virtual registers and transforming the code
into conventional SSA form. This means that every value used as a branch
argument will belong to the same virtual register as the corresponding
EBB argument value.

Conventional SSA form makes it easy to avoid memory-memory copies when
spilling values, and the virtual registers can be used as hints when
picking registers too. This reduces the number of register moves needed
for EBB arguments.
2017-06-22 15:03:48 -07:00
Jakob Stoklund Olesen
d5055275c4 Virtual registers.
Add a VirtRegs collection which tracks virtual registers.

A virtual register is a set of related SSA values whose live ranges
don't interfere. It is advantageous to use the same register or spill
slot for al the values in a virtual register. It reduces copies for EBB
arguments.
2017-06-22 14:51:10 -07:00
Jakob Stoklund Olesen
d079dead9a Skip ghost instructions when coloring.
Ghost instructions don't have an encoding, and don't appear in the
output. The values they define do not need to be assigned to registers,
so they can be skipped.
2017-06-22 14:49:43 -07:00
Jakob Stoklund Olesen
10e4b2fa06 Add two interference checking methods to LiveInterval.
The overlaps_def() method tests if a definition would conflict with the
live range.

The reaches_use() method tests if a live range is live at an
instruction.
2017-06-22 14:49:43 -07:00
Jakob Stoklund Olesen
b6cff6a98a Move EntityRef and entity_impl! into a new module.
The EntityRef trait is used by more than just the EntityMap now, so it
should live in its own module.

Also move the entity_impl! macro into the new module so it can be used
for defining new entity references anywhere.
2017-06-20 10:16:27 -07:00
Dan Gohman
0c7316ae28 Lint fixes (#99)
* Replace a single-character string literal with a character literal.

* Use is_some() instead of comparing with Some(_).

* Add code-quotes around type names in comments.

* Use !...is_empty() instead of len() != 0.

* Tidy up redundant returns.

* Remove redundant .clone() calls.

* Remove unnecessary explicit lifetime parameters.

* Tidy up unnecessary '&'s.

* Add parens to make operator precedence explicit.

* Use debug_assert_eq instead of debug_assert with ==.

* Replace a &Vec argument with a &[...].

* Replace `a = a op b` with `a op= b`.

* Avoid unnecessary closures.

* Avoid .iter() and .iter_mut() for iterating over containers.

* Remove unneeded qualification.
2017-06-19 16:24:10 -07:00
Jakob Stoklund Olesen
1dd8d913aa Assign spill slots to spilled values.
As soon as a value is spilled, also assign it to a spill slot.

For now, create a new spill slot for each spilled value. In the future,
values will be sharing spill slots of they are phi-related.
2017-06-16 13:34:18 -07:00
Jakob Stoklund Olesen
ddbf46bef4 Add typedefs for the common entity maps.
The various entity maps in a function end up being referenced in
multiple places, so create typedefs for them.
2017-06-16 13:21:05 -07:00
Jakob Stoklund Olesen
db62f435f8 Make register copies for incompatible operands.
An instruction may have fixed operand constraints that make it
impossibly to use a single register value to satisfy two at a time.

Detect when the same value is used for multiple fixed register operands
and insert copies during the spilling pass.
2017-06-15 13:12:13 -07:00
Jakob Stoklund Olesen
96f1228211 Always call reassign_in for register ABI arguments.
Even if an argument is already in the correct register, make sure that
we detect conflicts by registering the no-op move. This also means that
the ABI argument register won't be turned into a variable for the
solver.
2017-06-14 12:10:57 -07:00
Jakob Stoklund Olesen
454910407f Spill values live across calls.
Calls clobber many registers, so spill everything that is live across a
call for now.

In the future, we may add support for callee-saved registers.
2017-06-14 08:55:01 -07:00
Jakob Stoklund Olesen
0974b4a6e2 Extract spill insertion into a reload::insert_spill function.
Make sure that spill instructions are generated in the same way
everywhere, including adding encoding and updating live ranges.
2017-06-13 15:46:11 -07:00
Jakob Stoklund Olesen
396b998dad Handle ABI arguments correctly in the reload pass.
Values passed as arguments to calls and return instructions may also be
reload candidates.
2017-06-13 15:13:36 -07:00
Jakob Stoklund Olesen
63a372fd80 Basic spilling implementation.
Add a spilling pass which lowers register pressure by assigning SSA
values to the stack. Important missing features:

- Resolve conflicts where an instruction uses the same value more than
  once in incompatible ways.
- Deal with EBB arguments.

Fix bugs in the reload pass exposed by the first test case:

- Create live ranges for temporary registers.
- Set encodings on created spill and fill instructions.
2017-06-13 13:58:20 -07:00
Jakob Stoklund Olesen
9cea092bc3 Track transient register counts in Pressure.
The register pressure tracker now has to separate register counts: base
and transient.

The transient counts are used to track spikes of register pressure, such
as dead defs or temporary registers needed to satisfy instruction
constraints.

The base counts represent long-lived variables.
2017-06-13 13:44:00 -07:00
Jakob Stoklund Olesen
0d227fd230 Add a minimalistic reload pass.
The reload pass inserts spill and fill instructions as needed so
instructions that operate on registers will never see a value with stack
affinity.

This is a very basic implementation, and we can't write good test cases
until we have a spilling pass.
2017-06-07 12:05:38 -07:00
Jakob Stoklund Olesen
9adfd8709b Add Liveness methods for updating live ranges.
The create_dead() methods can create a live range for a new value, and
extend_local() can extend a live range within an EBB where it is already
live.

This is enough to update liveness for new values as long as they stay
local to their EBB.
2017-06-07 11:57:58 -07:00
Jakob Stoklund Olesen
1d8efaad83 Add a register pressure tracker.
The spilling and reload passes need to ensure that the set of live
ranges with register affinity can always be assigned registers. The
register pressure tracker can count how many registers are in use for
each top-level register class and give guidance on the type of
registers that need to be spilled when limits are exceeded.

Pressure tracking is extra complicated for the arm32 floating point
register bank because there are multiple top-level register classes (S,
D, Q) competing for the same register units.
2017-05-16 17:02:11 -07:00
Jakob Stoklund Olesen
d1e37def3f Implement ExactSizeIterator for RegSetIter.
The set of available registers in a register class is known ahead of
time. It can be computed with pop-count.
2017-05-16 10:53:30 -07:00
Jakob Stoklund Olesen
71bb7483b7 Compute top-level register classes for each register bank.
A top-level register class is one that has no sub-classes. It is
possible to have multiple top-level register classes in the same
register bank. For example, ARM's FPR bank has both D and Q top-level
register classes.

Number register classes such that all top-level register classes appear
as a contiguous sequence starting from 0. This will be used by the
register allocator when counting used registers per top-level register
class.
2017-05-15 15:19:49 -07:00
Jakob Stoklund Olesen
621f3a2f50 Add a register bank index to RegClassData.
This makes it possible to find the register bank that contains a
register class.
2017-05-15 15:17:58 -07:00
Benjamin Bouvier
29dc723e25 Update rustfmt to 0.8.4; (#81) 2017-05-15 15:10:47 -07:00
Jakob Stoklund Olesen
c713ea8c57 Add fixed constraints for ABI arguments and return values.
We can start adding some real test cases for the move resolver now.
2017-05-11 12:02:02 -07:00
Jakob Stoklund Olesen
9be262e878 Implement a move resolver for the register constraint solver.
After finding a register solution, it need to be executed as a sequence
of regmove instructions. This often requires a topological ordering of
the moves so they don't conflict.

When the solution contains cycles, try to grab an available scratch
register to implement the copies. Panic if that fails (later, we'll
implement emergency spilling in this case).

Make sure we handle odd aliasing in the arm32 floating point register
bank. Not everything is a simple cycle in that case, so make sure we
don't assume so.
2017-05-11 11:54:02 -07:00
Jakob Stoklund Olesen
b521254149 Solver variables keep track of where they came from.
The register constraint solver has two kinds of variables:

1. Live values that were already in a register, and
2. Values defined by the instruction.

Make a record of the original register holding the first kind of value.
2017-05-11 11:54:02 -07:00
Jakob Stoklund Olesen
21b4c3a00b Simplify the dead EBB argument tracking.
It is not necessary to to a second pass over the live values to update
the set of available registers. The color_args() and color_entry_args()
functions can do that in a single pass.
2017-05-11 11:48:58 -07:00
Jakob Stoklund Olesen
d1390006b1 Always create live ranges for dead EBB arguments.
The live value tracker expects them to be there.

We may eventually delete dead arguments from internal EBBs, but at least
the entry block needs to be able to handle dead function arguments.
2017-05-11 11:42:44 -07:00
Jakob Stoklund Olesen
94944d2057 Keep dead EBB arguments around in LiveValueTracker::ebb_top().
Provide a drop_dead_args() function which deletes them instead.

We still need to assign a register to dead EBB arguments, so they can't
just be ignored.
2017-05-11 11:28:39 -07:00
Jakob Stoklund Olesen
2c0d4136b0 Propagate a few more LiveRange properties to LiveValue.
The live value tracker goes through the trouble of looking up the live
range for each value it tracks. We can cache a few more interesting
properties from the live range in the LiveValue struct.
2017-05-11 11:28:39 -07:00
Jakob Stoklund Olesen
6b4c28d554 Use a constraint solver for register coloring.
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.
2017-05-09 14:48:45 -07:00