
#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