diff options
-rw-r--r-- | compiler/cmm/CmmOpt.hs | 21 | ||||
-rw-r--r-- | compiler/prelude/PrelNames.hs | 12 | ||||
-rw-r--r-- | compiler/prelude/PrelRules.hs | 21 | ||||
-rw-r--r-- | compiler/prelude/primops.txt.pp | 8 | ||||
-rw-r--r-- | compiler/utils/Util.hs | 24 | ||||
-rw-r--r-- | libraries/ghc-prim/GHC/Classes.hs | 3 | ||||
-rw-r--r-- | testsuite/tests/simplCore/should_compile/Makefile | 10 | ||||
-rw-r--r-- | testsuite/tests/simplCore/should_compile/T5615.hs | 10 | ||||
-rw-r--r-- | testsuite/tests/simplCore/should_compile/T5615.stdout | 1 | ||||
-rw-r--r-- | testsuite/tests/simplCore/should_compile/all.T | 1 |
10 files changed, 87 insertions, 24 deletions
diff --git a/compiler/cmm/CmmOpt.hs b/compiler/cmm/CmmOpt.hs index de3061d7d4..8d1641a7d4 100644 --- a/compiler/cmm/CmmOpt.hs +++ b/compiler/cmm/CmmOpt.hs @@ -26,6 +26,7 @@ module CmmOpt ( import CmmUtils import Cmm import DynFlags +import Util import Outputable import Platform @@ -376,26 +377,6 @@ cmmMachOpFoldM dflags mop [x, (CmmLit (CmmInt n _))] cmmMachOpFoldM _ _ _ = Nothing -- ----------------------------------------------------------------------------- --- exactLog2 - --- This algorithm for determining the $\log_2$ of exact powers of 2 comes --- from GCC. It requires bit manipulation primitives, and we use GHC --- extensions. Tough. - -exactLog2 :: Integer -> Maybe Integer -exactLog2 x - = if (x <= 0 || x >= 2147483648) then - Nothing - else - if (x .&. (-x)) /= x then - Nothing - else - Just (pow2 x) - where - pow2 x | x == 1 = 0 - | otherwise = 1 + pow2 (x `shiftR` 1) - --- ----------------------------------------------------------------------------- -- Utils isLit :: CmmExpr -> Bool diff --git a/compiler/prelude/PrelNames.hs b/compiler/prelude/PrelNames.hs index 00e9ffed96..558619a9db 100644 --- a/compiler/prelude/PrelNames.hs +++ b/compiler/prelude/PrelNames.hs @@ -232,6 +232,9 @@ basicKnownKeyNames toIntegerName, toRationalName, fromIntegralName, realToFracName, + -- Int# stuff + divIntName, modIntName, + -- String stuff fromStringName, @@ -912,6 +915,11 @@ metaDataDataConName = dcQual gHC_GENERICS (fsLit "MetaData") metaDataDataConKe metaConsDataConName = dcQual gHC_GENERICS (fsLit "MetaCons") metaConsDataConKey metaSelDataConName = dcQual gHC_GENERICS (fsLit "MetaSel") metaSelDataConKey +-- Primitive Int +divIntName, modIntName :: Name +divIntName = varQual gHC_CLASSES (fsLit "divInt#") divIntIdKey +modIntName = varQual gHC_CLASSES (fsLit "modInt#") modIntIdKey + -- Base strings Strings unpackCStringName, unpackCStringFoldrName, unpackCStringUtf8Name, eqStringName :: Name @@ -1909,7 +1917,7 @@ wildCardKey, absentErrorIdKey, augmentIdKey, appendIdKey, realWorldPrimIdKey, recConErrorIdKey, unpackCStringUtf8IdKey, unpackCStringAppendIdKey, unpackCStringFoldrIdKey, unpackCStringIdKey, - typeErrorIdKey :: Unique + typeErrorIdKey, divIntIdKey, modIntIdKey :: Unique wildCardKey = mkPreludeMiscIdUnique 0 -- See Note [WildCard binders] absentErrorIdKey = mkPreludeMiscIdUnique 1 @@ -1934,6 +1942,8 @@ unpackCStringFoldrIdKey = mkPreludeMiscIdUnique 19 unpackCStringIdKey = mkPreludeMiscIdUnique 20 voidPrimIdKey = mkPreludeMiscIdUnique 21 typeErrorIdKey = mkPreludeMiscIdUnique 22 +divIntIdKey = mkPreludeMiscIdUnique 23 +modIntIdKey = mkPreludeMiscIdUnique 24 unsafeCoerceIdKey, concatIdKey, filterIdKey, zipIdKey, bindIOIdKey, returnIOIdKey, newStablePtrIdKey, diff --git a/compiler/prelude/PrelRules.hs b/compiler/prelude/PrelRules.hs index a57609a89d..8868047005 100644 --- a/compiler/prelude/PrelRules.hs +++ b/compiler/prelude/PrelRules.hs @@ -988,7 +988,26 @@ builtinRules BuiltinRule { ru_name = fsLit "Inline", ru_fn = inlineIdName, ru_nargs = 2, ru_try = \_ _ _ -> match_inline }, BuiltinRule { ru_name = fsLit "MagicDict", ru_fn = idName magicDictId, - ru_nargs = 4, ru_try = \_ _ _ -> match_magicDict } + ru_nargs = 4, ru_try = \_ _ _ -> match_magicDict }, + mkBasicRule divIntName 2 $ msum + [ nonZeroLit 1 >> binaryLit (intOp2 div) + , leftZero zeroi + , do + [arg, Lit (MachInt d)] <- getArgs + Just n <- return $ exactLog2 d + dflags <- getDynFlags + return $ Var (mkPrimOpId ISraOp) `App` arg `App` mkIntVal dflags n + ], + mkBasicRule modIntName 2 $ msum + [ nonZeroLit 1 >> binaryLit (intOp2 mod) + , leftZero zeroi + , do + [arg, Lit (MachInt d)] <- getArgs + Just _ <- return $ exactLog2 d + dflags <- getDynFlags + return $ Var (mkPrimOpId AndIOp) + `App` arg `App` mkIntVal dflags (d - 1) + ] ] ++ builtinIntegerRules diff --git a/compiler/prelude/primops.txt.pp b/compiler/prelude/primops.txt.pp index e948610556..a38dd57755 100644 --- a/compiler/prelude/primops.txt.pp +++ b/compiler/prelude/primops.txt.pp @@ -221,12 +221,16 @@ primop IntMulMayOfloOp "mulIntMayOflo#" primop IntQuotOp "quotInt#" Dyadic Int# -> Int# -> Int# - {Rounds towards zero.} + {Rounds towards zero. The behavior is undefined if the second argument is + zero. + } with can_fail = True primop IntRemOp "remInt#" Dyadic Int# -> Int# -> Int# - {Satisfies \texttt{(quotInt\# x y) *\# y +\# (remInt\# x y) == x}.} + {Satisfies \texttt{(quotInt\# x y) *\# y +\# (remInt\# x y) == x}. The + behavior is undefined if the second argument is zero. + } with can_fail = True primop IntQuotRemOp "quotRemInt#" GenPrimOp diff --git a/compiler/utils/Util.hs b/compiler/utils/Util.hs index 121fdbbf6f..0b16fba72d 100644 --- a/compiler/utils/Util.hs +++ b/compiler/utils/Util.hs @@ -78,6 +78,9 @@ module Util ( -- * Argument processing getCmd, toCmdArgs, toArgs, + -- * Integers + exactLog2, + -- * Floating point readRational, @@ -985,6 +988,27 @@ toArgs str Right (arg, rest) _ -> Left ("Couldn't read " ++ show s ++ " as String") +----------------------------------------------------------------------------- +-- Integers + +-- This algorithm for determining the $\log_2$ of exact powers of 2 comes +-- from GCC. It requires bit manipulation primitives, and we use GHC +-- extensions. Tough. + +exactLog2 :: Integer -> Maybe Integer +exactLog2 x + = if (x <= 0 || x >= 2147483648) then + Nothing + else + if (x .&. (-x)) /= x then + Nothing + else + Just (pow2 x) + where + pow2 x | x == 1 = 0 + | otherwise = 1 + pow2 (x `shiftR` 1) + + {- -- ----------------------------------------------------------------------------- -- Floats diff --git a/libraries/ghc-prim/GHC/Classes.hs b/libraries/ghc-prim/GHC/Classes.hs index 9c40449188..5fa118a7f6 100644 --- a/libraries/ghc-prim/GHC/Classes.hs +++ b/libraries/ghc-prim/GHC/Classes.hs @@ -440,6 +440,9 @@ not False = True -- These don't really belong here, but we don't have a better place to -- put them +-- These functions have built-in rules. +{-# NOINLINE [0] divInt# #-} +{-# NOINLINE [0] modInt# #-} divInt# :: Int# -> Int# -> Int# x# `divInt#` y# -- Be careful NOT to overflow if we do any additional arithmetic diff --git a/testsuite/tests/simplCore/should_compile/Makefile b/testsuite/tests/simplCore/should_compile/Makefile index 8b7da66e27..288e3f96e5 100644 --- a/testsuite/tests/simplCore/should_compile/Makefile +++ b/testsuite/tests/simplCore/should_compile/Makefile @@ -144,3 +144,13 @@ T10083: '$(TEST_HC)' $(TEST_HC_OPTS) -c -O T10083.hs-boot '$(TEST_HC)' $(TEST_HC_OPTS) -c -O T10083a.hs '$(TEST_HC)' $(TEST_HC_OPTS) -c -O T10083.hs + +.PHONY: T5615 +T5615: + $(RM) -f T5615.o T5615.hi T5615.dump-simpl + '$(TEST_HC)' $(TEST_HC_OPTS) -c -O T5615.hs -ddump-simpl -ddump-to-file + -grep 'divInt#' T5615.dump-simpl + -grep 'modInt#' T5615.dump-simpl + -grep 'quotInt#' T5615.dump-simpl + -grep 'remInt#' T5615.dump-simpl + grep -c '1999#' T5615.dump-simpl diff --git a/testsuite/tests/simplCore/should_compile/T5615.hs b/testsuite/tests/simplCore/should_compile/T5615.hs new file mode 100644 index 0000000000..984480431b --- /dev/null +++ b/testsuite/tests/simplCore/should_compile/T5615.hs @@ -0,0 +1,10 @@ +main :: IO () +main = do + printInt $ 9999 `div` 5 + printInt $ 9999 `mod` 5 + n <- readLn + printInt $ n `div` 4 + printInt $ n `mod` 4 + +printInt :: Int -> IO () +printInt = print diff --git a/testsuite/tests/simplCore/should_compile/T5615.stdout b/testsuite/tests/simplCore/should_compile/T5615.stdout new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/testsuite/tests/simplCore/should_compile/T5615.stdout @@ -0,0 +1 @@ +1 diff --git a/testsuite/tests/simplCore/should_compile/all.T b/testsuite/tests/simplCore/should_compile/all.T index e2e0bb6c31..f985b4a859 100644 --- a/testsuite/tests/simplCore/should_compile/all.T +++ b/testsuite/tests/simplCore/should_compile/all.T @@ -137,6 +137,7 @@ test('simpl021', run_command, ['$MAKE -s --no-print-directory simpl021']) test('T5327', normal, run_command, ['$MAKE -s --no-print-directory T5327']) +test('T5615', normal, run_command, ['$MAKE -s --no-print-directory T5615']) test('T5623', normal, run_command, ['$MAKE -s --no-print-directory T5623']) test('T5658b', normal, |