Commit Graph

2269 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
Dan Gohman
e094389f12 Add a simple_gvn test that includes some basic control flow. 2017-06-22 14:34:21 -07:00
Jakob Stoklund Olesen
9e02b9818f Encode iconst.i32 for RISC-V.
For large constants with the low 12 bits clear, we already have the
"lui" encoding. Add "addi %x0" encodings for signed 12-bit constants.
2017-06-22 12:13:37 -07:00
Dan Gohman
e83e2ccf17 Documentation fixes (#103)
* Clarify that extended basic blocks are abbreviated as EBB.

* Fix typo.

* Fix a typo.

* Fix typos.

* Use the same phrase to indicate scalar-only as other places in the doc.

* Mention that `band_imm` and friends are scalar-only.

And mention that they're equivalent to their respective
non-immediate-form counterparts.
2017-06-22 12:01:32 -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
Aleksey Kuznetsov
1a480a2578 Implement an iterator over encodings (#96)
* Implement an iterator over encodings

* Implement TargetIsa::legal_encodings

* Exclude non-boolean settings of isa flags bytes

* Address flake8 long line error
2017-06-19 08:52:19 -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
a4cc66cb4a Add a stack frame manager.
Use a new StackSlots struct to keep track of a function's stack slots
instead of just an entity map. This let's us build more internal data
structures for tracking the stack slots if necessary.

Start by adding a make_spill_slot() function that will be used by the
register allocator.
2017-06-16 11:55:44 -07:00
Jakob Stoklund Olesen
91d919c11a Track stack slot kinds.
Add a StackSlotKind enumeration to help keep track of the different
kinds of stack slots supported:

- Incoming and outgoing function arguments on the stack.
- Spill slots and locals.

Change the text format syntax for declaring a stack slot to use a kind
keyword rather than just 'stack_slot'.
2017-06-16 11:01:22 -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
9eb0778f9b Add RISC-V encodings for call_indirect. 2017-06-14 16:14:16 -07:00
Jakob Stoklund Olesen
66af915eed Add RISC-V encodings for copy instructions. 2017-06-14 15:36:25 -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
e7c6efa31e Update docopt dependency to 0.8.0.
This breaks our depending on two different versions of the regex
library.

This updated docopt uses serde instead of rustc_serialize.
2017-06-14 10:38:06 -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
00551dbc5f Add RISC-V encodings for spill and fill.
Add a Stack() class for specifying operand constraints for values on the
stack.

Add encoding recipes for RISC-V spill and fill instructions. Don't
implement the encoding recipe functions yet since we don't have the
stack slot layout yet.
2017-06-13 13:39:52 -07:00
Jakob Stoklund Olesen
2875c6ddf9 Remove the ebb_dominates function.
This is now subsumed by the generic 'dominates' function.
2017-06-12 14:59:34 -07:00
Jakob Stoklund Olesen
d2dc7232c2 Generalize DominatorTree::dominates.
This is now a generic function that can test arbitrary combinations of
instructions and EBBs for dominance.

It can handle anything that converts into an expanded program point,
including a ValueDef.

Also fix a bug if the earlier dominates() function which didn't properly
handle block layouts that were not topologically ordered.
2017-06-12 14:52:42 -07:00
Jakob Stoklund Olesen
9090bbda24 Generalize rpo_cmp to handle all program points.
When comparing instructions in the same EBB, behave like the RPO visits
instructions in program order.

- Add a Layout::pp_ebb() method for convenience. It gets the EBB
  containing any program point.
- Add a conversion from ValueDef to ExpandedProgramPoint so it can be
  used with the rpo_cmp method.
2017-06-12 14:11:15 -07:00
Aleksey Kuznetsov
8b484b1c77 Binary function names (#91)
* Function names should start with %

* Create FunctionName from string

* Implement displaying of FunctionName as %nnnn with fallback to #xxxx

* Run rustfmt and fix FunctionName::with_string in parser

* Implement FunctionName::new as a generic function

* Binary function names should start with #

* Implement NameRepr for function name

* Fix examples in docs to reflect that function names start with %

* Rebase and fix filecheck tests
2017-06-10 10:30:37 -07:00
Denis Merigoux
731278aad8 Improved DFG API (#95)
* Improved DFG API with swap_remove_ebb_args and append_inst_arg
* Implemented EntityList::swap_remove
And used it for dfg::swap_remove_ebb_arg
2017-06-09 16:20:38 -07:00
Denis Merigoux
dacc4003a3 LICM pass: small changes after code review (#94) 2017-06-08 09:41:57 -07:00
Jakob Stoklund Olesen
eec980618b Remove cfg.postorder_ebbs().
This is now unused. Use domtree.cfg_postorder() instead.

Also remove the dead cfg.ebbs().
2017-06-07 13:46:03 -07:00
Jakob Stoklund Olesen
94872cc971 Stop using cfg.postorder_ebbs().
Switch to the new domtree.cfg_postorder() which returns a reference to a
pre-computed post-order instead of allocating memory and computing a new
post-order.
2017-06-07 13:38:27 -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
ac1db6e3c9 Implement a conversion from ValueDef into ProgramPoint.
A ValueDef is really no more than a program point plus an
argument/result number.
2017-06-07 11:58:08 -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
Denis Merigoux
9b06f76057 LICM pass (#87)
* LICM pass

* Uses loop analysis to detect loop tree
* For each loop (starting with the inner ones), create a pre-header and move there loop-invariant instructions
* An instruction is loop invariant if it does not use as argument a value defined earlier in the loop
* File tests to check LICM's correctness
* Optimized pre-header creation
If the loop already has a natural pre-header, we use it instead of creating a new one.
The natural pre-header of a loop is the only predecessor of the header it doesn't dominate.
2017-06-07 11:27:22 -07:00
Jakob Stoklund Olesen
2d8588d72a Add a dfg::replace_result() method.
This is analogous to replace_ebb_arg(). It replaces an instruction
result value with a new value, leaving the old value in a detached
state.
2017-06-07 09:53:27 -07:00
Igor
90958729fa Updated the regex crate to 0.2.2 as per issue #88 (#90)
* Updated the regex crate to 0.2.2 as per issue #88
* Added potential fix for cryptic CI error.
* Fixed incorrect handling of regex name call.

Fixes #88
2017-06-03 12:40:53 -07:00
Aleksey Kuznetsov
80d92ccbb5 Run rustfmt on lib/filecheck/tests/basic.rs 2017-06-03 10:00:07 -07:00
Aleksey Kuznetsov
920e32ed49 Move lib/filecheck/src/tests directory to lib/filecheck 2017-06-03 10:00:07 -07:00
Jakob Stoklund Olesen
22ad3c0bf8 Compute a CFG post-order when building the dominator tree.
The DominatorTree has existing DomNodes per EBB that can be used in lieu
of expensive HastSets for the depth-first traversal of the CFG.

Make the computed and cached post-order available for other passes
through the `cfg_postorder()` method which returns a slice.

The post-order algorithm is essentially the same as the one in
ControlFlowGraph::postorder_ebbs(), except it will never push a
successor node that has already been visited once. This is more
efficient, but it generates a different post-order.

Change the cfg_traversal tests to check this new algorithm.
2017-06-02 16:39:18 -07:00
Denis Merigoux
7d6113e479 Loop analysis of the IL
* Implemented in two passes
* First pass discovers the loops headers (they dominate one of their predecessors)
* Second pass traverses the blocks of each loop
* Discovers the loop tree structure
* Offers a new LoopAnalysis data structure queried from outside the module
2017-06-02 15:30:45 -07:00
Aleksey Kuznetsov
cb35869803 Remove unnecessary cloned() in reader::lexer::trailing_digits() 2017-06-02 10:29:13 -07:00
Dan Gohman
059845880c Fix more GVN issues (#83)
* Fix GVN skipping the instruction after a deleted instruction.

* Teach GVN to resolve aliases as it proceeds.

* Clean up an obsolete reference to extended_values.
2017-05-25 16:37:31 -07:00
Dan Gohman
dc809628f4 Start a very simple GVN pass (#79)
* Skeleton simple_gvn pass.
* Basic testing infrastructure for simple-gvn.
* Add can_load and can_store flags to instructions.
* Move the replace_values function into the DataFlowGraph.
* Make InstructionData derive from Hash, PartialEq, and Eq.
* Make EntityList's hash and eq functions panic.
* Change Ieee32 and Ieee64 to store u32 and u64, respectively.
2017-05-18 18:18:57 -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
66d2c0a95a Add a RegClassMask typedef and a MAX_TOPRCS constant.
Avoid spreading u32 as a bitmask of register classes throughout the
code.

Enforce the limit of 32 register classes total. This could easily be
raised if needed.

The MAX_TOPRCS constant is the highest possible number of top-level
register classes in an ISA. The RegClassData.toprc field is always
smaller than this limit.
2017-05-15 16:22:22 -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
0694384728 Generate Intel encoding recipes on demand.
Cretonne's encoding recipes need to have a fixed size so we can compute
accurate branch destination addresses. Intel's instruction encoding has
a lot of variance in the number of bytes needed to encode the opcode
which leads to a number of duplicated encoding recipes that only differ
in the opcode size.

Add an Intel-specific TailEnc Python class which represents an
abstraction over a set of recipes that are identical except for the
opcode encoding. The TailEnc can then generate specific encoding recipes
for each opcode format.

The opcode format is a prefix of the recipe name, so for example, the
'rr' TailEnc will generate the 'Op1rr', 'Op2rr', 'Mp2rr' etc recipes.

The TailEnc class provides a __call__ implementation that simply takes
the sequence of opcode bytes as arguments. It then looks up the right
prefix for the opcode bytes.
2017-05-14 11:53:44 -07:00