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)
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.
It won't matter. In code generation, that case will turn into a simple comparison and conditional jump. That's what always happens for such small case expressions. There are definitely times when this translation of ==# is unfortunate, making code that has a lot of poorly predicted branches, but that does not apply to the example you give.
To clarify, I'm talking about the inner case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With