2 -----------------------------------------------------------------------------
4 -- Machine-specific parts of the register allocator
6 -- (c) The University of Glasgow 1996-2004
8 -----------------------------------------------------------------------------
10 module SPARC.RegInfo (
38 #include "nativeGen/NCG.h"
39 #include "HsVersions.h"
47 import Constants ( rESERVED_C_STACK_BYTES )
51 -- -----------------------------------------------------------------------------
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,
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.
67 data RegUsage = RU [Reg] [Reg]
72 regUsage :: Instr -> RegUsage
74 regUsage instr = case instr of
75 SPILL reg _ -> usage ([reg], [])
76 RELOAD _ reg -> usage ([], [reg])
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])
109 JMP addr -> usage (regAddr addr, [])
110 JMP_TBL addr _ -> usage (regAddr addr, [])
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)
119 usage (src, dst) = RU (filter interesting src)
120 (filter interesting dst)
122 regAddr (AddrRegReg r1 r2) = [r1, r2]
123 regAddr (AddrRegImm r1 _) = [r1]
125 regRI (RIReg r) = [r]
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)
137 -- -----------------------------------------------------------------------------
138 -- 'patchRegs' function
140 -- 'patchRegs' takes an instruction and applies the given mapping to
141 -- all the register references.
143 patchRegs :: Instr -> (Reg -> Reg) -> Instr
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)
179 JMP addr -> JMP (fixAddr addr)
180 JMP_TBL addr ids -> JMP_TBL (fixAddr addr) ids
182 CALL (Left i) n t -> CALL (Left i) n t
183 CALL (Right r) n t -> CALL (Right (env r)) n t
186 fixAddr (AddrRegReg r1 r2) = AddrRegReg (env r1) (env r2)
187 fixAddr (AddrRegImm r1 i) = AddrRegImm (env r1) i
189 fixRI (RIReg r) = RIReg (env r)
193 -- -----------------------------------------------------------------------------
194 -- Determine the possible destinations from the current instruction.
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
200 jumpDests :: Instr -> [BlockId] -> [BlockId]
203 BI _ _ id -> id : acc
204 BF _ _ id -> id : acc
205 JMP_TBL _ ids -> ids ++ acc
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.
213 isJumpish :: Instr -> Bool
224 -- | Change the destination of this jump instruction
225 -- Used in joinToTargets in the linear allocator, when emitting fixup code
227 patchJump :: Instr -> BlockId -> BlockId -> Instr
228 patchJump insn old new
231 | id == old -> BI cc annul new
234 | id == old -> BF cc annul new
239 -- -----------------------------------------------------------------------------
240 -- Detecting reg->reg moves
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.
245 isRegRegMove :: Instr -> Maybe (Reg,Reg)
248 ADD False False src (RIReg src2) dst
249 | g0 == src2 -> Just (src, dst)
251 FMOV FF64 src dst -> Just (src, dst)
252 FMOV FF32 src dst -> Just (src, dst)
256 data JumpDest = DestBlockId BlockId | DestImm Imm
258 canShortcut :: Instr -> Maybe JumpDest
259 canShortcut _ = Nothing
261 shortcutJump :: (BlockId -> Maybe JumpDest) -> Instr -> Instr
262 shortcutJump _ other = other
267 -- -----------------------------------------------------------------------------
268 -- Generating spill instructions
270 -- SPARC: spill below frame pointer leaving 2 words/spill
272 :: Reg -- register to spill
273 -> Int -- current stack delta
274 -> Int -- spill slot to use
277 mkSpillInstr reg _ slot
278 = let off = spillSlotToOffset slot
279 off_w = 1 + (off `div` 4)
280 sz = case regClass reg of
285 in ST sz reg (fpRel (negate off_w))
289 :: Reg -- register to load
290 -> Int -- current stack delta
291 -> Int -- spill slot to use
294 mkLoadInstr reg _ slot
295 = let off = spillSlotToOffset slot
296 in let{off_w = 1 + (off `div` 4);
297 sz = case regClass reg of {
301 in LD sz (fpRel (- off_w)) reg
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
319 mkBranchInstr id = [BI ALWAYS False id, NOP]
326 maxSpillSlots = ((rESERVED_C_STACK_BYTES - 64) `div` spillSlotSize) - 1
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
338 = pprPanic "spillSlotToOffset:"
339 ( text "invalid spill location: " <> int slot
340 $$ text "maxSpillSlots: " <> int maxSpillSlots)