/compiler/nativeGen/RegAlloc/Linear/Base.hs
https://github.com/nominolo/ghc · Haskell · 137 lines · 53 code · 40 blank · 44 comment · 0 complexity · c8b1e679d92521fccd1c8cbe1ff52c51 MD5 · raw file
- -- | Put common type definitions here to break recursive module dependencies.
- module RegAlloc.Linear.Base (
- BlockAssignment,
- Loc(..),
- regsOfLoc,
- -- for stats
- SpillReason(..),
- RegAllocStats(..),
-
- -- the allocator monad
- RA_State(..),
- RegM(..)
- )
- where
- import RegAlloc.Linear.FreeRegs
- import RegAlloc.Linear.StackMap
- import RegAlloc.Liveness
- import Reg
- import Outputable
- import Unique
- import UniqFM
- import UniqSupply
- -- | Used to store the register assignment on entry to a basic block.
- -- 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.
- --
- type BlockAssignment
- = BlockMap (FreeRegs, RegMap Loc)
- -- | Where a vreg is currently stored
- -- 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.
- --
- data Loc
- -- | vreg is in a register
- = InReg !RealReg
- -- | vreg is held in a stack slot
- | InMem {-# UNPACK #-} !StackSlot
- -- | vreg is held in both a register and a stack slot
- | InBoth !RealReg
- {-# UNPACK #-} !StackSlot
- deriving (Eq, Show, Ord)
- instance Outputable Loc where
- ppr l = text (show l)
- -- | Get the reg numbers stored in this Loc.
- regsOfLoc :: Loc -> [RealReg]
- regsOfLoc (InReg r) = [r]
- regsOfLoc (InBoth r _) = [r]
- regsOfLoc (InMem _) = []
- -- | Reasons why instructions might be inserted by the spiller.
- -- Used when generating stats for -ddrop-asm-stats.
- --
- data SpillReason
- -- | vreg was spilled to a slot so we could use its
- -- current hreg for another vreg
- = SpillAlloc !Unique
- -- | vreg was moved because its hreg was clobbered
- | SpillClobber !Unique
- -- | vreg was loaded from a spill slot
- | SpillLoad !Unique
- -- | reg-reg move inserted during join to targets
- | SpillJoinRR !Unique
- -- | reg-mem move inserted during join to targets
- | SpillJoinRM !Unique
- -- | Used to carry interesting stats out of the register allocator.
- data RegAllocStats
- = RegAllocStats
- { ra_spillInstrs :: UniqFM [Int] }
- -- | The register alloctor state
- data RA_State
- = RA_State
- {
- -- | the current mapping from basic blocks to
- -- the register assignments at the beginning of that block.
- ra_blockassig :: BlockAssignment
-
- -- | free machine registers
- , ra_freeregs :: {-#UNPACK#-}!FreeRegs
- -- | assignment of temps to locations
- , ra_assig :: RegMap Loc
- -- | current stack delta
- , ra_delta :: Int
- -- | free stack slots for spilling
- , ra_stack :: StackMap
- -- | unique supply for generating names for join point fixup blocks.
- , ra_us :: UniqSupply
- -- | 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.
- , ra_spills :: [SpillReason] }
- -- | The register allocator monad type.
- newtype RegM a
- = RegM { unReg :: RA_State -> (# RA_State, a #) }