
#8250: cgrun072 (optllvm) failing -------------------------------------+------------------------------------ Reporter: leroux | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler (LLVM) | Version: 7.6.3 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Unknown/Multiple Type of failure: Runtime crash | Difficulty: Unknown Test Case: cgrun072 | Blocked By: Blocking: | Related Tickets: 7902 -------------------------------------+------------------------------------ Comment (by rwbarton): This is a sign-extension issue: the expected output is `2239642456 = 0x857e3b58`, which treated as a signed 32-bit integer is `2239642456 - 2^32 = -2055324840`. Obviously, `show` on a `Word32` shouldn't be producing output starting with a minus sign! * The NCG generates code for `MO_BSwap W32` that does the byte swap and clears the high 32 bits of the result. (This isn't directly relevant to this test failure, but provides context for the rest.) * The LLVM backend generates LLVM code that does the byte swap and then sign-extends the result to 64 bits, like this: {{{ %ln2uw = trunc i64 %ln2uv to i32 %ln2ux = call ccc i32 (i32)* @llvm.bswap.i32( i32 %ln2uw ) %ln2uy = sext i32 %ln2ux to i64 }}} The reason is that `genCallSimpleCast` does `castVars` before and after the call to `llvm.swap.i32`, and `castVars` produces `LM_Sext` for a widening conversion. That's what's causing the strange test output—the payload of a `Word32#` isn't supposed to have any of the high 32 bits set. * The primop `BSwap32Op` is documented as {{{ primop BSwap32Op "byteSwap32#" Monadic Word# -> Word# {Swap bytes in the lower 32 bits of a word. The higher bytes are undefined. } }}} so both the NCG and LLVM backends are correct, and the test is wrong. It should be doing {{{ bswap32 :: Word32 -> Word32 bswap32 (W32# w#) = W32# (narrow32Word# (byteSwap32# w#)) }}} and the same for `bswap16`. * The definitions of `byteSwap32` and `byteSwap16` in `GHC.Word` are also wrong for the same reason. They should be {{{ byteSwap32 :: Word32 -> Word32 byteSwap32 (W32# w#) = W32# (narrow32Word# (byteSwap32# w#)) }}} This doesn't currently make a difference, though, because base is built (by default?) with the NCG, which happens to produce a zero-extended result. An alternative approach would be to redefine the `BSwap32Op` primop to clear the higher bytes of its result. Then the LLVM backend would need to be fixed somehow (looks a little tricky to me) but the cgrun072 test and GHC.Word would be correct as they are. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/8250#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler