Ticket #2209 (closed merge: fixed)

Opened 5 years ago

Last modified 5 years ago

MagicHash extraction is wrong on x86_64 with -fasm -O2

Reported by: quark Owned by: igloo
Priority: normal Milestone: 6.8.3
Component: Compiler Version: 6.8.2
Keywords: Cc: ravi
Operating System: Linux Architecture: x86_64 (amd64)
Type of failure: Difficulty: Unknown
Test Case: Blocked By:
Blocking: Related Tickets:

Description

I am trying to directly get at the underlying IEEE representation of a Double with this code:

  word64ToDouble :: Word64 -> Double
  word64ToDouble w@(W64# x) = D# (unsafeCoerce# x)

  doubleToWord64 :: Double -> Word64
  doubleToWord64 d@(D# x) = W64# (unsafeCoerce# x)

I have, of course, checked "isEEE x" and "(sizeOf x) == 8" etc, to know that it is OK to do this.

This works on various x86 computers but fails on x86_64, when compiling with -fasm and -O2 (which I embedded with the OPTIONS pragma in the attached example).

The example shows that for a Double "2.0", the Word64 is wrong. And for a Word64 which should represent Nan, "isNaN" fails. Here is the output of the program on "x86_64" (the buggy system):

  False: NaN
  5697656
  expect: 4611686018427387904

Here is the expected output as seen on x86 systems:

  True
  4611686018427387904
  expect: 4611686018427387904

Note that if you insert a "trace" call to display the Integer, Word64, or Double, the example gives the right output! But when you take out the trace, it fails.

If a workaround for this problem can be identified, we would really appreciate it, as we are hitting this bug in code that we need to use but cannot workaround. If a fix is identified, it would be great if the fix made it into 6.8.3 (as we are happy to upgrade to that, rather than wait for a next stable release).

In our system, we do have a workaround for the "doubleToWord64" bug, but I cannot reproduce it in the small example. What we do is define the function like this:

  doubleToWord64 :: Double -> Word64
  doubleToWord64 d@(D# x) =
      if (d == d)
      then W64# (unsafeCoerce# x)
      else err ("doubleToWord64 " ++ show d)

This works in out system, but not in the attached example. And, again, we have no workaround for "word64ToDouble".

Attachments

Main_bug.hs Download (0.7 KB) - added by quark 5 years ago.

Change History

Changed 5 years ago by quark

  Changed 5 years ago by ravi

  • cc ravi added

follow-up: ↓ 3   Changed 5 years ago by igloo

  • difficulty set to Unknown
  • milestone set to 6.8.3

In my validated-HEAD, this gives me

/tmp/ghc4469_0/ghc4469_0.s:460:0:
     Error: suffix or operands invalid for `test'

/tmp/ghc4469_0/ghc4469_0.s:463:0:
     Error: suffix or operands invalid for `test'

/tmp/ghc4469_0/ghc4469_0.s:474:0:
     Error: suffix or operands invalid for `movsd'

complaining about these 3 lines:

    testq %xmm0,%xmm0
    testq %xmm0,%xmm0
    movsd .Ln1c1(%rip),%rsi

We do claim that this ("Casting an unboxed type to another unboxed type of the same size") works in the unsafeCoerce# docs, so we ought to fix it!

in reply to: ↑ 2   Changed 5 years ago by simonmar

  • owner set to simonmar

Replying to igloo:

We do claim that this ("Casting an unboxed type to another unboxed type of the same size") works in the unsafeCoerce# docs, so we ought to fix it!

I'm tempted to alter the docs here. The problem is that the Cmm generated for this program has a type error, which you can see by compiling with -dcmm-lint. This breaks some assumptions that the native code generator is making, with the result that it ends up being confused about floating point vs. scalar register assignments.

You can achieve the desired effect using castSTUArray, incedentally (this is the way we do it in GHC).

To make the direct coercion work, we'd have to make the unsafeCoerce# really compile into an operation at the Cmm level. Which is possible, but we'd have to add new primitives for the operation (the current float->int conversions do truncation, not bit-for-bit conversion), and add some code to CoreToStg? to generate the operations.

  Changed 5 years ago by simonmar

  • owner changed from simonmar to igloo
  • type changed from bug to merge

docs updated. could be merged:

Tue May 27 02:02:44 PDT 2008  Simon Marlow <marlowsd@gmail.com>
  * clarify that unsafeCoerce# :: Float# -> Int# is not safe (see #2209)

  Changed 5 years ago by igloo

  • status changed from new to closed
  • resolution set to fixed

Merged

Note: See TracTickets for help on using tickets.