Skip to content

UNPACK can lead to unnecessary copying and wasted stack space

You can write a pattern-matched function to take only certain components of a data type. If you pattern match on an UNPACKed component and GHC decomposes your function into several simpler functions, those functions will pass every UNPACKed component, used or not, between the simpler functions.

This wastes time copying the unneeded UNPACKed components to the stack and obviously wastes stack space.


For example, the function upd below

data D = D {-# UNPACK #-} !Double {-# UNPACK #-} !Double
data UPD = UPD {-# UNPACK #-} !Double D

upd (UPD _ (D x _)) = sqrt $! (x*x + x*x)

takes only one component of the nested data structure. However, it will be decomposed into Test.upd and Test.$wupd

Test.upd :: Test.UPD -> GHC.Types.Double
GblId
[Arity 1
 Worker Test.$wupd
 NoCafRefs
 Str: DmdType U(AU(LA))m]
Test.upd =
  __inline_me (\ (w_spS :: Test.UPD) ->
                 case w_spS of _ { Test.UPD ww_spU ww1_spV ->
                 case ww1_spV of _ { Test.D ww3_spX ww4_spY ->
                 case Test.$wupd ww_spU ww3_spX ww4_spY of ww5_sq3 { __DEFAULT ->
                 GHC.Types.D# ww5_sq3
                 }
                 }
                 })

Test.$wupd :: GHC.Prim.Double#
              -> GHC.Prim.Double#
              -> GHC.Prim.Double#
              -> GHC.Prim.Double#
GblId
[Arity 3
 NoCafRefs
 Str: DmdType ALA]
Test.$wupd =
  \ _ (ww1_spX :: GHC.Prim.Double#) _ ->
  ...

wherein Test.upd takes the structure and passes all of the UNPACKed components to Test.$wupd, giving it Arity 3, and which immediately drops all the unneeded components via underscores.


The correct behavior can be seen when you don't use UNPACK at all, as with ppb here

data B = B                !Double                !Double
data PPB = PPB                !Double B

ppb (PPB _ (B x _)) = sqrt $! (x*x + x*x)

for which GHC produces a nested function, Test.$wppb, which has Arity 1, as it should.

Test.$wppb :: GHC.Prim.Double# -> GHC.Prim.Double#
GblId
[Arity 1
 NoCafRefs
 Str: DmdType L]
Test.$wppb =
  \ (ww_sr1 :: GHC.Prim.Double#) ->
Trac metadata
Trac field Value
Version 6.12.3
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information