module CmmPipeline (
cmmPipeline
) where
import CLabel
import Cmm
import CmmDecl
import CmmLive
import CmmBuildInfoTables
import CmmCommonBlockElim
import CmmProcPoint
import CmmSpillReload
import CmmRewriteAssignments
import CmmStackLayout
import CmmContFlowOpt
import OptimizationFuel
import DynFlags
import ErrUtils
import HscTypes
import Data.Maybe
import Control.Monad
import Data.Map (Map)
import qualified Data.Map as Map
import Outputable
import StaticFlags
cmmPipeline :: HscEnv
-> (TopSRT, [Cmm])
-> Cmm
-> IO (TopSRT, [Cmm])
cmmPipeline hsc_env (topSRT, rst) prog =
do let dflags = hsc_dflags hsc_env
(Cmm tops) = runCmmContFlowOpts prog
showPass dflags "CPSZ"
(cafEnvs, tops) <- liftM unzip $ mapM (cpsTop hsc_env) tops
let topCAFEnv = mkTopCAFInfo (concat cafEnvs)
(topSRT, tops) <- foldM (toTops hsc_env topCAFEnv) (topSRT, []) tops
let cmms = Cmm (reverse (concat tops))
dumpIfSet_dyn dflags Opt_D_dump_cps_cmm "Post CPS Cmm" (pprPlatform (targetPlatform dflags) cmms)
let prog' = map runCmmContFlowOpts (cmms : rst)
return (topSRT, prog')
cpsTop :: HscEnv -> CmmTop -> IO ([(CLabel, CAFSet)], [(CAFSet, CmmTop)])
cpsTop _ p@(CmmData {}) = return ([], [(Map.empty, p)])
cpsTop hsc_env (CmmProc h@(TopInfo {stack_info=StackInfo {arg_space=entry_off}}) l g) =
do
g <- return $ elimCommonBlocks g
dumpPlatform platform Opt_D_dump_cmmz_cbe "Post common block elimination" g
let callPPs = callProcPoints g
procPoints <- run $ minimalProcPointSet (targetPlatform dflags) callPPs g
g <- run $ addProcPointProtocols callPPs procPoints g
dumpPlatform platform Opt_D_dump_cmmz_proc "Post Proc Points Added" g
g <- run $ dualLivenessWithInsertion procPoints g
dumpPlatform platform Opt_D_dump_cmmz_spills "Post spills and reloads" g
g <- runOptimization $ rewriteAssignments g
dumpPlatform platform Opt_D_dump_cmmz_rewrite "Post rewrite assignments" g
g <- runOptimization $ removeDeadAssignments g
dumpPlatform platform Opt_D_dump_cmmz_dead "Post remove dead assignments" g
g <- if opt_StubDeadValues
then run $ stubSlotsOnDeath g
else return g
dumpPlatform platform Opt_D_dump_cmmz_stub "Post stub dead stack slots" g
slotEnv <- run $ liveSlotAnal g
let spEntryMap = getSpEntryMap entry_off g
mbpprTrace "live slot analysis results: " (ppr slotEnv) $ return ()
let areaMap = layout procPoints spEntryMap slotEnv entry_off g
mbpprTrace "areaMap" (ppr areaMap) $ return ()
g <- run $ manifestSP spEntryMap areaMap entry_off g
dumpPlatform platform Opt_D_dump_cmmz_sp "Post manifestSP" g
procPointMap <- run $ procPointAnalysis procPoints g
dump Opt_D_dump_cmmz_procmap "procpoint map" procPointMap
gs <- run $ splitAtProcPoints l callPPs procPoints procPointMap
(CmmProc h l g)
mapM_ (dumpPlatform platform Opt_D_dump_cmmz_split "Post splitting") gs
cafEnv <- run $ cafAnal g
let localCAFs = catMaybes $ map (localCAFInfo cafEnv) gs
mbpprTrace "localCAFs" (ppr localCAFs) $ return ()
gs <- run $ mapM (lowerSafeForeignCalls areaMap) gs
mapM_ (dumpPlatform platform Opt_D_dump_cmmz_lower "Post lowerSafeForeignCalls") gs
gs <- return $ map (setInfoTableStackMap slotEnv areaMap) gs
mapM_ (dumpPlatform platform Opt_D_dump_cmmz_info "after setInfoTableStackMap") gs
gs <- return $ map (bundleCAFs cafEnv) gs
mapM_ (dumpPlatform platform Opt_D_dump_cmmz_cafs "after bundleCAFs") gs
return (localCAFs, gs)
where dflags = hsc_dflags hsc_env
platform = targetPlatform dflags
mbpprTrace x y z = if dopt Opt_D_dump_cmmz dflags then pprTrace x y z else z
dump f = dumpWith ppr f
dumpPlatform platform = dumpWith (pprPlatform platform)
dumpWith pprFun f txt g = do
dumpIfSet_dyn dflags f txt (pprFun g)
when (not (dopt f dflags)) $
dumpIfSet_dyn dflags Opt_D_dump_cmmz txt (pprFun g)
run = runInfiniteFuelIO (hsc_OptFuel hsc_env)
runOptimization = runFuelIO (hsc_OptFuel hsc_env)
toTops :: HscEnv -> Map CLabel CAFSet -> (TopSRT, [[CmmTop]])
-> [(CAFSet, CmmTop)] -> IO (TopSRT, [[CmmTop]])
toTops hsc_env topCAFEnv (topSRT, tops) gs =
do let setSRT (topSRT, rst) g =
do (topSRT, gs) <- setInfoTableSRT topCAFEnv topSRT g
return (topSRT, gs : rst)
(topSRT, gs') <- runFuelIO (hsc_OptFuel hsc_env) $ foldM setSRT (topSRT, []) gs
return (topSRT, concat gs' : tops)