8.3 Forward ICR optimizations
In the forward pass, we scan the code in forward depth-first order. We
examine each call to a known function, and:
- Eliminate any bindings for unused variables.
- Do top-down type assertion propagation. In local calls, we propagate
asserted and derived types between the call and the called lambda.
- Replace calls of foldable functions with constant arguments with the
result. We don’t have to actually delete the call node, since Top-Down
optimize will delete it now that its value is unused.
- Run any Optimizer for the current function. The optimizer does arbitrary
transformations by hacking directly on the IR. This is useful primarily
for arithmetic simplification and similar things that may need to examine
and modify calls other than the current call. The optimizer is responsible
for recording any changes that it makes. An optimizer can inhibit further
optimization of the node during the current pass by returning true. This
is useful when deleting the node.
- Do ICR transformations, replacing a global function call with equivalent
inline lisp code.
- Do bottom-up type propagation/inferencing. For some functions such as
Coerce we will dispatch to a function to find the result type. The
Derive-Type function just returns a type structure, and we check if it is
different from the old type in order to see if there was a change.
- Eliminate IFs with predicates known to be true or false.
- Substitute the value for unset let variables that are bound to constants,
unset lambda variables or functionals.
- Propagate types from local call args to var refs.
We use type info from the function continuation to find result types for
functions that don’t have a derive-type method.