1
0
mirror of https://github.com/catseye/SixtyPical.git synced 2024-11-22 17:32:01 +00:00

Flesh out and describe the fallthru optimization algorithm.

This commit is contained in:
Chris Pressey 2018-04-04 10:15:06 +01:00
parent 237a8b5b39
commit 2be4406964
2 changed files with 44 additions and 10 deletions

View File

@ -78,16 +78,6 @@ are trashed inside the block.
Not because it saves 3 bytes, but because it's a neat trick. Doing it optimally
is probably NP-complete. But doing it adequately is probably not that hard.
> Every routine is falled through to by zero or more routines.
> Don't consider the main routine.
> For each routine α that is finally-falled through to by a set of routines R(α),
> pick a movable routine β from R, move β in front of α, remove the `jmp` at the end of β and
> mark β as unmovable.
> Note this only works if β finally-falls through. If there are multiple tail
> positions, we can't eliminate all the `jmp`s.
> Note that if β finally-falls through to α it can't finally-fall through to anything
> else, so the sets R(α) should be disjoint for every α. (Right?)
### And at some point...
* `low` and `high` address operators - to turn `word` type into `byte`.

View File

@ -5,6 +5,50 @@ This is a test suite, written in [Falderal][] format, for SixtyPical's
ability to detect which routines make tail calls to other routines,
and thus can be re-arranged to simply "fall through" to them.
The theory is as follows.
SixtyPical supports a `goto`, but it can only appear in tail position.
If a routine r1 ends with a unique `goto` to a fixed routine r2 it is said
to *potentially fall through* to r2.
A *unique* `goto` means that there are not multiple different `goto`s in
tail position (which can happen if, for example, an `if` is the last thing
in a routine, and each branch of that `if` ends with a different `goto`.)
A *fixed* routine means, a routine which is known at compile time, not a
`goto` through a vector.
Consider the set R of all routines in the program.
Every routine r1 ∈ R either potentially falls through to a single routine
r2 ∈ R (r2 ≠ r1) or it does not potentially fall through to any routine.
We can say out(r1) = {r2} or out(r1) = ∅.
Every routine r ∈ R in this set also has a set of zero or more
routines from which it is potentially falled through to by. Call this
in(r). It is the case that out(r1) = {r2} → r1 ∈ in(r2).
We can trace out the connections by following the in- or our- sets of
a given routine. Because each routine potentially falls through to only
a single routine, the structures we find will be tree-like, not DAG-like.
But they do permit cycles.
So, we first break those cycles. We will be left with out() sets which
are disjoint trees, i.e. if r1 ∈ in(r2), then r1 ∉ in(r3) for all r3 ≠ r2.
We then follow an algorithm something like this. Treat R as a mutable
set and start with an empty list L. Then,
- Pick a routine r from R where out(r) = ∅.
- Find the longest chain of routines r1,r2,...rn in R where out(r1) = {r2},
out(r2} = {r3}, ... out(rn-1) = {rn}, and rn = r.
- Remove (r1,r2,...,rn) from R and append them to L in that order.
Mark (r1,r2,...rn-1) as "will have their final `goto` removed."
- Repeat until R is empty.
When times comes to generate code, generate it in the order given by L.
[Falderal]: http://catseye.tc/node/Falderal
-> Functionality "Dump fallthru map of SixtyPical program" is implemented by