#6056: INLINABLE pragma prevents worker-wrapper to happen.
-------------------------------------+--------------------------------------
Reporter: milan | Owner:
Type: bug | Status: new
Priority: normal | Component: Compiler
Version: 7.4.1 | Keywords:
Os: Unknown/Multiple | Architecture: Unknown/Multiple
Failure: Runtime performance bug | Testcase:
Blockedby: | Blocking:
Related: |
-------------------------------------+--------------------------------------
When working on containers I found out that a method returning a pair
marked as INLINABLE does not go through a worker/wrapper transformation to
get a worker that would return unboxed pair.
For example:
{{{
module Test where
smallerAndRest :: Ord a => a -> [a] -> (Maybe a, [a])
smallerAndRest x [] = (Nothing, [])
smallerAndRest x (y:ys) | y < x = (Just y, ys)
| otherwise = smallerAndRest x ys
{-# INLINABLE smallerAndRest #-}
}}}
With the `INLINABLE` pragma, `-ddump-prep` prints
{{{
==================== CorePrep ====================
Result size = 42
lvl_rkg :: forall a_ajz. (Data.Maybe.Maybe a_ajz, [a_ajz])
[GblId, Caf=NoCafRefs, Str=DmdType m, Unf=OtherCon []]
lvl_rkg =
\ (@ a_ajz) -> (Data.Maybe.Nothing @ a_ajz, GHC.Types.[] @ a_ajz)
Rec {
Test.smallerAndRest [InlPrag=INLINABLE[ALWAYS], Occ=LoopBreaker]
:: forall a_a9I.
GHC.Classes.Ord a_a9I =>
a_a9I -> [a_a9I] -> (Data.Maybe.Maybe a_a9I, [a_a9I])
[GblId, Arity=3, Caf=NoCafRefs, Str=DmdType LLSm, Unf=OtherCon []]
Test.smallerAndRest =
\ (@ a_ajz)
($dOrd_sko :: GHC.Classes.Ord a_ajz)
(x_skq :: a_ajz)
(ds_skk :: [a_ajz]) ->
case ds_skk of _ {
[] -> lvl_rkg @ a_ajz;
: y_skp ys_sks ->
case GHC.Classes.< @ a_ajz $dOrd_sko y_skp x_skq of _ {
GHC.Types.False ->
Test.smallerAndRest @ a_ajz $dOrd_sko x_skq ys_sks;
GHC.Types.True ->
let {
sat_skw :: Data.Maybe.Maybe a_ajz
[LclId]
sat_skw = Data.Maybe.Just @ a_ajz y_skp } in
(sat_skw, ys_sks)
}
}
end Rec }
}}}
but without the `INLINABLE` pragma, we get
{{{
==================== CorePrep ====================
Result size = 57
Rec {
Test.$wsmallerAndRest [Occ=LoopBreaker]
:: forall a_a9I.
GHC.Classes.Ord a_a9I =>
a_a9I -> [a_a9I] -> (# Data.Maybe.Maybe a_a9I, [a_a9I] #)
[GblId, Arity=3, Caf=NoCafRefs, Str=DmdType LLS, Unf=OtherCon []]
Test.$wsmallerAndRest =
\ (@ a_a9I)
(w_skC :: GHC.Classes.Ord a_a9I)
(w1_skE :: a_a9I)
(w2_sky :: [a_a9I]) ->
case w2_sky of _ {
[] -> (# Data.Maybe.Nothing @ a_a9I, GHC.Types.[] @ a_a9I #);
: y_skD ys_skG ->
case GHC.Classes.< @ a_a9I w_skC y_skD w1_skE of _ {
GHC.Types.False ->
Test.$wsmallerAndRest @ a_a9I w_skC w1_skE ys_skG;
GHC.Types.True ->
let {
sat_skV :: Data.Maybe.Maybe a_a9I
[LclId]
sat_skV = Data.Maybe.Just @ a_a9I y_skD } in
(# sat_skV, ys_skG #)
}
}
end Rec }
Test.smallerAndRest [InlPrag=INLINE[0]]
:: forall a_a9I.
GHC.Classes.Ord a_a9I =>
a_a9I -> [a_a9I] -> (Data.Maybe.Maybe a_a9I, [a_a9I])
[GblId, Arity=3, Caf=NoCafRefs, Str=DmdType LLSm, Unf=OtherCon []]
Test.smallerAndRest =
\ (@ a_a9I)
(w_skL :: GHC.Classes.Ord a_a9I)
(w1_skM :: a_a9I)
(w2_skN :: [a_a9I]) ->
case Test.$wsmallerAndRest @ a_a9I w_skL w1_skM w2_skN
of _ { (# ww1_skR, ww2_skS #) ->
(ww1_skR, ww2_skS)
}
}}}
Here the worker-wrapper creates a variant, which returns unboxed pair.
I assume that there is no simple solution to this, because the
worker/wrapper changes the INLINABLE on `smallerAndRest` to INLINE. The
INLINABLE could be added to `$wsmallerAndRest`, but then #5928 causes the
specialization to fail.
Maybe at least both `smallerAndRest` and `$wsmallerAndRest` could be
marked `INLINABLE`? Then it is not sure that `smallerAndRest` gets INLINED
and `$wsmallerAndRest` exposed, but it is not worse than current
situation.
--
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/6056>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
_______________________________________________
Glasgow-haskell-bugs mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs