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