LiberateCase and Lambda Dropping
Manuel M. T. Chakravarty
chak@cse.unsw.edu.au
Wed, 28 Feb 2001 23:08:58 +1100
LiberateCase would sometimes benefit from lambda dropping.
As an example, consider the definitions
import PrelGHC
import PrelBase
data AccessPath = Cont AccessPath
| Value Int
accessLen0#, accessLen1#, accessLen2# :: AccessPath -> Int#
accessLen0# (Value i) = case i of {I# i -> i}
accessLen1# (Cont ap) = accessLen0# ap
accessLen2# (Cont ap) = accessLen1# ap
main = print $ (I# (demandAll 10# (foo 1# ap)))
where
ap = Cont (Value 10)
foo 0# x = x
foo n# x = foo (n# -# 1#) x
and the following two variants of `demandAll'. The first
one is optimised perfectly by LiberateCase
demandAll :: Int# -> AccessPath -> Int#
demandAll n# ap = demandAll' n#
where
demandAll' n# = let
v = accessLen1# ap
in
case n# of
0# -> v
n# -> v +# demandAll' (n# -# 1#)
but the second one
demandAll :: Int# -> AccessPath -> Int#
demandAll n# ap = let
v = accessLen1# ap
in
case n# of
0# -> v
n# -> v +# demandAll (n# -# 1#) ap
is compiled to the inefficient
Main.demandAll :: (PrelGHC.Int# -> Main.AccessPath -> PrelGHC.Int#)
[Constant] __A 2 PS
Main.demandAll
= \ n# :: PrelGHC.Int# ap :: Main.AccessPath ->
case ap of wild {
Main.Value a -> PrelErr.patError @ PrelGHC.Int# lvl_s1Ky;
Main.Cont ap1 ->
case ap1 of wild1 {
Main.Cont a -> PrelErr.patError @ PrelGHC.Int# lvl1_s1Kx;
Main.Value i ->
case i of wild2 { PrelBase.I# i1 ->
case n# of ds {
0 -> i1;
__DEFAULT -> PrelGHC.+# i1 (Main.demandAll (PrelGHC.-# ds 1) wild)
}
}
}
}
Generally, arguments that remain constant in a recursive
function should be lambda dropped, I think.
Cheers,
Manuel
PS: This is not posing a big problem, but it is somewhat
annoying as I regularly attempt to write the more
concise form.