Skip to content

IR1 optimization macros

Masataro Asai edited this page Jul 14, 2018 · 7 revisions

sb-int:info structure

all compiler information is stored in a so-called info database. The API for accessing this database is (sb-int:info category kind name) e.g. (sb-int:info :function :info 'make-list).

In the source code I saw following combinations. They are not well documented:

  • category :function: kind: :source-location :type :where-from :kind :info :macro-function :compiler-macro-function :emitted-full-calls :ir1-convert :source-transform :inlinep :assumed-type :inline-expansion-designator
  • category :variable: kind: :source-location :type :declaration :where-from :variable-tls :always-bound
  • category :declaration :recognized
  • category :source-location kind :declaration
  • category :setf kind :expander
  • category :typed-structure :info
  • category :random-documentation :stuff
  • category :type :compiler-layout :deprecated :expander
  • category :prin1
  • category :no-ir2-yet
  • category :test
  • category :rest-p
  • category :ref-trans

fun-info

Infodb slots specified by :function :info contains a SB-C::FUN-INFO structure. Most internal / standard functions have its fun-info, which stores information on several optimization methods.

The macros to manipulate (mostly only adding) fun-info are sb-c:defknown, sb-c:defoptimizer, sb-c:deftransform.

sb-c:defknown

defknown sets up a fun-info entry in the infodb. Thus it should be called before other macros are evaluated. Re-evaluating this macro inserts a new fun-info instance, which is equivalent to wiping the infodb for that function.

It provides the following information:

  • function attributes, such as movable, flushable, dx-safe. This is discussed in function attributes.
  • function types. This is a static one, similar to the ftype'd information. What you see from declared type also comes from this.

Original documentation here.

sb-c:deftransform

deftransform can be seen as an implementation-specific, internal version of define-compiler-macro dispatched by the inferred argument types. For example, if the type of an argument of a call to copy-seq is known to be a vector in compile time, and if there is a deftransform specialized with vector with a loop-based, specialized version of the function, then the call can be replaced with the transformation result.

These functions are stored in the transforms slot in fun-info.

You may attach a docstring to deftransform. When the optimization policy is high, the compiler uses this docstring as a note when the transform was failed due to the type requirement.

Original documentation here.

sb-c:defoptimizer

Original documentation here.

Used to implement methods for deriving other types of information. Syntax is (defoptimizer name ...) or (defoptimzer (name kind) ...). However, the first type of defoptimizer without kind is rare, only used in vm-ir2tran.lisp. It looks like they are some kind of hack to implement functions that happened to have the same function signatures. So, let's focus on the second type of defoptimizer.

Documentation says kind is one of DERIVE-TYPE, OPTIMIZER, LTN-ANNOTATE and IR2-CONVERT. This is not true, there is no such restriction. There is no real documentation for each kind. However, the result of these optimization functions are stored in the corresponding slot with the same name in fun-info. See fun-info documentation.

Following kinds are actually used.

  • derive-type

the optimizer function defined by derive-type is used to derive the return-type of a function call from the types of arguments. For example, the result type of (random arg) is equivalent to the type of arg, and this can be implemented by derive-type. It should be a function that returns a type specifier a CTYPE object. CTYPE object can be constructed from a type specifier using sb-kernel:specifier-type. CTYPE documentation

  • stack-allocate-result

Returns a boolean, allows stack allocation if true.

  • optimizer

It allows misc optimizations, modifying the LVARs. Returns true if further optimizations of the call shouldn't be attempted.

Example: converting (values-list (list x y z)) into (values x y z). Example: constant folding coerce.

  • ltn-annotate : I have no idea what LTN means. SBCL contains lots of these unreadable abbreviations and it sucks.
  • ir2-convert provides special ir2 conversion for irregular functions.
  • ir2-hook
  • constraint-propagate-if : Used only once in compiler/typetran.lisp:(defoptimizer (%typep-wrapper constraint-propagate-if).

define-source-transform

This is essentially the same as compiler macros. It does not investigate the arguments and unconditionally expands a function call into another form. Expander functions are stored in (info :function :source-transform).

While a compiler-macro must deal with being invoked when its whole form matches (FUNCALL <f> ...) so that it must skip over <f> to find the arguments, a source-transform need not worry about that situation.

Original documentation here.

def-ir1-translator

Used to implement a special form. Stores information in (info :function :ir1-convert). Original documentation here.