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