#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

Reply via email to