MO_F_Mul and MO_F_Add are commutative
[ghc.git] / compiler / cmm / CmmMachOp.hs
1
2 module CmmMachOp
3 ( MachOp(..)
4 , pprMachOp, isCommutableMachOp, isAssociativeMachOp
5 , isComparisonMachOp, machOpResultType
6 , machOpArgReps, maybeInvertComparison
7
8 -- MachOp builders
9 , mo_wordAdd, mo_wordSub, mo_wordEq, mo_wordNe,mo_wordMul, mo_wordSQuot
10 , mo_wordSRem, mo_wordSNeg, mo_wordUQuot, mo_wordURem
11 , mo_wordSGe, mo_wordSLe, mo_wordSGt, mo_wordSLt, mo_wordUGe
12 , mo_wordULe, mo_wordUGt, mo_wordULt
13 , mo_wordAnd, mo_wordOr, mo_wordXor, mo_wordNot, mo_wordShl, mo_wordSShr, mo_wordUShr
14 , mo_u_8To32, mo_s_8To32, mo_u_16To32, mo_s_16To32
15 , mo_u_8ToWord, mo_s_8ToWord, mo_u_16ToWord, mo_s_16ToWord, mo_u_32ToWord, mo_s_32ToWord
16 , mo_32To8, mo_32To16, mo_WordTo8, mo_WordTo16, mo_WordTo32
17
18 -- CallishMachOp
19 , CallishMachOp(..)
20 , pprCallishMachOp
21 )
22 where
23
24 #include "HsVersions.h"
25
26 import CmmType
27 import Outputable
28
29 -----------------------------------------------------------------------------
30 -- MachOp
31 -----------------------------------------------------------------------------
32
33 {- |
34 Machine-level primops; ones which we can reasonably delegate to the
35 native code generators to handle.
36
37 Most operations are parameterised by the 'Width' that they operate on.
38 Some operations have separate signed and unsigned versions, and float
39 and integer versions.
40 -}
41
42 data MachOp
43 -- Integer operations (insensitive to signed/unsigned)
44 = MO_Add Width
45 | MO_Sub Width
46 | MO_Eq Width
47 | MO_Ne Width
48 | MO_Mul Width -- low word of multiply
49
50 -- Signed multiply/divide
51 | MO_S_MulMayOflo Width -- nonzero if signed multiply overflows
52 | MO_S_Quot Width -- signed / (same semantics as IntQuotOp)
53 | MO_S_Rem Width -- signed % (same semantics as IntRemOp)
54 | MO_S_Neg Width -- unary -
55
56 -- Unsigned multiply/divide
57 | MO_U_MulMayOflo Width -- nonzero if unsigned multiply overflows
58 | MO_U_Quot Width -- unsigned / (same semantics as WordQuotOp)
59 | MO_U_Rem Width -- unsigned % (same semantics as WordRemOp)
60
61 -- Signed comparisons
62 | MO_S_Ge Width
63 | MO_S_Le Width
64 | MO_S_Gt Width
65 | MO_S_Lt Width
66
67 -- Unsigned comparisons
68 | MO_U_Ge Width
69 | MO_U_Le Width
70 | MO_U_Gt Width
71 | MO_U_Lt Width
72
73 -- Floating point arithmetic
74 | MO_F_Add Width
75 | MO_F_Sub Width
76 | MO_F_Neg Width -- unary -
77 | MO_F_Mul Width
78 | MO_F_Quot Width
79
80 -- Floating point comparison
81 | MO_F_Eq Width
82 | MO_F_Ne Width
83 | MO_F_Ge Width
84 | MO_F_Le Width
85 | MO_F_Gt Width
86 | MO_F_Lt Width
87
88 -- Bitwise operations. Not all of these may be supported
89 -- at all sizes, and only integral Widths are valid.
90 | MO_And Width
91 | MO_Or Width
92 | MO_Xor Width
93 | MO_Not Width
94 | MO_Shl Width
95 | MO_U_Shr Width -- unsigned shift right
96 | MO_S_Shr Width -- signed shift right
97
98 -- Conversions. Some of these will be NOPs.
99 -- Floating-point conversions use the signed variant.
100 | MO_SF_Conv Width Width -- Signed int -> Float
101 | MO_FS_Conv Width Width -- Float -> Signed int
102 | MO_SS_Conv Width Width -- Signed int -> Signed int
103 | MO_UU_Conv Width Width -- unsigned int -> unsigned int
104 | MO_FF_Conv Width Width -- Float -> Float
105 deriving (Eq, Show)
106
107 pprMachOp :: MachOp -> SDoc
108 pprMachOp mo = text (show mo)
109
110
111
112 -- -----------------------------------------------------------------------------
113 -- Some common MachReps
114
115 -- A 'wordRep' is a machine word on the target architecture
116 -- Specifically, it is the size of an Int#, Word#, Addr#
117 -- and the unit of allocation on the stack and the heap
118 -- Any pointer is also guaranteed to be a wordRep.
119
120 mo_wordAdd, mo_wordSub, mo_wordEq, mo_wordNe,mo_wordMul, mo_wordSQuot
121 , mo_wordSRem, mo_wordSNeg, mo_wordUQuot, mo_wordURem
122 , mo_wordSGe, mo_wordSLe, mo_wordSGt, mo_wordSLt, mo_wordUGe
123 , mo_wordULe, mo_wordUGt, mo_wordULt
124 , mo_wordAnd, mo_wordOr, mo_wordXor, mo_wordNot, mo_wordShl, mo_wordSShr, mo_wordUShr
125 , mo_u_8To32, mo_s_8To32, mo_u_16To32, mo_s_16To32
126 , mo_u_8ToWord, mo_s_8ToWord, mo_u_16ToWord, mo_s_16ToWord, mo_u_32ToWord, mo_s_32ToWord
127 , mo_32To8, mo_32To16, mo_WordTo8, mo_WordTo16, mo_WordTo32
128 :: MachOp
129
130 mo_wordAdd = MO_Add wordWidth
131 mo_wordSub = MO_Sub wordWidth
132 mo_wordEq = MO_Eq wordWidth
133 mo_wordNe = MO_Ne wordWidth
134 mo_wordMul = MO_Mul wordWidth
135 mo_wordSQuot = MO_S_Quot wordWidth
136 mo_wordSRem = MO_S_Rem wordWidth
137 mo_wordSNeg = MO_S_Neg wordWidth
138 mo_wordUQuot = MO_U_Quot wordWidth
139 mo_wordURem = MO_U_Rem wordWidth
140
141 mo_wordSGe = MO_S_Ge wordWidth
142 mo_wordSLe = MO_S_Le wordWidth
143 mo_wordSGt = MO_S_Gt wordWidth
144 mo_wordSLt = MO_S_Lt wordWidth
145
146 mo_wordUGe = MO_U_Ge wordWidth
147 mo_wordULe = MO_U_Le wordWidth
148 mo_wordUGt = MO_U_Gt wordWidth
149 mo_wordULt = MO_U_Lt wordWidth
150
151 mo_wordAnd = MO_And wordWidth
152 mo_wordOr = MO_Or wordWidth
153 mo_wordXor = MO_Xor wordWidth
154 mo_wordNot = MO_Not wordWidth
155 mo_wordShl = MO_Shl wordWidth
156 mo_wordSShr = MO_S_Shr wordWidth
157 mo_wordUShr = MO_U_Shr wordWidth
158
159 mo_u_8To32 = MO_UU_Conv W8 W32
160 mo_s_8To32 = MO_SS_Conv W8 W32
161 mo_u_16To32 = MO_UU_Conv W16 W32
162 mo_s_16To32 = MO_SS_Conv W16 W32
163
164 mo_u_8ToWord = MO_UU_Conv W8 wordWidth
165 mo_s_8ToWord = MO_SS_Conv W8 wordWidth
166 mo_u_16ToWord = MO_UU_Conv W16 wordWidth
167 mo_s_16ToWord = MO_SS_Conv W16 wordWidth
168 mo_s_32ToWord = MO_SS_Conv W32 wordWidth
169 mo_u_32ToWord = MO_UU_Conv W32 wordWidth
170
171 mo_WordTo8 = MO_UU_Conv wordWidth W8
172 mo_WordTo16 = MO_UU_Conv wordWidth W16
173 mo_WordTo32 = MO_UU_Conv wordWidth W32
174
175 mo_32To8 = MO_UU_Conv W32 W8
176 mo_32To16 = MO_UU_Conv W32 W16
177
178
179 -- ----------------------------------------------------------------------------
180 -- isCommutableMachOp
181
182 {- |
183 Returns 'True' if the MachOp has commutable arguments. This is used
184 in the platform-independent Cmm optimisations.
185
186 If in doubt, return 'False'. This generates worse code on the
187 native routes, but is otherwise harmless.
188 -}
189 isCommutableMachOp :: MachOp -> Bool
190 isCommutableMachOp mop =
191 case mop of
192 MO_Add _ -> True
193 MO_Eq _ -> True
194 MO_Ne _ -> True
195 MO_Mul _ -> True
196 MO_S_MulMayOflo _ -> True
197 MO_U_MulMayOflo _ -> True
198 MO_And _ -> True
199 MO_Or _ -> True
200 MO_Xor _ -> True
201 MO_F_Add _ -> True
202 MO_F_Mul _ -> True
203 _other -> False
204
205 -- ----------------------------------------------------------------------------
206 -- isAssociativeMachOp
207
208 {- |
209 Returns 'True' if the MachOp is associative (i.e. @(x+y)+z == x+(y+z)@)
210 This is used in the platform-independent Cmm optimisations.
211
212 If in doubt, return 'False'. This generates worse code on the
213 native routes, but is otherwise harmless.
214 -}
215 isAssociativeMachOp :: MachOp -> Bool
216 isAssociativeMachOp mop =
217 case mop of
218 MO_Add {} -> True -- NB: does not include
219 MO_Mul {} -> True -- floatint point!
220 MO_And {} -> True
221 MO_Or {} -> True
222 MO_Xor {} -> True
223 _other -> False
224
225 -- ----------------------------------------------------------------------------
226 -- isComparisonMachOp
227
228 {- |
229 Returns 'True' if the MachOp is a comparison.
230
231 If in doubt, return False. This generates worse code on the
232 native routes, but is otherwise harmless.
233 -}
234 isComparisonMachOp :: MachOp -> Bool
235 isComparisonMachOp mop =
236 case mop of
237 MO_Eq _ -> True
238 MO_Ne _ -> True
239 MO_S_Ge _ -> True
240 MO_S_Le _ -> True
241 MO_S_Gt _ -> True
242 MO_S_Lt _ -> True
243 MO_U_Ge _ -> True
244 MO_U_Le _ -> True
245 MO_U_Gt _ -> True
246 MO_U_Lt _ -> True
247 MO_F_Eq {} -> True
248 MO_F_Ne {} -> True
249 MO_F_Ge {} -> True
250 MO_F_Le {} -> True
251 MO_F_Gt {} -> True
252 MO_F_Lt {} -> True
253 _other -> False
254
255 -- -----------------------------------------------------------------------------
256 -- Inverting conditions
257
258 -- Sometimes it's useful to be able to invert the sense of a
259 -- condition. Not all conditional tests are invertible: in
260 -- particular, floating point conditionals cannot be inverted, because
261 -- there exist floating-point values which return False for both senses
262 -- of a condition (eg. !(NaN > NaN) && !(NaN /<= NaN)).
263
264 maybeInvertComparison :: MachOp -> Maybe MachOp
265 maybeInvertComparison op
266 = case op of -- None of these Just cases include floating point
267 MO_Eq r -> Just (MO_Ne r)
268 MO_Ne r -> Just (MO_Eq r)
269 MO_U_Lt r -> Just (MO_U_Ge r)
270 MO_U_Gt r -> Just (MO_U_Le r)
271 MO_U_Le r -> Just (MO_U_Gt r)
272 MO_U_Ge r -> Just (MO_U_Lt r)
273 MO_S_Lt r -> Just (MO_S_Ge r)
274 MO_S_Gt r -> Just (MO_S_Le r)
275 MO_S_Le r -> Just (MO_S_Gt r)
276 MO_S_Ge r -> Just (MO_S_Lt r)
277 MO_F_Eq r -> Just (MO_F_Ne r)
278 MO_F_Ne r -> Just (MO_F_Eq r)
279 MO_F_Ge r -> Just (MO_F_Le r)
280 MO_F_Le r -> Just (MO_F_Ge r)
281 MO_F_Gt r -> Just (MO_F_Lt r)
282 MO_F_Lt r -> Just (MO_F_Gt r)
283 _other -> Nothing
284
285 -- ----------------------------------------------------------------------------
286 -- machOpResultType
287
288 {- |
289 Returns the MachRep of the result of a MachOp.
290 -}
291 machOpResultType :: MachOp -> [CmmType] -> CmmType
292 machOpResultType mop tys =
293 case mop of
294 MO_Add {} -> ty1 -- Preserve GC-ptr-hood
295 MO_Sub {} -> ty1 -- of first arg
296 MO_Mul r -> cmmBits r
297 MO_S_MulMayOflo r -> cmmBits r
298 MO_S_Quot r -> cmmBits r
299 MO_S_Rem r -> cmmBits r
300 MO_S_Neg r -> cmmBits r
301 MO_U_MulMayOflo r -> cmmBits r
302 MO_U_Quot r -> cmmBits r
303 MO_U_Rem r -> cmmBits r
304
305 MO_Eq {} -> comparisonResultRep
306 MO_Ne {} -> comparisonResultRep
307 MO_S_Ge {} -> comparisonResultRep
308 MO_S_Le {} -> comparisonResultRep
309 MO_S_Gt {} -> comparisonResultRep
310 MO_S_Lt {} -> comparisonResultRep
311
312 MO_U_Ge {} -> comparisonResultRep
313 MO_U_Le {} -> comparisonResultRep
314 MO_U_Gt {} -> comparisonResultRep
315 MO_U_Lt {} -> comparisonResultRep
316
317 MO_F_Add r -> cmmFloat r
318 MO_F_Sub r -> cmmFloat r
319 MO_F_Mul r -> cmmFloat r
320 MO_F_Quot r -> cmmFloat r
321 MO_F_Neg r -> cmmFloat r
322 MO_F_Eq {} -> comparisonResultRep
323 MO_F_Ne {} -> comparisonResultRep
324 MO_F_Ge {} -> comparisonResultRep
325 MO_F_Le {} -> comparisonResultRep
326 MO_F_Gt {} -> comparisonResultRep
327 MO_F_Lt {} -> comparisonResultRep
328
329 MO_And {} -> ty1 -- Used for pointer masking
330 MO_Or {} -> ty1
331 MO_Xor {} -> ty1
332 MO_Not r -> cmmBits r
333 MO_Shl r -> cmmBits r
334 MO_U_Shr r -> cmmBits r
335 MO_S_Shr r -> cmmBits r
336
337 MO_SS_Conv _ to -> cmmBits to
338 MO_UU_Conv _ to -> cmmBits to
339 MO_FS_Conv _ to -> cmmBits to
340 MO_SF_Conv _ to -> cmmFloat to
341 MO_FF_Conv _ to -> cmmFloat to
342 where
343 (ty1:_) = tys
344
345 comparisonResultRep :: CmmType
346 comparisonResultRep = bWord -- is it?
347
348
349 -- -----------------------------------------------------------------------------
350 -- machOpArgReps
351
352 -- | This function is used for debugging only: we can check whether an
353 -- application of a MachOp is "type-correct" by checking that the MachReps of
354 -- its arguments are the same as the MachOp expects. This is used when
355 -- linting a CmmExpr.
356
357 machOpArgReps :: MachOp -> [Width]
358 machOpArgReps op =
359 case op of
360 MO_Add r -> [r,r]
361 MO_Sub r -> [r,r]
362 MO_Eq r -> [r,r]
363 MO_Ne r -> [r,r]
364 MO_Mul r -> [r,r]
365 MO_S_MulMayOflo r -> [r,r]
366 MO_S_Quot r -> [r,r]
367 MO_S_Rem r -> [r,r]
368 MO_S_Neg r -> [r]
369 MO_U_MulMayOflo r -> [r,r]
370 MO_U_Quot r -> [r,r]
371 MO_U_Rem r -> [r,r]
372
373 MO_S_Ge r -> [r,r]
374 MO_S_Le r -> [r,r]
375 MO_S_Gt r -> [r,r]
376 MO_S_Lt r -> [r,r]
377
378 MO_U_Ge r -> [r,r]
379 MO_U_Le r -> [r,r]
380 MO_U_Gt r -> [r,r]
381 MO_U_Lt r -> [r,r]
382
383 MO_F_Add r -> [r,r]
384 MO_F_Sub r -> [r,r]
385 MO_F_Mul r -> [r,r]
386 MO_F_Quot r -> [r,r]
387 MO_F_Neg r -> [r]
388 MO_F_Eq r -> [r,r]
389 MO_F_Ne r -> [r,r]
390 MO_F_Ge r -> [r,r]
391 MO_F_Le r -> [r,r]
392 MO_F_Gt r -> [r,r]
393 MO_F_Lt r -> [r,r]
394
395 MO_And r -> [r,r]
396 MO_Or r -> [r,r]
397 MO_Xor r -> [r,r]
398 MO_Not r -> [r]
399 MO_Shl r -> [r,wordWidth]
400 MO_U_Shr r -> [r,wordWidth]
401 MO_S_Shr r -> [r,wordWidth]
402
403 MO_SS_Conv from _ -> [from]
404 MO_UU_Conv from _ -> [from]
405 MO_SF_Conv from _ -> [from]
406 MO_FS_Conv from _ -> [from]
407 MO_FF_Conv from _ -> [from]
408
409 -----------------------------------------------------------------------------
410 -- CallishMachOp
411 -----------------------------------------------------------------------------
412
413 -- CallishMachOps tend to be implemented by foreign calls in some backends,
414 -- so we separate them out. In Cmm, these can only occur in a
415 -- statement position, in contrast to an ordinary MachOp which can occur
416 -- anywhere in an expression.
417 data CallishMachOp
418 = MO_F64_Pwr
419 | MO_F64_Sin
420 | MO_F64_Cos
421 | MO_F64_Tan
422 | MO_F64_Sinh
423 | MO_F64_Cosh
424 | MO_F64_Tanh
425 | MO_F64_Asin
426 | MO_F64_Acos
427 | MO_F64_Atan
428 | MO_F64_Log
429 | MO_F64_Exp
430 | MO_F64_Sqrt
431 | MO_F32_Pwr
432 | MO_F32_Sin
433 | MO_F32_Cos
434 | MO_F32_Tan
435 | MO_F32_Sinh
436 | MO_F32_Cosh
437 | MO_F32_Tanh
438 | MO_F32_Asin
439 | MO_F32_Acos
440 | MO_F32_Atan
441 | MO_F32_Log
442 | MO_F32_Exp
443 | MO_F32_Sqrt
444
445 | MO_S_QuotRem Width
446 | MO_U_QuotRem Width
447 | MO_U_QuotRem2 Width
448 | MO_Add2 Width
449 | MO_U_Mul2 Width
450
451 | MO_WriteBarrier
452 | MO_Touch -- Keep variables live (when using interior pointers)
453
454 -- Note that these three MachOps all take 1 extra parameter than the
455 -- standard C lib versions. The extra (last) parameter contains
456 -- alignment of the pointers. Used for optimisation in backends.
457 | MO_Memcpy
458 | MO_Memset
459 | MO_Memmove
460
461 | MO_PopCnt Width
462 deriving (Eq, Show)
463
464 pprCallishMachOp :: CallishMachOp -> SDoc
465 pprCallishMachOp mo = text (show mo)
466