[Git][ghc/ghc][wip/21611-move-corem] 4 commits: Renamed endPassIO to endPass
Dominik Peteler (@mmhat)
gitlab at gitlab.haskell.org
Fri Aug 12 13:45:29 UTC 2022
Dominik Peteler pushed to branch wip/21611-move-corem at Glasgow Haskell Compiler / GHC
Commits:
2661a216 by Dominik Peteler at 2022-08-12T15:04:59+02:00
Renamed endPassIO to endPass
- - - - -
2db3a110 by Dominik Peteler at 2022-08-12T15:15:01+02:00
Renamed hscSimplify/hscSimplify' to optimizeCoreIO/optimizeCoreHsc
- - - - -
5030e60d by Dominik Peteler at 2022-08-12T15:24:51+02:00
Run simplifyPgm in SimplCountM
- - - - -
375910d6 by Dominik Peteler at 2022-08-12T15:45:04+02:00
Added note on the architecture of the Core optimizer
- - - - -
11 changed files:
- compiler/GHC.hs
- compiler/GHC/Core/EndPass.hs
- compiler/GHC/Core/Lint.hs
- compiler/GHC/Core/Opt.hs
- compiler/GHC/Core/Opt/Config.hs
- compiler/GHC/Core/Opt/Simplify.hs
- compiler/GHC/CoreToStg/Prep.hs
- compiler/GHC/Driver/Config/Core/Opt.hs
- compiler/GHC/Driver/Core/Opt.hs
- compiler/GHC/Driver/Main.hs
- compiler/GHC/HsToCore.hs
Changes:
=====================================
compiler/GHC.hs
=====================================
@@ -1285,7 +1285,7 @@ compileCore simplify fn = do
hsc_env <- getSession
simpl_guts <- liftIO $ do
plugins <- readIORef (tcg_th_coreplugins tcg)
- hscSimplify hsc_env plugins mod_guts
+ optimizeCoreIO hsc_env plugins mod_guts
tidy_guts <- liftIO $ hscTidy hsc_env simpl_guts
return $ Left tidy_guts
else
=====================================
compiler/GHC/Core/EndPass.hs
=====================================
@@ -10,7 +10,7 @@ compilation pass that returns Core. Heavily leverages `GHC.Core.Lint`.
module GHC.Core.EndPass (
EndPassConfig (..),
- endPassIO,
+ endPass,
dumpPassResult
) where
@@ -57,12 +57,14 @@ data EndPassConfig = EndPassConfig
, ep_passDetails :: !SDoc
}
-endPassIO :: Logger
- -> EndPassConfig
- -> CoreProgram -> [CoreRule]
- -> IO ()
--- Used by the IO-is CorePrep too
-endPassIO logger cfg binds rules
+-- | Check the correctness of a Core program after running an optimization pass.
+-- Used by CorePrep too.
+-- See Note [The architecture of the Core optimizer].
+endPass :: Logger
+ -> EndPassConfig
+ -> CoreProgram -> [CoreRule]
+ -> IO ()
+endPass logger cfg binds rules
= do { dumpPassResult logger (ep_dumpCoreSizes cfg) (ep_printUnqual cfg) mb_flag
(renderWithContext defaultSDocContext (ep_prettyPass cfg))
(ep_passDetails cfg) binds rules
=====================================
compiler/GHC/Core/Lint.hs
=====================================
@@ -9,6 +9,7 @@
A ``lint'' pass to check for Core correctness.
See Note [Core Lint guarantee].
+See Note [The architecture of the Core optimizer].
-}
module GHC.Core.Lint (
=====================================
compiler/GHC/Core/Opt.hs
=====================================
@@ -1,7 +1,7 @@
{-
(c) The GRASP/AQUA Project, Glasgow University, 1992-1998
-\section[SimplCore]{Driver for simplifying @Core@ programs}
+\section[GHC.Core.Opt]{Driver for optimizing @Core@ programs}
-}
{-# LANGUAGE CPP #-}
@@ -11,7 +11,7 @@ module GHC.Core.Opt ( CoreOptEnv (..), runCorePasses ) where
import GHC.Prelude
import GHC.Core
-import GHC.Core.EndPass ( EndPassConfig, endPassIO )
+import GHC.Core.EndPass ( EndPassConfig, endPass )
import GHC.Core.Opt.CSE ( cseProgram )
import GHC.Core.Ppr ( pprCoreBindings )
import GHC.Core.Lint ( LintAnnotationsConfig, DebugSetting(..), lintAnnots )
@@ -30,7 +30,7 @@ import GHC.Core.Opt.Simplify.Monad
import GHC.Core.Opt.SpecConstr ( specConstrProgram )
import GHC.Core.Opt.Specialise ( specProgram )
import GHC.Core.Opt.StaticArgs ( doStaticArgs )
-import GHC.Core.Opt.Stats ( SimplCountM, addCounts )
+import GHC.Core.Opt.Stats ( SimplCountM )
import GHC.Core.Opt.WorkWrap ( wwTopBinds )
import GHC.Core.LateCC (addLateCostCentres)
import GHC.Core.Rules ( extendRuleBaseList, extendRuleEnv )
@@ -87,6 +87,7 @@ data CoreOptEnv = CoreOptEnv
-- creation of the '[CoreToDo]') happens in
-- 'GHC.Driver.Config.Core.Opt'. Then this function "executes" that
-- plan.
+-- See Note [The architecture of the Core optimizer].
runCorePasses :: CoreOptEnv
-> [CoreToDo]
-> ModGuts
@@ -104,7 +105,7 @@ runCorePasses env passes guts
withTiming (co_logger env) (ppr pass <+> brackets (ppr this_mod)) (const ()) $ do
guts' <- lintAnnots (co_logger env) lint_anno_cfg doCorePassWithoutDebug guts
- liftIO $ endPassIO (co_logger env) end_pass_cfg (mg_binds guts') (mg_rules guts')
+ liftIO $ endPass (co_logger env) end_pass_cfg (mg_binds guts') (mg_rules guts')
return guts'
this_mod = mg_module guts
@@ -126,10 +127,8 @@ doCorePass env pass guts = do
let !read_ruleenv = readRuleEnv env guts
case pass of
- CoreDoSimplify opts -> {-# SCC "Simplify" #-} do
- (guts', sc) <- liftIO $ simplifyPgm (co_logger env) read_ruleenv (co_unitEnv env) opts guts
- addCounts sc
- return guts'
+ CoreDoSimplify opts -> {-# SCC "Simplify" #-}
+ simplifyPgm (co_logger env) read_ruleenv (co_unitEnv env) opts guts
CoreCSE -> {-# SCC "CommonSubExpr" #-}
updateBinds cseProgram
=====================================
compiler/GHC/Core/Opt/Config.hs
=====================================
@@ -34,10 +34,10 @@ import GHC.Utils.Outputable as Outputable
-- | A description of the plugin pass itself
type CorePluginPass = ModGuts -> CoreM ModGuts
-data CoreToDo -- These are diff core-to-core passes,
- -- which may be invoked in any order,
- -- as many times as you like.
-
+-- | These are diff core-to-core passes, which may be invoked in any order, as
+-- many times as you like.
+-- See Note [The architecture of the Core optimizer].
+data CoreToDo
= -- | The core-to-core simplifier.
CoreDoSimplify !SimplifyOpts
| CoreDoPluginPass String CorePluginPass
=====================================
compiler/GHC/Core/Opt/Simplify.hs
=====================================
@@ -21,7 +21,7 @@ import GHC.Core.Opt.Simplify.Iteration ( simplTopBinds, simplExpr, simplImpRules
import GHC.Core.Opt.Simplify.Utils ( activeRule, activeUnfolding )
import GHC.Core.Opt.Simplify.Env
import GHC.Core.Opt.Simplify.Monad
-import GHC.Core.Opt.Stats ( simplCountN )
+import GHC.Core.Opt.Stats ( SimplCountM, addCounts, simplCountN )
import GHC.Core.FamInstEnv
import GHC.Utils.Error ( withTiming )
@@ -44,6 +44,7 @@ import GHC.Types.Unique.FM
import GHC.Types.Name.Ppr
import Control.Monad
+import Control.Monad.IO.Class ( liftIO )
import Data.Foldable ( for_ )
#if __GLASGOW_HASKELL__ <= 810
@@ -144,9 +145,20 @@ simplifyPgm :: Logger
-> UnitEnv
-> SimplifyOpts
-> ModGuts
- -> IO (ModGuts, SimplCount) -- New bindings
-
-simplifyPgm logger read_ruleenv unit_env opts
+ -> SimplCountM ModGuts -- New bindings
+simplifyPgm logger read_ruleenv unit_env opts guts = do
+ (nguts, sc) <- liftIO $ simplifyPgmIO logger read_ruleenv unit_env opts guts
+ addCounts sc
+ return nguts
+
+simplifyPgmIO :: Logger
+ -> IO RuleEnv -- ^ Action to get the current RuleEnv
+ -> UnitEnv
+ -> SimplifyOpts
+ -> ModGuts
+ -> IO (ModGuts, SimplCount) -- New bindings
+
+simplifyPgmIO logger read_ruleenv unit_env opts
guts@(ModGuts { mg_module = this_mod
, mg_rdr_env = rdr_env
, mg_binds = binds, mg_rules = rules
=====================================
compiler/GHC/CoreToStg/Prep.hs
=====================================
@@ -32,7 +32,7 @@ import GHC.Builtin.Types
import GHC.Core.Utils
import GHC.Core.Opt.Arity
-import GHC.Core.EndPass ( EndPassConfig(..), endPassIO )
+import GHC.Core.EndPass ( EndPassConfig(..), endPass )
import GHC.Core
import GHC.Core.Make hiding( FloatBind(..) ) -- We use our own FloatBind here
import GHC.Core.Type
@@ -258,8 +258,7 @@ corePrepPgm logger cp_cfg pgm_cfg
floats2 <- corePrepTopBinds initialCorePrepEnv implicit_binds
return (deFloatTop (floats1 `appendFloats` floats2))
- endPassIO logger (cpPgm_endPassConfig pgm_cfg)
- binds_out []
+ endPass logger (cpPgm_endPassConfig pgm_cfg) binds_out []
return binds_out
corePrepExpr :: Logger -> CorePrepConfig -> CoreExpr -> IO CoreExpr
=====================================
compiler/GHC/Driver/Config/Core/Opt.hs
=====================================
@@ -1,7 +1,7 @@
{-
(c) The GRASP/AQUA Project, Glasgow University, 1992-1998
-\section[SimplCore]{Configuration of the driver for simplifying @Core@ programs}
+\section[GHC.Driver.Config.Core.Opt]{Configuration of the driver for optimizing @Core@ programs}
-}
{-# LANGUAGE CPP #-}
@@ -41,6 +41,8 @@ import Data.Foldable
************************************************************************
-}
+-- | Construct the main optimisation pipeline from the driver's session state.
+-- See Note [The architecture of the Core optimizer].
getCoreToDo :: DynFlags -> [Var] -> [CoreToDo]
getCoreToDo dflags extra_vars = execWriter $ do
-- We want to do the static argument transform before full laziness as it
=====================================
compiler/GHC/Driver/Core/Opt.hs
=====================================
@@ -1,4 +1,4 @@
-module GHC.Driver.Core.Opt ( hscSimplify, hscSimplify' ) where
+module GHC.Driver.Core.Opt ( optimizeCoreHsc, optimizeCoreIO ) where
import GHC.Prelude
@@ -34,27 +34,27 @@ import GHC.Utils.Logger as Logger
import Control.Monad.IO.Class
--------------------------------------------------------------
--- Simplifiers
+-- Core optimization entrypoints
--------------------------------------------------------------
--- | Run Core2Core simplifier. The list of String is a list of (Core) plugin
+-- | Run Core optimizer. The list of String is a list of (Core) plugin
-- module names added via TH (cf 'addCorePlugin').
-hscSimplify :: HscEnv -> [String] -> ModGuts -> IO ModGuts
-hscSimplify hsc_env plugins modguts =
- runHsc hsc_env $ hscSimplify' plugins modguts
-
--- | Run Core2Core simplifier. The list of String is a list of (Core) plugin
--- module names added via TH (cf 'addCorePlugin').
-hscSimplify' :: [String] -> ModGuts -> Hsc ModGuts
-hscSimplify' plugins ds_result = do
- hsc_env <- getHscEnv
+optimizeCoreIO :: HscEnv -> [String] -> ModGuts -> IO ModGuts
+optimizeCoreIO hsc_env plugins guts = do
hsc_env_with_plugins <- if null plugins -- fast path
then return hsc_env
- else liftIO $ initializePlugins
- $ hscUpdateFlags (\dflags -> foldr addPluginModuleName dflags plugins)
- hsc_env
+ else initializePlugins
+ $ hscUpdateFlags (\dflags -> foldr addPluginModuleName dflags plugins)
+ hsc_env
{-# SCC "Core2Core" #-}
- liftIO $ core2core hsc_env_with_plugins ds_result
+ core2core hsc_env_with_plugins guts
+
+-- | Run Core optimizer. The list of String is a list of (Core) plugin
+-- module names added via TH (cf 'addCorePlugin').
+optimizeCoreHsc :: [String] -> ModGuts -> Hsc ModGuts
+optimizeCoreHsc plugins guts = do
+ hsc_env <- getHscEnv
+ liftIO $ optimizeCoreIO hsc_env plugins guts
core2core :: HscEnv -> ModGuts -> IO ModGuts
core2core hsc_env guts@(ModGuts { mg_module = mod
@@ -84,11 +84,6 @@ core2core hsc_env guts@(ModGuts { mg_module = mod
, gwib_isBoot = NotBoot })
hpt_rule_base = mkRuleBase home_pkg_rules
- -- mod: get the module out of the current HscEnv so we can retrieve it from the monad.
- -- This is very convienent for the users of the monad (e.g. plugins do not have to
- -- consume the ModGuts to find the module) but somewhat ugly because mg_module may
- -- _theoretically_ be changed during the Core pipeline (it's part of ModGuts), which
- -- would mean our cached value would go out of date.
env = CoreOptEnv
{ co_logger = logger
, co_debugSetting = InheritDebugLevel
@@ -111,6 +106,11 @@ liftCoreMToSimplCountM hsc_env debug_settings guts m = do
return a
where
mod = mg_module guts
+ -- mod: get the module out of the ModGuts so we can retrieve it from the monad.
+ -- This is very convienent for the users of the monad (e.g. plugins do not have to
+ -- consume the ModGuts to find the module) but somewhat ugly because mg_module may
+ -- _theoretically_ be changed during the Core pipeline (it's part of ModGuts), which
+ -- would mean our cached value would go out of date.
loc = mg_loc guts
orph_mods = mkModuleSet (mod : dep_orphs (mg_deps guts))
gwib = GWIB { gwib_mod = moduleName mod, gwib_isBoot = NotBoot }
@@ -122,3 +122,56 @@ liftCoreMToSimplCountM hsc_env debug_settings guts m = do
NoDebugging -> let
dflags' = (hsc_dflags hsc_env) { debugLevel = 0 }
in hsc_env { hsc_dflags = dflags' }
+
+{-
+Note [The architecture of the Core optimizer]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Conceptually the Core optimizer consists of two stages:
+
+ 1. The planning stage.
+ 2. The execution stage.
+
+This division is mirrored in the interface of the different optimizations. For
+each of those optimzations we have
+
+ 1. a configuration record bundeling the options for a particular optimization
+ pass.
+ 2. an initialization function used to obtain such a configuration from
+ `DynFlags`. This function typically lives in a module named after the pass
+ in the `GHC.Driver.Config.Core.Opt` namespace and is used in the planning
+ stage.
+ 3. the actual optimization pass itself, with an entrypoint that takes the
+ configuration of the pass along with the execution context as arguments.
+ This entrypoint is called in the execution stage.
+
+The plan that is the result of the first stage is constructed by the
+`getCoreToDo` function found in the `GHC.Driver.Config.Core.Opt` module. This
+function determines the sequence of optimization passes run on the module in
+question and derives the configuration for each pass from the session's state
+(`DynFlags`) using the aforementioned initialization functions. The `CoreToDo`
+type that is finally used to wrap this configuration value is a sum type
+enumerating all the optimizations available in GHC.
+
+The entrypoint of the second stage are the `optimizeCore*` functions found in
+GHC.Driver.Core.Opt. These functions is part of the Application Layer and
+utilize the `runCorePasses` function from `GHC.Core.Opt` which is the
+counterpart of these functions in the Domain Layer. In other words, while the
+`optimizeCore*` know about `HscEnv` and are therefore bound to a concrete
+driver, `runCorePasses` is more independent as it is a component of its own.
+
+`runCorePasses` is essentially an interpreter for the `CoreToDo`s constructed in
+the planning phase. It calls the entrypoints of the passes with their respective
+configurations as arguments as well as some execution context like the unit
+environment, the rules and the type family instance in scope, and most notably
+the module we wish to compile (`ModGuts`).
+
+A similar split in functionality is done for the Core Linting: After each pass
+we may check the sanity of the resulting Core running a so-called EndPass check.
+The entrypoint for this check is the `endPass` function found in
+GHC.Core.EndPass. It comes as well with a configuration record and a
+corresponding initialization function for it in GHC.Driver.Core.EndPass. The
+definition of what actually is a correct Core program is defined by the linting
+functions in GHC.Core.Lint. These are used by the EndPass to check the program.
+
+-}
=====================================
compiler/GHC/Driver/Main.hs
=====================================
@@ -59,7 +59,7 @@ module GHC.Driver.Main
, hscTypecheckAndGetWarnings
, hscDesugar
, makeSimpleDetails
- , hscSimplify -- ToDo, shouldn't really export this
+ , optimizeCoreIO -- TODO: shouldn't really export this
, hscDesugarAndSimplify
-- * Safe Haskell
@@ -88,7 +88,7 @@ module GHC.Driver.Main
, hscCompileCoreExpr'
-- We want to make sure that we export enough to be able to redefine
-- hsc_typecheck in client code
- , hscParse', hscSimplify', hscDesugar', tcRnModule', doCodeGen
+ , hscParse', optimizeCoreHsc, hscDesugar', tcRnModule', doCodeGen
, getHscEnv
, hscSimpleIface'
, oneShotMsg
@@ -123,7 +123,7 @@ import GHC.Driver.Config.Stg.Ppr (initStgPprOpts)
import GHC.Driver.Config.Stg.Pipeline (initStgPipelineOpts)
import GHC.Driver.Config.StgToCmm (initStgToCmmConfig)
import GHC.Driver.Config.Cmm (initCmmConfig)
-import GHC.Driver.Core.Opt ( hscSimplify, hscSimplify' )
+import GHC.Driver.Core.Opt ( optimizeCoreHsc, optimizeCoreIO )
import GHC.Driver.Config.Diagnostic
import GHC.Driver.Config.Tidy
import GHC.Driver.Hooks
@@ -158,7 +158,7 @@ import GHC.Iface.Ext.Binary ( readHieFile, writeHieFile , hie_file_result)
import GHC.Iface.Ext.Debug ( diffFile, validateScopes )
import GHC.Core
-import GHC.Core.EndPass ( EndPassConfig(..), endPassIO )
+import GHC.Core.EndPass ( EndPassConfig(..), endPass )
import GHC.Core.Lint ( LintFlags(..), StaticPtrCheck(..) )
import GHC.Core.Lint.Interactive ( interactiveInScope )
import GHC.Core.Tidy ( tidyExpr )
@@ -1008,7 +1008,7 @@ hscDesugarAndSimplify summary (FrontendTypecheck tc_result) tc_warnings mb_old_h
-- Just cause we desugared doesn't mean we are generating code, see above.
Just desugared_guts | backendGeneratesCode bcknd -> do
plugins <- liftIO $ readIORef (tcg_th_coreplugins tc_result)
- simplified_guts <- hscSimplify' plugins desugared_guts
+ simplified_guts <- optimizeCoreHsc plugins desugared_guts
(cg_guts, details) <-
liftIO $ hscTidy hsc_env simplified_guts
@@ -2083,7 +2083,7 @@ hscParsedDecls hsc_env decls = runInteractiveHsc hsc_env $ do
{- Simplify -}
simpl_mg <- liftIO $ do
plugins <- readIORef (tcg_th_coreplugins tc_gblenv)
- hscSimplify hsc_env plugins ds_result
+ optimizeCoreIO hsc_env plugins ds_result
{- Tidy -}
(tidy_cg, mod_details) <- liftIO $ hscTidy hsc_env simpl_mg
@@ -2302,7 +2302,7 @@ hscTidy hsc_env guts = do
, ep_prettyPass = tidy_ppr
, ep_passDetails = empty
}
- endPassIO logger tidy_cfg all_tidy_binds tidy_rules
+ endPass logger tidy_cfg all_tidy_binds tidy_rules
-- If the endPass didn't print the rules, but ddump-rules is
-- on, print now
=====================================
compiler/GHC/HsToCore.hs
=====================================
@@ -48,7 +48,7 @@ import GHC.Core.Type
import GHC.Core.TyCon ( tyConDataCons )
import GHC.Core
import GHC.Core.FVs ( exprsSomeFreeVarsList )
-import GHC.Core.EndPass ( EndPassConfig(..), endPassIO )
+import GHC.Core.EndPass ( EndPassConfig(..), endPass )
import GHC.Core.Lint ( LintFlags(..) )
import GHC.Core.Lint.Interactive ( interactiveInScope )
import GHC.Core.SimpleOpt ( simpleOptPgm, simpleOptExpr )
@@ -240,7 +240,7 @@ deSugar hsc_env
, ep_prettyPass = desugar_before_ppr
, ep_passDetails = empty
}
- ; endPassIO (hsc_logger hsc_env) desugar_before_cfg final_pgm rules_for_imps
+ ; endPass (hsc_logger hsc_env) desugar_before_cfg final_pgm rules_for_imps
; let simpl_opts = initSimpleOpts dflags
; let (ds_binds, ds_rules_for_imps, occ_anald_binds)
@@ -267,7 +267,7 @@ deSugar hsc_env
, ep_prettyPass = desugar_after_ppr
, ep_passDetails = empty
}
- ; endPassIO (hsc_logger hsc_env) desugar_after_cfg ds_binds ds_rules_for_imps
+ ; endPass (hsc_logger hsc_env) desugar_after_cfg ds_binds ds_rules_for_imps
; let used_names = mkUsedNames tcg_env
pluginModules = map lpModule (loadedPlugins (hsc_plugins hsc_env))
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/16f3cbad85f3f52355a4b4faf807a85936a5d806...375910d6e279ca29f07782b8b0f90051a950f06c
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/16f3cbad85f3f52355a4b4faf807a85936a5d806...375910d6e279ca29f07782b8b0f90051a950f06c
You're receiving this email because of your account on gitlab.haskell.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20220812/361b1cab/attachment-0001.html>
More information about the ghc-commits
mailing list