NCG: Split RegAllocInfo into arch specific modules
[ghc-hetmet.git] / compiler / nativeGen / PPC / RegInfo.hs
1 -----------------------------------------------------------------------------
2 --
3 -- Machine-specific parts of the register allocator
4 --
5 -- (c) The University of Glasgow 1996-2004
6 --
7 -----------------------------------------------------------------------------
8
9 module PPC.RegInfo (
10         RegUsage(..),
11         noUsage,
12         regUsage,
13         patchRegs,
14         jumpDests,
15         isJumpish,
16         patchJump,
17         isRegRegMove,
18
19         JumpDest, 
20         canShortcut, 
21         shortcutJump, 
22
23         mkSpillInstr,
24         mkLoadInstr,
25         mkRegRegMoveInstr,
26         mkBranchInstr,
27
28         spillSlotSize,
29         maxSpillSlots,
30         spillSlotToOffset               
31 )
32
33 where
34
35 #include "nativeGen/NCG.h"
36 #include "HsVersions.h"
37
38 import BlockId
39 import Cmm
40 import CLabel
41 import RegsBase
42 import PPC.Regs
43 import PPC.Instr
44 import Outputable
45 import Constants        ( rESERVED_C_STACK_BYTES )
46 import FastBool
47
48 data RegUsage = RU [Reg] [Reg]
49
50 noUsage :: RegUsage
51 noUsage  = RU [] []
52
53 regUsage :: Instr -> RegUsage
54 regUsage instr = case instr of
55     SPILL  reg slot     -> usage ([reg], [])
56     RELOAD slot reg     -> usage ([], [reg])
57
58     LD    sz reg addr   -> usage (regAddr addr, [reg])
59     LA    sz reg addr   -> usage (regAddr addr, [reg])
60     ST    sz reg addr   -> usage (reg : regAddr addr, [])
61     STU    sz reg addr  -> usage (reg : regAddr addr, [])
62     LIS   reg imm       -> usage ([], [reg])
63     LI    reg imm       -> usage ([], [reg])
64     MR    reg1 reg2     -> usage ([reg2], [reg1])
65     CMP   sz reg ri     -> usage (reg : regRI ri,[])
66     CMPL  sz reg ri     -> usage (reg : regRI ri,[])
67     BCC   cond lbl      -> noUsage
68     BCCFAR cond lbl     -> noUsage
69     MTCTR reg           -> usage ([reg],[])
70     BCTR  targets       -> noUsage
71     BL    imm params    -> usage (params, callClobberedRegs)
72     BCTRL params        -> usage (params, callClobberedRegs)
73     ADD   reg1 reg2 ri  -> usage (reg2 : regRI ri, [reg1])
74     ADDC  reg1 reg2 reg3-> usage ([reg2,reg3], [reg1])
75     ADDE  reg1 reg2 reg3-> usage ([reg2,reg3], [reg1])
76     ADDIS reg1 reg2 imm -> usage ([reg2], [reg1])
77     SUBF  reg1 reg2 reg3-> usage ([reg2,reg3], [reg1])
78     MULLW reg1 reg2 ri  -> usage (reg2 : regRI ri, [reg1])
79     DIVW  reg1 reg2 reg3-> usage ([reg2,reg3], [reg1])
80     DIVWU reg1 reg2 reg3-> usage ([reg2,reg3], [reg1])
81     MULLW_MayOflo reg1 reg2 reg3        
82                         -> usage ([reg2,reg3], [reg1])
83     AND   reg1 reg2 ri  -> usage (reg2 : regRI ri, [reg1])
84     OR    reg1 reg2 ri  -> usage (reg2 : regRI ri, [reg1])
85     XOR   reg1 reg2 ri  -> usage (reg2 : regRI ri, [reg1])
86     XORIS reg1 reg2 imm -> usage ([reg2], [reg1])
87     EXTS  siz reg1 reg2 -> usage ([reg2], [reg1])
88     NEG   reg1 reg2     -> usage ([reg2], [reg1])
89     NOT   reg1 reg2     -> usage ([reg2], [reg1])
90     SLW   reg1 reg2 ri  -> usage (reg2 : regRI ri, [reg1])
91     SRW   reg1 reg2 ri  -> usage (reg2 : regRI ri, [reg1])
92     SRAW  reg1 reg2 ri  -> usage (reg2 : regRI ri, [reg1])
93     RLWINM reg1 reg2 sh mb me
94                         -> usage ([reg2], [reg1])
95     FADD  sz r1 r2 r3   -> usage ([r2,r3], [r1])
96     FSUB  sz r1 r2 r3   -> usage ([r2,r3], [r1])
97     FMUL  sz r1 r2 r3   -> usage ([r2,r3], [r1])
98     FDIV  sz r1 r2 r3   -> usage ([r2,r3], [r1])
99     FNEG  r1 r2         -> usage ([r2], [r1])
100     FCMP  r1 r2         -> usage ([r1,r2], [])
101     FCTIWZ r1 r2        -> usage ([r2], [r1])
102     FRSP r1 r2          -> usage ([r2], [r1])
103     MFCR reg            -> usage ([], [reg])
104     MFLR reg            -> usage ([], [reg])
105     FETCHPC reg         -> usage ([], [reg])
106     _                   -> noUsage
107   where
108     usage (src, dst) = RU (filter interesting src)
109                           (filter interesting dst)
110     regAddr (AddrRegReg r1 r2) = [r1, r2]
111     regAddr (AddrRegImm r1 _)  = [r1]
112
113     regRI (RIReg r) = [r]
114     regRI  _    = []
115
116 interesting :: Reg -> Bool
117 interesting (VirtualRegI  _)  = True
118 interesting (VirtualRegHi _)  = True
119 interesting (VirtualRegF  _)  = True
120 interesting (VirtualRegD  _)  = True
121 interesting (RealReg i)       = isFastTrue (freeReg i)
122
123
124 -- -----------------------------------------------------------------------------
125 -- 'patchRegs' function
126
127 -- 'patchRegs' takes an instruction and applies the given mapping to
128 -- all the register references.
129
130 patchRegs :: Instr -> (Reg -> Reg) -> Instr
131 patchRegs instr env = case instr of
132     SPILL reg slot      -> SPILL (env reg) slot
133     RELOAD slot reg     -> RELOAD slot (env reg)
134
135     LD    sz reg addr   -> LD sz (env reg) (fixAddr addr)
136     LA    sz reg addr   -> LA sz (env reg) (fixAddr addr)
137     ST    sz reg addr   -> ST sz (env reg) (fixAddr addr)
138     STU    sz reg addr  -> STU sz (env reg) (fixAddr addr)
139     LIS   reg imm       -> LIS (env reg) imm
140     LI    reg imm       -> LI (env reg) imm
141     MR    reg1 reg2     -> MR (env reg1) (env reg2)
142     CMP   sz reg ri     -> CMP sz (env reg) (fixRI ri)
143     CMPL  sz reg ri     -> CMPL sz (env reg) (fixRI ri)
144     BCC   cond lbl      -> BCC cond lbl
145     BCCFAR cond lbl     -> BCCFAR cond lbl
146     MTCTR reg           -> MTCTR (env reg)
147     BCTR  targets       -> BCTR targets
148     BL    imm argRegs   -> BL imm argRegs       -- argument regs
149     BCTRL argRegs       -> BCTRL argRegs        -- cannot be remapped
150     ADD   reg1 reg2 ri  -> ADD (env reg1) (env reg2) (fixRI ri)
151     ADDC  reg1 reg2 reg3-> ADDC (env reg1) (env reg2) (env reg3)
152     ADDE  reg1 reg2 reg3-> ADDE (env reg1) (env reg2) (env reg3)
153     ADDIS reg1 reg2 imm -> ADDIS (env reg1) (env reg2) imm
154     SUBF  reg1 reg2 reg3-> SUBF (env reg1) (env reg2) (env reg3)
155     MULLW reg1 reg2 ri  -> MULLW (env reg1) (env reg2) (fixRI ri)
156     DIVW  reg1 reg2 reg3-> DIVW (env reg1) (env reg2) (env reg3)
157     DIVWU reg1 reg2 reg3-> DIVWU (env reg1) (env reg2) (env reg3)
158     MULLW_MayOflo reg1 reg2 reg3
159                         -> MULLW_MayOflo (env reg1) (env reg2) (env reg3)
160     AND   reg1 reg2 ri  -> AND (env reg1) (env reg2) (fixRI ri)
161     OR    reg1 reg2 ri  -> OR  (env reg1) (env reg2) (fixRI ri)
162     XOR   reg1 reg2 ri  -> XOR (env reg1) (env reg2) (fixRI ri)
163     XORIS reg1 reg2 imm -> XORIS (env reg1) (env reg2) imm
164     EXTS  sz reg1 reg2 -> EXTS sz (env reg1) (env reg2)
165     NEG   reg1 reg2     -> NEG (env reg1) (env reg2)
166     NOT   reg1 reg2     -> NOT (env reg1) (env reg2)
167     SLW   reg1 reg2 ri  -> SLW (env reg1) (env reg2) (fixRI ri)
168     SRW   reg1 reg2 ri  -> SRW (env reg1) (env reg2) (fixRI ri)
169     SRAW  reg1 reg2 ri  -> SRAW (env reg1) (env reg2) (fixRI ri)
170     RLWINM reg1 reg2 sh mb me
171                         -> RLWINM (env reg1) (env reg2) sh mb me
172     FADD  sz r1 r2 r3   -> FADD sz (env r1) (env r2) (env r3)
173     FSUB  sz r1 r2 r3   -> FSUB sz (env r1) (env r2) (env r3)
174     FMUL  sz r1 r2 r3   -> FMUL sz (env r1) (env r2) (env r3)
175     FDIV  sz r1 r2 r3   -> FDIV sz (env r1) (env r2) (env r3)
176     FNEG  r1 r2         -> FNEG (env r1) (env r2)
177     FCMP  r1 r2         -> FCMP (env r1) (env r2)
178     FCTIWZ r1 r2        -> FCTIWZ (env r1) (env r2)
179     FRSP r1 r2          -> FRSP (env r1) (env r2)
180     MFCR reg            -> MFCR (env reg)
181     MFLR reg            -> MFLR (env reg)
182     FETCHPC reg         -> FETCHPC (env reg)
183     _ -> instr
184   where
185     fixAddr (AddrRegReg r1 r2) = AddrRegReg (env r1) (env r2)
186     fixAddr (AddrRegImm r1 i)  = AddrRegImm (env r1) i
187
188     fixRI (RIReg r) = RIReg (env r)
189     fixRI other = other
190
191
192
193 jumpDests :: Instr -> [BlockId] -> [BlockId]
194 jumpDests insn acc
195   = case insn of
196         BCC _ id        -> id : acc
197         BCCFAR _ id     -> id : acc
198         BCTR targets    -> targets ++ acc
199         _               -> acc
200         
201         
202 -- | Check whether a particular instruction is a jump, branch or call instruction (jumpish)
203 --      We can't just use jumpDests above because the jump might take its arg,
204 --      so the instr won't contain a blockid.
205 --
206 isJumpish :: Instr -> Bool
207 isJumpish instr
208  = case instr of
209         BCC{}           -> True
210         BCCFAR{}        -> True
211         JMP{}           -> True
212
213
214 -- | Change the destination of this jump instruction
215 --      Used in joinToTargets in the linear allocator, when emitting fixup code
216 --      for join points.
217 patchJump :: Instr -> BlockId -> BlockId -> Instr
218 patchJump insn old new
219   = case insn of
220         BCC cc id 
221          | id == old    -> BCC cc new
222
223         BCCFAR cc id 
224          | id == old    -> BCCFAR cc new
225
226         BCTR targets    -> error "Cannot patch BCTR"
227
228         _               -> insn
229
230
231 isRegRegMove :: Instr -> Maybe (Reg,Reg)
232 isRegRegMove (MR dst src) = Just (src,dst)
233 isRegRegMove _  = Nothing
234
235
236 data JumpDest = DestBlockId BlockId | DestImm Imm
237
238 canShortcut :: Instr -> Maybe JumpDest
239 canShortcut _ = Nothing
240
241 shortcutJump :: (BlockId -> Maybe JumpDest) -> Instr -> Instr
242 shortcutJump fn other = other
243
244
245
246
247 -- -----------------------------------------------------------------------------
248 -- Generating spill instructions
249
250 mkSpillInstr
251    :: Reg               -- register to spill
252    -> Int               -- current stack delta
253    -> Int               -- spill slot to use
254    -> Instr
255 mkSpillInstr reg delta slot
256   = let off     = spillSlotToOffset slot
257     in
258     let sz = case regClass reg of
259                 RcInteger -> II32
260                 RcDouble  -> FF64
261     in ST sz reg (AddrRegImm sp (ImmInt (off-delta)))
262
263
264 mkLoadInstr
265    :: Reg               -- register to load
266    -> Int               -- current stack delta
267    -> Int               -- spill slot to use
268    -> Instr
269 mkLoadInstr reg delta slot
270   = let off     = spillSlotToOffset slot
271     in
272     let sz = case regClass reg of
273                 RcInteger -> II32
274                 RcDouble  -> FF64
275     in LD sz reg (AddrRegImm sp (ImmInt (off-delta)))
276
277
278 mkRegRegMoveInstr
279     :: Reg
280     -> Reg
281     -> Instr
282 mkRegRegMoveInstr src dst
283     = MR dst src
284
285
286 mkBranchInstr
287     :: BlockId
288     -> [Instr]
289
290 mkBranchInstr id = [BCC ALWAYS id]
291
292
293
294 spillSlotSize :: Int
295 spillSlotSize = 8
296
297 maxSpillSlots :: Int
298 maxSpillSlots = ((rESERVED_C_STACK_BYTES - 64) `div` spillSlotSize) - 1
299
300 -- convert a spill slot number to a *byte* offset, with no sign:
301 -- decide on a per arch basis whether you are spilling above or below
302 -- the C stack pointer.
303 spillSlotToOffset :: Int -> Int
304 spillSlotToOffset slot
305    | slot >= 0 && slot < maxSpillSlots
306    = 64 + spillSlotSize * slot
307    | otherwise
308    = pprPanic "spillSlotToOffset:" 
309               (   text "invalid spill location: " <> int slot
310               $$  text "maxSpillSlots:          " <> int maxSpillSlots)