Skip to content

Mulitple comparisons on Word types produce redundant comparisons

The Ord and Eq instances that are derived for Word types seems to be inefficient (and appeared while writing a ByteString decoder for UTF8, which does a lot of Word8 matching).

The following code:

bad :: Word -> Bool
bad c | c < 1     = True  
      | c < 2     = True
      | otherwise = False

compiles to the rather horrible:

    case GHC.Prim.eqWord# ww_sXC __word 1 of wild2_aSC {
      GHC.Base.False ->
        case GHC.Prim.ltWord# ww_sXC __word 1 of wild_B1 {
          GHC.Base.False ->
            case GHC.Prim.eqWord# ww_sXC __word 2 of wild21_XUq {
              GHC.Base.False -> GHC.Prim.ltWord# ww_sXC __word 2;
              GHC.Base.True -> GHC.Base.False
            };
          GHC.Base.True -> GHC.Base.True
        };
      GHC.Base.True ->
        case GHC.Prim.eqWord# ww_sXC __word 2 of wild21_XUo {
          GHC.Base.False -> GHC.Prim.ltWord# ww_sXC __word 2;

In particular, notice the (<) on Word becomes a case eqWord# of case ltWord# of ...

While the equivalent at an Int type, using the hand written Ord/Eq instances in GHC.Base, produces:

M.good =
  \ (c_ag0 :: GHC.Base.Int) ->
    case c_ag0 of wild_aRF { GHC.Base.I# x_aRH ->
    case GHC.Prim.<# x_aRH 1 of wild1_B1 {
      GHC.Base.False -> GHC.Prim.<# x_aRH 2; GHC.Base.True -> GHC.Base.True
    }
    }

The poor code only seems to be generated if there's more than 1 comparison against the value.

If I manually wrap Word, and write an instance Eq and Ord for it, based on the ones for Int (attached), we get identical code to the Int case:

M.good =
  \ (c_agn :: M.MyWord) ->
    case c_agn `cast` ((M.:CoMyWord) :: M.MyWord ~ GHC.Word.Word)

    of wild_B1 { GHC.Word.W# x_agV ->
        case GHC.Prim.ltWord# x_agV __word 1 of wild1_X33 {
          GHC.Base.False -> GHC.Prim.ltWord# x_agV __word 2;
          GHC.Base.True -> GHC.Base.True
    }
    }

The Ord and Eq instances for Word seem to be deeply magic:

data Word = W# Word# deriving (Eq, Ord)

Are the instances wired in?

The solution to this might be to have similar instances of Eq and Ord for Word, as for Int, or to change the built-in deriving.

Trac metadata
Trac field Value
Version 6.8.2
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler
Test case
Differential revisions
BlockedBy
Related
Blocking
CC dons@galois.com
Operating system Multiple
Architecture Unknown
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information