NCG: Split RegAllocInfo into arch specific modules
[ghc-hetmet.git] / compiler / nativeGen / SPARC / RegInfo.hs
1
2 -----------------------------------------------------------------------------
3 --
4 -- Machine-specific parts of the register allocator
5 --
6 -- (c) The University of Glasgow 1996-2004
7 --
8 -----------------------------------------------------------------------------
9
10 module SPARC.RegInfo (
11         -- machine specific 
12         RegUsage(..),
13         noUsage,
14         regUsage,
15         patchRegs,
16         jumpDests,
17         isJumpish,
18         patchJump,
19         isRegRegMove,
20
21         JumpDest(..), 
22         canShortcut, 
23         shortcutJump, 
24
25         mkSpillInstr,
26         mkLoadInstr,
27         mkRegRegMoveInstr,
28         mkBranchInstr,
29         
30         spillSlotSize,
31         maxSpillSlots,
32         spillSlotToOffset               
33 )
34
35 where
36
37
38 #include "nativeGen/NCG.h"
39 #include "HsVersions.h"
40
41 import BlockId
42 import Instrs
43 import Regs
44 import Outputable
45 import Constants        ( rESERVED_C_STACK_BYTES )
46 import FastBool
47
48
49 -- -----------------------------------------------------------------------------
50 -- RegUsage type
51
52 -- @regUsage@ returns the sets of src and destination registers used
53 -- by a particular instruction.  Machine registers that are
54 -- pre-allocated to stgRegs are filtered out, because they are
55 -- uninteresting from a register allocation standpoint.  (We wouldn't
56 -- want them to end up on the free list!)  As far as we are concerned,
57 -- the fixed registers simply don't exist (for allocation purposes,
58 -- anyway).
59
60 -- regUsage doesn't need to do any trickery for jumps and such.  Just
61 -- state precisely the regs read and written by that insn.  The
62 -- consequences of control flow transfers, as far as register
63 -- allocation goes, are taken care of by the register allocator.
64
65 data RegUsage = RU [Reg] [Reg]
66
67 noUsage :: RegUsage
68 noUsage  = RU [] []
69
70 regUsage :: Instr -> RegUsage
71
72 regUsage instr = case instr of
73     SPILL  reg _        -> usage ([reg], [])
74     RELOAD _   reg      -> usage ([], [reg])
75
76     LD    _ addr reg    -> usage (regAddr addr, [reg])
77     ST    _ reg addr    -> usage (reg : regAddr addr, [])
78     ADD   _ _ r1 ar r2  -> usage (r1 : regRI ar, [r2])
79     SUB   _ _ r1 ar r2  -> usage (r1 : regRI ar, [r2])
80     UMUL    _ r1 ar r2  -> usage (r1 : regRI ar, [r2])
81     SMUL    _ r1 ar r2  -> usage (r1 : regRI ar, [r2])
82     UDIV    _ r1 ar r2  -> usage (r1 : regRI ar, [r2])
83     SDIV    _ r1 ar r2  -> usage (r1 : regRI ar, [r2])
84     RDY   rd            -> usage ([], [rd])
85     WRY   r1 r2         -> usage ([r1, r2], [])
86     AND   _ r1 ar r2    -> usage (r1 : regRI ar, [r2])
87     ANDN  _ r1 ar r2    -> usage (r1 : regRI ar, [r2])
88     OR    _ r1 ar r2    -> usage (r1 : regRI ar, [r2])
89     ORN   _ r1 ar r2    -> usage (r1 : regRI ar, [r2])
90     XOR   _ r1 ar r2    -> usage (r1 : regRI ar, [r2])
91     XNOR  _ r1 ar r2    -> usage (r1 : regRI ar, [r2])
92     SLL   r1 ar r2      -> usage (r1 : regRI ar, [r2])
93     SRL   r1 ar r2      -> usage (r1 : regRI ar, [r2])
94     SRA   r1 ar r2      -> usage (r1 : regRI ar, [r2])
95     SETHI _ reg         -> usage ([], [reg])
96     FABS  _ r1 r2       -> usage ([r1], [r2])
97     FADD  _ r1 r2 r3    -> usage ([r1, r2], [r3])
98     FCMP  _ _  r1 r2    -> usage ([r1, r2], [])
99     FDIV  _ r1 r2 r3    -> usage ([r1, r2], [r3])
100     FMOV  _ r1 r2       -> usage ([r1], [r2])
101     FMUL  _ r1 r2 r3    -> usage ([r1, r2], [r3])
102     FNEG  _ r1 r2       -> usage ([r1], [r2])
103     FSQRT _ r1 r2       -> usage ([r1], [r2])
104     FSUB  _ r1 r2 r3    -> usage ([r1, r2], [r3])
105     FxTOy _ _  r1 r2    -> usage ([r1], [r2])
106
107     JMP     addr        -> usage (regAddr addr, [])
108     JMP_TBL addr _      -> usage (regAddr addr, [])
109
110     CALL  (Left _  )  _ True  -> noUsage
111     CALL  (Left _  )  n False -> usage (argRegs n, callClobberedRegs)
112     CALL  (Right reg) _ True  -> usage ([reg], [])
113     CALL  (Right reg) n False -> usage (reg : (argRegs n), callClobberedRegs)
114
115     _                   -> noUsage
116   where
117     usage (src, dst) = RU (filter interesting src)
118                          (filter interesting dst)
119
120     regAddr (AddrRegReg r1 r2) = [r1, r2]
121     regAddr (AddrRegImm r1 _)  = [r1]
122
123     regRI (RIReg r) = [r]
124     regRI  _    = []
125
126
127 interesting :: Reg -> Bool
128 interesting (VirtualRegI  _)  = True
129 interesting (VirtualRegHi _)  = True
130 interesting (VirtualRegF  _)  = True
131 interesting (VirtualRegD  _)  = True
132 interesting (RealReg i)       = isFastTrue (freeReg i)
133
134
135 -- -----------------------------------------------------------------------------
136 -- 'patchRegs' function
137
138 -- 'patchRegs' takes an instruction and applies the given mapping to
139 -- all the register references.
140
141 patchRegs :: Instr -> (Reg -> Reg) -> Instr
142
143 patchRegs instr env = case instr of
144     SPILL reg slot      -> SPILL (env reg) slot
145     RELOAD slot reg     -> RELOAD slot (env reg)
146     LD    sz addr reg   -> LD sz (fixAddr addr) (env reg)
147     ST    sz reg addr   -> ST sz (env reg) (fixAddr addr)
148     ADD   x cc r1 ar r2 -> ADD x cc (env r1) (fixRI ar) (env r2)
149     SUB   x cc r1 ar r2 -> SUB x cc (env r1) (fixRI ar) (env r2)
150     UMUL    cc r1 ar r2 -> UMUL cc (env r1) (fixRI ar) (env r2)
151     SMUL    cc r1 ar r2 -> SMUL cc (env r1) (fixRI ar) (env r2)
152     UDIV    cc r1 ar r2 -> UDIV cc (env r1) (fixRI ar) (env r2)
153     SDIV    cc r1 ar r2 -> SDIV cc (env r1) (fixRI ar) (env r2)
154     RDY   rd            -> RDY (env rd)
155     WRY   r1 r2         -> WRY (env r1) (env r2)
156     AND   b r1 ar r2    -> AND b (env r1) (fixRI ar) (env r2)
157     ANDN  b r1 ar r2    -> ANDN b (env r1) (fixRI ar) (env r2)
158     OR    b r1 ar r2    -> OR b (env r1) (fixRI ar) (env r2)
159     ORN   b r1 ar r2    -> ORN b (env r1) (fixRI ar) (env r2)
160     XOR   b r1 ar r2    -> XOR b (env r1) (fixRI ar) (env r2)
161     XNOR  b r1 ar r2    -> XNOR b (env r1) (fixRI ar) (env r2)
162     SLL   r1 ar r2      -> SLL (env r1) (fixRI ar) (env r2)
163     SRL   r1 ar r2      -> SRL (env r1) (fixRI ar) (env r2)
164     SRA   r1 ar r2      -> SRA (env r1) (fixRI ar) (env r2)
165     SETHI imm reg       -> SETHI imm (env reg)
166     FABS  s r1 r2       -> FABS s (env r1) (env r2)
167     FADD  s r1 r2 r3    -> FADD s (env r1) (env r2) (env r3)
168     FCMP  e s r1 r2     -> FCMP e s (env r1) (env r2)
169     FDIV  s r1 r2 r3    -> FDIV s (env r1) (env r2) (env r3)
170     FMOV  s r1 r2       -> FMOV s (env r1) (env r2)
171     FMUL  s r1 r2 r3    -> FMUL s (env r1) (env r2) (env r3)
172     FNEG  s r1 r2       -> FNEG s (env r1) (env r2)
173     FSQRT s r1 r2       -> FSQRT s (env r1) (env r2)
174     FSUB  s r1 r2 r3    -> FSUB s (env r1) (env r2) (env r3)
175     FxTOy s1 s2 r1 r2   -> FxTOy s1 s2 (env r1) (env r2)
176
177     JMP     addr        -> JMP     (fixAddr addr)
178     JMP_TBL addr ids    -> JMP_TBL (fixAddr addr) ids
179
180     CALL  (Left i) n t  -> CALL (Left i) n t
181     CALL  (Right r) n t -> CALL (Right (env r)) n t
182     _ -> instr
183   where
184     fixAddr (AddrRegReg r1 r2) = AddrRegReg (env r1) (env r2)
185     fixAddr (AddrRegImm r1 i)  = AddrRegImm (env r1) i
186
187     fixRI (RIReg r) = RIReg (env r)
188     fixRI other = other
189
190
191 -- -----------------------------------------------------------------------------
192 -- Determine the possible destinations from the current instruction.
193
194 -- (we always assume that the next instruction is also a valid destination;
195 -- if this isn't the case then the jump should be at the end of the basic
196 -- block).
197
198 jumpDests :: Instr -> [BlockId] -> [BlockId]
199 jumpDests insn acc
200   = case insn of
201         BI   _ _ id     -> id : acc
202         BF   _ _ id     -> id : acc
203         JMP_TBL _ ids   -> ids ++ acc
204         _other          -> acc
205
206
207 -- | Check whether a particular instruction is a jump, branch or call instruction (jumpish)
208 --      We can't just use jumpDests above because the jump might take its arg,
209 --      so the instr won't contain a blockid.
210 --
211 isJumpish :: Instr -> Bool
212 isJumpish instr
213  = case instr of
214         BI{}            -> True
215         BF{}            -> True
216         JMP{}           -> True
217         JMP_TBL{}       -> True
218         CALL{}          -> True
219         _               -> False
220
221
222 -- | Change the destination of this jump instruction
223 --      Used in joinToTargets in the linear allocator, when emitting fixup code
224 --      for join points.
225 patchJump :: Instr -> BlockId -> BlockId -> Instr
226 patchJump insn old new
227   = case insn of
228         BI cc annul id
229          | id == old    -> BI cc annul new
230          
231         BF cc annul id
232          | id == old    -> BF cc annul new
233
234         _other          -> insn
235
236
237 -- -----------------------------------------------------------------------------
238 -- Detecting reg->reg moves
239
240 -- The register allocator attempts to eliminate reg->reg moves whenever it can,
241 -- by assigning the src and dest temporaries to the same real register.
242
243 isRegRegMove :: Instr -> Maybe (Reg,Reg)
244 isRegRegMove instr
245  = case instr of
246         ADD False False src (RIReg src2) dst
247          | g0 == src2           -> Just (src, dst)
248
249         FMOV FF64 src dst       -> Just (src, dst)
250         FMOV FF32  src dst      -> Just (src, dst)
251         _                       -> Nothing
252
253
254 data JumpDest = DestBlockId BlockId | DestImm Imm
255
256 canShortcut :: Instr -> Maybe JumpDest
257 canShortcut _ = Nothing
258
259 shortcutJump :: (BlockId -> Maybe JumpDest) -> Instr -> Instr
260 shortcutJump _ other = other
261
262
263
264
265 -- -----------------------------------------------------------------------------
266 -- Generating spill instructions
267
268 -- SPARC: spill below frame pointer leaving 2 words/spill
269 mkSpillInstr
270    :: Reg               -- register to spill
271    -> Int               -- current stack delta
272    -> Int               -- spill slot to use
273    -> Instr
274
275 mkSpillInstr reg _ slot
276   = let off     = spillSlotToOffset slot
277         off_w   = 1 + (off `div` 4)
278         sz      = case regClass reg of
279                         RcInteger -> II32
280                         RcFloat   -> FF32
281                         RcDouble  -> FF64
282                 
283     in ST sz reg (fpRel (negate off_w))
284
285
286 mkLoadInstr
287    :: Reg               -- register to load
288    -> Int               -- current stack delta
289    -> Int               -- spill slot to use
290    -> Instr
291
292 mkLoadInstr reg _ slot
293   = let off     = spillSlotToOffset slot
294     in  let{off_w = 1 + (off `div` 4);
295             sz = case regClass reg of {
296                    RcInteger -> II32;
297                    RcFloat   -> FF32;
298                    RcDouble  -> FF64}}
299         in LD sz (fpRel (- off_w)) reg
300
301
302 mkRegRegMoveInstr
303     :: Reg
304     -> Reg
305     -> Instr
306 mkRegRegMoveInstr src dst
307     = case regClass src of
308         RcInteger -> ADD  False False src (RIReg g0) dst
309         RcDouble  -> FMOV FF64 src dst
310         RcFloat   -> FMOV FF32  src dst
311
312
313 mkBranchInstr
314     :: BlockId
315     -> [Instr]
316
317 mkBranchInstr id = [BI ALWAYS False id, NOP]
318
319
320 spillSlotSize :: Int
321 spillSlotSize = 8
322
323 maxSpillSlots :: Int
324 maxSpillSlots = ((rESERVED_C_STACK_BYTES - 64) `div` spillSlotSize) - 1
325
326
327 -- convert a spill slot number to a *byte* offset, with no sign:
328 -- decide on a per arch basis whether you are spilling above or below
329 -- the C stack pointer.
330 spillSlotToOffset :: Int -> Int
331 spillSlotToOffset slot
332    | slot >= 0 && slot < maxSpillSlots
333    = 64 + spillSlotSize * slot
334
335    | otherwise
336    = pprPanic "spillSlotToOffset:" 
337               (   text "invalid spill location: " <> int slot
338               $$  text "maxSpillSlots:          " <> int maxSpillSlots)
339