2 -- | Free regs map for SPARC
3 module RegAlloc.Linear.SPARC.FreeRegs
19 --------------------------------------------------------------------------------
20 -- SPARC is like PPC, except for twinning of floating point regs.
21 -- When we allocate a double reg we must take an even numbered
22 -- float reg, as well as the one after it.
25 -- Holds bitmaps showing what registers are currently allocated.
26 -- The float and double reg bitmaps overlap, but we only alloc
27 -- float regs into the float map, and double regs into the double map.
29 -- Free regs have a bit set in the corresponding bitmap.
33 !Word32 -- int reg bitmap regs 0..31
34 !Word32 -- float reg bitmap regs 32..63
35 !Word32 -- double reg bitmap regs 32..63
39 -- | A reg map where no regs are free to be allocated.
40 noFreeRegs :: FreeRegs
41 noFreeRegs = FreeRegs 0 0 0
44 -- | The initial set of free regs.
45 -- Don't treat the top half of reg pairs we're using as doubles as being free.
46 initFreeRegs :: FreeRegs
50 -- freeDouble = getFreeRegs RcDouble regs
51 regs = foldr releaseReg noFreeRegs allocable
52 allocable = allocatableRegs \\ doublePairs
53 doublePairs = [43, 45, 47, 49, 51, 53]
56 -- | Get all the free registers of this class.
57 getFreeRegs :: RegClass -> FreeRegs -> [RegNo] -- lazilly
58 getFreeRegs cls (FreeRegs g f d)
59 | RcInteger <- cls = go g 1 0
60 | RcFloat <- cls = go f 1 32
61 | RcDouble <- cls = go d 1 32
62 | otherwise = pprPanic "RegAllocLinear.getFreeRegs: Bad register class " (ppr cls)
65 go x m i | x .&. m /= 0 = i : (go x (m `shiftL` 1) $! i+1)
66 | otherwise = go x (m `shiftL` 1) $! i+1
68 showFreeRegs :: FreeRegs -> String
71 ++ " integer: " ++ (show $ getFreeRegs RcInteger regs) ++ "\n"
72 ++ " float: " ++ (show $ getFreeRegs RcFloat regs) ++ "\n"
73 ++ " double: " ++ (show $ getFreeRegs RcDouble regs) ++ "\n"
77 -- | Check whether a reg is free
78 regIsFree :: RegNo -> FreeRegs -> Bool
79 regIsFree r (FreeRegs g f d)
81 -- a general purpose reg
83 , mask <- 1 `shiftL` fromIntegral r
86 -- use the first 22 float regs as double precision
89 , mask <- 1 `shiftL` (fromIntegral r - 32)
92 -- use the last 10 float regs as single precision
94 , mask <- 1 `shiftL` (fromIntegral r - 32)
99 grabReg :: RegNo -> FreeRegs -> FreeRegs
100 grabReg r (FreeRegs g f d)
102 -- a general purpose reg
104 , mask <- complement (1 `shiftL` fromIntegral r)
105 = FreeRegs (g .&. mask) f d
107 -- use the first 22 float regs as double precision
110 , mask <- complement (1 `shiftL` (fromIntegral r - 32))
111 = FreeRegs g f (d .&. mask)
113 -- use the last 10 float regs as single precision
115 , mask <- complement (1 `shiftL` (fromIntegral r - 32))
116 = FreeRegs g (f .&. mask) d
120 -- | Release a register from allocation.
121 -- The register liveness information says that most regs die after a C call,
122 -- but we still don't want to allocate to some of them.
124 releaseReg :: RegNo -> FreeRegs -> FreeRegs
125 releaseReg r regs@(FreeRegs g f d)
126 -- don't release pinned reg
127 | not $ isFastTrue (freeReg r)
130 -- don't release the high part of double regs
131 -- this prevents them from being allocated as single precison regs.
141 -- a general purpose reg
143 , mask <- 1 `shiftL` fromIntegral r
144 = FreeRegs (g .|. mask) f d
146 -- use the first 22 float regs as double precision
149 , mask <- 1 `shiftL` (fromIntegral r - 32)
150 = FreeRegs g f (d .|. mask)
152 -- use the last 10 float regs as single precision
154 , mask <- 1 `shiftL` (fromIntegral r - 32)
155 = FreeRegs g (f .|. mask) d
158 -- | Allocate a register in the map.
159 allocateReg :: RegNo -> FreeRegs -> FreeRegs
160 allocateReg r regs -- (FreeRegs g f d)
162 -- if the reg isn't actually free then we're in trouble
163 {- | not $ regIsFree r regs
165 "RegAllocLinear.allocateReg"
166 (text "reg " <> ppr r <> text " is not free")