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.