[project @ 2000-03-27 13:24:12 by simonpj]
[ghc-hetmet.git] / ghc / compiler / prelude / PrelRules.lhs
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
3 %
4 \section[ConFold]{Constant Folder}
5
6 ToDo:
7    check boundaries before folding, e.g. we can fold the Float addition
8    (i1 + i2) only if it results in a valid Float.
9
10 \begin{code}
11 module PrelRules ( primOpRule, builtinRules ) where
12
13 #include "HsVersions.h"
14
15 import CoreSyn
16 import Rules            ( ProtoCoreRule(..) )
17 import Id               ( idUnfolding, mkWildId, isDataConId_maybe )
18 import Literal          ( Literal(..), mkMachInt, mkMachWord, inIntRange, literalType,
19                           word2IntLit, int2WordLit, int2CharLit, char2IntLit, int2FloatLit, int2DoubleLit
20                         )
21 import PrimOp           ( PrimOp(..), primOpOcc )
22 import TysWiredIn       ( trueDataConId, falseDataConId )
23 import TyCon            ( tyConDataCons, isEnumerationTyCon, isNewTyCon )
24 import DataCon          ( DataCon, dataConTag, dataConRepArity, dataConTyCon, dataConId, fIRST_TAG )
25 import CoreUnfold       ( maybeUnfoldingTemplate )
26 import CoreUtils        ( exprIsValue, cheapEqExpr, exprIsConApp_maybe )
27 import Type             ( splitTyConApp_maybe )
28 import OccName          ( occNameUserString)
29 import ThinAir          ( unpackCStringFoldrId )
30 import Maybes           ( maybeToBool )
31 import Char             ( ord, chr )
32 import Outputable
33 \end{code}
34
35
36
37 \begin{code}
38 primOpRule :: PrimOp -> CoreRule
39 primOpRule op 
40   = BuiltinRule (primop_rule op)
41   where
42     op_name = _PK_ (occNameUserString (primOpOcc op))
43     op_name_case = op_name _APPEND_ SLIT("case")
44
45     -- ToDo:    something for integer-shift ops?
46     --          NotOp
47     --          Int2WordOp      -- SIGH: these two cause trouble in unfoldery
48     --          Int2AddrOp      -- as we can't distinguish unsigned literals in interfaces (ToDo?)
49
50     primop_rule SeqOp       = seqRule
51     primop_rule TagToEnumOp = tagToEnumRule
52     primop_rule DataToTagOp = dataToTagRule
53
54         -- Char operations
55     primop_rule OrdOp           = oneLit (litCoerce char2IntLit op_name)
56  
57         -- Int/Word operations
58     primop_rule IntAddOp    = twoLits (intOp2 (+) op_name)
59     primop_rule IntSubOp    = twoLits (intOp2 (-) op_name)
60     primop_rule IntMulOp    = twoLits (intOp2 (*) op_name)
61     primop_rule IntQuotOp   = twoLits (intOp2Z quot op_name)
62     primop_rule IntRemOp    = twoLits (intOp2Z rem  op_name)
63     primop_rule IntNegOp    = oneLit  (negOp op_name)
64
65     primop_rule ChrOp           = oneLit (litCoerce int2CharLit   op_name)
66     primop_rule Int2FloatOp     = oneLit (litCoerce int2FloatLit  op_name)
67     primop_rule Int2DoubleOp    = oneLit (litCoerce int2DoubleLit op_name)
68     primop_rule Word2IntOp      = oneLit (litCoerce word2IntLit   op_name)
69     primop_rule Int2WordOp      = oneLit (litCoerce int2WordLit   op_name)
70
71         -- Float
72     primop_rule FloatAddOp   = twoLits (floatOp2 (+) op_name)
73     primop_rule FloatSubOp   = twoLits (floatOp2 (-) op_name)
74     primop_rule FloatMulOp   = twoLits (floatOp2 (*) op_name)
75     primop_rule FloatDivOp   = twoLits (floatOp2Z (/) op_name)
76     primop_rule FloatNegOp   = oneLit  (negOp op_name)
77
78         -- Double
79     primop_rule DoubleAddOp   = twoLits (doubleOp2 (+) op_name)
80     primop_rule DoubleSubOp   = twoLits (doubleOp2 (-) op_name)
81     primop_rule DoubleMulOp   = twoLits (doubleOp2 (*) op_name)
82     primop_rule DoubleDivOp   = twoLits (doubleOp2Z (/) op_name)
83
84         -- Relational operators
85     primop_rule IntEqOp  = relop (==) `or_rule` litEq True  op_name_case
86     primop_rule IntNeOp  = relop (/=) `or_rule` litEq False op_name_case
87     primop_rule CharEqOp = relop (==) `or_rule` litEq True  op_name_case
88     primop_rule CharNeOp = relop (/=) `or_rule` litEq False op_name_case
89
90     primop_rule IntGtOp         = relop (>) 
91     primop_rule IntGeOp         = relop (>=)
92     primop_rule IntLeOp         = relop (<=)
93     primop_rule IntLtOp         = relop (<) 
94                                             
95     primop_rule CharGtOp        = relop (>) 
96     primop_rule CharGeOp        = relop (>=)
97     primop_rule CharLeOp        = relop (<=)
98     primop_rule CharLtOp        = relop (<) 
99                                             
100     primop_rule FloatGtOp       = relop (>) 
101     primop_rule FloatGeOp       = relop (>=)
102     primop_rule FloatLeOp       = relop (<=)
103     primop_rule FloatLtOp       = relop (<) 
104     primop_rule FloatEqOp       = relop (==)
105     primop_rule FloatNeOp       = relop (/=)
106                                             
107     primop_rule DoubleGtOp      = relop (>) 
108     primop_rule DoubleGeOp      = relop (>=)
109     primop_rule DoubleLeOp      = relop (<=)
110     primop_rule DoubleLtOp      = relop (<) 
111     primop_rule DoubleEqOp      = relop (==)
112     primop_rule DoubleNeOp      = relop (/=)
113                                             
114     primop_rule WordGtOp        = relop (>) 
115     primop_rule WordGeOp        = relop (>=)
116     primop_rule WordLeOp        = relop (<=)
117     primop_rule WordLtOp        = relop (<) 
118     primop_rule WordEqOp        = relop (==)
119     primop_rule WordNeOp        = relop (/=)
120
121     primop_rule other           = \args -> Nothing
122
123
124     relop cmp = twoLits (cmpOp (\ord -> ord `cmp` EQ) op_name)
125         -- Cunning.  cmpOp compares the values to give an Ordering.
126         -- It applies its argument to that ordering value to turn
127         -- the ordering into a boolean value.  (`cmp` EQ) is just the job.
128 \end{code}
129
130 %************************************************************************
131 %*                                                                      *
132 \subsection{Doing the business}
133 %*                                                                      *
134 %************************************************************************
135
136         IMPORTANT NOTE
137
138 In all these operations we might find a LitLit as an operand; that's
139 why we have the catch-all Nothing case.
140
141 \begin{code}
142 --------------------------
143 litCoerce :: (Literal -> Literal) -> RuleName -> Literal -> Maybe (RuleName, CoreExpr)
144 litCoerce fn name lit = Just (name, Lit (fn lit))
145
146 --------------------------
147 cmpOp :: (Ordering -> Bool) -> FAST_STRING -> Literal -> Literal -> Maybe (RuleName, CoreExpr)
148 cmpOp cmp name l1 l2
149   = go l1 l2
150   where
151     done res | cmp res = Just (name, trueVal)
152              | otherwise    = Just (name, falseVal)
153
154         -- These compares are at different types
155     go (MachChar i1)   (MachChar i2)   = done (i1 `compare` i2)
156     go (MachInt i1)    (MachInt i2)    = done (i1 `compare` i2)
157     go (MachInt64 i1)  (MachInt64 i2)  = done (i1 `compare` i2)
158     go (MachWord i1)   (MachWord i2)   = done (i1 `compare` i2)
159     go (MachWord64 i1) (MachWord64 i2) = done (i1 `compare` i2)
160     go (MachFloat i1)  (MachFloat i2)  = done (i1 `compare` i2)
161     go (MachDouble i1) (MachDouble i2) = done (i1 `compare` i2)
162     go l1              l2              = Nothing
163
164 --------------------------
165
166 negOp name (MachFloat f)  = Just (name, mkFloatVal (-f))
167 negOp name (MachDouble d) = Just (name, mkDoubleVal (-d))
168 negOp name l@(MachInt i)  = intResult name (ppr l) (-i)
169 negOp name l              = Nothing
170
171 --------------------------
172 intOp2 op name l1@(MachInt i1) l2@(MachInt i2)
173   = intResult name (ppr l1 <+> ppr l2) (i1 `op` i2)
174 intOp2 op name l1 l2 = Nothing          -- Could find LitLit
175
176 intOp2Z op name (MachInt i1) (MachInt i2)
177   | i2 /= 0 = Just (name, mkIntVal (i1 `op` i2))
178 intOp2Z op name l1 l2 = Nothing         -- LitLit or zero dividend
179
180
181 --------------------------
182 floatOp2  op name (MachFloat f1) (MachFloat f2)
183   = Just (name, mkFloatVal (f1 `op` f2))
184 floatOp2  op name l1 l2 = Nothing
185
186 floatOp2Z op name (MachFloat f1) (MachFloat f2)
187   | f1 /= 0   = Just (name, mkFloatVal (f1 `op` f2))
188 floatOp2Z op name l1 l2 = Nothing
189
190
191
192 --------------------------
193 doubleOp2  op name (MachDouble f1) (MachDouble f2)
194   = Just (name, mkDoubleVal (f1 `op` f2))
195 doubleOp2 op name l1 l2 = Nothing
196
197 doubleOp2Z op name (MachDouble f1) (MachDouble f2)
198   | f1 /= 0   = Just (name, mkDoubleVal (f1 `op` f2))
199 doubleOp2Z op name l1 l2 = Nothing
200
201
202 --------------------------
203         -- This stuff turns
204         --      n ==# 3#
205         -- into
206         --      case n of
207         --        3# -> True
208         --        m  -> False
209         --
210         -- This is a Good Thing, because it allows case-of case things
211         -- to happen, and case-default absorption to happen.  For
212         -- example:
213         --
214         --      if (n ==# 3#) || (n ==# 4#) then e1 else e2
215         -- will transform to
216         --      case n of
217         --        3# -> e1
218         --        4# -> e1
219         --        m  -> e2
220         -- (modulo the usual precautions to avoid duplicating e1)
221
222 litEq :: Bool           -- True <=> equality, False <=> inequality
223         -> RuleName
224         -> RuleFun
225 litEq is_eq name [Lit lit, expr] = do_lit_eq is_eq name lit expr
226 litEq is_eq name [expr, Lit lit] = do_lit_eq is_eq name lit expr
227 litEq is_eq name other           = Nothing
228
229 do_lit_eq is_eq name lit expr
230   = Just (name, Case expr (mkWildId (literalType lit))
231                      [(LitAlt lit, [], val_if_eq),
232                       (DEFAULT,    [], val_if_neq)])
233   where
234     val_if_eq  | is_eq     = trueVal
235                | otherwise = falseVal
236     val_if_neq | is_eq     = falseVal
237                | otherwise = trueVal
238
239 intResult name pp_args result
240   | not (inIntRange result)
241         -- Better tell the user that we've overflowed...
242         -- ..not that it stops us from actually folding!
243   
244   = pprTrace "Warning:" (text "Integer overflow in:" <+> ppr name <+> pp_args)
245     Just (name, mkIntVal (squash result))
246
247   | otherwise
248   = Just (name, mkIntVal result)
249
250 squash :: Integer -> Integer    -- Squash into Int range
251 squash i = toInteger ((fromInteger i)::Int)
252 \end{code}
253
254
255 %************************************************************************
256 %*                                                                      *
257 \subsection{Vaguely generic functions
258 %*                                                                      *
259 %************************************************************************
260
261 \begin{code}
262 type RuleFun = [CoreExpr] -> Maybe (RuleName, CoreExpr)
263
264 or_rule :: RuleFun -> RuleFun -> RuleFun
265 or_rule r1 r2 args = case r1 args of
266                    Just stuff -> Just stuff
267                    Nothing    -> r2 args
268
269 twoLits :: (Literal -> Literal -> Maybe (RuleName, CoreExpr)) -> RuleFun
270 twoLits rule [Lit l1, Lit l2] = rule l1 l2
271 twoLits rule other            = Nothing
272
273 oneLit :: (Literal -> Maybe (RuleName, CoreExpr)) -> RuleFun
274 oneLit rule [Lit l1] = rule l1
275 oneLit rule other    = Nothing
276
277
278 trueVal       = Var trueDataConId
279 falseVal      = Var falseDataConId
280 mkIntVal i    = Lit (mkMachInt i)
281 mkCharVal c   = Lit (MachChar   c)
282 mkFloatVal f  = Lit (MachFloat  f)
283 mkDoubleVal d = Lit (MachDouble d)
284 \end{code}
285
286                                                 
287 %************************************************************************
288 %*                                                                      *
289 \subsection{Special rules for seq, tagToEnum, dataToTag}
290 %*                                                                      *
291 %************************************************************************
292
293 In the parallel world, we use _seq_ to control the order in which
294 certain expressions will be evaluated.  Operationally, the expression
295 ``_seq_ a b'' evaluates a and then evaluates b.  We have an inlining
296 for _seq_ which translates _seq_ to:
297
298    _seq_ = /\ a b -> \ x::a y::b -> case seq# x of { 0# -> parError#; _ -> y }
299
300 Now, we know that the seq# primitive will never return 0#, but we
301 don't let the simplifier know that.  We also use a special error
302 value, parError#, which is *not* a bottoming Id, so as far as the
303 simplifier is concerned, we have to evaluate seq# a before we know
304 whether or not y will be evaluated.
305
306 If we didn't have the extra case, then after inlining the compiler might
307 see:
308         f p q = case seq# p of { _ -> p+q }
309
310 If it sees that, it can see that f is strict in q, and hence it might
311 evaluate q before p!  The "0# ->" case prevents this happening.
312 By having the parError# branch we make sure that anything in the
313 other branch stays there!
314
315 This is fine, but we'd like to get rid of the extraneous code.  Hence,
316 we *do* let the simplifier know that seq# is strict in its argument.
317 As a result, we hope that `a' will be evaluated before seq# is called.
318 At this point, we have a very special and magical simpification which
319 says that ``seq# a'' can be immediately simplified to `1#' if we
320 know that `a' is already evaluated.
321
322 NB: If we ever do case-floating, we have an extra worry:
323
324     case a of
325       a' -> let b' = case seq# a of { True -> b; False -> parError# }
326             in case b' of ...
327
328     =>
329
330     case a of
331       a' -> let b' = case True of { True -> b; False -> parError# }
332             in case b' of ...
333
334     =>
335
336     case a of
337       a' -> let b' = b
338             in case b' of ...
339
340     =>
341
342     case a of
343       a' -> case b of ...
344
345 The second case must never be floated outside of the first!
346
347 \begin{code}
348 seqRule [Type ty, arg] | exprIsValue arg = Just (SLIT("Seq"), mkIntVal 1)
349 seqRule other                            = Nothing
350 \end{code}
351
352
353 \begin{code}
354 tagToEnumRule [Type ty, Lit (MachInt i)]
355   = ASSERT( isEnumerationTyCon tycon ) 
356     Just (SLIT("TagToEnum"), Var (dataConId dc))
357   where 
358     tag = fromInteger i
359     constrs = tyConDataCons tycon
360     (dc:_) = [ dc | dc <- constrs, tag == dataConTag dc - fIRST_TAG ]
361     (Just (tycon,_)) = splitTyConApp_maybe ty
362
363 tagToEnumRule other = Nothing
364 \end{code}
365
366 For dataToTag#, we can reduce if either 
367         
368         (a) the argument is a constructor
369         (b) the argument is a variable whose unfolding is a known constructor
370
371 \begin{code}
372 dataToTagRule [_, val_arg]
373   = case exprIsConApp_maybe val_arg of
374         Just (dc,_) -> ASSERT( not (isNewTyCon (dataConTyCon dc)) )
375                        Just (SLIT("DataToTag"), 
376                              mkIntVal (toInteger (dataConTag dc - fIRST_TAG)))
377
378         other       -> Nothing
379
380 dataToTagRule other = Nothing
381 \end{code}
382
383 %************************************************************************
384 %*                                                                      *
385 \subsection{Built in rules}
386 %*                                                                      *
387 %************************************************************************
388
389 \begin{code}
390 builtinRules :: [ProtoCoreRule]
391 -- Rules for non-primops that can't be expressed using a RULE pragma
392 builtinRules
393   = [ ProtoCoreRule False unpackCStringFoldrId 
394                     (BuiltinRule match_append_lit_str)
395     ]
396
397
398 -- unpack "foo" c (unpack "baz" c n)  =  unpack "foobaz" c n
399
400 match_append_lit_str [Type ty1,
401                       Lit (MachStr s1),
402                       c1,
403                       Var unpk `App` Type ty2 
404                                `App` Lit (MachStr s2)
405                                `App` c2
406                                `App` n
407                      ]
408   | unpk == unpackCStringFoldrId && 
409     c1 `cheapEqExpr` c2
410   = ASSERT( ty1 == ty2 )
411     Just (SLIT("AppendLitString"),
412           Var unpk `App` Type ty1
413                    `App` Lit (MachStr (s1 _APPEND_ s2))
414                    `App` c1
415                    `App` n)
416
417 match_append_lit_str other = Nothing
418 \end{code}