Base.hs 4.02 KB
Newer Older
1 2 3

-- | Put common type definitions here to break recursive module dependencies.

Sylvain Henry's avatar
Sylvain Henry committed
4
module GHC.CmmToAsm.Reg.Linear.Base (
5 6 7 8 9 10 11 12 13 14 15
        BlockAssignment,

        Loc(..),
        regsOfLoc,

        -- for stats
        SpillReason(..),
        RegAllocStats(..),

        -- the allocator monad
        RA_State(..),
16 17 18 19
)

where

20 21
import GhcPrelude

Sylvain Henry's avatar
Sylvain Henry committed
22 23 24
import GHC.CmmToAsm.Reg.Linear.StackMap
import GHC.CmmToAsm.Reg.Liveness
import GHC.Platform.Reg
25

Sylvain Henry's avatar
Sylvain Henry committed
26
import GHC.Driver.Session
27 28 29 30
import Outputable
import Unique
import UniqFM
import UniqSupply
31
import GHC.Cmm.BlockId
32 33 34


-- | Used to store the register assignment on entry to a basic block.
35 36 37
--      We use this to handle join points, where multiple branch instructions
--      target a particular label. We have to insert fixup code to make
--      the register assignments from the different sources match up.
38
--
39 40
type BlockAssignment freeRegs
        = BlockMap (freeRegs, RegMap Loc)
41 42 43


-- | Where a vreg is currently stored
44 45 46 47 48 49 50 51 52
--      A temporary can be marked as living in both a register and memory
--      (InBoth), for example if it was recently loaded from a spill location.
--      This makes it cheap to spill (no save instruction required), but we
--      have to be careful to turn this into InReg if the value in the
--      register is changed.

--      This is also useful when a temporary is about to be clobbered.  We
--      save it in a spill location, but mark it as InBoth because the current
--      instruction might still want to read it.
53
--
54 55 56
data Loc
        -- | vreg is in a register
        = InReg   !RealReg
57

58 59
        -- | vreg is held in a stack slot
        | InMem   {-# UNPACK #-}  !StackSlot
60 61


62 63 64 65
        -- | vreg is held in both a register and a stack slot
        | InBoth   !RealReg
                   {-# UNPACK #-} !StackSlot
        deriving (Eq, Show, Ord)
66 67

instance Outputable Loc where
68
        ppr l = text (show l)
69 70


71
-- | Get the reg numbers stored in this Loc.
72
regsOfLoc :: Loc -> [RealReg]
73 74 75 76 77
regsOfLoc (InReg r)    = [r]
regsOfLoc (InBoth r _) = [r]
regsOfLoc (InMem _)    = []


78
-- | Reasons why instructions might be inserted by the spiller.
79
--      Used when generating stats for -ddrop-asm-stats.
80 81
--
data SpillReason
82 83 84
        -- | vreg was spilled to a slot so we could use its
        --      current hreg for another vreg
        = SpillAlloc    !Unique
85

86 87
        -- | vreg was moved because its hreg was clobbered
        | SpillClobber  !Unique
88

89 90
        -- | vreg was loaded from a spill slot
        | SpillLoad     !Unique
91

92 93
        -- | reg-reg move inserted during join to targets
        | SpillJoinRR   !Unique
94

95 96
        -- | reg-mem move inserted during join to targets
        | SpillJoinRM   !Unique
97 98 99 100


-- | Used to carry interesting stats out of the register allocator.
data RegAllocStats
101
        = RegAllocStats
102 103 104 105
        { ra_spillInstrs        :: UniqFM [Int]
        , ra_fixupList     :: [(BlockId,BlockId,BlockId)]
        -- ^ (from,fixup,to) : We inserted fixup code between from and to
        }
106 107


Gabor Greif's avatar
Gabor Greif committed
108
-- | The register allocator state
109
data RA_State freeRegs
110 111 112 113 114
        = RA_State

        {
        -- | the current mapping from basic blocks to
        --      the register assignments at the beginning of that block.
115
          ra_blockassig :: BlockAssignment freeRegs
116

117
        -- | free machine registers
118
        , ra_freeregs   :: !freeRegs
119

120 121
        -- | assignment of temps to locations
        , ra_assig      :: RegMap Loc
122

123 124
        -- | current stack delta
        , ra_delta      :: Int
125

126 127
        -- | free stack slots for spilling
        , ra_stack      :: StackMap
128

129 130
        -- | unique supply for generating names for join point fixup blocks.
        , ra_us         :: UniqSupply
131

132 133 134
        -- | Record why things were spilled, for -ddrop-asm-stats.
        --      Just keep a list here instead of a map of regs -> reasons.
        --      We don't want to slow down the allocator if we're not going to emit the stats.
135
        , ra_spills     :: [SpillReason]
136 137 138 139
        , ra_DynFlags   :: DynFlags

        -- | (from,fixup,to) : We inserted fixup code between from and to
        , ra_fixups     :: [(BlockId,BlockId,BlockId)] }
140 141