Erase unneeded spill/reloads after register allocation
[ghc-hetmet.git] / compiler / nativeGen / RegSpillClean.hs
1 -- | Clean out unneeded spill/reload instrs
2 --
3 module RegSpillClean (
4         cleanSpills
5 )
6 where
7
8 import RegLiveness
9 import RegAllocInfo
10 import MachRegs
11 import MachInstrs
12 import Cmm
13
14 import UniqSet
15
16
17 -- | Clean out unneeded spill/reloads from this top level thing.
18 cleanSpills :: LiveCmmTop -> LiveCmmTop
19 cleanSpills cmm
20         = mapBlockTop cleanBlock cmm
21  where
22         cleanBlock (BasicBlock id instrs)
23                 = BasicBlock id
24                 $ cleanSpill  emptyUniqSet []
25                 $ cleanReload emptyUniqSet []
26                 $ instrs
27
28
29 -- | Clean out unneeded reload instructions.
30 --      Walking forwards across the code
31 --        If there are no writes to a reg between a reload and the
32 --        last spill or reload then we don't need the reload.
33 --
34 cleanReload
35         :: UniqSet Reg          -- ^ hregs that were reloaded but not written to yet
36         -> [LiveInstr]          -- ^ acc
37         -> [LiveInstr]          -- ^ instrs to clean (in backwards order)
38         -> [LiveInstr]          -- ^ cleaned instrs  (in forward   order)
39
40 cleanReload valid acc []        = acc
41 cleanReload valid acc (li@(Instr instr live) : instrs)
42         | SPILL reg slot        <- instr
43         , valid'                <- addOneToUniqSet valid reg
44         = cleanReload valid' (li : acc) instrs
45
46         | RELOAD slot reg       <- instr
47         = if elementOfUniqSet reg valid
48            then cleanReload valid acc instrs
49            else cleanReload (addOneToUniqSet valid reg) (li : acc) instrs
50
51         | RU read written       <- regUsage instr
52         , valid'                <- minusUniqSet valid (mkUniqSet written)
53         = cleanReload valid' (li : acc) instrs
54
55
56 -- | Clean out unneeded spill instructions.
57 --      Walking backwards across the code.
58 --       If there were no reloads from a slot between a spill and the last one
59 --       then the slot was never read and we don't need the spill.
60
61 cleanSpill
62         :: UniqSet Int          -- ^ slots that have been spilled, but not reload from
63         -> [LiveInstr]          -- ^ acc
64         -> [LiveInstr]          -- ^ instrs to clean (in forwards order)
65         -> [LiveInstr]          -- ^ cleaned instrs  (in backwards order)
66
67 cleanSpill unused acc []        = acc
68 cleanSpill unused acc (li@(Instr instr live) : instrs)
69         | SPILL reg slot        <- instr
70         = if elementOfUniqSet slot unused
71            then cleanSpill unused acc instrs
72            else cleanSpill (addOneToUniqSet unused slot) (li : acc) instrs
73
74         | RELOAD slot reg       <- instr
75         , unused'               <- delOneFromUniqSet unused slot
76         = cleanSpill unused' (li : acc) instrs
77
78         | otherwise
79         = cleanSpill unused (li : acc) instrs
80