2 % (c) The AQUA Project, Glasgow University, 1993-1995
6 #include "HsVersions.h"
7 #include "../../includes/platform.h"
8 #include "../../includes/GhcConstants.h"
11 FutureLive(..), RegLiveness(..), RegUsage(..), Reg(..),
12 MachineRegisters(..), MachineCode(..),
14 mkReg, runRegAllocate, runHairyRegAllocate,
17 -- And, for self-sufficiency
18 CLabel, OrdList, PrimKind, UniqSet(..), UniqFM,
24 import CLabelInfo ( CLabel )
27 import Maybes ( maybeToBool, Maybe(..) )
28 import OrdList -- ( mkUnitList, mkSeqList, mkParList, OrdList )
31 import PrimKind ( PrimKind(..) )
36 #if ! OMIT_NATIVE_CODEGEN
38 # if alpha_TARGET_ARCH
39 import AlphaCode -- ( AlphaInstr, AlphaRegs ) -- for specializing
42 runRegAllocate :: AlphaRegs -> [Int] -> (OrdList AlphaInstr) -> [AlphaInstr]
47 import I386Code -- ( I386Instr, I386Regs ) -- for specializing
50 runRegAllocate :: I386Regs -> [Int] -> (OrdList I386Instr) -> [I386Instr]
54 # if sparc_TARGET_ARCH
55 import SparcCode -- ( SparcInstr, SparcRegs ) -- for specializing
58 runRegAllocate :: SparcRegs -> [Int] -> (OrdList SparcInstr) -> [SparcInstr]
66 %************************************************************************
68 \subsection[Reg]{Real registers}
70 %************************************************************************
72 Static Registers correspond to actual machine registers. These should
73 be avoided until the last possible moment.
75 Dynamic registers are allocated on the fly, usually to represent a single
76 value in the abstract assembly code (i.e. dynamic registers are usually
77 single assignment). Ultimately, they are mapped to available machine
78 registers before spitting out the code.
82 data Reg = FixedReg FAST_INT -- A pre-allocated machine register
84 | MappedReg FAST_INT -- A dynamically allocated machine register
86 | MemoryReg Int PrimKind -- A machine "register" actually held in a memory
87 -- allocated table of registers which didn't fit
90 | UnmappedReg Unique PrimKind -- One of an infinite supply of registers,
91 -- always mapped to one of the earlier two
93 -- No thanks: deriving (Eq)
95 mkReg :: Unique -> PrimKind -> Reg
98 instance Text Reg where
99 showsPrec _ (FixedReg i) = showString "%" . shows IBOX(i)
100 showsPrec _ (MappedReg i) = showString "%" . shows IBOX(i)
101 showsPrec _ (MemoryReg i _) = showString "%M" . shows i
102 showsPrec _ (UnmappedReg i _) = showString "%U" . shows i
105 instance Outputable Reg where
106 ppr sty r = ppStr (show r)
109 cmpReg (FixedReg i) (FixedReg i') = cmp_ihash i i'
110 cmpReg (MappedReg i) (MappedReg i') = cmp_ihash i i'
111 cmpReg (MemoryReg i _) (MemoryReg i' _) = cmp_i i i'
112 cmpReg (UnmappedReg u _) (UnmappedReg u' _) = cmpUnique u u'
117 if tag1 _LT_ tag2 then LT_ else GT_
119 tagReg (FixedReg _) = (ILIT(1) :: FAST_INT)
120 tagReg (MappedReg _) = ILIT(2)
121 tagReg (MemoryReg _ _) = ILIT(3)
122 tagReg (UnmappedReg _ _) = ILIT(4)
124 cmp_i :: Int -> Int -> TAG_
125 cmp_i a1 a2 = if a1 == a2 then EQ_ else if a1 < a2 then LT_ else GT_
127 cmp_ihash :: FAST_INT -> FAST_INT -> TAG_
128 cmp_ihash a1 a2 = if a1 _EQ_ a2 then EQ_ else if a1 _LT_ a2 then LT_ else GT_
130 instance Eq Reg where
131 a == b = case cmpReg a b of { EQ_ -> True; _ -> False }
132 a /= b = case cmpReg a b of { EQ_ -> False; _ -> True }
134 instance Ord Reg where
135 a <= b = case cmpReg a b of { LT_ -> True; EQ_ -> True; GT__ -> False }
136 a < b = case cmpReg a b of { LT_ -> True; EQ_ -> False; GT__ -> False }
137 a >= b = case cmpReg a b of { LT_ -> False; EQ_ -> True; GT__ -> True }
138 a > b = case cmpReg a b of { LT_ -> False; EQ_ -> False; GT__ -> True }
139 #ifdef __GLASGOW_HASKELL__
140 _tagCmp a b = case cmpReg a b of { LT_ -> _LT; EQ_ -> _EQ; GT__ -> _GT }
143 instance NamedThing Reg where
144 -- the *only* method that should be defined is "getTheUnique"!
145 -- (so we can use UniqFMs/UniqSets on Regs
146 getTheUnique (UnmappedReg u _) = u
147 getTheUnique (FixedReg i) = mkPseudoUnique1 IBOX(i)
148 getTheUnique (MappedReg i) = mkPseudoUnique2 IBOX(i)
149 getTheUnique (MemoryReg i _) = mkPseudoUnique3 i
152 This is the generic register allocator.
154 %************************************************************************
156 \subsection[RegPlace]{Map Stix registers to {\em real} registers}
158 %************************************************************************
160 An important point: The @regUsage@ function for a particular assembly language
161 must not refer to fixed registers, such as Hp, SpA, etc. The source and destination
162 lists should only refer to dynamically allocated registers or static registers
163 from the free list. As far as we are concerned, the fixed registers simply don't
164 exist (for allocation purposes, anyway).
168 class MachineRegisters a where
169 mkMRegs :: [Int] -> a
170 possibleMRegs :: PrimKind -> a -> [Int]
171 useMReg :: a -> FAST_INT -> a
172 useMRegs :: a -> [Int] -> a
173 freeMReg :: a -> FAST_INT -> a
174 freeMRegs :: a -> [Int] -> a
176 type RegAssignment = FiniteMap Reg Reg
177 type RegConflicts = FiniteMap Int (UniqSet Reg)
181 (FiniteMap CLabel (UniqSet Reg))
190 = RF (UniqSet Reg) -- in use
195 = RI (UniqSet Reg) -- in use
196 (UniqSet Reg) -- sources
197 (UniqSet Reg) -- destinations
209 class MachineCode a where
211 -- flatten :: OrdList a -> [a]
212 regUsage :: a -> RegUsage
213 regLiveness :: a -> RegLiveness -> RegLiveness
214 patchRegs :: a -> (Reg -> Reg) -> a
215 spillReg :: Reg -> Reg -> OrdList a
216 loadReg :: Reg -> Reg -> OrdList a
220 First we try something extremely simple.
221 If that fails, we have to do things the hard way.
226 :: (MachineRegisters a, MachineCode b)
232 runRegAllocate regs reserve_regs instrs =
235 Nothing -> hairyAlloc
237 flatInstrs = flattenOrdList instrs
238 simpleAlloc = simpleRegAlloc regs [] emptyFM flatInstrs
239 hairyAlloc = hairyRegAlloc regs reserve_regs flatInstrs
241 runHairyRegAllocate -- use only hairy for i386!
242 :: (MachineRegisters a, MachineCode b)
248 runHairyRegAllocate regs reserve_regs instrs
249 = hairyRegAlloc regs reserve_regs flatInstrs
251 flatInstrs = flattenOrdList instrs
254 Here is the simple register allocator. Just dole out registers until
255 we run out, or until one gets clobbered before its last use. Don't
256 do anything fancy with branches. Just pretend that you've got a block
257 of straight-line code and hope for the best. Experience indicates that
258 this approach will suffice for about 96 percent of the code blocks that
264 :: (MachineRegisters a, MachineCode b)
265 => a -- registers to select from
266 -> [Reg] -- live static registers
267 -> RegAssignment -- mapping of dynamics to statics
271 simpleRegAlloc _ _ _ [] = Just []
272 simpleRegAlloc free live env (instr:instrs) =
273 if null deadSrcs && maybeToBool newAlloc && maybeToBool instrs2 then
274 Just (instr3 : instrs3)
278 instr3 = patchRegs instr (lookup env2)
280 (srcs, dsts) = case regUsage instr of { RU s d -> (uniqSetToList s, uniqSetToList d) }
282 lookup env x = case lookupFM env x of {Just y -> y; Nothing -> x}
284 deadSrcs = [r | r@(UnmappedReg _ _) <- srcs, lookup env r `not_elem` live]
285 newDsts = [r | r@(UnmappedReg _ _) <- dsts, r `not_elem` keysFM env]
287 newAlloc = foldr allocateNewReg (Just (free, [])) newDsts
288 (free2, new) = case newAlloc of Just x -> x
290 env2 = env `addListToFM` new
292 live2 = map snd new ++ [x | x <- live, x `not_elem` dsts]
294 instrs2 = simpleRegAlloc free2 live2 env2 instrs
295 instrs3 = case instrs2 of Just x -> x
298 :: MachineRegisters a
300 -> Maybe (a, [(Reg, Reg)])
301 -> Maybe (a, [(Reg, Reg)])
303 allocateNewReg _ Nothing = Nothing
305 allocateNewReg d@(UnmappedReg _ pk) (Just (free, prs)) =
306 if null choices then Nothing
307 else Just (free2, prs2)
309 choices = possibleMRegs pk free
311 free2 = free `useMReg` (case reg of {IBOX(reg2) -> reg2} )
312 prs2 = ((d, MappedReg (case reg of {IBOX(reg2) -> reg2})) : prs)
316 Here is the ``clever'' bit. First go backward (i.e. left), looking for
317 the last use of dynamic registers. Then go forward (i.e. right), filling
318 registers with static placements.
323 :: (MachineRegisters a, MachineCode b)
329 hairyRegAlloc regs reserve_regs instrs =
330 case mapAccumB (doRegAlloc reserve_regs)
331 (RH regs' 1 emptyFM) noFuture instrs
332 of (RH _ loc' _, _, instrs') ->
333 if loc' == 1 then instrs' else
334 case mapAccumB do_RegAlloc_Nil
335 (RH regs'' loc' emptyFM) noFuture (flattenOrdList (patchMem instrs'))
336 of ((RH _ loc'' _),_,instrs'') ->
337 if loc'' == loc' then instrs'' else panic "runRegAllocate"
339 regs' = regs `useMRegs` reserve_regs
340 regs'' = mkMRegs reserve_regs `asTypeOf` regs
342 do_RegAlloc_Nil = doRegAlloc [] -- out here to avoid CAF (sigh)
344 :: (MachineRegisters a, MachineCode b)
348 -> (RegHistory a, RegFuture, b)
350 noFuture :: RegFuture
351 noFuture = RF emptyUniqSet (FL emptyUniqSet emptyFM) emptyFM
354 Here we patch instructions that reference ``registers'' which are really in
355 memory somewhere (the mapping is under the control of the machine-specific
356 code generator). We place the appropriate load sequences before any instructions
357 that use memory registers as sources, and we place the appropriate spill sequences
358 after any instructions that use memory registers as destinations. The offending
359 instructions are rewritten with new dynamic registers, so we have to run register
360 allocation again after all of this is said and done.
369 patchMem cs = foldr (mkSeqList . patchMem') mkEmptyList cs
377 if null memSrcs && null memDsts then mkUnitList instr
379 (foldr mkParList mkEmptyList loadSrcs)
381 (foldr mkParList mkEmptyList spillDsts))
384 (RU srcs dsts) = regUsage instr
386 memToDyn (MemoryReg i pk) = UnmappedReg (mkBuiltinUnique i) pk
387 memToDyn other = other
389 memSrcs = [ r | r@(MemoryReg _ _) <- uniqSetToList srcs]
390 memDsts = [ r | r@(MemoryReg _ _) <- uniqSetToList dsts]
392 loadSrcs = map load memSrcs
393 spillDsts = map spill memDsts
395 load mem = loadReg mem (memToDyn mem)
396 spill mem = spillReg (memToDyn mem) mem
398 instr' = mkUnitList (patchRegs instr memToDyn)
405 :: (MachineRegisters a, MachineCode b)
410 -> (RegHistory a, RegFuture, b)
412 doRegAlloc reserved_regs free_env in_use instr = (free_env', in_use', instr')
414 (free_env', instr') = doRegAlloc' reserved_regs free_env info instr
415 (in_use', info) = getUsage in_use instr
425 -> (RegFuture, RegInfo a)
427 getUsage (RF next_in_use future reg_conflicts) instr =
428 (RF in_use' future' reg_conflicts',
429 RI in_use' srcs dsts last_used reg_conflicts')
430 where (RU srcs dsts) = regUsage instr
431 (RL in_use future') = regLiveness instr (RL next_in_use future)
432 live_through = in_use `minusUniqSet` dsts
433 last_used = [ r | r <- uniqSetToList srcs,
434 not (r `elementOfUniqSet` (fstFL future) || r `elementOfUniqSet` in_use)]
435 in_use' = srcs `unionUniqSets` live_through
436 reg_conflicts' = case new_conflicts of
438 _ -> addListToFM reg_conflicts new_conflicts
439 new_conflicts = if isEmptyUniqSet live_dynamics then []
440 else [ (r, merge_conflicts r)
441 | r <- extractMappedRegNos (uniqSetToList dsts) ]
442 merge_conflicts reg = case lookupFM reg_conflicts reg of
443 Nothing -> live_dynamics
444 Just conflicts -> conflicts `unionUniqSets` live_dynamics
445 live_dynamics = mkUniqSet
446 [ r | r@(UnmappedReg _ _) <- uniqSetToList live_through ]
449 :: (MachineRegisters a, MachineCode b)
456 doRegAlloc' reserved (RH frs loc env) (RI in_use srcs dsts lastu conflicts) instr =
458 (RH frs'' loc' env'', patchRegs instr dynToStatic)
462 -- free up new registers
464 free = extractMappedRegNos (map dynToStatic lastu)
466 -- (1) free registers that are used last as source operands in this instruction
467 frs_not_in_use = frs `useMRegs` (extractMappedRegNos (uniqSetToList in_use))
468 frs' = (frs_not_in_use `freeMRegs` free) `useMRegs` reserved
470 -- (2) allocate new registers for the destination operands
471 -- allocate registers for new dynamics
473 new_dynamix = [ r | r@(UnmappedReg _ _) <- uniqSetToList dsts, r `not_elem` keysFM env ]
475 (frs'', loc', new) = foldr allocateNewRegs (frs', loc, []) new_dynamix
477 env' = addListToFM env new
479 env'' = delListFromFM env' lastu
481 dynToStatic :: Reg -> Reg
482 dynToStatic dyn@(UnmappedReg _ _) =
483 case lookupFM env' dyn of
485 Nothing -> trace "Lost register; possibly a floating point type error in a _ccall_?" dyn
486 dynToStatic other = other
489 :: MachineRegisters a
490 => Reg -> (a, Int, [(Reg, Reg)]) -> (a, Int, [(Reg, Reg)])
492 allocateNewRegs d@(UnmappedReg _ pk) (fs, mem, lst) = (fs', mem', (d, f) : lst)
493 where (fs', f, mem') = case acceptable fs of
494 [] -> (fs, MemoryReg mem pk, mem + 1)
495 (IBOX(x2):_) -> (fs `useMReg` x2, MappedReg x2, mem)
497 acceptable regs = filter no_conflict (possibleMRegs pk regs)
498 no_conflict reg = case lookupFM conflicts reg of
500 Just conflicts -> not (d `elementOfUniqSet` conflicts)
504 extractMappedRegNos :: [Reg] -> [Int]
506 extractMappedRegNos regs
509 ex (MappedReg i) acc = IBOX(i) : acc -- we'll take it
510 ex _ acc = acc -- leave it out
513 We keep a local copy of the Prelude function \tr{notElem},
514 so that it can be specialised. (Hack me gently. [WDP 94/11])
517 not_elem x (y:ys) = x /= y && not_elem x ys