Cheng Shao pushed to branch wip/ghci-no-simpl at Glasgow Haskell Compiler / GHC
Commits:
-
8f3d80ff
by Luite Stegeman at 2025-09-13T08:43:09+02:00
-
eb389338
by Luite Stegeman at 2025-09-13T08:43:09+02:00
-
99b233f4
by Alison at 2025-09-13T16:51:04-04:00
-
c892dd78
by Cheng Shao at 2025-09-14T09:19:25+02:00
-
a9cd271d
by Cheng Shao at 2025-09-14T09:19:25+02:00
-
9502796c
by Cheng Shao at 2025-09-14T09:19:25+02:00
-
54ee4bca
by Cheng Shao at 2025-09-14T09:19:25+02:00
14 changed files:
- compiler/GHC/Core/Opt/Pipeline.hs
- compiler/GHC/Core/Opt/Simplify.hs
- compiler/GHC/Driver/Config/Core/Opt/Simplify.hs
- compiler/GHC/Driver/Main.hs
- compiler/GHC/Runtime/Heap/Inspect.hs
- compiler/GHC/StgToCmm/Layout.hs
- libraries/ghc-heap/GHC/Exts/Heap.hs
- testsuite/tests/codeGen/should_run/T13825-unit.hs
- testsuite/tests/interface-stability/ghc-prim-exports.stdout
- testsuite/tests/interface-stability/ghc-prim-exports.stdout-mingw32
- testsuite/tests/unboxedsums/UbxSumUnpackedSize.stdout
- testsuite/tests/unboxedsums/UbxSumUnpackedSize.stdout-ws-32
- utils/genprimopcode/Main.hs
- + utils/genprimopcode/hie.yaml
Changes:
| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | |
| 7 | 7 | {-# LANGUAGE CPP #-}
|
| 8 | 8 | |
| 9 | -module GHC.Core.Opt.Pipeline ( core2core, simplifyExpr ) where
|
|
| 9 | +module GHC.Core.Opt.Pipeline ( core2core ) where
|
|
| 10 | 10 | |
| 11 | 11 | import GHC.Prelude
|
| 12 | 12 | |
| ... | ... | @@ -27,7 +27,7 @@ import GHC.Core.Ppr ( pprCoreBindings ) |
| 27 | 27 | import GHC.Core.Utils ( dumpIdInfoOfProgram )
|
| 28 | 28 | import GHC.Core.Lint ( lintAnnots )
|
| 29 | 29 | import GHC.Core.Lint.Interactive ( interactiveInScope )
|
| 30 | -import GHC.Core.Opt.Simplify ( simplifyExpr, simplifyPgm )
|
|
| 30 | +import GHC.Core.Opt.Simplify ( simplifyPgm )
|
|
| 31 | 31 | import GHC.Core.Opt.Simplify.Monad
|
| 32 | 32 | import GHC.Core.Opt.Monad
|
| 33 | 33 | import GHC.Core.Opt.Pipeline.Types
|
| 1 | 1 | {-# LANGUAGE CPP #-}
|
| 2 | 2 | |
| 3 | 3 | module GHC.Core.Opt.Simplify
|
| 4 | - ( SimplifyExprOpts(..), SimplifyOpts(..)
|
|
| 5 | - , simplifyExpr, simplifyPgm
|
|
| 4 | + ( SimplifyOpts(..)
|
|
| 5 | + , simplifyPgm
|
|
| 6 | 6 | ) where
|
| 7 | 7 | |
| 8 | 8 | import GHC.Prelude
|
| ... | ... | @@ -11,20 +11,18 @@ import GHC.Driver.Flags |
| 11 | 11 | |
| 12 | 12 | import GHC.Core
|
| 13 | 13 | import GHC.Core.Rules
|
| 14 | -import GHC.Core.Ppr ( pprCoreBindings, pprCoreExpr )
|
|
| 15 | -import GHC.Core.Opt.OccurAnal ( occurAnalysePgm, occurAnalyseExpr )
|
|
| 16 | -import GHC.Core.Stats ( coreBindsSize, coreBindsStats, exprSize )
|
|
| 14 | +import GHC.Core.Ppr ( pprCoreBindings )
|
|
| 15 | +import GHC.Core.Opt.OccurAnal ( occurAnalysePgm )
|
|
| 16 | +import GHC.Core.Stats ( coreBindsSize, coreBindsStats )
|
|
| 17 | 17 | import GHC.Core.Utils ( mkTicks, stripTicksTop )
|
| 18 | 18 | import GHC.Core.Lint ( LintPassResultConfig, dumpPassResult, lintPassResult )
|
| 19 | -import GHC.Core.Opt.Simplify.Iteration ( simplTopBinds, simplExpr, simplImpRules )
|
|
| 19 | +import GHC.Core.Opt.Simplify.Iteration ( simplTopBinds, simplImpRules )
|
|
| 20 | 20 | import GHC.Core.Opt.Simplify.Utils ( activeRule )
|
| 21 | 21 | import GHC.Core.Opt.Simplify.Inline ( activeUnfolding )
|
| 22 | 22 | import GHC.Core.Opt.Simplify.Env
|
| 23 | 23 | import GHC.Core.Opt.Simplify.Monad
|
| 24 | 24 | import GHC.Core.Opt.Stats ( simplCountN )
|
| 25 | -import GHC.Core.FamInstEnv
|
|
| 26 | 25 | |
| 27 | -import GHC.Utils.Error ( withTiming )
|
|
| 28 | 26 | import GHC.Utils.Logger as Logger
|
| 29 | 27 | import GHC.Utils.Outputable
|
| 30 | 28 | import GHC.Utils.Constants (debugIsOn)
|
| ... | ... | @@ -44,72 +42,6 @@ import GHC.Types.Unique.FM |
| 44 | 42 | import Control.Monad
|
| 45 | 43 | import Data.Foldable ( for_ )
|
| 46 | 44 | |
| 47 | -{-
|
|
| 48 | -************************************************************************
|
|
| 49 | -* *
|
|
| 50 | - Gentle simplification
|
|
| 51 | -* *
|
|
| 52 | -************************************************************************
|
|
| 53 | --}
|
|
| 54 | - |
|
| 55 | --- | Configuration record for `simplifyExpr`.
|
|
| 56 | --- The values of this datatype are /only/ driven by the demands of that function.
|
|
| 57 | -data SimplifyExprOpts = SimplifyExprOpts
|
|
| 58 | - { se_fam_inst :: ![FamInst]
|
|
| 59 | - , se_mode :: !SimplMode
|
|
| 60 | - , se_top_env_cfg :: !TopEnvConfig
|
|
| 61 | - }
|
|
| 62 | - |
|
| 63 | -simplifyExpr :: Logger
|
|
| 64 | - -> ExternalUnitCache
|
|
| 65 | - -> SimplifyExprOpts
|
|
| 66 | - -> CoreExpr
|
|
| 67 | - -> IO CoreExpr
|
|
| 68 | --- ^ Simplify an expression using 'simplExprGently'.
|
|
| 69 | ---
|
|
| 70 | --- See 'simplExprGently' for details.
|
|
| 71 | -simplifyExpr logger euc opts expr
|
|
| 72 | - = withTiming logger (text "Simplify [expr]") (const ()) $
|
|
| 73 | - do { eps <- eucEPS euc ;
|
|
| 74 | - ; let fam_envs = ( eps_fam_inst_env eps
|
|
| 75 | - , extendFamInstEnvList emptyFamInstEnv $ se_fam_inst opts
|
|
| 76 | - )
|
|
| 77 | - simpl_env = mkSimplEnv (se_mode opts) fam_envs
|
|
| 78 | - top_env_cfg = se_top_env_cfg opts
|
|
| 79 | - read_eps_rules = eps_rule_base <$> eucEPS euc
|
|
| 80 | - read_ruleenv = updExternalPackageRules emptyRuleEnv <$> read_eps_rules
|
|
| 81 | - |
|
| 82 | - ; let sz = exprSize expr
|
|
| 83 | - |
|
| 84 | - ; (expr', counts) <- initSmpl logger read_ruleenv top_env_cfg sz $
|
|
| 85 | - simplExprGently simpl_env expr
|
|
| 86 | - |
|
| 87 | - ; Logger.putDumpFileMaybe logger Opt_D_dump_simpl_stats
|
|
| 88 | - "Simplifier statistics" FormatText (pprSimplCount counts)
|
|
| 89 | - |
|
| 90 | - ; Logger.putDumpFileMaybe logger Opt_D_dump_simpl "Simplified expression"
|
|
| 91 | - FormatCore
|
|
| 92 | - (pprCoreExpr expr')
|
|
| 93 | - |
|
| 94 | - ; return expr'
|
|
| 95 | - }
|
|
| 96 | - |
|
| 97 | -simplExprGently :: SimplEnv -> CoreExpr -> SimplM CoreExpr
|
|
| 98 | --- ^ Simplifies an expression by doing occurrence analysis, then simplification,
|
|
| 99 | --- and repeating (twice currently), because one pass alone leaves tons of crud.
|
|
| 100 | ---
|
|
| 101 | --- Used only:
|
|
| 102 | ---
|
|
| 103 | --- 1. for user expressions typed in at the interactive prompt (see 'GHC.Driver.Main.hscStmt'),
|
|
| 104 | --- 2. for Template Haskell splices (see 'GHC.Tc.Gen.Splice.runMeta').
|
|
| 105 | ---
|
|
| 106 | --- The name 'Gently' suggests that the SimplMode is InitialPhase,
|
|
| 107 | --- and in fact that is so.... but the 'Gently' in 'simplExprGently' doesn't
|
|
| 108 | --- enforce that; it just simplifies the expression twice.
|
|
| 109 | -simplExprGently env expr = do
|
|
| 110 | - expr1 <- simplExpr env (occurAnalyseExpr expr)
|
|
| 111 | - simplExpr env (occurAnalyseExpr expr1)
|
|
| 112 | - |
|
| 113 | 45 | {-
|
| 114 | 46 | ************************************************************************
|
| 115 | 47 | * *
|
| 1 | 1 | module GHC.Driver.Config.Core.Opt.Simplify
|
| 2 | - ( initSimplifyExprOpts
|
|
| 3 | - , initSimplifyOpts
|
|
| 2 | + ( initSimplifyOpts
|
|
| 4 | 3 | , initSimplMode
|
| 5 | 4 | , initGentleSimplMode
|
| 6 | 5 | ) where
|
| ... | ... | @@ -9,7 +8,7 @@ import GHC.Prelude |
| 9 | 8 | |
| 10 | 9 | import GHC.Core.Rules ( RuleBase )
|
| 11 | 10 | import GHC.Core.Opt.Pipeline.Types ( CoreToDo(..) )
|
| 12 | -import GHC.Core.Opt.Simplify ( SimplifyExprOpts(..), SimplifyOpts(..) )
|
|
| 11 | +import GHC.Core.Opt.Simplify ( SimplifyOpts(..) )
|
|
| 13 | 12 | import GHC.Core.Opt.Simplify.Env ( FloatEnable(..), SimplMode(..), SimplPhase(..) )
|
| 14 | 13 | import GHC.Core.Opt.Simplify.Monad ( TopEnvConfig(..) )
|
| 15 | 14 | |
| ... | ... | @@ -19,26 +18,9 @@ import GHC.Driver.Config.Core.Rules ( initRuleOpts ) |
| 19 | 18 | import GHC.Driver.Config.Core.Opt.Arity ( initArityOpts )
|
| 20 | 19 | import GHC.Driver.DynFlags ( DynFlags(..), GeneralFlag(..), gopt )
|
| 21 | 20 | |
| 22 | -import GHC.Runtime.Context ( InteractiveContext(..) )
|
|
| 23 | - |
|
| 24 | 21 | import GHC.Types.Basic ( CompilerPhase(..) )
|
| 25 | 22 | import GHC.Types.Var ( Var )
|
| 26 | 23 | |
| 27 | -initSimplifyExprOpts :: DynFlags -> InteractiveContext -> SimplifyExprOpts
|
|
| 28 | -initSimplifyExprOpts dflags ic = SimplifyExprOpts
|
|
| 29 | - { se_fam_inst = snd $ ic_instances ic
|
|
| 30 | - , se_mode = (initSimplMode dflags InitialPhase "GHCi")
|
|
| 31 | - { sm_inline = False
|
|
| 32 | - -- Do not do any inlining, in case we expose some
|
|
| 33 | - -- unboxed tuple stuff that confuses the bytecode
|
|
| 34 | - -- interpreter
|
|
| 35 | - }
|
|
| 36 | - , se_top_env_cfg = TopEnvConfig
|
|
| 37 | - { te_history_size = historySize dflags
|
|
| 38 | - , te_tick_factor = simplTickFactor dflags
|
|
| 39 | - }
|
|
| 40 | - }
|
|
| 41 | - |
|
| 42 | 24 | initSimplifyOpts :: DynFlags -> [Var] -> Int -> SimplMode -> RuleBase -> SimplifyOpts
|
| 43 | 25 | initSimplifyOpts dflags extra_vars iterations mode hpt_rule_base = let
|
| 44 | 26 | -- This is a particularly ugly construction, but we will get rid of it in !8341.
|
| ... | ... | @@ -121,8 +121,8 @@ import GHC.Driver.Errors |
| 121 | 121 | import GHC.Driver.Messager
|
| 122 | 122 | import GHC.Driver.Errors.Types
|
| 123 | 123 | import GHC.Driver.CodeOutput
|
| 124 | +import GHC.Driver.Config
|
|
| 124 | 125 | import GHC.Driver.Config.Cmm.Parser (initCmmParserConfig)
|
| 125 | -import GHC.Driver.Config.Core.Opt.Simplify ( initSimplifyExprOpts )
|
|
| 126 | 126 | import GHC.Driver.Config.Core.Lint ( endPassHscEnvIO )
|
| 127 | 127 | import GHC.Driver.Config.Core.Lint.Interactive ( lintInteractiveExpr )
|
| 128 | 128 | import GHC.Driver.Config.CoreToStg
|
| ... | ... | @@ -181,6 +181,7 @@ import GHC.Core.Utils ( exprType ) |
| 181 | 181 | import GHC.Core.ConLike
|
| 182 | 182 | import GHC.Core.Opt.Pipeline
|
| 183 | 183 | import GHC.Core.Opt.Pipeline.Types ( CoreToDo (..))
|
| 184 | +import GHC.Core.SimpleOpt
|
|
| 184 | 185 | import GHC.Core.TyCon
|
| 185 | 186 | import GHC.Core.InstEnv
|
| 186 | 187 | import GHC.Core.FamInstEnv
|
| ... | ... | @@ -2712,15 +2713,17 @@ hscCompileCoreExpr hsc_env loc expr = |
| 2712 | 2713 | hscCompileCoreExpr' :: HscEnv -> SrcSpan -> CoreExpr -> IO (ForeignHValue, [Linkable], PkgsLoaded)
|
| 2713 | 2714 | hscCompileCoreExpr' hsc_env srcspan ds_expr = do
|
| 2714 | 2715 | {- Simplify it -}
|
| 2715 | - -- Question: should we call SimpleOpt.simpleOptExpr here instead?
|
|
| 2716 | - -- It is, well, simpler, and does less inlining etc.
|
|
| 2717 | 2716 | let dflags = hsc_dflags hsc_env
|
| 2718 | 2717 | let logger = hsc_logger hsc_env
|
| 2719 | - let ic = hsc_IC hsc_env
|
|
| 2720 | - let unit_env = hsc_unit_env hsc_env
|
|
| 2721 | - let simplify_expr_opts = initSimplifyExprOpts dflags ic
|
|
| 2722 | 2718 | |
| 2723 | - simpl_expr <- simplifyExpr logger (ue_eps unit_env) simplify_expr_opts ds_expr
|
|
| 2719 | + let simpl_expr =
|
|
| 2720 | + simpleOptExpr
|
|
| 2721 | + ( initSimpleOpts $
|
|
| 2722 | + if gopt Opt_UnoptimizedCoreForInterpreter dflags
|
|
| 2723 | + then updOptLevel 0 dflags
|
|
| 2724 | + else dflags
|
|
| 2725 | + )
|
|
| 2726 | + ds_expr
|
|
| 2724 | 2727 | |
| 2725 | 2728 | -- Create a unique temporary binding
|
| 2726 | 2729 | --
|
| ... | ... | @@ -74,12 +74,12 @@ import GHC.Utils.Outputable as Ppr |
| 74 | 74 | import GHC.Utils.Panic
|
| 75 | 75 | import GHC.Char
|
| 76 | 76 | import GHC.Exts.Heap
|
| 77 | -import GHC.Runtime.Heap.Layout ( roundUpTo )
|
|
| 77 | +import GHC.Runtime.Heap.Layout (ByteOff)
|
|
| 78 | 78 | import GHC.IO (throwIO)
|
| 79 | 79 | |
| 80 | 80 | import Control.Monad
|
| 81 | 81 | import Data.Maybe
|
| 82 | -import Data.List ((\\))
|
|
| 82 | +import Data.List ((\\), mapAccumL)
|
|
| 83 | 83 | import Data.List.NonEmpty (NonEmpty (..))
|
| 84 | 84 | import qualified Data.List.NonEmpty as NE
|
| 85 | 85 | import GHC.Exts
|
| ... | ... | @@ -89,6 +89,10 @@ import Foreign hiding (shiftL, shiftR) |
| 89 | 89 | import System.IO.Unsafe
|
| 90 | 90 | import GHC.InfoProv
|
| 91 | 91 | |
| 92 | +import GHC.StgToCmm.Closure ( NonVoid(NonVoid))
|
|
| 93 | +import GHC.StgToCmm.Layout (mkVirtHeapOffsets, ClosureHeader(..))
|
|
| 94 | +import Data.Array (Array, (!), array)
|
|
| 95 | + |
|
| 92 | 96 | ---------------------------------------------
|
| 93 | 97 | -- * A representation of semi evaluated Terms
|
| 94 | 98 | ---------------------------------------------
|
| ... | ... | @@ -922,63 +926,80 @@ extractSubTerms :: (Type -> ForeignHValue -> TcM Term) |
| 922 | 926 | -> [Word] -- ^ data arguments
|
| 923 | 927 | -> [Type]
|
| 924 | 928 | -> TcM [Term]
|
| 925 | -extractSubTerms recurse ptr_args data_args = liftM thdOf3 . go 0 0
|
|
| 929 | +extractSubTerms recurse ptr_args data_args tys = do
|
|
| 930 | + dflags <- getDynFlags
|
|
| 931 | + let profile = targetProfile dflags
|
|
| 932 | + (n_primreps, r) = mapAccumL collectReps 0 tys
|
|
| 933 | + (rep_tys, make_term) = unzip r
|
|
| 934 | + (_tot_words, ptr_words, nv_rep_offsets) =
|
|
| 935 | + mkVirtHeapOffsets profile NoHeader (map NonVoid $ concat rep_tys)
|
|
| 936 | + rep_offsets = map (\(NonVoid x, off) -> (x, off)) nv_rep_offsets
|
|
| 937 | + -- index maps the Int index of each PrimRep to its ByteOff
|
|
| 938 | + index :: Array Int ByteOff
|
|
| 939 | + index = array (0, n_primreps-1) rep_offsets
|
|
| 940 | + mapM (\m -> m index ptr_words) make_term
|
|
| 926 | 941 | where
|
| 927 | - go ptr_i arr_i [] = return (ptr_i, arr_i, [])
|
|
| 928 | - go ptr_i arr_i (ty:tys)
|
|
| 942 | + |
|
| 943 | + {- Collect all PrimReps from the Type, indexing each with an Int.
|
|
| 944 | + Also returns a function to construct the Term once the heap offset of
|
|
| 945 | + each indexed PrimRep is known.
|
|
| 946 | + -}
|
|
| 947 | + collectReps :: Int -- first index to use
|
|
| 948 | + -> Type
|
|
| 949 | + -> ( Int -- next available index
|
|
| 950 | + , ( [(PrimRep, Int)] -- indexed PrimReps
|
|
| 951 | + , Array Int ByteOff -> Int -> TcM Term
|
|
| 952 | + ))
|
|
| 953 | + collectReps n ty
|
|
| 929 | 954 | | Just (tc, elem_tys) <- tcSplitTyConApp_maybe ty
|
| 930 | 955 | , isUnboxedTupleTyCon tc
|
| 931 | - -- See Note [Unboxed tuple RuntimeRep vars] in GHC.Core.TyCon
|
|
| 932 | - = do (ptr_i, arr_i, terms0) <-
|
|
| 933 | - go ptr_i arr_i (dropRuntimeRepArgs elem_tys)
|
|
| 934 | - (ptr_i, arr_i, terms1) <- go ptr_i arr_i tys
|
|
| 935 | - return (ptr_i, arr_i, unboxedTupleTerm ty terms0 : terms1)
|
|
| 936 | - | otherwise
|
|
| 937 | - = case typePrimRep ty of
|
|
| 938 | - [rep_ty] -> do
|
|
| 939 | - (ptr_i, arr_i, term0) <- go_rep ptr_i arr_i ty rep_ty
|
|
| 940 | - (ptr_i, arr_i, terms1) <- go ptr_i arr_i tys
|
|
| 941 | - return (ptr_i, arr_i, term0 : terms1)
|
|
| 942 | - rep_tys -> do
|
|
| 943 | - (ptr_i, arr_i, terms0) <- go_unary_types ptr_i arr_i rep_tys
|
|
| 944 | - (ptr_i, arr_i, terms1) <- go ptr_i arr_i tys
|
|
| 945 | - return (ptr_i, arr_i, unboxedTupleTerm ty terms0 : terms1)
|
|
| 946 | - |
|
| 947 | - go_unary_types ptr_i arr_i [] = return (ptr_i, arr_i, [])
|
|
| 948 | - go_unary_types ptr_i arr_i (rep_ty:rep_tys) = do
|
|
| 949 | - tv <- newVar liftedTypeKind
|
|
| 950 | - (ptr_i, arr_i, term0) <- go_rep ptr_i arr_i tv rep_ty
|
|
| 951 | - (ptr_i, arr_i, terms1) <- go_unary_types ptr_i arr_i rep_tys
|
|
| 952 | - return (ptr_i, arr_i, term0 : terms1)
|
|
| 953 | - |
|
| 954 | - go_rep ptr_i arr_i ty rep
|
|
| 956 | + -- See Note [Unboxed tuple RuntimeRep vars] in GHC.Core.TyCon
|
|
| 957 | + = let (n', sub) = mapAccumL collectReps n (dropRuntimeRepArgs elem_tys)
|
|
| 958 | + (reps, mk_terms) = unzip sub
|
|
| 959 | + in (n', (concat reps,
|
|
| 960 | + \idx ptr_words -> unboxedTupleTerm ty <$>
|
|
| 961 | + mapM (\mk -> mk idx ptr_words) mk_terms))
|
|
| 962 | + | otherwise =
|
|
| 963 | + case typePrimRep ty of
|
|
| 964 | + [rep] -> (n + 1
|
|
| 965 | + ,([(rep, n)]
|
|
| 966 | + ,\idx ptr_words -> mkTerm ptr_words ty rep (idx ! n)))
|
|
| 967 | + reps -> let n_reps = length reps
|
|
| 968 | + indexed_reps = zip reps [n..]
|
|
| 969 | + mk idx ptr_words =
|
|
| 970 | + unboxedTupleTerm ty <$>
|
|
| 971 | + mapM (\(rep, i) -> mkTerm ptr_words ty rep (idx ! i))
|
|
| 972 | + indexed_reps
|
|
| 973 | + in (n + n_reps, (indexed_reps, mk))
|
|
| 974 | + |
|
| 975 | + |
|
| 976 | + |
|
| 977 | + mkTerm :: Int -> Type -> PrimRep -> ByteOff -> TcM Term
|
|
| 978 | + mkTerm ptr_words ty rep byte_offset
|
|
| 955 | 979 | | isGcPtrRep rep = do
|
| 956 | - t <- recurse ty $ ptr_args !! ptr_i
|
|
| 957 | - return (ptr_i + 1, arr_i, t)
|
|
| 980 | + platform <- getPlatform
|
|
| 981 | + let word_size = platformWordSizeInBytes platform
|
|
| 982 | + (word_offset, r) = byte_offset `quotRem` word_size
|
|
| 983 | + massert (word_offset < length ptr_args)
|
|
| 984 | + massert (r == 0)
|
|
| 985 | + r <- recurse ty (ptr_args !! (byte_offset `quot` word_size))
|
|
| 986 | + pure r
|
|
| 958 | 987 | | otherwise = do
|
| 959 | - -- This is a bit involved since we allow packing multiple fields
|
|
| 960 | - -- within a single word. See also
|
|
| 961 | - -- GHC.StgToCmm.Layout.mkVirtHeapOffsetsWithPadding
|
|
| 962 | 988 | platform <- getPlatform
|
| 963 | 989 | let word_size = platformWordSizeInBytes platform
|
| 964 | - endian = platformByteOrder platform
|
|
| 965 | - size_b = primRepSizeB platform rep
|
|
| 966 | - -- Align the start offset (eg, 2-byte value should be 2-byte
|
|
| 967 | - -- aligned). But not more than to a word. The offset calculation
|
|
| 968 | - -- should be the same with the offset calculation in
|
|
| 969 | - -- GHC.StgToCmm.Layout.mkVirtHeapOffsetsWithPadding.
|
|
| 970 | - !aligned_idx = roundUpTo arr_i (min word_size size_b)
|
|
| 971 | - !new_arr_i = aligned_idx + size_b
|
|
| 972 | - ws | size_b < word_size =
|
|
| 973 | - [index size_b aligned_idx word_size endian]
|
|
| 974 | - | otherwise =
|
|
| 975 | - let (q, r) = size_b `quotRem` word_size
|
|
| 976 | - in assert (r == 0 )
|
|
| 977 | - [ data_args !! i
|
|
| 978 | - | o <- [0.. q - 1]
|
|
| 979 | - , let i = (aligned_idx `quot` word_size) + o
|
|
| 980 | - ]
|
|
| 981 | - return (ptr_i, new_arr_i, Prim ty ws)
|
|
| 990 | + endian = platformByteOrder platform
|
|
| 991 | + size_b = primRepSizeB platform rep
|
|
| 992 | + ws | size_b < word_size
|
|
| 993 | + = [index size_b (byte_offset - word_size * ptr_words) word_size endian]
|
|
| 994 | + | otherwise
|
|
| 995 | + =
|
|
| 996 | + let (q, r) = size_b `quotRem` word_size
|
|
| 997 | + in assert (r == 0 )
|
|
| 998 | + [ data_args !! i
|
|
| 999 | + | o <- [0.. q - 1]
|
|
| 1000 | + , let i = (byte_offset `quot` word_size) - ptr_words + o
|
|
| 1001 | + ]
|
|
| 1002 | + return (Prim ty ws)
|
|
| 982 | 1003 | |
| 983 | 1004 | unboxedTupleTerm ty terms
|
| 984 | 1005 | = Term ty (Right (tupleDataCon Unboxed (length terms)))
|
| ... | ... | @@ -56,7 +56,8 @@ import GHC.Platform.Profile |
| 56 | 56 | import GHC.Unit
|
| 57 | 57 | |
| 58 | 58 | import GHC.Utils.Misc
|
| 59 | -import Data.List (mapAccumL, partition)
|
|
| 59 | +import Data.List (mapAccumL, partition, sortBy)
|
|
| 60 | +import Data.Ord (comparing)
|
|
| 60 | 61 | import GHC.Utils.Outputable
|
| 61 | 62 | import GHC.Utils.Panic
|
| 62 | 63 | import GHC.Utils.Constants (debugIsOn)
|
| ... | ... | @@ -459,10 +460,19 @@ mkVirtHeapOffsetsWithPadding profile header things = |
| 459 | 460 | ThunkHeader -> thunkHdrSize profile
|
| 460 | 461 | hdr_bytes = wordsToBytes platform hdr_words
|
| 461 | 462 | |
| 462 | - (ptrs, non_ptrs) = partition (isGcPtrRep . fst . fromNonVoid) things
|
|
| 463 | + (ptrs, unsorted_non_ptrs) = partition (isGcPtrRep . fst . fromNonVoid) things
|
|
| 464 | + |
|
| 465 | + -- Sort the non-pointer fields by their size, starting with the largest
|
|
| 466 | + -- size, so that we can pack them more efficiently.
|
|
| 467 | + |
|
| 468 | + cmp_sizes (NonVoid (rep1, _)) (NonVoid (rep2, _)) =
|
|
| 469 | + comparing (primRepSizeB platform) rep2 rep1
|
|
| 470 | + |
|
| 471 | + non_ptrs = sortBy cmp_sizes unsorted_non_ptrs
|
|
| 463 | 472 | |
| 464 | 473 | (bytes_of_ptrs, ptrs_w_offsets) =
|
| 465 | 474 | mapAccumL computeOffset 0 ptrs
|
| 475 | + |
|
| 466 | 476 | (tot_bytes, non_ptrs_w_offsets) =
|
| 467 | 477 | mapAccumL computeOffset bytes_of_ptrs non_ptrs
|
| 468 | 478 |
| ... | ... | @@ -67,10 +67,26 @@ import GHC.Exts.Heap.ClosureTypes |
| 67 | 67 | import GHC.Exts.Heap.Constants
|
| 68 | 68 | import GHC.Exts.Heap.ProfInfo.Types
|
| 69 | 69 | #if defined(PROFILING)
|
| 70 | +import GHC.Exts.Heap.InfoTable () -- See Note [No way-dependent imports]
|
|
| 70 | 71 | import GHC.Exts.Heap.InfoTableProf
|
| 71 | 72 | #else
|
| 72 | 73 | import GHC.Exts.Heap.InfoTable
|
| 74 | +import GHC.Exts.Heap.InfoTableProf () -- See Note [No way-dependent imports]
|
|
| 75 | + |
|
| 76 | +{-
|
|
| 77 | +Note [No way-dependent imports]
|
|
| 78 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 79 | +`ghc -M` currently assumes that the imports for a module are the same
|
|
| 80 | +in every way. This is arguably a bug, but breaking this assumption by
|
|
| 81 | +importing different things in different ways can cause trouble. For
|
|
| 82 | +example, this module in the profiling way imports and uses
|
|
| 83 | +GHC.Exts.Heap.InfoTableProf. When it was not also imported in the
|
|
| 84 | +vanilla way, there were intermittent build failures due to this module
|
|
| 85 | +being compiled in the profiling way before GHC.Exts.Heap.InfoTableProf
|
|
| 86 | +in the profiling way. (#15197)
|
|
| 87 | +-}
|
|
| 73 | 88 | #endif
|
| 89 | + |
|
| 74 | 90 | import GHC.Exts.Heap.Utils
|
| 75 | 91 | import qualified GHC.Exts.Heap.FFIClosures as FFIClosures
|
| 76 | 92 | import qualified GHC.Exts.Heap.ProfInfo.PeekProfInfo as PPI
|
| ... | ... | @@ -25,8 +25,8 @@ tests :: Ghc () |
| 25 | 25 | tests = do
|
| 26 | 26 | (_, _, off) <- runTest [("a", FloatRep), ("b", DoubleRep)]
|
| 27 | 27 | assert_32_64 (map fmt off)
|
| 28 | - ["F(a,4)", "F(b,8)"]
|
|
| 29 | - ["F(a,8)", "P(4,12)", "F(b,16)"]
|
|
| 28 | + ["F(b,4)", "F(a,12)"]
|
|
| 29 | + ["F(b,8)", "F(a,16)", "P(4,20)"]
|
|
| 30 | 30 | |
| 31 | 31 | (_, _, off) <- runTest [("a", FloatRep), ("b", FloatRep)]
|
| 32 | 32 | assert_32_64 (map fmt off)
|
| ... | ... | @@ -40,8 +40,8 @@ tests = do |
| 40 | 40 | |
| 41 | 41 | (_, _, off) <- runTest [("a", FloatRep), ("b", FloatRep), ("c", Int64Rep)]
|
| 42 | 42 | assert_32_64 (map fmt off)
|
| 43 | - ["F(a,4)", "F(b,8)", "F(c,12)"]
|
|
| 44 | - ["F(a,8)", "F(b,12)", "F(c,16)"]
|
|
| 43 | + ["F(c,4)", "F(a,12)", "F(b,16)"]
|
|
| 44 | + ["F(c,8)", "F(a,16)", "F(b,20)"]
|
|
| 45 | 45 | |
| 46 | 46 | (_, _, off) <- runTest [("a", Int64Rep), ("b", FloatRep), ("c", FloatRep)]
|
| 47 | 47 | assert_32_64 (map fmt off)
|
| ... | ... | @@ -50,8 +50,8 @@ tests = do |
| 50 | 50 | |
| 51 | 51 | (_, _, off) <- runTest [("a", Int64Rep), ("b", FloatRep), ("c", Int64Rep)]
|
| 52 | 52 | assert_32_64 (map fmt off)
|
| 53 | - ["F(a,4)", "F(b,12)", "F(c,16)"]
|
|
| 54 | - ["F(a,8)", "F(b,16)", "P(4,20)", "F(c,24)"]
|
|
| 53 | + ["F(a,4)", "F(c,12)", "F(b,20)"]
|
|
| 54 | + ["F(a,8)", "F(c,16)", "F(b,24)", "P(4,28)"]
|
|
| 55 | 55 | |
| 56 | 56 | |
| 57 | 57 | assert_32_64 :: (Eq a, Show a) => a -> a -> a -> Ghc ()
|
| ... | ... | @@ -3481,6 +3481,7 @@ module GHC.PrimopWrappers where |
| 3481 | 3481 | remWord8# :: GHC.Internal.Prim.Word8# -> GHC.Internal.Prim.Word8# -> GHC.Internal.Prim.Word8#
|
| 3482 | 3482 | resizeMutableByteArray# :: forall s. GHC.Internal.Prim.MutableByteArray# s -> GHC.Internal.Prim.Int# -> GHC.Internal.Prim.State# s -> (# GHC.Internal.Prim.State# s, GHC.Internal.Prim.MutableByteArray# s #)
|
| 3483 | 3483 | retry# :: forall a_levpoly. GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld -> (# GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld, a_levpoly #)
|
| 3484 | + seq :: forall a b_reppoly. a -> b_reppoly -> b_reppoly
|
|
| 3484 | 3485 | setAddrRange# :: GHC.Internal.Prim.Addr# -> GHC.Internal.Prim.Int# -> GHC.Internal.Prim.Int# -> GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld -> GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld
|
| 3485 | 3486 | setByteArray# :: forall s. GHC.Internal.Prim.MutableByteArray# s -> GHC.Internal.Prim.Int# -> GHC.Internal.Prim.Int# -> GHC.Internal.Prim.Int# -> GHC.Internal.Prim.State# s -> GHC.Internal.Prim.State# s
|
| 3486 | 3487 | setOtherThreadAllocationCounter# :: GHC.Internal.Prim.Int64# -> GHC.Internal.Prim.ThreadId# -> GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld -> GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld
|
| ... | ... | @@ -3484,6 +3484,7 @@ module GHC.PrimopWrappers where |
| 3484 | 3484 | remWord8# :: GHC.Internal.Prim.Word8# -> GHC.Internal.Prim.Word8# -> GHC.Internal.Prim.Word8#
|
| 3485 | 3485 | resizeMutableByteArray# :: forall s. GHC.Internal.Prim.MutableByteArray# s -> GHC.Internal.Prim.Int# -> GHC.Internal.Prim.State# s -> (# GHC.Internal.Prim.State# s, GHC.Internal.Prim.MutableByteArray# s #)
|
| 3486 | 3486 | retry# :: forall a_levpoly. GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld -> (# GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld, a_levpoly #)
|
| 3487 | + seq :: forall a b_reppoly. a -> b_reppoly -> b_reppoly
|
|
| 3487 | 3488 | setAddrRange# :: GHC.Internal.Prim.Addr# -> GHC.Internal.Prim.Int# -> GHC.Internal.Prim.Int# -> GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld -> GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld
|
| 3488 | 3489 | setByteArray# :: forall s. GHC.Internal.Prim.MutableByteArray# s -> GHC.Internal.Prim.Int# -> GHC.Internal.Prim.Int# -> GHC.Internal.Prim.Int# -> GHC.Internal.Prim.State# s -> GHC.Internal.Prim.State# s
|
| 3489 | 3490 | setOtherThreadAllocationCounter# :: GHC.Internal.Prim.Int64# -> GHC.Internal.Prim.ThreadId# -> GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld -> GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld
|
| ... | ... | @@ -29,4 +29,4 @@ size: 10 |
| 29 | 29 | |
| 30 | 30 | ### u_maybeW32
|
| 31 | 31 | U_MaybeW32 NothingW32 (JustW32 0) NothingW32 (JustW32 4294967295) NothingW32 (JustW32 0) NothingW32 (JustW32 4294967295)
|
| 32 | -size: 9 |
|
| 32 | +size: 6 |
| ... | ... | @@ -29,4 +29,4 @@ size: 11 |
| 29 | 29 | |
| 30 | 30 | ### u_maybeW32
|
| 31 | 31 | U_MaybeW32 NothingW32 (JustW32 0) NothingW32 (JustW32 4294967295) NothingW32 (JustW32 0) NothingW32 (JustW32 4294967295)
|
| 32 | -size: 17 |
|
| 32 | +size: 11 |
| ... | ... | @@ -510,7 +510,7 @@ gen_wrappers (Info _ entries) |
| 510 | 510 | want_wrapper :: Entry -> Bool
|
| 511 | 511 | want_wrapper entry =
|
| 512 | 512 | and
|
| 513 | - [ is_primop entry
|
|
| 513 | + [ (is_primop entry || is_seq_pseudoop entry)
|
|
| 514 | 514 | , not $ name entry `elem` magical_primops
|
| 515 | 515 | , not $ is_vector entry
|
| 516 | 516 | -- We currently don't generate wrappers for vector primops.
|
| ... | ... | @@ -520,6 +520,12 @@ gen_wrappers (Info _ entries) |
| 520 | 520 | -- suppose this choice can be revisited?
|
| 521 | 521 | ]
|
| 522 | 522 | |
| 523 | + -- We also want a wrapper for the `seq` pseudoop, since GHCi
|
|
| 524 | + -- expects to find a value binding in PrimopWrappers.
|
|
| 525 | + is_seq_pseudoop :: Entry -> Bool
|
|
| 526 | + is_seq_pseudoop (PseudoOpSpec { name = n }) = n == "seq"
|
|
| 527 | + is_seq_pseudoop _ = False
|
|
| 528 | + |
|
| 523 | 529 | magical_primops :: [String]
|
| 524 | 530 | magical_primops =
|
| 525 | 531 | [ "tagToEnum#"
|
| 1 | +cradle:
|
|
| 2 | + cabal: |