Add Cmm support for 512-bit-wide values.
[ghc.git] / compiler / cmm / CmmType.hs
1
2 module CmmType
3 ( CmmType -- Abstract
4 , b8, b16, b32, b64, b128, b256, b512, f32, f64, bWord, bHalfWord, gcWord
5 , cInt, cLong
6 , cmmBits, cmmFloat
7 , typeWidth, cmmEqType, cmmEqType_ignoring_ptrhood
8 , isFloatType, isGcPtrType, isWord32, isWord64, isFloat64, isFloat32
9
10 , Width(..)
11 , widthInBits, widthInBytes, widthInLog, widthFromBytes
12 , wordWidth, halfWordWidth, cIntWidth, cLongWidth
13 , halfWordMask
14 , narrowU, narrowS
15 , rEP_CostCentreStack_mem_alloc
16 , rEP_CostCentreStack_scc_count
17 , rEP_StgEntCounter_allocs
18 , rEP_StgEntCounter_allocd
19
20 , ForeignHint(..)
21
22 , Length
23 , vec, vec2, vec4, vec8, vec16
24 , vec2f64, vec2b64, vec4f32, vec4b32, vec8b16, vec16b8
25 , cmmVec
26 , vecLength, vecElemType
27 , isVecType
28 )
29 where
30
31 #include "HsVersions.h"
32
33 import DynFlags
34 import FastString
35 import Outputable
36
37 import Data.Word
38 import Data.Int
39
40 -----------------------------------------------------------------------------
41 -- CmmType
42 -----------------------------------------------------------------------------
43
44 -- NOTE: CmmType is an abstract type, not exported from this
45 -- module so you can easily change its representation
46 --
47 -- However Width is exported in a concrete way,
48 -- and is used extensively in pattern-matching
49
50 data CmmType -- The important one!
51 = CmmType CmmCat Width
52
53 data CmmCat -- "Category" (not exported)
54 = GcPtrCat -- GC pointer
55 | BitsCat -- Non-pointer
56 | FloatCat -- Float
57 | VecCat Length CmmCat -- Vector
58 deriving( Eq )
59 -- See Note [Signed vs unsigned] at the end
60
61 instance Outputable CmmType where
62 ppr (CmmType cat wid) = ppr cat <> ppr (widthInBits wid)
63
64 instance Outputable CmmCat where
65 ppr FloatCat = ptext $ sLit("F")
66 ppr GcPtrCat = ptext $ sLit("P")
67 ppr BitsCat = ptext $ sLit("I")
68 ppr (VecCat n cat) = ppr cat <> text "x" <> ppr n <> text "V"
69
70 -- Why is CmmType stratified? For native code generation,
71 -- most of the time you just want to know what sort of register
72 -- to put the thing in, and for this you need to know how
73 -- many bits thing has and whether it goes in a floating-point
74 -- register. By contrast, the distinction between GcPtr and
75 -- GcNonPtr is of interest to only a few parts of the code generator.
76
77 -------- Equality on CmmType --------------
78 -- CmmType is *not* an instance of Eq; sometimes we care about the
79 -- Gc/NonGc distinction, and sometimes we don't
80 -- So we use an explicit function to force you to think about it
81 cmmEqType :: CmmType -> CmmType -> Bool -- Exact equality
82 cmmEqType (CmmType c1 w1) (CmmType c2 w2) = c1==c2 && w1==w2
83
84 cmmEqType_ignoring_ptrhood :: CmmType -> CmmType -> Bool
85 -- This equality is temporary; used in CmmLint
86 -- but the RTS files are not yet well-typed wrt pointers
87 cmmEqType_ignoring_ptrhood (CmmType c1 w1) (CmmType c2 w2)
88 = c1 `weak_eq` c2 && w1==w2
89 where
90 weak_eq :: CmmCat -> CmmCat -> Bool
91 FloatCat `weak_eq` FloatCat = True
92 FloatCat `weak_eq` _other = False
93 _other `weak_eq` FloatCat = False
94 (VecCat l1 cat1) `weak_eq` (VecCat l2 cat2) = l1 == l2
95 && cat1 `weak_eq` cat2
96 (VecCat {}) `weak_eq` _other = False
97 _other `weak_eq` (VecCat {}) = False
98 _word1 `weak_eq` _word2 = True -- Ignores GcPtr
99
100 --- Simple operations on CmmType -----
101 typeWidth :: CmmType -> Width
102 typeWidth (CmmType _ w) = w
103
104 cmmBits, cmmFloat :: Width -> CmmType
105 cmmBits = CmmType BitsCat
106 cmmFloat = CmmType FloatCat
107
108 -------- Common CmmTypes ------------
109 -- Floats and words of specific widths
110 b8, b16, b32, b64, b128, b256, b512, f32, f64 :: CmmType
111 b8 = cmmBits W8
112 b16 = cmmBits W16
113 b32 = cmmBits W32
114 b64 = cmmBits W64
115 b128 = cmmBits W128
116 b256 = cmmBits W256
117 b512 = cmmBits W512
118 f32 = cmmFloat W32
119 f64 = cmmFloat W64
120
121 -- CmmTypes of native word widths
122 bWord :: DynFlags -> CmmType
123 bWord dflags = cmmBits (wordWidth dflags)
124
125 bHalfWord :: DynFlags -> CmmType
126 bHalfWord dflags = cmmBits (halfWordWidth dflags)
127
128 gcWord :: DynFlags -> CmmType
129 gcWord dflags = CmmType GcPtrCat (wordWidth dflags)
130
131 cInt, cLong :: DynFlags -> CmmType
132 cInt dflags = cmmBits (cIntWidth dflags)
133 cLong dflags = cmmBits (cLongWidth dflags)
134
135
136 ------------ Predicates ----------------
137 isFloatType, isGcPtrType :: CmmType -> Bool
138 isFloatType (CmmType FloatCat _) = True
139 isFloatType _other = False
140
141 isGcPtrType (CmmType GcPtrCat _) = True
142 isGcPtrType _other = False
143
144 isWord32, isWord64, isFloat32, isFloat64 :: CmmType -> Bool
145 -- isWord64 is true of 64-bit non-floats (both gc-ptrs and otherwise)
146 -- isFloat32 and 64 are obvious
147
148 isWord64 (CmmType BitsCat W64) = True
149 isWord64 (CmmType GcPtrCat W64) = True
150 isWord64 _other = False
151
152 isWord32 (CmmType BitsCat W32) = True
153 isWord32 (CmmType GcPtrCat W32) = True
154 isWord32 _other = False
155
156 isFloat32 (CmmType FloatCat W32) = True
157 isFloat32 _other = False
158
159 isFloat64 (CmmType FloatCat W64) = True
160 isFloat64 _other = False
161
162 -----------------------------------------------------------------------------
163 -- Width
164 -----------------------------------------------------------------------------
165
166 data Width = W8 | W16 | W32 | W64
167 | W80 -- Extended double-precision float,
168 -- used in x86 native codegen only.
169 -- (we use Ord, so it'd better be in this order)
170 | W128
171 | W256
172 | W512
173 deriving (Eq, Ord, Show)
174
175 instance Outputable Width where
176 ppr rep = ptext (mrStr rep)
177
178 mrStr :: Width -> LitString
179 mrStr W8 = sLit("W8")
180 mrStr W16 = sLit("W16")
181 mrStr W32 = sLit("W32")
182 mrStr W64 = sLit("W64")
183 mrStr W128 = sLit("W128")
184 mrStr W256 = sLit("W256")
185 mrStr W512 = sLit("W512")
186 mrStr W80 = sLit("W80")
187
188
189 -------- Common Widths ------------
190 wordWidth :: DynFlags -> Width
191 wordWidth dflags
192 | wORD_SIZE dflags == 4 = W32
193 | wORD_SIZE dflags == 8 = W64
194 | otherwise = panic "MachOp.wordRep: Unknown word size"
195
196 halfWordWidth :: DynFlags -> Width
197 halfWordWidth dflags
198 | wORD_SIZE dflags == 4 = W16
199 | wORD_SIZE dflags == 8 = W32
200 | otherwise = panic "MachOp.halfWordRep: Unknown word size"
201
202 halfWordMask :: DynFlags -> Integer
203 halfWordMask dflags
204 | wORD_SIZE dflags == 4 = 0xFFFF
205 | wORD_SIZE dflags == 8 = 0xFFFFFFFF
206 | otherwise = panic "MachOp.halfWordMask: Unknown word size"
207
208 -- cIntRep is the Width for a C-language 'int'
209 cIntWidth, cLongWidth :: DynFlags -> Width
210 cIntWidth dflags = case cINT_SIZE dflags of
211 4 -> W32
212 8 -> W64
213 s -> panic ("cIntWidth: Unknown cINT_SIZE: " ++ show s)
214 cLongWidth dflags = case cLONG_SIZE dflags of
215 4 -> W32
216 8 -> W64
217 s -> panic ("cIntWidth: Unknown cLONG_SIZE: " ++ show s)
218
219 widthInBits :: Width -> Int
220 widthInBits W8 = 8
221 widthInBits W16 = 16
222 widthInBits W32 = 32
223 widthInBits W64 = 64
224 widthInBits W128 = 128
225 widthInBits W256 = 256
226 widthInBits W512 = 512
227 widthInBits W80 = 80
228
229 widthInBytes :: Width -> Int
230 widthInBytes W8 = 1
231 widthInBytes W16 = 2
232 widthInBytes W32 = 4
233 widthInBytes W64 = 8
234 widthInBytes W128 = 16
235 widthInBytes W256 = 32
236 widthInBytes W512 = 64
237 widthInBytes W80 = 10
238
239 widthFromBytes :: Int -> Width
240 widthFromBytes 1 = W8
241 widthFromBytes 2 = W16
242 widthFromBytes 4 = W32
243 widthFromBytes 8 = W64
244 widthFromBytes 16 = W128
245 widthFromBytes 32 = W256
246 widthFromBytes 64 = W512
247 widthFromBytes 10 = W80
248 widthFromBytes n = pprPanic "no width for given number of bytes" (ppr n)
249
250 -- log_2 of the width in bytes, useful for generating shifts.
251 widthInLog :: Width -> Int
252 widthInLog W8 = 0
253 widthInLog W16 = 1
254 widthInLog W32 = 2
255 widthInLog W64 = 3
256 widthInLog W128 = 4
257 widthInLog W256 = 5
258 widthInLog W512 = 6
259 widthInLog W80 = panic "widthInLog: F80"
260
261 -- widening / narrowing
262
263 narrowU :: Width -> Integer -> Integer
264 narrowU W8 x = fromIntegral (fromIntegral x :: Word8)
265 narrowU W16 x = fromIntegral (fromIntegral x :: Word16)
266 narrowU W32 x = fromIntegral (fromIntegral x :: Word32)
267 narrowU W64 x = fromIntegral (fromIntegral x :: Word64)
268 narrowU _ _ = panic "narrowTo"
269
270 narrowS :: Width -> Integer -> Integer
271 narrowS W8 x = fromIntegral (fromIntegral x :: Int8)
272 narrowS W16 x = fromIntegral (fromIntegral x :: Int16)
273 narrowS W32 x = fromIntegral (fromIntegral x :: Int32)
274 narrowS W64 x = fromIntegral (fromIntegral x :: Int64)
275 narrowS _ _ = panic "narrowTo"
276
277 -----------------------------------------------------------------------------
278 -- SIMD
279 -----------------------------------------------------------------------------
280
281 type Length = Int
282
283 vec :: Length -> CmmType -> CmmType
284 vec l (CmmType cat w) = CmmType (VecCat l cat) vecw
285 where
286 vecw :: Width
287 vecw = widthFromBytes (l*widthInBytes w)
288
289 vec2, vec4, vec8, vec16 :: CmmType -> CmmType
290 vec2 = vec 2
291 vec4 = vec 4
292 vec8 = vec 8
293 vec16 = vec 16
294
295 vec2f64, vec2b64, vec4f32, vec4b32, vec8b16, vec16b8 :: CmmType
296 vec2f64 = vec 2 f64
297 vec2b64 = vec 2 b64
298 vec4f32 = vec 4 f32
299 vec4b32 = vec 4 b32
300 vec8b16 = vec 8 b16
301 vec16b8 = vec 16 b8
302
303 cmmVec :: Int -> CmmType -> CmmType
304 cmmVec n (CmmType cat w) =
305 CmmType (VecCat n cat) (widthFromBytes (n*widthInBytes w))
306
307 vecLength :: CmmType -> Length
308 vecLength (CmmType (VecCat l _) _) = l
309 vecLength _ = panic "vecLength: not a vector"
310
311 vecElemType :: CmmType -> CmmType
312 vecElemType (CmmType (VecCat l cat) w) = CmmType cat scalw
313 where
314 scalw :: Width
315 scalw = widthFromBytes (widthInBytes w `div` l)
316 vecElemType _ = panic "vecElemType: not a vector"
317
318 isVecType :: CmmType -> Bool
319 isVecType (CmmType (VecCat {}) _) = True
320 isVecType _ = False
321
322 -------------------------------------------------------------------------
323 -- Hints
324
325 -- Hints are extra type information we attach to the arguments and
326 -- results of a foreign call, where more type information is sometimes
327 -- needed by the ABI to make the correct kind of call.
328
329 data ForeignHint
330 = NoHint | AddrHint | SignedHint
331 deriving( Eq )
332 -- Used to give extra per-argument or per-result
333 -- information needed by foreign calling conventions
334
335 -------------------------------------------------------------------------
336
337 -- These don't really belong here, but I don't know where is best to
338 -- put them.
339
340 rEP_CostCentreStack_mem_alloc :: DynFlags -> CmmType
341 rEP_CostCentreStack_mem_alloc dflags
342 = cmmBits (widthFromBytes (pc_REP_CostCentreStack_mem_alloc pc))
343 where pc = sPlatformConstants (settings dflags)
344
345 rEP_CostCentreStack_scc_count :: DynFlags -> CmmType
346 rEP_CostCentreStack_scc_count dflags
347 = cmmBits (widthFromBytes (pc_REP_CostCentreStack_scc_count pc))
348 where pc = sPlatformConstants (settings dflags)
349
350 rEP_StgEntCounter_allocs :: DynFlags -> CmmType
351 rEP_StgEntCounter_allocs dflags
352 = cmmBits (widthFromBytes (pc_REP_StgEntCounter_allocs pc))
353 where pc = sPlatformConstants (settings dflags)
354
355 rEP_StgEntCounter_allocd :: DynFlags -> CmmType
356 rEP_StgEntCounter_allocd dflags
357 = cmmBits (widthFromBytes (pc_REP_StgEntCounter_allocd pc))
358 where pc = sPlatformConstants (settings dflags)
359
360 -------------------------------------------------------------------------
361 {- Note [Signed vs unsigned]
362 ~~~~~~~~~~~~~~~~~~~~~~~~~
363 Should a CmmType include a signed vs. unsigned distinction?
364
365 This is very much like a "hint" in C-- terminology: it isn't necessary
366 in order to generate correct code, but it might be useful in that the
367 compiler can generate better code if it has access to higher-level
368 hints about data. This is important at call boundaries, because the
369 definition of a function is not visible at all of its call sites, so
370 the compiler cannot infer the hints.
371
372 Here in Cmm, we're taking a slightly different approach. We include
373 the int vs. float hint in the CmmType, because (a) the majority of
374 platforms have a strong distinction between float and int registers,
375 and (b) we don't want to do any heavyweight hint-inference in the
376 native code backend in order to get good code. We're treating the
377 hint more like a type: our Cmm is always completely consistent with
378 respect to hints. All coercions between float and int are explicit.
379
380 What about the signed vs. unsigned hint? This information might be
381 useful if we want to keep sub-word-sized values in word-size
382 registers, which we must do if we only have word-sized registers.
383
384 On such a system, there are two straightforward conventions for
385 representing sub-word-sized values:
386
387 (a) Leave the upper bits undefined. Comparison operations must
388 sign- or zero-extend both operands before comparing them,
389 depending on whether the comparison is signed or unsigned.
390
391 (b) Always keep the values sign- or zero-extended as appropriate.
392 Arithmetic operations must narrow the result to the appropriate
393 size.
394
395 A clever compiler might not use either (a) or (b) exclusively, instead
396 it would attempt to minimize the coercions by analysis: the same kind
397 of analysis that propagates hints around. In Cmm we don't want to
398 have to do this, so we plump for having richer types and keeping the
399 type information consistent.
400
401 If signed/unsigned hints are missing from CmmType, then the only
402 choice we have is (a), because we don't know whether the result of an
403 operation should be sign- or zero-extended.
404
405 Many architectures have extending load operations, which work well
406 with (b). To make use of them with (a), you need to know whether the
407 value is going to be sign- or zero-extended by an enclosing comparison
408 (for example), which involves knowing above the context. This is
409 doable but more complex.
410
411 Further complicating the issue is foreign calls: a foreign calling
412 convention can specify that signed 8-bit quantities are passed as
413 sign-extended 32 bit quantities, for example (this is the case on the
414 PowerPC). So we *do* need sign information on foreign call arguments.
415
416 Pros for adding signed vs. unsigned to CmmType:
417
418 - It would let us use convention (b) above, and get easier
419 code generation for extending loads.
420
421 - Less information required on foreign calls.
422
423 - MachOp type would be simpler
424
425 Cons:
426
427 - More complexity
428
429 - What is the CmmType for a VanillaReg? Currently it is
430 always wordRep, but now we have to decide whether it is
431 signed or unsigned. The same VanillaReg can thus have
432 different CmmType in different parts of the program.
433
434 - Extra coercions cluttering up expressions.
435
436 Currently for GHC, the foreign call point is moot, because we do our
437 own promotion of sub-word-sized values to word-sized values. The Int8
438 type is represnted by an Int# which is kept sign-extended at all times
439 (this is slightly naughty, because we're making assumptions about the
440 C calling convention rather early on in the compiler). However, given
441 this, the cons outweigh the pros.
442
443 -}
444