
#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