Skip to content

Inadequate FloatIn pass may leave redundant allocations in the hot path

Consider

module T21128a where

indexError :: Show a => a -> a -> a ->  b
indexError a b c = error (show a ++ show b ++ show c)
{-# NOINLINE indexError #-}

index :: Int -> Int -> Int -> Int
index l u i
  | l <= i && i < u = i-l
  | otherwise       = indexError l u i
{-# INLINE index #-}
module T21128 where

import T21128a

theresCrud :: Int -> Int -> Int
theresCrud x y = go x
  where
    go 0 = index 0 y 0
    go 1 = index x y 1
    go n = go (n-1)
{-# NOINLINE theresCrud #-}

The GHC versions I've looked at (8.10 and master) will unbox x and y. But that will stop with the following simplified Core (output here from master):

lvl = \ y -> $windexError $fShowInt_$cshow l y l

lvl1 = \ ww y -> $windexError $fShowInt_$cshow (I# ww) y i

$wtheresCrud
  = \ ww ww1 ->
      let { y = I# ww1 } in
      join {
        lvl2
          = case <=# ww 1# of {
              __DEFAULT -> case lvl1 ww y of wild { };
              1# ->
                case <# 1# ww1 of {
                  __DEFAULT -> case lvl1 ww y of wild { };
                  1# -> -# 1# ww
                }
            } } in
      join {
        lvl3
          = case <# 0# ww1 of {
              __DEFAULT -> case lvl y of wild { };
              1# -> 0#
            } } in
      joinrec {
        $wgo ww2
          = case ww2 of wild {
              __DEFAULT -> jump $wgo (-# wild 1#);
              0# -> jump lvl3;
              1# -> jump lvl2
            }; } in
      jump $wgo ww

NB: Those exit join points correspond to the two index calls.

Note the reboxing of y. While the reboxing of x happens in the bottoming join point exit_X18, y is shared among both index calls and can't be floated into the exit join points without duplicating the binding. Similarly, y won't be inlined, because ... I don't know why. Code size concerns maybe.

The result is that y is allocated in the hot path where it is never needed boxed.

This issue is merely to document this inconvenience. Not sure if we want to take concrete action on such a narrow use case; probably depends on how involved the fix is. Something for @simonpj to ponder.

Edited by Sebastian Graf
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information