2 -- | Free regs map for SPARC
3 module RegAlloc.Linear.SPARC.FreeRegs
14 --------------------------------------------------------------------------------
15 -- SPARC is like PPC, except for twinning of floating point regs.
16 -- When we allocate a double reg we must take an even numbered
17 -- float reg, as well as the one after it.
20 -- Holds bitmaps showing what registers are currently allocated.
21 -- The float and double reg bitmaps overlap, but we only alloc
22 -- float regs into the float map, and double regs into the double map.
24 -- Free regs have a bit set in the corresponding bitmap.
28 !Word32 -- int reg bitmap regs 0..31
29 !Word32 -- float reg bitmap regs 32..63
30 !Word32 -- double reg bitmap regs 32..63
34 -- | A reg map where no regs are free to be allocated.
35 noFreeRegs :: FreeRegs
36 noFreeRegs = FreeRegs 0 0 0
39 -- | The initial set of free regs.
40 -- Don't treat the top half of reg pairs we're using as doubles as being free.
41 initFreeRegs :: FreeRegs
45 -- freeDouble = getFreeRegs RcDouble regs
46 regs = foldr releaseReg noFreeRegs allocable
47 allocable = allocatableRegs \\ doublePairs
48 doublePairs = [43, 45, 47, 49, 51, 53]
51 -- | Get all the free registers of this class.
52 getFreeRegs :: RegClass -> FreeRegs -> [RegNo] -- lazilly
53 getFreeRegs cls (FreeRegs g f d)
54 | RcInteger <- cls = go g 1 0
55 | RcFloat <- cls = go f 1 32
56 | RcDouble <- cls = go d 1 32
57 | otherwise = pprPanic "RegAllocLinear.getFreeRegs: Bad register class " (ppr cls)
60 go x m i | x .&. m /= 0 = i : (go x (m `shiftL` 1) $! i+1)
61 | otherwise = go x (m `shiftL` 1) $! i+1
63 showFreeRegs :: FreeRegs -> String
66 ++ " integer: " ++ (show $ getFreeRegs RcInteger regs) ++ "\n"
67 ++ " float: " ++ (show $ getFreeRegs RcFloat regs) ++ "\n"
68 ++ " double: " ++ (show $ getFreeRegs RcDouble regs) ++ "\n"
72 -- | Check whether a reg is free
73 regIsFree :: RegNo -> FreeRegs -> Bool
74 regIsFree r (FreeRegs g f d)
76 -- a general purpose reg
78 , mask <- 1 `shiftL` fromIntegral r
81 -- use the first 22 float regs as double precision
84 , mask <- 1 `shiftL` (fromIntegral r - 32)
87 -- use the last 10 float regs as single precision
89 , mask <- 1 `shiftL` (fromIntegral r - 32)
94 grabReg :: RegNo -> FreeRegs -> FreeRegs
95 grabReg r (FreeRegs g f d)
97 -- a general purpose reg
99 , mask <- complement (1 `shiftL` fromIntegral r)
100 = FreeRegs (g .&. mask) f d
102 -- use the first 22 float regs as double precision
105 , mask <- complement (1 `shiftL` (fromIntegral r - 32))
106 = FreeRegs g f (d .&. mask)
108 -- use the last 10 float regs as single precision
110 , mask <- complement (1 `shiftL` (fromIntegral r - 32))
111 = FreeRegs g (f .&. mask) d
115 -- | Release a register from allocation.
116 -- The register liveness information says that most regs die after a C call,
117 -- but we still don't want to allocate to some of them.
119 releaseReg :: RegNo -> FreeRegs -> FreeRegs
120 releaseReg r regs@(FreeRegs g f d)
122 -- used by STG machine, or otherwise unavailable
123 -- see includes/MachRegs.h for more info
128 -- r5-r7: reserved for OS
130 | r >= 5 && r <= 7 = regs
134 -- r8 - r13: allocable
137 | r >= 14 && r <= 15 = regs
142 -- r22 - r23: allocable
143 | r >= 17 && r <= 21 = regs
146 -- r24 - r29: Sp, Base, SpLim, Hp, HpLim, R6
149 | r >= 24 && r <= 31 = regs
152 -- r32 & r33: floating point return from C fun
155 -- r38 & r39: NCG spill tmp
156 -- r40 & r41: NCG spill tmp
157 | r >= 32 && r <= 41 = regs
159 -- r42 - r53: allocatable as double prec float regs
162 -- r58 - r59: NCG spill tmps
163 | r >= 54 && r <= 59 = regs
165 -- r60-r64: allocatable as single prec float regs.
168 -- never release the high part of double regs.
169 -- this prevents them from being allocated as single precison regs.
177 -- a general purpose reg
179 , mask <- 1 `shiftL` fromIntegral r
180 = FreeRegs (g .|. mask) f d
182 -- use the first 22 float regs as double precision
185 , mask <- 1 `shiftL` (fromIntegral r - 32)
186 = FreeRegs g f (d .|. mask)
188 -- use the last 10 float regs as single precision
190 , mask <- 1 `shiftL` (fromIntegral r - 32)
191 = FreeRegs g (f .|. mask) d
194 -- | Allocate a register in the map.
195 allocateReg :: RegNo -> FreeRegs -> FreeRegs
196 allocateReg r regs -- (FreeRegs g f d)
198 -- if the reg isn't actually free then we're in trouble
199 {- | not $ regIsFree r regs
201 "RegAllocLinear.allocateReg"
202 (text "reg " <> ppr r <> text " is not free")