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