SpecConstr broken for NOINLINE loops in 6.13
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.
Trac metadata
Trac field | Value |
---|---|
Version | 6.13 |
Type | Bug |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | Compiler |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | |
Operating system | |
Architecture |