[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