* module/language/tree-il/optimize.scm (make-optimizer): If the keyword
argument #:dump-optimized-tree-il? is present, print the Tree-IL that
will be handed to the next compiler. Also re-enable #:verify-tree-il?.
Can help reduce case-lambda* / lambda* at Tree-IL optimization-time.
* module/language/tree-il/demux-lambda.scm: New file.
* am/bootstrap.am (SOURCES): Add new file.
* module/language/tree-il/optimize.scm (make-optimizer):
* module/system/base/optimize.scm (available-optimizations): Enable
demux-lambda at level 2.
* am/bootstrap.am (SOURCES):
* module/Makefile.am (SOURCES):
* module/language/tree-il/optimize.scm (make-optimizer): Wire up the new
pass.
* module/language/tree-il/resolve-free-vars.scm: New pass.
* module/system/base/optimize.scm (available-optimizations): Enable new
pass at -O1.
* module/language/tree-il/optimize.scm (make-optimizer): New procedure,
to compute an optimizer given options, lazily loading optimization
modules.
(optimize): Use make-optimizer.
(make-lowerer): Use make-optimizer, so as to only load needed
optimizations. Speeds up bootstrap times.
* module/language/cps/optimize.scm (define-optimizer):
(optimize-higher-order-cps, optimize-first-order-cps):
(make-cps-lowerer):
* module/language/tree-il/optimize.scm (optimize, make-lowerer): In an
embarrassing bug, after parsing optimization arguments, we were
aconsing them instead of the expected cons*. This meant the bootstrap
was running all Tree-IL optimizations! Change to have optimizers not
have defaults and use alists after parsing.
* module/language/cps/optimize.scm (cps-optimizations):
* module/language/tree-il/optimize.scm (tree-il-optimizations):
* module/system/base/optimize.scm (available-optimizations): Invert the
dependency tree to hold the names and default optimization levels in a
central place instead of in the optimizers. It moves definitions
farther from uses, but it avoids us having to load the CPS optimizer
if we don't need it, which improves bootstrap times.
* module/language/cps/compile-bytecode.scm (compile-bytecode):
* module/language/tree-il/compile-bytecode.scm (compile-bytecode):
* module/language/tree-il/compile-cps.scm (compile-cps): Rely on
compiler to lower incoming term already.
* module/language/tree-il/optimize.scm (make-lowerer): New procedure.
* module/system/base/compile.scm (compute-lowerer): New procedure,
replaceing add-default-optimizations.
(compute-compiler): Lower before running compiler.
* module/system/base/language.scm (<language>): Change
optimizations-for-level field to "lowerer".
* module/scripts/compile.scm (%options, compile): Parse -O0, -O1 and so
on to #:optimization-level instead of expanding to all the
optimization flags.
* module/language/cps/optimize.scm (lower-cps): Move here from
compile-bytecode.scm.
(make-cps-lowerer): New function.
* module/language/cps/spec.scm (cps): Declare lowerer.
* module/language/tree-il/letrectify.scm (compute-private-toplevels):
New function; computes the subset of declarative bindings that are
private to a module. If the module exports a macro, all bindings are
public, as we have no way to know what binding might be exported.
(letrectify): Add #:seal-private-bindings? keyword arg. If true, avoid
making boxes for private definitions.
* module/language/tree-il/optimize.scm (optimize): Add
-Oseal-private-bindings, enabled at -O3.
* doc/ref/api-evaluation.texi (Compilation): Document the -O options.
* doc/ref/api-modules.texi (Using Guile Modules): @@ docs refer to
declarative modules.
(Creating Guile Modules): Use when for 1-armed if.
(Declarative Modules): Make implications of declarative bindings more
explicit, and explicitly document ways to disable the optimization.
* module/language/tree-il/optimize.scm (tree-il-optimizations): Punt
letrectification to -O2.
* module/language/tree-il/optimize.scm (optimize): Change to run
fix-letrec before peval. Also, run it unconditionally, so that later
passes don't have to deal with letrec.
* module/language/tree-il/peval.scm (build-var-table, peval): Remove
letrec cases.
* module/language/tree-il/optimize.scm (optimize): Disable
resolve-primitives below -O2. This is because compile-cps is going to
start expanding all primcalls it sees.
* module/system/base/optimize.scm: New module.
* module/Makefile.am (SOURCES):
* am/bootstrap.am (SOURCES): Add new module.
* module/language/tree-il/optimize.scm (tree-il-optimizations): Rename
from tree-il-default-optimization-options. Directly specify the
optimization level at which a pass should be enabled.
* module/language/cps/optimize.scm (cps-optimizations): Likewise, rename
from cps-default-optimization-options.
* module/scripts/compile.scm (%options, show-optimization-help): Adapt
to use new module.
* module/scripts/compile.scm (%options): Resurrect -O option and make it
follow GCC, more or less. The default is equivalent to -O2.
* module/language/cps/compile-bytecode.scm (lower-cps):
* module/language/cps/optimize.scm (optimize-higher-order-cps): Move
split-rec to run unconditionally for now, as closure conversion fails
without it.
(define-optimizer): Only verify the result if we are debugging, to
save time.
(cps-default-optimization-options): New exported procedure.
* module/language/tree-il/optimize.scm
(tree-il-default-optimization-options): New exported procedure.
* module/language/tree-il.scm (pre-order): Re-implement in terms of
pre-post-order, and rename from pre-order!.
* module/language/tree-il/primitives.scm (expand-primitives): Adapt to
pre-order change, and rename from expand-primitives!.
* module/language/tree-il/optimize.scm (optimize): Adapt to
expand-primitives! change, and rename from optimize!.
* module/language/tree-il/compile-glil.scm:
* module/system/repl/common.scm:
* test-suite/tests/cse.test:
* test-suite/tests/peval.test:
* test-suite/tests/tree-il.test: Adapt to expand-primitives and optimize
changes.
* module/language/tree-il.scm (pre-post-order): New helper, like
pre-order! and post-order! but not destructive.
(post-order): Implement in terms of pre-post-order, and rename from
post-order!.
* module/ice-9/compile-psyntax.scm (squeeze-tree-il):
* module/language/tree-il/canonicalize.scm (canonicalize):
* module/language/tree-il/fix-letrec.scm (fix-letrec):
* module/language/tree-il/primitives.scm (resolve-primitives): Use
post-order, and rename from the destructive
variants (squeeze-tree-il!, canonicalize!, etc). Adapt callers.
* test-suite/tests/tree-il.test (strip-source): Adapt to post-order.
* test-suite/tests/cse.test:
* test-suite/tests/peval.test:
* module/language/tree-il/optimize.scm: Adapt callers.
* module/language/tree-il/peval.scm: Move to its own file. Remove the
bits about <prompt> thunk-application bodies, as they are not
optimizations, simply expectations of the compiler. `canonicalize'
handles that now.
* module/language/tree-il/optimize.scm: Use peval from its module.
Don't call `inline!', as that's useless now.
* module/language/tree-il/canonicalize.scm: New file, implementing a
pass that `compile-tree-il' runs on the result from the optimizer.
The compiler currently expects a <let> form to have bindings, for
example, and this pass turns a <let> without bindings into its body.
* module/language/tree-il/inline.scm: Deprecate, as `peval' does
everything this function ever did.
* module/language/tree-il/compile-glil.scm: Canonicalize after
optimizing. This should allow us to skip the optimizer entirely, if
we want.
* module/Makefile.am: Update and reorder a little bit.
* module/language/tree-il/optimize.scm (peval): If it's a lambda in the
operator position, inline without a nested counter, as it's not
possible to increase code size.
* module/language/tree-il/optimize.scm (peval): Factor prune-bindings
out of `let' and company. Have it process unreferenced bindings in
effect context instead of always residualizing non-constant
expressions.
* module/language/tree-il/optimize.scm (types-check?): New helper, to
determine if a primcall will apply without throwing an exception.
(peval): constant-expression? returns #f for expressions that don't
types-check?. Effect-free primitives that type-check are void.
* module/language/tree-il/optimize.scm (alpha-rename, peval): Add
<dynset> cases. Allow any kind of <application>. Remove the `catch'
wrapper as now peval handles all kinds of expressions.
* module/language/tree-il/optimize.scm (peval): Fix a duplicate
traversal for constructors in effect or test context. Add support for
eliding make-prompt-tag.
* test-suite/tests/tree-il.test ("partial evaluation"): Update the test
for make-prompt-tag elision.
* module/language/tree-il/optimize.scm (alpha-rename, peval): Handle
<prompt> and <abort>. Attempt to remove the prompt if the tag is
otherwise unreferenced.
* module/language/tree-il/primitives.scm (*primitive-constructors*): Add
make-prompt-tag as a constructor.
* test-suite/tests/tree-il.test ("partial evaluation"): Add a test that
an prompt whose tag is unreferenced is removed.
* module/language/tree-il/optimize.scm (peval): Fix treatment of `cons'
to not process the value twice, leading to n^2 work. This prevented
primitives.scm from compiling in a reasonable amount of time, because
it contained a `(foo ... ,@bar) form that resulted in a long sequence
of nested conses, and no effort counter was in place as it was not
within an inlining attempt.
* module/language/tree-il/optimize.scm (transfer!, make-nested-counter):
(make-recursive-counter, peval): Limit the algorithm's time to be
strictly O(N) by transferring effort and size counters of recursive
inlining attempts from containing counters.
* test-suite/tests/tree-il.test ("partial evaluation"): Update
expectations for the ((lambda (x) (x x)) (lambda (x) (x x))) case, as
the new accounting policy will cause the entire inlining attempt to
abort.
* module/language/tree-il/optimize.scm (peval): Fix calculation of how
many init expressions to drop when inlining lambdas.
* test-suite/tests/tree-il.test ("partial evaluation"): Add tests.
* module/language/tree-il/optimize.scm (peval): The old approach of
optimistically producing constants and then de-constifying them at
their uses was not only cumbersome but incorrect: it both failed to
preserve identity in some cases and failed to retain immutable
constant values. Instead, now we only produce constants if they
really are constant and immutable. The constant folder has to have a
few more algebraic cases to be as effective as it was, to destructure
(car (cons _ _)) appropriately. On the plus side, now constructors
and deconstructors can handle impure cases more generally.
* test-suite/tests/tree-il.test ("partial evaluation"): Add constructor
and destructuring tests. Adapt other tests to new expectations.
* module/language/tree-il/optimize.scm (peval): Add missing
maybe-unconst calls. Things are getting ugly. They will get better
in the next commit though.
* module/language/tree-il/optimize.scm (code-contains-calls?): Remove
this helper, we will deal with recursion when it happens, not after
the fact.
(peval): Add keyword args for various size and effort limits. Instead
of keeping a call stack, keep a chain of <counter> records, each with
an abort continuation. If ever an inlining attempt is taking too
long, measured in terms of number of trips through the main loop, the
counter will abort. Add new contexts, `operator' and `operand'. They
have different default size limits. In the future we should actually
use the size counter, instead of these heuristics.
The <lexical-ref> case is smarter now, and tries to avoid propagating
too much data. Perhaps it should be dumber though, and use a
counter. That would require changes to the environment structure.
Inline <lambda> applications to <let>, so that we allow residual
lexical references to have bindings. Add a `for-operand' helper, and
use it for the RHS of `let' expressions. A `let' is an inlined
`lambda'.
`Let' and company no longer elide bindings if the result is a
constant, as the arguments could have effects. Peval will still do as
much as it can, though.
* test-suite/tests/tree-il.test ("partial evaluation"): Update the tests
for the new expectations. They are uniformly awesomer, with the
exception of two cases in which pure but not constant data is not
propagated.
* module/language/tree-il/optimize.scm (peval): Rename `var-table' to
`store', as we're going to put some more things in it. Rename
`record-lexical-bindings' to `record-source-expression', which also
takes the original, pre-renaming expression. Keep a mapping from new
expressions to original expressions, available using the
`source-expression' helper.
* module/language/tree-il/optimize.scm (<counter>, abort-counter)
(record-effort!, record-size!, find-counter, make-top-counter)
(make-nested-counter, make-recursive-counter): New helpers, as yet
unused, but which will implement fixed effort bounds on the inlining
algorithm.
* module/language/tree-il/optimize.scm (peval): Rename `record-lexicals'
to `record-lexical-bindings'. Record residualized lexical
references. Record lexical references in maybe-unlambda.
Unfortunately this has the disadvantage that the speculative mapping
of lambda expressions to lexical references records that reference,
even if we are not going to residualize it. After processing a `let',
prune pure unreferenced bindings. (We can do better than this in the
future: we can simply process them for effect.)
* test-suite/tests/tree-il.test (pass-if-peval): More debugging.
("partial evaluation"): Update to reflect the fact that the `y'
binding won't be emitted.
* module/language/tree-il/optimize.scm (alpha-rename, peval): Add
support for lexical-set, while avoiding copy propagation and pruning
of assigned variables.
* module/language/tree-il/optimize.scm (<var>, build-var-table, peval):
Before going into peval, build a table indicating refcounts and a set?
flag for all lexicals. Add to the table when introducing new bindings
(via alpha-renaming).
* module/language/tree-il/optimize.scm (peval): Rename
`pure-expression?' to `constant-expression?', in the sense of GCC's
`pure' and `const'. A <toplevel-ref> is not constant, because it can
be mutated. A <dynref> isn't constant either, for the same reason.
* test-suite/tests/tree-il.test ("partial evaluation"): Add a test, and
update existing tests that assumed that toplevel-ref would propagate.
* module/language/tree-il/optimize.scm (peval): Add a "test" context,
which folds statically decidable values to <const>. Fold pure
expressions to <void> in "effect" contexts. Adapt the <conditional>
and <sequence> tests to simply look for <const> or <void> expressions,
respectively.
* module/language/tree-il/optimize.scm (alpha-rename): Rename the
init
expressions of a <lambda-case>.
(peval): Coalesce the <let-values> clauses.
Fix pure-expression? matching of <lambda> clauses.
Loop over and maybe-unconst the inits of a <lambda-case>.