Skip to content

Refer to preallocated closures for top level INTLIKE constructors.

Motivation

GHC has static closures for Int's in the range MIN_INTLIKE .. MAX_INTLIKE

When binding a value of type foo = 1 :: Int inside a function we already refer to these static closures.

During code gen for constructor applications we simply check for the Int case, and then compute a LambdaFormInfo which tells use sites to refer to the precomputed Int closure. This avoids a static or a dynamic version of the I# application, instead reusing the precomputed one.

This does currently not work for top level closures. The reason is that we don't export LambdaFormInfo across modules.

A top level definition foo = I# 1# :: Int will be referenced by other modules by resolving the symbol foo_closure.

For this reason we are forced to emit a static Int closure with the label foo_closure which will be resolved by the linker.

A (worse) alternative would be to instead emit a indirection to the preallocated closures. But the indirection would be just as large as the Int closure itself so this would not be beneficial.

Proposal

After the implementation of #17004 (closed) we will have the ability to export LambdaFormInfo which contains information about we reference a given Id. If we make the LambdaFormInfo an required export for each top level Id we could then omit generating static Int closures in the MIN_INTLIKE .. MAX_INTLIKE range, and instead export a reference to the preallocated ones.

As a side note, the same approach would work for solving #16831, removing which should allow us to remove all cases of STATIC_IND I can think of.

Benefits

This would have two benefits:

  • Reduced code size. If I remember correctly GHC has a few KB worth of static Int closures which could be avoided this way.
  • We would have fewer memory locations representing the same value, resulting in better data locality.
Edited by Andreas Klebinger
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information