[commit: testsuite] master: Test for #7600. (5aae346)
David Terei
davidterei at gmail.com
Thu Jan 17 09:39:21 CET 2013
Repository : ssh://darcs.haskell.org//srv/darcs/testsuite
On branch : master
http://hackage.haskell.org/trac/ghc/changeset/5aae346f6b4fb8c580491221e02df842df1612b0
>---------------------------------------------------------------
commit 5aae346f6b4fb8c580491221e02df842df1612b0
Author: David Terei <davidterei at gmail.com>
Date: Thu Jan 17 00:24:38 2013 -0800
Test for #7600.
>---------------------------------------------------------------
tests/codeGen/should_run/T7600.hs | 111 +++++++++++++++++++++++++++++++++
tests/codeGen/should_run/T7600.stdout | 2 +
tests/codeGen/should_run/T7600_A.hs | 83 ++++++++++++++++++++++++
tests/codeGen/should_run/all.T | 2 +
4 files changed, 198 insertions(+), 0 deletions(-)
diff --git a/tests/codeGen/should_run/T7600.hs b/tests/codeGen/should_run/T7600.hs
new file mode 100644
index 0000000..9f0e118
--- /dev/null
+++ b/tests/codeGen/should_run/T7600.hs
@@ -0,0 +1,111 @@
+-- !!! Bug # 7600.
+-- The LLVM backend can be tricky to get right with floating point constants
+-- and GHC. See Note [LLVM Float Types] in compiler/llvmGen/Llvm/Types.hs for
+-- why this is.
+--
+-- Two issues to watch for (that this bug tries to track):
+--
+-- 1) We need to narrow a double to a float but then expand back out (so that
+-- we end up with the precision of a float but in double precision byte form).
+-- GHC seems to optimize this away for some ways of doing this.
+--
+-- 2) The 'realToFrac' method returns different results at the byte level
+-- depending on if optimisations are on or off. We use the double2float and
+-- float2Double methods instead as they don't suffer from this.
+--
+-- Also worth looking at ticket # 3676 about issues with 'realToFrac'.
+module Main (main) where
+
+import T7600_A
+
+-- a fp constant that requires double precision, but we only use a single
+-- precision type.
+-- expected output: float 0x7FF0000000000000
+float_number :: Float
+float_number = 1.82173691287639817263897126389712638972163e+300
+
+-- as above but use double precision so we can represent it.
+-- expected output: double 0x7E45C3163C1ACF96
+double_number :: Double
+double_number = 1.82173691287639817263897126389712638972163e+300
+
+-- Test run
+main :: IO ()
+main = test_run float_number double_number
+
+
+
+-- XXX: We don't run below, but it can be useful to test how the optimizer is
+-- running... the NOINLINE pragmas are needed below generally, but often not
+-- for Bug31_A as the constant is in a different module...
+
+-- -- Test run
+-- test_run' :: Float -> Double -> IO ()
+-- test_run' float_number double_number = do
+-- print $ dToStr double_number
+-- print $ dToStr (widen $ narrow double_number)
+-- print $ dToStr (widen' $ narrow' double_number)
+-- let dd = case double_number of { (D# x) -> x }
+-- print $ dToStr (D# (float2Double# (double2Float# dd)))
+--
+-- -- use standard Haskell functions for type conversion... which are kind of
+-- -- insane (see ticket # 3676) [these fail when -O0 is used...]
+-- {-# NOINLINE narrow #-}
+-- narrow :: Double -> Float
+-- narrow = realToFrac
+--
+-- {-# NOINLINE widen #-}
+-- widen :: Float -> Double
+-- widen = realToFrac
+--
+-- -- use GHC specific functions which work as expected [work for both -O0 and -O]
+-- {-# NOINLINE narrow' #-}
+-- narrow' :: Double -> Float
+-- narrow' = double2Float
+--
+-- {-# NOINLINE widen' #-}
+-- widen' :: Float -> Double
+-- widen' = float2Double
+--
+-- doubleToBytes :: Double -> [Int]
+-- doubleToBytes d
+-- = runST (do
+-- arr <- newArray_ ((0::Int),7)
+-- writeArray arr 0 d
+-- arr <- castDoubleToWord8Array arr
+-- i0 <- readArray arr 0
+-- i1 <- readArray arr 1
+-- i2 <- readArray arr 2
+-- i3 <- readArray arr 3
+-- i4 <- readArray arr 4
+-- i5 <- readArray arr 5
+-- i6 <- readArray arr 6
+-- i7 <- readArray arr 7
+-- return (map fromIntegral [i0,i1,i2,i3,i4,i5,i6,i7])
+-- )
+--
+-- castFloatToWord8Array :: STUArray s Int Float -> ST s (STUArray s Int Word8)
+-- castFloatToWord8Array = castSTUArray
+--
+-- castDoubleToWord8Array :: STUArray s Int Double -> ST s (STUArray s Int Word8)
+-- castDoubleToWord8Array = castSTUArray
+--
+-- dToStr :: Double -> String
+-- dToStr d
+-- = let bs = doubleToBytes d
+-- hex d' = case showHex d' "" of
+-- [] -> error "dToStr: too few hex digits for float"
+-- [x] -> ['0',x]
+-- [x,y] -> [x,y]
+-- _ -> error "dToStr: too many hex digits for float"
+--
+-- str = map toUpper $ concat . fixEndian . (map hex) $ bs
+-- in "0x" ++ str
+--
+-- fixEndian :: [a] -> [a]
+-- -- #ifdef WORDS_BIGENDIAN
+-- -- fixEndian = id
+-- -- #else
+-- fixEndian = reverse
+-- -- #endif
+
diff --git a/tests/codeGen/should_run/T7600.stdout b/tests/codeGen/should_run/T7600.stdout
new file mode 100644
index 0000000..d37bad0
--- /dev/null
+++ b/tests/codeGen/should_run/T7600.stdout
@@ -0,0 +1,2 @@
+"0x7E45C3163C1ACF96"
+"0x7FF0000000000000"
diff --git a/tests/codeGen/should_run/T7600_A.hs b/tests/codeGen/should_run/T7600_A.hs
new file mode 100644
index 0000000..52c28cb
--- /dev/null
+++ b/tests/codeGen/should_run/T7600_A.hs
@@ -0,0 +1,83 @@
+-- !!! Bug # 7600.
+-- See file T7600 for main description.
+{-# LANGUAGE CPP #-}
+module T7600_A (test_run) where
+
+import Control.Monad.ST
+import Data.Array.Unsafe( castSTUArray )
+import Data.Array.ST hiding( castSTUArray )
+import Data.Char
+import Data.Word
+import Numeric
+
+import GHC.Float
+
+-- Test run
+test_run :: Float -> Double -> IO ()
+test_run float_number double_number = do
+ print $ dToStr double_number
+ -- XXX: Below is the bad code due to changing with optimisation.
+ -- print $ dToStr (widen $ narrow double_number)
+ print $ dToStr (widen' $ narrow' double_number)
+
+-- use standard Haskell functions for type conversion... which are kind of
+-- insane (see ticket # 3676) [these fail when -O0 is used...]
+narrow :: Double -> Float
+{-# NOINLINE narrow #-}
+narrow = realToFrac
+
+widen :: Float -> Double
+{-# NOINLINE widen #-}
+widen = realToFrac
+
+-- use GHC specific functions which work as expected [work for both -O0 and -O]
+narrow' :: Double -> Float
+{-# NOINLINE narrow' #-}
+narrow' = double2Float
+
+widen' :: Float -> Double
+{-# NOINLINE widen' #-}
+widen' = float2Double
+
+doubleToBytes :: Double -> [Int]
+doubleToBytes d
+ = runST (do
+ arr <- newArray_ ((0::Int),7)
+ writeArray arr 0 d
+ arr <- castDoubleToWord8Array arr
+ i0 <- readArray arr 0
+ i1 <- readArray arr 1
+ i2 <- readArray arr 2
+ i3 <- readArray arr 3
+ i4 <- readArray arr 4
+ i5 <- readArray arr 5
+ i6 <- readArray arr 6
+ i7 <- readArray arr 7
+ return (map fromIntegral [i0,i1,i2,i3,i4,i5,i6,i7])
+ )
+
+castFloatToWord8Array :: STUArray s Int Float -> ST s (STUArray s Int Word8)
+castFloatToWord8Array = castSTUArray
+
+castDoubleToWord8Array :: STUArray s Int Double -> ST s (STUArray s Int Word8)
+castDoubleToWord8Array = castSTUArray
+
+dToStr :: Double -> String
+dToStr d
+ = let bs = doubleToBytes d
+ hex d' = case showHex d' "" of
+ [] -> error "dToStr: too few hex digits for float"
+ [x] -> ['0',x]
+ [x,y] -> [x,y]
+ _ -> error "dToStr: too many hex digits for float"
+
+ str = map toUpper $ concat . fixEndian . (map hex) $ bs
+ in "0x" ++ str
+
+fixEndian :: [a] -> [a]
+#ifdef WORDS_BIGENDIAN
+fixEndian = id
+#else
+fixEndian = reverse
+#endif
+
diff --git a/tests/codeGen/should_run/all.T b/tests/codeGen/should_run/all.T
index 456f2c2..a8c5a0a 100644
--- a/tests/codeGen/should_run/all.T
+++ b/tests/codeGen/should_run/all.T
@@ -104,3 +104,5 @@ test('Word2Float32', unless_wordsize(32, skip), compile_and_run, [''])
test('Word2Float64', unless_wordsize(64, skip), compile_and_run, [''])
test('T7361', normal, compile_and_run, [''])
+test('T7600', normal, compile_and_run, [''])
+
More information about the ghc-commits
mailing list