#2387: Optimizer misses unboxing opportunity
------------------------------------+---------------------------------------
Reporter: dolio | Owner:
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 6.8.2
Severity: minor | Resolution:
Keywords: optimizer unbox box | Testcase:
Architecture: x86_64 (amd64) | Os: Linux
------------------------------------+---------------------------------------
Comment (by dolio):
Here's an even simpler test case:
{{{
module Main (main) where
import System.Environment
loop :: Int -> IO Int
loop n = go 0
where
go i
| i < n = go (i+1)
| otherwise = return i
main = loop 10 >>= print
}}}
This turns into:
{{{
$wgo :: Int#
-> State# RealWorld
-> (# State# RealWorld, Int #)
$wgo =
\ (ww_sxz :: Int#) (eta_sxO :: State# RealWorld) ->
case <# ww_sxz 10 of wild_B1 {
False -> (# eta_sxO, I# ww_sxz #);
True -> $wgo (+# ww_sxz 1) eta_sxO
}
a :: State# RealWorld
-> (# State# RealWorld, () #)
a =
\ (eta_apt :: State# RealWorld) ->
case $wgo 0 eta_apt of wild_avR { (# new_s_avT, a103_avU #) ->
case a24
stdout
(case a103_avU of w_avB { I# ww_avD ->
$wshowSignedInt 0 ww_avD ([] @ Char)
})
new_s_avT
of wild1_avo { (# new_s1_avq, a1031_avr #) ->
$wa6 stdout '\n' new_s1_avq
}
}
}}}
Similarly:
{{{
{-# LANGUAGE UnboxedTuples #-}
module Main (main) where
import System.Environment
loop :: Int -> (# Int, Int #)
loop n = go 0
where
go i
| i < n = go (i+1)
| otherwise = (# i, i #)
main = case loop 10 of
(# i, _ #) -> print i
}}}
Yields:
{{{
$wgo :: Int# -> (# Int, Int #)
$wgo =
\ (ww_sw8 :: Int#) ->
case <# ww_sw8 10 of wild_B1 {
False ->
let {
wild1_swr :: Int
[]
wild1_swr = I# ww_sw8 } in
(# wild1_swr, wild1_swr #);
True -> $wgo (+# ww_sw8 1)
}
}}}
To get the level of unboxing desired, we must:
{{{
module Main (main) where
import System.Environment
data Pair = P {-# UNPACK #-} !Int {-# UNPACK #-} !Int
loop :: Int -> Pair
loop n = go 0
where
go i
| i < n = go (i+1)
| otherwise = P i i
main = case loop 10 of
P i _ -> print i
}}}
Which becomes:
{{{
$wgo :: Int# -> (# Int#, Int# #)
$wgo =
\ (ww_swB :: Int#) ->
case <# ww_swB 10 of wild_B1 {
False -> (# ww_swB, ww_swB #);
True -> $wgo (+# ww_swB 1)
}
main :: IO ()
main =
case $wgo 0 of ww_swH { (# ww1_swJ, ww2_swK #) ->
(\ (eta1_aoZ :: State# RealWorld) ->
case a24
stdout
($wshowSignedInt 0 ww1_swJ ([] @ Char))
eta1_aoZ
of wild_auM { (# new_s_auO, a103_auP #) ->
$wa6 stdout '\n' new_s_auO
})
`cast` (sym ((:CoIO) ())
:: State# RealWorld
-> (# State# RealWorld, () #)
~
IO ())
}
}}}
However, that isn't an option for ST, obviously. A custom, strict,
polymorphic pair doesn't unpack, either (obviously, perhaps), so there
appears to be no way with ST/IO to get the level of unpacking that one
would be able to get writing with explicit State# s and unboxed tuples.
Or, more generally, there appears to be no way to return multiple unboxed
results from a recursive function without explicitly dealing with unboxed
values/strict monomorphic products.
--
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/2387#comment:1>
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