truncate = float2Int rule is incorrect
This is only on powerpc...
$ cat Test.hs
module Main where
f = read "2147483648" :: Float -- Hack to prevent inlining
main = print (truncate f :: Int)
b@brian:~$ ghc -no-recomp -O Test.hs && ./a.out
2147483647
b@brian:~$ ghc -no-recomp -O Test.hs -frules-off && ./a.out
-2147483648
In GHC.Float we have
{-# RULES "truncate/Float->Int" truncate = float2Int #-}
...
float2Int (F# x) = I# (float2Int# x)
But when there is oveflow float2Int# on PPC doesn't behave the same way as fromIntegral . (truncate::Float -> Integer), it does on x86 though.
I'm not sure if this should be fixed in the libraries or in the codegen. I'd probably argue that float2Int# should stay the same though, so programmers have access to a fast float to int conversion when they know overflow isn't an issue. Something like uncheckedFloat2Int# (like the shift ops) with a float2Int# wrapper is probably right.
As a side note, the builtin rule in PrelRules for float2Int is also incorrect as it goes via Integer. If float2Int# in the codegen is modified this will become correct but if the uncheckedFloat2Int# route is taken then that rule should probably be fixed.
I may fix this sometime, but for now I just wanted to document it.
Trac metadata
| Trac field | Value |
|---|---|
| Version | 6.7 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | lowest |
| Resolution | Unresolved |
| Component | libraries/base |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | Multiple |
| Architecture |