module GHC.CmmToAsm.Reg.Graph.Coalesce (
regCoalesce,
slurpJoinMovs
) where
import GHC.Prelude
import GHC.CmmToAsm.Reg.Liveness
import GHC.CmmToAsm.Instr
import GHC.Platform.Reg
import GHC.Cmm
import GHC.Data.Bag
import GHC.Data.Graph.Directed
import GHC.Platform (Platform)
import GHC.Types.Unique (getUnique)
import GHC.Types.Unique.FM
import GHC.Types.Unique.Supply
import GHC.Types.Unique.Set
regCoalesce
:: Instruction instr
=> Platform
-> [LiveCmmDecl statics instr]
-> UniqSM [LiveCmmDecl statics instr]
regCoalesce :: forall instr statics.
Instruction instr =>
Platform
-> [LiveCmmDecl statics instr]
-> UniqSM [LiveCmmDecl statics instr]
regCoalesce Platform
platform [LiveCmmDecl statics instr]
code
= do
let joins :: Bag (Reg, Reg)
joins = (Bag (Reg, Reg) -> Bag (Reg, Reg) -> Bag (Reg, Reg))
-> Bag (Reg, Reg) -> [Bag (Reg, Reg)] -> Bag (Reg, Reg)
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Bag (Reg, Reg) -> Bag (Reg, Reg) -> Bag (Reg, Reg)
forall a. Bag a -> Bag a -> Bag a
unionBags Bag (Reg, Reg)
forall a. Bag a
emptyBag
([Bag (Reg, Reg)] -> Bag (Reg, Reg))
-> [Bag (Reg, Reg)] -> Bag (Reg, Reg)
forall a b. (a -> b) -> a -> b
$ (LiveCmmDecl statics instr -> Bag (Reg, Reg))
-> [LiveCmmDecl statics instr] -> [Bag (Reg, Reg)]
forall a b. (a -> b) -> [a] -> [b]
map (Platform -> LiveCmmDecl statics instr -> Bag (Reg, Reg)
forall instr statics.
Instruction instr =>
Platform -> LiveCmmDecl statics instr -> Bag (Reg, Reg)
slurpJoinMovs Platform
platform) [LiveCmmDecl statics instr]
code
let alloc :: UniqFM Reg Reg
alloc = (UniqFM Reg Reg -> (Reg, Reg) -> UniqFM Reg Reg)
-> UniqFM Reg Reg -> [(Reg, Reg)] -> UniqFM Reg Reg
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' UniqFM Reg Reg -> (Reg, Reg) -> UniqFM Reg Reg
buildAlloc UniqFM Reg Reg
forall {k} (key :: k) elt. UniqFM key elt
emptyUFM
([(Reg, Reg)] -> UniqFM Reg Reg) -> [(Reg, Reg)] -> UniqFM Reg Reg
forall a b. (a -> b) -> a -> b
$ Bag (Reg, Reg) -> [(Reg, Reg)]
forall a. Bag a -> [a]
bagToList Bag (Reg, Reg)
joins
let patched :: [LiveCmmDecl statics instr]
patched = (LiveCmmDecl statics instr -> LiveCmmDecl statics instr)
-> [LiveCmmDecl statics instr] -> [LiveCmmDecl statics instr]
forall a b. (a -> b) -> [a] -> [b]
map (Platform
-> (Reg -> Reg)
-> LiveCmmDecl statics instr
-> LiveCmmDecl statics instr
forall instr statics.
(Instruction instr, HasDebugCallStack) =>
Platform
-> (Reg -> Reg)
-> LiveCmmDecl statics instr
-> LiveCmmDecl statics instr
patchEraseLive Platform
platform (UniqFM Reg Reg -> Reg -> Reg
sinkReg UniqFM Reg Reg
alloc)) [LiveCmmDecl statics instr]
code
[LiveCmmDecl statics instr] -> UniqSM [LiveCmmDecl statics instr]
forall a. a -> UniqSM a
forall (m :: * -> *) a. Monad m => a -> m a
return [LiveCmmDecl statics instr]
patched
buildAlloc :: UniqFM Reg Reg -> (Reg, Reg) -> UniqFM Reg Reg
buildAlloc :: UniqFM Reg Reg -> (Reg, Reg) -> UniqFM Reg Reg
buildAlloc UniqFM Reg Reg
fm (Reg
r1, Reg
r2)
= let rmin :: Reg
rmin = Reg -> Reg -> Reg
forall a. Ord a => a -> a -> a
min Reg
r1 Reg
r2
rmax :: Reg
rmax = Reg -> Reg -> Reg
forall a. Ord a => a -> a -> a
max Reg
r1 Reg
r2
in UniqFM Reg Reg -> Reg -> Reg -> UniqFM Reg Reg
forall key elt.
Uniquable key =>
UniqFM key elt -> key -> elt -> UniqFM key elt
addToUFM UniqFM Reg Reg
fm Reg
rmax Reg
rmin
sinkReg :: UniqFM Reg Reg -> Reg -> Reg
sinkReg :: UniqFM Reg Reg -> Reg -> Reg
sinkReg UniqFM Reg Reg
fm Reg
r
= case UniqFM Reg Reg -> Reg -> Maybe Reg
forall key elt. Uniquable key => UniqFM key elt -> key -> Maybe elt
lookupUFM UniqFM Reg Reg
fm Reg
r of
Maybe Reg
Nothing -> Reg
r
Just Reg
r' -> UniqFM Reg Reg -> Reg -> Reg
sinkReg UniqFM Reg Reg
fm Reg
r'
slurpJoinMovs
:: Instruction instr
=> Platform
-> LiveCmmDecl statics instr
-> Bag (Reg, Reg)
slurpJoinMovs :: forall instr statics.
Instruction instr =>
Platform -> LiveCmmDecl statics instr -> Bag (Reg, Reg)
slurpJoinMovs Platform
platform LiveCmmDecl statics instr
live
= Bag (Reg, Reg) -> LiveCmmDecl statics instr -> Bag (Reg, Reg)
slurpCmm Bag (Reg, Reg)
forall a. Bag a
emptyBag LiveCmmDecl statics instr
live
where
slurpCmm :: Bag (Reg, Reg) -> LiveCmmDecl statics instr -> Bag (Reg, Reg)
slurpCmm Bag (Reg, Reg)
rs CmmData{}
= Bag (Reg, Reg)
rs
slurpCmm Bag (Reg, Reg)
rs (CmmProc LiveInfo
_ CLabel
_ [GlobalRegUse]
_ [SCC (GenBasicBlock (LiveInstr instr))]
sccs)
= (Bag (Reg, Reg)
-> GenBasicBlock (LiveInstr instr) -> Bag (Reg, Reg))
-> Bag (Reg, Reg)
-> [GenBasicBlock (LiveInstr instr)]
-> Bag (Reg, Reg)
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Bag (Reg, Reg) -> GenBasicBlock (LiveInstr instr) -> Bag (Reg, Reg)
slurpBlock Bag (Reg, Reg)
rs ([SCC (GenBasicBlock (LiveInstr instr))]
-> [GenBasicBlock (LiveInstr instr)]
forall a. [SCC a] -> [a]
flattenSCCs [SCC (GenBasicBlock (LiveInstr instr))]
sccs)
slurpBlock :: Bag (Reg, Reg) -> GenBasicBlock (LiveInstr instr) -> Bag (Reg, Reg)
slurpBlock Bag (Reg, Reg)
rs (BasicBlock BlockId
_ [LiveInstr instr]
instrs)
= (Bag (Reg, Reg) -> LiveInstr instr -> Bag (Reg, Reg))
-> Bag (Reg, Reg) -> [LiveInstr instr] -> Bag (Reg, Reg)
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Bag (Reg, Reg) -> LiveInstr instr -> Bag (Reg, Reg)
slurpLI Bag (Reg, Reg)
rs [LiveInstr instr]
instrs
slurpLI :: Bag (Reg, Reg) -> LiveInstr instr -> Bag (Reg, Reg)
slurpLI Bag (Reg, Reg)
rs (LiveInstr InstrSR instr
_ Maybe Liveness
Nothing) = Bag (Reg, Reg)
rs
slurpLI Bag (Reg, Reg)
rs (LiveInstr InstrSR instr
instr (Just Liveness
live))
| Just (Reg
r1, Reg
r2) <- Platform -> InstrSR instr -> Maybe (Reg, Reg)
forall instr.
Instruction instr =>
Platform -> instr -> Maybe (Reg, Reg)
takeRegRegMoveInstr Platform
platform InstrSR instr
instr
, Unique -> UniqSet RegWithFormat -> Bool
forall a. Unique -> UniqSet a -> Bool
elemUniqSet_Directly (Reg -> Unique
forall a. Uniquable a => a -> Unique
getUnique Reg
r1) (UniqSet RegWithFormat -> Bool) -> UniqSet RegWithFormat -> Bool
forall a b. (a -> b) -> a -> b
$ Liveness -> UniqSet RegWithFormat
liveDieRead Liveness
live
, Unique -> UniqSet RegWithFormat -> Bool
forall a. Unique -> UniqSet a -> Bool
elemUniqSet_Directly (Reg -> Unique
forall a. Uniquable a => a -> Unique
getUnique Reg
r2) (UniqSet RegWithFormat -> Bool) -> UniqSet RegWithFormat -> Bool
forall a b. (a -> b) -> a -> b
$ Liveness -> UniqSet RegWithFormat
liveBorn Liveness
live
, Reg -> Bool
isVirtualReg Reg
r1 Bool -> Bool -> Bool
&& Reg -> Bool
isVirtualReg Reg
r2
= (Reg, Reg) -> Bag (Reg, Reg) -> Bag (Reg, Reg)
forall a. a -> Bag a -> Bag a
consBag (Reg
r1, Reg
r2) Bag (Reg, Reg)
rs
| Bool
otherwise
= Bag (Reg, Reg)
rs