4 , pprMachOp, isCommutableMachOp, isAssociativeMachOp
5 , isComparisonMachOp, machOpResultType
6 , machOpArgReps, maybeInvertComparison
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
24 #include "HsVersions.h"
29 -----------------------------------------------------------------------------
31 -----------------------------------------------------------------------------
36 It might suffice to keep just a width, without distinguishing between
37 floating and integer types. However, keeping the distinction will
38 help the native code generator to assign registers more easily.
43 Machine-level primops; ones which we can reasonably delegate to the
44 native code generators to handle. Basically contains C's primops
47 Nomenclature: all ops indicate width and signedness, where
48 appropriate. Widths: 8\/16\/32\/64 means the given size, obviously.
49 Nat means the operation works on STG word sized objects.
50 Signedness: S means signed, U means unsigned. For operations where
51 signedness is irrelevant or makes no difference (for example
52 integer add), the signedness component is omitted.
54 An exception: NatP is a ptr-typed native word. From the point of
55 view of the native code generators this distinction is irrelevant,
56 but the C code generator sometimes needs this info to emit the
61 -- Integer operations (insensitive to signed/unsigned)
66 | MO_Mul Width -- low word of multiply
68 -- Signed multiply/divide
69 | MO_S_MulMayOflo Width -- nonzero if signed multiply overflows
70 | MO_S_Quot Width -- signed / (same semantics as IntQuotOp)
71 | MO_S_Rem Width -- signed % (same semantics as IntRemOp)
72 | MO_S_Neg Width -- unary -
74 -- Unsigned multiply/divide
75 | MO_U_MulMayOflo Width -- nonzero if unsigned multiply overflows
76 | MO_U_Quot Width -- unsigned / (same semantics as WordQuotOp)
77 | MO_U_Rem Width -- unsigned % (same semantics as WordRemOp)
85 -- Unsigned comparisons
91 -- Floating point arithmetic
94 | MO_F_Neg Width -- unary -
98 -- Floating point comparison
106 -- Bitwise operations. Not all of these may be supported
107 -- at all sizes, and only integral Widths are valid.
113 | MO_U_Shr Width -- unsigned shift right
114 | MO_S_Shr Width -- signed shift right
116 -- Conversions. Some of these will be NOPs.
117 -- Floating-point conversions use the signed variant.
118 | MO_SF_Conv Width Width -- Signed int -> Float
119 | MO_FS_Conv Width Width -- Float -> Signed int
120 | MO_SS_Conv Width Width -- Signed int -> Signed int
121 | MO_UU_Conv Width Width -- unsigned int -> unsigned int
122 | MO_FF_Conv Width Width -- Float -> Float
125 pprMachOp :: MachOp -> SDoc
126 pprMachOp mo = text (show mo)
130 -- -----------------------------------------------------------------------------
131 -- Some common MachReps
133 -- A 'wordRep' is a machine word on the target architecture
134 -- Specifically, it is the size of an Int#, Word#, Addr#
135 -- and the unit of allocation on the stack and the heap
136 -- Any pointer is also guaranteed to be a wordRep.
138 mo_wordAdd, mo_wordSub, mo_wordEq, mo_wordNe,mo_wordMul, mo_wordSQuot
139 , mo_wordSRem, mo_wordSNeg, mo_wordUQuot, mo_wordURem
140 , mo_wordSGe, mo_wordSLe, mo_wordSGt, mo_wordSLt, mo_wordUGe
141 , mo_wordULe, mo_wordUGt, mo_wordULt
142 , mo_wordAnd, mo_wordOr, mo_wordXor, mo_wordNot, mo_wordShl, mo_wordSShr, mo_wordUShr
143 , mo_u_8To32, mo_s_8To32, mo_u_16To32, mo_s_16To32
144 , mo_u_8ToWord, mo_s_8ToWord, mo_u_16ToWord, mo_s_16ToWord, mo_u_32ToWord, mo_s_32ToWord
145 , mo_32To8, mo_32To16, mo_WordTo8, mo_WordTo16, mo_WordTo32
148 mo_wordAdd = MO_Add wordWidth
149 mo_wordSub = MO_Sub wordWidth
150 mo_wordEq = MO_Eq wordWidth
151 mo_wordNe = MO_Ne wordWidth
152 mo_wordMul = MO_Mul wordWidth
153 mo_wordSQuot = MO_S_Quot wordWidth
154 mo_wordSRem = MO_S_Rem wordWidth
155 mo_wordSNeg = MO_S_Neg wordWidth
156 mo_wordUQuot = MO_U_Quot wordWidth
157 mo_wordURem = MO_U_Rem wordWidth
159 mo_wordSGe = MO_S_Ge wordWidth
160 mo_wordSLe = MO_S_Le wordWidth
161 mo_wordSGt = MO_S_Gt wordWidth
162 mo_wordSLt = MO_S_Lt wordWidth
164 mo_wordUGe = MO_U_Ge wordWidth
165 mo_wordULe = MO_U_Le wordWidth
166 mo_wordUGt = MO_U_Gt wordWidth
167 mo_wordULt = MO_U_Lt wordWidth
169 mo_wordAnd = MO_And wordWidth
170 mo_wordOr = MO_Or wordWidth
171 mo_wordXor = MO_Xor wordWidth
172 mo_wordNot = MO_Not wordWidth
173 mo_wordShl = MO_Shl wordWidth
174 mo_wordSShr = MO_S_Shr wordWidth
175 mo_wordUShr = MO_U_Shr wordWidth
177 mo_u_8To32 = MO_UU_Conv W8 W32
178 mo_s_8To32 = MO_SS_Conv W8 W32
179 mo_u_16To32 = MO_UU_Conv W16 W32
180 mo_s_16To32 = MO_SS_Conv W16 W32
182 mo_u_8ToWord = MO_UU_Conv W8 wordWidth
183 mo_s_8ToWord = MO_SS_Conv W8 wordWidth
184 mo_u_16ToWord = MO_UU_Conv W16 wordWidth
185 mo_s_16ToWord = MO_SS_Conv W16 wordWidth
186 mo_s_32ToWord = MO_SS_Conv W32 wordWidth
187 mo_u_32ToWord = MO_UU_Conv W32 wordWidth
189 mo_WordTo8 = MO_UU_Conv wordWidth W8
190 mo_WordTo16 = MO_UU_Conv wordWidth W16
191 mo_WordTo32 = MO_UU_Conv wordWidth W32
193 mo_32To8 = MO_UU_Conv W32 W8
194 mo_32To16 = MO_UU_Conv W32 W16
197 -- ----------------------------------------------------------------------------
198 -- isCommutableMachOp
201 Returns 'True' if the MachOp has commutable arguments. This is used
202 in the platform-independent Cmm optimisations.
204 If in doubt, return 'False'. This generates worse code on the
205 native routes, but is otherwise harmless.
207 isCommutableMachOp :: MachOp -> Bool
208 isCommutableMachOp mop =
214 MO_S_MulMayOflo _ -> True
215 MO_U_MulMayOflo _ -> True
221 -- ----------------------------------------------------------------------------
222 -- isAssociativeMachOp
225 Returns 'True' if the MachOp is associative (i.e. @(x+y)+z == x+(y+z)@)
226 This is used in the platform-independent Cmm optimisations.
228 If in doubt, return 'False'. This generates worse code on the
229 native routes, but is otherwise harmless.
231 isAssociativeMachOp :: MachOp -> Bool
232 isAssociativeMachOp mop =
234 MO_Add {} -> True -- NB: does not include
235 MO_Mul {} -> True -- floatint point!
241 -- ----------------------------------------------------------------------------
242 -- isComparisonMachOp
245 Returns 'True' if the MachOp is a comparison.
247 If in doubt, return False. This generates worse code on the
248 native routes, but is otherwise harmless.
250 isComparisonMachOp :: MachOp -> Bool
251 isComparisonMachOp mop =
271 -- -----------------------------------------------------------------------------
272 -- Inverting conditions
274 -- Sometimes it's useful to be able to invert the sense of a
275 -- condition. Not all conditional tests are invertible: in
276 -- particular, floating point conditionals cannot be inverted, because
277 -- there exist floating-point values which return False for both senses
278 -- of a condition (eg. !(NaN > NaN) && !(NaN /<= NaN)).
280 maybeInvertComparison :: MachOp -> Maybe MachOp
281 maybeInvertComparison op
282 = case op of -- None of these Just cases include floating point
283 MO_Eq r -> Just (MO_Ne r)
284 MO_Ne r -> Just (MO_Eq r)
285 MO_U_Lt r -> Just (MO_U_Ge r)
286 MO_U_Gt r -> Just (MO_U_Le r)
287 MO_U_Le r -> Just (MO_U_Gt r)
288 MO_U_Ge r -> Just (MO_U_Lt r)
289 MO_S_Lt r -> Just (MO_S_Ge r)
290 MO_S_Gt r -> Just (MO_S_Le r)
291 MO_S_Le r -> Just (MO_S_Gt r)
292 MO_S_Ge r -> Just (MO_S_Lt r)
293 MO_F_Eq r -> Just (MO_F_Ne r)
294 MO_F_Ne r -> Just (MO_F_Eq r)
295 MO_F_Ge r -> Just (MO_F_Le r)
296 MO_F_Le r -> Just (MO_F_Ge r)
297 MO_F_Gt r -> Just (MO_F_Lt r)
298 MO_F_Lt r -> Just (MO_F_Gt r)
301 -- ----------------------------------------------------------------------------
305 Returns the MachRep of the result of a MachOp.
307 machOpResultType :: MachOp -> [CmmType] -> CmmType
308 machOpResultType mop tys =
310 MO_Add {} -> ty1 -- Preserve GC-ptr-hood
311 MO_Sub {} -> ty1 -- of first arg
312 MO_Mul r -> cmmBits r
313 MO_S_MulMayOflo r -> cmmBits r
314 MO_S_Quot r -> cmmBits r
315 MO_S_Rem r -> cmmBits r
316 MO_S_Neg r -> cmmBits r
317 MO_U_MulMayOflo r -> cmmBits r
318 MO_U_Quot r -> cmmBits r
319 MO_U_Rem r -> cmmBits r
321 MO_Eq {} -> comparisonResultRep
322 MO_Ne {} -> comparisonResultRep
323 MO_S_Ge {} -> comparisonResultRep
324 MO_S_Le {} -> comparisonResultRep
325 MO_S_Gt {} -> comparisonResultRep
326 MO_S_Lt {} -> comparisonResultRep
328 MO_U_Ge {} -> comparisonResultRep
329 MO_U_Le {} -> comparisonResultRep
330 MO_U_Gt {} -> comparisonResultRep
331 MO_U_Lt {} -> comparisonResultRep
333 MO_F_Add r -> cmmFloat r
334 MO_F_Sub r -> cmmFloat r
335 MO_F_Mul r -> cmmFloat r
336 MO_F_Quot r -> cmmFloat r
337 MO_F_Neg r -> cmmFloat r
338 MO_F_Eq {} -> comparisonResultRep
339 MO_F_Ne {} -> comparisonResultRep
340 MO_F_Ge {} -> comparisonResultRep
341 MO_F_Le {} -> comparisonResultRep
342 MO_F_Gt {} -> comparisonResultRep
343 MO_F_Lt {} -> comparisonResultRep
345 MO_And {} -> ty1 -- Used for pointer masking
348 MO_Not r -> cmmBits r
349 MO_Shl r -> cmmBits r
350 MO_U_Shr r -> cmmBits r
351 MO_S_Shr r -> cmmBits r
353 MO_SS_Conv _ to -> cmmBits to
354 MO_UU_Conv _ to -> cmmBits to
355 MO_FS_Conv _ to -> cmmBits to
356 MO_SF_Conv _ to -> cmmFloat to
357 MO_FF_Conv _ to -> cmmFloat to
361 comparisonResultRep :: CmmType
362 comparisonResultRep = bWord -- is it?
365 -- -----------------------------------------------------------------------------
368 -- | This function is used for debugging only: we can check whether an
369 -- application of a MachOp is "type-correct" by checking that the MachReps of
370 -- its arguments are the same as the MachOp expects. This is used when
371 -- linting a CmmExpr.
373 machOpArgReps :: MachOp -> [Width]
381 MO_S_MulMayOflo r -> [r,r]
385 MO_U_MulMayOflo r -> [r,r]
415 MO_Shl r -> [r,wordWidth]
416 MO_U_Shr r -> [r,wordWidth]
417 MO_S_Shr r -> [r,wordWidth]
419 MO_SS_Conv from _ -> [from]
420 MO_UU_Conv from _ -> [from]
421 MO_SF_Conv from _ -> [from]
422 MO_FS_Conv from _ -> [from]
423 MO_FF_Conv from _ -> [from]
425 -----------------------------------------------------------------------------
427 -----------------------------------------------------------------------------
429 -- CallishMachOps tend to be implemented by foreign calls in some backends,
430 -- so we separate them out. In Cmm, these can only occur in a
431 -- statement position, in contrast to an ordinary MachOp which can occur
432 -- anywhere in an expression.
461 | MO_Touch -- Keep variables live (when using interior pointers)
464 pprCallishMachOp :: CallishMachOp -> SDoc
465 pprCallishMachOp mo = text (show mo)