* 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
* 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.
* 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.
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.
These special-purpose arguments and return values are only relevant for
the function being compiled, so add a `current` flag to
legalize_signature().
- Add the necessary argument values to the entry block to represent
the special-purpose arguments.
- Propagate the link and sret arguments to return instructions if the
legalized signature asks for it.
Enumerate a set of special purposes for function arguments that general
purpose code needs to know about. Some of these argument purposes will
only appear in the signature of the current function, representing
things the prologue and epilogues need to know about like the link
register and callee-saved registers.
Get rid of the 'inreg' argument flag. Arguments can be pre-assigned to a
specific register instead.
- The detach_secondary_results() is a leftover from the two-plane value
representation. Use detach_results() instead to remove all instruction
results.
- Make the append_* DFG methods more direct. Don't depend on calling the
corresponding attach_* methods. Just create a new value directly,
using the values.next_key() trick.
This makes it possible to reuse one or more result values in the
instruction that is being inserted.
Also add a with_result(v) method for the common case of reusing a single
result value. This could be specialized in the future.
These methods are used to reattach detached values:
- change_to_alias
- attach_result
- attach_ebb_arg
Add an assertion to all of them to ensure that the provided value is not
already attached somewhere else. Use a new value_is_attached() method
for the test.
Also include a verifier check for uses of detached values.
All values are now references into the value table, so drop the
distinction between direct and table values. Direct values don't exist
any more.
Also remove the parser support for the 'vxNN' syntax. Only 'vNN' values
can be parsed now.
Soon, InstructionData won't have sufficient information to compute this.
Give TargetIsa::encode() an explicit ctrl_typevar argument. This
function does not require the instruction to be inserted in the DFG
tables.
Since results are in a value list, they don't need to form a linked
list any longer.
- Simplify make_inst_results() to create values in the natural order.
- Eliminate the last use of next_secondary_value().
- Delete unused result manipulation methods.
We only ever create table values now.
Simplify legalizer::legalize_inst_results. Instead of calling
detach_secondary_results, just detach all the results and don't treat
the first result specially.
We don't want to distinguish between single-result and multiple-result
instructions any longer.
- Merge the simple_instruction() and complex_instruction() builder
methods into a single build() that can handle all cases.
- All format constructors now take a ctrl_type argument. Previously,
some would take a result_type argument.
- Instruction constructors no longer attempt to compute a single result
type. Just pass a ctrl_type and let the backend decide.
Fix one format constructor call in legalizer/split.rs which now takes a
ctrl_type instead of a result type.
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.
This is the first step of a larger refactoring to represent instruction
results as value lists instead of using linked lists. The refactoring
will also eliminate the special treatment of first results such that all
result values can be detached and redefined.
This change put us in a temporary state where results are represented
both as linked lists and ValueList vectors.
- Add a dfg.results table.
- Add the first result in make_inst(). This behavior will change.
- Recompute the result list in make_inst_results().
- Make dfg.first_result(inst) crash if the instruction has no results.
- Add a dfg.is_inst_valid() method for the verifier.
- Use the inst_args_mut() method when rewriting values in the parser.
- Add a new branch_destination_mut() to use when rewriting EBBs.
This also gets rid of one of the large instruction format switches in
the parser.
Now that we have a value list of the arguments, we can get rid of:
- The first_arg and last_arg members in EbbData,
- The next member in the ValueData::Arg variant.
Rather than returning the head of a linked list of EBB arguments, just
return the whole value list of all the arguments.
Delete the next_ebb_arg() method which was only used for traversing that
list.
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.
Any *.cton files in the docs directory are now included when running the
test-all.sh script. This is to ensure that the examples are in fact
correct IL.
Always print NaN and Inf floats with a sign. Print the positive ones as
+NaN and +Inf to make them easier to parse.
Compute exact EBB header offsets and check that branches are in range.
Not implemented yet: Relax branches that are not in range.
Invoke the relax_branches() pass from the 'test binemit' file tests so
they can verify the proper encoding of branch instructions too.
This instruction behaves like icmp fused with brnz, and it can be used
to represent fused compare+branch instruction on Intel when optimizing
for macro-op fusion.
RISC-V provides compare-and-branch instructions directly, and it is
needed there too.
Compare a scalar integer to an immediate constant. Both Intel and RISC-V
ISAs have this operation.
This requires the addition of a new IntCompareImm instruction format.
* Verify that a recomputed dominator tree is identical to the existing one.
* The verifier now typechecks instruction results and arguments.
* The verifier now typechecks instruction results and arguments.
* The verifier now typechecks instruction results and arguments.
* Added `inst_{fixed,variable}_args` accessor functions.
* Improved error messages in verifier.
* Type check return statements against the function signature.
Use the meta language encoding recipes to generate an emit_inst()
function for each ISA. The generated calls into recipe_*() functions
that must be implemented by hand.
Implement recipe_*() functions for the RISC-V recipes.
Add the TargetIsa::emit_inst() entry point which emits an instruction to
a CodeSink trait object.
When the legalizer splits a value into halves, it would previously stop
if the value was an EBB argument. With this change, we also split EBB
arguments and iteratively split arguments on branches to the EBB.
The iterative splitting stops when we hit the entry block arguments or
an instruction that isn't one of the concatenation instructions.