comment updates
[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 _other -> False
202
203 -- ----------------------------------------------------------------------------
204 -- isAssociativeMachOp
205
206 {- |
207 Returns 'True' if the MachOp is associative (i.e. @(x+y)+z == x+(y+z)@)
208 This is used in the platform-independent Cmm optimisations.
209
210 If in doubt, return 'False'. This generates worse code on the
211 native routes, but is otherwise harmless.
212 -}
213 isAssociativeMachOp :: MachOp -> Bool
214 isAssociativeMachOp mop =
215 case mop of
216 MO_Add {} -> True -- NB: does not include
217 MO_Mul {} -> True -- floatint point!
218 MO_And {} -> True
219 MO_Or {} -> True
220 MO_Xor {} -> True
221 _other -> False
222
223 -- ----------------------------------------------------------------------------
224 -- isComparisonMachOp
225
226 {- |
227 Returns 'True' if the MachOp is a comparison.
228
229 If in doubt, return False. This generates worse code on the
230 native routes, but is otherwise harmless.
231 -}
232 isComparisonMachOp :: MachOp -> Bool
233 isComparisonMachOp mop =
234 case mop of
235 MO_Eq _ -> True
236 MO_Ne _ -> True
237 MO_S_Ge _ -> True
238 MO_S_Le _ -> True
239 MO_S_Gt _ -> True
240 MO_S_Lt _ -> True
241 MO_U_Ge _ -> True
242 MO_U_Le _ -> True
243 MO_U_Gt _ -> True
244 MO_U_Lt _ -> True
245 MO_F_Eq {} -> True
246 MO_F_Ne {} -> True
247 MO_F_Ge {} -> True
248 MO_F_Le {} -> True
249 MO_F_Gt {} -> True
250 MO_F_Lt {} -> True
251 _other -> False
252
253 -- -----------------------------------------------------------------------------
254 -- Inverting conditions
255
256 -- Sometimes it's useful to be able to invert the sense of a
257 -- condition. Not all conditional tests are invertible: in
258 -- particular, floating point conditionals cannot be inverted, because
259 -- there exist floating-point values which return False for both senses
260 -- of a condition (eg. !(NaN > NaN) && !(NaN /<= NaN)).
261
262 maybeInvertComparison :: MachOp -> Maybe MachOp
263 maybeInvertComparison op
264 = case op of -- None of these Just cases include floating point
265 MO_Eq r -> Just (MO_Ne r)
266 MO_Ne r -> Just (MO_Eq r)
267 MO_U_Lt r -> Just (MO_U_Ge r)
268 MO_U_Gt r -> Just (MO_U_Le r)
269 MO_U_Le r -> Just (MO_U_Gt r)
270 MO_U_Ge r -> Just (MO_U_Lt r)
271 MO_S_Lt r -> Just (MO_S_Ge r)
272 MO_S_Gt r -> Just (MO_S_Le r)
273 MO_S_Le r -> Just (MO_S_Gt r)
274 MO_S_Ge r -> Just (MO_S_Lt r)
275 MO_F_Eq r -> Just (MO_F_Ne r)
276 MO_F_Ne r -> Just (MO_F_Eq r)
277 MO_F_Ge r -> Just (MO_F_Le r)
278 MO_F_Le r -> Just (MO_F_Ge r)
279 MO_F_Gt r -> Just (MO_F_Lt r)
280 MO_F_Lt r -> Just (MO_F_Gt r)
281 _other -> Nothing
282
283 -- ----------------------------------------------------------------------------
284 -- machOpResultType
285
286 {- |
287 Returns the MachRep of the result of a MachOp.
288 -}
289 machOpResultType :: MachOp -> [CmmType] -> CmmType
290 machOpResultType mop tys =
291 case mop of
292 MO_Add {} -> ty1 -- Preserve GC-ptr-hood
293 MO_Sub {} -> ty1 -- of first arg
294 MO_Mul r -> cmmBits r
295 MO_S_MulMayOflo r -> cmmBits r
296 MO_S_Quot r -> cmmBits r
297 MO_S_Rem r -> cmmBits r
298 MO_S_Neg r -> cmmBits r
299 MO_U_MulMayOflo r -> cmmBits r
300 MO_U_Quot r -> cmmBits r
301 MO_U_Rem r -> cmmBits r
302
303 MO_Eq {} -> comparisonResultRep
304 MO_Ne {} -> comparisonResultRep
305 MO_S_Ge {} -> comparisonResultRep
306 MO_S_Le {} -> comparisonResultRep
307 MO_S_Gt {} -> comparisonResultRep
308 MO_S_Lt {} -> comparisonResultRep
309
310 MO_U_Ge {} -> comparisonResultRep
311 MO_U_Le {} -> comparisonResultRep
312 MO_U_Gt {} -> comparisonResultRep
313 MO_U_Lt {} -> comparisonResultRep
314
315 MO_F_Add r -> cmmFloat r
316 MO_F_Sub r -> cmmFloat r
317 MO_F_Mul r -> cmmFloat r
318 MO_F_Quot r -> cmmFloat r
319 MO_F_Neg r -> cmmFloat r
320 MO_F_Eq {} -> comparisonResultRep
321 MO_F_Ne {} -> comparisonResultRep
322 MO_F_Ge {} -> comparisonResultRep
323 MO_F_Le {} -> comparisonResultRep
324 MO_F_Gt {} -> comparisonResultRep
325 MO_F_Lt {} -> comparisonResultRep
326
327 MO_And {} -> ty1 -- Used for pointer masking
328 MO_Or {} -> ty1
329 MO_Xor {} -> ty1
330 MO_Not r -> cmmBits r
331 MO_Shl r -> cmmBits r
332 MO_U_Shr r -> cmmBits r
333 MO_S_Shr r -> cmmBits r
334
335 MO_SS_Conv _ to -> cmmBits to
336 MO_UU_Conv _ to -> cmmBits to
337 MO_FS_Conv _ to -> cmmBits to
338 MO_SF_Conv _ to -> cmmFloat to
339 MO_FF_Conv _ to -> cmmFloat to
340 where
341 (ty1:_) = tys
342
343 comparisonResultRep :: CmmType
344 comparisonResultRep = bWord -- is it?
345
346
347 -- -----------------------------------------------------------------------------
348 -- machOpArgReps
349
350 -- | This function is used for debugging only: we can check whether an
351 -- application of a MachOp is "type-correct" by checking that the MachReps of
352 -- its arguments are the same as the MachOp expects. This is used when
353 -- linting a CmmExpr.
354
355 machOpArgReps :: MachOp -> [Width]
356 machOpArgReps op =
357 case op of
358 MO_Add r -> [r,r]
359 MO_Sub r -> [r,r]
360 MO_Eq r -> [r,r]
361 MO_Ne r -> [r,r]
362 MO_Mul r -> [r,r]
363 MO_S_MulMayOflo r -> [r,r]
364 MO_S_Quot r -> [r,r]
365 MO_S_Rem r -> [r,r]
366 MO_S_Neg r -> [r]
367 MO_U_MulMayOflo r -> [r,r]
368 MO_U_Quot r -> [r,r]
369 MO_U_Rem r -> [r,r]
370
371 MO_S_Ge r -> [r,r]
372 MO_S_Le r -> [r,r]
373 MO_S_Gt r -> [r,r]
374 MO_S_Lt r -> [r,r]
375
376 MO_U_Ge r -> [r,r]
377 MO_U_Le r -> [r,r]
378 MO_U_Gt r -> [r,r]
379 MO_U_Lt r -> [r,r]
380
381 MO_F_Add r -> [r,r]
382 MO_F_Sub r -> [r,r]
383 MO_F_Mul r -> [r,r]
384 MO_F_Quot r -> [r,r]
385 MO_F_Neg r -> [r]
386 MO_F_Eq r -> [r,r]
387 MO_F_Ne r -> [r,r]
388 MO_F_Ge r -> [r,r]
389 MO_F_Le r -> [r,r]
390 MO_F_Gt r -> [r,r]
391 MO_F_Lt r -> [r,r]
392
393 MO_And r -> [r,r]
394 MO_Or r -> [r,r]
395 MO_Xor r -> [r,r]
396 MO_Not r -> [r]
397 MO_Shl r -> [r,wordWidth]
398 MO_U_Shr r -> [r,wordWidth]
399 MO_S_Shr r -> [r,wordWidth]
400
401 MO_SS_Conv from _ -> [from]
402 MO_UU_Conv from _ -> [from]
403 MO_SF_Conv from _ -> [from]
404 MO_FS_Conv from _ -> [from]
405 MO_FF_Conv from _ -> [from]
406
407 -----------------------------------------------------------------------------
408 -- CallishMachOp
409 -----------------------------------------------------------------------------
410
411 -- CallishMachOps tend to be implemented by foreign calls in some backends,
412 -- so we separate them out. In Cmm, these can only occur in a
413 -- statement position, in contrast to an ordinary MachOp which can occur
414 -- anywhere in an expression.
415 data CallishMachOp
416 = MO_F64_Pwr
417 | MO_F64_Sin
418 | MO_F64_Cos
419 | MO_F64_Tan
420 | MO_F64_Sinh
421 | MO_F64_Cosh
422 | MO_F64_Tanh
423 | MO_F64_Asin
424 | MO_F64_Acos
425 | MO_F64_Atan
426 | MO_F64_Log
427 | MO_F64_Exp
428 | MO_F64_Sqrt
429 | MO_F32_Pwr
430 | MO_F32_Sin
431 | MO_F32_Cos
432 | MO_F32_Tan
433 | MO_F32_Sinh
434 | MO_F32_Cosh
435 | MO_F32_Tanh
436 | MO_F32_Asin
437 | MO_F32_Acos
438 | MO_F32_Atan
439 | MO_F32_Log
440 | MO_F32_Exp
441 | MO_F32_Sqrt
442 | MO_WriteBarrier
443 | MO_Touch -- Keep variables live (when using interior pointers)
444
445 -- Note that these three MachOps all take 1 extra parameter than the
446 -- standard C lib versions. The extra (last) parameter contains
447 -- alignment of the pointers. Used for optimisation in backends.
448 | MO_Memcpy
449 | MO_Memset
450 | MO_Memmove
451 deriving (Eq, Show)
452
453 pprCallishMachOp :: CallishMachOp -> SDoc
454 pprCallishMachOp mo = text (show mo)
455