2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
4 \section[ConFold]{Constant Folder}
6 Conceptually, constant folding should be parameterized with the kind
7 of target machine to get identical behaviour during compilation time
8 and runtime. We cheat a little bit here...
11 check boundaries before folding, e.g. we can fold the Float addition
12 (i1 + i2) only if it results in a valid Float.
16 {-# OPTIONS -optc-DNON_POSIX_SOURCE #-}
18 module PrelRules ( primOpRules, builtinRules ) where
20 #include "HsVersions.h"
23 import Id ( mkWildId, idUnfolding )
24 import Literal ( Literal(..), mkMachInt, mkMachWord
26 , word2IntLit, int2WordLit
27 , narrow8IntLit, narrow16IntLit, narrow32IntLit
28 , narrow8WordLit, narrow16WordLit, narrow32WordLit
29 , char2IntLit, int2CharLit
30 , float2IntLit, int2FloatLit, double2IntLit, int2DoubleLit
31 , float2DoubleLit, double2FloatLit
33 import PrimOp ( PrimOp(..), tagToEnumKey )
34 import TysWiredIn ( boolTy, trueDataConId, falseDataConId )
35 import TyCon ( tyConDataCons_maybe, isEnumerationTyCon, isNewTyCon )
36 import DataCon ( dataConTag, dataConTyCon, dataConWorkId, fIRST_TAG )
37 import CoreUtils ( cheapEqExpr, exprIsConApp_maybe )
38 import Type ( tyConAppTyCon, coreEqType )
39 import OccName ( occNameFS )
40 import PrelNames ( unpackCStringFoldrName, unpackCStringFoldrIdKey, hasKey,
41 eqStringName, unpackCStringIdKey, inlineIdName )
42 import Maybes ( orElse )
43 import Name ( Name, nameOccName )
46 import StaticFlags ( opt_SimplExcessPrecision )
48 import Data.Bits ( Bits(..) )
49 #if __GLASGOW_HASKELL__ >= 500
50 import Data.Word ( Word )
52 import Data.Word ( Word64 )
57 Note [Constant folding]
58 ~~~~~~~~~~~~~~~~~~~~~~~
59 primOpRules generates the rewrite rules for each primop
60 These rules do what is often called "constant folding"
61 E.g. the rules for +# might say
63 Well, of course you'd need a lot of rules if you did it
64 like that, so we use a BuiltinRule instead, so that we
65 can match in any two literal values. So the rule is really
67 (Lit 4) +# (Lit y) = Lit (x+#y)
68 where the (+#) on the rhs is done at compile time
70 That is why these rules are built in here. Other rules
71 which don't need to be built in are in GHC.Base. For
77 primOpRules :: PrimOp -> Name -> [CoreRule]
78 primOpRules op op_name = primop_rule op
81 one_lit = oneLit op_name
82 two_lits = twoLits op_name
83 relop cmp = two_lits (cmpOp (\ord -> ord `cmp` EQ))
84 -- Cunning. cmpOp compares the values to give an Ordering.
85 -- It applies its argument to that ordering value to turn
86 -- the ordering into a boolean value. (`cmp` EQ) is just the job.
88 -- ToDo: something for integer-shift ops?
91 primop_rule TagToEnumOp = mkBasicRule op_name 2 tagToEnumRule
92 primop_rule DataToTagOp = mkBasicRule op_name 2 dataToTagRule
95 primop_rule IntAddOp = two_lits (intOp2 (+))
96 primop_rule IntSubOp = two_lits (intOp2 (-))
97 primop_rule IntMulOp = two_lits (intOp2 (*))
98 primop_rule IntQuotOp = two_lits (intOp2Z quot)
99 primop_rule IntRemOp = two_lits (intOp2Z rem)
100 primop_rule IntNegOp = one_lit negOp
103 #if __GLASGOW_HASKELL__ >= 500
104 primop_rule WordAddOp = two_lits (wordOp2 (+))
105 primop_rule WordSubOp = two_lits (wordOp2 (-))
106 primop_rule WordMulOp = two_lits (wordOp2 (*))
108 primop_rule WordQuotOp = two_lits (wordOp2Z quot)
109 primop_rule WordRemOp = two_lits (wordOp2Z rem)
110 #if __GLASGOW_HASKELL__ >= 407
111 primop_rule AndOp = two_lits (wordBitOp2 (.&.))
112 primop_rule OrOp = two_lits (wordBitOp2 (.|.))
113 primop_rule XorOp = two_lits (wordBitOp2 xor)
117 primop_rule Word2IntOp = one_lit (litCoerce word2IntLit)
118 primop_rule Int2WordOp = one_lit (litCoerce int2WordLit)
119 primop_rule Narrow8IntOp = one_lit (litCoerce narrow8IntLit)
120 primop_rule Narrow16IntOp = one_lit (litCoerce narrow16IntLit)
121 primop_rule Narrow32IntOp = one_lit (litCoerce narrow32IntLit)
122 primop_rule Narrow8WordOp = one_lit (litCoerce narrow8WordLit)
123 primop_rule Narrow16WordOp = one_lit (litCoerce narrow16WordLit)
124 primop_rule Narrow32WordOp = one_lit (litCoerce narrow32WordLit)
125 primop_rule OrdOp = one_lit (litCoerce char2IntLit)
126 primop_rule ChrOp = one_lit (litCoerce int2CharLit)
127 primop_rule Float2IntOp = one_lit (litCoerce float2IntLit)
128 primop_rule Int2FloatOp = one_lit (litCoerce int2FloatLit)
129 primop_rule Double2IntOp = one_lit (litCoerce double2IntLit)
130 primop_rule Int2DoubleOp = one_lit (litCoerce int2DoubleLit)
131 -- SUP: Not sure what the standard says about precision in the following 2 cases
132 primop_rule Float2DoubleOp = one_lit (litCoerce float2DoubleLit)
133 primop_rule Double2FloatOp = one_lit (litCoerce double2FloatLit)
136 primop_rule FloatAddOp = two_lits (floatOp2 (+))
137 primop_rule FloatSubOp = two_lits (floatOp2 (-))
138 primop_rule FloatMulOp = two_lits (floatOp2 (*))
139 primop_rule FloatDivOp = two_lits (floatOp2Z (/))
140 primop_rule FloatNegOp = one_lit negOp
143 primop_rule DoubleAddOp = two_lits (doubleOp2 (+))
144 primop_rule DoubleSubOp = two_lits (doubleOp2 (-))
145 primop_rule DoubleMulOp = two_lits (doubleOp2 (*))
146 primop_rule DoubleDivOp = two_lits (doubleOp2Z (/))
147 primop_rule DoubleNegOp = one_lit negOp
149 -- Relational operators
150 primop_rule IntEqOp = relop (==) ++ litEq op_name True
151 primop_rule IntNeOp = relop (/=) ++ litEq op_name False
152 primop_rule CharEqOp = relop (==) ++ litEq op_name True
153 primop_rule CharNeOp = relop (/=) ++ litEq op_name False
155 primop_rule IntGtOp = relop (>)
156 primop_rule IntGeOp = relop (>=)
157 primop_rule IntLeOp = relop (<=)
158 primop_rule IntLtOp = relop (<)
160 primop_rule CharGtOp = relop (>)
161 primop_rule CharGeOp = relop (>=)
162 primop_rule CharLeOp = relop (<=)
163 primop_rule CharLtOp = relop (<)
165 primop_rule FloatGtOp = relop (>)
166 primop_rule FloatGeOp = relop (>=)
167 primop_rule FloatLeOp = relop (<=)
168 primop_rule FloatLtOp = relop (<)
169 primop_rule FloatEqOp = relop (==)
170 primop_rule FloatNeOp = relop (/=)
172 primop_rule DoubleGtOp = relop (>)
173 primop_rule DoubleGeOp = relop (>=)
174 primop_rule DoubleLeOp = relop (<=)
175 primop_rule DoubleLtOp = relop (<)
176 primop_rule DoubleEqOp = relop (==)
177 primop_rule DoubleNeOp = relop (/=)
179 primop_rule WordGtOp = relop (>)
180 primop_rule WordGeOp = relop (>=)
181 primop_rule WordLeOp = relop (<=)
182 primop_rule WordLtOp = relop (<)
183 primop_rule WordEqOp = relop (==)
184 primop_rule WordNeOp = relop (/=)
186 primop_rule other = []
191 %************************************************************************
193 \subsection{Doing the business}
195 %************************************************************************
197 ToDo: the reason these all return Nothing is because there used to be
198 the possibility of an argument being a litlit. Litlits are now gone,
199 so this could be cleaned up.
202 --------------------------
203 litCoerce :: (Literal -> Literal) -> Literal -> Maybe CoreExpr
204 litCoerce fn lit = Just (Lit (fn lit))
206 --------------------------
207 cmpOp :: (Ordering -> Bool) -> Literal -> Literal -> Maybe CoreExpr
211 done res | cmp res = Just trueVal
212 | otherwise = Just falseVal
214 -- These compares are at different types
215 go (MachChar i1) (MachChar i2) = done (i1 `compare` i2)
216 go (MachInt i1) (MachInt i2) = done (i1 `compare` i2)
217 go (MachInt64 i1) (MachInt64 i2) = done (i1 `compare` i2)
218 go (MachWord i1) (MachWord i2) = done (i1 `compare` i2)
219 go (MachWord64 i1) (MachWord64 i2) = done (i1 `compare` i2)
220 go (MachFloat i1) (MachFloat i2) = done (i1 `compare` i2)
221 go (MachDouble i1) (MachDouble i2) = done (i1 `compare` i2)
224 --------------------------
226 negOp :: Literal -> Maybe CoreExpr -- Negate
227 negOp (MachFloat 0.0) = Nothing -- can't represent -0.0 as a Rational
228 negOp (MachFloat f) = Just (mkFloatVal (-f))
229 negOp (MachDouble 0.0) = Nothing
230 negOp (MachDouble d) = Just (mkDoubleVal (-d))
231 negOp (MachInt i) = intResult (-i)
234 --------------------------
235 intOp2 :: (Integer->Integer->Integer) -> Literal -> Literal -> Maybe CoreExpr
236 intOp2 op (MachInt i1) (MachInt i2) = intResult (i1 `op` i2)
237 intOp2 op l1 l2 = Nothing -- Could find LitLit
239 intOp2Z :: (Integer->Integer->Integer) -> Literal -> Literal -> Maybe CoreExpr
240 -- Like intOp2, but Nothing if i2=0
241 intOp2Z op (MachInt i1) (MachInt i2)
242 | i2 /= 0 = intResult (i1 `op` i2)
243 intOp2Z op l1 l2 = Nothing -- LitLit or zero dividend
245 --------------------------
246 #if __GLASGOW_HASKELL__ >= 500
247 wordOp2 :: (Integer->Integer->Integer) -> Literal -> Literal -> Maybe CoreExpr
248 wordOp2 op (MachWord w1) (MachWord w2)
249 = wordResult (w1 `op` w2)
250 wordOp2 op l1 l2 = Nothing -- Could find LitLit
253 wordOp2Z :: (Integer->Integer->Integer) -> Literal -> Literal -> Maybe CoreExpr
254 wordOp2Z op (MachWord w1) (MachWord w2)
255 | w2 /= 0 = wordResult (w1 `op` w2)
256 wordOp2Z op l1 l2 = Nothing -- LitLit or zero dividend
258 #if __GLASGOW_HASKELL__ >= 500
259 wordBitOp2 op l1@(MachWord w1) l2@(MachWord w2)
260 = wordResult (w1 `op` w2)
262 -- Integer is not an instance of Bits, so we operate on Word64
263 wordBitOp2 op l1@(MachWord w1) l2@(MachWord w2)
264 = wordResult ((fromIntegral::Word64->Integer) (fromIntegral w1 `op` fromIntegral w2))
266 wordBitOp2 op l1 l2 = Nothing -- Could find LitLit
268 --------------------------
269 floatOp2 op (MachFloat f1) (MachFloat f2)
270 = Just (mkFloatVal (f1 `op` f2))
271 floatOp2 op l1 l2 = Nothing
273 floatOp2Z op (MachFloat f1) (MachFloat f2)
274 | f2 /= 0 = Just (mkFloatVal (f1 `op` f2))
275 floatOp2Z op l1 l2 = Nothing
277 --------------------------
278 doubleOp2 op (MachDouble f1) (MachDouble f2)
279 = Just (mkDoubleVal (f1 `op` f2))
280 doubleOp2 op l1 l2 = Nothing
282 doubleOp2Z op (MachDouble f1) (MachDouble f2)
283 | f2 /= 0 = Just (mkDoubleVal (f1 `op` f2))
284 doubleOp2Z op l1 l2 = Nothing
287 --------------------------
295 -- This is a Good Thing, because it allows case-of case things
296 -- to happen, and case-default absorption to happen. For
299 -- if (n ==# 3#) || (n ==# 4#) then e1 else e2
305 -- (modulo the usual precautions to avoid duplicating e1)
308 -> Bool -- True <=> equality, False <=> inequality
311 = [BuiltinRule { ru_name = occNameFS (nameOccName op_name)
312 `appendFS` FSLIT("->case"),
314 ru_nargs = 2, ru_try = rule_fn }]
316 rule_fn [Lit lit, expr] = do_lit_eq lit expr
317 rule_fn [expr, Lit lit] = do_lit_eq lit expr
318 rule_fn other = Nothing
321 = Just (Case expr (mkWildId (literalType lit)) boolTy
322 [(DEFAULT, [], val_if_neq),
323 (LitAlt lit, [], val_if_eq)])
324 val_if_eq | is_eq = trueVal
325 | otherwise = falseVal
326 val_if_neq | is_eq = falseVal
327 | otherwise = trueVal
329 -- Note that we *don't* warn the user about overflow. It's not done at
330 -- runtime either, and compilation of completely harmless things like
331 -- ((124076834 :: Word32) + (2147483647 :: Word32))
332 -- would yield a warning. Instead we simply squash the value into the
333 -- Int range, but not in a way suitable for cross-compiling... :-(
334 intResult :: Integer -> Maybe CoreExpr
336 = Just (mkIntVal (toInteger (fromInteger result :: Int)))
338 #if __GLASGOW_HASKELL__ >= 500
339 wordResult :: Integer -> Maybe CoreExpr
341 = Just (mkWordVal (toInteger (fromInteger result :: Word)))
346 %************************************************************************
348 \subsection{Vaguely generic functions
350 %************************************************************************
353 mkBasicRule :: Name -> Int -> ([CoreExpr] -> Maybe CoreExpr) -> [CoreRule]
354 -- Gives the Rule the same name as the primop itself
355 mkBasicRule op_name n_args rule_fn
356 = [BuiltinRule { ru_name = occNameFS (nameOccName op_name),
358 ru_nargs = n_args, ru_try = rule_fn }]
360 oneLit :: Name -> (Literal -> Maybe CoreExpr)
363 = mkBasicRule op_name 1 rule_fn
365 rule_fn [Lit l1] = test (convFloating l1)
368 twoLits :: Name -> (Literal -> Literal -> Maybe CoreExpr)
371 = mkBasicRule op_name 2 rule_fn
373 rule_fn [Lit l1, Lit l2] = test (convFloating l1) (convFloating l2)
376 -- When excess precision is not requested, cut down the precision of the
377 -- Rational value to that of Float/Double. We confuse host architecture
378 -- and target architecture here, but it's convenient (and wrong :-).
379 convFloating :: Literal -> Literal
380 convFloating (MachFloat f) | not opt_SimplExcessPrecision =
381 MachFloat (toRational ((fromRational f) :: Float ))
382 convFloating (MachDouble d) | not opt_SimplExcessPrecision =
383 MachDouble (toRational ((fromRational d) :: Double))
386 trueVal = Var trueDataConId
387 falseVal = Var falseDataConId
388 mkIntVal i = Lit (mkMachInt i)
389 mkWordVal w = Lit (mkMachWord w)
390 mkFloatVal f = Lit (convFloating (MachFloat f))
391 mkDoubleVal d = Lit (convFloating (MachDouble d))
395 %************************************************************************
397 \subsection{Special rules for seq, tagToEnum, dataToTag}
399 %************************************************************************
402 tagToEnumRule [Type ty, Lit (MachInt i)]
403 = ASSERT( isEnumerationTyCon tycon )
404 case filter correct_tag (tyConDataCons_maybe tycon `orElse` []) of
407 [] -> Nothing -- Abstract type
408 (dc:rest) -> ASSERT( null rest )
409 Just (Var (dataConWorkId dc))
411 correct_tag dc = (dataConTag dc - fIRST_TAG) == tag
413 tycon = tyConAppTyCon ty
415 tagToEnumRule other = Nothing
418 For dataToTag#, we can reduce if either
420 (a) the argument is a constructor
421 (b) the argument is a variable whose unfolding is a known constructor
424 dataToTagRule [Type ty1, Var tag_to_enum `App` Type ty2 `App` tag]
425 | tag_to_enum `hasKey` tagToEnumKey
426 , ty1 `coreEqType` ty2
427 = Just tag -- dataToTag (tagToEnum x) ==> x
429 dataToTagRule [_, val_arg]
430 | Just (dc,_) <- exprIsConApp_maybe val_arg
431 = ASSERT( not (isNewTyCon (dataConTyCon dc)) )
432 Just (mkIntVal (toInteger (dataConTag dc - fIRST_TAG)))
434 dataToTagRule other = Nothing
437 %************************************************************************
439 \subsection{Built in rules}
441 %************************************************************************
444 builtinRules :: [CoreRule]
445 -- Rules for non-primops that can't be expressed using a RULE pragma
447 = [ BuiltinRule FSLIT("AppendLitString") unpackCStringFoldrName 4 match_append_lit,
448 BuiltinRule FSLIT("EqString") eqStringName 2 match_eq_string,
449 BuiltinRule FSLIT("Inline") inlineIdName 1 match_inline
453 ---------------------------------------------------
455 -- unpackFoldrCString# "foo" c (unpackFoldrCString# "baz" c n) = unpackFoldrCString# "foobaz" c n
457 match_append_lit [Type ty1,
460 Var unpk `App` Type ty2
461 `App` Lit (MachStr s2)
465 | unpk `hasKey` unpackCStringFoldrIdKey &&
467 = ASSERT( ty1 `coreEqType` ty2 )
468 Just (Var unpk `App` Type ty1
469 `App` Lit (MachStr (s1 `appendFS` s2))
473 match_append_lit other = Nothing
475 ---------------------------------------------------
477 -- eqString (unpackCString# (Lit s1)) (unpackCString# (Lit s2) = s1==s2
479 match_eq_string [Var unpk1 `App` Lit (MachStr s1),
480 Var unpk2 `App` Lit (MachStr s2)]
481 | unpk1 `hasKey` unpackCStringIdKey,
482 unpk2 `hasKey` unpackCStringIdKey
483 = Just (if s1 == s2 then trueVal else falseVal)
485 match_eq_string other = Nothing
488 ---------------------------------------------------
490 -- inline (f a b c) = <f's unfolding> a b c
491 -- (if f has an unfolding)
493 | (Var f, args1) <- collectArgs e,
494 Just unf <- maybeUnfoldingTemplate (idUnfolding f)
495 = Just (mkApps unf args1)
497 match_inline other = Nothing