summaryrefslogtreecommitdiff
path: root/compiler/prelude/PrelRules.lhs
diff options
context:
space:
mode:
authorIan Lynagh <igloo@earth.li>2011-09-24 21:35:06 +0100
committerIan Lynagh <igloo@earth.li>2011-09-24 21:35:06 +0100
commitdac072bad236a1d0498239cc5421cad0c12328ca (patch)
treec86f4c7a3885977e40d6840ac69077c635e58860 /compiler/prelude/PrelRules.lhs
parent488e21c8cf07340c4d2f86f8177825a321cb312d (diff)
downloadhaskell-dac072bad236a1d0498239cc5421cad0c12328ca.tar.gz
Add some more Integer rules
Also renumbered the IDs and alined some things properly
Diffstat (limited to 'compiler/prelude/PrelRules.lhs')
-rw-r--r--compiler/prelude/PrelRules.lhs107
1 files changed, 66 insertions, 41 deletions
diff --git a/compiler/prelude/PrelRules.lhs b/compiler/prelude/PrelRules.lhs
index e8467aa27d..13e3a9cfb8 100644
--- a/compiler/prelude/PrelRules.lhs
+++ b/compiler/prelude/PrelRules.lhs
@@ -30,6 +30,7 @@ import DataCon ( dataConTag, dataConTyCon, dataConWorkId, fIRST_TAG )
import CoreUtils ( cheapEqExpr, exprIsHNF )
import CoreUnfold ( exprIsConApp_maybe )
import Type
+import TypeRep
import OccName ( occNameFS )
import PrelNames
import Maybes ( orElse )
@@ -605,57 +606,61 @@ are explicit.)
builtinRules :: [CoreRule]
-- Rules for non-primops that can't be expressed using a RULE pragma
builtinRules
- = [ BuiltinRule { ru_name = fsLit "AppendLitString", ru_fn = unpackCStringFoldrName,
- ru_nargs = 4, ru_try = match_append_lit },
- BuiltinRule { ru_name = fsLit "EqString", ru_fn = eqStringName,
- ru_nargs = 2, ru_try = match_eq_string },
- BuiltinRule { ru_name = fsLit "Inline", ru_fn = inlineIdName,
- ru_nargs = 2, ru_try = match_inline },
- rule_Integer_convert "integerToWord" integerToWordName mkWordLitWord,
- rule_Integer_convert "integerToInt" integerToIntName mkIntLitInt,
- rule_Integer_binop "plusInteger" plusIntegerName (+),
- rule_Integer_binop "timesInteger" timesIntegerName (*),
- rule_Integer_binop "minusInteger" minusIntegerName (-),
- rule_Integer_unop "negateInteger" negateIntegerName negate,
- rule_Integer_binop_Bool "eqInteger" eqIntegerName (==),
- rule_Integer_binop_Bool "neqInteger" neqIntegerName (/=),
- rule_Integer_unop "absInteger" absIntegerName abs,
- rule_Integer_unop "signumInteger" signumIntegerName signum,
- rule_Integer_binop_Bool "leInteger" leIntegerName (<=),
- rule_Integer_binop_Bool "gtInteger" gtIntegerName (>),
- rule_Integer_binop_Bool "ltInteger" ltIntegerName (<),
- rule_Integer_binop_Bool "geInteger" geIntegerName (>=),
- rule_Integer_binop_Ordering "compareInteger" compareIntegerName compare,
- -- TODO: divMod/quoteRem/quot/rem rules. Due to the 0 check we
- -- need rules for the generic functions, rather than the
- -- Integer-specific functions
- rule_Integer_binop "gcdInteger" gcdIntegerName gcd,
- rule_Integer_binop "lcmInteger" lcmIntegerName lcm,
- rule_Integer_binop "andInteger" andIntegerName (.&.),
- rule_Integer_binop "orInteger" orIntegerName (.|.),
- rule_Integer_binop "xorInteger" xorIntegerName xor,
- rule_Integer_unop "complementInteger" complementIntegerName complement,
- -- TODO: Likewise, these rules currently don't do anything, due to
- -- the sign test in shift's definition
- rule_Integer_Int_binop "shiftLInteger" shiftLIntegerName shiftL,
- rule_Integer_Int_binop "shiftRInteger" shiftRIntegerName shiftR
- ]
- where rule_Integer_convert str name convert
+ = [BuiltinRule { ru_name = fsLit "AppendLitString",
+ ru_fn = unpackCStringFoldrName,
+ ru_nargs = 4, ru_try = match_append_lit },
+ BuiltinRule { ru_name = fsLit "EqString", ru_fn = eqStringName,
+ ru_nargs = 2, ru_try = match_eq_string },
+ BuiltinRule { ru_name = fsLit "Inline", ru_fn = inlineIdName,
+ ru_nargs = 2, ru_try = match_inline }]
+ ++ builtinIntegerRules
+
+builtinIntegerRules :: [CoreRule]
+builtinIntegerRules =
+ [rule_convert "integerToWord" integerToWordName mkWordLitWord,
+ rule_convert "integerToInt" integerToIntName mkIntLitInt,
+ rule_binop "plusInteger" plusIntegerName (+),
+ rule_binop "timesInteger" timesIntegerName (*),
+ rule_binop "minusInteger" minusIntegerName (-),
+ rule_unop "negateInteger" negateIntegerName negate,
+ rule_binop_Bool "eqInteger" eqIntegerName (==),
+ rule_binop_Bool "neqInteger" neqIntegerName (/=),
+ 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_Ordering "compareInteger" compareIntegerName compare,
+ rule_divop "quotRemInteger" quotRemIntegerName quotRem,
+ rule_divop "divModInteger" divModIntegerName divMod,
+ rule_binop "gcdInteger" gcdIntegerName gcd,
+ rule_binop "lcmInteger" lcmIntegerName lcm,
+ rule_binop "andInteger" andIntegerName (.&.),
+ rule_binop "orInteger" orIntegerName (.|.),
+ rule_binop "xorInteger" xorIntegerName xor,
+ rule_unop "complementInteger" complementIntegerName complement,
+ rule_Int_binop "shiftLInteger" shiftLIntegerName shiftL,
+ rule_Int_binop "shiftRInteger" shiftRIntegerName shiftR]
+ where rule_convert str name convert
= BuiltinRule { ru_name = fsLit str, ru_fn = name, ru_nargs = 1,
ru_try = match_Integer_convert convert }
- rule_Integer_unop str name op
+ rule_unop str name op
= BuiltinRule { ru_name = fsLit str, ru_fn = name, ru_nargs = 1,
ru_try = match_Integer_unop op }
- rule_Integer_binop str name op
+ rule_binop str name op
= BuiltinRule { ru_name = fsLit str, ru_fn = name, ru_nargs = 2,
ru_try = match_Integer_binop op }
- rule_Integer_Int_binop str name op
+ rule_divop str name op
+ = BuiltinRule { ru_name = fsLit str, ru_fn = name, ru_nargs = 2,
+ ru_try = match_Integer_divop op }
+ 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_Integer_binop_Bool str name op
+ rule_binop_Bool str name op
= BuiltinRule { ru_name = fsLit str, ru_fn = name, ru_nargs = 2,
ru_try = match_Integer_binop_Bool op }
- rule_Integer_binop_Ordering str name 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 }
@@ -746,6 +751,26 @@ match_Integer_binop binop _ [Lit (LitInteger x i), Lit (LitInteger y _)]
= Just (Lit (LitInteger (x `binop` y) i))
match_Integer_binop _ _ _ = Nothing
+-- This helper is used for the quotRem and divMod functions
+match_Integer_divop :: (Integer -> Integer -> (Integer, Integer))
+ -> IdUnfoldingFun
+ -> [Expr CoreBndr]
+ -> Maybe (Expr CoreBndr)
+match_Integer_divop divop _ [Lit (LitInteger x i), Lit (LitInteger y _)]
+ | y /= 0
+ = case x `divop` y of
+ (r, s) ->
+ case idType i of
+ FunTy _ (FunTy _ integerTy) ->
+ Just $ mkConApp (tupleCon UnboxedTuple 2)
+ [Type integerTy,
+ Type integerTy,
+ Lit (LitInteger r i),
+ Lit (LitInteger s i)]
+ _ -> panic "match_Integer_divop: mkIntegerId has the wrong type"
+
+match_Integer_divop _ _ _ = Nothing
+
match_Integer_Int_binop :: (Integer -> Int -> Integer)
-> IdUnfoldingFun
-> [Expr CoreBndr]