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: |