[GHC] #4064: SpecConstr broken for NOINLINE loops in 6.13
GHC
cvs-ghc at haskell.org
Wed May 12 03:36:36 EDT 2010
#4064: SpecConstr broken for NOINLINE loops in 6.13
---------------------------------+------------------------------------------
Reporter: rl | Owner:
Type: bug | Status: new
Priority: normal | Component: Compiler
Version: 6.13 | Keywords:
Os: Unknown/Multiple | Testcase:
Architecture: Unknown/Multiple | Failure: Runtime performance bug
---------------------------------+------------------------------------------
Example:
{{{
foo :: Int -> Int -> Int
{-# NOINLINE foo #-}
foo n k | n <= 0 = k
| otherwise = foo (n-1) (k+1)
}}}
This is what GHC generates:
{{{
Rec {
X.foo_$sfoo [Occ=LoopBreaker]
:: GHC.Prim.Int# -> GHC.Prim.Int# -> GHC.Types.Int
[GblId, Arity=2, Caf=NoCafRefs, Str=DmdType LL]
X.foo_$sfoo =
\ (sc_sjW :: GHC.Prim.Int#) (sc1_sjX :: GHC.Prim.Int#) ->
case GHC.Prim.<=# sc1_sjX 0 of _ {
GHC.Bool.False ->
X.foo
(GHC.Types.I# (GHC.Prim.-# sc1_sjX 1))
(GHC.Types.I# (GHC.Prim.+# sc_sjW 1));
GHC.Bool.True -> GHC.Types.I# sc_sjW
}
X.foo [InlPrag=NOINLINE (sat-args=2), Occ=LoopBreaker]
:: GHC.Types.Int -> GHC.Types.Int -> GHC.Types.Int
[GblId, Arity=2, Caf=NoCafRefs, Str=DmdType U(L)U(L)m]
X.foo =
\ (n_aaj :: GHC.Types.Int) (k_aak :: GHC.Types.Int) ->
case n_aaj of _ { GHC.Types.I# x_ajn ->
case GHC.Prim.<=# x_ajn 0 of _ {
GHC.Bool.False ->
case k_aak of _ { GHC.Types.I# x1_aiX ->
X.foo
(GHC.Types.I# (GHC.Prim.-# x_ajn 1))
(GHC.Types.I# (GHC.Prim.+# x1_aiX 1))
};
GHC.Bool.True -> k_aak
}
}
end Rec }
------ Local rules for imported ids --------
"SC:X.foo0" [NEVER]
forall {sc_sjW :: GHC.Prim.Int# sc1_sjX :: GHC.Prim.Int#}
X.foo (GHC.Types.I# sc1_sjX) (GHC.Types.I# sc_sjW)
= X.foo_$sfoo sc_sjW sc1_sjX
}}}
At the moment, we don't worker/wrapper NOINLINE things because doing so
would generate a wrapper which wouldn't be inlined. But apparently, we do
!SpecConstr NOINLINE functions, generating rules and specialisations which
can never be used, like above.
The trivial solution is to have !SpecConstr ignore NOINLINE functions.
Perhaps we could also think about transforming `foo` to this instead:
{{{
{-# NOINLINE foo #-}
foo = foo'
foo' n k | n <= 0 = k
| otherwise = foo' (n-1) (k+1)
}}}
Now, we can apply worker/wrapper and !SpecConstr to `foo'` without any
restrictions. One could argue that `foo` has been "inlined" into its own
rhs but I can't imagine how that could ever be a problem.
--
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/4064>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the Glasgow-haskell-bugs
mailing list