X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=compiler%2FnativeGen%2FRegSpill.hs;h=0fdb8ce857e7c05c3443f63c352f8335b91ebd56;hb=97169c5dd31537b28f5f8ad08cd6cdf82c1ecefd;hp=4921cf119dc4bf58a3d79162924871a292354885;hpb=0f7d268d00795a58a06ae3c92ebbd14571295b84;p=ghc-hetmet.git diff --git a/compiler/nativeGen/RegSpill.hs b/compiler/nativeGen/RegSpill.hs index 4921cf1..0fdb8ce 100644 --- a/compiler/nativeGen/RegSpill.hs +++ b/compiler/nativeGen/RegSpill.hs @@ -1,18 +1,21 @@ +{-# OPTIONS -fno-warn-missing-signatures #-} + module RegSpill ( - regSpill + regSpill, + SpillStats(..), + accSpillSL ) where -#include "HsVersions.h" - import RegLiveness import RegAllocInfo import MachRegs import MachInstrs import Cmm +import State import Unique import UniqFM import UniqSet @@ -36,8 +39,9 @@ regSpill -> UniqSet Int -- ^ available stack slots -> UniqSet Reg -- ^ the regs to spill -> UniqSM - ([LiveCmmTop] -- ^ code will spill instructions - , UniqSet Int) -- ^ left over slots + ([LiveCmmTop] -- code will spill instructions + , UniqSet Int -- left over slots + , SpillStats ) -- stats about what happened during spilling regSpill code slotsFree regs @@ -58,30 +62,24 @@ regSpill code slotsFree regs us <- getUs -- run the spiller on all the blocks - let (# code', _ #) = - runSpill (mapM (mapBlockTopM (regSpill_block regSlotMap)) code) + let (code', state') = + runState (mapM (mapBlockTopM (regSpill_block regSlotMap)) code) (initSpillS us) return ( code' - , minusUniqSet slotsFree (mkUniqSet slots) ) + , minusUniqSet slotsFree (mkUniqSet slots) + , makeSpillStats state') regSpill_block regSlotMap (BasicBlock i instrs) = do instrss' <- mapM (regSpill_instr regSlotMap) instrs return $ BasicBlock i (concat instrss') - -regSpill_instr _ li@(Instr (DELTA delta) _) - = do - setDelta delta - return [li] - regSpill_instr _ li@(Instr _ Nothing) = do return [li] - regSpill_instr regSlotMap - (Instr instr (Just live)) + (Instr instr (Just _)) = do -- work out which regs are read and written in this instr let RU rlRead rlWritten = regUsage instr @@ -130,44 +128,45 @@ regSpill_instr regSlotMap spillRead regSlotMap instr reg | Just slot <- lookupUFM regSlotMap reg - = do delta <- getDelta - (instr', nReg) <- patchInstr reg instr + = do (instr', nReg) <- patchInstr reg instr - let pre = [ COMMENT FSLIT("spill read") - , mkLoadInstr nReg delta slot ] + modify $ \s -> s + { stateSpillSL = addToUFM_C accSpillSL (stateSpillSL s) reg (reg, 0, 1) } - return ( instr', (pre, [])) + return ( instr' + , ( [RELOAD slot nReg] + , []) ) | otherwise = panic "RegSpill.spillRead: no slot defined for spilled reg" spillWrite regSlotMap instr reg | Just slot <- lookupUFM regSlotMap reg - = do delta <- getDelta - (instr', nReg) <- patchInstr reg instr + = do (instr', nReg) <- patchInstr reg instr - let post = [ COMMENT FSLIT("spill write") - , mkSpillInstr nReg delta slot ] + modify $ \s -> s + { stateSpillSL = addToUFM_C accSpillSL (stateSpillSL s) reg (reg, 1, 0) } - return ( instr', ([], post)) + return ( instr' + , ( [] + , [SPILL nReg slot])) | otherwise = panic "RegSpill.spillWrite: no slot defined for spilled reg" spillModify regSlotMap instr reg | Just slot <- lookupUFM regSlotMap reg - = do delta <- getDelta - (instr', nReg) <- patchInstr reg instr - - let pre = [ COMMENT FSLIT("spill mod load") - , mkLoadInstr nReg delta slot ] + = do (instr', nReg) <- patchInstr reg instr - let post = [ COMMENT FSLIT("spill mod write") - , mkSpillInstr nReg delta slot ] + modify $ \s -> s + { stateSpillSL = addToUFM_C accSpillSL (stateSpillSL s) reg (reg, 1, 1) } - return ( instr', (pre, post)) + return ( instr' + , ( [RELOAD slot nReg] + , [SPILL nReg slot])) | otherwise = panic "RegSpill.spillModify: no slot defined for spilled reg" + -- | rewrite uses of this virtual reg in an instr to use a different virtual reg patchInstr :: Reg -> Instr -> SpillM (Instr, Reg) patchInstr reg instr @@ -184,50 +183,48 @@ patchReg1 old new instr in patchRegs instr patchF -------------------------------------------------------------------------------------------- +------------------------------------------------------ -- Spiller monad data SpillS = SpillS - { stateDelta :: Int - , stateUS :: UniqSupply } + { stateUS :: UniqSupply + , stateSpillSL :: UniqFM (Reg, Int, Int) } -- ^ spilled reg vs number of times vreg was loaded, stored initSpillS uniqueSupply = SpillS - { stateDelta = 0 - , stateUS = uniqueSupply } + { stateUS = uniqueSupply + , stateSpillSL = emptyUFM } -newtype SpillM a - = SpillM - { runSpill :: SpillS -> (# a, SpillS #) } +type SpillM a = State SpillS a -instance Monad SpillM where - return x = SpillM $ \s -> (# x, s #) +newUnique :: SpillM Unique +newUnique + = do us <- gets stateUS + case splitUniqSupply us of + (us1, us2) + -> do let uniq = uniqFromSupply us1 + modify $ \s -> s { stateUS = us2 } + return uniq - m >>= n = SpillM $ \s -> - case runSpill m s of - (# r, s' #) -> runSpill (n r) s' +accSpillSL (r1, s1, l1) (_, s2, l2) + = (r1, s1 + s2, l1 + l2) -setDelta :: Int -> SpillM () -setDelta delta - = SpillM $ \s -> (# (), s { stateDelta = delta } #) -getDelta :: SpillM Int -getDelta = SpillM $ \s -> (# stateDelta s, s #) +---------------------------------------------------- +-- Spiller stats -newUnique :: SpillM Unique -newUnique - = SpillM $ \s - -> case splitUniqSupply (stateUS s) of - (us1, us2) - -> (# uniqFromSupply us1 - , s { stateUS = us2 } #) - -mapAccumLM _ s [] = return (s, []) -mapAccumLM f s (x:xs) - = do - (s1, x') <- f s x - (s2, xs') <- mapAccumLM f s1 xs - return (s2, x' : xs') +data SpillStats + = SpillStats + { spillStoreLoad :: UniqFM (Reg, Int, Int) } + +makeSpillStats :: SpillS -> SpillStats +makeSpillStats s + = SpillStats + { spillStoreLoad = stateSpillSL s } +instance Outputable SpillStats where + ppr stats + = (vcat $ map (\(r, s, l) -> ppr r <+> int s <+> int l) + $ eltsUFM (spillStoreLoad stats))