
(compiled with ghc 6.10 with options -O2 -ddump-simpl) I was wondering why lvl_s1mF is not being inlined into a_s1Gv in the core at the bottom of this email as that is the only place it is ever referenced. It also seems the extra levels of indirection are defeating the strictness analyzer on eta_s1CN in a_s1Gv as all code branches either directly force it or ultimately pass it to digit_s1l3 as in the included branch. Also, why isn't digit_s1l3 optimized to take its first parameter unboxed? It is strict in its first argument, and grepping the core shows that it is only ever used like in lvl_s1mF (i.e., passed things like lvl_s1mG). Thanks! -Tyson PS: Is there any way to get better control over the loop breaker choice? For a slightly simpler digit function, it is not chosen, and great code is produced. I've tried using INLINE on digit, but that seems to result in the monad bind operator not being inlined, which produces even worse code. . . . letrec { lvl_s1mF :: Control.Monad.State.Strict.StateT GHC.Types.Int (Control.Monad.State.Strict.StateT GHC.Types.Int (Control.Monad.Error.ErrorT GHC.Base.String Control.Monad.Identity.Identity)) GHC.Types.Int [Str: DmdType {s1l3->C(S)}] lvl_s1mF = digit_s1l3 lvl_s1mG; . . . a_s1Gv :: GHC.Types.Int -> GHC.Types.Int -> Control.Monad.Error.ErrorT [GHC.Types.Char] Control.Monad.Identity.Identity ((GHC.Types.Int, GHC.Types.Int), GHC.Types.Int) [Arity 2 Str: DmdType U(L)L {a1hP->U(TTTL) s1ka->U(L)}] a_s1Gv = a_s1Gv = \ (eta_a1px [ALWAYS Just U(L)] :: GHC.Types.Int) (eta_s1CN [ALWAYS Just L] :: GHC.Types.Int) -> . . .... GHC.Bool.True -> (((lvl_s1mF `cast` (... ~ GHC.Types.Int -> Control.Monad.State.Strict.StateT GHC.Types.Int (Control.Monad.Error.ErrorT GHC.Base.String Control.Monad.Identity.Identity) (GHC.Types.Int, GHC.Types.Int))) (GHC.Types.I# (GHC.Prim.+# x_a1tl 1))) `cast` (... ~ GHC.Types.Int -> Control.Monad.Error.ErrorT GHC.Base.String Control.Monad.Identity.Identity ((GHC.Types.Int, GHC.Types.Int), GHC.Types.Int))) eta_s1CN .... . . . . . digit_s1l3 [ALWAYS LoopBreaker Nothing] :: GHC.Types.Int -> Control.Monad.State.Strict.StateT GHC.Types.Int (Control.Monad.State.Strict.StateT GHC.Types.Int (Control.Monad.Error.ErrorT GHC.Base.String Control.Monad.Identity.Identity)) GHC.Types.Int [Arity 1 Str: DmdType U(L)] digit_s1l3 = \ (x_aqR [ALWAYS Just U(L)] ::GHC.Types.Int) -> case x_aqR of x_XsO [ALWAYS Just A] { GHC.Types.I# ipv_s1bt [ALWAYS Just L] -> let { . . . } in (\ (eta_X1sC [ALWAYS Just L] :: GHC.Types.Int) (eta_s1FE [ALWAYS Just U(L)] :: GHC.Types.Int) -> . . . ) `cast` (... ~ Control.Monad.State.Strict.StateT GHC.Types.Int (Control.Monad.State.Strict.StateT GHC.Types.Int (Control.Monad.Error.ErrorT GHC.Base.String Control.Monad.Identity.Identity)) GHC.Types.Int) . . . } . . . lvl_s1mG :: GHC.Types.Int [Str: DmdType m] lvl_s1mG = GHC.Types.I# 0