#2625: Unexpected -ddump-simpl output for derived Ord instance and UNPACKed 
fields
------------------------------+---------------------------------------------
 Reporter:  aslatter          |          Owner:                
     Type:  bug               |         Status:  new           
 Priority:  low               |      Milestone:  _|_           
Component:  Compiler          |        Version:  6.8.3         
 Severity:  normal            |     Resolution:                
 Keywords:                    |     Difficulty:  Unknown       
 Testcase:                    |   Architecture:  x86_64 (amd64)
       Os:  Unknown/Multiple  |  
------------------------------+---------------------------------------------
Changes (by simonpj):

  * priority:  normal => low
  * milestone:  6.10 branch => _|_

Comment:

 Here's what is happening.  The compare functions for A and B look like
 this (initially):
 {{{
 compareA :: A -> A -> Ordering
 compareA (A x1 .. x8) (A y1 .. y8)
   = compare (B x1 .. x8) (B y1 .. y8)

 compareB :: B -> B -> Ordering
 compareB (B x1 .. x8) (B y1 .. y8)
   = if x1>y1 then GT else ... blah blah blah...
 }}}
 Note that the signature of `compareB` '''must''' be `B -> B -> Ordering`,
 so `compareA` is obliged to re-box the B argument.  That always
 potentially happens when you use `{-# UNPACK #-}`: if you match on the
 constructor you may need to construct a value of the unpacked type to pass
 on to some other function.

 OK after strictness analysis you might hope that `compareB` gets 16
 arguments.  But GHC is wary about giving workers an arbitrarily large
 number of arguments, so it has an arbitrary threshold of 10.  As a result,
 the worker for `compareB` looks like this:
 {{{
 $wcompareB :: Int# -> ... -> Int# -> B -> Ordering
 $wcompareB x1 .. x8 (B y1 .. y8) = <blah>
 }}}
 The first argument is unpacked but not the second.  And that is what is
 happening to you.

 I don't know a good solution in general.  `{-# UNPACK #-}` can (and must)
 lead to the possibility of reboxing.  (In this case `compareB` is strict,
 so its wrapper may do unboxing ,up to the threshold, but in general the
 called function may be lazy.)

 There is a workaround here: the flag `-fmax-worker-args=N` will change the
 threshold
  to N, and that fixes the problem.  But it's not a ''satisfying'' fix.

 I'll leave this open at low priority.   By all means contribute
 suggestions!

 Simon

-- 
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/2625#comment:3>
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