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