[GHC] #8250: cgrun072 (optllvm) failing

GHC ghc-devs at haskell.org
Sat Sep 7 15:48:55 CEST 2013


#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




More information about the ghc-tickets mailing list