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