module CmmLiveZ ( CmmLive , cmmLivenessZ , liveLattice , middleLiveness, noLiveOnEntry ) where import BlockId import CmmExpr import CmmTx import DFMonad import Control.Monad import PprCmm() import PprCmmZ() import ZipCfg import ZipDataflow import ZipCfgCmmRep import Maybes import Outputable import UniqSet ----------------------------------------------------------------------------- -- Calculating what variables are live on entry to a basic block ----------------------------------------------------------------------------- -- | The variables live on entry to a block type CmmLive = RegSet -- | The dataflow lattice liveLattice :: DataflowLattice CmmLive liveLattice = DataflowLattice "live LocalReg's" emptyUniqSet add False where add new old = let join = unionUniqSets new old in (if sizeUniqSet join > sizeUniqSet old then aTx else noTx) join -- | A mapping from block labels to the variables live on entry type BlockEntryLiveness = BlockEnv CmmLive ----------------------------------------------------------------------------- -- | Calculated liveness info for a CmmGraph ----------------------------------------------------------------------------- cmmLivenessZ :: CmmGraph -> FuelMonad BlockEntryLiveness cmmLivenessZ g@(LGraph entry _) = liftM (check . zdfFpFacts) (res :: FuelMonad (CmmBackwardFixedPoint CmmLive)) where res = zdfSolveFrom emptyBlockEnv "liveness analysis" liveLattice transfers emptyUniqSet (graphOfLGraph g) transfers = BackwardTransfers (flip const) mid last mid m = gen_kill m . midLive m last l = gen_kill l . lastLive l check facts = noLiveOnEntry entry (expectJust "check" $ lookupBlockEnv facts entry) facts gen_kill :: (DefinerOfLocalRegs a, UserOfLocalRegs a) => a -> CmmLive -> CmmLive gen_kill a = gen a . kill a middleLiveness :: Middle -> CmmLive -> CmmLive middleLiveness = gen_kill -- | On entry to the procedure, there had better not be any LocalReg's live-in. noLiveOnEntry :: BlockId -> CmmLive -> a -> a noLiveOnEntry bid in_fact x = if isEmptyUniqSet in_fact then x else pprPanic "LocalReg's live-in to graph" (ppr bid <+> ppr in_fact) -- | The transfer equations use the traditional 'gen' and 'kill' -- notations, which should be familiar from the dragon book. gen :: UserOfLocalRegs a => a -> RegSet -> RegSet gen a live = foldRegsUsed extendRegSet live a kill :: DefinerOfLocalRegs a => a -> RegSet -> RegSet kill a live = foldRegsDefd delOneFromUniqSet live a midLive :: Middle -> CmmLive -> CmmLive midLive (MidForeignCall {}) _ = emptyUniqSet midLive _ live = live lastLive :: Last -> (BlockId -> CmmLive) -> CmmLive lastLive l env = last l where last (LastBranch id) = env id last (LastCall _ _ _ _ _) = emptyUniqSet last (LastCondBranch _ t f) = unionUniqSets (env t) (env f) last (LastSwitch _ tbl) = unionManyUniqSets $ map env (catMaybes tbl)