1 -----------------------------------------------------------------------------
3 -- (c) The University of Glasgow 2002-2004
5 -- Low-level machine operations, used in the Cmm datatype.
7 -----------------------------------------------------------------------------
25 maybeInvertComparison,
82 #include "HsVersions.h"
87 -- -----------------------------------------------------------------------------
91 A MachRep is the "representation" of a value in Cmm. It is used for
92 resource allocation: eg. which kind of register a value should be
95 The primary requirement is that there exists a function
97 cmmExprRep :: CmmExpr -> MachRep
101 - a register has an implicit MachRep
102 - a literal has an implicit MachRep
103 - an operation (MachOp) has an implicit result MachRep
105 It also means that we can check that the arguments to a MachOp have
106 the correct MachRep, i.e. we can do a kind of lint-style type checking
118 | F80 -- extended double-precision, used in x86 native codegen only.
119 deriving (Eq, Ord, Show)
121 mrStr I8 = SLIT("I8")
122 mrStr I16 = SLIT("I16")
123 mrStr I32 = SLIT("I32")
124 mrStr I64 = SLIT("I64")
125 mrStr I128 = SLIT("I128")
126 mrStr F32 = SLIT("F32")
127 mrStr F64 = SLIT("F64")
128 mrStr F80 = SLIT("F80")
130 instance Outputable MachRep where
131 ppr rep = ptext (mrStr rep)
134 Implementation notes:
136 It might suffice to keep just a width, without distinguishing between
137 floating and integer types. However, keeping the distinction will
138 help the native code generator to assign registers more easily.
142 Should a MachRep include a signed vs. unsigned distinction?
144 This is very much like a "hint" in C-- terminology: it isn't necessary
145 in order to generate correct code, but it might be useful in that the
146 compiler can generate better code if it has access to higher-level
147 hints about data. This is important at call boundaries, because the
148 definition of a function is not visible at all of its call sites, so
149 the compiler cannot infer the hints.
151 Here in Cmm, we're taking a slightly different approach. We include
152 the int vs. float hint in the MachRep, because (a) the majority of
153 platforms have a strong distinction between float and int registers,
154 and (b) we don't want to do any heavyweight hint-inference in the
155 native code backend in order to get good code. We're treating the
156 hint more like a type: our Cmm is always completely consistent with
157 respect to hints. All coercions between float and int are explicit.
159 What about the signed vs. unsigned hint? This information might be
160 useful if we want to keep sub-word-sized values in word-size
161 registers, which we must do if we only have word-sized registers.
163 On such a system, there are two straightforward conventions for
164 representing sub-word-sized values:
166 (a) Leave the upper bits undefined. Comparison operations must
167 sign- or zero-extend both operands before comparing them,
168 depending on whether the comparison is signed or unsigned.
170 (b) Always keep the values sign- or zero-extended as appropriate.
171 Arithmetic operations must narrow the result to the appropriate
174 A clever compiler might not use either (a) or (b) exclusively, instead
175 it would attempt to minimize the coercions by analysis: the same kind
176 of analysis that propagates hints around. In Cmm we don't want to
177 have to do this, so we plump for having richer types and keeping the
178 type information consistent.
180 If signed/unsigned hints are missing from MachRep, then the only
181 choice we have is (a), because we don't know whether the result of an
182 operation should be sign- or zero-extended.
184 Many architectures have extending load operations, which work well
185 with (b). To make use of them with (a), you need to know whether the
186 value is going to be sign- or zero-extended by an enclosing comparison
187 (for example), which involves knowing above the context. This is
188 doable but more complex.
190 Further complicating the issue is foreign calls: a foreign calling
191 convention can specify that signed 8-bit quantities are passed as
192 sign-extended 32 bit quantities, for example (this is the case on the
193 PowerPC). So we *do* need sign information on foreign call arguments.
195 Pros for adding signed vs. unsigned to MachRep:
197 - It would let us use convention (b) above, and get easier
198 code generation for extending loads.
200 - Less information required on foreign calls.
202 - MachOp type would be simpler
208 - What is the MachRep for a VanillaReg? Currently it is
209 always wordRep, but now we have to decide whether it is
210 signed or unsigned. The same VanillaReg can thus have
211 different MachReps in different parts of the program.
213 - Extra coercions cluttering up expressions.
215 Currently for GHC, the foreign call point is moot, because we do our
216 own promotion of sub-word-sized values to word-sized values. The Int8
217 type is represnted by an Int# which is kept sign-extended at all times
218 (this is slightly naughty, because we're making assumptions about the
219 C calling convention rather early on in the compiler). However, given
220 this, the cons outweigh the pros.
225 machRepBitWidth :: MachRep -> Int
226 machRepBitWidth I8 = 8
227 machRepBitWidth I16 = 16
228 machRepBitWidth I32 = 32
229 machRepBitWidth I64 = 64
230 machRepBitWidth I128 = 128
231 machRepBitWidth F32 = 32
232 machRepBitWidth F64 = 64
233 machRepBitWidth F80 = 80
235 machRepByteWidth :: MachRep -> Int
236 machRepByteWidth I8 = 1
237 machRepByteWidth I16 = 2
238 machRepByteWidth I32 = 4
239 machRepByteWidth I64 = 8
240 machRepByteWidth I128 = 16
241 machRepByteWidth F32 = 4
242 machRepByteWidth F64 = 8
243 machRepByteWidth F80 = 10
245 -- log_2 of the width in bytes, useful for generating shifts.
246 machRepLogWidth :: MachRep -> Int
247 machRepLogWidth I8 = 0
248 machRepLogWidth I16 = 1
249 machRepLogWidth I32 = 2
250 machRepLogWidth I64 = 3
251 machRepLogWidth I128 = 4
252 machRepLogWidth F32 = 2
253 machRepLogWidth F64 = 3
254 machRepLogWidth F80 = panic "machRepLogWidth: F80"
256 isFloatingRep :: MachRep -> Bool
257 isFloatingRep F32 = True
258 isFloatingRep F64 = True
259 isFloatingRep F80 = True
260 isFloatingRep _ = False
262 -- -----------------------------------------------------------------------------
266 A hint gives a little more information about a data value. Hints are
267 used on the arguments to a foreign call, where the code generator needs
268 to know some extra information on top of the MachRep of each argument in
269 order to generate a correct call.
279 mhStr NoHint = SLIT("NoHint")
280 mhStr PtrHint = SLIT("PtrHint")
281 mhStr SignedHint = SLIT("SignedHint")
282 mhStr FloatHint = SLIT("FloatHint")
284 instance Outputable MachHint where
285 ppr hint = ptext (mhStr hint)
287 -- -----------------------------------------------------------------------------
291 Machine-level primops; ones which we can reasonably delegate to the
292 native code generators to handle. Basically contains C's primops
295 Nomenclature: all ops indicate width and signedness, where
296 appropriate. Widths: 8\/16\/32\/64 means the given size, obviously.
297 Nat means the operation works on STG word sized objects.
298 Signedness: S means signed, U means unsigned. For operations where
299 signedness is irrelevant or makes no difference (for example
300 integer add), the signedness component is omitted.
302 An exception: NatP is a ptr-typed native word. From the point of
303 view of the native code generators this distinction is irrelevant,
304 but the C code generator sometimes needs this info to emit the
310 -- Integer operations
315 | MO_Mul MachRep -- low word of multiply
316 | MO_S_MulMayOflo MachRep -- nonzero if signed multiply overflows
317 | MO_S_Quot MachRep -- signed / (same semantics as IntQuotOp)
318 | MO_S_Rem MachRep -- signed % (same semantics as IntRemOp)
319 | MO_S_Neg MachRep -- unary -
320 | MO_U_MulMayOflo MachRep -- nonzero if unsigned multiply overflows
321 | MO_U_Quot MachRep -- unsigned / (same semantics as WordQuotOp)
322 | MO_U_Rem MachRep -- unsigned % (same semantics as WordRemOp)
324 -- Signed comparisons (floating-point comparisons also use these)
330 -- Unsigned comparisons
336 -- Bitwise operations. Not all of these may be supported at all sizes,
337 -- and only integral MachReps are valid.
343 | MO_U_Shr MachRep -- unsigned shift right
344 | MO_S_Shr MachRep -- signed shift right
346 -- Conversions. Some of these will be NOPs.
347 -- Floating-point conversions use the signed variant.
348 | MO_S_Conv MachRep{-from-} MachRep{-to-} -- signed conversion
349 | MO_U_Conv MachRep{-from-} MachRep{-to-} -- unsigned conversion
353 pprMachOp :: MachOp -> SDoc
354 pprMachOp mo = text (show mo)
357 -- These MachOps tend to be implemented by foreign calls in some backends,
358 -- so we separate them out. In Cmm, these can only occur in a
359 -- statement position, in contrast to an ordinary MachOp which can occur
360 -- anywhere in an expression.
391 pprCallishMachOp :: CallishMachOp -> SDoc
392 pprCallishMachOp mo = text (show mo)
394 -- -----------------------------------------------------------------------------
395 -- Some common MachReps
397 -- A 'wordRep' is a machine word on the target architecture
398 -- Specifically, it is the size of an Int#, Word#, Addr#
399 -- and the unit of allocation on the stack and the heap
400 -- Any pointer is also guaranteed to be a wordRep.
402 wordRep | wORD_SIZE == 4 = I32
403 | wORD_SIZE == 8 = I64
404 | otherwise = panic "MachOp.wordRep: Unknown word size"
406 halfWordRep | wORD_SIZE == 4 = I16
407 | wORD_SIZE == 8 = I32
408 | otherwise = panic "MachOp.halfWordRep: Unknown word size"
410 mo_wordAdd = MO_Add wordRep
411 mo_wordSub = MO_Sub wordRep
412 mo_wordEq = MO_Eq wordRep
413 mo_wordNe = MO_Ne wordRep
414 mo_wordMul = MO_Mul wordRep
415 mo_wordSQuot = MO_S_Quot wordRep
416 mo_wordSRem = MO_S_Rem wordRep
417 mo_wordSNeg = MO_S_Neg wordRep
418 mo_wordUQuot = MO_U_Quot wordRep
419 mo_wordURem = MO_U_Rem wordRep
421 mo_wordSGe = MO_S_Ge wordRep
422 mo_wordSLe = MO_S_Le wordRep
423 mo_wordSGt = MO_S_Gt wordRep
424 mo_wordSLt = MO_S_Lt wordRep
426 mo_wordUGe = MO_U_Ge wordRep
427 mo_wordULe = MO_U_Le wordRep
428 mo_wordUGt = MO_U_Gt wordRep
429 mo_wordULt = MO_U_Lt wordRep
431 mo_wordAnd = MO_And wordRep
432 mo_wordOr = MO_Or wordRep
433 mo_wordXor = MO_Xor wordRep
434 mo_wordNot = MO_Not wordRep
435 mo_wordShl = MO_Shl wordRep
436 mo_wordSShr = MO_S_Shr wordRep
437 mo_wordUShr = MO_U_Shr wordRep
439 mo_u_8To32 = MO_U_Conv I8 I32
440 mo_s_8To32 = MO_S_Conv I8 I32
441 mo_u_16To32 = MO_U_Conv I16 I32
442 mo_s_16To32 = MO_S_Conv I16 I32
444 mo_u_8ToWord = MO_U_Conv I8 wordRep
445 mo_s_8ToWord = MO_S_Conv I8 wordRep
446 mo_u_16ToWord = MO_U_Conv I16 wordRep
447 mo_s_16ToWord = MO_S_Conv I16 wordRep
448 mo_s_32ToWord = MO_S_Conv I32 wordRep
449 mo_u_32ToWord = MO_U_Conv I32 wordRep
451 mo_WordTo8 = MO_U_Conv wordRep I8
452 mo_WordTo16 = MO_U_Conv wordRep I16
453 mo_WordTo32 = MO_U_Conv wordRep I32
455 mo_32To8 = MO_U_Conv I32 I8
456 mo_32To16 = MO_U_Conv I32 I16
458 -- cIntRep is the MachRep for a C-language 'int'
461 #elif SIZEOF_INT == 8
467 #elif SIZEOF_LONG == 8
471 -- ----------------------------------------------------------------------------
472 -- isCommutableMachOp
475 Returns 'True' if the MachOp has commutable arguments. This is used
476 in the platform-independent Cmm optimisations.
478 If in doubt, return 'False'. This generates worse code on the
479 native routes, but is otherwise harmless.
481 isCommutableMachOp :: MachOp -> Bool
482 isCommutableMachOp mop =
488 MO_S_MulMayOflo _ -> True
489 MO_U_MulMayOflo _ -> True
495 -- ----------------------------------------------------------------------------
496 -- isAssociativeMachOp
499 Returns 'True' if the MachOp is associative (i.e. @(x+y)+z == x+(y+z)@)
500 This is used in the platform-independent Cmm optimisations.
502 If in doubt, return 'False'. This generates worse code on the
503 native routes, but is otherwise harmless.
505 isAssociativeMachOp :: MachOp -> Bool
506 isAssociativeMachOp mop =
508 MO_Add r -> not (isFloatingRep r)
509 MO_Mul r -> not (isFloatingRep r)
515 -- ----------------------------------------------------------------------------
516 -- isComparisonMachOp
519 Returns 'True' if the MachOp is a comparison.
521 If in doubt, return False. This generates worse code on the
522 native routes, but is otherwise harmless.
524 isComparisonMachOp :: MachOp -> Bool
525 isComparisonMachOp mop =
539 -- -----------------------------------------------------------------------------
540 -- Inverting conditions
542 -- Sometimes it's useful to be able to invert the sense of a
543 -- condition. Not all conditional tests are invertible: in
544 -- particular, floating point conditionals cannot be inverted, because
545 -- there exist floating-point values which return False for both senses
546 -- of a condition (eg. !(NaN > NaN) && !(NaN /<= NaN)).
548 maybeInvertComparison :: MachOp -> Maybe MachOp
549 maybeInvertComparison op
551 MO_Eq r | not (isFloatingRep r) -> Just (MO_Ne r)
552 MO_Ne r | not (isFloatingRep r) -> Just (MO_Eq r)
553 MO_U_Lt r | not (isFloatingRep r) -> Just (MO_U_Ge r)
554 MO_U_Gt r | not (isFloatingRep r) -> Just (MO_U_Le r)
555 MO_U_Le r | not (isFloatingRep r) -> Just (MO_U_Gt r)
556 MO_U_Ge r | not (isFloatingRep r) -> Just (MO_U_Lt r)
557 MO_S_Lt r | not (isFloatingRep r) -> Just (MO_S_Ge r)
558 MO_S_Gt r | not (isFloatingRep r) -> Just (MO_S_Le r)
559 MO_S_Le r | not (isFloatingRep r) -> Just (MO_S_Gt r)
560 MO_S_Ge r | not (isFloatingRep r) -> Just (MO_S_Lt r)
563 -- ----------------------------------------------------------------------------
567 Returns the MachRep of the result of a MachOp.
569 resultRepOfMachOp :: MachOp -> MachRep
570 resultRepOfMachOp mop =
574 MO_Eq r -> comparisonResultRep
575 MO_Ne r -> comparisonResultRep
577 MO_S_MulMayOflo r -> r
581 MO_U_MulMayOflo r -> r
585 MO_S_Ge r -> comparisonResultRep
586 MO_S_Le r -> comparisonResultRep
587 MO_S_Gt r -> comparisonResultRep
588 MO_S_Lt r -> comparisonResultRep
590 MO_U_Ge r -> comparisonResultRep
591 MO_U_Le r -> comparisonResultRep
592 MO_U_Gt r -> comparisonResultRep
593 MO_U_Lt r -> comparisonResultRep
603 MO_S_Conv from to -> to
604 MO_U_Conv from to -> to
607 comparisonResultRep = wordRep -- is it?
610 -- -----------------------------------------------------------------------------
613 -- | This function is used for debugging only: we can check whether an
614 -- application of a MachOp is "type-correct" by checking that the MachReps of
615 -- its arguments are the same as the MachOp expects. This is used when
616 -- linting a CmmExpr.
618 machOpArgReps :: MachOp -> [MachRep]
626 MO_S_MulMayOflo r -> [r,r]
630 MO_U_MulMayOflo r -> [r,r]
648 MO_Shl r -> [r,wordRep]
649 MO_U_Shr r -> [r,wordRep]
650 MO_S_Shr r -> [r,wordRep]
652 MO_S_Conv from to -> [from]
653 MO_U_Conv from to -> [from]