Inconsistent treatment of signedness of Cmm literals
Consider these Cmm programs:
testA() { return ( 0x8000000000000000::bits64 ); }
testB() { return ( -0x8000000000000000::bits64 ); }
testC() { return (%quot( 0x8000000000000000::bits64, 2)); }
testD() { return (%quot(-0x8000000000000000::bits64, 2)); }
In general, one wouldn't expect that 0x8000000000000000::bits64
and -0x8000000000000000::bits64
differ semantically, given that we assume a two's complement sign representation.
In the case of testA
and testB
GHC respects this expectation. However, in the case of testC
and testD
there is a surprising difference:
Program Value emitted in assembler
----------- ---------------------------
`testA` `-9223372036854775808`
`testB` `-9223372036854775808`
`testC` ` 4611686018427387904`
`testD` `-4611686018427387904`
That is, while we produce the correct result in testD
, in testC
we silently drop the sign bit. Given that this same behavior is not observed in testA
and testB
, I can only assume that this is some constant folding going awry.