module CmmLive
( CmmLocalLive
, CmmGlobalLive
, cmmLocalLiveness
, cmmGlobalLiveness
, liveLattice
, noLiveOnEntry, xferLive, gen, kill, gen_kill
, removeDeadAssignments
)
where
import UniqSupply
import DynFlags
import BlockId
import Cmm
import CmmUtils
import PprCmmExpr ()
import Hoopl
import Maybes
import Outputable
type CmmLive r = RegSet r
type CmmLocalLive = CmmLive LocalReg
type CmmGlobalLive = CmmLive GlobalReg
liveLattice :: Ord r => DataflowLattice (CmmLive r)
liveLattice = DataflowLattice "live LocalReg's" emptyRegSet add
where add _ (OldFact old) (NewFact new) =
(changeIf $ sizeRegSet join > sizeRegSet old, join)
where !join = plusRegSet old new
type BlockEntryLiveness r = BlockEnv (CmmLive r)
cmmLocalLiveness :: DynFlags -> CmmGraph -> BlockEntryLiveness LocalReg
cmmLocalLiveness dflags graph =
check $ dataflowAnalBwd graph [] $ analBwd liveLattice (xferLive dflags)
where entry = g_entry graph
check facts = noLiveOnEntry entry
(expectJust "check" $ mapLookup entry facts) facts
cmmGlobalLiveness :: DynFlags -> CmmGraph -> BlockEntryLiveness GlobalReg
cmmGlobalLiveness dflags graph =
dataflowAnalBwd graph [] $ analBwd liveLattice (xferLive dflags)
noLiveOnEntry :: BlockId -> CmmLive LocalReg -> a -> a
noLiveOnEntry bid in_fact x =
if nullRegSet in_fact then x
else pprPanic "LocalReg's live-in to graph" (ppr bid <+> ppr in_fact)
gen :: UserOfRegs r a => DynFlags -> a -> RegSet r -> RegSet r
gen dflags a live = foldRegsUsed dflags extendRegSet live a
kill :: DefinerOfRegs r a => DynFlags -> a -> RegSet r -> RegSet r
kill dflags a live = foldRegsDefd dflags deleteFromRegSet live a
gen_kill :: (DefinerOfRegs r a, UserOfRegs r a)
=> DynFlags -> a -> CmmLive r -> CmmLive r
gen_kill dflags a = gen dflags a . kill dflags a
xferLive :: forall r . ( UserOfRegs r (CmmNode O O)
, DefinerOfRegs r (CmmNode O O)
, UserOfRegs r (CmmNode O C)
, DefinerOfRegs r (CmmNode O C))
=> DynFlags -> BwdTransfer CmmNode (CmmLive r)
xferLive dflags = mkBTransfer3 fst mid lst
where fst _ f = f
mid :: CmmNode O O -> CmmLive r -> CmmLive r
mid n f = gen_kill dflags n f
lst :: CmmNode O C -> FactBase (CmmLive r) -> CmmLive r
lst n f = gen_kill dflags n $ joinOutFacts liveLattice n f
removeDeadAssignments :: DynFlags -> CmmGraph
-> UniqSM (CmmGraph, BlockEnv CmmLocalLive)
removeDeadAssignments dflags g =
dataflowPassBwd g [] $ analRewBwd liveLattice (xferLive dflags) rewrites
where rewrites = mkBRewrite3 nothing middle nothing
middle :: CmmNode O O -> Fact O CmmLocalLive -> CmmReplGraph O O
middle (CmmAssign (CmmLocal reg') _) live
| not (reg' `elemRegSet` live)
= return $ Just emptyGraph
middle (CmmAssign lhs (CmmReg rhs)) _ | lhs == rhs
= return $ Just emptyGraph
middle (CmmStore lhs (CmmLoad rhs _)) _ | lhs == rhs
= return $ Just emptyGraph
middle _ _ = return Nothing
nothing :: CmmNode e x -> Fact x CmmLocalLive -> CmmReplGraph e x
nothing _ _ = return Nothing