[GHC] #15696: Derived Ord instance for enumerations with more than 8 elements seems to be incorrect

GHC ghc-devs at haskell.org
Thu Oct 4 07:54:23 UTC 2018


#15696: Derived Ord instance for enumerations with more than 8 elements seems to be
incorrect
-------------------------------------+-------------------------------------
        Reporter:  mrkkrp            |                Owner:  (none)
            Type:  bug               |               Status:  patch
        Priority:  highest           |            Milestone:  8.6.2
       Component:  Compiler          |              Version:  8.6.1
      Resolution:                    |             Keywords:
Operating System:  Unknown/Multiple  |         Architecture:
 Type of failure:  Incorrect result  |  Unknown/Multiple
  at runtime                         |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):  Phab:D5196,
       Wiki Page:                    |  Phab:D5201
-------------------------------------+-------------------------------------
Changes (by osa1):

 * differential:  Phab:D5196 => Phab:D5196, Phab:D5201


Comment:

 > As for the type-driven rewriting

 This is not possible unless we somehow distinguish "stuff that directly
 points to a value (without going through indirections)" from other at the
 type level.

 ----

 I submitted another diff that fixes this bug in Cmm. It also does a bunch
 of simplifications in other parts of the compiler (removes notes, special
 cases, and hacks for `dataToTag#`). Here are some example code we
 generate:

 Program:

 {{{
 data T = T1 | T2

 main = do
     print (I# (dataToTag# f))
     print (I# (dataToTag# a))
   where
     {-# NOINLINE f #-}
     f = T2
     {-# NOINLINE a #-}
     a = f
 }}}

 For the first `dataToTag#` we generate:

 {{{
 _s1yo::I64 = 1;   // CmmAssign
 }}}

 for the second

 {{{
     // ======= DATA TO TAG ========
     Hp = Hp - 16;   // CmmAssign
     I64[Sp - 24] = c1yE;   // CmmStore
     R1 = a_r1lF_closure;   // CmmAssign
     Sp = Sp - 24;   // CmmAssign
     if (R1 & 7 != 0) goto c1yE; else goto c1yF;   // CmmCondBranch
 c1yF: // global
     call (I64[R1])(R1) returns to c1yE, args: 8, res: 8, upd: 24;   //
 CmmCall, this is where we evalaute the arg
 c1yE: // global
     _c1yD::I64 = R1;   // CmmAssign
     // ======= DATA TO TAG SMALL FAMILY ========
     _s1yr::I64 = _c1yD::I64 & 7 - 1;   // CmmAssign, read the tag bits
 }}}

 If I make this type a "big family", then we generate (for the second
 `dataToTag#`)

 {{{
     // ======= DATA TO TAG ========
     Hp = Hp - 16;   // CmmAssign
     I64[Sp - 24] = c1A0;   // CmmStore
     R1 = a_r1mL_closure;   // CmmAssign
     Sp = Sp - 24;   // CmmAssign
     if (R1 & 7 != 0) goto c1A0; else goto c1A1;   // CmmCondBranch
 c1A1: // global
     call (I64[R1])(R1) returns to c1A0, args: 8, res: 8, upd: 24;   //
 CmmCall, enter the argument
 c1A0: // global
     _c1zZ::I64 = R1;   // CmmAssign
     // ======= DATA TO TAG GENERAL CASE ========
     _s1zN::I64 = %MO_UU_Conv_W32_W64(I32[I64[_c1zZ::I64 & (-8)] - 4]);
 // CmmAssign, read info table
 }}}

 The patch is not ready (I'll need to update some notes, I also left some
 TODOs and questions in the code) but it fixes the bug and demonstrates
 that this is possible (and even easy) to do in Cmm.

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


More information about the ghc-tickets mailing list