Currently in Gambit there are two ways to achieve whole program optimization.
The first is to conceptually concatenate all modules by using a file that contains “include”s of all the modules. This has the advantage of exposing all definitions to the inliner, and to allow the tree-shaker to eliminate the useless code. This obviously gives a relatively slow compilation, but the best code specialization because the compiler “sees the whole code base”.
The second method is to use the “core” declaration (which is undocumented). When a toplevel definition is in the scope of a (not core) declaration, it will not generate any code per-se, but the definition is remembered so that the definition can be inlined in the rest of the program. For example:
% cat mod.scm ;; File: mod.scm
(define (twice x) (declare (standard-bindings) (fixnum) (not safe)) (+ x x))
(define (cube y) (declare (standard-bindings) (fixnum) (not safe)) (* y y y))
% cat prog.scm ;; File: prog.scm
(declare (block) (not core)) (include "mod.scm") (declare (core))
(println (cube (twice (read))))
% gsc -c -expansion prog.scm Expansion:
(println (let ((y (let ((x (read))) ('#<procedure #2 ##fx+> x x)))) ('#<procedure #3 ##fx*> y y y)))
Marc