[GHC] #2273: inlining defeats seq
GHC
trac at galois.com
Thu May 8 13:05:39 EDT 2008
#2273: inlining defeats seq
-------------------------+--------------------------------------------------
Reporter: igloo | Owner:
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 6.9
Severity: normal | Keywords:
Difficulty: Unknown | Testcase:
Architecture: Unknown | Os: Unknown
-------------------------+--------------------------------------------------
Consider this module:
{{{
module Q (tcExtendIdEnv2) where
-- Interesting code:
tcExtendIdEnv2 :: M a
tcExtendIdEnv2 = do env <- getEnv
let level :: Int
level = thLevel (tcl_th_ctxt env)
level `seq` tc_extend_local_id_env level
{-# NOINLINE tc_extend_local_id_env #-}
tc_extend_local_id_env :: Int -> M a
tc_extend_local_id_env th_lvl = if read "foo"
then th_lvl `seq` return undefined
else return undefined
thLevel :: ThStage -> Int
thLevel Comp = 0
thLevel (Splice l) = l
thLevel (Brack l) = l
-- Dull code:
type M a = IOEnv TcLclEnv a
data TcLclEnv = TcLclEnv { tcl_th_ctxt :: !ThStage }
data ThStage = Comp | Splice Int | Brack Int
getEnv :: IOEnv env env
getEnv = IOEnv (\ env -> return env)
newtype IOEnv env a = IOEnv { unIOEnv :: env -> IO a }
instance Monad (IOEnv m) where
IOEnv m >>= f = IOEnv (\ env -> do r <- m env
unIOEnv (f r) env )
return a = IOEnv (\ _ -> return a)
fail = error
}}}
Compiling with
{{{
ghc -O -ddump-simpl -ddump-stg -c Q.hs
}}}
we get, in the STG,
{{{
Q.$wa =
\r srt:(0,*bitmap*) [ww_sDx w_sDO]
case
case ww_sDx of wild_sEs {
Q.Comp -> Q.lvl;
Q.Splice l_sDA -> l_sDA;
Q.Brack l_sDC -> l_sDC;
}
of
tpl_sEt
{ GHC.Base.I# ipv_sEu ->
let { sat_sDN = NO_CCS Q.TcLclEnv! [ww_sDx]; } in
let {
sat_sDL =
\u []
case ww_sDx of wild_sEv {
Q.Comp -> Q.lvl;
Q.Splice l_sDH -> l_sDH;
Q.Brack l_sDJ -> l_sDJ;
};
} in Q.tc_extend_local_id_env sat_sDL sat_sDN w_sDO;
};
}}}
GHC seems to have inlined `level`, forced it (due to the seq), but passed
along a second, inlined, unevaluated copy to `tc_extend_local_id_env`. So
the whole environment is retained, defeating the purpose of the seq!
If I mark `level` as `NOINLINE` then the STG looks like this:
{{{
Q.a5 =
\r srt:(0,*bitmap*) [env_sD1 eta_sDh]
case env_sD1 of tpl_sDg {
Q.TcLclEnv ipv_sD5 ->
case
case ipv_sD5 of wild_sDN {
Q.Comp -> Q.lvl;
Q.Splice l_sD8 -> l_sD8;
Q.Brack l_sDa -> l_sDa;
}
of
level_sDc
{ __DEFAULT ->
case level_sDc of tpl1_sDf {
GHC.Base.I# ipv1_sDO -> Q.tc_extend_local_id_env
tpl1_sDf tpl_sDg eta_sDh;
};
};
};
}}}
which fixes the env-retained problem, although I don't understand why two
cases are done.
It would be nice not to have to resort to this level of trickery, though!
--
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/2273>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the Glasgow-haskell-bugs
mailing list