summaryrefslogtreecommitdiff
path: root/compiler/prelude/PrelRules.lhs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/prelude/PrelRules.lhs')
-rw-r--r--compiler/prelude/PrelRules.lhs387
1 files changed, 195 insertions, 192 deletions
diff --git a/compiler/prelude/PrelRules.lhs b/compiler/prelude/PrelRules.lhs
index 079ab0cc98..64a9f9b912 100644
--- a/compiler/prelude/PrelRules.lhs
+++ b/compiler/prelude/PrelRules.lhs
@@ -20,17 +20,18 @@ module PrelRules ( primOpRules, builtinRules ) where
#include "HsVersions.h"
#include "../includes/MachDeps.h"
-import {-# SOURCE #-} MkId ( mkPrimOpId )
+import {-# SOURCE #-} MkId ( mkPrimOpId, magicSingIId )
import CoreSyn
import MkCore
import Id
+import Var (setVarType)
import Literal
import CoreSubst ( exprIsLiteral_maybe )
import PrimOp ( PrimOp(..), tagToEnumKey )
import TysWiredIn
import TysPrim
-import TyCon ( tyConDataCons_maybe, isEnumerationTyCon, isNewTyCon )
+import TyCon ( tyConDataCons_maybe, isEnumerationTyCon, isNewTyCon, unwrapNewTyCon_maybe )
import DataCon ( dataConTag, dataConTyCon, dataConWorkId )
import CoreUtils ( cheapEqExpr, exprIsHNF )
import CoreUnfold ( exprIsConApp_maybe )
@@ -46,6 +47,7 @@ import BasicTypes
import DynFlags
import Platform
import Util
+import Coercion (mkUnbranchedAxInstCo,mkSymCo,Role(..))
import Control.Monad
import Data.Bits as Bits
@@ -195,7 +197,8 @@ primOpRules nm FloatAddOp = mkPrimOpRule nm 2 [ binaryLit (floatOp2 (+))
primOpRules nm FloatSubOp = mkPrimOpRule nm 2 [ binaryLit (floatOp2 (-))
, rightIdentity zerof ]
primOpRules nm FloatMulOp = mkPrimOpRule nm 2 [ binaryLit (floatOp2 (*))
- , identity onef ]
+ , identity onef
+ , strengthReduction twof FloatAddOp ]
-- zeroElem zerof doesn't hold because of NaN
primOpRules nm FloatDivOp = mkPrimOpRule nm 2 [ guardFloatDiv >> binaryLit (floatOp2 (/))
, rightIdentity onef ]
@@ -208,7 +211,8 @@ primOpRules nm DoubleAddOp = mkPrimOpRule nm 2 [ binaryLit (doubleOp2 (+))
primOpRules nm DoubleSubOp = mkPrimOpRule nm 2 [ binaryLit (doubleOp2 (-))
, rightIdentity zerod ]
primOpRules nm DoubleMulOp = mkPrimOpRule nm 2 [ binaryLit (doubleOp2 (*))
- , identity oned ]
+ , identity oned
+ , strengthReduction twod DoubleAddOp ]
-- zeroElem zerod doesn't hold because of NaN
primOpRules nm DoubleDivOp = mkPrimOpRule nm 2 [ guardDoubleDiv >> binaryLit (doubleOp2 (/))
, rightIdentity oned ]
@@ -216,6 +220,7 @@ primOpRules nm DoubleNegOp = mkPrimOpRule nm 1 [ unaryLit negOp
, inversePrimOp DoubleNegOp ]
-- Relational operators
+
primOpRules nm IntEqOp = mkRelOpRule nm (==) [ litEq True ]
primOpRules nm IntNeOp = mkRelOpRule nm (/=) [ litEq False ]
primOpRules nm CharEqOp = mkRelOpRule nm (==) [ litEq True ]
@@ -231,19 +236,19 @@ primOpRules nm CharGeOp = mkRelOpRule nm (>=) [ boundsCmp Ge ]
primOpRules nm CharLeOp = mkRelOpRule nm (<=) [ boundsCmp Le ]
primOpRules nm CharLtOp = mkRelOpRule nm (<) [ boundsCmp Lt ]
-primOpRules nm FloatGtOp = mkRelOpRule nm (>) []
-primOpRules nm FloatGeOp = mkRelOpRule nm (>=) []
-primOpRules nm FloatLeOp = mkRelOpRule nm (<=) []
-primOpRules nm FloatLtOp = mkRelOpRule nm (<) []
-primOpRules nm FloatEqOp = mkRelOpRule nm (==) [ litEq True ]
-primOpRules nm FloatNeOp = mkRelOpRule nm (/=) [ litEq False ]
+primOpRules nm FloatGtOp = mkFloatingRelOpRule nm (>) []
+primOpRules nm FloatGeOp = mkFloatingRelOpRule nm (>=) []
+primOpRules nm FloatLeOp = mkFloatingRelOpRule nm (<=) []
+primOpRules nm FloatLtOp = mkFloatingRelOpRule nm (<) []
+primOpRules nm FloatEqOp = mkFloatingRelOpRule nm (==) [ litEq True ]
+primOpRules nm FloatNeOp = mkFloatingRelOpRule nm (/=) [ litEq False ]
-primOpRules nm DoubleGtOp = mkRelOpRule nm (>) []
-primOpRules nm DoubleGeOp = mkRelOpRule nm (>=) []
-primOpRules nm DoubleLeOp = mkRelOpRule nm (<=) []
-primOpRules nm DoubleLtOp = mkRelOpRule nm (<) []
-primOpRules nm DoubleEqOp = mkRelOpRule nm (==) [ litEq True ]
-primOpRules nm DoubleNeOp = mkRelOpRule nm (/=) [ litEq False ]
+primOpRules nm DoubleGtOp = mkFloatingRelOpRule nm (>) []
+primOpRules nm DoubleGeOp = mkFloatingRelOpRule nm (>=) []
+primOpRules nm DoubleLeOp = mkFloatingRelOpRule nm (<=) []
+primOpRules nm DoubleLtOp = mkFloatingRelOpRule nm (<) []
+primOpRules nm DoubleEqOp = mkFloatingRelOpRule nm (==) [ litEq True ]
+primOpRules nm DoubleNeOp = mkFloatingRelOpRule nm (/=) [ litEq False ]
primOpRules nm WordGtOp = mkRelOpRule nm (>) [ boundsCmp Gt ]
primOpRules nm WordGeOp = mkRelOpRule nm (>=) [ boundsCmp Ge ]
@@ -278,14 +283,27 @@ mkRelOpRule :: Name -> (forall a . Ord a => a -> a -> Bool)
mkRelOpRule nm cmp extra
= mkPrimOpRule nm 2 $ rules ++ extra
where
- rules = [ binaryLit (\_ -> cmpOp cmp)
- , equalArgs >>
+ rules = [ binaryCmpLit cmp
+ , do equalArgs
-- x `cmp` x does not depend on x, so
-- compute it for the arbitrary value 'True'
-- and use that result
- return (if cmp True True
- then trueVal
- else falseVal) ]
+ dflags <- getDynFlags
+ return (if cmp True True
+ then trueValInt dflags
+ else falseValInt dflags) ]
+
+-- Note [Rules for floating-point comparisons]
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+--
+-- We need different rules for floating-point values because for floats
+-- it is not true that x = x. The special case when this does not occur
+-- are NaNs.
+
+mkFloatingRelOpRule :: Name -> (forall a . Ord a => a -> a -> Bool)
+ -> [RuleM CoreExpr] -> Maybe CoreRule
+mkFloatingRelOpRule nm cmp extra -- See Note [Rules for floating-point comparisons]
+ = mkPrimOpRule nm 2 $ binaryCmpLit cmp : extra
-- common constants
zeroi, onei, zerow, onew :: DynFlags -> Literal
@@ -294,18 +312,20 @@ onei dflags = mkMachInt dflags 1
zerow dflags = mkMachWord dflags 0
onew dflags = mkMachWord dflags 1
-zerof, onef, zerod, oned :: Literal
+zerof, onef, twof, zerod, oned, twod :: Literal
zerof = mkMachFloat 0.0
onef = mkMachFloat 1.0
+twof = mkMachFloat 2.0
zerod = mkMachDouble 0.0
oned = mkMachDouble 1.0
+twod = mkMachDouble 2.0
-cmpOp :: (forall a . Ord a => a -> a -> Bool)
+cmpOp :: DynFlags -> (forall a . Ord a => a -> a -> Bool)
-> Literal -> Literal -> Maybe CoreExpr
-cmpOp cmp = go
+cmpOp dflags cmp = go
where
- done True = Just trueVal
- done False = Just falseVal
+ done True = Just $ trueValInt dflags
+ done False = Just $ falseValInt dflags
-- These compares are at different types
go (MachChar i1) (MachChar i2) = done (i1 `cmp` i2)
@@ -402,19 +422,22 @@ litEq :: Bool -- True <=> equality, False <=> inequality
-> RuleM CoreExpr
litEq is_eq = msum
[ do [Lit lit, expr] <- getArgs
- do_lit_eq lit expr
+ dflags <- getDynFlags
+ do_lit_eq dflags lit expr
, do [expr, Lit lit] <- getArgs
- do_lit_eq lit expr ]
+ dflags <- getDynFlags
+ do_lit_eq dflags lit expr ]
where
- do_lit_eq lit expr = do
+ do_lit_eq dflags lit expr = do
guard (not (litIsLifted lit))
- return (mkWildCase expr (literalType lit) boolTy
+ return (mkWildCase expr (literalType lit) intPrimTy
[(DEFAULT, [], val_if_neq),
(LitAlt lit, [], val_if_eq)])
- val_if_eq | is_eq = trueVal
- | otherwise = falseVal
- val_if_neq | is_eq = falseVal
- | otherwise = trueVal
+ where
+ val_if_eq | is_eq = trueValInt dflags
+ | otherwise = falseValInt dflags
+ val_if_neq | is_eq = falseValInt dflags
+ | otherwise = trueValInt dflags
-- | Check if there is comparison with minBound or maxBound, that is
@@ -429,14 +452,14 @@ boundsCmp op = do
data Comparison = Gt | Ge | Lt | Le
mkRuleFn :: DynFlags -> Comparison -> CoreExpr -> CoreExpr -> Maybe CoreExpr
-mkRuleFn dflags Gt (Lit lit) _ | isMinBound dflags lit = Just falseVal
-mkRuleFn dflags Le (Lit lit) _ | isMinBound dflags lit = Just trueVal
-mkRuleFn dflags Ge _ (Lit lit) | isMinBound dflags lit = Just trueVal
-mkRuleFn dflags Lt _ (Lit lit) | isMinBound dflags lit = Just falseVal
-mkRuleFn dflags Ge (Lit lit) _ | isMaxBound dflags lit = Just trueVal
-mkRuleFn dflags Lt (Lit lit) _ | isMaxBound dflags lit = Just falseVal
-mkRuleFn dflags Gt _ (Lit lit) | isMaxBound dflags lit = Just falseVal
-mkRuleFn dflags Le _ (Lit lit) | isMaxBound dflags lit = Just trueVal
+mkRuleFn dflags Gt (Lit lit) _ | isMinBound dflags lit = Just $ falseValInt dflags
+mkRuleFn dflags Le (Lit lit) _ | isMinBound dflags lit = Just $ trueValInt dflags
+mkRuleFn dflags Ge _ (Lit lit) | isMinBound dflags lit = Just $ trueValInt dflags
+mkRuleFn dflags Lt _ (Lit lit) | isMinBound dflags lit = Just $ falseValInt dflags
+mkRuleFn dflags Ge (Lit lit) _ | isMaxBound dflags lit = Just $ trueValInt dflags
+mkRuleFn dflags Lt (Lit lit) _ | isMaxBound dflags lit = Just $ falseValInt dflags
+mkRuleFn dflags Gt _ (Lit lit) | isMaxBound dflags lit = Just $ falseValInt dflags
+mkRuleFn dflags Le _ (Lit lit) | isMaxBound dflags lit = Just $ trueValInt dflags
mkRuleFn _ _ _ _ = Nothing
isMinBound :: DynFlags -> Literal -> Bool
@@ -512,10 +535,10 @@ mkBasicRule op_name n_args rm
= BuiltinRule { ru_name = occNameFS (nameOccName op_name),
ru_fn = op_name,
ru_nargs = n_args,
- ru_try = \dflags _ -> runRuleM rm dflags }
+ ru_try = \ dflags in_scope _ -> runRuleM rm dflags in_scope }
newtype RuleM r = RuleM
- { runRuleM :: DynFlags -> IdUnfoldingFun -> [CoreExpr] -> Maybe r }
+ { runRuleM :: DynFlags -> InScopeEnv -> [CoreExpr] -> Maybe r }
instance Monad RuleM where
return x = RuleM $ \_ _ _ -> Just x
@@ -557,8 +580,8 @@ removeOp32 = mzero
getArgs :: RuleM [CoreExpr]
getArgs = RuleM $ \_ _ args -> Just args
-getIdUnfoldingFun :: RuleM IdUnfoldingFun
-getIdUnfoldingFun = RuleM $ \_ iu _ -> Just iu
+getInScopeEnv :: RuleM InScopeEnv
+getInScopeEnv = RuleM $ \_ iu _ -> Just iu
-- return the n-th argument of this rule, if it is a literal
-- argument indices start from 0
@@ -579,6 +602,11 @@ binaryLit op = do
[Lit l1, Lit l2] <- getArgs
liftMaybe $ op dflags (convFloating dflags l1) (convFloating dflags l2)
+binaryCmpLit :: (forall a . Ord a => a -> a -> Bool) -> RuleM CoreExpr
+binaryCmpLit op = do
+ dflags <- getDynFlags
+ binaryLit (\_ -> cmpOp dflags op)
+
leftIdentity :: Literal -> RuleM CoreExpr
leftIdentity id_lit = leftIdentityDynFlags (const id_lit)
@@ -656,9 +684,40 @@ guardDoubleDiv = do
-- is representable in Float/Double but not in (normalised)
-- Rational. (#3676) Perhaps we should generate (0 :% (-1)) instead?
-trueVal, falseVal :: Expr CoreBndr
-trueVal = Var trueDataConId
-falseVal = Var falseDataConId
+strengthReduction :: Literal -> PrimOp -> RuleM CoreExpr
+strengthReduction two_lit add_op = do -- Note [Strength reduction]
+ arg <- msum [ do [arg, Lit mult_lit] <- getArgs
+ guard (mult_lit == two_lit)
+ return arg
+ , do [Lit mult_lit, arg] <- getArgs
+ guard (mult_lit == two_lit)
+ return arg ]
+ return $ Var (mkPrimOpId add_op) `App` arg `App` arg
+
+-- Note [Strength reduction]
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~
+--
+-- This rule turns floating point multiplications of the form 2.0 * x and
+-- x * 2.0 into x + x addition, because addition costs less than multiplication.
+-- See #7116
+
+-- Note [What's true and false]
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+--
+-- trueValInt and falseValInt represent true and false values returned by
+-- comparison primops for Char, Int, Word, Integer, Double, Float and Addr.
+-- True is represented as an unboxed 1# literal, while false is represented
+-- as 0# literal.
+-- We still need Bool data constructors (True and False) to use in a rule
+-- for constant folding of equal Strings
+
+trueValInt, falseValInt :: DynFlags -> Expr CoreBndr
+trueValInt dflags = Lit $ onei dflags -- see Note [What's true and false]
+falseValInt dflags = Lit $ zeroi dflags
+
+trueValBool, falseValBool :: Expr CoreBndr
+trueValBool = Var trueDataConId -- see Note [What's true and false]
+falseValBool = Var falseDataConId
ltVal, eqVal, gtVal :: Expr CoreBndr
ltVal = Var ltDataConId
@@ -719,7 +778,7 @@ tagToEnumRule = do
let tag = fromInteger i
correct_tag dc = (dataConTag dc - fIRST_TAG) == tag
(dc:rest) <- return $ filter correct_tag (tyConDataCons_maybe tycon `orElse` [])
- ASSERT (null rest) return ()
+ ASSERT(null rest) return ()
return $ mkTyApps (Var (dataConWorkId dc)) tc_args
-- See Note [tagToEnum#]
@@ -745,8 +804,8 @@ dataToTagRule = a `mplus` b
b = do
dflags <- getDynFlags
[_, val_arg] <- getArgs
- id_unf <- getIdUnfoldingFun
- (dc,_,_) <- liftMaybe $ exprIsConApp_maybe id_unf val_arg
+ in_scope <- getInScopeEnv
+ (dc,_,_) <- liftMaybe $ exprIsConApp_maybe in_scope val_arg
ASSERT( not (isNewTyCon (dataConTyCon dc)) ) return ()
return $ mkIntVal dflags (toInteger (dataConTag dc - fIRST_TAG))
\end{code}
@@ -812,11 +871,14 @@ builtinRules :: [CoreRule]
builtinRules
= [BuiltinRule { ru_name = fsLit "AppendLitString",
ru_fn = unpackCStringFoldrName,
- ru_nargs = 4, ru_try = \_ _ -> match_append_lit },
+ ru_nargs = 4, ru_try = \_ _ _ -> match_append_lit },
BuiltinRule { ru_name = fsLit "EqString", ru_fn = eqStringName,
- ru_nargs = 2, ru_try = \_ _ -> match_eq_string },
+ ru_nargs = 2, ru_try = \dflags _ _ -> match_eq_string dflags },
BuiltinRule { ru_name = fsLit "Inline", ru_fn = inlineIdName,
- ru_nargs = 2, ru_try = \_ _ -> match_inline }]
+ ru_nargs = 2, ru_try = \_ _ _ -> match_inline },
+ BuiltinRule { ru_name = fsLit "MagicSingI", ru_fn = idName magicSingIId,
+ ru_nargs = 3, ru_try = \_ _ _ -> match_magicSingI }
+ ]
++ builtinIntegerRules
builtinIntegerRules :: [CoreRule]
@@ -833,19 +895,15 @@ builtinIntegerRules =
rule_binop "minusInteger" minusIntegerName (-),
rule_binop "timesInteger" timesIntegerName (*),
rule_unop "negateInteger" negateIntegerName negate,
- rule_binop_Bool "eqInteger" eqIntegerName (==),
- rule_binop_Bool "neqInteger" neqIntegerName (/=),
+ rule_binop_Prim "eqInteger#" eqIntegerPrimName (==),
+ rule_binop_Prim "neqInteger#" neqIntegerPrimName (/=),
rule_unop "absInteger" absIntegerName abs,
rule_unop "signumInteger" signumIntegerName signum,
- rule_binop_Bool "leInteger" leIntegerName (<=),
- rule_binop_Bool "gtInteger" gtIntegerName (>),
- rule_binop_Bool "ltInteger" ltIntegerName (<),
- rule_binop_Bool "geInteger" geIntegerName (>=),
+ rule_binop_Prim "leInteger#" leIntegerPrimName (<=),
+ rule_binop_Prim "gtInteger#" gtIntegerPrimName (>),
+ rule_binop_Prim "ltInteger#" ltIntegerPrimName (<),
+ rule_binop_Prim "geInteger#" geIntegerPrimName (>=),
rule_binop_Ordering "compareInteger" compareIntegerName compare,
- rule_divop_both "divModInteger" divModIntegerName divMod,
- rule_divop_both "quotRemInteger" quotRemIntegerName quotRem,
- rule_divop_one "quotInteger" quotIntegerName quot,
- rule_divop_one "remInteger" remIntegerName rem,
rule_encodeFloat "encodeFloatInteger" encodeFloatIntegerName mkFloatLitFloat,
rule_convert "floatFromInteger" floatFromIntegerName (\_ -> mkFloatLitFloat),
rule_encodeFloat "encodeDoubleInteger" encodeDoubleIntegerName mkDoubleLitDouble,
@@ -861,6 +919,13 @@ builtinIntegerRules =
rule_unop "complementInteger" complementIntegerName complement,
rule_Int_binop "shiftLInteger" shiftLIntegerName shiftL,
rule_Int_binop "shiftRInteger" shiftRIntegerName shiftR,
+ -- See Note [Integer division constant folding] in libraries/base/GHC/Real.lhs
+ rule_divop_one "quotInteger" quotIntegerName quot,
+ rule_divop_one "remInteger" remIntegerName rem,
+ rule_divop_one "divInteger" divIntegerName div,
+ rule_divop_one "modInteger" modIntegerName mod,
+ rule_divop_both "divModInteger" divModIntegerName divMod,
+ rule_divop_both "quotRemInteger" quotRemIntegerName quotRem,
-- These rules below don't actually have to be built in, but if we
-- put them in the Haskell source then we'd have to duplicate them
-- between all Integer implementations
@@ -902,9 +967,9 @@ builtinIntegerRules =
rule_Int_binop str name op
= BuiltinRule { ru_name = fsLit str, ru_fn = name, ru_nargs = 2,
ru_try = match_Integer_Int_binop op }
- rule_binop_Bool str name op
+ rule_binop_Prim str name op
= BuiltinRule { ru_name = fsLit str, ru_fn = name, ru_nargs = 2,
- ru_try = match_Integer_binop_Bool op }
+ ru_try = match_Integer_binop_Prim op }
rule_binop_Ordering str name op
= BuiltinRule { ru_name = fsLit str, ru_fn = name, ru_nargs = 2,
ru_try = match_Integer_binop_Ordering op }
@@ -929,8 +994,8 @@ builtinIntegerRules =
-- unpackFoldrCString# "foo" c (unpackFoldrCString# "baz" c n)
-- = unpackFoldrCString# "foobaz" c n
-match_append_lit :: IdUnfoldingFun -> [Expr CoreBndr] -> Maybe (Expr CoreBndr)
-match_append_lit _ [Type ty1,
+match_append_lit :: [Expr CoreBndr] -> Maybe (Expr CoreBndr)
+match_append_lit [Type ty1,
Lit (MachStr s1),
c1,
Var unpk `App` Type ty2
@@ -946,18 +1011,18 @@ match_append_lit _ [Type ty1,
`App` c1
`App` n)
-match_append_lit _ _ = Nothing
+match_append_lit _ = Nothing
---------------------------------------------------
-- The rule is this:
-- eqString (unpackCString# (Lit s1)) (unpackCString# (Lit s2) = s1==s2
-match_eq_string :: IdUnfoldingFun -> [Expr CoreBndr] -> Maybe (Expr CoreBndr)
+match_eq_string :: DynFlags -> [Expr CoreBndr] -> Maybe (Expr CoreBndr)
match_eq_string _ [Var unpk1 `App` Lit (MachStr s1),
- Var unpk2 `App` Lit (MachStr s2)]
+ Var unpk2 `App` Lit (MachStr s2)]
| unpk1 `hasKey` unpackCStringIdKey,
unpk2 `hasKey` unpackCStringIdKey
- = Just (if s1 == s2 then trueVal else falseVal)
+ = Just (if s1 == s2 then trueValBool else falseValBool)
match_eq_string _ _ = Nothing
@@ -975,41 +1040,47 @@ match_eq_string _ _ = Nothing
-- programmer can't avoid
--
-- Also, don't forget about 'inline's type argument!
-match_inline :: IdUnfoldingFun -> [Expr CoreBndr] -> Maybe (Expr CoreBndr)
-match_inline _ (Type _ : e : _)
+match_inline :: [Expr CoreBndr] -> Maybe (Expr CoreBndr)
+match_inline (Type _ : e : _)
| (Var f, args1) <- collectArgs e,
Just unf <- maybeUnfoldingTemplate (realIdUnfolding f)
-- Ignore the IdUnfoldingFun here!
= Just (mkApps unf args1)
-match_inline _ _ = Nothing
+match_inline _ = Nothing
+
+
+-- See Note [magicSingIId magic] in `basicTypes/MkId.lhs`
+-- for a description of what is going on here.
+match_magicSingI :: [Expr CoreBndr] -> Maybe (Expr CoreBndr)
+match_magicSingI (Type t : e : Lam b _ : _)
+ | ((_ : _ : fu : _),_) <- splitFunTys t
+ , (sI_type,_) <- splitFunTy fu
+ , Just (sI_tc,xs) <- splitTyConApp_maybe sI_type
+ , Just (_,_,co) <- unwrapNewTyCon_maybe sI_tc
+ = Just $ let f = setVarType b fu
+ in Lam f $ Var f `App` Cast e (mkSymCo (mkUnbranchedAxInstCo Representational co xs))
+
+match_magicSingI _ = Nothing
-------------------------------------------------
-- Integer rules
--- smallInteger (79::Int#) = 79::Integer
--- wordToInteger (79::Word#) = 79::Integer
+-- smallInteger (79::Int#) = 79::Integer
+-- wordToInteger (79::Word#) = 79::Integer
-- Similarly Int64, Word64
-match_IntToInteger :: DynFlags
- -> Id
- -> IdUnfoldingFun
- -> [Expr CoreBndr]
- -> Maybe (Expr CoreBndr)
-match_IntToInteger _ id id_unf [xl]
+match_IntToInteger :: RuleFun
+match_IntToInteger _ id_unf fn [xl]
| Just (MachInt x) <- exprIsLiteral_maybe id_unf xl
- = case idType id of
+ = case idType fn of
FunTy _ integerTy ->
Just (Lit (LitInteger x integerTy))
_ ->
panic "match_IntToInteger: Id has the wrong type"
match_IntToInteger _ _ _ _ = Nothing
-match_WordToInteger :: DynFlags
- -> Id
- -> IdUnfoldingFun
- -> [Expr CoreBndr]
- -> Maybe (Expr CoreBndr)
-match_WordToInteger _ id id_unf [xl]
+match_WordToInteger :: RuleFun
+match_WordToInteger _ id_unf id [xl]
| Just (MachWord x) <- exprIsLiteral_maybe id_unf xl
= case idType id of
FunTy _ integerTy ->
@@ -1018,12 +1089,8 @@ match_WordToInteger _ id id_unf [xl]
panic "match_WordToInteger: Id has the wrong type"
match_WordToInteger _ _ _ _ = Nothing
-match_Int64ToInteger :: DynFlags
- -> Id
- -> IdUnfoldingFun
- -> [Expr CoreBndr]
- -> Maybe (Expr CoreBndr)
-match_Int64ToInteger _ id id_unf [xl]
+match_Int64ToInteger :: RuleFun
+match_Int64ToInteger _ id_unf id [xl]
| Just (MachInt64 x) <- exprIsLiteral_maybe id_unf xl
= case idType id of
FunTy _ integerTy ->
@@ -1032,12 +1099,8 @@ match_Int64ToInteger _ id id_unf [xl]
panic "match_Int64ToInteger: Id has the wrong type"
match_Int64ToInteger _ _ _ _ = Nothing
-match_Word64ToInteger :: DynFlags
- -> Id
- -> IdUnfoldingFun
- -> [Expr CoreBndr]
- -> Maybe (Expr CoreBndr)
-match_Word64ToInteger _ id id_unf [xl]
+match_Word64ToInteger :: RuleFun
+match_Word64ToInteger _ id_unf id [xl]
| Just (MachWord64 x) <- exprIsLiteral_maybe id_unf xl
= case idType id of
FunTy _ integerTy ->
@@ -1049,47 +1112,29 @@ match_Word64ToInteger _ _ _ _ = Nothing
-------------------------------------------------
match_Integer_convert :: Num a
=> (DynFlags -> a -> Expr CoreBndr)
- -> DynFlags
- -> Id
- -> IdUnfoldingFun
- -> [Expr CoreBndr]
- -> Maybe (Expr CoreBndr)
-match_Integer_convert convert dflags _ id_unf [xl]
+ -> RuleFun
+match_Integer_convert convert dflags id_unf _ [xl]
| Just (LitInteger x _) <- exprIsLiteral_maybe id_unf xl
= Just (convert dflags (fromInteger x))
match_Integer_convert _ _ _ _ _ = Nothing
-match_Integer_unop :: (Integer -> Integer)
- -> DynFlags
- -> Id
- -> IdUnfoldingFun
- -> [Expr CoreBndr]
- -> Maybe (Expr CoreBndr)
-match_Integer_unop unop _ _ id_unf [xl]
+match_Integer_unop :: (Integer -> Integer) -> RuleFun
+match_Integer_unop unop _ id_unf _ [xl]
| Just (LitInteger x i) <- exprIsLiteral_maybe id_unf xl
= Just (Lit (LitInteger (unop x) i))
match_Integer_unop _ _ _ _ _ = Nothing
-match_Integer_binop :: (Integer -> Integer -> Integer)
- -> DynFlags
- -> Id
- -> IdUnfoldingFun
- -> [Expr CoreBndr]
- -> Maybe (Expr CoreBndr)
-match_Integer_binop binop _ _ id_unf [xl,yl]
+match_Integer_binop :: (Integer -> Integer -> Integer) -> RuleFun
+match_Integer_binop binop _ id_unf _ [xl,yl]
| Just (LitInteger x i) <- exprIsLiteral_maybe id_unf xl
, Just (LitInteger y _) <- exprIsLiteral_maybe id_unf yl
= Just (Lit (LitInteger (x `binop` y) i))
match_Integer_binop _ _ _ _ _ = Nothing
-- This helper is used for the quotRem and divMod functions
-match_Integer_divop_both :: (Integer -> Integer -> (Integer, Integer))
- -> DynFlags
- -> Id
- -> IdUnfoldingFun
- -> [Expr CoreBndr]
- -> Maybe (Expr CoreBndr)
-match_Integer_divop_both divop _ _ id_unf [xl,yl]
+match_Integer_divop_both
+ :: (Integer -> Integer -> (Integer, Integer)) -> RuleFun
+match_Integer_divop_both divop _ id_unf _ [xl,yl]
| Just (LitInteger x t) <- exprIsLiteral_maybe id_unf xl
, Just (LitInteger y _) <- exprIsLiteral_maybe id_unf yl
, y /= 0
@@ -1101,51 +1146,31 @@ match_Integer_divop_both divop _ _ id_unf [xl,yl]
Lit (LitInteger s t)]
match_Integer_divop_both _ _ _ _ _ = Nothing
--- This helper is used for the quotRem and divMod functions
-match_Integer_divop_one :: (Integer -> Integer -> Integer)
- -> DynFlags
- -> Id
- -> IdUnfoldingFun
- -> [Expr CoreBndr]
- -> Maybe (Expr CoreBndr)
-match_Integer_divop_one divop _ _ id_unf [xl,yl]
+-- This helper is used for the quot and rem functions
+match_Integer_divop_one :: (Integer -> Integer -> Integer) -> RuleFun
+match_Integer_divop_one divop _ id_unf _ [xl,yl]
| Just (LitInteger x i) <- exprIsLiteral_maybe id_unf xl
, Just (LitInteger y _) <- exprIsLiteral_maybe id_unf yl
, y /= 0
= Just (Lit (LitInteger (x `divop` y) i))
match_Integer_divop_one _ _ _ _ _ = Nothing
-match_Integer_Int_binop :: (Integer -> Int -> Integer)
- -> DynFlags
- -> Id
- -> IdUnfoldingFun
- -> [Expr CoreBndr]
- -> Maybe (Expr CoreBndr)
-match_Integer_Int_binop binop _ _ id_unf [xl,yl]
+match_Integer_Int_binop :: (Integer -> Int -> Integer) -> RuleFun
+match_Integer_Int_binop binop _ id_unf _ [xl,yl]
| Just (LitInteger x i) <- exprIsLiteral_maybe id_unf xl
, Just (MachInt y) <- exprIsLiteral_maybe id_unf yl
= Just (Lit (LitInteger (x `binop` fromIntegral y) i))
match_Integer_Int_binop _ _ _ _ _ = Nothing
-match_Integer_binop_Bool :: (Integer -> Integer -> Bool)
- -> DynFlags
- -> Id
- -> IdUnfoldingFun
- -> [Expr CoreBndr]
- -> Maybe (Expr CoreBndr)
-match_Integer_binop_Bool binop _ _ id_unf [xl, yl]
+match_Integer_binop_Prim :: (Integer -> Integer -> Bool) -> RuleFun
+match_Integer_binop_Prim binop dflags id_unf _ [xl, yl]
| Just (LitInteger x _) <- exprIsLiteral_maybe id_unf xl
, Just (LitInteger y _) <- exprIsLiteral_maybe id_unf yl
- = Just (if x `binop` y then trueVal else falseVal)
-match_Integer_binop_Bool _ _ _ _ _ = Nothing
-
-match_Integer_binop_Ordering :: (Integer -> Integer -> Ordering)
- -> DynFlags
- -> Id
- -> IdUnfoldingFun
- -> [Expr CoreBndr]
- -> Maybe (Expr CoreBndr)
-match_Integer_binop_Ordering binop _ _ id_unf [xl, yl]
+ = Just (if x `binop` y then trueValInt dflags else falseValInt dflags)
+match_Integer_binop_Prim _ _ _ _ _ = Nothing
+
+match_Integer_binop_Ordering :: (Integer -> Integer -> Ordering) -> RuleFun
+match_Integer_binop_Ordering binop _ id_unf _ [xl, yl]
| Just (LitInteger x _) <- exprIsLiteral_maybe id_unf xl
, Just (LitInteger y _) <- exprIsLiteral_maybe id_unf yl
= Just $ case x `binop` y of
@@ -1156,12 +1181,8 @@ match_Integer_binop_Ordering _ _ _ _ _ = Nothing
match_Integer_Int_encodeFloat :: RealFloat a
=> (a -> Expr CoreBndr)
- -> DynFlags
- -> Id
- -> IdUnfoldingFun
- -> [Expr CoreBndr]
- -> Maybe (Expr CoreBndr)
-match_Integer_Int_encodeFloat mkLit _ _ id_unf [xl,yl]
+ -> RuleFun
+match_Integer_Int_encodeFloat mkLit _ id_unf _ [xl,yl]
| Just (LitInteger x _) <- exprIsLiteral_maybe id_unf xl
, Just (MachInt y) <- exprIsLiteral_maybe id_unf yl
= Just (mkLit $ encodeFloat x (fromInteger y))
@@ -1179,24 +1200,16 @@ match_Integer_Int_encodeFloat _ _ _ _ _ = Nothing
-- NaN or +-Inf
match_rationalTo :: RealFloat a
=> (a -> Expr CoreBndr)
- -> DynFlags
- -> Id
- -> IdUnfoldingFun
- -> [Expr CoreBndr]
- -> Maybe (Expr CoreBndr)
-match_rationalTo mkLit _ _ id_unf [xl, yl]
+ -> RuleFun
+match_rationalTo mkLit _ id_unf _ [xl, yl]
| Just (LitInteger x _) <- exprIsLiteral_maybe id_unf xl
, Just (LitInteger y _) <- exprIsLiteral_maybe id_unf yl
, y /= 0
= Just (mkLit (fromRational (x % y)))
match_rationalTo _ _ _ _ _ = Nothing
-match_decodeDouble :: DynFlags
- -> Id
- -> IdUnfoldingFun
- -> [Expr CoreBndr]
- -> Maybe (Expr CoreBndr)
-match_decodeDouble _ fn id_unf [xl]
+match_decodeDouble :: RuleFun
+match_decodeDouble _ id_unf fn [xl]
| Just (MachDouble x) <- exprIsLiteral_maybe id_unf xl
= case idType fn of
FunTy _ (TyConApp _ [integerTy, intHashTy]) ->
@@ -1211,23 +1224,13 @@ match_decodeDouble _ fn id_unf [xl]
panic "match_decodeDouble: Id has the wrong type"
match_decodeDouble _ _ _ _ = Nothing
-match_XToIntegerToX :: Name
- -> DynFlags
- -> Id
- -> IdUnfoldingFun
- -> [Expr CoreBndr]
- -> Maybe (Expr CoreBndr)
+match_XToIntegerToX :: Name -> RuleFun
match_XToIntegerToX n _ _ _ [App (Var x) y]
| idName x == n
= Just y
match_XToIntegerToX _ _ _ _ _ = Nothing
-match_smallIntegerTo :: PrimOp
- -> DynFlags
- -> Id
- -> IdUnfoldingFun
- -> [Expr CoreBndr]
- -> Maybe (Expr CoreBndr)
+match_smallIntegerTo :: PrimOp -> RuleFun
match_smallIntegerTo primOp _ _ _ [App (Var x) y]
| idName x == smallIntegerName
= Just $ App (Var (mkPrimOpId primOp)) y