Refer to preallocated closures for top level INTLIKE constructors.
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.
After the implementation of #17004 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.
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.