Obsidian-0.0.0.1: Obsidian/CodeGen/Liveness.hs
{- Joel Svensson 2012, 2013
notes:
added case for SeqFor Jan-21-2013
-}
module Obsidian.CodeGen.Liveness where
import qualified Data.Set as Set
import Obsidian.Exp
import Obsidian.Globs
import Obsidian.CodeGen.Program
import Control.Monad.State
---------------------------------------------------------------------------
--
---------------------------------------------------------------------------
type Liveness = Set.Set Name
---------------------------------------------------------------------------
--
---------------------------------------------------------------------------
type IML = [(Statement Liveness,Liveness)]
{- Plan:
# Step through program from end to start
# as soon as a new name is encountered, add it to the living set
# when an "Allocate" is found, delete the name it allocated from the living set.
Requirements:
# All names are unique!
TODO: Think more carefully about the ForAllBlocks case
TODO: Can ixs contain array names ?
(Most likely yes! think about the counting sort example)
-}
-- Nice type
computeLiveness :: IMList a -> IML
computeLiveness im = reverse $ evalState (cl (reverse im)) Set.empty
-- Nice Type
computeLiveness1 :: Liveness -> IMList a -> IML
computeLiveness1 l im = reverse $ evalState (cl (reverse im)) l
-- cl :: IM -> State Liveness IML
cl im = mapM process im
where
safeHead [] = Set.empty
safeHead (x:xs) = snd x
-- Horrific type
process :: (Statement a,a) -> State Liveness (Statement Liveness,Liveness)
process (SAssign nom ixs e,_) =
do
s <- get
let arrays = collectArrays e
living = Set.fromList (nom:arrays) `Set.union` s
put living -- update state
return (SAssign nom ixs e,living)
process (SAtomicOp n1 n2 ixs op,_) =
do
s <- get
return (SAtomicOp n1 n2 ixs op,s)
process (SAllocate name size t,_) =
do
modify (name `Set.delete`)
s <- get
return (SAllocate name size t,s)
process (SDeclare name t,_) =
do
s <- get
return (SDeclare name t,s)
process (SOutput name t,_) =
do
s <- get
return (SOutput name t,s)
process (SSynchronize,_) =
do
s <- get
return (SSynchronize,s)
process (SCond bexp im,_) =
do
-- TODO: What should really happen here ?
s <- get
let iml = computeLiveness1 s im
l = safeHead iml
ns = s `Set.union` l
put ns
-- Is this correct ? Same question, all below
return (SCond bexp iml,ns)
process (SSeqFor nom n im,_) =
do
s <- get
let iml = computeLiveness1 s im
l = safeHead iml
ns = s `Set.union` l
put ns
return (SSeqFor nom n iml,ns)
process (SForAll n im,_) =
do
s <- get
let iml = computeLiveness1 s im
l = safeHead iml
ns = s `Set.union` l
put ns
return (SForAll n iml,ns)
process (SForAllBlocks n im,_) =
do
s <- get
let iml = computeLiveness1 s im
l = safeHead iml
ns = s `Set.union` l
put ns
return (SForAllBlocks n iml,ns)
process (SForAllThreads n im,_) =
do
s <- get
let iml = computeLiveness1 s im
l = safeHead iml
ns = s `Set.union` l
put ns
return (SForAllThreads n iml,ns)