Skip to content

Compress certain IdInfo fields into a single Word64

Motivation

IdInfos are an absolute massive part of GHC's residency during compilation. Contributing a bit over 15% of residency during it's peak and over 10% over much of the pipeline. image

So reducing it's size by 1/3rd would reduce GHC's footprint by 5% at it's peak with no other changes.

I assume they are also a significant contributor to compiler allocations, so compacting these fields would be beneficial there as well. But maybe not as much so as with residency.

Proposal

Currently IdInfo is implemented like this:

data IdInfo
  = IdInfo {
        arityInfo       :: !ArityInfo,          -- ^ 'Id' arity
        ruleInfo        :: RuleInfo,            -- ^ Specialisations of the 'Id's function which exist
                                                -- See Note [Specialisations and RULES in IdInfo]
        unfoldingInfo   :: Unfolding,           -- ^ The 'Id's unfolding
        cafInfo         :: CafInfo,             -- ^ 'Id' CAF info
        oneShotInfo     :: OneShotInfo,         -- ^ Info about a lambda-bound variable, if the 'Id' is one
        inlinePragInfo  :: InlinePragma,        -- ^ Any inline pragma atached to the 'Id'
        occInfo         :: OccInfo,             -- ^ How the 'Id' occurs in the program

        strictnessInfo  :: StrictSig,      --  ^ A strictness signature

        demandInfo      :: Demand,       -- ^ ID demand information
        callArityInfo   :: !ArityInfo,   -- ^ How this is called.
                                         -- n <=> all calls have at least n arguments

        levityInfo      :: LevityInfo    -- ^ when applied, will this Id ever have a levity-polymorphic type?
    }

Nothing is wrong about that but it's not ideal.

In particular the fields arityInfo, cafInfo, oneShotInfo, callArityInfo and levityInfo could all be compressed into a single Word64 bitmask (if we are content with a max arity of 32k) reducing the size of IdInfo from 12 Words to 8 Words.

So the type would be something like this:

data IdInfo
  = IdInfo {
        ruleInfo        :: RuleInfo,            -- ^ Specialisations of the 'Id's function which exist
                                                -- See Note [Specialisations and RULES in IdInfo]
        unfoldingInfo   :: Unfolding,           -- ^ The 'Id's unfolding
        inlinePragInfo  :: InlinePragma,        -- ^ Any inline pragma atached to the 'Id'
        occInfo         :: OccInfo,             -- ^ How the 'Id' occurs in the program

        strictnessInfo  :: StrictSig,      --  ^ A strictness signature

        demandInfo      :: Demand,       -- ^ ID demand information
                                         -- n <=> all calls have at least n arguments

        bitField        :: BitField64        -- ^ Encodes arities, oneShotInfo, cafInfo and levityInfo.

    }

newtype BitField64 = BitField64 Word64

-- Functions to extract the values from the bitfield
callArityInfo   :: BitField -> !ArityInfo
arityInfo :: ...
...

Problems

  • Not all of these fields are strict. It's likely that making them strict would outweigh in order to shrink IdInfo would still be worthwhile. But there might be issues lurking there I did not account for.

  • Code churn. These fields are used in many places, as such the diff would be fairly substantial. However using pattern synonyms and other tricks I don't think code using the actual values would look much different, if at all.

  • Somebody needs to implement it. I don't plan to in the near future.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information