[GHC] #10120: Unnecessary code duplication from case analysis
GHC
ghc-devs at haskell.org
Fri Feb 27 05:31:15 UTC 2015
#10120: Unnecessary code duplication from case analysis
-------------------------------------+-------------------------------------
Reporter: bgamari | Owner:
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 7.10.1-rc2
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture:
Type of failure: Runtime | Unknown/Multiple
performance bug | Test Case:
Blocked By: | Blocking:
Related Tickets: | Differential Revisions:
-------------------------------------+-------------------------------------
Description changed by bgamari:
Old description:
> Consider a case analysis like this,
>
> {{{#!hs
> predicate c =
> c == '-' || c == '_' || c == '.' || c == '~' || c == ':'
> || c == '@' || c == '&' || c == '=' || c == '+' || c == '$' || c ==
> ','
>
> f x | predicate x = do_something
> f x = do_something_else
> main = f 'a'
> }}}
>
> GHC in some cases appears to produce Core for this example by
> constructing a case analysis on `x`, replicating `do_something` in every
> branch,
>
> {{{#!hs
> $wa_r3UQ
> :: GHC.Prim.Char#
> -> GHC.Prim.State# GHC.Prim.RealWorld
> -> (# GHC.Prim.State# GHC.Prim.RealWorld, () #)
> [GblId, Arity=2, Str=DmdType <S,1*U><L,U>]
> $wa_r3UQ =
> \ (ww_s3TD :: GHC.Prim.Char#)
> (w_s3TA [OS=OneShot] :: GHC.Prim.State# GHC.Prim.RealWorld) ->
> case ww_s3TD of _ [Occ=Dead] {
> __DEFAULT -> (# w_s3TA, GHC.Tuple.() #);
> '$' ->
> GHC.IO.Handle.Text.hPutStr2
> GHC.IO.Handle.FD.stdout lvl2_r3Uv GHC.Types.True w_s3TA;
> '&' ->
> GHC.IO.Handle.Text.hPutStr2
> GHC.IO.Handle.FD.stdout lvl4_r3Ux GHC.Types.True w_s3TA;
> '+' ->
> GHC.IO.Handle.Text.hPutStr2
> GHC.IO.Handle.FD.stdout lvl6_r3Uz GHC.Types.True w_s3TA;
> ',' ->
> GHC.IO.Handle.Text.hPutStr2
> GHC.IO.Handle.FD.stdout lvl8_r3UB GHC.Types.True w_s3TA;
> '-' ->
> GHC.IO.Handle.Text.hPutStr2
> GHC.IO.Handle.FD.stdout lvl10_r3UD GHC.Types.True w_s3TA;
> '.' ->
> GHC.IO.Handle.Text.hPutStr2
> GHC.IO.Handle.FD.stdout lvl12_r3UF GHC.Types.True w_s3TA;
> ':' ->
> GHC.IO.Handle.Text.hPutStr2
> GHC.IO.Handle.FD.stdout lvl14_r3UH GHC.Types.True w_s3TA;
> '=' ->
> GHC.IO.Handle.Text.hPutStr2
> GHC.IO.Handle.FD.stdout lvl16_r3UJ GHC.Types.True w_s3TA;
> '@' ->
> GHC.IO.Handle.Text.hPutStr2
> GHC.IO.Handle.FD.stdout lvl18_r3UL GHC.Types.True w_s3TA;
> '_' ->
> GHC.IO.Handle.Text.hPutStr2
> GHC.IO.Handle.FD.stdout lvl20_r3UN GHC.Types.True w_s3TA;
> '~' ->
> GHC.IO.Handle.Text.hPutStr2
> GHC.IO.Handle.FD.stdout lvl22_r3UP GHC.Types.True w_s3TA
> }
> }}}
>
> This seems to be sub-optimal for instruction cache efficiency, the number
> of branches in generated machine code, code size, and understandability
> of the resulting Core. I would have expected something like,
>
> ```#!hs
> f x =
> let p = pred x
> in case p of
> True -> do_something
> False -> do_something_else
> ```
New description:
Consider a case analysis like this,
{{{#!hs
predicate c =
c == '-' || c == '_' || c == '.' || c == '~' || c == ':'
|| c == '@' || c == '&' || c == '=' || c == '+' || c == '$' || c ==
','
f x | predicate x = do_something
f x = do_something_else
main = f 'a'
}}}
GHC in some cases appears to produce Core for this example by constructing
a case analysis on `x`, replicating `do_something` in every branch,
{{{#!hs
$wa_r3UQ
:: GHC.Prim.Char#
-> GHC.Prim.State# GHC.Prim.RealWorld
-> (# GHC.Prim.State# GHC.Prim.RealWorld, () #)
[GblId, Arity=2, Str=DmdType <S,1*U><L,U>]
$wa_r3UQ =
\ (ww_s3TD :: GHC.Prim.Char#)
(w_s3TA [OS=OneShot] :: GHC.Prim.State# GHC.Prim.RealWorld) ->
case ww_s3TD of _ [Occ=Dead] {
__DEFAULT -> (# w_s3TA, GHC.Tuple.() #);
'$' ->
GHC.IO.Handle.Text.hPutStr2
GHC.IO.Handle.FD.stdout lvl2_r3Uv GHC.Types.True w_s3TA;
...
'_' ->
GHC.IO.Handle.Text.hPutStr2
GHC.IO.Handle.FD.stdout lvl20_r3UN GHC.Types.True w_s3TA;
'~' ->
GHC.IO.Handle.Text.hPutStr2
GHC.IO.Handle.FD.stdout lvl22_r3UP GHC.Types.True w_s3TA
}
}}}
This seems to be sub-optimal for instruction cache efficiency, the number
of branches in generated machine code, code size, and understandability of
the resulting Core. I would have expected something like,
{{{#!hs
f x =
let p = pred x
in case p of
True -> do_something
False -> do_something_else
}}}
--
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10120#comment:1>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list