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