1 -----------------------------------------------------------------------------
3 -- Machine-specific parts of the register allocator
5 -- (c) The University of Glasgow 1996-2004
7 -----------------------------------------------------------------------------
35 #include "nativeGen/NCG.h"
36 #include "HsVersions.h"
45 import Constants ( rESERVED_C_STACK_BYTES )
48 data RegUsage = RU [Reg] [Reg]
53 regUsage :: Instr -> RegUsage
54 regUsage instr = case instr of
55 SPILL reg slot -> usage ([reg], [])
56 RELOAD slot reg -> usage ([], [reg])
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])
108 usage (src, dst) = RU (filter interesting src)
109 (filter interesting dst)
110 regAddr (AddrRegReg r1 r2) = [r1, r2]
111 regAddr (AddrRegImm r1 _) = [r1]
113 regRI (RIReg r) = [r]
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)
124 -- -----------------------------------------------------------------------------
125 -- 'patchRegs' function
127 -- 'patchRegs' takes an instruction and applies the given mapping to
128 -- all the register references.
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)
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)
185 fixAddr (AddrRegReg r1 r2) = AddrRegReg (env r1) (env r2)
186 fixAddr (AddrRegImm r1 i) = AddrRegImm (env r1) i
188 fixRI (RIReg r) = RIReg (env r)
193 jumpDests :: Instr -> [BlockId] -> [BlockId]
197 BCCFAR _ id -> id : acc
198 BCTR targets -> targets ++ acc
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.
206 isJumpish :: Instr -> Bool
214 -- | Change the destination of this jump instruction
215 -- Used in joinToTargets in the linear allocator, when emitting fixup code
217 patchJump :: Instr -> BlockId -> BlockId -> Instr
218 patchJump insn old new
221 | id == old -> BCC cc new
224 | id == old -> BCCFAR cc new
226 BCTR targets -> error "Cannot patch BCTR"
231 isRegRegMove :: Instr -> Maybe (Reg,Reg)
232 isRegRegMove (MR dst src) = Just (src,dst)
233 isRegRegMove _ = Nothing
236 data JumpDest = DestBlockId BlockId | DestImm Imm
238 canShortcut :: Instr -> Maybe JumpDest
239 canShortcut _ = Nothing
241 shortcutJump :: (BlockId -> Maybe JumpDest) -> Instr -> Instr
242 shortcutJump fn other = other
247 -- -----------------------------------------------------------------------------
248 -- Generating spill instructions
251 :: Reg -- register to spill
252 -> Int -- current stack delta
253 -> Int -- spill slot to use
255 mkSpillInstr reg delta slot
256 = let off = spillSlotToOffset slot
258 let sz = case regClass reg of
261 in ST sz reg (AddrRegImm sp (ImmInt (off-delta)))
265 :: Reg -- register to load
266 -> Int -- current stack delta
267 -> Int -- spill slot to use
269 mkLoadInstr reg delta slot
270 = let off = spillSlotToOffset slot
272 let sz = case regClass reg of
275 in LD sz reg (AddrRegImm sp (ImmInt (off-delta)))
282 mkRegRegMoveInstr src dst
290 mkBranchInstr id = [BCC ALWAYS id]
298 maxSpillSlots = ((rESERVED_C_STACK_BYTES - 64) `div` spillSlotSize) - 1
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
308 = pprPanic "spillSlotToOffset:"
309 ( text "invalid spill location: " <> int slot
310 $$ text "maxSpillSlots: " <> int maxSpillSlots)