Search code examples
haskelloptimizationghcunboxing

Helping GHC unbox an Int in equality on a constant


Here is a test program:

main = do
    n <- fmap read $ getLine :: IO Int
    if (999999 == n) then putStrLn "equal" else return ()

And here is the relevant bit of core when compiled with ghc --make -O2 -ddump-to-file -ddump-simpl -dsuppress-module-prefixes -dsuppress-uniques -ddump-core-stats -ddump-inlinings:

case readEither6 @ Int (run @ Int main3 ipv1) of _ [Occ=Dead] {
  [] -> case error @ Int readEither4 of wild1 { };
  : x ds1 ->
    case ds1 of _ [Occ=Dead] {
      [] ->
        case x of _ [Occ=Dead] { I# ipv2 ->
        case ipv2 of _ [Occ=Dead] {
          __DEFAULT -> (# ipv, () #);
          999999 -> hPutStr2 stdout main2 True ipv
        }
        };
      : ipv2 ipv3 -> case error @ Int readEither2 of wild2 { }
    }

I'm wondering if the case match on the literal 999999 is really the most efficient thing here, and if not how can I encourage GHC to turn this into a call to ==# or something?

(My actual application is more involved)


Solution

  • On my Ubuntu box, the relevant core code compiled to this

    406168: 48 81 7b 07 3f 42 0f    cmpq   $0xf423f,0x7(%rbx)
    40616f: 00 
    406170: 75 28                   jne    40619a <c4fz_info+0x32>
    406172: bf 52 e3 6d 00          mov    $0x6de352,%edi
    406177: be 90 65 6d 00          mov    $0x6d6590,%esi
    40617c: 41 be 18 6a 6d 00       mov    $0x6d6a18,%r14d
    406182: 48 83 c5 08             add    $0x8,%rbp
    406186: e9 65 3c 00 00          jmpq   409df0 <base_GHCziIOziHandleziText_hPutStr2_info>
    

    The first to third line are basically equivalant to the c code

    if (variable == 999999) { ....
    

    Which is about as optimal as you can get.