packages feed

lhc-0.10: src/Grin/SimpleCore/DeadCode.hs

module Grin.SimpleCore.DeadCode
    ( removeDeadCode
    ) where

import CompactString
import Grin.SimpleCore.Types

import qualified Data.Map as Map
import qualified Data.Set as Set



removeDeadCode :: [(String,String)] -> [String] -> Map.Map (String,String) SimpleModule -> ([SimpleType], [SimpleEnum], [SimpleDef])
removeDeadCode initialModules entryPoints modules
    = let entryPointsCompact = map fromString entryPoints
          addModules mods entries = entries `Map.union` Map.unions (map (entityMap `find`) mods)
          loop entries seenMods seen ds
              = let (mods,refs) = unzip (map (entries `find`) ds)
                    new  = Set.unions refs `Set.difference` seen
                    seen' = Set.union seen new
                in if Set.null new
                   then ( Set.toList seenMods
                        , seen `Set.union` Set.fromList entryPointsCompact)
                   else loop (addModules (concat mods) entries) (Set.union seenMods (Set.fromList (concat mods)))  seen' (Set.toList new)
          (modDeps, deps) = loop (addModules initialModules Map.empty) (Set.fromList initialModules) Set.empty entryPointsCompact
          neededMods = map (modules `find`) modDeps
          tdefs = concatMap moduleTypes neededMods
          defs = concatMap moduleDefs neededMods
      in ( [ tdef | tdef <- tdefs] -- Unused nodes are removed later.
         , concatMap moduleEnums neededMods
         , [ def  | def  <- defs, simpleDefName def `Set.member` deps ]
         )
    where find m k = case Map.lookup k m of
                       Just v  -> v
                       Nothing -> error $ "Grin.SimpleCore.DeadCode.removeDeadCode: Couldn't find key: " ++ show k
          entityMap :: Map.Map (String,String) (Map.Map CompactString ([(String,String)], Set.Set CompactString)) 
          entityMap = flip Map.map modules $ \smod ->
                      Map.fromList $ [ (simpleDefName def, (simpleDefDeps def, defDependencies def)) | def <- moduleDefs smod ] ++
                                     [ (simpleTypeName tdef, ([],Set.empty)) | tdef <- moduleTypes smod]


defDependencies :: SimpleDef  -> Set.Set CompactString
defDependencies def
    = dependencies (simpleDefBody def) `Set.difference` Set.fromList (simpleDefArgs def)

dependencies :: SimpleExp -> Set.Set CompactString
dependencies (Var var isUnboxed) = Set.singleton var
dependencies Primitive{}= Set.empty
dependencies (EnumPrimitive prim arg ty) = Set.singleton arg
dependencies (Dcon var) = Set.singleton var
dependencies Lit{} = Set.empty
dependencies (App a args) = Set.unions (dependencies a : map dependencies args)
dependencies (Let var toplevel _ _ e)
    = Set.delete var $ Set.insert toplevel $ dependencies e
dependencies (LetRec defs e)
    = let vars      = Set.fromList [ var | (var,_,_,_) <- defs ]
          toplevels = Set.fromList [ toplevel | (_,toplevel,_,_) <- defs ]
      in (dependencies e `Set.union` toplevels) `Set.difference` vars
dependencies (LetStrict name def e)
    = Set.delete name $ dependencies def `Set.union` dependencies e
dependencies (Case e bind alts)
    = Set.delete bind $ Set.unions (dependencies e : map altDependencies alts)
dependencies (CaseStrict e bind alts)
    = Set.delete bind $ Set.unions (dependencies e : map altDependencies alts)
dependencies External{} = Set.empty
dependencies DynExternal{} = Set.empty
dependencies Label{} = Set.empty
dependencies (Note _ e) = dependencies e

altDependencies :: Alt -> Set.Set CompactString
altDependencies (Acon tag args e)
    = Set.insert tag $ dependencies e `Set.difference` Set.fromList args
altDependencies (Alit _ e)
    = dependencies e
altDependencies (Adefault e)
    = dependencies e