Commit Graph

69 Commits

Author SHA1 Message Date
Jakob Stoklund Olesen
268e8e3114 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
b4e785d0f5 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
61a0844b24 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
342121aba0 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
bae37e523f 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
66bc0a9c8b 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
8955b13620 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
f2f162f37e 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
5a23f975fc 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
6381da948f 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
36f189810e 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
96fe287f67 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
d94bd8c236 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
f545c97cb0 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
0c7b2c7b68 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
06afd3b77b 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
09ac27a797 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
ca6eddaf88 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
a2fd9cf0cc Update rustfmt to 0.8.4; (#81) 2017-05-15 15:10:47 -07:00
Jakob Stoklund Olesen
663b50efcc 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
51fc887a5a 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
f8e466d60e 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
4dda3e02f1 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
9f743cf3a5 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
d03a217466 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
9d4e23d894 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
be047ba5c4 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
Jakob Stoklund Olesen
0dbdd90af7 Add a register diversion tracker.
Keep track of the current location of register values as regmove
instructions are encountered throughout an EBB.
2017-05-09 14:48:45 -07:00
Jakob Stoklund Olesen
fedc834ecd Also return live-through values from process_inst().
The coloring algorithm will need to look at the live-through values to
check if they interfere with fixed-register outputs for calls etc.
2017-05-08 13:57:39 -07:00
Jakob Stoklund Olesen
d1d6c626d9 Add a few register utilities. 2017-05-08 13:39:26 -07:00
Jakob Stoklund Olesen
6fe4aa2f8d Extract the topological ordering into a module.
Multiple passes will need to iterate over EBBs in a
dominator-topological order. Move that functionality into a separate
module.
2017-04-27 17:39:58 -07:00
Jakob Stoklund Olesen
962a3a6a5e Upgrade to Rust 1.17.
- Remove some uses of 'static in const and static globals that are no
  longer needed.
- Use the new struct initialization shorthand.
2017-04-27 12:46:44 -07:00
Jakob Stoklund Olesen
4c8eb85f39 Color entry block arguments using the function signature.
The arguments to the entry block arrive in registers determined by the
ABI. This information is stored in the signature.

Use a separate function for coloring entry block arguments using the
signature information. We can't handle stack arguments yet.
2017-04-26 14:38:16 -07:00
Jakob Stoklund Olesen
bb8ae9a4fb Add a TargetIsa::allocatable_registers() method.
This gives the target ISA a chance to reserve registers like the stack
pointer or hard-wired 0 registers like %x0 on RISC-V.
2017-04-26 13:54:40 -07:00
Jakob Stoklund Olesen
1e51f97108 Rename Affinity::Any to Affinity::None.
This value affinity doesn't mean "whatever", it means that the value
does not interact with any real instructions, where "real" means
instructions that have a legal encoding.

Update the liveness verifier to check this property:

- Encoded instructions can only use real values.
- Encoded instructions define real values.
- Ghost instructions define ghost values.
2017-04-26 11:20:17 -07:00
Jakob Stoklund Olesen
2f866171ca Add an Affinity::display() method.
Make it possible to display affinities given a RegInfo reference.
2017-04-26 11:16:38 -07:00
Jakob Stoklund Olesen
93db01d38a Assign an affinity to function argument values.
Use the argument types from the function signature to initialize the
affinity of register and stack arguments.
2017-04-26 10:50:56 -07:00
Eric Anholt
100666e300 Verify that the instruction encoding matches what the ISA would encode.
Fixes #69
2017-04-23 17:21:32 -07:00
Jakob Stoklund Olesen
5d9e703e4f Run the post-regalloc verification inside the regalloc context.
This means that we can verify the basics with verify_context before
moving on to verifying the liveness information.

Live ranges are now verified immediately after computing them and after
register allocation is complete.
2017-04-21 16:25:24 -07:00
Jakob Stoklund Olesen
85f277a2fb Add a liveness verifier.
The liveness verifier will check that the live ranges are consistent
with the function. It runs as part of the register allocation pipeline
when enable_verifier is set.

The initial implementation checks the live ranges, but not the
ISA-specific constraints and affinities.
2017-04-21 16:01:08 -07:00
Jakob Stoklund Olesen
3c99dc0eb4 Change dfg.inst_results to return a slice.
Now we can access instruction results and arguments as well as EBB
arguments as slices.

Delete the Values iterator which was traversing the linked lists of
values. It is no longer needed.
2017-04-11 16:57:15 -07:00
Jakob Stoklund Olesen
ccba325b6c Keep EBB arguments in a ValueList.
This is the first step of the value list refactoring which will replace
linked lists of values with value lists.

- Keep a ValueList in the EbbData struct containing all the EBB
  arguments.
- Change dfg.ebb_args() to return a slice instead of an iterator.

This leaves us in a temporary hybrid state where we maintain both a
linked list and a ValueList vector of the EBB arguments.
2017-04-11 11:36:50 -07:00
Jakob Stoklund Olesen
6ab35e54b8 Move encoding-related information into an EncInfo struct.
The tables returned by recipe_names() and recipe_constraints() are now
collected into an EncInfo struct that is available from
TargetIsa::encoding_info(). This is equivalent to the register bank
tables available fro TargetIsa::register_info().

This cleans of the TargetIsa interface and makes it easier to add
encoding-related information.
2017-04-05 10:07:19 -07:00
Jakob Stoklund Olesen
8353651559 rustfmt 0.8.1 2017-04-05 09:00:11 -07:00
Jakob Stoklund Olesen
f710f13949 Add dfg.inst_args(_mut) methods.
A shortcut for calling arguments() directly that goes with the existing
inst_results() method.
2017-03-23 15:07:22 -07:00
Jakob Stoklund Olesen
f84e218a93 Rename the 'cfg' module to 'flowgraph'.
The 'cfg' name was easy to confuse with 'configuration'.
2017-03-21 15:33:23 -07:00
Jakob Stoklund Olesen
32709a56ca Upgrade to rustfmt 0.8.0.
Lots of changes this time.

Worked around what looks like a rustfmt bug in parse_inst_operands where
a large match was nested inside Ok().
2017-03-14 10:48:05 -07:00
Jakob Stoklund Olesen
f451cf42c8 Simplify the arguments() return type.
Now that variable arguments are always stored in a value list with the
fixed arguments, we no longer need the arcane [&[Value]; 2] return type.

Arguments are always stored contiguously, so just return a &[Value]
slice.

Also remove the each_arg() methods which were just trying to make it
easier to work with the old slice pair.
2017-03-09 22:09:22 -08:00
Jakob Stoklund Olesen
1135a89af9 Convert the Branch and Jump instruction formats to value_list.
The Branch format also stores its fixed argument in the value list. This
requires the value pool to be passed to a few more functions.

Note that this actually makes the Branch and Jump variants of
InstructionData identical. The instruction format hashing does not yet
understand that all value operands are stored in the value list. We'll
fix that in a later patch.

Also convert IndirectCall, noting that Call and IndirectCall remain
separate instruction formats because they have different immediate
fields.
2017-03-09 15:38:12 -08:00
Jakob Stoklund Olesen
364b8e5f0a Use value lists for call arguments.
Add a new kind of instruction format that keeps all of its value
arguments in a value list. These value lists are all allocated out of
the dfg.value_lists memory pool.

Instruction formats with the value_list property set store *all* of
their value arguments in a single value list. There is no distinction
between fixed arguments and variable arguments.

Change the Call instruction format to use the value list representation
for its arguments.

This change is only the beginning. The intent is to eliminate the
boxed_storage instruction formats completely. Value lists use less
memory, and when the transition is complete, InstructionData will have a
trivial Drop implementation.
2017-03-09 14:34:07 -08:00