Fixed linear regalloc bug, dropped some tracing code
[ghc-hetmet.git] / compiler / nativeGen / RegAllocLinear.hs
1 {-# OPTIONS -fno-warn-missing-signatures #-}
2 -----------------------------------------------------------------------------
3 --
4 -- The register allocator
5 --
6 -- (c) The University of Glasgow 2004
7 --
8 -----------------------------------------------------------------------------
9
10 {-
11 The algorithm is roughly:
12  
13   1) Compute strongly connected components of the basic block list.
14
15   2) Compute liveness (mapping from pseudo register to
16      point(s) of death?).
17
18   3) Walk instructions in each basic block.  We keep track of
19         (a) Free real registers (a bitmap?)
20         (b) Current assignment of temporaries to machine registers and/or
21             spill slots (call this the "assignment").
22         (c) Partial mapping from basic block ids to a virt-to-loc mapping.
23             When we first encounter a branch to a basic block,
24             we fill in its entry in this table with the current mapping.
25
26      For each instruction:
27         (a) For each real register clobbered by this instruction:
28             If a temporary resides in it,
29                 If the temporary is live after this instruction,
30                     Move the temporary to another (non-clobbered & free) reg,
31                     or spill it to memory.  Mark the temporary as residing
32                     in both memory and a register if it was spilled (it might
33                     need to be read by this instruction).
34             (ToDo: this is wrong for jump instructions?)
35
36         (b) For each temporary *read* by the instruction:
37             If the temporary does not have a real register allocation:
38                 - Allocate a real register from the free list.  If
39                   the list is empty:
40                   - Find a temporary to spill.  Pick one that is
41                     not used in this instruction (ToDo: not
42                     used for a while...)
43                   - generate a spill instruction
44                 - If the temporary was previously spilled,
45                   generate an instruction to read the temp from its spill loc.
46             (optimisation: if we can see that a real register is going to
47             be used soon, then don't use it for allocation).
48
49         (c) Update the current assignment
50
51         (d) If the intstruction is a branch:
52               if the destination block already has a register assignment,
53                 Generate a new block with fixup code and redirect the
54                 jump to the new block.
55               else,
56                 Update the block id->assignment mapping with the current
57                 assignment.
58
59         (e) Delete all register assignments for temps which are read
60             (only) and die here.  Update the free register list.
61
62         (f) Mark all registers clobbered by this instruction as not free,
63             and mark temporaries which have been spilled due to clobbering
64             as in memory (step (a) marks then as in both mem & reg).
65
66         (g) For each temporary *written* by this instruction:
67             Allocate a real register as for (b), spilling something
68             else if necessary.
69                 - except when updating the assignment, drop any memory
70                   locations that the temporary was previously in, since
71                   they will be no longer valid after this instruction.
72
73         (h) Delete all register assignments for temps which are
74             written and die here (there should rarely be any).  Update
75             the free register list.
76
77         (i) Rewrite the instruction with the new mapping.
78
79         (j) For each spilled reg known to be now dead, re-add its stack slot
80             to the free list.
81
82 -}
83
84 module RegAllocLinear (
85         regAlloc,
86         RegAllocStats, pprStats
87   ) where
88
89 #include "HsVersions.h"
90
91 import BlockId
92 import MachRegs
93 import MachInstrs
94 import RegAllocInfo
95 import RegLiveness
96 import Cmm hiding (RegSet)
97
98 import Digraph
99 import Unique           ( Uniquable(getUnique), Unique )
100 import UniqSet
101 import UniqFM
102 import UniqSupply
103 import Outputable
104 import State
105 import FastString
106
107 import Data.Maybe
108 import Data.List
109 import Control.Monad
110 import Data.Word
111 import Data.Bits
112
113
114 -- -----------------------------------------------------------------------------
115 -- The free register set
116
117 -- This needs to be *efficient*
118
119 {- Here's an inefficient 'executable specification' of the FreeRegs data type:
120 type FreeRegs = [RegNo]
121
122 noFreeRegs = 0
123 releaseReg n f = if n `elem` f then f else (n : f)
124 initFreeRegs = allocatableRegs
125 getFreeRegs cls f = filter ( (==cls) . regClass . RealReg ) f
126 allocateReg f r = filter (/= r) f
127 -}
128
129 #if defined(powerpc_TARGET_ARCH)
130
131 -- The PowerPC has 32 integer and 32 floating point registers.
132 -- This is 32bit PowerPC, so Word64 is inefficient - two Word32s are much
133 -- better.
134 -- Note that when getFreeRegs scans for free registers, it starts at register
135 -- 31 and counts down. This is a hack for the PowerPC - the higher-numbered
136 -- registers are callee-saves, while the lower regs are caller-saves, so it
137 -- makes sense to start at the high end.
138 -- Apart from that, the code does nothing PowerPC-specific, so feel free to
139 -- add your favourite platform to the #if (if you have 64 registers but only
140 -- 32-bit words).
141
142 data FreeRegs = FreeRegs !Word32 !Word32
143               deriving( Show )  -- The Show is used in an ASSERT
144
145 noFreeRegs :: FreeRegs
146 noFreeRegs = FreeRegs 0 0
147
148 releaseReg :: RegNo -> FreeRegs -> FreeRegs
149 releaseReg r (FreeRegs g f)
150     | r > 31    = FreeRegs g (f .|. (1 `shiftL` (fromIntegral r - 32)))
151     | otherwise = FreeRegs (g .|. (1 `shiftL` fromIntegral r)) f
152     
153 initFreeRegs :: FreeRegs
154 initFreeRegs = foldr releaseReg noFreeRegs allocatableRegs
155
156 getFreeRegs :: RegClass -> FreeRegs -> [RegNo]  -- lazilly
157 getFreeRegs cls (FreeRegs g f)
158     | RcDouble <- cls = go f (0x80000000) 63
159     | RcInteger <- cls = go g (0x80000000) 31
160     | otherwise = pprPanic "RegAllocLinear.getFreeRegs: Bad cls" (ppr cls)
161     where
162         go _ 0 _ = []
163         go x m i | x .&. m /= 0 = i : (go x (m `shiftR` 1) $! i-1)
164                  | otherwise    = go x (m `shiftR` 1) $! i-1
165
166 allocateReg :: RegNo -> FreeRegs -> FreeRegs
167 allocateReg r (FreeRegs g f) 
168     | r > 31    = FreeRegs g (f .&. complement (1 `shiftL` (fromIntegral r - 32)))
169     | otherwise = FreeRegs (g .&. complement (1 `shiftL` fromIntegral r)) f
170
171 #else
172
173 -- If we have less than 32 registers, or if we have efficient 64-bit words,
174 -- we will just use a single bitfield.
175
176 #if defined(alpha_TARGET_ARCH)
177 type FreeRegs = Word64
178 #else
179 type FreeRegs = Word32
180 #endif
181
182 noFreeRegs :: FreeRegs
183 noFreeRegs = 0
184
185 releaseReg :: RegNo -> FreeRegs -> FreeRegs
186 releaseReg n f = f .|. (1 `shiftL` n)
187
188 initFreeRegs :: FreeRegs
189 initFreeRegs = foldr releaseReg noFreeRegs allocatableRegs
190
191 getFreeRegs :: RegClass -> FreeRegs -> [RegNo]  -- lazilly
192 getFreeRegs cls f = go f 0
193   where go 0 _ = []
194         go n m 
195           | n .&. 1 /= 0 && regClass (RealReg m) == cls
196           = m : (go (n `shiftR` 1) $! (m+1))
197           | otherwise
198           = go (n `shiftR` 1) $! (m+1)
199         -- ToDo: there's no point looking through all the integer registers
200         -- in order to find a floating-point one.
201
202 allocateReg :: RegNo -> FreeRegs -> FreeRegs
203 allocateReg r f = f .&. complement (1 `shiftL` fromIntegral r)
204
205 #endif
206
207 -- -----------------------------------------------------------------------------
208 -- The assignment of virtual registers to stack slots
209
210 -- We have lots of stack slots. Memory-to-memory moves are a pain on most
211 -- architectures. Therefore, we avoid having to generate memory-to-memory moves
212 -- by simply giving every virtual register its own stack slot.
213
214 -- The StackMap stack map keeps track of virtual register - stack slot
215 -- associations and of which stack slots are still free. Once it has been
216 -- associated, a stack slot is never "freed" or removed from the StackMap again,
217 -- it remains associated until we are done with the current CmmProc.
218
219 type StackSlot = Int
220 data StackMap = StackMap [StackSlot] (UniqFM StackSlot)
221
222 emptyStackMap :: StackMap
223 emptyStackMap = StackMap [0..maxSpillSlots] emptyUFM
224
225 getStackSlotFor :: StackMap -> Unique -> (StackMap,Int)
226 getStackSlotFor (StackMap [] _) _
227         = panic "RegAllocLinear.getStackSlotFor: out of stack slots, try -fregs-graph"
228         -- This happens with darcs' SHA1.hs, see #1993
229
230 getStackSlotFor fs@(StackMap (freeSlot:stack') reserved) reg =
231     case lookupUFM reserved reg of
232         Just slot -> (fs,slot)
233         Nothing -> (StackMap stack' (addToUFM reserved reg freeSlot), freeSlot)
234
235 -- -----------------------------------------------------------------------------
236 -- Top level of the register allocator
237
238 -- Allocate registers
239 regAlloc 
240         :: LiveCmmTop
241         -> UniqSM (NatCmmTop, Maybe RegAllocStats)
242
243 regAlloc (CmmData sec d) 
244         = return
245                 ( CmmData sec d
246                 , Nothing )
247         
248 regAlloc (CmmProc (LiveInfo info _ _) lbl params (ListGraph []))
249         = return ( CmmProc info lbl params (ListGraph [])
250                  , Nothing )
251         
252 regAlloc (CmmProc static lbl params (ListGraph comps))
253         | LiveInfo info (Just first_id) block_live      <- static
254         = do    
255                 -- do register allocation on each component.
256                 (final_blocks, stats)
257                         <- linearRegAlloc first_id block_live 
258                         $ map (\b -> case b of 
259                                         BasicBlock _ [b]        -> AcyclicSCC b
260                                         BasicBlock _ bs         -> CyclicSCC  bs)
261                         $ comps
262
263                 -- make sure the block that was first in the input list
264                 --      stays at the front of the output
265                 let ((first':_), rest')
266                                 = partition ((== first_id) . blockId) final_blocks
267
268                 return  ( CmmProc info lbl params (ListGraph (first' : rest'))
269                         , Just stats)
270         
271 -- bogus. to make non-exhaustive match warning go away.
272 regAlloc (CmmProc _ _ _ _)
273         = panic "RegAllocLinear.regAlloc: no match"
274
275
276 -- -----------------------------------------------------------------------------
277 -- Linear sweep to allocate registers
278
279 data Loc = InReg   {-# UNPACK #-} !RegNo
280          | InMem   {-# UNPACK #-} !Int          -- stack slot
281          | InBoth  {-# UNPACK #-} !RegNo
282                    {-# UNPACK #-} !Int          -- stack slot
283   deriving (Eq, Show, Ord)
284
285 {- 
286 A temporary can be marked as living in both a register and memory
287 (InBoth), for example if it was recently loaded from a spill location.
288 This makes it cheap to spill (no save instruction required), but we
289 have to be careful to turn this into InReg if the value in the
290 register is changed.
291
292 This is also useful when a temporary is about to be clobbered.  We
293 save it in a spill location, but mark it as InBoth because the current
294 instruction might still want to read it.
295 -}
296
297 instance Outputable Loc where
298   ppr l = text (show l)
299
300
301 -- | Do register allocation on some basic blocks.
302 --   But be careful to allocate a block in an SCC only if it has
303 --   an entry in the block map or it is the first block.
304 --
305 linearRegAlloc
306         :: BlockId                      -- ^ the first block
307         -> BlockMap RegSet              -- ^ live regs on entry to each basic block
308         -> [SCC LiveBasicBlock]         -- ^ instructions annotated with "deaths"
309         -> UniqSM ([NatBasicBlock], RegAllocStats)
310
311 linearRegAlloc first_id block_live sccs
312  = do   us      <- getUs
313         let (_, _, stats, blocks) =
314                 runR emptyBlockMap initFreeRegs emptyRegMap emptyStackMap us
315                         $ linearRA_SCCs first_id block_live [] sccs
316
317         return  (blocks, stats)
318
319 linearRA_SCCs _ _ blocksAcc []
320         = return $ reverse blocksAcc
321
322 linearRA_SCCs first_id block_live blocksAcc (AcyclicSCC block : sccs) 
323  = do   blocks' <- processBlock block_live block
324         linearRA_SCCs first_id block_live 
325                 ((reverse blocks') ++ blocksAcc)
326                 sccs
327
328 linearRA_SCCs first_id block_live blocksAcc (CyclicSCC blocks : sccs) 
329  = do   let process [] []         accum = return $ reverse accum
330             process [] next_round accum = process next_round [] accum
331             process (b@(BasicBlock id _) : blocks) next_round accum =
332               do block_assig <- getBlockAssigR
333                  if isJust (lookupBlockEnv block_assig id) || id == first_id
334                   then do b'  <- processBlock block_live b
335                           process blocks next_round (b' : accum)
336                   else process blocks (b : next_round) accum
337         blockss' <- process blocks [] (return [])
338         linearRA_SCCs first_id block_live
339                 (reverse (concat blockss') ++ blocksAcc)
340                 sccs
341                 
342
343 -- | Do register allocation on this basic block
344 --
345 processBlock
346         :: BlockMap RegSet              -- ^ live regs on entry to each basic block
347         -> LiveBasicBlock               -- ^ block to do register allocation on
348         -> RegM [NatBasicBlock]         -- ^ block with registers allocated
349
350 processBlock block_live (BasicBlock id instrs)
351  = do   initBlock id
352         (instrs', fixups)
353                 <- linearRA block_live [] [] instrs
354
355         return  $ BasicBlock id instrs' : fixups
356
357
358 -- | Load the freeregs and current reg assignment into the RegM state
359 --      for the basic block with this BlockId.
360 initBlock :: BlockId -> RegM ()
361 initBlock id
362  = do   block_assig     <- getBlockAssigR
363         case lookupBlockEnv block_assig id of
364                 -- no prior info about this block: assume everything is
365                 -- free and the assignment is empty.
366                 Nothing
367                  -> do  setFreeRegsR    initFreeRegs
368                         setAssigR       emptyRegMap
369
370                 -- load info about register assignments leading into this block.
371                 Just (freeregs, assig)
372                  -> do  setFreeRegsR    freeregs
373                         setAssigR       assig
374
375
376 linearRA
377         :: BlockMap RegSet
378         -> [Instr] -> [NatBasicBlock] -> [LiveInstr]
379         -> RegM ([Instr], [NatBasicBlock])
380
381 linearRA _          instr_acc fixups []
382         = return (reverse instr_acc, fixups)
383
384 linearRA block_live instr_acc fixups (instr:instrs)
385  = do   (instr_acc', new_fixups) <- raInsn block_live instr_acc instr
386         linearRA block_live instr_acc' (new_fixups++fixups) instrs
387
388 -- -----------------------------------------------------------------------------
389 -- Register allocation for a single instruction
390
391 type BlockAssignment = BlockMap (FreeRegs, RegMap Loc)
392
393 raInsn  :: BlockMap RegSet              -- Live temporaries at each basic block
394         -> [Instr]                      -- new instructions (accum.)
395         -> LiveInstr                    -- the instruction (with "deaths")
396         -> RegM (
397              [Instr],                   -- new instructions
398              [NatBasicBlock]            -- extra fixup blocks
399            )
400
401 raInsn _     new_instrs (Instr (COMMENT _) Nothing)
402  = return (new_instrs, [])
403
404 raInsn _     new_instrs (Instr (DELTA n) Nothing)  
405  = do
406     setDeltaR n
407     return (new_instrs, [])
408
409 raInsn block_live new_instrs (Instr instr (Just live))
410  = do
411     assig    <- getAssigR
412
413     -- If we have a reg->reg move between virtual registers, where the
414     -- src register is not live after this instruction, and the dst
415     -- register does not already have an assignment,
416     -- and the source register is assigned to a register, not to a spill slot,
417     -- then we can eliminate the instruction.
418     -- (we can't eliminitate it if the source register is on the stack, because
419     --  we do not want to use one spill slot for different virtual registers)
420     case isRegRegMove instr of
421         Just (src,dst)  | src `elementOfUniqSet` (liveDieRead live), 
422                           isVirtualReg dst,
423                           not (dst `elemUFM` assig),
424                           Just (InReg _) <- (lookupUFM assig src) -> do
425            case src of
426               RealReg i -> setAssigR (addToUFM assig dst (InReg i))
427                 -- if src is a fixed reg, then we just map dest to this
428                 -- reg in the assignment.  src must be an allocatable reg,
429                 -- otherwise it wouldn't be in r_dying.
430               _virt -> case lookupUFM assig src of
431                          Nothing -> panic "raInsn"
432                          Just loc ->
433                            setAssigR (addToUFM (delFromUFM assig src) dst loc)
434
435            -- we have elimianted this instruction
436            freeregs <- getFreeRegsR
437            assig <- getAssigR
438           {-
439           pprTrace "raInsn" (text "ELIMINATED: " <> docToSDoc (pprInstr instr) $$ ppr r_dying <+> ppr w_dying $$ text (show freeregs) $$ ppr assig) $ do
440           -}
441            return (new_instrs, [])
442
443         _ -> genRaInsn block_live new_instrs instr 
444                         (uniqSetToList $ liveDieRead live) 
445                         (uniqSetToList $ liveDieWrite live)
446
447
448 raInsn _ _ li
449         = pprPanic "raInsn" (text "no match for:" <> ppr li)
450
451
452 genRaInsn block_live new_instrs instr r_dying w_dying =
453     case regUsage instr              of { RU read written ->
454     case partition isRealReg written of { (real_written1,virt_written) ->
455     do
456     let 
457         real_written = [ r | RealReg r <- real_written1 ]
458
459         -- we don't need to do anything with real registers that are
460         -- only read by this instr.  (the list is typically ~2 elements,
461         -- so using nub isn't a problem).
462         virt_read = nub (filter isVirtualReg read)
463     -- in
464
465     -- (a) save any temporaries which will be clobbered by this instruction
466     clobber_saves <- saveClobberedTemps real_written r_dying
467
468     {-
469     freeregs <- getFreeRegsR
470     assig <- getAssigR
471     pprTrace "raInsn" (docToSDoc (pprInstr instr) $$ ppr r_dying <+> ppr w_dying $$ ppr virt_read <+> ppr virt_written $$ text (show freeregs) $$ ppr assig) $ do
472     -}
473
474     -- (b), (c) allocate real regs for all regs read by this instruction.
475     (r_spills, r_allocd) <- 
476         allocateRegsAndSpill True{-reading-} virt_read [] [] virt_read
477
478     -- (d) Update block map for new destinations
479     -- NB. do this before removing dead regs from the assignment, because
480     -- these dead regs might in fact be live in the jump targets (they're
481     -- only dead in the code that follows in the current basic block).
482     (fixup_blocks, adjusted_instr)
483         <- joinToTargets block_live [] instr (jumpDests instr [])
484
485     -- (e) Delete all register assignments for temps which are read
486     --     (only) and die here.  Update the free register list.
487     releaseRegs r_dying
488
489     -- (f) Mark regs which are clobbered as unallocatable
490     clobberRegs real_written
491
492     -- (g) Allocate registers for temporaries *written* (only)
493     (w_spills, w_allocd) <- 
494         allocateRegsAndSpill False{-writing-} virt_written [] [] virt_written
495
496     -- (h) Release registers for temps which are written here and not
497     -- used again.
498     releaseRegs w_dying
499
500     let
501         -- (i) Patch the instruction
502         patch_map = listToUFM   [ (t,RealReg r) | 
503                                   (t,r) <- zip virt_read r_allocd
504                                           ++ zip virt_written w_allocd ]
505
506         patched_instr = patchRegs adjusted_instr patchLookup
507         patchLookup x = case lookupUFM patch_map x of
508                                 Nothing -> x
509                                 Just y  -> y
510     -- in
511
512     -- pprTrace "patched" (docToSDoc (pprInstr patched_instr)) $ do
513
514     -- (j) free up stack slots for dead spilled regs
515     -- TODO (can't be bothered right now)
516
517     -- erase reg->reg moves where the source and destination are the same.
518     --  If the src temp didn't die in this instr but happened to be allocated
519     --  to the same real reg as the destination, then we can erase the move anyway.
520         squashed_instr  = case isRegRegMove patched_instr of
521                                 Just (src, dst)
522                                  | src == dst   -> []
523                                 _               -> [patched_instr]
524
525     return (squashed_instr ++ w_spills ++ reverse r_spills
526                  ++ clobber_saves ++ new_instrs,
527             fixup_blocks)
528   }}
529
530 -- -----------------------------------------------------------------------------
531 -- releaseRegs
532
533 releaseRegs regs = do
534   assig <- getAssigR
535   free <- getFreeRegsR
536   loop assig free regs 
537  where
538   loop _     free _ | free `seq` False = undefined
539   loop assig free [] = do setAssigR assig; setFreeRegsR free; return ()
540   loop assig free (RealReg r : rs) = loop assig (releaseReg r free) rs
541   loop assig free (r:rs) = 
542      case lookupUFM assig r of
543         Just (InBoth real _) -> loop (delFromUFM assig r) (releaseReg real free) rs
544         Just (InReg real) -> loop (delFromUFM assig r) (releaseReg real free) rs
545         _other            -> loop (delFromUFM assig r) free rs
546
547 -- -----------------------------------------------------------------------------
548 -- Clobber real registers
549
550 {-
551 For each temp in a register that is going to be clobbered:
552   - if the temp dies after this instruction, do nothing
553   - otherwise, put it somewhere safe (another reg if possible,
554     otherwise spill and record InBoth in the assignment).
555
556 for allocateRegs on the temps *read*,
557   - clobbered regs are allocatable.
558
559 for allocateRegs on the temps *written*, 
560   - clobbered regs are not allocatable.
561 -}
562
563 saveClobberedTemps
564    :: [RegNo]              -- real registers clobbered by this instruction
565    -> [Reg]                -- registers which are no longer live after this insn
566    -> RegM [Instr]         -- return: instructions to spill any temps that will
567                            -- be clobbered.
568
569 saveClobberedTemps [] _ = return [] -- common case
570 saveClobberedTemps clobbered dying =  do
571   assig <- getAssigR
572   let
573         to_spill  = [ (temp,reg) | (temp, InReg reg) <- ufmToList assig,
574                                    reg `elem` clobbered,
575                                    temp `notElem` map getUnique dying  ]
576   -- in
577   (instrs,assig') <- clobber assig [] to_spill
578   setAssigR assig'
579   return instrs
580  where
581   clobber assig instrs [] = return (instrs,assig)
582   clobber assig instrs ((temp,reg):rest)
583     = do
584         --ToDo: copy it to another register if possible
585         (spill,slot) <- spillR (RealReg reg) temp
586         recordSpill (SpillClobber temp)
587
588         let new_assign  = addToUFM assig temp (InBoth reg slot)
589         clobber new_assign (spill : COMMENT (fsLit "spill clobber") : instrs) rest
590
591 clobberRegs :: [RegNo] -> RegM ()
592 clobberRegs [] = return () -- common case
593 clobberRegs clobbered = do
594   freeregs <- getFreeRegsR
595   setFreeRegsR $! foldr allocateReg freeregs clobbered
596   assig <- getAssigR
597   setAssigR $! clobber assig (ufmToList assig)
598  where
599     -- if the temp was InReg and clobbered, then we will have
600     -- saved it in saveClobberedTemps above.  So the only case
601     -- we have to worry about here is InBoth.  Note that this
602     -- also catches temps which were loaded up during allocation
603     -- of read registers, not just those saved in saveClobberedTemps.
604   clobber assig [] = assig
605   clobber assig ((temp, InBoth reg slot) : rest)
606         | reg `elem` clobbered
607         = clobber (addToUFM assig temp (InMem slot)) rest
608   clobber assig (_:rest)
609         = clobber assig rest 
610
611 -- -----------------------------------------------------------------------------
612 -- allocateRegsAndSpill
613
614 -- This function does several things:
615 --   For each temporary referred to by this instruction,
616 --   we allocate a real register (spilling another temporary if necessary).
617 --   We load the temporary up from memory if necessary.
618 --   We also update the register assignment in the process, and
619 --   the list of free registers and free stack slots.
620
621 allocateRegsAndSpill
622         :: Bool                 -- True <=> reading (load up spilled regs)
623         -> [Reg]                -- don't push these out
624         -> [Instr]              -- spill insns
625         -> [RegNo]              -- real registers allocated (accum.)
626         -> [Reg]                -- temps to allocate
627         -> RegM ([Instr], [RegNo])
628
629 allocateRegsAndSpill _       _    spills alloc []
630   = return (spills,reverse alloc)
631
632 allocateRegsAndSpill reading keep spills alloc (r:rs) = do
633   assig <- getAssigR
634   case lookupUFM assig r of
635   -- case (1a): already in a register
636      Just (InReg my_reg) ->
637         allocateRegsAndSpill reading keep spills (my_reg:alloc) rs
638
639   -- case (1b): already in a register (and memory)
640   -- NB1. if we're writing this register, update its assignemnt to be
641   -- InReg, because the memory value is no longer valid.
642   -- NB2. This is why we must process written registers here, even if they
643   -- are also read by the same instruction.
644      Just (InBoth my_reg _) -> do
645         when (not reading) (setAssigR (addToUFM assig r (InReg my_reg)))
646         allocateRegsAndSpill reading keep spills (my_reg:alloc) rs
647
648   -- Not already in a register, so we need to find a free one...
649      loc -> do
650         freeregs <- getFreeRegsR
651
652         case getFreeRegs (regClass r) freeregs of
653
654         -- case (2): we have a free register
655           my_reg:_ -> do
656             spills'   <- loadTemp reading r loc my_reg spills
657             let new_loc 
658                  | Just (InMem slot) <- loc, reading = InBoth my_reg slot
659                  | otherwise                         = InReg my_reg
660             setAssigR (addToUFM assig r $! new_loc)
661             setFreeRegsR (allocateReg my_reg freeregs)
662             allocateRegsAndSpill reading keep spills' (my_reg:alloc) rs
663
664         -- case (3): we need to push something out to free up a register
665           [] -> do
666             let
667               keep' = map getUnique keep
668               candidates1 = [ (temp,reg,mem)
669                             | (temp, InBoth reg mem) <- ufmToList assig,
670                               temp `notElem` keep', regClass (RealReg reg) == regClass r ]
671               candidates2 = [ (temp,reg)
672                             | (temp, InReg reg) <- ufmToList assig,
673                               temp `notElem` keep', regClass (RealReg reg) == regClass r  ]
674             -- in
675             ASSERT2(not (null candidates1 && null candidates2), 
676                     text (show freeregs) <+> ppr r <+> ppr assig) do
677
678             case candidates1 of
679
680              -- we have a temporary that is in both register and mem,
681              -- just free up its register for use.
682              -- 
683              (temp,my_reg,slot):_ -> do
684                 spills' <- loadTemp reading r loc my_reg spills
685                 let     
686                   assig1  = addToUFM assig temp (InMem slot)
687                   assig2  = addToUFM assig1 r (InReg my_reg)
688                 -- in
689                 setAssigR assig2
690                 allocateRegsAndSpill reading keep spills' (my_reg:alloc) rs
691
692              -- otherwise, we need to spill a temporary that currently
693              -- resides in a register.
694
695
696              [] -> do
697
698                 -- TODO: plenty of room for optimisation in choosing which temp
699                 -- to spill.  We just pick the first one that isn't used in 
700                 -- the current instruction for now.
701
702                 let (temp_to_push_out, my_reg) = myHead "regalloc" candidates2
703
704                 (spill_insn, slot) <- spillR (RealReg my_reg) temp_to_push_out
705                 let spill_store  = (if reading then id else reverse)
706                                         [ COMMENT (fsLit "spill alloc") 
707                                         , spill_insn ]
708
709                 -- record that this temp was spilled
710                 recordSpill (SpillAlloc temp_to_push_out)
711
712                 -- update the register assignment
713                 let assig1  = addToUFM assig temp_to_push_out   (InMem slot)
714                 let assig2  = addToUFM assig1 r                 (InReg my_reg)
715                 setAssigR assig2
716
717                 -- if need be, load up a spilled temp into the reg we've just freed up.
718                 spills' <- loadTemp reading r loc my_reg spills
719
720                 allocateRegsAndSpill reading keep
721                         (spill_store ++ spills')
722                         (my_reg:alloc) rs
723
724
725 -- | Load up a spilled temporary if we need to.
726 loadTemp
727         :: Bool
728         -> Reg          -- the temp being loaded
729         -> Maybe Loc    -- the current location of this temp
730         -> RegNo        -- the hreg to load the temp into
731         -> [Instr]
732         -> RegM [Instr]
733
734 loadTemp True vreg (Just (InMem slot)) hreg spills
735  = do
736         insn <- loadR (RealReg hreg) slot
737         recordSpill (SpillLoad $ getUnique vreg)
738         return  $  COMMENT (fsLit "spill load") : insn : spills
739
740 loadTemp _ _ _ _ spills =
741    return spills
742
743
744 myHead s [] = panic s
745 myHead _ (x:_) = x
746
747 -- -----------------------------------------------------------------------------
748 -- Joining a jump instruction to its targets
749
750 -- The first time we encounter a jump to a particular basic block, we
751 -- record the assignment of temporaries.  The next time we encounter a
752 -- jump to the same block, we compare our current assignment to the
753 -- stored one.  They might be different if spilling has occrred in one
754 -- branch; so some fixup code will be required to match up the
755 -- assignments.
756
757 joinToTargets
758         :: BlockMap RegSet
759         -> [NatBasicBlock]
760         -> Instr
761         -> [BlockId]
762         -> RegM ([NatBasicBlock], Instr)
763
764 joinToTargets _          new_blocks instr []
765   = return (new_blocks, instr)
766
767 joinToTargets block_live new_blocks instr (dest:dests) = do
768   block_assig <- getBlockAssigR
769   assig <- getAssigR
770   let
771         -- adjust the assignment to remove any registers which are not
772         -- live on entry to the destination block.
773         adjusted_assig = filterUFM_Directly still_live assig
774
775         live_set = lookItUp "joinToTargets" block_live dest
776         still_live uniq _ = uniq `elemUniqSet_Directly` live_set
777
778         -- and free up those registers which are now free.
779         to_free =
780           [ r | (reg, loc) <- ufmToList assig, 
781                 not (elemUniqSet_Directly reg live_set), 
782                 r <- regsOfLoc loc ]
783
784         regsOfLoc (InReg r)    = [r]
785         regsOfLoc (InBoth r _) = [r]
786         regsOfLoc (InMem _)    = []
787   -- in
788   case lookupBlockEnv block_assig dest of
789         -- Nothing <=> this is the first time we jumped to this
790         -- block.
791         Nothing -> do
792           freeregs <- getFreeRegsR
793           let freeregs' = foldr releaseReg freeregs to_free 
794           setBlockAssigR (extendBlockEnv block_assig dest 
795                                 (freeregs',adjusted_assig))
796           joinToTargets block_live new_blocks instr dests
797
798         Just (_, dest_assig)
799
800            -- the assignments match
801            | ufmToList dest_assig == ufmToList adjusted_assig
802            -> joinToTargets block_live new_blocks instr dests
803
804            -- need fixup code
805            | otherwise
806            -> do
807                delta <- getDeltaR
808                
809                let graph = makeRegMovementGraph adjusted_assig dest_assig
810                let sccs  = stronglyConnCompFromEdgedVerticesR graph
811                fixUpInstrs <- mapM (handleComponent delta instr) sccs
812
813                block_id <- getUniqueR
814                let block = BasicBlock (BlockId block_id) $
815                        concat fixUpInstrs ++ mkBranchInstr dest
816
817                let instr' = patchJump instr dest (BlockId block_id)
818
819                joinToTargets block_live (block : new_blocks) instr' dests
820
821
822 -- | Construct a graph of register\/spill movements.
823 --
824 --      We cut some corners by
825 --      a) not handling cyclic components
826 --      b) not handling memory-to-memory moves.
827 --
828 --      Cyclic components seem to occur only very rarely,
829 --      and we don't need memory-to-memory moves because we
830 --      make sure that every temporary always gets its own
831 --      stack slot.
832
833 makeRegMovementGraph :: RegMap Loc -> RegMap Loc -> [(Unique, Loc, [Loc])]
834 makeRegMovementGraph adjusted_assig dest_assig
835  = let
836         mkNodes src vreg
837          = expandNode vreg src
838          $ lookupWithDefaultUFM_Directly
839                 dest_assig
840                 (panic "RegAllocLinear.makeRegMovementGraph")
841                 vreg
842
843    in   [ node  | (vreg, src) <- ufmToList adjusted_assig
844                 , node <- mkNodes src vreg ]
845
846 -- The InBoth handling is a little tricky here.  If
847 -- the destination is InBoth, then we must ensure that
848 -- the value ends up in both locations.  An InBoth
849 -- destination must conflict with an InReg or InMem
850 -- source, so we expand an InBoth destination as
851 -- necessary.  An InBoth source is slightly different:
852 -- we only care about the register that the source value
853 -- is in, so that we can move it to the destinations.
854
855 expandNode vreg loc@(InReg src) (InBoth dst mem)
856         | src == dst = [(vreg, loc, [InMem mem])]
857         | otherwise  = [(vreg, loc, [InReg dst, InMem mem])]
858
859 expandNode vreg loc@(InMem src) (InBoth dst mem)
860         | src == mem = [(vreg, loc, [InReg dst])]
861         | otherwise  = [(vreg, loc, [InReg dst, InMem mem])]
862
863 expandNode _        (InBoth _ src) (InMem dst)
864         | src == dst = [] -- guaranteed to be true
865
866 expandNode _        (InBoth src _) (InReg dst)
867         | src == dst = []
868
869 expandNode vreg     (InBoth src _) dst
870         = expandNode vreg (InReg src) dst
871
872 expandNode vreg src dst
873         | src == dst = []
874         | otherwise  = [(vreg, src, [dst])]
875
876
877 -- | Make a move instruction between these two locations so we
878 --      can join together allocations for different basic blocks.
879 --
880 makeMove :: Int -> Unique -> Loc -> Loc -> RegM Instr
881 makeMove _     vreg (InReg src) (InReg dst)
882  = do   recordSpill (SpillJoinRR vreg)
883         return  $ mkRegRegMoveInstr (RealReg src) (RealReg dst)
884
885 makeMove delta vreg (InMem src) (InReg dst)
886  = do   recordSpill (SpillJoinRM vreg)
887         return  $ mkLoadInstr (RealReg dst) delta src
888
889 makeMove delta vreg (InReg src) (InMem dst)
890  = do   recordSpill (SpillJoinRM vreg)
891         return  $ mkSpillInstr (RealReg src) delta dst
892
893 makeMove _     vreg src dst
894         = panic $ "makeMove " ++ show vreg ++ " (" ++ show src ++ ") ("
895                 ++ show dst ++ ")"
896                 ++ " (workaround: use -fviaC)"
897
898
899 -- we have eliminated any possibility of single-node cylces
900 -- in expandNode above.
901 handleComponent :: Int -> Instr -> SCC (Unique, Loc, [Loc]) -> RegM [Instr]
902 handleComponent delta _  (AcyclicSCC (vreg,src,dsts))
903          = mapM (makeMove delta vreg src) dsts
904
905 -- we can not have cycles that involve memory
906 -- locations as source nor as single destination
907 -- because memory locations (stack slots) are
908 -- allocated exclusively for a virtual register and
909 -- therefore can not require a fixup
910 handleComponent delta instr (CyclicSCC ((vreg, (InReg sreg),dsts):rest))
911  = do
912         spill_id <- getUniqueR
913         (_, slot)               <- spillR (RealReg sreg) spill_id
914         remainingFixUps         <- mapM (handleComponent delta instr) (stronglyConnCompFromEdgedVerticesR rest)
915         restoreAndFixInstr      <- getRestoreMoves dsts slot
916         return ([instr] ++ concat remainingFixUps ++ restoreAndFixInstr)
917
918         where
919         getRestoreMoves [r@(InReg reg), mem@(InMem _)] slot
920          = do
921                 restoreToReg    <- loadR (RealReg reg) slot
922                 moveInstr       <- makeMove delta vreg r mem
923                 return $ [COMMENT (fsLit "spill join move"), restoreToReg, moveInstr]
924
925         getRestoreMoves [InReg reg] slot
926                 = loadR (RealReg reg) slot >>= return . (:[])
927
928         getRestoreMoves [InMem _] _     = panic "getRestoreMoves can not handle memory only restores"
929         getRestoreMoves _ _             = panic "getRestoreMoves unknown case"
930
931
932 handleComponent _ _ (CyclicSCC _)
933  = panic "Register Allocator: handleComponent cyclic"
934
935
936
937 -- -----------------------------------------------------------------------------
938 -- The register allocator's monad.  
939
940 -- Here we keep all the state that the register allocator keeps track
941 -- of as it walks the instructions in a basic block.
942
943 data RA_State 
944   = RA_State {
945         ra_blockassig :: BlockAssignment,
946                 -- The current mapping from basic blocks to 
947                 -- the register assignments at the beginning of that block.
948         ra_freeregs   :: {-#UNPACK#-}!FreeRegs, -- free machine registers
949         ra_assig      :: RegMap Loc,    -- assignment of temps to locations
950         ra_delta      :: Int,           -- current stack delta
951         ra_stack      :: StackMap,      -- free stack slots for spilling
952         ra_us         :: UniqSupply,    -- unique supply for generating names
953                                         -- for fixup blocks.
954
955         -- Record why things were spilled, for -ddrop-asm-stats.
956         --      Just keep a list here instead of a map of regs -> reasons.
957         --      We don't want to slow down the allocator if we're not going to emit the stats.
958         ra_spills     :: [SpillReason]
959   }
960
961 newtype RegM a = RegM { unReg :: RA_State -> (# RA_State, a #) }
962
963
964 instance Monad RegM where
965   m >>= k   =  RegM $ \s -> case unReg m s of { (# s, a #) -> unReg (k a) s }
966   return a  =  RegM $ \s -> (# s, a #)
967
968 runR :: BlockAssignment -> FreeRegs -> RegMap Loc -> StackMap -> UniqSupply
969   -> RegM a -> (BlockAssignment, StackMap, RegAllocStats, a)
970 runR block_assig freeregs assig stack us thing =
971   case unReg thing (RA_State{ ra_blockassig=block_assig, ra_freeregs=freeregs,
972                         ra_assig=assig, ra_delta=0{-???-}, ra_stack=stack,
973                         ra_us = us, ra_spills = [] }) of
974         (# state'@RA_State{ ra_blockassig=block_assig, ra_stack=stack' }, returned_thing #)
975                 -> (block_assig, stack', makeRAStats state', returned_thing)
976
977 spillR :: Reg -> Unique -> RegM (Instr, Int)
978 spillR reg temp = RegM $ \ s@RA_State{ra_delta=delta, ra_stack=stack} ->
979   let (stack',slot) = getStackSlotFor stack temp
980       instr  = mkSpillInstr reg delta slot
981   in
982   (# s{ra_stack=stack'}, (instr,slot) #)
983
984 loadR :: Reg -> Int -> RegM Instr
985 loadR reg slot = RegM $ \ s@RA_State{ra_delta=delta} ->
986   (# s, mkLoadInstr reg delta slot #)
987
988 getFreeRegsR :: RegM FreeRegs
989 getFreeRegsR = RegM $ \ s@RA_State{ra_freeregs = freeregs} ->
990   (# s, freeregs #)
991
992 setFreeRegsR :: FreeRegs -> RegM ()
993 setFreeRegsR regs = RegM $ \ s ->
994   (# s{ra_freeregs = regs}, () #)
995
996 getAssigR :: RegM (RegMap Loc)
997 getAssigR = RegM $ \ s@RA_State{ra_assig = assig} ->
998   (# s, assig #)
999
1000 setAssigR :: RegMap Loc -> RegM ()
1001 setAssigR assig = RegM $ \ s ->
1002   (# s{ra_assig=assig}, () #)
1003
1004 getBlockAssigR :: RegM BlockAssignment
1005 getBlockAssigR = RegM $ \ s@RA_State{ra_blockassig = assig} ->
1006   (# s, assig #)
1007
1008 setBlockAssigR :: BlockAssignment -> RegM ()
1009 setBlockAssigR assig = RegM $ \ s ->
1010   (# s{ra_blockassig = assig}, () #)
1011
1012 setDeltaR :: Int -> RegM ()
1013 setDeltaR n = RegM $ \ s ->
1014   (# s{ra_delta = n}, () #)
1015
1016 getDeltaR :: RegM Int
1017 getDeltaR = RegM $ \s -> (# s, ra_delta s #)
1018
1019 getUniqueR :: RegM Unique
1020 getUniqueR = RegM $ \s ->
1021   case splitUniqSupply (ra_us s) of
1022     (us1, us2) -> (# s{ra_us = us2}, uniqFromSupply us1 #)
1023
1024 -- | Record that a spill instruction was inserted, for profiling.
1025 recordSpill :: SpillReason -> RegM ()
1026 recordSpill spill
1027         = RegM $ \s -> (# s { ra_spills = spill : ra_spills s}, () #)
1028
1029 -- -----------------------------------------------------------------------------
1030
1031 -- | Reasons why instructions might be inserted by the spiller.
1032 --      Used when generating stats for -ddrop-asm-stats.
1033 --
1034 data SpillReason
1035         = SpillAlloc    !Unique -- ^ vreg was spilled to a slot so we could use its
1036                                 --      current hreg for another vreg
1037         | SpillClobber  !Unique -- ^ vreg was moved because its hreg was clobbered
1038         | SpillLoad     !Unique -- ^ vreg was loaded from a spill slot
1039
1040         | SpillJoinRR   !Unique -- ^ reg-reg move inserted during join to targets
1041         | SpillJoinRM   !Unique -- ^ reg-mem move inserted during join to targets
1042
1043
1044 -- | Used to carry interesting stats out of the register allocator.
1045 data RegAllocStats
1046         = RegAllocStats
1047         { ra_spillInstrs        :: UniqFM [Int] }
1048
1049
1050 -- | Make register allocator stats from its final state.
1051 makeRAStats :: RA_State -> RegAllocStats
1052 makeRAStats state
1053         = RegAllocStats
1054         { ra_spillInstrs        = binSpillReasons (ra_spills state) }
1055
1056
1057 -- | Build a map of how many times each reg was alloced, clobbered, loaded etc.
1058 binSpillReasons
1059         :: [SpillReason] -> UniqFM [Int]
1060
1061 binSpillReasons reasons
1062         = addListToUFM_C
1063                 (zipWith (+))
1064                 emptyUFM
1065                 (map (\reason -> case reason of
1066                         SpillAlloc r    -> (r, [1, 0, 0, 0, 0])
1067                         SpillClobber r  -> (r, [0, 1, 0, 0, 0])
1068                         SpillLoad r     -> (r, [0, 0, 1, 0, 0])
1069                         SpillJoinRR r   -> (r, [0, 0, 0, 1, 0])
1070                         SpillJoinRM r   -> (r, [0, 0, 0, 0, 1])) reasons)
1071
1072
1073 -- | Count reg-reg moves remaining in this code.
1074 countRegRegMovesNat :: NatCmmTop -> Int
1075 countRegRegMovesNat cmm
1076         = execState (mapGenBlockTopM countBlock cmm) 0
1077  where
1078         countBlock b@(BasicBlock _ instrs)
1079          = do   mapM_ countInstr instrs
1080                 return  b
1081
1082         countInstr instr
1083                 | Just _        <- isRegRegMove instr
1084                 = do    modify (+ 1)
1085                         return instr
1086
1087                 | otherwise
1088                 =       return instr
1089
1090
1091 -- | Pretty print some RegAllocStats
1092 pprStats :: [NatCmmTop] -> [RegAllocStats] -> SDoc
1093 pprStats code statss
1094  = let  -- sum up all the instrs inserted by the spiller
1095         spills          = foldl' (plusUFM_C (zipWith (+)))
1096                                 emptyUFM
1097                         $ map ra_spillInstrs statss
1098
1099         spillTotals     = foldl' (zipWith (+))
1100                                 [0, 0, 0, 0, 0]
1101                         $ eltsUFM spills
1102
1103         -- count how many reg-reg-moves remain in the code
1104         moves           = sum $ map countRegRegMovesNat code
1105
1106         pprSpill (reg, spills)
1107                 = parens $ (hcat $ punctuate (text ", ")  (doubleQuotes (ppr reg) : map ppr spills))
1108
1109    in   (  text "-- spills-added-total"
1110         $$ text "--    (allocs, clobbers, loads, joinRR, joinRM, reg_reg_moves_remaining)"
1111         $$ (parens $ (hcat $ punctuate (text ", ") (map ppr spillTotals ++ [ppr moves])))
1112         $$ text ""
1113         $$ text "-- spills-added"
1114         $$ text "--    (reg_name, allocs, clobbers, loads, joinRR, joinRM)"
1115         $$ (vcat $ map pprSpill
1116                  $ ufmToList spills)
1117         $$ text "")
1118
1119
1120 -- -----------------------------------------------------------------------------
1121 -- Utils
1122
1123 my_fromJust :: String -> SDoc -> Maybe a -> a
1124 my_fromJust _ _ (Just x) = x
1125 my_fromJust s p Nothing = pprPanic ("fromJust: " ++ s) p
1126
1127 lookItUp :: String -> BlockMap a -> BlockId -> a
1128 lookItUp str fm x = my_fromJust str (ppr x) (lookupBlockEnv fm x)