Unexpected lack of optimisation
Neil Mitchell
ndmitchell at gmail.com
Mon Apr 28 17:13:03 EDT 2008
Hi
Using GHC 6.9.20071226:
The following code:
-------------------------------------------------------
test s | begin2 'n' 'a' s = "test"
| begin2 'n' 'b' s = "test2"
begin2 :: Char -> Char -> String -> Bool
begin2 x1 x2 (y:ys) | x1 == y = begin1 x2 ys
begin2 _ _ _ = False
begin1 :: Char -> String -> Bool
begin1 x1 (y:ys) | x1 == y = True
-------------------------------------------------------
You might expect the head of the list s to be tested for equality with
'n' only once. Something like:
test s = case s of
s1:ss -> case s1 of
'n' -> .... choose 'a' or 'b' ....
_ -> fail
Unfortunately, GHC can't common up these two tests. It inserts a
State# RealWorld in the middle, giving a result of:
test s = case s of
s1:ss -> case s1 of
'n' -> case ss of
s2:ss -> case s2 of
'a' -> ....
_ ->
retry state
_ -> retry state
retry dummy = case s of
s1:ss -> case s1 of
'n' -> ....
If GHC was to inline the "retry" (which is a local let-bound lambda)
it should have no problem merging these two cases. I'm not entirely
sure why the State# gets inserted, but was wondering if it is
necessary?
The complete -ddump-simpl is at the end of this message.
Thanks
Neil
--------------------------------------------------------------
Text.HTML.TagSoup.Development.Sample.test :: GHC.Base.String -> [GHC.Base.Char]
[GlobalId]
[Arity 1]
Text.HTML.TagSoup.Development.Sample.test =
\ (s_a6g :: GHC.Base.String) ->
let {
$j_s7l :: GHC.Prim.State# GHC.Prim.RealWorld -> [GHC.Base.Char]
[Arity 1]
$j_s7l =
\ (w_s7m :: GHC.Prim.State# GHC.Prim.RealWorld) ->
let {
$j1_s7d :: GHC.Prim.State# GHC.Prim.RealWorld -> [GHC.Base.Char]
[Arity 1]
$j1_s7d =
\ (w1_s7e :: GHC.Prim.State# GHC.Prim.RealWorld) ->
GHC.Err.patError
@ [GHC.Base.Char]
"Text/HTML/TagSoup/Development/Sample.hs:(48,0)-(49,34)|function test"
} in
case s_a6g of wild_Xl {
[] -> $j1_s7d GHC.Prim.realWorld#;
: y_a6o ys_a6q ->
case GHC.Base.$f4 of tpl_Xr { GHC.Base.:DEq tpl1_B2 tpl2_B3 ->
case tpl1_B2 (GHC.Base.C# 'n') y_a6o of wild1_Xp {
GHC.Base.False -> $j1_s7d GHC.Prim.realWorld#;
GHC.Base.True ->
let {
fail_d6S :: GHC.Base.Bool
[]
fail_d6S =
GHC.Err.patError
@ GHC.Base.Bool
"Text/HTML/TagSoup/Development/Sample.hs:57:0-32|function begin1" } in
case ys_a6q of wild2_XB {
[] ->
case fail_d6S of wild3_Xj {
GHC.Base.False -> $j1_s7d GHC.Prim.realWorld#;
GHC.Base.True -> GHC.Base.unpackCString# "test2"
};
: y1_a6y ys1_a6A ->
case GHC.Base.$f4 of tpl3_XH { GHC.Base.:DEq
tpl4_XL tpl5_XN ->
case tpl4_XL (GHC.Base.C# 'b') y1_a6y of wild3_Xo {
GHC.Base.False ->
case fail_d6S of wild4_Xj {
GHC.Base.False -> $j1_s7d GHC.Prim.realWorld#;
GHC.Base.True -> GHC.Base.unpackCString# "test2"
};
GHC.Base.True -> GHC.Base.unpackCString# "test2"
}
}
}
}
}
} } in
case s_a6g of wild_B1 {
[] -> $j_s7l GHC.Prim.realWorld#;
: y_a6o ys_a6q ->
case GHC.Base.$f4 of tpl_Xp { GHC.Base.:DEq tpl1_B2 tpl2_B3 ->
case tpl1_B2 (GHC.Base.C# 'n') y_a6o of wild1_XT {
GHC.Base.False -> $j_s7l GHC.Prim.realWorld#;
GHC.Base.True ->
let {
fail_d6S :: GHC.Base.Bool
[]
fail_d6S =
GHC.Err.patError
@ GHC.Base.Bool
"Text/HTML/TagSoup/Development/Sample.hs:57:0-32|function begin1" } in
case ys_a6q of wild2_Xz {
[] ->
case fail_d6S of wild3_XD {
GHC.Base.False -> $j_s7l GHC.Prim.realWorld#;
GHC.Base.True -> GHC.Base.unpackCString# "test"
};
: y1_a6y ys1_a6A ->
case GHC.Base.$f4 of tpl3_XF { GHC.Base.:DEq tpl4_XJ tpl5_XL ->
case tpl4_XJ (GHC.Base.C# 'a') y1_a6y of wild3_Xo {
GHC.Base.False ->
case fail_d6S of wild4_XN {
GHC.Base.False -> $j_s7l GHC.Prim.realWorld#;
GHC.Base.True -> GHC.Base.unpackCString# "test"
};
GHC.Base.True -> GHC.Base.unpackCString# "test"
}
}
}
}
}
}
More information about the Glasgow-haskell-users
mailing list