Simplifier does case-to-let too eagerly
Roman found an example where the simplifier was turning a case expression to a let binding when it shouldn't
foo :: Int -> Maybe (Double,Double) -> Double
foo _ Nothing = 0
foo 0 (Just (x,y)) = x+y
foo n (Just (x,y)) = let r = f x y in r `seq` foo (n-1) (Just r)
where
f x y | x <= y = (x,y)
| otherwise = (y,x)
GHC 7.0.1 generates this
foo =
\ (ds_dks :: Int) (ds_dkt :: Maybe (Double, Double)) ->
case ds_dkt of _ {
Nothing -> lvl_sly;
Just ipv_skO ->
case ds_dks of _ { I# ds_dku ->
case ds_dku of ds_XkC {
__DEFAULT ->
case ipv_skO of _ { (x_aax, y_aay) ->
case x_aax of wild_akY { D# x_al0 ->
case y_aay of wild1_al2 { D# y_al4 ->
foo
(I# (-# ds_XkC 1))
(Just
@ (Double, Double)
(case <=## x_al0 y_al4 of _ {
False -> (wild1_al2, wild_akY); True -> (wild_akY, wild1_al2)
}))
}
}
};
0 -> case ipv_skO of _ { (x_aau, y_aav) -> plusDouble x_aau y_aav }
}
}
}
That <=##
should be outside the call to foo
not inside. (The code isn't wrong, it's just less efficient than it should be.)
I know what's wrong. Patch coming.
Trac metadata
Trac field | Value |
---|---|
Version | 7.0.1 |
Type | Bug |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | Compiler |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | |
Operating system | |
Architecture |