Failure to do CPR in the presence of a local letrec
Consider this code:
{-# LANGUAGE BangPatterns #-}
module NoCPR (e) where
e :: (Int, Int) -> Int -> Int -> (Int, Int)
e x y n = je x y
where je !x y | y > 0 = x
| otherwise = je x (y + n)
(which is adapted from #5949 (closed)).
We get this Core:
-- RHS size: {terms: 38, types: 27, coercions: 0, joins: 1/1}
e :: (Int, Int) -> Int -> Int -> (Int, Int)
[GblId,
Arity=3,
Caf=NoCafRefs,
Str=<S,1*U(U,U)><S(S),1*U(U)><L,U(U)>m,
Unf=OtherCon []]
e = \ (x [Occ=Once!] :: (Int, Int))
(y [Occ=Once!] :: Int)
(n [Occ=OnceL!] :: Int) ->
case x of { (ww1 [Occ=Once], ww2 [Occ=Once]) ->
case y of { I# ww4 [Occ=Once] ->
joinrec {
$wje [InlPrag=[0], Occ=LoopBreakerT[3]]
:: Int -> Int -> Int# -> (Int, Int)
[LclId[JoinId(3)], Arity=3, Str=<L,U><L,U><S,U>m, Unf=OtherCon []]
$wje (ww5 [Occ=Once*] :: Int)
(ww6 [Occ=Once*] :: Int)
(ww7 :: Int#)
= case ># ww7 0# of {
__DEFAULT ->
case n of { I# y1 [Occ=Once] ->
case +# ww7 y1 of sat { __DEFAULT -> jump $wje ww5 ww6 sat }
};
1# -> (ww5, ww6)
}; } in
jump $wje ww1 ww2 ww4
}
}
Why is there no CPR happening for e
? In fact, why is there no unboxing happening – it was for the following similar code:
e :: (Int, Int) -> Int -> (Int, Int)
e x y = x `seq` if y > 10
then x
else e x (y + 1)
(This is a spin-off of the dicussion at https://phabricator.haskell.org/D3811#107708).
Trac metadata
Trac field | Value |
---|---|
Version | 8.3 |
Type | Bug |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | Compiler |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | |
Operating system | |
Architecture |