#5161: Poor performance of division; unnecessary branching
------------------------------------------------------------+---------------
    Reporter:  rtvd                                         |        Owner:     
                    
        Type:  bug                                          |       Status:  
patch                  
    Priority:  normal                                       |    Milestone:     
                    
   Component:  libraries/base                               |      Version:  
7.0.3                  
    Keywords:  div quot rem mod performance slow branching  |     Testcase:     
                    
   Blockedby:                                               |   Difficulty:     
                    
          Os:  Unknown/Multiple                             |     Blocking:     
                    
Architecture:  Unknown/Multiple                             |      Failure:  
Runtime performance bug
------------------------------------------------------------+---------------

Comment(by simonpj):

 Your changes replace the guard
 {{{
    | x == minBound && y == (-1) = overflowError
 }}}
 by
 {{{
    | y == (-1) && x == minBound = overflowError
 }}}
 At first I couldn't see how this would make any difference.   After all,
 if `y` is 2 (say), then the overflow case is statically inaccessible, so
 the test should vanish. Here's why it doesn't.  Initially we have
 something roughly like this:
 {{{
 quot x y = case x of
              -9223372036854775808 -> case y of
                                         -1 -> overflowError
                                         DEFAULT -> x `quot#` y
              DEFAULT -> x `quot#` y
 }}}
 (I'm omitting the unboxing etc.)

 Now if we have the call {{{(p `quot` 2)}}}, and we inline `quot` we get:
 {{{
   case p of
     -9223372036854775808 -> case 2 of
                               -1 -> overflowError
                               DEFAULT -> p `quot#` 2
     DEFAULT -> p `quot#` 2
 }}}
 The inner case simplifies, leaving
 {{{
   case p of
     -9223372036854775808 -> p `quot#` 2
     DEFAULT              -> p `quot#` 2
 }}}
 At this point I thought we'd just have a case with two identical branches,
 which is eliminated (assuming it doesn't affect strictness, which it
 doesn't in this case), leaving the desired {{{(p `quot#` 1)}}}.

 BUT in the `minBound` branch we know what `p` is, and GHC cleverly does
 the division at compile time, giving
 {{{
   case p of
     -9223372036854775808 -> -4611686018427387904
     DEFAULT              -> p `quot#` 2
 }}}
 Darn!  Now the branches aren't identical!

 By switching the order of tests you've stopped this happening.  But it'll
 happen instead if you have a constant '''numerator'''.  The term {{{(2
 `quot` q)}}} will turn into
 {{{
 case q of
   -1      -> 0
   DEFAULT -> 2 `quot#` q
 }}}
 Constant denominators are more common than constant numerators, so I think
 your patch is a good one -- Ian can you apply please?  ''But also can you
 add this Trac comment into the code with `Note [Ordering of tests]` or
 something, and point to it from the test sites?''

 I wish I could see a good way to make GHC generate the best code
 regardless of test ordering.  I can think of some un-satisfying solutions:
  * Delay constant folding until a later phase
  * Delay case-of-case until a later phase
 but neither are great. Phase ordering is very delicate and non-modular.

-- 
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/5161#comment:2>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler

_______________________________________________
Glasgow-haskell-bugs mailing list
Glasgow-haskell-bugs@haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs

Reply via email to