[GHC] #10120: Unnecessary code duplication from case analysis

GHC ghc-devs at haskell.org
Fri Feb 27 05:39:43 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 (generated by GHC 7.10),
>
> {{{#!hs
> $wa_r3UQ =
>   \ ww_s3TC w_s3Tz ->
>     case ww_s3TC of _ {
>       __DEFAULT -> (# w_s3Tz, () #);
>       '$' -> hPutStr2 stdout lvl2_r3Uv True w_s3Tz;
>       '&' -> hPutStr2 stdout lvl4_r3Ux True w_s3Tz;
>       ...
>       '_' -> hPutStr2 stdout lvl20_r3UN True w_s3Tz;
>       '~' -> hPutStr2 stdout lvl22_r3UP True w_s3Tz
>     }
> }}}
>
> 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
 (generated by GHC 7.10),

 {{{#!hs
 $wa_r3UQ =
   \ ww_s3TC w_s3Tz ->
     case ww_s3TC of _ {
       __DEFAULT -> (# w_s3Tz, () #);
       '$' -> hPutStr2 stdout lvl2_r3Uv True w_s3Tz;
       '&' -> hPutStr2 stdout lvl4_r3Ux True w_s3Tz;
       ...
       '_' -> hPutStr2 stdout lvl20_r3UN True w_s3Tz;
       '~' -> hPutStr2 stdout lvl22_r3UP True w_s3Tz
     }
 }}}

 In some cases where `do_something` is large this can lead to a substantial
 increase in code size.

 There are really two issues here,

  1. That a branch-y case analysis is being used for a boolean condition
  2. That `do_something` is being inlined into each branch

 This seems to be sub-optimal for instruction cache efficiency, the number
 of branches in generated machine code, 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:6>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list