Skip to content

INLINE CONLIKE sometimes fails to inline

I got surprisingly poor results from the cheapBuild experiment (see #7206), so I decided to try a simple example.

foo :: Int -> Int
foo n = s + p
  where
    nums = [1..n]
    s = sum nums
    p = product nums

The idea is that we want nums to inline into s and p; the lost sharing is unimportant. Unfortunately, this didn't fuse. I got

-- RHS size: {terms: 44, types: 31, coercions: 0, joins: 2/3}
$wfoo :: Int# -> Int#
$wfoo
  = \ (ww_s2HT :: Int#) ->
      let {
        nums_s2Gq :: [Int]
        nums_s2Gq = eftInt 1# ww_s2HT } in
      joinrec {
        $wgo_s2HP :: [Int] -> Int# -> Int#
        $wgo_s2HP (w_s2HJ :: [Int]) (ww1_s2HN :: Int#)
          = case w_s2HJ of {
              [] ->
                joinrec {
                  $wgo1_s2HI :: [Int] -> Int# -> Int#
                  $wgo1_s2HI (w1_s2HC :: [Int]) (ww2_s2HG :: Int#)
                    = case w1_s2HC of {
                        [] -> +# ww1_s2HN ww2_s2HG;
                        : y_a2F9 ys_a2Fa ->
                          case y_a2F9 of { I# y1_a2Gf ->
                          jump $wgo1_s2HI ys_a2Fa (*# ww2_s2HG y1_a2Gf)
                          }
                      }; } in
                jump $wgo1_s2HI nums_s2Gq 1#;
              : y_a2F9 ys_a2Fa ->
                case y_a2F9 of { I# y1_a2EX ->
                jump $wgo_s2HP ys_a2Fa (+# ww1_s2HN y1_a2EX)
                }
            }; } in
      jump $wgo_s2HP nums_s2Gq 0#

-- RHS size: {terms: 10, types: 4, coercions: 0, joins: 0/0}
foo :: Int -> Int
foo
  = \ (w_s2HQ :: Int) ->
      case w_s2HQ of { I# ww1_s2HT ->
      case $wfoo ww1_s2HT of ww2_s2HX { __DEFAULT -> I# ww2_s2HX }
      }

I verified that cheapBuild actually appeared (in -dverbose-core2core), but it didn't fuse, and ultimately inlined.

Interestingly, forcing the argument manually fixed the problem:

foo :: Int -> Int
foo !n = s + p
  where
    nums = [1..n]
    s = sum nums
    p = product nums

produces

$wfoo :: Int# -> Int#
$wfoo
  = \ (ww_s2Ia :: Int#) ->
      case tagToEnum# (># 1# ww_s2Ia) of {
        False ->
          joinrec {
            $wgo_s2I6 :: Int# -> Int# -> Int#
            $wgo_s2I6 (w_s2I0 :: Int#) (ww1_s2I4 :: Int#)
              = case tagToEnum# (==# w_s2I0 ww_s2Ia) of {
                  False -> jump $wgo_s2I6 (+# w_s2I0 1#) (+# ww1_s2I4 w_s2I0);
                  True ->
                    let {
                      x_X2Fz :: Int#
                      x_X2Fz = +# ww1_s2I4 w_s2I0 } in
                    joinrec {
                      $wgo1_s2HY :: Int# -> Int# -> Int#
                      $wgo1_s2HY (w1_s2HS :: Int#) (ww2_s2HW :: Int#)
                        = case tagToEnum# (==# w1_s2HS ww_s2Ia) of {
                            False -> jump $wgo1_s2HY (+# w1_s2HS 1#) (*# ww2_s2HW w1_s2HS);
                            True -> +# x_X2Fz (*# ww2_s2HW w1_s2HS)
                          }; } in
                    jump $wgo1_s2HY 1# 1#
                }; } in
          jump $wgo_s2I6 1# 0#;
        True -> 1#
      }
Trac metadata
Trac field Value
Version 8.1
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information