
#11710: Fusion of a simple listArray call is very fragile -------------------------------------+------------------------------------- Reporter: bgamari | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Runtime | Unknown/Multiple performance bug | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonpj): Yes, see `Note [Desugaring explicit lists]` in `DsExpr`, about the "static tail" of a list. For `listArray (1,100) [1,2` we get {{{ let { $dIx_aHr :: Ix Integer [LclId, Str=DmdType] $dIx_aHr = GHC.Arr.$fIxInteger } in let { $dNum_aSd :: Num Integer [LclId, Str=DmdType] $dNum_aSd = GHC.Num.$fNumInteger } in let { $dNum_aSh :: Num Integer [LclId, Str=DmdType] $dNum_aSh = $dNum_aSd } in let { $dNum_aSj :: Num Integer [LclId, Str=DmdType] $dNum_aSj = $dNum_aSh } in let { $dNum_aSf :: Num Integer [LclId, Str=DmdType] $dNum_aSf = $dNum_aSd } in letrec { alex_table_aSk :: Array Integer Integer [LclId, Str=DmdType] alex_table_aSk = listArray @ Integer @ Integer $dIx_aHr (0, 100) (GHC.Types.: @ Integer 1 (GHC.Types.: @ Integer 2 (GHC.Types.[] @ Integer))); } }}} (The dead `Num` dictionaries happen because the desugarer short-circuits the calls to `fromInteger @ Integer`.) Notice that the list has no free vars, so via the "static tail" trick in `DsExpr` we generate an explicit list. But for `listArray (0,100) [-1,2]` we get {{{ let { $dIx_aHs :: Ix Integer [LclId, Str=DmdType] $dIx_aHs = GHC.Arr.$fIxInteger } in let { $dNum_aSe :: Num Integer [LclId, Str=DmdType] $dNum_aSe = GHC.Num.$fNumInteger } in let { $dNum_aSi :: Num Integer [LclId, Str=DmdType] $dNum_aSi = $dNum_aSe } in let { $dNum_aSm :: Num Integer [LclId, Str=DmdType] $dNum_aSm = $dNum_aSi } in let { $dNum_aSk :: Num Integer [LclId, Str=DmdType] $dNum_aSk = $dNum_aSi } in let { $dNum_aSg :: Num Integer [LclId, Str=DmdType] $dNum_aSg = $dNum_aSe } in letrec { alex_table_aSn :: Array Integer Integer [LclId, Str=DmdType] alex_table_aSn = listArray @ Integer @ Integer $dIx_aHs (0, 100) (GHC.Base.build @ Integer (\ (@ a_d22o) (c_d22p :: Integer -> a_d22o -> a_d22o) (n_d22q :: a_d22o) -> c_d22p (negate @ Integer $dNum_aSi 1) (GHC.Base.foldr @ Integer @ a_d22o c_d22p n_d22q (GHC.Types.: @ Integer 2 (GHC.Types.[] @ Integer))))); } in }}} Now the calls to `negate` have a dictionary `$dNum_asi` which isn't top- level, so the "static tail" stuff fails and we generate a `build`. **This is obviously far too fragile. I think we should just drop the "static tail" idea entirely.** It's never bad to generate the build form, except for generating bloated code; see #11707. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11710#comment:4 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler