{-# LANGUAGE BangPatterns #-}
module CmmPipeline (
cmmPipeline
) where
import GhcPrelude
import Cmm
import CmmLint
import CmmBuildInfoTables
import CmmCommonBlockElim
import CmmImplementSwitchPlans
import CmmProcPoint
import CmmContFlowOpt
import CmmLayoutStack
import CmmSink
import Hoopl.Collections
import UniqSupply
import DynFlags
import ErrUtils
import HscTypes
import Control.Monad
import Outputable
import GHC.Platform
cmmPipeline
:: HscEnv
-> ModuleSRTInfo
-> CmmGroup
-> IO (ModuleSRTInfo, CmmGroup)
cmmPipeline :: HscEnv -> ModuleSRTInfo -> CmmGroup -> IO (ModuleSRTInfo, CmmGroup)
cmmPipeline HscEnv
hsc_env ModuleSRTInfo
srtInfo CmmGroup
prog = DynFlags
-> SDoc
-> ((ModuleSRTInfo, CmmGroup) -> ())
-> IO (ModuleSRTInfo, CmmGroup)
-> IO (ModuleSRTInfo, CmmGroup)
forall (m :: * -> *) a.
MonadIO m =>
DynFlags -> SDoc -> (a -> ()) -> m a -> m a
withTimingSilent DynFlags
dflags (String -> SDoc
text String
"Cmm pipeline") (ModuleSRTInfo, CmmGroup) -> ()
forall (t :: * -> *) a a. Foldable t => (a, t a) -> ()
forceRes (IO (ModuleSRTInfo, CmmGroup) -> IO (ModuleSRTInfo, CmmGroup))
-> IO (ModuleSRTInfo, CmmGroup) -> IO (ModuleSRTInfo, CmmGroup)
forall a b. (a -> b) -> a -> b
$
do let dflags :: DynFlags
dflags = HscEnv -> DynFlags
hsc_dflags HscEnv
hsc_env
[(CAFEnv, CmmGroup)]
tops <- {-# SCC "tops" #-} (CmmDecl -> IO (CAFEnv, CmmGroup))
-> CmmGroup -> IO [(CAFEnv, CmmGroup)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (HscEnv -> CmmDecl -> IO (CAFEnv, CmmGroup)
cpsTop HscEnv
hsc_env) CmmGroup
prog
(ModuleSRTInfo
srtInfo, CmmGroup
cmms) <- {-# SCC "doSRTs" #-} DynFlags
-> ModuleSRTInfo
-> [(CAFEnv, CmmGroup)]
-> IO (ModuleSRTInfo, CmmGroup)
doSRTs DynFlags
dflags ModuleSRTInfo
srtInfo [(CAFEnv, CmmGroup)]
tops
DynFlags -> DumpFlag -> String -> SDoc -> IO ()
dumpWith DynFlags
dflags DumpFlag
Opt_D_dump_cmm_cps String
"Post CPS Cmm" (CmmGroup -> SDoc
forall a. Outputable a => a -> SDoc
ppr CmmGroup
cmms)
(ModuleSRTInfo, CmmGroup) -> IO (ModuleSRTInfo, CmmGroup)
forall (m :: * -> *) a. Monad m => a -> m a
return (ModuleSRTInfo
srtInfo, CmmGroup
cmms)
where forceRes :: (a, t a) -> ()
forceRes (a
info, t a
group) =
a
info a -> () -> ()
`seq` (a -> () -> ()) -> () -> t a -> ()
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\a
decl ()
r -> a
decl a -> () -> ()
`seq` ()
r) () t a
group
dflags :: DynFlags
dflags = HscEnv -> DynFlags
hsc_dflags HscEnv
hsc_env
cpsTop :: HscEnv -> CmmDecl -> IO (CAFEnv, [CmmDecl])
cpsTop :: HscEnv -> CmmDecl -> IO (CAFEnv, CmmGroup)
cpsTop HscEnv
_ p :: CmmDecl
p@(CmmData {}) = (CAFEnv, CmmGroup) -> IO (CAFEnv, CmmGroup)
forall (m :: * -> *) a. Monad m => a -> m a
return (CAFEnv
forall (map :: * -> *) a. IsMap map => map a
mapEmpty, [CmmDecl
p])
cpsTop HscEnv
hsc_env CmmDecl
proc =
do
CmmProc CmmTopInfo
h CLabel
l [GlobalReg]
v CmmGraph
g <- {-# SCC "cmmCfgOpts(1)" #-}
CmmDecl -> IO CmmDecl
forall (m :: * -> *) a. Monad m => a -> m a
return (CmmDecl -> IO CmmDecl) -> CmmDecl -> IO CmmDecl
forall a b. (a -> b) -> a -> b
$ Bool -> CmmDecl -> CmmDecl
cmmCfgOptsProc Bool
splitting_proc_points CmmDecl
proc
DumpFlag -> String -> CmmGraph -> IO ()
dump DumpFlag
Opt_D_dump_cmm_cfg String
"Post control-flow optimisations" CmmGraph
g
let !TopInfo {stack_info :: CmmTopInfo -> CmmStackInfo
stack_info=StackInfo { arg_space :: CmmStackInfo -> ByteOff
arg_space = ByteOff
entry_off
, do_layout :: CmmStackInfo -> Bool
do_layout = Bool
do_layout }} = CmmTopInfo
h
CmmGraph
g <- {-# SCC "elimCommonBlocks" #-}
GeneralFlag
-> (CmmGraph -> CmmGraph)
-> CmmGraph
-> DumpFlag
-> String
-> IO CmmGraph
condPass GeneralFlag
Opt_CmmElimCommonBlocks CmmGraph -> CmmGraph
elimCommonBlocks CmmGraph
g
DumpFlag
Opt_D_dump_cmm_cbe String
"Post common block elimination"
CmmGraph
g <- {-# SCC "createSwitchPlans" #-}
UniqSM CmmGraph -> IO CmmGraph
forall a. UniqSM a -> IO a
runUniqSM (UniqSM CmmGraph -> IO CmmGraph) -> UniqSM CmmGraph -> IO CmmGraph
forall a b. (a -> b) -> a -> b
$ DynFlags -> CmmGraph -> UniqSM CmmGraph
cmmImplementSwitchPlans DynFlags
dflags CmmGraph
g
DumpFlag -> String -> CmmGraph -> IO ()
dump DumpFlag
Opt_D_dump_cmm_switch String
"Post switch plan" CmmGraph
g
let call_pps :: ProcPointSet
call_pps = {-# SCC "callProcPoints" #-} CmmGraph -> ProcPointSet
callProcPoints CmmGraph
g
ProcPointSet
proc_points <-
if Bool
splitting_proc_points
then do
ProcPointSet
pp <- {-# SCC "minimalProcPointSet" #-} UniqSM ProcPointSet -> IO ProcPointSet
forall a. UniqSM a -> IO a
runUniqSM (UniqSM ProcPointSet -> IO ProcPointSet)
-> UniqSM ProcPointSet -> IO ProcPointSet
forall a b. (a -> b) -> a -> b
$
Platform -> ProcPointSet -> CmmGraph -> UniqSM ProcPointSet
minimalProcPointSet (DynFlags -> Platform
targetPlatform DynFlags
dflags) ProcPointSet
call_pps CmmGraph
g
DynFlags -> DumpFlag -> String -> SDoc -> IO ()
dumpWith DynFlags
dflags DumpFlag
Opt_D_dump_cmm_proc String
"Proc points"
(CLabel -> SDoc
forall a. Outputable a => a -> SDoc
ppr CLabel
l SDoc -> SDoc -> SDoc
$$ ProcPointSet -> SDoc
forall a. Outputable a => a -> SDoc
ppr ProcPointSet
pp SDoc -> SDoc -> SDoc
$$ CmmGraph -> SDoc
forall a. Outputable a => a -> SDoc
ppr CmmGraph
g)
ProcPointSet -> IO ProcPointSet
forall (m :: * -> *) a. Monad m => a -> m a
return ProcPointSet
pp
else
ProcPointSet -> IO ProcPointSet
forall (m :: * -> *) a. Monad m => a -> m a
return ProcPointSet
call_pps
(CmmGraph
g, LabelMap StackMap
stackmaps) <-
{-# SCC "layoutStack" #-}
if Bool
do_layout
then UniqSM (CmmGraph, LabelMap StackMap)
-> IO (CmmGraph, LabelMap StackMap)
forall a. UniqSM a -> IO a
runUniqSM (UniqSM (CmmGraph, LabelMap StackMap)
-> IO (CmmGraph, LabelMap StackMap))
-> UniqSM (CmmGraph, LabelMap StackMap)
-> IO (CmmGraph, LabelMap StackMap)
forall a b. (a -> b) -> a -> b
$ DynFlags
-> ProcPointSet
-> ByteOff
-> CmmGraph
-> UniqSM (CmmGraph, LabelMap StackMap)
cmmLayoutStack DynFlags
dflags ProcPointSet
proc_points ByteOff
entry_off CmmGraph
g
else (CmmGraph, LabelMap StackMap) -> IO (CmmGraph, LabelMap StackMap)
forall (m :: * -> *) a. Monad m => a -> m a
return (CmmGraph
g, LabelMap StackMap
forall (map :: * -> *) a. IsMap map => map a
mapEmpty)
DumpFlag -> String -> CmmGraph -> IO ()
dump DumpFlag
Opt_D_dump_cmm_sp String
"Layout Stack" CmmGraph
g
CmmGraph
g <- {-# SCC "sink" #-}
GeneralFlag
-> (CmmGraph -> CmmGraph)
-> CmmGraph
-> DumpFlag
-> String
-> IO CmmGraph
condPass GeneralFlag
Opt_CmmSink (DynFlags -> CmmGraph -> CmmGraph
cmmSink DynFlags
dflags) CmmGraph
g
DumpFlag
Opt_D_dump_cmm_sink String
"Sink assignments"
let cafEnv :: CAFEnv
cafEnv = {-# SCC "cafAnal" #-} ProcPointSet -> CLabel -> CmmGraph -> CAFEnv
cafAnal ProcPointSet
call_pps CLabel
l CmmGraph
g
DynFlags -> DumpFlag -> String -> SDoc -> IO ()
dumpWith DynFlags
dflags DumpFlag
Opt_D_dump_cmm_caf String
"CAFEnv" (CAFEnv -> SDoc
forall a. Outputable a => a -> SDoc
ppr CAFEnv
cafEnv)
CmmGroup
g <- if Bool
splitting_proc_points
then do
let pp_map :: LabelMap Status
pp_map = {-# SCC "procPointAnalysis" #-}
ProcPointSet -> CmmGraph -> LabelMap Status
procPointAnalysis ProcPointSet
proc_points CmmGraph
g
DynFlags -> DumpFlag -> String -> SDoc -> IO ()
dumpWith DynFlags
dflags DumpFlag
Opt_D_dump_cmm_procmap String
"procpoint map" (SDoc -> IO ()) -> SDoc -> IO ()
forall a b. (a -> b) -> a -> b
$
LabelMap Status -> SDoc
forall a. Outputable a => a -> SDoc
ppr LabelMap Status
pp_map
CmmGroup
g <- {-# SCC "splitAtProcPoints" #-} UniqSM CmmGroup -> IO CmmGroup
forall a. UniqSM a -> IO a
runUniqSM (UniqSM CmmGroup -> IO CmmGroup) -> UniqSM CmmGroup -> IO CmmGroup
forall a b. (a -> b) -> a -> b
$
DynFlags
-> CLabel
-> ProcPointSet
-> ProcPointSet
-> LabelMap Status
-> CmmDecl
-> UniqSM CmmGroup
splitAtProcPoints DynFlags
dflags CLabel
l ProcPointSet
call_pps ProcPointSet
proc_points LabelMap Status
pp_map
(CmmTopInfo -> CLabel -> [GlobalReg] -> CmmGraph -> CmmDecl
forall d h g. h -> CLabel -> [GlobalReg] -> g -> GenCmmDecl d h g
CmmProc CmmTopInfo
h CLabel
l [GlobalReg]
v CmmGraph
g)
DumpFlag -> String -> CmmGroup -> IO ()
forall (t :: * -> *) a.
(Foldable t, Outputable a) =>
DumpFlag -> String -> t a -> IO ()
dumps DumpFlag
Opt_D_dump_cmm_split String
"Post splitting" CmmGroup
g
CmmGroup -> IO CmmGroup
forall (m :: * -> *) a. Monad m => a -> m a
return CmmGroup
g
else do
CmmGroup -> IO CmmGroup
forall (m :: * -> *) a. Monad m => a -> m a
return (CmmGroup -> IO CmmGroup) -> CmmGroup -> IO CmmGroup
forall a b. (a -> b) -> a -> b
$ [ProcPointSet -> CmmDecl -> CmmDecl
attachContInfoTables ProcPointSet
call_pps (CmmTopInfo -> CLabel -> [GlobalReg] -> CmmGraph -> CmmDecl
forall d h g. h -> CLabel -> [GlobalReg] -> g -> GenCmmDecl d h g
CmmProc CmmTopInfo
h CLabel
l [GlobalReg]
v CmmGraph
g)]
CmmGroup
g <- {-# SCC "setInfoTableStackMap" #-}
CmmGroup -> IO CmmGroup
forall (m :: * -> *) a. Monad m => a -> m a
return (CmmGroup -> IO CmmGroup) -> CmmGroup -> IO CmmGroup
forall a b. (a -> b) -> a -> b
$ (CmmDecl -> CmmDecl) -> CmmGroup -> CmmGroup
forall a b. (a -> b) -> [a] -> [b]
map (DynFlags -> LabelMap StackMap -> CmmDecl -> CmmDecl
setInfoTableStackMap DynFlags
dflags LabelMap StackMap
stackmaps) CmmGroup
g
DumpFlag -> String -> CmmGroup -> IO ()
forall (t :: * -> *) a.
(Foldable t, Outputable a) =>
DumpFlag -> String -> t a -> IO ()
dumps DumpFlag
Opt_D_dump_cmm_info String
"after setInfoTableStackMap" CmmGroup
g
CmmGroup
g <- {-# SCC "cmmCfgOpts(2)" #-}
CmmGroup -> IO CmmGroup
forall (m :: * -> *) a. Monad m => a -> m a
return (CmmGroup -> IO CmmGroup) -> CmmGroup -> IO CmmGroup
forall a b. (a -> b) -> a -> b
$ if DynFlags -> ByteOff
optLevel DynFlags
dflags ByteOff -> ByteOff -> Bool
forall a. Ord a => a -> a -> Bool
>= ByteOff
1
then (CmmDecl -> CmmDecl) -> CmmGroup -> CmmGroup
forall a b. (a -> b) -> [a] -> [b]
map (Bool -> CmmDecl -> CmmDecl
cmmCfgOptsProc Bool
splitting_proc_points) CmmGroup
g
else CmmGroup
g
CmmGroup
g <- CmmGroup -> IO CmmGroup
forall (m :: * -> *) a. Monad m => a -> m a
return ((CmmDecl -> CmmDecl) -> CmmGroup -> CmmGroup
forall a b. (a -> b) -> [a] -> [b]
map CmmDecl -> CmmDecl
removeUnreachableBlocksProc CmmGroup
g)
DumpFlag -> String -> CmmGroup -> IO ()
forall (t :: * -> *) a.
(Foldable t, Outputable a) =>
DumpFlag -> String -> t a -> IO ()
dumps DumpFlag
Opt_D_dump_cmm_cfg String
"Post control-flow optimisations" CmmGroup
g
(CAFEnv, CmmGroup) -> IO (CAFEnv, CmmGroup)
forall (m :: * -> *) a. Monad m => a -> m a
return (CAFEnv
cafEnv, CmmGroup
g)
where dflags :: DynFlags
dflags = HscEnv -> DynFlags
hsc_dflags HscEnv
hsc_env
platform :: Platform
platform = DynFlags -> Platform
targetPlatform DynFlags
dflags
dump :: DumpFlag -> String -> CmmGraph -> IO ()
dump = DynFlags -> DumpFlag -> String -> CmmGraph -> IO ()
dumpGraph DynFlags
dflags
dumps :: DumpFlag -> String -> t a -> IO ()
dumps DumpFlag
flag String
name
= (a -> IO ()) -> t a -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (DynFlags -> DumpFlag -> String -> SDoc -> IO ()
dumpWith DynFlags
dflags DumpFlag
flag String
name (SDoc -> IO ()) -> (a -> SDoc) -> a -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> SDoc
forall a. Outputable a => a -> SDoc
ppr)
condPass :: GeneralFlag
-> (CmmGraph -> CmmGraph)
-> CmmGraph
-> DumpFlag
-> String
-> IO CmmGraph
condPass GeneralFlag
flag CmmGraph -> CmmGraph
pass CmmGraph
g DumpFlag
dumpflag String
dumpname =
if GeneralFlag -> DynFlags -> Bool
gopt GeneralFlag
flag DynFlags
dflags
then do
CmmGraph
g <- CmmGraph -> IO CmmGraph
forall (m :: * -> *) a. Monad m => a -> m a
return (CmmGraph -> IO CmmGraph) -> CmmGraph -> IO CmmGraph
forall a b. (a -> b) -> a -> b
$ CmmGraph -> CmmGraph
pass CmmGraph
g
DumpFlag -> String -> CmmGraph -> IO ()
dump DumpFlag
dumpflag String
dumpname CmmGraph
g
CmmGraph -> IO CmmGraph
forall (m :: * -> *) a. Monad m => a -> m a
return CmmGraph
g
else CmmGraph -> IO CmmGraph
forall (m :: * -> *) a. Monad m => a -> m a
return CmmGraph
g
splitting_proc_points :: Bool
splitting_proc_points = DynFlags -> HscTarget
hscTarget DynFlags
dflags HscTarget -> HscTarget -> Bool
forall a. Eq a => a -> a -> Bool
/= HscTarget
HscAsm
Bool -> Bool -> Bool
|| Bool -> Bool
not (DynFlags -> Bool
tablesNextToCode DynFlags
dflags)
Bool -> Bool -> Bool
||
Bool
usingInconsistentPicReg
usingInconsistentPicReg :: Bool
usingInconsistentPicReg
= case (Platform -> Arch
platformArch Platform
platform, Platform -> OS
platformOS Platform
platform, DynFlags -> Bool
positionIndependent DynFlags
dflags)
of (Arch
ArchX86, OS
OSDarwin, Bool
pic) -> Bool
pic
(Arch, OS, Bool)
_ -> Bool
False
runUniqSM :: UniqSM a -> IO a
runUniqSM :: UniqSM a -> IO a
runUniqSM UniqSM a
m = do
UniqSupply
us <- Char -> IO UniqSupply
mkSplitUniqSupply Char
'u'
a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (UniqSupply -> UniqSM a -> a
forall a. UniqSupply -> UniqSM a -> a
initUs_ UniqSupply
us UniqSM a
m)
dumpGraph :: DynFlags -> DumpFlag -> String -> CmmGraph -> IO ()
dumpGraph :: DynFlags -> DumpFlag -> String -> CmmGraph -> IO ()
dumpGraph DynFlags
dflags DumpFlag
flag String
name CmmGraph
g = do
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (GeneralFlag -> DynFlags -> Bool
gopt GeneralFlag
Opt_DoCmmLinting DynFlags
dflags) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ CmmGraph -> IO ()
do_lint CmmGraph
g
DynFlags -> DumpFlag -> String -> SDoc -> IO ()
dumpWith DynFlags
dflags DumpFlag
flag String
name (CmmGraph -> SDoc
forall a. Outputable a => a -> SDoc
ppr CmmGraph
g)
where
do_lint :: CmmGraph -> IO ()
do_lint CmmGraph
g = case DynFlags -> CmmGraph -> Maybe SDoc
cmmLintGraph DynFlags
dflags CmmGraph
g of
Just SDoc
err -> do { DynFlags -> SDoc -> IO ()
fatalErrorMsg DynFlags
dflags SDoc
err
; DynFlags -> ByteOff -> IO ()
ghcExit DynFlags
dflags ByteOff
1
}
Maybe SDoc
Nothing -> () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
dumpWith :: DynFlags -> DumpFlag -> String -> SDoc -> IO ()
dumpWith :: DynFlags -> DumpFlag -> String -> SDoc -> IO ()
dumpWith DynFlags
dflags DumpFlag
flag String
txt SDoc
sdoc = do
DynFlags -> DumpFlag -> String -> SDoc -> IO ()
dumpIfSet_dyn DynFlags
dflags DumpFlag
flag String
txt SDoc
sdoc
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not (DumpFlag -> DynFlags -> Bool
dopt DumpFlag
flag DynFlags
dflags)) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (DumpFlag -> DynFlags -> Bool
dopt DumpFlag
Opt_D_dump_cmm_verbose DynFlags
dflags)
(IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ DynFlags -> PrintUnqualified -> DumpFlag -> String -> SDoc -> IO ()
dumpSDoc DynFlags
dflags PrintUnqualified
alwaysQualify DumpFlag
flag String
txt SDoc
sdoc
DynFlags -> DumpFlag -> String -> SDoc -> IO ()
dumpIfSet_dyn DynFlags
dflags DumpFlag
Opt_D_dump_cmm_verbose_by_proc String
txt SDoc
sdoc