[GHC] #10521: Wrong results in strict Word8 storage on x64

GHC ghc-devs at haskell.org
Tue Jun 16 15:29:26 UTC 2015


#10521: Wrong results in strict Word8 storage on x64
-------------------------------------+-------------------------------------
        Reporter:  VincentBerthoux2  |                   Owner:
            Type:  bug               |                  Status:  new
        Priority:  highest           |               Milestone:  7.10.2
       Component:  Compiler          |                 Version:  7.10.1
      Resolution:                    |                Keywords:
Operating System:  Unknown/Multiple  |            Architecture:  x86_64
 Type of failure:  Incorrect result  |  (amd64)
  at runtime                         |               Test Case:
      Blocked By:                    |                Blocking:
 Related Tickets:                    |  Differential Revisions:
-------------------------------------+-------------------------------------

Comment (by rwbarton):

 I reduced the test case further to
 {{{
 import Data.Word( Word8 )

 toV :: Float -> Word8
 toV d = let coeff = significand d *  255.9999 / d
             a = truncate $ d * coeff
             b = exponent d
         in a `seq` (b `seq` a)  -- just   b `seq` a   is not enough to
 reproduce the bug

 main :: IO ()
 main =
   print $ map toV [ 3.56158e-2, 0.7415215, 0.5383201, 0.1289829,
 0.45520145 ]
 }}}

 It's looking like an issue in the backend where it doesn't understand that
 F1 and D1 are the same physical register (%xmm1) on x86_64. Possibly an
 old issue that was uncovered by 7.10's new implementation of `significand
 :: Float -> Float` going through Double.

 Specifically for the (correct) Core
 {{{
 Main.main14 =
   \ (d_aC5 [OS=ProbOneShot] :: Float) ->
     case d_aC5 of _ [Occ=Dead] { GHC.Types.F# x_a22N ->
     case GHC.Prim.decodeFloat_Int# x_a22N
     of _ [Occ=Dead] { (# ipv_a1Gg, ipv1_a1Gh #) ->
     case integer-gmp-1.0.0.0:GHC.Integer.Type.encodeDoubleInteger
            (integer-gmp-1.0.0.0:GHC.Integer.Type.smallInteger ipv_a1Gg)
 (-24)
     of wild1_a1Gj { __DEFAULT ->
     case GHC.Float.$w$cexponent1 x_a22N of _ [Occ=Dead] { __DEFAULT ->
     case GHC.Prim.divideFloat#
            (GHC.Prim.timesFloat#
               (GHC.Prim.double2Float# wild1_a1Gj) (__float 255.9999))
            x_a22N
     of wild2_a234 { __DEFAULT ->
     GHC.Word.W8#
       (GHC.Prim.narrow8Word#
          (GHC.Prim.int2Word#
             (GHC.Prim.float2Int# (GHC.Prim.timesFloat# x_a22N
 wild2_a234))))
     }
     }
     }
     }
     }
 }}}
 we generate Cmm like
 {{{
 ...
        c3MY:
            I64[Sp] = c3N2;
            R3 = (-24);
            R2 = R1;
            call GHC.Integer.Type.encodeDoubleInteger_info(R3,
                                                           R2) returns to
 c3N2, args: 8, res: 8, upd: 8;
        c3N2:
            I64[Sp - 8] = c3N6;
            F1 = F32[Sp + 8];
            F64[Sp] = D1;
            Sp = Sp - 8;
            call GHC.Float.$w$cexponent1_info(F1) returns to c3N6, args: 8,
 res: 8, upd: 8;
 ...
 }}}

 The assignment to F1 is to set up the arguments for `$w$cexponent1` from
 `x_a22N` which has been saved on the stack, and the read from D1 is to
 save the return value `wild1_a1Gj` from `encodeDoubleInteger`. Technically
 the program became incorrect in the "Sink assignments" pass when the read
 from D1 was moved past the store to F1, but maybe it just doesn't make
 sense to cater to the possibility of multiple STG global registers being
 aliases of one another.

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10521#comment:5>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list