Add a DominatorTreePreorder data structure which can be initialized for
a DominatorTree and used for queries involving a pre-order of the
dominator tree.
Print out the pre-order and send it through filecheck in "test domtree"
file tests.
Add a LibCall type which represents runtime library functions that many
be synthesized by Cretonne from pure instructions.
Add a LibCall variant to ExternalName to represent one of these runtime
functions.
Individual compilation passes call the corresponding timing::*()
function and hold on to their timing token while they run. This causes
nested per-pass timing information to be recorded in thread-local
storage.
The --time-passes command line option prints a pass timing report to
stdout.
Get rid of the per-value Vec in the LiveRange data type and use a
bforest::Map instead to represent the live-in intervals for non-local
live ranges.
This has some advantages:
- The memory footprint of a local live range is reduced from 40 to 20
bytes, and
- Clearing the Liveness data structure is now a constant time operation
which doesn't call free().
- The potentially quadratic behavior when computing large live ranges is
controlled by the logarithmic B-tree operations.
This makes the whole LiveRange generic over the program order instead of
having a number of methods that are individually program order-generic.
This makes is possible to have data members that depend on the program
order, as we will shortly.
This also gives us stronger type checking on the public LiveRange
methods which now require a Layout argument, not just any program order.
Change the default value for the "enable_verifier" setting so the
verifier runs unless it is explicitly disabled.
Most projects using Cretonne are best off running the verifier always
until they start caring about compile time performance. Then they can
easily disable the verifier.
* Use imm64 rather than offset32
* Add predicate to enforce signed 32-bit limit to imm
* Remove AdjustSpImm format
* Add encoding tests for adjust_sp_imm
* Adjust use of adjust_sp_imm in Intel prologue_epilogue to match
Like before, we store a redundant EBB with each predecessor instruction
which allows invalidate_ebb_successors() to clean up the successor's
predecessor lists even after instructions have been moved around in the
layout.
Define two public iterator types in the flowgraph module, PredIter and
SuccIter, which are by-value iterators over an EBB's predecessors and
successors respectively.
Provide matching pred_iter() and succ_iter() methods for inspecting the
CFG. Remove the get_predecessors() method which returned a slice.
Update the uses of get_predecessors(), none of which depended on it
being a slice.
This abstraction makes it possible to change the internal representation
of the CFG.
* Treat VMContext as standard positional argument when using Native CallConv.
This requires threading the CallConv through legalize_args and into ArgAssigner.
* Stash CallConv in the intel-specific Args struct, for use ArgAssigner.
This has two advantages over the previous Vec<Ebb>:
- Duplicates are removed.
- Clearing the control flow graph is constant time.
The set of EBB successors is simply ordered by EBB number.
The control flow graph does not guarantee any particular ordering for
its successor lists, and the post-order we are computing for building
the dominator tree needs to be "split-invariant".
See #146 for details.
- Discover EBB successors directly from the EBB instruction sequence to
guarantee that the post-order we compute is canonical/split-invariant.
- Use an alternative graph DFS algorithm which doesn't require indexing
into a slice of successors.
This changes cfg_postorder in some cases because the edge pruning when
converting the (DAG) CFG to a tree for the DFT is different.
The default container is empty. We need a manual implementation of
Default because deriving it seems to imply that K and V generic
parameter types must also implement Default.
Cloning can be used to clone an empty container or for cloning the whole
forest. We can derive this trait because we already require Copy for K
and V.
The iter() methods return an iterator that traverses all set elements /
map key-value pairs. The iterator doesn't require a mutable container
and forest reference, unlike the cursor types.