Ticket #4267 (new bug)
Strictness analyser is to conservative about passing a boxed parameter
| Reported by: | tibbe | Owned by: | |
|---|---|---|---|
| Priority: | low | Milestone: | 7.6.1 |
| Component: | Compiler | Version: | 6.13 |
| Keywords: | Cc: | ||
| Operating System: | Unknown/Multiple | Architecture: | Unknown/Multiple |
| Type of failure: | None/Unknown | Difficulty: | |
| Test Case: | Blocked By: | ||
| Blocking: | Related Tickets: |
Description
Given the following two modules:
Fold.hs:
module Fold (Tree, fold') where
data Tree a = Leaf | Node a !(Tree a) !(Tree a)
-- Strict, pre-order fold.
fold' :: (a -> b -> a) -> a -> Tree b -> a
fold' f = go
where
go z Leaf = z
go z (Node a l r) = let z' = go z l
z'' = f z' a
in z' `seq` z'' `seq` go z'' r
{-# INLINE fold' #-}
FoldTest.hs:
module FoldTest (sumTree) where import Fold sumTree :: Tree Int -> Int sumTree = fold' (+) 0
I'd expect that the accumulator z used in go to be an unboxed Int#. However, it's boxed:
sumTree1 :: Int
sumTree1 = I# 0
sumTree_go :: Int -> Fold.Tree Int -> Int
sumTree_go =
\ (z :: Int) (ds_ddX :: Fold.Tree Int) ->
case ds_ddX of _ {
Fold.Leaf -> z;
Fold.Node a l r ->
case sumTree_go z l of _ { I# z' ->
case a of _ { I# a# ->
sumTree_go (I# (+# z' a#)) r
}
}
}
sumTree :: Fold.Tree Int -> Int
sumTree =
\ (eta1_B1 :: Fold.Tree Int) ->
sumTree_go sumTree1 eta1_B1
Given this definition of fold'
fold' :: (a -> b -> a) -> a -> Tree b -> a
fold' f = go
where
go z _ | z `seq` False = undefined
go z Leaf = z
go z (Node a l r) = go (f (go z l) a) r
{-# INLINE fold' #-}
I get the core I want. However, this version isn't explicit in that the left branch (i.e. go z l) should be evaluated before f is called on the result. In other words, I think my first definition is the one that correctly expresses the evaluation order, yet it results in worse core.
Change History
Note: See
TracTickets for help on using
tickets.
