[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Guile-commits] 01/01: Letrectify only on -O2; update docs
From: |
Andy Wingo |
Subject: |
[Guile-commits] 01/01: Letrectify only on -O2; update docs |
Date: |
Sun, 25 Aug 2019 06:53:01 -0400 (EDT) |
wingo pushed a commit to branch master
in repository guile.
commit 31cb10af81f78590dc7da530455aab38727dcc94
Author: Andy Wingo <address@hidden>
Date: Sun Aug 25 12:51:03 2019 +0200
Letrectify only on -O2; update docs
* 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.
---
doc/ref/api-evaluation.texi | 11 +++++
doc/ref/api-modules.texi | 84 +++++++++++++++++++++++++++++++++---
module/language/tree-il/optimize.scm | 7 ++-
3 files changed, 96 insertions(+), 6 deletions(-)
diff --git a/doc/ref/api-evaluation.texi b/doc/ref/api-evaluation.texi
index cfae07f..bcebacf 100644
--- a/doc/ref/api-evaluation.texi
+++ b/doc/ref/api-evaluation.texi
@@ -675,6 +675,17 @@ warnings include @code{unused-variable},
@code{unused-toplevel},
@code{arity-mismatch}, @code{format},
@code{duplicate-case-datum}, and @code{bad-case-datum}.
+@item -O @var{opt}
+@itemx --optimize=@var{opt}
+@cindex optimizations, compiler
+Enable or disable specific compiler optimizations; use @code{-Ohelp} for
+a list of available options. The default is @code{-O2}, which enables
+most optimizations. @code{-O1} is recommended if compilation speed is
+more important than the speed of the compiled code. Pass
+@code{-Ono-@var{opt}} to disable a specific compiler pass. Any number
+of @code{-O} options can be passed to the compiler, with later ones
+taking precedence.
+
@item -f @var{lang}
@itemx --from=@var{lang}
Use @var{lang} as the source language of @var{file}. If this option is
omitted,
diff --git a/doc/ref/api-modules.texi b/doc/ref/api-modules.texi
index eb8cc1a..d73df46 100644
--- a/doc/ref/api-modules.texi
+++ b/doc/ref/api-modules.texi
@@ -240,7 +240,8 @@ Refer to the binding named @var{binding-name} in module
Refer to the binding named @var{binding-name} in module
@var{module-name}. The binding must not have been exported by the
module. This syntax is only intended for debugging purposes or as a
-last resort.
+last resort. @xref{Declarative Modules}, for some limitations on the
+use of @code{@@@@}.
@end deffn
@node Creating Guile Modules
@@ -290,8 +291,8 @@ example,
(define-module (my mod)
#:autoload (srfi srfi-1) (partition delete-duplicates))
...
-(if something
- (set! foo (delete-duplicates ...)))
+(when something
+ (set! foo (delete-duplicates ...)))
@end example
When a module is autoloaded, all its bindings become available.
@@ -922,7 +923,7 @@ However, as Scheme godparent Mathias Felleisen wrote in
``On the
Expressive Power of Programming Languages'', a more expressive language
is necessarily harder to reason about. There are transformations that
Guile's compiler would like to make which can't be done if every
-top-level binding is subject to mutation at any time.
+top-level definition is subject to mutation at any time.
Consider this module:
@@ -946,6 +947,9 @@ text. However, in the general case it could be that a
programmer could
reach into the @code{(boxes)} module at any time and change the value of
@code{box-ref}.
+@cindex declarative
+@cindex modules, declarative
+@cindex definitions, declarative
To allow Guile to reason about the values of top-levels from a module, a
module can be marked as @dfn{declarative}. This flag applies only to
the subset of top-level definitions that are themselves declarative:
@@ -965,7 +969,7 @@ By default, modules are compiled declaratively if the
@code{user-modules-declarative?} parameter is true when the
module is compiled.
-@deffn {Scheme Parameter} user-modules-declarative-by-default?
+@deffn {Scheme Parameter} user-modules-declarative?
A boolean indicating whether definitions in modules created by
@code{define-module} or implicitly as part of a compilation unit without
an explicit module can be treated as declarative.
@@ -974,6 +978,76 @@ an explicit module can be treated as declarative.
Because it's usually what you want, the default value of
@code{user-modules-declarative?} is @code{#t}.
+@subsubheading Should I Mark My Module As Declarative?
+
+In the vast majority of use cases, declarative modules are what you
+want. However, there are exceptions.
+
+Consider the @code{(boxes)} module above. Let's say you want to be able
+to go in and change the definition of @code{box-set!} at run-time:
+
+@example
+scheme@@(guile-user)> (use-modules (boxes))
+scheme@@(guile-user)> ,module boxes
+scheme@@(boxes)> (define (box-set! x y) (set-car! x (pk y)))
+@end example
+
+However, considering that @code{(boxes)} is a declarative module, it
+could be that @code{box-swap!} inlined the call to @code{box-set!} -- so
+it may be that you are surprised if you call @code{(box-swap! x y)} and
+you don't see the new definition being used. (Note, however, that Guile
+has no guarantees about what definitions its compiler will or will not
+inline.)
+
+If you want to allow the definition of @code{box-set!} to be changed and
+to have all of its uses updated, then probably the best option is to
+edit the module and reload the whole thing:
+
+@example
+scheme@@(guile-user)> ,reload (boxes)
+@end example
+
+The advantage of the reloading approach is that you maintain the
+optimizations that declarative modules enable, while also being able to
+live-update the code. If the module keeps precious program state, those
+definitions can be marked as @code{define-once} to prevent reloads from
+overwriting them. @xref{Top Level}, for more on @code{define-once}.
+Incidentally, @code{define-once} also prevents declarative-definition
+optimizations, so if there's a limited subset of redefinable bindings,
+@code{define-once} could be an interesting tool to mark those
+definitions as works-in-progress for interactive program development.
+
+To users, whether a module is declarative or not is mostly immaterial:
+besides normal use via @code{use-modules}, users can reference and
+redefine public or private bindings programmatically or interactively.
+The only difference is that changing a declarative definition may not
+change all of its uses. If this use-case is important to you, and if
+reloading whole modules is insufficient, then you can mark all
+definitions in a module as non-declarative by adding
+@code{#:declarative? #f} to the module definition.
+
+The default of whether modules are declarative or not can be controlled
+via the @code{(user-modules-declarative?)} parameter mentioned above,
+but care should be taken to set this parameter when the modules are
+compiled, e.g. via @code{(eval-when (expand) (user-modules-declarative?
+#f))}. @xref{Eval When}.
+
+Alternately you can prevent declarative-definition optimizations by
+compiling at the @code{-O1} optimization level instead of the default
+@code{-O2}, or via explicitly passing @code{-Ono-letrectify} to the
+@code{guild compile} invocation. @xref{Compilation}, for more on
+compiler options.
+
+@cindex inlining
+One final note. Currently, definitions from declarative modules can
+only be inlined within the module they are defined in, and within a
+compilation unit. This may change in the future to allow Guile to
+inline imported declarative definitions as well (cross-module inlining).
+To Guile, whether a definition is inlinable or not is a property of the
+definition, not its use. We hope to improve compiler tooling in the
+future to allow the user to identify definitions that are out of date
+when a declarative binding is redefined.
+
@node Accessing Modules from C
@subsection Accessing Modules from C
diff --git a/module/language/tree-il/optimize.scm
b/module/language/tree-il/optimize.scm
index 2f89f73..c252e54 100644
--- a/module/language/tree-il/optimize.scm
+++ b/module/language/tree-il/optimize.scm
@@ -59,7 +59,12 @@
;; Avoid resolve-primitives until -O2, when CPS optimizations kick in.
;; Otherwise, inlining the primcalls during Tree-IL->CPS compilation
;; will result in a lot of code that will never get optimized nicely.
+ ;; Similarly letrectification is great for generated code quality, but
+ ;; as it gives the compiler more to work with, it increases compile
+ ;; time enough that we reserve it for -O2. Also, this makes -O1 avoid
+ ;; assumptions about top-level values, in the same way that avoiding
+ ;; resolve-primitives does.
'((#:resolve-primitives? 2)
(#:expand-primitives? 1)
- (#:letrectify? 1)
+ (#:letrectify? 2)
(#:partial-eval? 1)))