2 -- | Free regs map for SPARC
3 module RegAlloc.Linear.SPARC.FreeRegs
16 --------------------------------------------------------------------------------
17 -- SPARC is like PPC, except for twinning of floating point regs.
18 -- When we allocate a double reg we must take an even numbered
19 -- float reg, as well as the one after it.
22 -- Holds bitmaps showing what registers are currently allocated.
23 -- The float and double reg bitmaps overlap, but we only alloc
24 -- float regs into the float map, and double regs into the double map.
26 -- Free regs have a bit set in the corresponding bitmap.
30 !Word32 -- int reg bitmap regs 0..31
31 !Word32 -- float reg bitmap regs 32..63
32 !Word32 -- double reg bitmap regs 32..63
36 -- | A reg map where no regs are free to be allocated.
37 noFreeRegs :: FreeRegs
38 noFreeRegs = FreeRegs 0 0 0
41 -- | The initial set of free regs.
42 -- Don't treat the top half of reg pairs we're using as doubles as being free.
43 initFreeRegs :: FreeRegs
47 -- freeDouble = getFreeRegs RcDouble regs
48 regs = foldr releaseReg noFreeRegs allocable
49 allocable = allocatableRegs \\ doublePairs
50 doublePairs = [43, 45, 47, 49, 51, 53]
53 -- | Get all the free registers of this class.
54 getFreeRegs :: RegClass -> FreeRegs -> [RegNo] -- lazilly
55 getFreeRegs cls (FreeRegs g f d)
56 | RcInteger <- cls = go g 1 0
57 | RcFloat <- cls = go f 1 32
58 | RcDouble <- cls = go d 1 32
59 | otherwise = pprPanic "RegAllocLinear.getFreeRegs: Bad register class " (ppr cls)
62 go x m i | x .&. m /= 0 = i : (go x (m `shiftL` 1) $! i+1)
63 | otherwise = go x (m `shiftL` 1) $! i+1
65 showFreeRegs :: FreeRegs -> String
68 ++ " integer: " ++ (show $ getFreeRegs RcInteger regs) ++ "\n"
69 ++ " float: " ++ (show $ getFreeRegs RcFloat regs) ++ "\n"
70 ++ " double: " ++ (show $ getFreeRegs RcDouble regs) ++ "\n"
74 -- | Check whether a reg is free
75 regIsFree :: RegNo -> FreeRegs -> Bool
76 regIsFree r (FreeRegs g f d)
78 -- a general purpose reg
80 , mask <- 1 `shiftL` fromIntegral r
83 -- use the first 22 float regs as double precision
86 , mask <- 1 `shiftL` (fromIntegral r - 32)
89 -- use the last 10 float regs as single precision
91 , mask <- 1 `shiftL` (fromIntegral r - 32)
96 grabReg :: RegNo -> FreeRegs -> FreeRegs
97 grabReg r (FreeRegs g f d)
99 -- a general purpose reg
101 , mask <- complement (1 `shiftL` fromIntegral r)
102 = FreeRegs (g .&. mask) f d
104 -- use the first 22 float regs as double precision
107 , mask <- complement (1 `shiftL` (fromIntegral r - 32))
108 = FreeRegs g f (d .&. mask)
110 -- use the last 10 float regs as single precision
112 , mask <- complement (1 `shiftL` (fromIntegral r - 32))
113 = FreeRegs g (f .&. mask) d
117 -- | Release a register from allocation.
118 -- The register liveness information says that most regs die after a C call,
119 -- but we still don't want to allocate to some of them.
121 releaseReg :: RegNo -> FreeRegs -> FreeRegs
122 releaseReg r regs@(FreeRegs g f d)
123 -- don't release pinned reg
124 | not $ isFastTrue (freeReg r)
127 -- don't release the high part of double regs
128 -- this prevents them from being allocated as single precison regs.
136 -- a general purpose reg
138 , mask <- 1 `shiftL` fromIntegral r
139 = FreeRegs (g .|. mask) f d
141 -- use the first 22 float regs as double precision
144 , mask <- 1 `shiftL` (fromIntegral r - 32)
145 = FreeRegs g f (d .|. mask)
147 -- use the last 10 float regs as single precision
149 , mask <- 1 `shiftL` (fromIntegral r - 32)
150 = FreeRegs g (f .|. mask) d
153 -- | Allocate a register in the map.
154 allocateReg :: RegNo -> FreeRegs -> FreeRegs
155 allocateReg r regs -- (FreeRegs g f d)
157 -- if the reg isn't actually free then we're in trouble
158 {- | not $ regIsFree r regs
160 "RegAllocLinear.allocateReg"
161 (text "reg " <> ppr r <> text " is not free")