520c7e7a7d5a0bc45b3377676936d7925d9b9632
[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(..)
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 deriving (Eq, Show)
107
108 pprMachOp :: MachOp -> SDoc
109 pprMachOp mo = text (show mo)
110
111
112
113 -- -----------------------------------------------------------------------------
114 -- Some common MachReps
115
116 -- A 'wordRep' is a machine word on the target architecture
117 -- Specifically, it is the size of an Int#, Word#, Addr#
118 -- and the unit of allocation on the stack and the heap
119 -- Any pointer is also guaranteed to be a wordRep.
120
121 mo_wordAdd, mo_wordSub, mo_wordEq, mo_wordNe,mo_wordMul, mo_wordSQuot
122 , mo_wordSRem, mo_wordSNeg, mo_wordUQuot, mo_wordURem
123 , mo_wordSGe, mo_wordSLe, mo_wordSGt, mo_wordSLt, mo_wordUGe
124 , mo_wordULe, mo_wordUGt, mo_wordULt
125 , mo_wordAnd, mo_wordOr, mo_wordXor, mo_wordNot, mo_wordShl, mo_wordSShr, mo_wordUShr
126 , mo_u_8ToWord, mo_s_8ToWord, mo_u_16ToWord, mo_s_16ToWord, mo_u_32ToWord, mo_s_32ToWord
127 , mo_WordTo8, mo_WordTo16, mo_WordTo32, mo_WordTo64
128 :: DynFlags -> MachOp
129
130 mo_u_8To32, mo_s_8To32, mo_u_16To32, mo_s_16To32
131 , mo_32To8, mo_32To16
132 :: MachOp
133
134 mo_wordAdd dflags = MO_Add (wordWidth dflags)
135 mo_wordSub dflags = MO_Sub (wordWidth dflags)
136 mo_wordEq dflags = MO_Eq (wordWidth dflags)
137 mo_wordNe dflags = MO_Ne (wordWidth dflags)
138 mo_wordMul dflags = MO_Mul (wordWidth dflags)
139 mo_wordSQuot dflags = MO_S_Quot (wordWidth dflags)
140 mo_wordSRem dflags = MO_S_Rem (wordWidth dflags)
141 mo_wordSNeg dflags = MO_S_Neg (wordWidth dflags)
142 mo_wordUQuot dflags = MO_U_Quot (wordWidth dflags)
143 mo_wordURem dflags = MO_U_Rem (wordWidth dflags)
144
145 mo_wordSGe dflags = MO_S_Ge (wordWidth dflags)
146 mo_wordSLe dflags = MO_S_Le (wordWidth dflags)
147 mo_wordSGt dflags = MO_S_Gt (wordWidth dflags)
148 mo_wordSLt dflags = MO_S_Lt (wordWidth dflags)
149
150 mo_wordUGe dflags = MO_U_Ge (wordWidth dflags)
151 mo_wordULe dflags = MO_U_Le (wordWidth dflags)
152 mo_wordUGt dflags = MO_U_Gt (wordWidth dflags)
153 mo_wordULt dflags = MO_U_Lt (wordWidth dflags)
154
155 mo_wordAnd dflags = MO_And (wordWidth dflags)
156 mo_wordOr dflags = MO_Or (wordWidth dflags)
157 mo_wordXor dflags = MO_Xor (wordWidth dflags)
158 mo_wordNot dflags = MO_Not (wordWidth dflags)
159 mo_wordShl dflags = MO_Shl (wordWidth dflags)
160 mo_wordSShr dflags = MO_S_Shr (wordWidth dflags)
161 mo_wordUShr dflags = MO_U_Shr (wordWidth dflags)
162
163 mo_u_8To32 = MO_UU_Conv W8 W32
164 mo_s_8To32 = MO_SS_Conv W8 W32
165 mo_u_16To32 = MO_UU_Conv W16 W32
166 mo_s_16To32 = MO_SS_Conv W16 W32
167
168 mo_u_8ToWord dflags = MO_UU_Conv W8 (wordWidth dflags)
169 mo_s_8ToWord dflags = MO_SS_Conv W8 (wordWidth dflags)
170 mo_u_16ToWord dflags = MO_UU_Conv W16 (wordWidth dflags)
171 mo_s_16ToWord dflags = MO_SS_Conv W16 (wordWidth dflags)
172 mo_s_32ToWord dflags = MO_SS_Conv W32 (wordWidth dflags)
173 mo_u_32ToWord dflags = MO_UU_Conv W32 (wordWidth dflags)
174
175 mo_WordTo8 dflags = MO_UU_Conv (wordWidth dflags) W8
176 mo_WordTo16 dflags = MO_UU_Conv (wordWidth dflags) W16
177 mo_WordTo32 dflags = MO_UU_Conv (wordWidth dflags) W32
178 mo_WordTo64 dflags = MO_UU_Conv (wordWidth dflags) W64
179
180 mo_32To8 = MO_UU_Conv W32 W8
181 mo_32To16 = MO_UU_Conv W32 W16
182
183
184 -- ----------------------------------------------------------------------------
185 -- isCommutableMachOp
186
187 {- |
188 Returns 'True' if the MachOp has commutable arguments. This is used
189 in the platform-independent Cmm optimisations.
190
191 If in doubt, return 'False'. This generates worse code on the
192 native routes, but is otherwise harmless.
193 -}
194 isCommutableMachOp :: MachOp -> Bool
195 isCommutableMachOp mop =
196 case mop of
197 MO_Add _ -> True
198 MO_Eq _ -> True
199 MO_Ne _ -> True
200 MO_Mul _ -> True
201 MO_S_MulMayOflo _ -> True
202 MO_U_MulMayOflo _ -> True
203 MO_And _ -> True
204 MO_Or _ -> True
205 MO_Xor _ -> True
206 MO_F_Add _ -> True
207 MO_F_Mul _ -> True
208 _other -> False
209
210 -- ----------------------------------------------------------------------------
211 -- isAssociativeMachOp
212
213 {- |
214 Returns 'True' if the MachOp is associative (i.e. @(x+y)+z == x+(y+z)@)
215 This is used in the platform-independent Cmm optimisations.
216
217 If in doubt, return 'False'. This generates worse code on the
218 native routes, but is otherwise harmless.
219 -}
220 isAssociativeMachOp :: MachOp -> Bool
221 isAssociativeMachOp mop =
222 case mop of
223 MO_Add {} -> True -- NB: does not include
224 MO_Mul {} -> True -- floatint point!
225 MO_And {} -> True
226 MO_Or {} -> True
227 MO_Xor {} -> True
228 _other -> False
229
230 -- ----------------------------------------------------------------------------
231 -- isComparisonMachOp
232
233 {- |
234 Returns 'True' if the MachOp is a comparison.
235
236 If in doubt, return False. This generates worse code on the
237 native routes, but is otherwise harmless.
238 -}
239 isComparisonMachOp :: MachOp -> Bool
240 isComparisonMachOp mop =
241 case mop of
242 MO_Eq _ -> True
243 MO_Ne _ -> True
244 MO_S_Ge _ -> True
245 MO_S_Le _ -> True
246 MO_S_Gt _ -> True
247 MO_S_Lt _ -> True
248 MO_U_Ge _ -> True
249 MO_U_Le _ -> True
250 MO_U_Gt _ -> True
251 MO_U_Lt _ -> True
252 MO_F_Eq {} -> True
253 MO_F_Ne {} -> True
254 MO_F_Ge {} -> True
255 MO_F_Le {} -> True
256 MO_F_Gt {} -> True
257 MO_F_Lt {} -> True
258 _other -> False
259
260 -- -----------------------------------------------------------------------------
261 -- Inverting conditions
262
263 -- Sometimes it's useful to be able to invert the sense of a
264 -- condition. Not all conditional tests are invertible: in
265 -- particular, floating point conditionals cannot be inverted, because
266 -- there exist floating-point values which return False for both senses
267 -- of a condition (eg. !(NaN > NaN) && !(NaN /<= NaN)).
268
269 maybeInvertComparison :: MachOp -> Maybe MachOp
270 maybeInvertComparison op
271 = case op of -- None of these Just cases include floating point
272 MO_Eq r -> Just (MO_Ne r)
273 MO_Ne r -> Just (MO_Eq r)
274 MO_U_Lt r -> Just (MO_U_Ge r)
275 MO_U_Gt r -> Just (MO_U_Le r)
276 MO_U_Le r -> Just (MO_U_Gt r)
277 MO_U_Ge r -> Just (MO_U_Lt r)
278 MO_S_Lt r -> Just (MO_S_Ge r)
279 MO_S_Gt r -> Just (MO_S_Le r)
280 MO_S_Le r -> Just (MO_S_Gt r)
281 MO_S_Ge r -> Just (MO_S_Lt r)
282 _other -> Nothing
283
284 -- ----------------------------------------------------------------------------
285 -- machOpResultType
286
287 {- |
288 Returns the MachRep of the result of a MachOp.
289 -}
290 machOpResultType :: DynFlags -> MachOp -> [CmmType] -> CmmType
291 machOpResultType dflags mop tys =
292 case mop of
293 MO_Add {} -> ty1 -- Preserve GC-ptr-hood
294 MO_Sub {} -> ty1 -- of first arg
295 MO_Mul r -> cmmBits r
296 MO_S_MulMayOflo r -> cmmBits r
297 MO_S_Quot r -> cmmBits r
298 MO_S_Rem r -> cmmBits r
299 MO_S_Neg r -> cmmBits r
300 MO_U_MulMayOflo r -> cmmBits r
301 MO_U_Quot r -> cmmBits r
302 MO_U_Rem r -> cmmBits r
303
304 MO_Eq {} -> comparisonResultRep dflags
305 MO_Ne {} -> comparisonResultRep dflags
306 MO_S_Ge {} -> comparisonResultRep dflags
307 MO_S_Le {} -> comparisonResultRep dflags
308 MO_S_Gt {} -> comparisonResultRep dflags
309 MO_S_Lt {} -> comparisonResultRep dflags
310
311 MO_U_Ge {} -> comparisonResultRep dflags
312 MO_U_Le {} -> comparisonResultRep dflags
313 MO_U_Gt {} -> comparisonResultRep dflags
314 MO_U_Lt {} -> comparisonResultRep dflags
315
316 MO_F_Add r -> cmmFloat r
317 MO_F_Sub r -> cmmFloat r
318 MO_F_Mul r -> cmmFloat r
319 MO_F_Quot r -> cmmFloat r
320 MO_F_Neg r -> cmmFloat r
321 MO_F_Eq {} -> comparisonResultRep dflags
322 MO_F_Ne {} -> comparisonResultRep dflags
323 MO_F_Ge {} -> comparisonResultRep dflags
324 MO_F_Le {} -> comparisonResultRep dflags
325 MO_F_Gt {} -> comparisonResultRep dflags
326 MO_F_Lt {} -> comparisonResultRep dflags
327
328 MO_And {} -> ty1 -- Used for pointer masking
329 MO_Or {} -> ty1
330 MO_Xor {} -> ty1
331 MO_Not r -> cmmBits r
332 MO_Shl r -> cmmBits r
333 MO_U_Shr r -> cmmBits r
334 MO_S_Shr r -> cmmBits r
335
336 MO_SS_Conv _ to -> cmmBits to
337 MO_UU_Conv _ to -> cmmBits to
338 MO_FS_Conv _ to -> cmmBits to
339 MO_SF_Conv _ to -> cmmFloat to
340 MO_FF_Conv _ to -> cmmFloat to
341 where
342 (ty1:_) = tys
343
344 comparisonResultRep :: DynFlags -> CmmType
345 comparisonResultRep = bWord -- is it?
346
347
348 -- -----------------------------------------------------------------------------
349 -- machOpArgReps
350
351 -- | This function is used for debugging only: we can check whether an
352 -- application of a MachOp is "type-correct" by checking that the MachReps of
353 -- its arguments are the same as the MachOp expects. This is used when
354 -- linting a CmmExpr.
355
356 machOpArgReps :: DynFlags -> MachOp -> [Width]
357 machOpArgReps dflags op =
358 case op of
359 MO_Add r -> [r,r]
360 MO_Sub r -> [r,r]
361 MO_Eq r -> [r,r]
362 MO_Ne r -> [r,r]
363 MO_Mul r -> [r,r]
364 MO_S_MulMayOflo r -> [r,r]
365 MO_S_Quot r -> [r,r]
366 MO_S_Rem r -> [r,r]
367 MO_S_Neg r -> [r]
368 MO_U_MulMayOflo r -> [r,r]
369 MO_U_Quot r -> [r,r]
370 MO_U_Rem r -> [r,r]
371
372 MO_S_Ge r -> [r,r]
373 MO_S_Le r -> [r,r]
374 MO_S_Gt r -> [r,r]
375 MO_S_Lt r -> [r,r]
376
377 MO_U_Ge r -> [r,r]
378 MO_U_Le r -> [r,r]
379 MO_U_Gt r -> [r,r]
380 MO_U_Lt r -> [r,r]
381
382 MO_F_Add r -> [r,r]
383 MO_F_Sub r -> [r,r]
384 MO_F_Mul r -> [r,r]
385 MO_F_Quot r -> [r,r]
386 MO_F_Neg r -> [r]
387 MO_F_Eq r -> [r,r]
388 MO_F_Ne r -> [r,r]
389 MO_F_Ge r -> [r,r]
390 MO_F_Le r -> [r,r]
391 MO_F_Gt r -> [r,r]
392 MO_F_Lt r -> [r,r]
393
394 MO_And r -> [r,r]
395 MO_Or r -> [r,r]
396 MO_Xor r -> [r,r]
397 MO_Not r -> [r]
398 MO_Shl r -> [r, wordWidth dflags]
399 MO_U_Shr r -> [r, wordWidth dflags]
400 MO_S_Shr r -> [r, wordWidth dflags]
401
402 MO_SS_Conv from _ -> [from]
403 MO_UU_Conv from _ -> [from]
404 MO_SF_Conv from _ -> [from]
405 MO_FS_Conv from _ -> [from]
406 MO_FF_Conv from _ -> [from]
407
408 -----------------------------------------------------------------------------
409 -- CallishMachOp
410 -----------------------------------------------------------------------------
411
412 -- CallishMachOps tend to be implemented by foreign calls in some backends,
413 -- so we separate them out. In Cmm, these can only occur in a
414 -- statement position, in contrast to an ordinary MachOp which can occur
415 -- anywhere in an expression.
416 data CallishMachOp
417 = MO_F64_Pwr
418 | MO_F64_Sin
419 | MO_F64_Cos
420 | MO_F64_Tan
421 | MO_F64_Sinh
422 | MO_F64_Cosh
423 | MO_F64_Tanh
424 | MO_F64_Asin
425 | MO_F64_Acos
426 | MO_F64_Atan
427 | MO_F64_Log
428 | MO_F64_Exp
429 | MO_F64_Sqrt
430 | MO_F32_Pwr
431 | MO_F32_Sin
432 | MO_F32_Cos
433 | MO_F32_Tan
434 | MO_F32_Sinh
435 | MO_F32_Cosh
436 | MO_F32_Tanh
437 | MO_F32_Asin
438 | MO_F32_Acos
439 | MO_F32_Atan
440 | MO_F32_Log
441 | MO_F32_Exp
442 | MO_F32_Sqrt
443
444 | MO_S_QuotRem Width
445 | MO_U_QuotRem Width
446 | MO_U_QuotRem2 Width
447 | MO_Add2 Width
448 | MO_U_Mul2 Width
449
450 | MO_WriteBarrier
451 | MO_Touch -- Keep variables live (when using interior pointers)
452
453 -- Note that these three MachOps all take 1 extra parameter than the
454 -- standard C lib versions. The extra (last) parameter contains
455 -- alignment of the pointers. Used for optimisation in backends.
456 | MO_Memcpy
457 | MO_Memset
458 | MO_Memmove
459
460 | MO_PopCnt Width
461 deriving (Eq, Show)
462
463 pprCallishMachOp :: CallishMachOp -> SDoc
464 pprCallishMachOp mo = text (show mo)
465