X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=compiler%2Futils%2FFastTypes.lhs;h=ace46e6e1b344830f4c8536cfc83de296f6d2f0b;hp=c58346d3f8890c1ece64052eb49b1d48324efcc4;hb=914e415702a25a6e52ab1eaaf2aea233d6c6097e;hpb=046ee54f048ddd721dcee41916d6a6f68db3b15b diff --git a/compiler/utils/FastTypes.lhs b/compiler/utils/FastTypes.lhs index c58346d..ace46e6 100644 --- a/compiler/utils/FastTypes.lhs +++ b/compiler/utils/FastTypes.lhs @@ -1,15 +1,63 @@ % % (c) The University of Glasgow, 2000-2006 % -\section{Fast integers and booleans} +\section{Fast integers, etc... booleans moved to FastBool for using panic} \begin{code} + +--Even if the optimizer could handle boxed arithmetic equally well, +--this helps automatically check the sources to make sure that +--it's only used in an appropriate pattern of efficiency. +--(it also makes `let`s and `case`s stricter...) + +-- | Fast integers, characters and pointer types for use in many parts of GHC module FastTypes ( - FastInt, _ILIT, iBox, iUnbox, + -- * FastInt + FastInt, + + -- ** Getting in and out of FastInt + _ILIT, iBox, iUnbox, + + -- ** Arithmetic on FastInt (+#), (-#), (*#), quotFastInt, negateFastInt, - (==#), (<#), (<=#), (>=#), (>#), + --quotRemFastInt is difficult because unboxed values can't + --be tupled, but unboxed tuples aren't portable. Just use + -- nuisance boxed quotRem and rely on optimization. + (==#), (/=#), (<#), (<=#), (>=#), (>#), + minFastInt, maxFastInt, + --prefer to distinguish operations, not types, between + --signed and unsigned. + --left-shift is the same for 'signed' and 'unsigned' numbers + shiftLFastInt, + --right-shift isn't the same for negative numbers (ones with + --the highest-order bit '1'). If you don't care because the + --number you're shifting is always nonnegative, use the '_' version + --which should just be the fastest one. + shiftR_FastInt, + --"L' = logical or unsigned shift; 'A' = arithmetic or signed shift + shiftRLFastInt, shiftRAFastInt, + bitAndFastInt, bitOrFastInt, + --add more operations to this file as you need them + + -- * FastChar + FastChar, + + -- ** Getting in and out of FastChar + _CLIT, cBox, cUnbox, + + -- ** Operations on FastChar + fastOrd, fastChr, eqFastChar, + --note, fastChr is "unsafe"Chr: it doesn't check for + --character values above the range of Unicode - FastBool, fastBool, isFastTrue, fastOr, fastAnd + -- * FastPtr + FastPtr, + + -- ** Getting in and out of FastPtr + pBox, pUnbox, + + -- ** Casting FastPtrs + castFastPtr ) where #include "HsVersions.h" @@ -18,30 +66,61 @@ module FastTypes ( -- Import the beggars import GHC.Exts - ( Int(..), Int#, (+#), (-#), (*#), - quotInt#, negateInt#, (==#), (<#), (<=#), (>=#), (>#) - ) type FastInt = Int# -_ILIT (I# x) = x + +--in case it's a macro, don't lexically feed an argument! +--e.g. #define _ILIT(x) (x#) , #define _ILIT(x) (x :: FastInt) +_ILIT = \(I# x) -> x +--perhaps for accomodating caseless-leading-underscore treatment, +--something like _iLIT or iLIT would be better? + iBox x = I# x iUnbox (I# x) = x quotFastInt = quotInt# negateFastInt = negateInt# -type FastBool = Int# -fastBool True = 1# -fastBool False = 0# -isFastTrue x = x ==# 1# +--I think uncheckedIShiftL# and uncheckedIShiftRL# are the same +--as uncheckedShiftL# and uncheckedShiftRL# ... +--should they be used? How new are they? +--They existed as far back as GHC 6.0 at least... +shiftLFastInt x y = uncheckedIShiftL# x y +shiftR_FastInt x y = uncheckedIShiftRL# x y +shiftRLFastInt x y = uncheckedIShiftRL# x y +shiftRAFastInt x y = uncheckedIShiftRA# x y +--{-# INLINE shiftLNonnegativeFastInt #-} +--{-# INLINE shiftRNonnegativeFastInt #-} +--shiftLNonnegativeFastInt n p = word2Int#((int2Word# n) `uncheckedShiftL#` p) +--shiftRNonnegativeFastInt n p = word2Int#((int2Word# n) `uncheckedShiftRL#` p) +bitAndFastInt x y = word2Int# (and# (int2Word# x) (int2Word# y)) +bitOrFastInt x y = word2Int# (or# (int2Word# x) (int2Word# y)) -fastOr 1# _ = 1# -fastOr 0# x = x +type FastChar = Char# +_CLIT = \(C# c) -> c +cBox c = C# c +cUnbox (C# c) = c +fastOrd c = ord# c +fastChr x = chr# x +eqFastChar a b = eqChar# a b -fastAnd 0# x = 0# -fastAnd 1# x = x +--note that the type-parameter doesn't provide any safety +--when it's a synonym, but as long as we keep it compiling +--with and without __GLASGOW_HASKELL__ defined, it's fine. +type FastPtr a = Addr# +pBox p = Ptr p +pUnbox (Ptr p) = p +castFastPtr p = p #else /* ! __GLASGOW_HASKELL__ */ +import Data.Char (ord, chr) + +import Data.Bits +import Data.Word (Word) --is it a good idea to assume this exists too? +--does anyone need shiftRLFastInt? (apparently yes.) + +import Foreign.Ptr + type FastInt = Int _ILIT x = x iBox x = x @@ -50,16 +129,85 @@ iUnbox x = x (-#) = (-) (*#) = (*) quotFastInt = quot +--quotRemFastInt = quotRem negateFastInt = negate (==#) = (==) +(/=#) = (/=) (<#) = (<) (<=#) = (<=) (>=#) = (>=) (>#) = (>) +shiftLFastInt = shiftL +shiftR_FastInt = shiftR +shiftRAFastInt = shiftR +shiftRLFastInt n p = fromIntegral (shiftR (fromIntegral n :: Word) p) +--shiftLFastInt n p = n * (2 ^ p) +--assuming quot-Int is faster and the +--same for nonnegative arguments than div-Int +--shiftR_FastInt n p = n `quot` (2 ^ p) +--shiftRAFastInt n p = n `div` (2 ^ p) +--I couldn't figure out how to implement without Word nor Bits +--shiftRLFastInt n p = fromIntegral ((fromIntegral n :: Word) `quot` (2 ^ (fromIntegral p :: Word))) + +bitAndFastInt = (.&.) +bitOrFastInt = (.|.) type FastBool = Bool fastBool x = x -_IS_TRUE_ x = x +isFastTrue x = x +-- make sure these are as strict as the unboxed version, +-- so that the performance characteristics match +fastOr False False = False +fastOr _ _ = True +fastAnd True True = True +fastAnd _ _ = False + +type FastChar = Char +_CLIT c = c +cBox c = c +cUnbox c = c +fastOrd = ord +fastChr = chr --or unsafeChr if there was a standard location for it +eqFastChar = (==) + +type FastPtr a = Ptr a +pBox p = p +pUnbox p = p +castFastPtr = castPtr + +--These are among the type-signatures necessary for !ghc to compile +-- but break ghc (can't give a signature for an import...) +--Note that the comparisons actually do return Bools not FastBools. +(+#), (-#), (*#) :: FastInt -> FastInt -> FastInt +(==#), (/=#), (<#), (<=#), (>=#), (>#) :: FastInt -> FastInt -> Bool #endif /* ! __GLASGOW_HASKELL__ */ + +minFastInt, maxFastInt :: FastInt -> FastInt -> FastInt +minFastInt x y = if x <# y then x else y +maxFastInt x y = if x <# y then y else x + +-- type-signatures will improve the non-ghc-specific versions +-- and keep things accurate (and ABLE to compile!) +_ILIT :: Int -> FastInt +iBox :: FastInt -> Int +iUnbox :: Int -> FastInt + +quotFastInt :: FastInt -> FastInt -> FastInt +negateFastInt :: FastInt -> FastInt +shiftLFastInt, shiftR_FastInt, shiftRAFastInt, shiftRLFastInt + :: FastInt -> FastInt -> FastInt +bitAndFastInt, bitOrFastInt :: FastInt -> FastInt -> FastInt + +_CLIT :: Char -> FastChar +cBox :: FastChar -> Char +cUnbox :: Char -> FastChar +fastOrd :: FastChar -> FastInt +fastChr :: FastInt -> FastChar +eqFastChar :: FastChar -> FastChar -> Bool + +pBox :: FastPtr a -> Ptr a +pUnbox :: Ptr a -> FastPtr a +castFastPtr :: FastPtr a -> FastPtr b + \end{code}