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