#14844: SpecConstr also non-recursive function -------------------------------------+------------------------------------- Reporter: nomeata | Owner: (none) Type: task | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.5 Resolution: | Keywords: SpecConstr Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by nomeata): And here some details on the second point. After the first run of SpecConstr, we have somthing like this {{{ $w$lf_s6DU [InlPrag=NOUSERINLINE[0]] :: Double -> Double -> GHC.Prim.Int# -> (# Double, Double #) [LclId, Arity=3, Str=<L,U(U)><L,U(U)><S,U>m] $w$lf_s6DU = \ (ww_s6AD :: Double) (ww_s6AE :: Double) (ww_s6AI :: GHC.Prim.Int#) -> joinrec { $s$l$w$lf_s6Hv :: GHC.Prim.Int# -> GHC.Prim.Double# -> GHC.Prim.Double# -> (# Double, Double #) [LclId[JoinId(3)], Arity=3, Str=<L,U><L,U><L,U>] $s$l$w$lf_s6Hv (sc_s6Hu :: GHC.Prim.Int#) (sc_s6Ht :: GHC.Prim.Double#) (sc_s6Hs :: GHC.Prim.Double#) … $l$w$lf_X6Ep [Occ=LoopBreaker] :: Double -> Double -> GHC.Prim.Int# -> (# Double, Double #) [LclId[JoinId(3)], Arity=3, RULES: "SC:$l$w$lf0" forall (sc_s6Hu :: GHC.Prim.Int#) (sc_s6Ht :: GHC.Prim.Double#) (sc_s6Hs :: GHC.Prim.Double#). $l$w$lf_X6Ep (GHC.Types.D# sc_s6Hs) (GHC.Types.D# sc_s6Ht) sc_s6Hu = jump $s$l$w$lf_s6Hv sc_s6Hu sc_s6Ht sc_s6Hs] $l$w$lf_X6Ep (ww_X6B9 [Dmd=<L,U(U)>] :: Double) (ww_X6Bb [Dmd=<L,U(U)>] :: Double) (ww_X6Bg [Dmd=<S,U>] :: GHC.Prim.Int#) … }; } in jump $l$w$lf_X6Ep ww_s6AD ww_s6AE ww_s6AI … … … case $w$lf_s6DU (GHC.Types.D# (GHC.Prim.cosDouble# wild2_a5jY)) (GHC.Types.D# (GHC.Prim.sinDouble# wild2_a5jY)) wild_XM of }}} We can clearly see that `$w$lf_s6DU` has been loopified, with a local joinrec `$l$w$lf_X6Ep`, and that this local join rec `$l$w$lf_X6Ep` has been !SpecConstr’ed to `$s$l$w$lf_s6Hv`. But why does `$w$lf_s6DU` not get `SpecConstr’ed? Because of {{{ specialise entry { $w$lf_s6DU [$w$lf_s6DU (D# (cosDouble# wild2_a5jY)) (D# (sinDouble# wild2_a5jY)) wild_XM] callToPats [D# (cosDouble# wild2_a5jY), D# (sinDouble# wild2_a5jY), wild_XM] [unk-occ, unk-occ, unk-occ] }}} which means that it sees the calls passing constructors, but it does not know that the arguments (e.g. `ww_s6AD`) get scrutinizes, so it does not act on this. After simplification, however, we have {{{ $w$lf_s6DU [InlPrag=NOUSERINLINE[0]] :: Double -> Double -> GHC.Prim.Int# -> (# Double, Double #) [LclId, Arity=3, Str=<L,U(U)><L,U(U)><S,U>m, RULES: "SC:$w$lf0" [0] forall (sc_s6KF :: GHC.Prim.Int#) (sc_s6KE :: GHC.Prim.Double#) (sc_s6KD :: GHC.Prim.Double#). $w$lf_s6DU (GHC.Types.D# sc_s6KD) (GHC.Types.D# sc_s6KE) sc_s6KF = $s$w$lf_s6KG sc_s6KF sc_s6KE sc_s6KD] $w$lf_s6DU = \ (ww_s6AD :: Double) (ww_s6AE :: Double) (ww_s6AI :: GHC.Prim.Int#) -> joinrec { $s$l$w$lf_s6Hv [Occ=LoopBreaker] :: GHC.Prim.Int# -> GHC.Prim.Double# -> GHC.Prim.Double# -> (# Double, Double #) … }; } in case ww_s6AD of ww3_s6DY { GHC.Types.D# ww4_s6DZ -> case ww_s6AE of ww5_s6E1 { GHC.Types.D# ww6_s6E2 -> case GHC.Prim.remInt# ww_s6AI 2# of { __DEFAULT -> case ww_s6AI of wild_X11 { … }}} i.e. `$l$w$lf_X6Ep` has been inlined and thus exposed a case analysis of ww_s6AD, and now `$w$lf_s6DU` gets specialized as expected. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/14844#comment:6> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler