Literal Pattern match loses order
I found this long-standing bug while investigating #10245 (closed):
Consider this code:
f1 :: Int -> String
f1 n = case n of
0 -> "bar"
0x10000000000000000 -> "foo"
_ -> "c"
{-# NOINLINE f1 #-}
g1 :: Int -> String
g1 n = if n == 0 then "bar" else
if n == 0x10000000000000000 then "foo" else
"c"
{-# NOINLINE g1 #-}
f2 :: Int -> String
f2 n = case n of
0x10000000000000000 -> "foo"
0 -> "bar"
_ -> "c"
{-# NOINLINE f2 #-}
g2 :: Int -> String
g2 n = if n == 0x10000000000000000 then "foo" else
if n == 0 then "bar" else
"c"
{-# NOINLINE g2 #-}
main = do
let i = read "0" :: Int
print (f1 i)
print (g1 i)
print (f2 i)
print (g2 i)
According to the report, f1 should behave like g1 and f2 should behave like g2. But that is not the case: I get
"foo"
"bar"
"foo"
"foo"
The reason is that the branches are sorted, to create fancy code for it, but this does not take into account that 0x10000000000000000 = 0, at least for Int.
This bug is present also in 7.8.4, and not (directly) related to my CmmSwitch code: It can also be observed with interpreted code, so the fix must happen earlier.
Edited by Ben Gamari