2 -- | Free regs map for SPARC
3 module RegAlloc.Linear.SPARC.FreeRegs
18 --------------------------------------------------------------------------------
19 -- SPARC is like PPC, except for twinning of floating point regs.
20 -- When we allocate a double reg we must take an even numbered
21 -- float reg, as well as the one after it.
24 -- Holds bitmaps showing what registers are currently allocated.
25 -- The float and double reg bitmaps overlap, but we only alloc
26 -- float regs into the float map, and double regs into the double map.
28 -- Free regs have a bit set in the corresponding bitmap.
32 !Word32 -- int reg bitmap regs 0..31
33 !Word32 -- float reg bitmap regs 32..63
34 !Word32 -- double reg bitmap regs 32..63
38 -- | A reg map where no regs are free to be allocated.
39 noFreeRegs :: FreeRegs
40 noFreeRegs = FreeRegs 0 0 0
43 -- | The initial set of free regs.
44 -- Don't treat the top half of reg pairs we're using as doubles as being free.
45 initFreeRegs :: FreeRegs
49 -- freeDouble = getFreeRegs RcDouble regs
50 regs = foldr releaseReg noFreeRegs allocable
51 allocable = allocatableRegs \\ doublePairs
52 doublePairs = [43, 45, 47, 49, 51, 53]
55 -- | Get all the free registers of this class.
56 getFreeRegs :: RegClass -> FreeRegs -> [RegNo] -- lazilly
57 getFreeRegs cls (FreeRegs g f d)
58 | RcInteger <- cls = go g 1 0
59 | RcFloat <- cls = go f 1 32
60 | RcDouble <- cls = go d 1 32
61 | otherwise = pprPanic "RegAllocLinear.getFreeRegs: Bad register class " (ppr cls)
64 go x m i | x .&. m /= 0 = i : (go x (m `shiftL` 1) $! i+1)
65 | otherwise = go x (m `shiftL` 1) $! i+1
67 showFreeRegs :: FreeRegs -> String
70 ++ " integer: " ++ (show $ getFreeRegs RcInteger regs) ++ "\n"
71 ++ " float: " ++ (show $ getFreeRegs RcFloat regs) ++ "\n"
72 ++ " double: " ++ (show $ getFreeRegs RcDouble regs) ++ "\n"
76 -- | Check whether a reg is free
77 regIsFree :: RegNo -> FreeRegs -> Bool
78 regIsFree r (FreeRegs g f d)
80 -- a general purpose reg
82 , mask <- 1 `shiftL` fromIntegral r
85 -- use the first 22 float regs as double precision
88 , mask <- 1 `shiftL` (fromIntegral r - 32)
91 -- use the last 10 float regs as single precision
93 , mask <- 1 `shiftL` (fromIntegral r - 32)
98 grabReg :: RegNo -> FreeRegs -> FreeRegs
99 grabReg r (FreeRegs g f d)
101 -- a general purpose reg
103 , mask <- complement (1 `shiftL` fromIntegral r)
104 = FreeRegs (g .&. mask) f d
106 -- use the first 22 float regs as double precision
109 , mask <- complement (1 `shiftL` (fromIntegral r - 32))
110 = FreeRegs g f (d .&. mask)
112 -- use the last 10 float regs as single precision
114 , mask <- complement (1 `shiftL` (fromIntegral r - 32))
115 = FreeRegs g (f .&. mask) d
119 -- | Release a register from allocation.
120 -- The register liveness information says that most regs die after a C call,
121 -- but we still don't want to allocate to some of them.
123 releaseReg :: RegNo -> FreeRegs -> FreeRegs
124 releaseReg r regs@(FreeRegs g f d)
125 -- don't release pinned reg
126 | not $ isFastTrue (freeReg r)
129 -- don't release the high part of double regs
130 -- this prevents them from being allocated as single precison regs.
138 -- a general purpose reg
140 , mask <- 1 `shiftL` fromIntegral r
141 = FreeRegs (g .|. mask) f d
143 -- use the first 22 float regs as double precision
146 , mask <- 1 `shiftL` (fromIntegral r - 32)
147 = FreeRegs g f (d .|. mask)
149 -- use the last 10 float regs as single precision
151 , mask <- 1 `shiftL` (fromIntegral r - 32)
152 = FreeRegs g (f .|. mask) d
155 -- | Allocate a register in the map.
156 allocateReg :: RegNo -> FreeRegs -> FreeRegs
157 allocateReg r regs -- (FreeRegs g f d)
159 -- if the reg isn't actually free then we're in trouble
160 {- | not $ regIsFree r regs
162 "RegAllocLinear.allocateReg"
163 (text "reg " <> ppr r <> text " is not free")